diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/changelog /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/changelog --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/changelog 2008-06-13 16:48:41.000000000 +0100 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/changelog 2008-06-13 16:48:41.000000000 +0100 @@ -1,3 +1,33 @@ +libgeo-metar-perl (1.15-1) unstable; urgency=low + + * New upstream release, new upstream maintainer. + * debian/docs: removed HACKING. + * debian/copyright: updated CP info, plus new format. + * debian/control: added myself to Uploaders, fixed case in short desc. Fix + incorrect Build-Depends{,-Indep} distribution. + * debian/patches: finally merged all the patches from #304962 and #262397 + with the new upstream release! Also, sent the patches upstream as + CPAN#36708. (Closes: #304962). + + -- Martín Ferrari Fri, 13 Jun 2008 02:42:42 -0300 + +libgeo-metar-perl (1.14-6) UNRELEASED; urgency=low + + [ gregor herrmann ] + * debian/control: Added: Vcs-Svn field (source stanza); Vcs-Browser + field (source stanza); Homepage field (source stanza). + * Set Maintainer to Debian Perl Group. + * Use dist-based URL in debian/watch. + + [ Martín Ferrari ] + * Moved modifications to the code to a patch file. + * Added quilt stuff. + * debian/control: updated Standards-Version, debhelper version, fixed + depends, and revamped Description. + * debian/rules: rewritten to conform current practices. + + -- gregor herrmann Sat, 01 Dec 2007 18:54:54 +0100 + libgeo-metar-perl (1.14-5) unstable; urgency=low * Change to POD formatting so URL doesn't break oddly (Closes: #272910) diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/compat /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/compat --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/compat 2008-06-13 16:48:41.000000000 +0100 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/compat 2008-06-13 16:48:41.000000000 +0100 @@ -1 +1 @@ -4 +5 diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/control /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/control --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/control 2008-06-13 16:48:41.000000000 +0100 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/control 2008-06-13 16:48:41.000000000 +0100 @@ -1,18 +1,21 @@ Source: libgeo-metar-perl Section: perl Priority: optional -Maintainer: Jay Bonci -Build-Depends-Indep: debhelper (>= 4.1.40), perl (>= 5.6.0-16) -Standards-Version: 3.6.1.0 +Maintainer: Debian Perl Group +Uploaders: Jay Bonci , Martín Ferrari +Build-Depends: debhelper (>= 5), quilt +Build-Depends-Indep: perl (>= 5.6.0-16) +Standards-Version: 3.7.3 +Homepage: http://search.cpan.org/dist/Geo-METAR/ +Vcs-Svn: svn://svn.debian.org/pkg-perl/trunk/libgeo-metar-perl/ +Vcs-Browser: http://svn.debian.org/wsvn/pkg-perl/trunk/libgeo-metar-perl/ Package: libgeo-metar-perl Architecture: all Depends: ${perl:Depends} -Description: Geo::METAR, Accessing Aviation Weather Information with Perl - libgeo-metar-perl (Geo::METAR) is a set of Perl modules which allow - accessing of aviation weather information with Perl. - The Geo::METAR home page is located at: - http://www.wcnet.org/~jzawodn/perl/Geo-METAR/ - This is a perl module to allow accessing weather info. +Description: accessing Aviation Weather Information with Perl + Geo::METAR is a Perl module to access and parse aviation weather information + with Perl. + . Note: This version differs slightly from the version in CPAN. See the file README.Debian for specific changes diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/copyright /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/copyright --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/copyright 2008-06-13 16:48:41.000000000 +0100 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/copyright 2008-06-13 16:48:41.000000000 +0100 @@ -1,18 +1,23 @@ -This package was debianized by Remi Lefebvre on -Sun, 14 Nov 1999 15:11:57 -0500. +The main website is at: http://idefix.net/~koos/perl/Geo-METAR/ +also: http://search.cpan.org/dist/Geo-METAR -It was updated by Jay Bonci on 4/28/2003 +Upstream Author: Jeremy D. Zawodny , + Koos van den Hout -The main website is at: http://www.wcnet.org/~jzawodn/perl/Geo-METAR/ -also: -http://search.cpan.org/dist/Geo-METAR - -Upstream Author: Jeremy D. Zawodny - -Copyright: - -You are free to distribute this software under the terms of -the GNU General Public License. +Files: * +Copyright: © 1997-2000 Jeremy D. Zawodny + © 2007 Koos van den Hout +License: GPL-2+ + Geo::METAR is covered under the GNU Public License (GPL) version 2 or later. + +Files: debian/* +Copyright: © 2007 Martín Ferrari + © 2007 gregor herrmann + © 2003,2004 Jay Bonci + © 1999,2000 Remi Lefebvre +License: other + It is assumed that maintainers did choose a license compatible with the + software. On Debian GNU/Linux systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL file. diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/docs /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/docs --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/docs 2008-06-13 16:48:41.000000000 +0100 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/docs 2008-06-13 16:48:41.000000000 +0100 @@ -1,4 +1,3 @@ debian/README.Debian README TODO -HACKING diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/libgeo-metar-perl.examples /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/libgeo-metar-perl.examples --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/libgeo-metar-perl.examples 2008-06-13 16:48:41.000000000 +0100 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/libgeo-metar-perl.examples 1970-01-01 01:00:00.000000000 +0100 @@ -1,2 +0,0 @@ -examples/fetch_temp.pl -examples/simple_dump.pl diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/patches/pressure.patch /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/patches/pressure.patch --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/patches/pressure.patch 1970-01-01 01:00:00.000000000 +0100 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/patches/pressure.patch 2008-06-13 16:48:41.000000000 +0100 @@ -0,0 +1,88 @@ +Index: libgeo-metar-perl/METAR.pm +=================================================================== +--- libgeo-metar-perl.orig/METAR.pm ++++ libgeo-metar-perl/METAR.pm +@@ -185,9 +185,9 @@ + + # PRESSURE + # +-# The pressure, or altimeter setting, at the reporting site recorded in +-# inches of mercury (Hg) minus the decimal point. It should always look +-# like (A\d\d\d\d). ++# The pressure, or altimeter setting, at the reporting site recorded in whole ++# hectopascals (starts with a Q) or inches of mercury (Hg) minus the decimal ++# point (starts with an A). It should always look like ([AQ]\d\d\d\d). + # + # KNMI: Q\d\d\d\d pressure in hPa calculated for sea level + +@@ -354,7 +354,8 @@ sub new + $self->{HOURLY_DEW_F} = undef; # hourly dew point, celcius + $self->{HOURLY_DEW_C} = undef; # hourly dew point, fahrenheit + $self->{HOURLY_PRECIP} = undef; # hourly precipitation +- $self->{ALT} = undef; # altimeter setting ++ $self->{ALT} = undef; # altimeter setting (Hg) ++ $self->{ALT_HP} = undef; # altimeter setting (hPa) + $self->{SLP} = undef; # sea level pressure + $self->{REMARKS} = undef; # remarks + +@@ -891,18 +892,14 @@ sub _process + } + + ## +- ## is it an altimeter setting? ++ ## is it an altimeter setting? (in.Hg) + ## + + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_remarks) and ($tok =~ /^A(\d\d)(\d\d)$/i)) + { + $self->{alt} = $tok; +- $self->{ALT} = "$1.$2"; +- +- # inches Hg pressure. How imperial can you get +- # conversion using 'units' +- +- $self->{pressure} = 33.863886 * $self->{ALT}; ++ $self->{ALT} = "$1.$2"+0; ++ $self->{ALT_HP} = "$1.$2" * 33.863886; + + print "[$tok] is an altimeter setting.\n" if $self->{debug}; + $parsestate = $expect_recentweather; +@@ -910,14 +907,14 @@ sub _process + } + + ## +- ## is it a pressure? ++ ## is it a pressure? (hPa) + ## + + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_remarks) and ($tok =~ /^Q(\d\d\d\d)$/i)) + { + $self->{pressure} = $1; +- +- $self->{ALT} = 0.029529983*$self->{pressure}; ++ $self->{ALT_HP} = $1; ++ $self->{ALT} = 0.029529983 * $self->{pressure}; + print "[$tok] is an air pressure.\n" if $self->{debug}; + $parsestate = $expect_recentweather; + next; +@@ -1378,7 +1375,8 @@ sub dump + print "weather: " . join(', ', @{$self->{weather}}) . "\n"; + print "sky: " . join(', ', @{$self->{sky}}) . "\n"; + print "temp_dew: $self->{temp_dew}\n"; +- print "alt: $self->{ALT}\n"; ++ print "alt: $self->{alt}\n"; ++ print "pressure: $self->{pressure}\n"; + print "slp: $self->{slp}\n"; + print "remarks: " . join (', ', @{$self->{remarks}}) . "\n"; + print "\n"; +@@ -1668,6 +1666,10 @@ Hourly dewpoint, celcius + + Altimeter setting (barometric pressure). + ++=item ALT_HP ++ ++Altimeter setting in hectopascals. ++ + =item REMARKS + + Any remarks in the report. diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/patches/series /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/patches/series --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/patches/series 1970-01-01 01:00:00.000000000 +0100 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/patches/series 2008-06-13 16:48:41.000000000 +0100 @@ -0,0 +1,4 @@ +wind.patch +pressure.patch +visibility.patch +various.patch diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/patches/various.patch /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/patches/various.patch --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/patches/various.patch 1970-01-01 01:00:00.000000000 +0100 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/patches/various.patch 2008-06-13 16:48:41.000000000 +0100 @@ -0,0 +1,103 @@ +Index: libgeo-metar-perl/METAR.pm +=================================================================== +--- libgeo-metar-perl.orig/METAR.pm ++++ libgeo-metar-perl/METAR.pm +@@ -364,8 +364,7 @@ sub new + # default=METAR + $self->{site} = undef; # the site code (4 chars) + $self->{date_time} = undef; # date/time +- $self->{modifier} = "AUTO"; # the AUTO/COR modifier (if +- # any) default=AUTO ++ $self->{modifier} = undef; # the AUTO/COR modifier + $self->{wind} = undef; # the wind information + $self->{windtype} = undef; # the wind speed type (knots/meterpersecond/kilometersperhour) + $self->{windvar} = undef; # the wind variation +@@ -1431,8 +1430,11 @@ applications. + Here is how you I use the Geo::METAR module. + + One use that I have had for this module is to query the NWS METAR page +-(using the LWP modules) at +-http://weather.noaa.gov/cgi-bin/mgetmetar.pl?cccc=EHSB to get an ++(using the LWP modules) at: ++ ++I ++ ++to get an + up-to-date METAR. Then, I scan thru the output, looking for what looks + like a METAR string (that's not hard in Perl). Oh, EHSB can be any site + location code where there is a reporting station. +Index: libgeo-metar-perl/t/metar.t +=================================================================== +--- libgeo-metar-perl.orig/t/metar.t ++++ libgeo-metar-perl/t/metar.t +@@ -5,59 +5,19 @@ + # Test script for METAR installation. + + use strict; +-use Test; ++use Test::More tests => 7; + +-BEGIN { plan tests => 6 } ++my $modname = "Geo::METAR"; ++my $m; + +-use Geo::METAR; +- +-my %tally = (passed => 0, failed => 0, skipped => 0); +- +-print "Testing METAR.\n"; +- +-my $m = new Geo::METAR; +- +-# Create a new instance. +- +-if (ref $m eq 'Geo::METAR') { +- ok(1); +-} else { +- ok(0); +-} +- +-## +-## Try out one hard-coded example. We need many more of these. +-## +- +-if ($m->metar("KFDY 251450Z 21012G21KT 8SM OVC065 04/M01 A3010 RMK 57014")) { +- ok(1); +-} else { +- ok(0); +-} +- +-if ($m->SITE eq "KFDY") { +- ok(1); +-} else { +- ok(0); +-} +- +-if ($m->DATE eq "25") { +- ok(1); +-} else { +- ok(0); +-} +- +-if ($m->MOD eq "AUTO") { +- ok(1); +-} else { +- ok(0); +-} +- +-if ($m->TEMP_F eq "39.2") { +- ok(1); +-} else { +- ok(0); +-} ++use_ok($modname); ++ok($m = $modname->new()); ++ok(ref $m eq $modname); ++ ++ok($m->metar("KFDY 251450Z 21012G21KT 8SM OVC065 04/M01 A3010 RMK 57014")); ++ok($m->SITE eq "KFDY"); ++ok($m->DATE eq "25"); ++ok($m->TEMP_F eq "39.2"); + + exit; + diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/patches/visibility.patch /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/patches/visibility.patch --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/patches/visibility.patch 1970-01-01 01:00:00.000000000 +0100 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/patches/visibility.patch 2008-06-13 16:48:41.000000000 +0100 @@ -0,0 +1,22 @@ +Index: libgeo-metar-perl/METAR.pm +=================================================================== +--- libgeo-metar-perl.orig/METAR.pm ++++ libgeo-metar-perl/METAR.pm +@@ -1282,7 +1282,7 @@ sub _process + ## Visibility. + ## + +- { ++ if($self->{visibility}) { + my $vis = $self->{visibility}; + # test for statute miles + if ($vis =~ /SM$/){ +@@ -1290,7 +1290,7 @@ sub _process + if ($vis =~ /M(\d\/\d)/o) { + $self->{VISIBILITY} = "Less than $1 statute miles"; + } else { +- $self->{VISIBILITY} = $vis . " Statute Miles"; ++ $self->{VISIBILITY} = $vis . " statute miles"; + } # end if + # auto metars can have non-directional visibility reports + } elsif (($self->{MOD} eq 'AUTO') and ($vis =~ /(\d+)NDV$/)){ diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/patches/wind.patch /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/patches/wind.patch --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/patches/wind.patch 1970-01-01 01:00:00.000000000 +0100 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/patches/wind.patch 2008-06-13 16:48:41.000000000 +0100 @@ -0,0 +1,210 @@ +Index: libgeo-metar-perl/METAR.pm +=================================================================== +--- libgeo-metar-perl.orig/METAR.pm ++++ libgeo-metar-perl/METAR.pm +@@ -333,9 +333,13 @@ sub new + $self->{WIND_GUST_KTS} = undef; # wind gusts (knots) + $self->{WIND_MPH} = undef; # wind speed (MPH) + $self->{WIND_GUST_MPH} = undef; # wind gusts (MPH) ++ $self->{WIND_MS} = undef; # wind speed (m/s) ++ $self->{WIND_GUST_MS} = undef; # wind gusts (m/s) + $self->{WIND_VAR} = undef; # wind variation (text) + $self->{WIND_VAR_1} = undef; # wind variation (direction 1) + $self->{WIND_VAR_2} = undef; # wind variation (direction 2) ++ $self->{WIND_VAR_ENG_1}= undef; # wind variation (text, direction 1) ++ $self->{WIND_VAR_ENG_2}= undef; # wind variation (text, direction 2) + $self->{VISIBILITY} = undef; # visibility info + $self->{RUNWAY} = [ ]; # runway vis. + $self->{WEATHER} = [ ]; # current weather +@@ -1112,14 +1116,20 @@ sub _process + { + my $wind = $self->{wind}; + my $dir_deg = substr($wind,0,3); ++ my $wind_speed; + my $dir_eng = ""; + my $dir_abb = ""; + ++ $wind_speed = $1 if($wind =~ /...(\d{2,3})/o); + # Check for wind direction + if ($dir_deg =~ /VRB/i) { +- $dir_deg = "Variable"; ++ $dir_deg = $dir_eng = "Variable"; + } else { +- if ($dir_deg < 15) { ++ if ($wind_speed == 0 and $dir_deg == 0) { ++ # Calm wind (00000KT in METAR) ++ $dir_eng = "Calm"; ++ print "wind is calm\n" if $self->{debug}; ++ } elsif ($dir_deg < 15) { + $dir_eng = "North"; + $dir_abb = "N"; + } elsif ($dir_deg < 30) { +@@ -1167,38 +1177,45 @@ sub _process + } elsif ($dir_deg < 345) { + $dir_eng = "North/Northwest"; + $dir_abb = "NNW"; +- } else { ++ } elsif ($dir_deg < 360) { + $dir_eng = "North"; + $dir_abb = "N"; ++ } else { ++ # Shouldn't happen, but if for some reason the METAR ++ # information doesn't contain a reasonable direction... ++ $dir_eng = "undeterminable"; + } + } + + my $kts_speed = undef; + my $mph_speed = undef; ++ my $mps_speed = undef; + + my $kts_gust = ""; + my $mph_gust = ""; ++ my $mps_gust = ""; + + # parse knots + + if ($self->{windtype} == $wt_knots){ + $wind =~ /...(\d\d\d?)/o; + $kts_speed = $1; +- $mph_speed = $kts_speed * 1.1508; +- ++ $mph_speed = $kts_speed * 1.15077945; ++ $mps_speed = $kts_speed * 0.514444444; + + if ($wind =~ /.{5,6}G(\d\d\d?)/o) { + $kts_gust = $1; +- $mph_gust = $kts_gust * 1.1508; ++ $mph_gust = $kts_gust * 1.15077945; ++ $mps_gust = $kts_gust * 0.514444444; + } + # else: parse meters/second + } elsif ($self->{windtype} == $wt_mps){ + $wind=~ /...(\d\d\d?)/o; +- my $mps_speed = $1; ++ $mps_speed = $1; + $kts_speed = $mps_speed * 1.9438445; # units + $mph_speed = $mps_speed * 2.2369363; + if ($wind =~ /\d{5,6}G(\d\d\d?)/o) { +- my $mps_gust = $1; ++ $mps_gust = $1; + $kts_gust = $mps_gust * 1.9438445; + $mph_gust = $mps_gust * 2.2369363; + } +@@ -1208,9 +1225,11 @@ sub _process + + $self->{WIND_KTS} = $kts_speed; + $self->{WIND_MPH} = $mph_speed; ++ $self->{WIND_MS} = $mps_speed; + + $self->{WIND_GUST_KTS} = $kts_gust; + $self->{WIND_GUST_MPH} = $mph_gust; ++ $self->{WIND_GUST_MS} = $mps_gust; + + $self->{WIND_DIR_DEG} = $dir_deg; + $self->{WIND_DIR_ENG} = $dir_eng; +@@ -1226,8 +1245,39 @@ sub _process + { + if ($self->{windvar} =~ /^(\d\d\d)V(\d\d\d)$/){ + $self->{WIND_VAR} = "Varying between $1 and $2"; +- $self->{WIND_VAR_1} = $1; +- $self->{WIND_VAR_2} = $2; ++ $self->{WIND_VAR_1} = $1; ++ $self->{WIND_VAR_2} = $2; ++ my @direction = ( ++ 15 => "North", ++ 30 => "North/Northeast", ++ 60 => "Northeast", ++ 75 => "East/Northeast", ++ 105 => "East", ++ 120 => "East/Southeast", ++ 150 => "Southeast", ++ 165 => "South/Southeast", ++ 195 => "South", ++ 210 => "South/Southwest", ++ 240 => "Southwest", ++ 265 => "West/Southwest", ++ 285 => "West", ++ 300 => "West/Northwest", ++ 330 => "Northwest", ++ 345 => "North/Northwest", ++ 360 => "North", ++ 1000 => "undeterminable"); ++ for(my $x = 0; $x < $#direction; $x += 2) { ++ if($self->{WIND_VAR_1} < $direction[$x]) { ++ $self->{WIND_VAR_ENG_1} = $direction[$x+1]; ++ last; ++ } ++ } ++ for(my $x = 0; $x < $#direction; $x += 2) { ++ if($self->{WIND_VAR_2} < $direction[$x]) { ++ $self->{WIND_VAR_ENG_2} = $direction[$x+1]; ++ last; ++ } ++ } + } + } + +@@ -1322,6 +1372,7 @@ sub dump + print "date_time: $self->{date_time}\n"; + print "modifier: $self->{modifier}\n"; + print "wind: $self->{wind}\n"; ++ print "variable wind: $self->{vrbwind}\n"; + print "visibility: $self->{visibility}\n"; + print "runway: $self->{runway}\n"; + print "weather: " . join(', ', @{$self->{weather}}) . "\n"; +@@ -1503,11 +1554,11 @@ Modifier (AUTO/COR) if any. + + =item WIND_DIR_ENG + +-The current wind direction in english (Southwest, East, North, etc.) ++The current wind direction in English (Southwest, East, North, etc.) + + =item WIND_DIR_ABB + +-The current wind direction in abbreviated english (S, E, N, etc.) ++The current wind direction in abbreviated English (S, E, N, etc.) + + =item WIND_DIR_DEG + +@@ -1521,6 +1572,10 @@ The current wind speed in Knots. + + The current wind speed in Miles Per Hour. + ++=item WIND_MS ++ ++The current wind speed in Metres Per Second. ++ + =item WIND_GUST_KTS + + The current wind gusting speed in Knots. +@@ -1529,6 +1584,10 @@ The current wind gusting speed in Knots. + + The current wind gusting speed in Miles Per Hour. + ++=item WIND_GUST_MS ++ ++The current wind gusting speed in Metres Per Second. ++ + =item WIND_VAR + + The wind variation in English +@@ -1537,10 +1596,18 @@ The wind variation in English + + The first wind variation direction + ++=item WIND_VAR_ENG_1 ++ ++The first wind variation direction in English ++ + =item WIND_VAR_2 + + The second wind variation direction + ++=item WIND_VAR_ENG_2 ++ ++The second wind variation direction in English ++ + =item VISIBILITY + + Visibility information. diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/README.Debian /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/README.Debian --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/README.Debian 2008-06-13 16:48:41.000000000 +0100 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/README.Debian 2008-06-13 16:48:41.000000000 +0100 @@ -8,17 +8,23 @@ http://bugs.debian.org/libgeo-metar-perl Contributors: - Timo Hietanen (#262397) - - also grabs the altimeter setting if it's reported in hectopascals (Q\d\d\d\d instead of A\d\d\d\d) + Timo Hietanen (#262397) + - also grabs the altimeter setting if it's reported in hectopascals + (Q\d\d\d\d instead of A\d\d\d\d) - dont's set $self->{MOD} to "AUTO" by default - tries a bit harder not to mix up weather groups with station identifiers - - recognizes the visibility setting "CAVOK" (ceiling and visibility OK) - - Doesn't recognize the METAR tag dddVddd (d = digit), which defines wind direction's variation. - - Assumes that station ID begins with the letter 'K' (matches /K[A-Z]{3,3}/), while it should match /[A-Z]{4,4}/ - - Tries to find the visibility information even though $self->{visibility} isn't defined (information - missing from the METAR report). This leads to a couple of warnings about uninitalized variables. + - Tries to find the visibility information even though $self->{visibility} + isn't defined (information missing from the METAR report). This leads to + a couple of warnings about uninitalized variables. +A couple of bugs that need fixing, reported by Timo: + +- Unknown METAR group: RESHRA +- Unknown METAR group: R06/P1500UU +- Unknown METAR group: VV002 +- Unknown METAR group: 6000NE +- Unknown METAR group: 24CLRD// +- Unknown METAR group: 2419//95 +- Interprets R24/0650V1400N R06/0800V1200D as temperature 24, dew point 6 +- Convert numerals to numeric (04 -> 4) - --Jay Bonci - - diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/rules /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/rules --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/rules 2008-06-13 16:48:41.000000000 +0100 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/rules 2008-06-13 16:48:41.000000000 +0100 @@ -5,33 +5,36 @@ # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 -# This is the debhelper compatibility version to use. -# export DH_COMPAT=4 +export PERL_MM_USE_DEFAULT=1 -PACKAGE=`pwd | sed -e "s/.*\/\\(.*\\)-.*/\\1/"` +PACKAGE = $(shell dh_listpackages) +TMP = $(CURDIR)/debian/$(PACKAGE) +PERL ?= /usr/bin/perl +include /usr/share/quilt/quilt.make -build: +build: build-stamp +build-stamp: $(QUILT_STAMPFN) dh_testdir - # Add here commands to compile the package. - perl Makefile.PL verbose INSTALLDIRS=vendor -clean: + $(PERL) Makefile.PL verbose INSTALLDIRS=vendor + $(MAKE) + $(MAKE) test + touch $@ + +clean: unpatch dh_testdir dh_testroot + dh_clean build-stamp install-stamp + [ ! -f Makefile ] || $(MAKE) realclean - -$(MAKE) clean - rm -f Makefile.old - dh_clean - -install: +install: install-stamp +install-stamp: build-stamp dh_testdir dh_testroot dh_clean -k dh_installdirs - - $(MAKE) PREFIX=$(CURDIR)/debian/$(PACKAGE)/usr OPTIMIZE="-O2 -g -Wall" test install - -find $(CURDIR)/debian -type d | xargs rmdir -p --ignore-fail-on-non-empty - -find $(CURDIR)/examples/ -exec chmod 755 {} \; + $(MAKE) install DESTDIR=$(TMP) PREFIX=/usr + touch $@ binary-arch:; binary-indep: build install @@ -40,16 +43,15 @@ dh_installdocs dh_installman dh_installchangelogs - dh_installexamples + dh_installexamples examples/* dh_link - dh_strip + dh_perl dh_compress dh_fixperms dh_installdeb - dh_perl dh_gencontrol dh_md5sums dh_builddeb binary: binary-indep binary-arch -.PHONY: build clean binary-indep binary-arch binary install configure +.PHONY: build clean binary-indep binary-arch binary install diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/watch /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/watch --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/debian/watch 2008-06-13 16:48:41.000000000 +0100 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/debian/watch 2008-06-13 16:48:41.000000000 +0100 @@ -1,2 +1,2 @@ -version=2 -http://www.cpan.org/modules/by-module/Geo/Geo-METAR-([0-9].*)\.tar.gz +version=3 +http://search.cpan.org/dist/Geo-METAR/ .*/Geo-METAR-v?([[:digit:]].*)\.tar\.gz diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/examples/fetch_temp.pl /tmp/cendO84dgE/libgeo-metar-perl-1.15/examples/fetch_temp.pl --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/examples/fetch_temp.pl 2000-11-25 00:04:50.000000000 +0000 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/examples/fetch_temp.pl 2007-11-13 21:19:27.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/perl -w -# $Id: fetch_temp.pl,v 1.3 2000/11/25 00:03:12 jzawodn Exp $ +# $Id: fetch_temp.pl,v 1.1 2007/11/13 21:19:27 koos Exp $ # Brief Description # ================= diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/examples/simple_dump.pl /tmp/cendO84dgE/libgeo-metar-perl-1.15/examples/simple_dump.pl --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/examples/simple_dump.pl 2000-11-25 00:04:50.000000000 +0000 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/examples/simple_dump.pl 2007-11-13 21:19:27.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/perl -# $Id: simple_dump.pl,v 1.2 1999/11/19 00:10:57 jzawodn Exp $ +# $Id: simple_dump.pl,v 1.1 2007/11/13 21:19:27 koos Exp $ # Example script for METAR.pm. diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/HACKING /tmp/cendO84dgE/libgeo-metar-perl-1.15/HACKING --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/HACKING 2000-11-25 00:04:50.000000000 +0000 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/HACKING 1970-01-01 01:00:00.000000000 +0100 @@ -1,7 +0,0 @@ -Notes for folks hacking on Geo::METAR -===================================== - -If you use Emacs to edit the code, I recommend cperl-mode an the -cperl-style `C++'. It's what I use. - -Feel free to add things to the TODO list. diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/Makefile.PL /tmp/cendO84dgE/libgeo-metar-perl-1.15/Makefile.PL --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/Makefile.PL 2000-11-25 00:04:50.000000000 +0000 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/Makefile.PL 2007-11-13 21:19:22.000000000 +0000 @@ -2,7 +2,7 @@ WriteMakefile( NAME => 'Geo::METAR', - DISTNAME => 'METAR-1.14', + DISTNAME => 'METAR-1.15', VERSION_FROM => 'METAR.pm', - PREREQ_PM => {}, + PREREQ_PM => {}, ); diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/MANIFEST /tmp/cendO84dgE/libgeo-metar-perl-1.15/MANIFEST --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/MANIFEST 2000-11-25 00:04:50.000000000 +0000 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/MANIFEST 2007-11-13 21:19:22.000000000 +0000 @@ -1,7 +1,6 @@ METAR.pm Makefile.PL README -HACKING TODO t/metar.t examples/fetch_temp.pl diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/METAR.pm /tmp/cendO84dgE/libgeo-metar-perl-1.15/METAR.pm --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/METAR.pm 2008-06-13 16:48:41.000000000 +0100 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/METAR.pm 2008-01-02 13:47:00.000000000 +0000 @@ -1,4 +1,32 @@ -# $Id: METAR.pm,v 1.8 2000/11/25 00:07:38 jzawodn Exp $ +# $Id: METAR.pm,v 1.11 2008/01/02 13:47:00 koos Exp $ + +# KH: fix the parser +# should be a finite state machine +# - metar has rules what comes after what. but codes can be missing. +# (measurement not done) or //// (measurement broken at the moment) +# so given a state counter, it can stay the same or go up one or more states, +# but it can never go down +# +# info on the last bit which is actually a forecast: (German) +# http://www.wetterklima.de/flug/metar/Metarvorhersage.htm +# +# more info here (dutch, and txt 707 is not standard metar) +# http://www.vwkweb.nl/index.html?http://www.vwkweb.nl/weerinfo/weerinfo_teletekst707.html +# and also (dutch) +# http://www.gids.nl/weather/eheh/metari.html +# +# 'METAR decoding in Europe' +# http://users.hol.gr/~chatos/VATSIM/TM/metar.html +# +# english explanation +# http://booty.org.uk/booty.weather/metinfo/codes/METAR_decode.htm +# +# canadian explanation +# http://meteocentre.com/doc/metar.html +# +# 'METAR decoding, TAF decoding' +# http://stoivane.kapsi.fi/metar/ +# # This module is used for decoding NWS METAR code. @@ -18,47 +46,83 @@ # 9/205 51007 # # LA +# # KLAX 251450Z 07004KT 7SM SCT100 BKN200 14/11 A3005 RMK AO2 SLP173 # T01390111 56005 +# +# Soesterberg +# +# EHSB 181325Z 24009KT 8000 -RA BR FEW011 SCT022 OVC030 07/06 Q1011 WHT WHT TEMPO GRN # For METAR info, please see # http://tgsv5.nws.noaa.gov/oso/oso1/oso12/metar.htm +# moved +# http://metar.noaa.gov/ +# +# in scary detail (metar coding) +# +# http://metar.noaa.gov/table_master.jsp?sub_menu=yes&show=fmh1ch12.htm&dir=./handbook/&title=title_handbook +# + # The METAR specification is dictated in the Federal Meteorological Handbook # which is available on-line at: # http://tgsv5.nws.noaa.gov/oso/oso1/oso12/fmh1.htm # General Structure is: -# SITE, DATE/TIME, WIND, VISIBILITY, CLOUDS, TEMPERATURE, PRESSURE, REMARKS +# TYPE, SITE, DATE/TIME, WIND, VISIBILITY, CLOUDS, TEMPERATURE, PRESSURE, REMARKS # Specifically: -# SITE +# TYPE (optional) +# METAR or SPECI +# METAR: regular report +# SPECI: special report + +# SITE (required, only once) # # 4-Char site identifier (KLAX for LA, KHST for Houston) -# DATE/TIME +# DATE/TIME (required, only once) # # 6-digit time followed by "Z", indicating UTC -# WIND +# REPORT MODIFIER (optional) +# AUTO or COR +# AUTO = Automatic report (no human intervention) +# COR = Corrected METAR or SPECI + +# WIND (group) # # Wind direction (\d\d\d) and speed (\d?\d\d) and optionaling gusting # information denoted by "G" and speed (\d?\d\d) followed by "KT", for knots. # # Wind direction MAY be "VRB" (variable) instead of a compass direction. # +# Variable Wind Direction (Speeds greater than 6 knots). Variable wind +# direction with wind speed greater than 6 knots shall be coded in the +# format, dndndnVdxdxdx +# # Calm wind is recorded as 00000KT. -# VISIBILITY +# VISIBILITY (group) # -# Visibility (\d+) followed by "SM" for statute miles +# Visibility (\d+) followed by "SM" for statute miles or no 'SM' for meters +# (european) # # May be 1/(\d)SM for a fraction. # # May be M1/\d)SM for less than a given fraction. (M="-") +# +# \d\d\d\d according to KNMI +# lowest horizontal visibility (looking around) +# round down +# 0000 - 0500m in steps of 0050m +# 0500 - 5000m in steps of 0100m +# 5000 - 9999m in steps of 1000m +# 10km or more is 9999 -# RUNWAY Visual Range Group (I've never seen this, but it's in the spec) +# RUNWAY Visual Range (Group) # # R(\d\d\d)(L|C|R)?/((M|P)?\d\d\d\d){1,2}FT # @@ -70,6 +134,16 @@ # # "M" beginning a value means less than the reportable value of \d\d\d\d. # "P" beginning a value means more than the reportable value of \d\d\d\d. +# +# new +# +# R(\d\d\d[LCR]?)/([MP]?\d\d\d\d)(V[MP]?\d\d\d\d)?FT +# +# $1 runway number + Left/Center/Right +# $2 visibility feet +# $3 Varying feet +# M = less than +# P = more than # WEATHER (Present Weather Group) # @@ -85,6 +159,22 @@ # The report may have a trailing CB (cumulonimbus) or TCU (towering # cumulus) appended. ([A-Z]{2,3})?(\d\d\d)(CB|TCU)? +# Vertical visibility (VV) +# +# VV +# This group is reported when the sky is obscured. VV is the group indicator, +# and hshshs is the vertical visibility in units of 30 metres +# (hundreds of feet). +# +# hshshs - Examples of Encoding +# HEIGHT METAR CODE +# 100 ft (30 metres) 001 +# 450 ft (135 metres) 004 +# 2,700 ft (810 metres) 027 +# 12,600 ft (3,780 metres) 1300 +# +# source http://meteocentre.com/doc/metar.html +# # TEMPERATURE and DEW POINT # # (M?\d\d)/(M?\d\d) where $1 is the current temperature in degrees celcius, @@ -95,13 +185,11 @@ # PRESSURE # -# The pressure, or altimeter setting, at the reporting site recorded in inches -# of mercury (Hg) minus the decimal point. It should always look like -# (A\d\d\d\d). -# -# Note: The WMO standard is to report the altimeter in whole hectopascals. In -# this case, the altimeter setting group will be begin with a Q instead of an -# A. +# The pressure, or altimeter setting, at the reporting site recorded in +# inches of mercury (Hg) minus the decimal point. It should always look +# like (A\d\d\d\d). +# +# KNMI: Q\d\d\d\d pressure in hPa calculated for sea level # REMARKS # @@ -109,6 +197,26 @@ # informative of special conditions. # # Remarks begin with the "RMK" keyword and continue to the end of the line. +# +# trend group +# +# color codes BLU WHT GRN YLO AMB RED +# BLACK: vliegveld dicht +# future trend +# NOSIG no significant change +# TEMPO temporary change +# WHT WHT TEMPO GRN = current white, prediction white temporary green +# NSW no significant weather +# AT at a given time +# PROB30 probability 30% +# BECMG becoming +# BECMG (weather) FM \d\d\d\d TL \d\d\d\d = from until utc times +# BECMG (weather) AT \d\d\d\d = at utc time +# BECMG (weather) TL \d\d\d\d = change until utc time +# BECMG 2000 visibility +# BECMG NSW weather type +# etc etc +# FCST CANCEL (2 tokens!) Forecast cancel: no further forecasts for a while ### Package Definition @@ -121,59 +229,80 @@ use vars qw($AUTOLOAD $VERSION); use Carp 'cluck'; -$VERSION = '1.14'; +$VERSION = '1.15'; ## ## Lookup tables ## my %_weather_types = ( - MI => 'shallow', - PI => 'partial', - BC => 'patches', - DR => 'drizzle', - BL => 'blowing', - SH => 'shower(s)', - TS => 'thunderstorm', - FZ => 'freezing', - - DZ => 'drizzle', - RA => 'rain', - SN => 'snow', - SG => 'snow grains', - IC => 'ice crystals', - PE => 'ice pellets', - GR => 'hail', - GS => 'small hail/snow pellets', - UP => 'unknown precip', - - BR => 'mist', - FG => 'fog', - FU => 'smoke', - VA => 'volcanic ash', - DU => 'dust', - SA => 'sand', - HZ => 'haze', - PY => 'spray', - - PO => 'dust/sand whirls', - SQ => 'squalls', - FC => 'funnel cloud(tornado/waterspout)', - SS => 'sand storm', - DS => 'dust storm' - ); + MI => 'shallow', + PI => 'partial', + BC => 'patches', + DR => 'drizzle', + BL => 'blowing', + SH => 'shower(s)', + TS => 'thunderstorm', + FZ => 'freezing', + + DZ => 'drizzle', + RA => 'rain', + SN => 'snow', + SG => 'snow grains', + IC => 'ice crystals', + PE => 'ice pellets', + GR => 'hail', + GS => 'small hail/snow pellets', + UP => 'unknown precip', + + BR => 'mist', + FG => 'fog', + PRFG => 'fog banks', # officially PR is a modifier of FG + FU => 'smoke', + VA => 'volcanic ash', + DU => 'dust', + SA => 'sand', + HZ => 'haze', + PY => 'spray', + + PO => 'dust/sand whirls', + SQ => 'squalls', + FC => 'funnel cloud(tornado/waterspout)', + SS => 'sand storm', + DS => 'dust storm', +); my $_weather_types_pat = join("|", keys(%_weather_types)); my %_sky_types = ( - SKC => "Sky Clear", - CLR => "Sky Clear", - SCT => "Scattered", - BKN => "Broken", - FEW => "Few", - OVC => "Solid Overcast", + SKC => "Sky Clear", + CLR => "Sky Clear", + SCT => "Scattered", + BKN => "Broken", + FEW => "Few", + OVC => "Solid Overcast", + NSC => "No significant clouds", + NCD => "No cloud detected", ); +my %_trend_types = ( + BLU => "8 km view", + WHT => "5 km view", + GRN => "3.7 km view", + YLO => "1.6 km view", + AMB => "0.8 km view", + RED => "< 0.8 km view", + BLACK => "airport closed", + NOSIG => "No significant change", + TEMPO => "Temporary change", + NSW => "No significant weather", + PROB => "Probability", + BECMG => "Becoming", + LAST => "Last", +); + +my $_trend_types_pat = join("|", keys(%_trend_types)); + ## ## Constructor. ## @@ -198,47 +327,50 @@ $self->{TIME} = undef; # time it was issued $self->{MOD} = undef; # modifier (AUTO/COR) $self->{WIND_DIR_DEG} = undef; # wind dir in degrees - $self->{WIND_DIR_ENG} = undef; # wind dir in english (NW/SE) + $self->{WIND_DIR_ENG} = undef; # wind dir in english (Northwest/Southeast) + $self->{WIND_DIR_ABB} = undef; # wind dir in abbreviated english (NW/SE) $self->{WIND_KTS} = undef; # wind speed (knots) $self->{WIND_GUST_KTS} = undef; # wind gusts (knots) $self->{WIND_MPH} = undef; # wind speed (MPH) $self->{WIND_GUST_MPH} = undef; # wind gusts (MPH) - $self->{WIND_VAR_DEG} = undef; # wind variation in degrees - $self->{WIND_VAR_ENG} = undef; # wind variation in english + $self->{WIND_VAR} = undef; # wind variation (text) + $self->{WIND_VAR_1} = undef; # wind variation (direction 1) + $self->{WIND_VAR_2} = undef; # wind variation (direction 2) $self->{VISIBILITY} = undef; # visibility info - $self->{RUNWAY} = undef; # runyway vis. + $self->{RUNWAY} = [ ]; # runway vis. $self->{WEATHER} = [ ]; # current weather $self->{WEATHER_LOG} = [ ]; # weather log - $self->{SKY} = [ ]; # curent sky + $self->{SKY} = [ ]; # current sky (cloudcover) $self->{TEMP_F} = undef; # current temp, celcius - $self->{TEMP_C} = undef; # converted to farenheit + $self->{TEMP_C} = undef; # converted to fahrenheit $self->{DEW_F} = undef; # dew point, celcius - $self->{DEW_C} = undef; # dew point, farenheit + $self->{DEW_C} = undef; # dew point, fahrenheit $self->{HOURLY_TEMP_F} = undef; # hourly current temp, celcius - $self->{HOURLY_TEMP_C} = undef; # hourly converted to farenheit + $self->{HOURLY_TEMP_C} = undef; # hourly converted to fahrenheit $self->{HOURLY_DEW_F} = undef; # hourly dew point, celcius - $self->{HOURLY_DEW_C} = undef; # hourly dew point, farenheit + $self->{HOURLY_DEW_C} = undef; # hourly dew point, fahrenheit $self->{HOURLY_PRECIP} = undef; # hourly precipitation - $self->{ALT} = undef; # altimeter setting (Hg) - $self->{ALT_HP} = undef; # altimeter setting (hPa) + $self->{ALT} = undef; # altimeter setting $self->{SLP} = undef; # sea level pressure - $self->{REMARKS} = undef; # remarks and such + $self->{REMARKS} = undef; # remarks $self->{tokens} = [ ]; # the "token" list $self->{type} = "METAR"; # the report type (METAR/SPECI) # default=METAR $self->{site} = undef; # the site code (4 chars) $self->{date_time} = undef; # date/time - $self->{modifier} = undef; # the AUTO/COR modifier + $self->{modifier} = "AUTO"; # the AUTO/COR modifier (if + # any) default=AUTO $self->{wind} = undef; # the wind information - $self->{vrbwind} = undef; # variable wind information + $self->{windtype} = undef; # the wind speed type (knots/meterpersecond/kilometersperhour) + $self->{windvar} = undef; # the wind variation $self->{visibility} = undef; # visibility information $self->{runway} = undef; # runway visibility $self->{weather} = [ ]; # current weather conditions $self->{sky} = [ ]; # sky conditions (cloud cover) $self->{temp_dew} = undef; # temp and dew pt. - $self->{alt} = undef; # altimeter setting (Hg) - $self->{alt_hp} = undef; # altimeter setting (hPa) + $self->{alt} = undef; # altimeter setting + $self->{pressure} = undef; # pressure (HPa) $self->{slp} = undef; # sea level pressure $self->{remarks} = [ ]; # remarks @@ -360,7 +492,6 @@ my @toks = @{$self->{tokens}}; # copy tokens array... my $tok; - my $in_remarks = 0; # started processing remarks ## This is a semi-brute-force way of doing things, but the amount ## of data is relatively small, so it shouldn't be a big deal. @@ -368,6 +499,34 @@ ## Ideally, I'd have it skip checks for items which have been ## found, but that would make this more "linear" and I'd remove ## the pretty while loop. + # + # KH: modified to maintain state to not get lost in remarks and stuff + # and be a lot better at parsing + + # states + + my $expect_type = 0; + my $expect_site = 1; + my $expect_datetime = 2; + my $expect_modifier = 3; + my $expect_wind = 4; + my $expect_visibility = 5; + my $expect_runwayvisual = 6; + my $expect_presentweather = 7; + my $expect_clouds = 8; + my $expect_temperature = 9; + my $expect_pressure = 10; + my $expect_recentweather = 11; + my $expect_remarks = 12; + my $expect_usremarks = 13; + + my $parsestate = $expect_type; + + # windtypes + + my $wt_knots = 1; + my $wt_mps = 2; + my $wt_kph = 3; ## Assume standard report by default @@ -376,13 +535,13 @@ while (defined($tok = shift(@toks))) ## as long as there are tokens { - print "trying to match [$tok]\n" if $self->{debug}; + print "trying to match [$tok] state is $parsestate\n" if $self->{debug}; ## ## is it a report type? ## - if (($tok =~ /METAR/i) or ($tok =~ /SPECI/i)) + if (($parsestate == $expect_type) and ($tok =~ /(METAR|SPECI)/i)) { $self->{type} = $tok; @@ -395,6 +554,7 @@ $self->{TYPE} = "Special Weather Report"; } print "[$tok] is a report type.\n" if $self->{debug}; + $parsestate = $expect_site; next; } @@ -402,10 +562,11 @@ ## is is a site ID? ## - elsif ($tok =~ /^[A-Z]{4,4}$/ && !$self->{site}) + elsif (($parsestate <= $expect_site) and ($tok =~ /([A-Z]{4}|K[A-Z0-9]{3})/)) { $self->{site} = $tok; print "[$tok] is a site ID.\n" if $self->{debug}; + $parsestate = $expect_datetime; next; } @@ -413,10 +574,11 @@ ## is it a date/time? ## - elsif ($tok =~ /\d{6,6}Z/i) + elsif (($parsestate == $expect_datetime) and ($tok =~ /\d{6,6}Z/i)) { $self->{date_time} = $tok; print "[$tok] is a date/time.\n" if $self->{debug}; + $parsestate = $expect_modifier; next; @@ -426,77 +588,140 @@ ## is it a report modifier? ## - elsif (($tok =~ /AUTO/i) or ($tok =~ /COR/i)) + elsif (($parsestate == $expect_modifier) and ($tok =~ /AUTO|COR|CC[A-Z]/i)) { $self->{modifier} = $tok; print "[$tok] is a report modifier.\n" if $self->{debug}; + $parsestate = $expect_wind; next; } ## - ## is it wind information? - ## + ## is it wind information in knots? + # + # eew: KT seems to be optional + # but making it optional fails on other stuff + # sortafix: wind needs to be \d\d\d\d\d or VRB\d\d + # optional \d\d\d\d\dG\d\d\d (gust direction) - elsif ($tok =~ /.*?KT$/i) + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_visibility) and ($tok =~ /(\d{3}|VRB)\d{2}(G\d{1,3})?(KT)?$/i)) { $self->{wind} = $tok; - print "[$tok] is wind information.\n" if $self->{debug}; + $self->{windtype} = $wt_knots; + print "[$tok] is wind information in knots.\n" if $self->{debug}; + $parsestate = $expect_wind; # stay in wind, it can have variation next; } - ## - ## is it variable wind information? - ## - - elsif ($tok =~ /^\d\d\dV\d\d\d$/i) + ## + ## is it wind information in meters per second? + ## + ## can be variable too + + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_visibility) and ($tok =~ /^(\d{3}|VRB)\d{2}(G\d{2,3})?MPS$/)) { - $self->{vrbwind} = $tok; - print "[$tok] is variable wind information.\n" if $self->{debug}; + $self->{wind} = $tok; + print "[$tok] is wind information.\n" if $self->{debug}; + $self->{windtype} = $wt_mps; + $parsestate = $expect_wind; # stay in wind, it can have variation + next; + } + + ## + ## is it wind variation information? + ## + + elsif (($parsestate >= $expect_wind) and ($parsestate < $expect_visibility) and ($tok =~ /^\d{3}V\d{3}$/)) + { + $self->{windvar} = $tok; + print "[$tok] is wind variation information.\n" if $self->{debug}; + $parsestate = $expect_visibility; + next; + } + + ## + ## wind information missing at the moment? + ## + + elsif (($parsestate >= $expect_wind) and ($parsestate < $expect_visibility) and ($tok =~ /^\/\/\/\/\/(KT|MPS)$/)){ + print "[$tok] is missing wind information.\n" if $self->{debug}; + $parsestate = $expect_visibility; + next; + } + + ## + ## is it visibility information in meters? + ## + + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_runwayvisual) and ($tok =~ /^\d{4}$/)) + { + $self->{visibility} = $tok; + print "[$tok] is numerical visibility information.\n" if $self->{debug}; + $parsestate = $expect_visibility; + next; + } + + ## auto visibility information in meters? + + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_runwayvisual) and ($tok =~ /^\d{4}NDV$/)) + { + $self->{visibility} = $tok; + print "[$tok] is automatic numerical visibility information.\n" if $self->{debug}; + $parsestate = $expect_visibility; next; } ## - ## is it visibility information? + ## is it visibility information in statute miles? ## - elsif ($tok =~ /.*?SM$/i) + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_runwayvisual) and ($tok =~ /.*?SM$/i)) { $self->{visibility} = $tok; - print "[$tok] is visibility information.\n" if $self->{debug}; + print "[$tok] is statute miles visibility information.\n" if $self->{debug}; + $parsestate = $expect_visibility; next; } - ## - ## does it say CAVOK? (ceiling and visibility ok) - ## - - elsif ($tok =~ /^CAVOK/i) - { - $self->{visibility} = $tok; - print "[$tok] is visibility information, too.\n" if $self->{debug}; - next; - } - ## ## is it visibility information with a leading digit? + ## + ## sample: + ## KERV 132345Z AUTO 07008KT 1 1/4SM HZ 34/11 A3000 RMK AO2 + ## ^^^^^^^ ## - elsif ($tok =~ /^\d$/) + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_runwayvisual) and ($tok =~ /^\d$/)) { $tok .= " " . shift(@toks); $self->{visibility} = $tok; - print "[$tok is multi-part visibility information.\n" if $self->{debug}; + print "[$tok] is multi-part visibility information.\n" if $self->{debug}; + $parsestate = $expect_visibility; next; } + ## visibility modifier + + elsif (($parsestate == $expect_visibility) and ($tok =~ /^\d{4}(N|S|E|W|NE|NW|SE|SW)$/)) + { + print "[$tok] is a visibility modifier.\n" if $self->{debug}; + next; + } + ## ## is it runway visibility info? ## + # KH: I've seen runway visibility with 'U' units + # EHSB 121425Z 22010KT 1200 R27/1600U -DZ BKN003 OVC007 07/07 Q1016 AMB FCST CANCEL + # U= going up, D= going down, N= no change + # tendency of visual range, http://stoivane.kapsi.fi/metar/ - elsif ($tok =~ /R.*?FT$/i) + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_presentweather) and ($tok =~ /R\d+(L|R|C)?\/P?\d+(VP?\d+)?(FT|D|U|N|\/)?$/i)) { - $self->{runway} = $tok; + push (@{$self->{RUNWAY}},$tok); print "[$tok] is runway visual information.\n" if $self->{debug}; + $parsestate = $expect_runwayvisual; + # there can be multiple runways, so stay at this state next; } @@ -504,7 +729,7 @@ ## is it current weather info? ## - elsif ($tok =~ /^(-|\+)?(VC)?($_weather_types_pat)+/i) + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_clouds) and ($tok =~ /^(-|\+)?(VC)?($_weather_types_pat)+/i)) { my $engl = ""; my $qual = $1; @@ -546,27 +771,47 @@ $engl =~ s/\s\s/ /gio; push(@{$self->{WEATHER}},$engl); - push(@{$self->{weather}},$tok); print "[$tok] is current weather.\n" if $self->{debug}; + $parsestate = $expect_presentweather; + # there can be multiple current weather types, so stay at this state next; } + ## + ## special case: CAVOK + ## + + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_temperature) and ( $tok eq 'CAVOK' )) + { + push(@{$self->{sky}},$tok); + push(@{$self->{SKY}}, "Sky Clear"); + push(@{$self->{weather}},$tok); + push(@{$self->{WEATHER}},"No significant weather"); + $self->{visibility} = '9999'; + $parsestate = $expect_temperature; + next; + } + ## ## is it sky conditions (clear)? ## - elsif ( $tok eq "SKC" || $tok eq "CLR" ) + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_temperature) and ( $tok =~ /SKC|CLR/ )) { push(@{$self->{sky}},$tok); push(@{$self->{SKY}}, "Sky Clear"); + print "[$tok] is a sky condition.\n" if $self->{debug}; + $parsestate = $expect_clouds; + next; } ## ## is it sky conditions (clouds)? ## + ## sky conditions can end with /// - elsif ( $tok =~ /^(FEW|SCT|BKN|OVC|SKC|CLR)(\d\d\d)?(CB|TCU)?$/i) + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_temperature) and ( $tok =~ /^(FEW|SCT|BKN|OVC)(\d\d\d)?(CB|TCU)?\/*$/i)) { push(@{$self->{sky}},$tok); my $engl = ""; @@ -593,14 +838,40 @@ push(@{$self->{SKY}}, $engl); print "[$tok] is a sky condition.\n" if $self->{debug}; + $parsestate = $expect_clouds; + # clouds DO repeat. a lot ;) next; } + ## + ## auto detected cloud conditions + ## + + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_temperature) and ( $tok =~ /^(NSC|NCD)$/ )){ + my $engl = ""; + + $engl = $_sky_types{$tok}; + push(@{$self->{SKY}}, $engl); + print "[$tok] is an automatic sky condition.\n" if $self->{debug}; + $parsestate = $expect_temperature; + next; + } + + ## + ## Vertical visibility + ## + + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_temperature) and ( $tok =~ /^VV\d+$/ )){ + print "[$tok] is vertical visibility.\n" if $self->{debug}; + $parsestate = $expect_temperature; + next; + } + ## ## is it temperature and dew point info? ## - elsif ($tok =~ /(M?\d\d)\/(M?\d\d)/i) + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_pressure) and ($tok =~ /^(M?\d\d)\/(M?\d{0,2})/i)) { next if $self->{temp_dew}; $self->{temp_dew} = $tok; @@ -611,54 +882,84 @@ $self->{DEW_C} =~ s/^M/-/; print "[$tok] is temperature/dew point information.\n" if $self->{debug}; + $parsestate = $expect_pressure; next; } ## - ## is it an altimeter setting? (inches in mercury) + ## is it an altimeter setting? ## - elsif (!$in_remarks && $tok =~ /^A(\d\d)(\d\d)$/i) + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_remarks) and ($tok =~ /^A(\d\d)(\d\d)$/i)) { $self->{alt} = $tok; $self->{ALT} = "$1.$2"; + + # inches Hg pressure. How imperial can you get + # conversion using 'units' + + $self->{pressure} = 33.863886 * $self->{ALT}; + print "[$tok] is an altimeter setting.\n" if $self->{debug}; + $parsestate = $expect_recentweather; next; } - + ## - ## is it an altimeter setting? (hectopascals) - - elsif (!$in_remarks && $tok =~ /^Q(\d\d\d\d)$/i) + ## is it a pressure? + ## + + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_remarks) and ($tok =~ /^Q(\d\d\d\d)$/i)) { - $self->{alt_hp} = $tok; - $self->{ALT_HP} = $1; - print "[$tok] is an altimeter setting in hectopascals.\n" - if $self->{debug}; + $self->{pressure} = $1; + + $self->{ALT} = 0.029529983*$self->{pressure}; + print "[$tok] is an air pressure.\n" if $self->{debug}; + $parsestate = $expect_recentweather; + next; + } + + ## + ## recent weather? + ## + + elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_remarks) and ($tok =~ /^RE($_weather_types_pat)$/)){ + print "[$tok] is recent significant weather.\n" if $self->{debug}; + $parsestate = $expect_remarks; + next; + } + + ## + ## euro type trend? + ## + + elsif (($parsestate >= $expect_modifier) and ($tok =~ /^$_trend_types_pat/)){ + print "[$tok] is a trend.\n" if $self->{debug}; + $parsestate = $expect_remarks; next; } ## - ## automatic station type? + ## us type remarks? .. can happen quite early in the process already ## - elsif ($in_remarks && $tok =~ /^A(O\d)$/i) + elsif (($parsestate >= $expect_modifier) and ($tok =~ /^RMK$/i)) { - $self->{autostationtype} = $tok; - $self->{AUTO_STATIONTYPE} = $1; - print "[$tok] is an automatic station type remark.\n" if $self->{debug}; + push(@{$self->{remarks}},$tok); + print "[$tok] is a (US type) remark.\n" if $self->{debug}; + $parsestate = $expect_usremarks; next; } ## - ## remarks? + ## automatic station type? ## - elsif ($tok =~ /^RMK$/i) + elsif (($parsestate == $expect_usremarks) and ($tok =~ /^A(O\d)$/i)) { - push(@{$self->{remarks}},$tok); - $in_remarks = 1; - print "[$tok] is a remark.\n" if $self->{debug}; + $self->{autostationtype} = $tok; + $self->{AUTO_STATIONTYPE} = $1; + print "[$tok] is an automatic station type remark.\n" if $self->{debug}; next; } @@ -666,7 +967,7 @@ ## sea level pressure ## - elsif ($tok =~ /^SLP(\d+)/i) + elsif (($parsestate == $expect_usremarks) and ($tok =~ /^SLP(\d+)/i)) { $self->{slp} = $tok; $self->{SLP} = "$1 mb"; @@ -678,7 +979,7 @@ ## sea level pressure not available ## - elsif ($tok eq "SLPNO") + elsif (($parsestate == $expect_usremarks) and ($tok eq "SLPNO")) { $self->{slp} = "SLPNO"; $self->{SLP} = "not available"; @@ -690,7 +991,7 @@ ## hourly precipitation ## - elsif ($tok =~ /^P(\d\d\d\d)$/i) + elsif (($parsestate == $expect_usremarks) and ($tok =~ /^P(\d\d\d\d)$/i)) { $self->{hourlyprecip} = $tok; @@ -705,7 +1006,7 @@ ## weather begin/end times ## - elsif ($tok =~ /^($_weather_types_pat)([BE\d]+)$/i) + elsif (($parsestate == $expect_usremarks) and ($tok =~ /^($_weather_types_pat)([BE\d]+)$/i)) { my $engl = ""; my $times = $2; @@ -732,7 +1033,7 @@ ## remarks for significant cloud types ## - elsif ($in_remarks && ($tok eq "CB" || $tok eq "TCU")) + elsif (($parsestate >= $expect_recentweather) and ($tok eq "CB" || $tok eq "TCU")) { push(@{$self->{sigclouds}}, $tok); @@ -741,13 +1042,14 @@ } elsif ( $tok eq "TCU" ) { push(@{$self->{SIGCLOUDS}}, "Towering Cumulus"); } + $parsestate = $expect_usremarks; } ## ## hourly temp/dewpoint ## - elsif ($tok =~ /^T(\d)(\d\d)(\d)(\d)(\d\d)(\d)$/i) + elsif (($parsestate == $expect_usremarks) and ($tok =~ /^T(\d)(\d\d)(\d)(\d)(\d\d)(\d)$/i)) { $self->{hourlytempdew} = $tok; if ( $1 == 1 ) { @@ -769,11 +1071,11 @@ ## unknown, not in remarks yet ## - elsif (!$in_remarks) + elsif ($parsestate < $expect_remarks) { push(@{$self->{unknown}},$tok); push(@{$self->{UNKNOWN}},$tok); - print "[$tok] is unknown.\n" if $self->{debug}; + print "[$tok] is unexpected at this state.\n" if $self->{debug}; next; } @@ -806,10 +1108,12 @@ ## Okay, wind finally gets interesting. ## - { + if ( defined $self->{wind} ) + { my $wind = $self->{wind}; my $dir_deg = substr($wind,0,3); my $dir_eng = ""; + my $dir_abb = ""; # Check for wind direction if ($dir_deg =~ /VRB/i) { @@ -817,51 +1121,90 @@ } else { if ($dir_deg < 15) { $dir_eng = "North"; + $dir_abb = "N"; } elsif ($dir_deg < 30) { $dir_eng = "North/Northeast"; + $dir_abb = "NNE"; } elsif ($dir_deg < 60) { $dir_eng = "Northeast"; + $dir_abb = "NE"; } elsif ($dir_deg < 75) { $dir_eng = "East/Northeast"; + $dir_abb = "ENE"; } elsif ($dir_deg < 105) { $dir_eng = "East"; + $dir_abb = "E"; } elsif ($dir_deg < 120) { $dir_eng = "East/Southeast"; + $dir_abb = "ESE"; } elsif ($dir_deg < 150) { $dir_eng = "Southeast"; + $dir_abb = "SE"; } elsif ($dir_deg < 165) { $dir_eng = "South/Southeast"; + $dir_abb = "SSE"; } elsif ($dir_deg < 195) { $dir_eng = "South"; + $dir_abb = "S"; } elsif ($dir_deg < 210) { $dir_eng = "South/Southwest"; + $dir_abb = "SSW"; } elsif ($dir_deg < 240) { $dir_eng = "Southwest"; + $dir_abb = "SW"; } elsif ($dir_deg < 265) { $dir_eng = "West/Southwest"; + $dir_abb = "WSW"; } elsif ($dir_deg < 285) { $dir_eng = "West"; + $dir_abb = "W"; } elsif ($dir_deg < 300) { $dir_eng = "West/Northwest"; + $dir_abb = "WNW"; } elsif ($dir_deg < 330) { $dir_eng = "Northwest"; + $dir_abb = "NW"; } elsif ($dir_deg < 345) { $dir_eng = "North/Northwest"; + $dir_abb = "NNW"; } else { $dir_eng = "North"; + $dir_abb = "N"; } } - $wind =~ /...(\d\d\d?)/o; - my $kts_speed = $1; - my $mph_speed = $kts_speed * 1.1508; - my $kts_gust = ""; - my $mph_gust = ""; - - if ($wind =~ /.{5,6}G(\d\d\d?)/o) { - $kts_gust = $1; - $mph_gust = $kts_gust * 1.1508; - } + my $kts_speed = undef; + my $mph_speed = undef; + + my $kts_gust = ""; + my $mph_gust = ""; + + # parse knots + + if ($self->{windtype} == $wt_knots){ + $wind =~ /...(\d\d\d?)/o; + $kts_speed = $1; + $mph_speed = $kts_speed * 1.1508; + + + if ($wind =~ /.{5,6}G(\d\d\d?)/o) { + $kts_gust = $1; + $mph_gust = $kts_gust * 1.1508; + } + # else: parse meters/second + } elsif ($self->{windtype} == $wt_mps){ + $wind=~ /...(\d\d\d?)/o; + my $mps_speed = $1; + $kts_speed = $mps_speed * 1.9438445; # units + $mph_speed = $mps_speed * 2.2369363; + if ($wind =~ /\d{5,6}G(\d\d\d?)/o) { + my $mps_gust = $1; + $kts_gust = $mps_gust * 1.9438445; + $mph_gust = $mps_gust * 2.2369363; + } + } else { + warn "Geo::METAR Parser error: unknown windtype\n"; + } $self->{WIND_KTS} = $kts_speed; $self->{WIND_MPH} = $mph_speed; @@ -871,61 +1214,20 @@ $self->{WIND_DIR_DEG} = $dir_deg; $self->{WIND_DIR_ENG} = $dir_eng; + $self->{WIND_DIR_ABB} = $dir_abb; } - ## - ## Variable wind information - ## + ## + ## wind variation + ## + if (defined $self->{windvar}) { - if ($self->{vrbwind}) { - my $vrbwind = $self->{vrbwind}; - my $vrbwind_deg_1 = substr($vrbwind,0,3); - my $vrbwind_deg_2 = substr($vrbwind,4,3); - my $vrbwind_eng_1 = ""; - my $vrbwind_eng_2 = ""; - - if ($vrbwind_deg_1 < 15) { $vrbwind_eng_1 = "North"; } - elsif ($vrbwind_deg_1 < 30) { $vrbwind_eng_1 = "North/Northeast"; } - elsif ($vrbwind_deg_1 < 60) { $vrbwind_eng_1 = "Northeast"; } - elsif ($vrbwind_deg_1 < 75) { $vrbwind_eng_1 = "East/Northeast"; } - elsif ($vrbwind_deg_1 < 105) { $vrbwind_eng_1 = "East"; } - elsif ($vrbwind_deg_1 < 120) { $vrbwind_eng_1 = "East/Southeast"; } - elsif ($vrbwind_deg_1 < 150) { $vrbwind_eng_1 = "Southeast"; } - elsif ($vrbwind_deg_1 < 165) { $vrbwind_eng_1 = "South/Southeast"; } - elsif ($vrbwind_deg_1 < 195) { $vrbwind_eng_1 = "South"; } - elsif ($vrbwind_deg_1 < 210) { $vrbwind_eng_1 = "South/Southwest"; } - elsif ($vrbwind_deg_1 < 240) { $vrbwind_eng_1 = "Southwest"; } - elsif ($vrbwind_deg_1 < 265) { $vrbwind_eng_1 = "West/Southwest"; } - elsif ($vrbwind_deg_1 < 285) { $vrbwind_eng_1 = "West"; } - elsif ($vrbwind_deg_1 < 300) { $vrbwind_eng_1 = "West/Northwest"; } - elsif ($vrbwind_deg_1 < 330) { $vrbwind_eng_1 = "Northwest"; } - elsif ($vrbwind_deg_1 < 345) { $vrbwind_eng_1 = "North/Northwest"; } - else { $vrbwind_eng_1 = "North"; } - - if ($vrbwind_deg_2 < 15) { $vrbwind_eng_2 = "North"; } - elsif ($vrbwind_deg_2 < 30) { $vrbwind_eng_2 = "North/Northeast"; } - elsif ($vrbwind_deg_2 < 60) { $vrbwind_eng_2 = "Northeast"; } - elsif ($vrbwind_deg_2 < 75) { $vrbwind_eng_2 = "East/Northeast"; } - elsif ($vrbwind_deg_2 < 105) { $vrbwind_eng_2 = "East"; } - elsif ($vrbwind_deg_2 < 120) { $vrbwind_eng_2 = "East/Southeast"; } - elsif ($vrbwind_deg_2 < 150) { $vrbwind_eng_2 = "Southeast"; } - elsif ($vrbwind_deg_2 < 165) { $vrbwind_eng_2 = "South/Southeast"; } - elsif ($vrbwind_deg_2 < 195) { $vrbwind_eng_2 = "South"; } - elsif ($vrbwind_deg_2 < 210) { $vrbwind_eng_2 = "South/Southwest"; } - elsif ($vrbwind_deg_2 < 240) { $vrbwind_eng_2 = "Southwest"; } - elsif ($vrbwind_deg_2 < 265) { $vrbwind_eng_2 = "West/Southwest"; } - elsif ($vrbwind_deg_2 < 285) { $vrbwind_eng_2 = "West"; } - elsif ($vrbwind_deg_2 < 300) { $vrbwind_eng_2 = "West/Northwest"; } - elsif ($vrbwind_deg_2 < 330) { $vrbwind_eng_2 = "Northwest"; } - elsif ($vrbwind_deg_2 < 345) { $vrbwind_eng_2 = "North/Northwest"; } - else { $vrbwind_eng_2 = "North"; } - - push @{$self->{WIND_VAR_DEG}}, $vrbwind_deg_1; - push @{$self->{WIND_VAR_DEG}}, $vrbwind_deg_2; - push @{$self->{WIND_VAR_ENG}}, $vrbwind_eng_1; - push @{$self->{WIND_VAR_ENG}}, $vrbwind_eng_2; + if ($self->{windvar} =~ /^(\d\d\d)V(\d\d\d)$/){ + $self->{WIND_VAR} = "Varying between $1 and $2"; + $self->{WIND_VAR_1} = $1; + $self->{WIND_VAR_2} = $2; } } @@ -934,37 +1236,23 @@ ## { - if ($self->{visibility}) { - my $vis = $self->{visibility}; - $vis =~ s/SM$//oi; # nuke the "SM" - if ($vis =~ /^CAVOK$/i) { - $self->{VISIBILITY} = "Ceiling and visibility OK"; - } - elsif ($vis =~ /M(\d\/\d)/o) { - $self->{VISIBILITY} = "Less than $1 statute miles"; - } else { - $self->{VISIBILITY} = $vis . " Statute Miles"; - } # end if + my $vis = $self->{visibility}; + # test for statute miles + if ($vis =~ /SM$/){ + $vis =~ s/SM$//oi; # nuke the "SM" + if ($vis =~ /M(\d\/\d)/o) { + $self->{VISIBILITY} = "Less than $1 statute miles"; + } else { + $self->{VISIBILITY} = $vis . " Statute Miles"; + } # end if + # auto metars can have non-directional visibility reports + } elsif (($self->{MOD} eq 'AUTO') and ($vis =~ /(\d+)NDV$/)){ + $self->{VISIBILITY} = "$1 meters non-directional visibility"; + } else { + $self->{VISIBILITY} = $vis . " meters"; } } - ## - ## Convert ALT to ALT_HP or vice versa - ## - - { - if ($self->{ALT} && !$self->{ALT_HP}) { - my $alt = $self->{ALT}; - $alt = $alt * 1.33; # mmHg to hPa - $self->{ALT_HP} = $alt; - } - elsif (!$self->{ALT} && $self->{ALT_HP}) { - my $alt = $self->{ALT_HP}; - $alt = $alt * 0.75; # hPa to mmHg - $self->{ALT} = $alt; - } - } - ## ## Calculate F temps for all C temps ## @@ -975,11 +1263,16 @@ { my $fkey = $1 . "_F"; - next unless defined $self->{$key}; + next unless defined $self->{$key} && $self->{$key}; $self->{$fkey} = sprintf("%.1f", (($self->{$key} * (9/5)) + 32)); } } + + # join the runway group + + $self->{runway} = join(', ' , @{$self->{RUNWAY}}); + } ## @@ -1022,21 +1315,19 @@ { my $self = shift; - print "METAR dump follows.\n\n"; + print "Modified METAR dump follows.\n\n"; print "type: $self->{type}\n"; print "site: $self->{site}\n"; print "date_time: $self->{date_time}\n"; print "modifier: $self->{modifier}\n"; print "wind: $self->{wind}\n"; - print "variable wind: $self->{vrbwind}\n"; print "visibility: $self->{visibility}\n"; print "runway: $self->{runway}\n"; print "weather: " . join(', ', @{$self->{weather}}) . "\n"; print "sky: " . join(', ', @{$self->{sky}}) . "\n"; print "temp_dew: $self->{temp_dew}\n"; - print "alt: $self->{alt}\n"; - print "alt_hp: $self->{alt_hp}\n"; + print "alt: $self->{ALT}\n"; print "slp: $self->{slp}\n"; print "remarks: " . join (', ', @{$self->{remarks}}) . "\n"; print "\n"; @@ -1080,7 +1371,9 @@ METAR reports are available on-line, thanks to the National Weather Service. Since reading the METAR format isn't easy for non-pilots, these reports are relatively useles to the common man who just wants a quick glace at the -weather. +weather. This module tries to parse the METAR reports so the data can be +used to create readable weather reports and/or process the data in +applications. =head1 USAGE @@ -1089,21 +1382,22 @@ Here is how you I use the Geo::METAR module. One use that I have had for this module is to query the NWS METAR page -(using the LWP modules) at: - -I - -to get an up-to-date METAR. Then, I scan thru the output, looking for what -looks like a METAR string (that's not hard in Perl). Oh, KFDY can be any site +(using the LWP modules) at +http://weather.noaa.gov/cgi-bin/mgetmetar.pl?cccc=EHSB to get an +up-to-date METAR. Then, I scan thru the output, looking for what looks +like a METAR string (that's not hard in Perl). Oh, EHSB can be any site location code where there is a reporting station. I then pass the METAR into this module and get the info I want. I can -then update my home page with the current temperature, sky conditions, or -whatnot. +then update my webcam page with the current temperature, sky conditions, or +whatnot. See for yourself at http://webcam.idefix.net/ + +See the BUGS section for a remark about multiple passes with the same +Geo::METAR object. =head2 Functions -The following functions are defined in the AcctInfo module. Most of +The following functions are defined in the METAR module. Most of them are I, meaning that you're supposed to use them. Some are I, meaning that you're not supposed to use them -- but I won't stop you. Assume that functions are I @@ -1175,7 +1469,7 @@ This section lists those variables and what they represent. If you call B, you'll find that it spits all of these -out in roughly this order, too. +out. =over @@ -1189,7 +1483,7 @@ =item TYPE -Report type: "METAR or SPECI". +Report type in English ("Routine Weather Report" or "Special Weather Report") =item SITE @@ -1197,7 +1491,7 @@ =item DATE -The date on which the report was issued. +The date (just the day of the month) on which the report was issued. =item TIME @@ -1209,19 +1503,15 @@ =item WIND_DIR_ENG -The current wind direction in English (Southwest, East, North, etc.) - -=item WIND_DIR_DEG - -The current wind direction in degrees. +The current wind direction in english (Southwest, East, North, etc.) -=item WIND_VAR_ENG +=item WIND_DIR_ABB -Variable wind direction in English. +The current wind direction in abbreviated english (S, E, N, etc.) -=item WIND_VAR_DEG +=item WIND_DIR_DEG -Variable wind direction in degrees. +The current wind direction in degrees. =item WIND_KTS @@ -1239,6 +1529,18 @@ The current wind gusting speed in Miles Per Hour. +=item WIND_VAR + +The wind variation in English + +=item WIND_VAR_1 + +The first wind variation direction + +=item WIND_VAR_2 + +The second wind variation direction + =item VISIBILITY Visibility information. @@ -1253,11 +1555,15 @@ =item WEATHER -Current weather. +Current weather (array) + +=item WEATHER_LOG + +Current weather log (array) =item SKY -Current sky conditions. +Current cloud cover (array) =item TEMP_C @@ -1265,23 +1571,35 @@ =item TEMP_F -Temperature in Farenheit. +Temperature in Fahrenheit. -=item C_DEW +=item DEW_C Dew point in Celsius. -=item F_DEW +=item DEW_F -Dew point in Farenheit. +Dew point in Fahrenheit. -=item ALT +=item HOURLY_TEMP_F -Altimeter setting (barometric pressure). +Hourly current temperature, fahrenheit -=item ALT_HP +=item HOURLY_TEMP_C -Altimeter setting in hectopascals. +Hourly current temperature, celcius + +=item HOURLY_DEW_F + +Hourly dewpoint, fahrenheit + +=item HOURLY_DEW_C + +Hourly dewpoint, celcius + +=item ALT + +Altimeter setting (barometric pressure). =item REMARKS @@ -1296,20 +1614,15 @@ Older versions of this module were installed as "METAR" instaed of "Geo::METAR" -=head2 Adding a find() method. - -I should add a function called find() which can be passed a big chunk -of text (or a ref to one) and a site identifier. It will scan through -the text and find the METAR. The result can be fed back into this -module for processing. - -That'd be cool, I think. - =head1 BUGS -There currently aren't any known BUGS (features which don't work as -advetised). There are lacking features. See the TODO section for more -on that. +The Geo::METAR is only initialized once, which means you'll get left-over +crud in variables when you call the metar() function twice. + +What is an invalid METAR in one country is a standard one in the next. +The standard is interpreted and used by meteorologists all over the world, +with local variations. This means there will always be METARs that will +trip the parser. =head1 TODO @@ -1318,47 +1631,59 @@ list before you submit a bug report or request a new feture. It might already be on the TODO list. -=head1 AUTHOR AND COPYRIGHT +=head1 AUTHORS AND COPYRIGHT -Copyright 1997-2000, Jeremy D. Zawodny +Copyright 1997-2000, Jeremy D. Zawodny + +Copyright 2007, Koos van den Hout Geo::METAR is covered under the GNU Public License (GPL) version 2 or later. The Geo::METAR Web site is located at: - http://www.wcnet.org/~jzawodn/perl/Geo-METAR/ + http://idefix.net/~koos/perl/Geo-METAR/ =head1 CREDITS -In addition to my work on Geo::METAR, I've received ideas, help, and +In addition to our work on Geo::METAR, We've received ideas, help, and patches from the following folks: - * Otterboy + * Ethan Dicks + + Testing of Geo::METAR at the South Pole. Corrections and pointers + to interesting cases to test. + + * Otterboy Random script fixes and initial debugging help - * Remi Lefebvre + * Remi Lefebvre Debian packaging as libgeo-metar-perl.deb. - * Mike Engelhart + * Mike Engelhart Wind direction naming corrections. - * Michael Starling + * Michael Starling Wind direction naming corrections. - * Hans Einar Nielssen + * Hans Einar Nielssen Wind direction naming corrections. - * Nathan Neulinger + * Nathan Neulinger Lots of enhancements and corrections. Too many to list here. -=cut +=head1 RELATED PROJECTS + +B at http://www.lcdproc.org/ uses Geo::METAR in lcdmetar.pl to +display weather data on an lcd. +=cut +# vim:expandtab:sw=4 ts=4 diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/README /tmp/cendO84dgE/libgeo-metar-perl-1.15/README --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/README 2000-11-25 00:10:50.000000000 +0000 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/README 2007-11-14 16:41:56.000000000 +0000 @@ -3,6 +3,7 @@ Accessing Aviation Weather Information with Perl. Copyright (c) 1997-2000, Jeremy D. Zawodny + Copyright (c) 2007, Koos van den Hout BACKGROUND @@ -11,7 +12,7 @@ The Geo::METAR home page is located at: - http://www.wcnet.org/jzawodn/perl/Geo-METAR/ + http://idefix.net/~koos/perl/Geo-METAR/ There may be bugs in the code as well as in the documentation. If you find either, I'd appreciate a patch or at least a mail message @@ -59,7 +60,7 @@ directory. They are provided as examples. They should provide an idea of what you can do with this module. - simple_dump.pl Process a simple METAR. + simple_dump.pl Process a simple METAR. fetch_temp.pl Fetch the temperature and print it out. If you develop a good example that would be useful to others, I'd diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/t/metar.t /tmp/cendO84dgE/libgeo-metar-perl-1.15/t/metar.t --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/t/metar.t 2008-06-13 16:48:41.000000000 +0100 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/t/metar.t 2007-11-13 21:19:27.000000000 +0000 @@ -1,23 +1,63 @@ #!/usr/bin/perl # -# $Id: metar.t,v 1.4 2000/11/24 23:43:08 jzawodn Exp $ +# $Id: metar.t,v 1.1 2007/11/13 21:19:27 koos Exp $ # # Test script for METAR installation. use strict; -use Test::More tests => 7; +use Test; -my $modname = "Geo::METAR"; -my $m; +BEGIN { plan tests => 6 } -use_ok($modname); -ok($m = $modname->new()); -ok(ref $m eq $modname); - -ok($m->metar("KFDY 251450Z 21012G21KT 8SM OVC065 04/M01 A3010 RMK 57014")); -ok($m->SITE eq "KFDY"); -ok($m->DATE eq "25"); -ok($m->TEMP_F eq "39.2"); +use Geo::METAR; + +my %tally = (passed => 0, failed => 0, skipped => 0); + +print "Testing METAR.\n"; + +my $m = new Geo::METAR; + +# Create a new instance. + +if (ref $m eq 'Geo::METAR') { + ok(1); +} else { + ok(0); +} + +## +## Try out one hard-coded example. We need many more of these. +## + +if ($m->metar("KFDY 251450Z 21012G21KT 8SM OVC065 04/M01 A3010 RMK 57014")) { + ok(1); +} else { + ok(0); +} + +if ($m->SITE eq "KFDY") { + ok(1); +} else { + ok(0); +} + +if ($m->DATE eq "25") { + ok(1); +} else { + ok(0); +} + +if ($m->MOD eq "AUTO") { + ok(1); +} else { + ok(0); +} + +if ($m->TEMP_F eq "39.2") { + ok(1); +} else { + ok(0); +} exit; diff -Nru /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/TODO /tmp/cendO84dgE/libgeo-metar-perl-1.15/TODO --- /tmp/aJaTOdUKVa/libgeo-metar-perl-1.14/TODO 2000-11-25 00:04:50.000000000 +0000 +++ /tmp/cendO84dgE/libgeo-metar-perl-1.15/TODO 2007-11-14 16:39:55.000000000 +0000 @@ -5,28 +5,6 @@ likely to be completed. - * Automatically find METAR data in an arbitrary data stream. - - Add a find() function to METAR that will look at a bunch of data - and try to find the METAR data. Ideally, it would need no help - from the user, but in thinking about it I think the user may have - to supply a hint of some sort (like site code). - - - * Move project to SourceForge. - - I've applied to do so, I just haven't received confirmation quite - yet. - - - * Apply remaining patches. - - A few patches remain in my INBOX. I've changed a lot in the - process of applying the larger changes, so I'm going to hold off - and apply some of the remaining changes manually after I'm sure - nothing major has broken. - - * Improved the test suite. It'd be nice to have a lot of METARs which encompass various @@ -36,18 +14,18 @@ * International METAR support. Sites around the world use similar (but slightly different) - formats for their METARs. I've had several requests to add support - for parsing them properly as well. + formats for their METARs. There is always a METAR format the parser + will fail on. * Calculate Heat Index and/or Wind Chill Both would be fairly easy to do, provided you get the formulas - correct. - + correct. (Those vary around the world!) + If you'd like to submit a patch for any of these, please let me know! Please put 'METAR' in the subject of your e-mail. -Jeremy@Zawodny.com +Koos van den Hout