%% URL read for Real-time Weather Station Measurements
%
clear all
close all
clc
%
station_repos = 'http://w1.weather.gov/data/obhistory/'; % This is where 
% the weather stations are located at www.weather.gov 
% You type in your address and then look for the 4-letter station
% identifier (for example, if you type in '10024' for NYC, the station
% ID for that Zip Code is 'KNYC' - Central Park's weather station
%
station_name_formal = 'Austin-Bergstrom International Airport';
station_ID = 'KAUS';
%
% concatenate station repository with your local station
%
web_url = strcat(station_repos,station_ID,'.html');
%
% Crawl the URL for data
web_str_crawl = webread(web_url);
%
% Now for the fun - parsing the data!
%
station_table = data_reformat(web_str_crawl);
%
% Preparing the Figure to Plot
[fig1,ax1,dcm_obj] = fig_open();
%
% Now reformat the data and plot it!
%
plot_algo(station_table,station_name_formal,station_ID,[7,8])
% 
fig1.Visible='on';  
saveas(fig1,'test.png')
%
%
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%------------------------FUNCTIONS--------------------------------------%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
function station_table = data_reformat(web_url_str)
%
% Parse each row, which in html is identified by <td></td>, then put each
% into the station_parse variable
station_parse = {};
for jj = 1:length(web_url_str)-4
    if web_url_str(jj:jj+4)=='</td>'
        for kk = 1:80
            if web_url_str(jj-kk)=='>'
                station_parse{end+1} = web_url_str(jj-kk+1:jj-1);
                break
            end
        end
    end
end
% shift data to get rid of the extra headers
station_vec = {};
n_shift = 9;
for ll = 1:length(station_parse)
    if ll>=n_shift
        station_vec{ll-n_shift+1} =station_parse{ll};         
    end
end
%
% reformat the data into an easily-readable table
%
col_size = 18;
station_table = {zeros(floor(length(station_vec)/col_size)+1,col_size)};
% I rewrote the headers to make them more friendly for labeling
station_header = {'Date','Time (Local)','Wind [MPH]','Visibility [Miles]','Weather Cond.',...
    'Sky Cond.','Air Temperature [F]','Dew Point [F]','Temp (6 Hour Max) [F]','Temp (6 Hour Min)','Relative Humidity [%]',...
    'Wind Chill [F]','Heat Index [F]','Pressure (Alt, inches)','Pressure (Sea, mbar)',...
    'Precipitation (1 hr) [inches]','Precipitation (inches) [3 hr]','Precipitation (inches) [6 hr]'};
% This is the loop where the table is created and formatted
for mm = 1:floor(length(station_vec)/col_size)+1
    for nn = 1:col_size
        if mm == 1
            station_table{mm,nn} = station_header{nn};
        else
            pp = (mm-2)*col_size+nn;
            if nn==11
                station_table{mm,nn} = station_vec{pp}(1:2);
            else
                station_table{mm,nn} = station_vec{pp};
            end
        end
    end
end

end

function [fig1,ax1,dcm_obj] = fig_open()
set(0,'defaultfigurecolor',[1 1 1]) % white background
set(0,'defaultaxesfontname','cambria math') % beautify the axes a bit
scrn_size = get(0,'ScreenSize'); % get size of screen
shrink_pct = 0.1; % shrink the figure by 10%
%
fig1 = figure('Visible','off','DefaultAxesFontSize',20,'Position',...
    [scrn_size(1)+(scrn_size(3)*shrink_pct) scrn_size(2)+(scrn_size(4)*shrink_pct)...
    scrn_size(3)-(scrn_size(3)*2*shrink_pct) scrn_size(4)-(scrn_size(4)*2*shrink_pct)]); % shrinking the figure
%
ax1 = gca;
dcm_obj = datacursormode(fig1); % enable control of datatips
% set(dcm_obj,'UpdateFcn',@myupdatefcn) % this will be used to configure
% data tips
set(ax1,'fontsize',22,'Color',[0.8 0.8 0.8],'gridcolor',[1 1 1],'gridalpha',0.9) % set the axis color
% to compliment the white background
%
xlabel('Time [Day HH:MM]') % x-axis date label
hold all
grid on % grid for more contrast in the axes
end
%
function [datenum_vec,var_pick,var_name] = parse_and_format(station_table,var_col)
curr_time = datetime(); % get the current time for year information
datenum_vec = []; var_pick = [];
var_name = station_table{1,var_col}; % variable name
for ss = 2:length(station_table) % starting at the second row since the first contains the variable names
    var_pick = [var_pick,str2double(station_table{ss,var_col})];    
    if isempty(str2double(station_table{ss,var_col})) % if there is no data in the row, skip the loop
        continue
    end
    if ss==2 % making sure the first row is the reference year, month, and day
        datenum_vec = [datenum_vec,datenum(year(curr_time),month(curr_time),str2num(station_table{ss}),str2num(station_table{ss,2}(1:2)),str2num(station_table{ss,2}(4:5)),0)];
    else
        if str2double(station_table{ss})>str2double(station_table{2}) % this ensures that if the date grows, then the day is in the previous month
            if month(curr_time)==1 % if it's december, then we have to roll back the month and year
                datenum_vec = [datenum_vec,datenum(year(curr_time)-1,12,str2double(station_table{ss}),str2double(station_table{ss,2}(1:2)),str2double(station_table{ss,2}(4:5)),0)];                            
            else % end of month, roll back month
                datenum_vec = [datenum_vec,datenum(year(curr_time),month(curr_time)-1,str2double(station_table{ss}),str2double(station_table{ss,2}(1:2)),str2double(station_table{ss,2}(4:5)),0)];                
            end
        else
            datenum_vec = [datenum_vec,datenum(year(curr_time),month(curr_time),str2double(station_table{ss}),str2double(station_table{ss,2}(1:2)),str2double(station_table{ss,2}(4:5)),0)];                            
        end
    end    
end
end

function plot_algo(station_table,station_name_formal,home_station,var_select)
    legend_str = {};    
    for ii = 1:length(var_select) % loop through variables to ensure legend catches each
        [datenum_vec,var_pick,var_name] = parse_and_format(station_table,var_select(ii)); % send variable through parse function
        % plotting traits
        sz = 10; % size of marker
        color_map = lines; % colormap used for lines and markers
        if length(var_select)<=2 % this is particular to my dataset (METAR)
            switch ii
                case 1 % if only 1 variable, make 1 y-axis label
                    ylabel(var_name)
                case 2 % if two variables, make two y-axis labels
                    yyaxis right; % second y-axis to the right
                    y2 = gca;
                    ylabel(var_name)
                    y2.YColor = color_map(ii,:); % ensure the color of the axis matches the second line
            end % in my case, I'm chosing to discard the y-labels if more than 2 variables are entered
        end 
        % plot specifics: -s creates a square marker with a line
        plot(datenum_vec,var_pick,'-s','linewidth',3,'color',color_map(ii,:),...
            'MarkerFaceColor',(1-color_map(ii,:))/1.5+color_map(ii,:),'MarkerEdgeColor',[25 25 25]./256,...
            'MarkerSize',sz)
        % title handling for month and year
        curr_time = datetime(); 
        title(strcat('Weather for {}',station_name_formal,'{ }(',home_station,') in {}',datestr(curr_time,'mmmm, yyyy')))              
        xlabel('Time [Day HH:MM]')
        % chosing to step through x-values by 6 (72/6 = 12 x-ticks)
        xticks(datenum_vec(end:-6:1))
        datetick(gca,'x','dd HH:MM','keepticks')
        % rotating the x-ticks so they don't overlap
        xtickangle(20)
        % setting the limits
        xlim([datenum_vec(end) datenum_vec(1)])
        % appending the names to the legend handler
        legend_str{end+1} = var_name; 
    end
    % white background and letting MATLAB choose the best location for the
    % legend
    legend(legend_str,'Location','Best','Color','white')
end