#!/usr/bin/perl # # Grabs the latest local weather conditions from the # National Weather Service (NWS). Uses the decoded METAR reports. # # Need to give the 4-character METAR station code on the # Command Line. E.g.; # # GrabWeather YSSY # use strict; use IO::File; my $StationID = uc shift @ARGV or die "Usage: $0 \n"; my $ReportDir = '.wmWeatherReports'; my $WeatherSrc = 'http://tgftp.nws.noaa.gov/data/observations/metar/decoded/'; my $DataFileName; my $TxtFileName; my $home; sub initialize { # Change to users home directory. $home = $ENV{HOME} || (getpwuid($<))[7]; chdir() || chdir($home) or die "chdir '$home' failed: $!"; # Create the report directory if needed unless(-e $ReportDir) { mkdir $ReportDir, 0755 or die "unable to mkdir '$ReportDir': $!"; } chdir $ReportDir or die "chdir '$ReportDir' failed: $!"; # Set the file name to get from $WeatherSrc $TxtFileName = "$StationID.TXT"; # Set the file name for results $DataFileName = "$StationID.dat"; # Get the html file from $WeatherSrc # Is LWP installed? eval { require LWP::UserAgent }; if ($@) { my $cmd = qq{wget --proxy=off --passive-ftp --tries=0 --quiet } . qq{--output-document=$home/$ReportDir/$TxtFileName $WeatherSrc/$TxtFileName}; `$cmd` == 0 or die "unable to fetch weather: $?"; } else { $ENV{FTP_PASSIVE} = 1; # LWP uses Net::FTP internally. my $ua = new LWP::UserAgent; my $req = new HTTP::Request(GET => "$WeatherSrc/$TxtFileName"); my $rsp = $ua->request( $req ); die $rsp->status_line unless $rsp->is_success; my $fh = new IO::File "> $home/$ReportDir/$TxtFileName" or die "unable to write '$home/$ReportDir/$TxtFileName': $!"; print $fh $rsp->content; close $fh or die "error closing '$home/$ReportDir/$TxtFileName': $!"; } } ############################################ main ############################################ initialize(); # # Parse TXT File. # my %stats = ( temp => -99.0, # chill => -99.0, dew_point => -99.0, # pressure => -99.0, # humidity => -99.0, # universal_time => '99:99', ); my $fh = new IO::File $TxtFileName or die "unable to read '$TxtFileName': $!"; my $line = 0; while (<$fh>) { chomp; if ($line == 0) { $stats{station_info} = $1, next if /^(.*)\s\(/; $line++; } $stats{update_time} = $1, next if / ([0-2.][0-9.]:[0-5.][0-9.])\s[AP]M/; $stats{sky_conditions} = $1, next if /Sky conditions: (.*)/; $stats{temp} = $1, next if /Temperature:\s*(\-{0,1}[0-9.]{1,}).*/; $stats{chill} = $1, next if /Windchill:\s*(\-{0,1}[0-9.]{1,}).*/; $stats{dew_point} = $1, next if /Dew Point:\s*(\-{0,1}[0-9.]{1,}).*/; $stats{pressure} = $2, next if /Pressure\s\(altimeter\):\s*(.*)\s*([0-9.]{4,}).*/; $stats{humidity} = $1, next if /Relative Humidity:\s*(\d{1,})\%.*/; $stats{coded_metar} = $1, next if /ob: (.*)/; } close $fh or die "error closing '$TxtFileName': $!"; # # Isolate the Wind groups out of the coded METAR report. # There may be two groups - the normal one and a variability set. # $stats{wind_group} = $stats{coded_metar}; $stats{wind_group} =~ s/ RMK\s.*$//; $stats{var_flag} = 1 if $stats{wind_group} =~ /\d+(KT|MPS)\s\d+V\d+\s/; if ($stats{wind_group} =~ /\s(\w{3})(?:(\d+)G)?(\d+)(KT|MPS)\s/) { @stats{qw( direction speed1 speed2 )} = ($1, $2, $3); if ($4 eq 'MPS') { $stats{speed1} *= 1.942 if defined $stats{speed1}; $stats{speed2} *= 1.942; } } # # Get the Time out of the coded Metar Report. # if ($stats{coded_metar} =~ /$StationID \d+?(\d{2})(\d{2})Z/) { $stats{universal_time} = "$1:$2"; } # # Write out the stuff we need to the Data File. This is the file that will # be read by GKrellWeather. # #print "$DataFileName\n"; my $fh = $STDOUT; my $fh = new IO::File ">$DataFileName" or die "unable to write '$DataFileName': $!"; print $fh map { "$stats{$_}\n" } qw( station_info update_time sky_conditions universal_time temp dew_point chill pressure humidity ); if (not exists $stats{direction}) { print $fh "-99\n"; } elsif ($stats{direction} =~ /VRB/) { print $fh "99\n"; } elsif ($stats{var_flag}) { print $fh $stats{direction} * -1, "\n"; } else { print $fh $stats{direction} + 0, "\n"; } if (not $stats{direction}) { print $fh "-99\n"; } elsif (defined $stats{speed1} and defined $stats{speed2}) { my $ave_speed = (($stats{speed1} + $stats{speed2})/2.0) * 1.15155; print $fh "-$ave_speed\n"; } else { print $fh $stats{speed2} * 1.15155, "\n"; } close $fh or die "error closing '$DataFileName': $!";