[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: perl metar decoder -- parsing DIRmin/max wrong ?
- Subject: Re: perl metar decoder -- parsing DIRmin/max wrong ?
- Date: Fri, 16 Jan 2004 13:15:35 -0700 (MST)
David,
Thanks for catching these errors. I made the matches more strigent to
correct the problems. Included is a modified metar2nc with the fixes.
Robb...
On Fri, 16 Jan 2004, David Larson wrote:
> Robb,
>
> Could you check the parsing of a METAR for me?
>
> KPDX 160555Z 15003KT 1/4SM R10R/2800V5000FT BR OVC004 05/05 A3013
>
> What I see as a result of parsing is that part of the runway data
> (800V500) gets parsed out of the METAR into the DIRmin/DIRmax, and then
> subsequently the runway data isn't parsed out properly either (of course).
>
> I've made a few changes to the metar decoder from version 2.4.3 for
> tweaks here and there ... so I must admit this might again be a problem
> I've inflicted on myself.
>
> The following code seems to interfere with the runway processing code:
> # get min|max wind direction
> if( s#(\d{3})V(\d{3})\s*## ) {
> $DIRmin = $1 ;
> $DIRmax = $2 ;
> }
>
> What do you think about the following mod:
> if( s#(\d{3})V(\d{3})(\s+|$)## ) {
>
> The point of the above being just to ensure there is at least one
> trailing whitespace (or EOL).
>
> Thanks for the help,
> Dave
>
>
===============================================================================
Robb Kambic Unidata Program Center
Software Engineer III Univ. Corp for Atmospheric Research
address@hidden WWW: http://www.unidata.ucar.edu/
===============================================================================
#! /usr/local/bin/perl
#
# usage: metar2nc cdlfile [datatdir] [yymm] < ncfile
#
#
#chdir( "/home/rkambic/code/decoders/src/metar" ) ;
use NetCDF ;
use Time::Local ;
# process command line switches
while ($_ = $ARGV[0], /^-/) {
shift;
last if /^--$/;
/^(-v)/ && $verbose++;
}
# process input parameters
if( $#ARGV == 0 ) {
$cdlfile = $ARGV[ 0 ] ;
} elsif( $#ARGV == 1 ) {
$cdlfile = $ARGV[ 0 ] ;
if( $ARGV[ 1 ] =~ /^\d/ ) {
$yymm = $ARGV[ 1 ] ;
} else {
$datadir = $ARGV[ 1 ] ;
}
} elsif( $#ARGV == 2 ) {
$cdlfile = $ARGV[ 0 ] ;
$datadir = $ARGV[ 1 ] ;
$yymm = $ARGV[ 2 ] ;
} else {
die "usage: metar2nc cdlfile [datatdir] [yymm] < ncfile $!\n" ;
}
print "Missing cdlfile file $cdlfile: $!\n" unless -e $cdlfile ;
if( -e "util/ncgen" ) {
$ncgen = "util/ncgen" ;
} elsif( -e "/usr/local/ldm/util/ncgen" ) {
$ncgen = "/usr/local/ldm/util/ncgen" ;
} elsif( -e "/upc/netcdf/bin/ncgen" ) {
$ncgen = "/upc/netcdf/bin/ncgen" ;
} elsif( -e "./ncgen" ) {
$ncgen = "./ncgen" ;
} else {
open( NCGEN, "which ncgen |" ) ;
$ncgen = <NCGEN> ;
close( NCGEN ) ;
if( $ncgen =~ /no ncgen/ ) {
die "Can't find NetCDF utility 'ncgen' in PATH, util/ncgen
/usr/local/ldm/util/ncgen, /upc/netcdf/bin/ncgen, or ./ncgen : $!\n" ;
} else {
$ncgen = "ncgen" ;
}
}
# the data and the metadata directories
$datadir = "." if( ! $datadir ) ;
$metadir = $datadir . "/../metadata/surface/metar" ;
# redirect STDOUT and STDERR
open( STDOUT, ">$datadir/metarLog.$$.log" ) ||
die "could not open $datadir/metarLog.$$.log: $!\n" ;
open( STDERR, ">&STDOUT" ) ||
die "could not dup stdout: $!\n" ;
select( STDERR ) ; $| = 1 ;
select( STDOUT ) ; $| = 1 ;
die "Missing cdlfile file $cdlfile: $!\n" unless -e $cdlfile ;
# year and month
if( ! $yymm ) {
$theyear = (gmtime())[ 5 ] ;
$theyear = ( $theyear < 100 ? $theyear : $theyear - 100 ) ;
$theyear = sprintf( "%02d", $theyear ) ;
$themonth = (gmtime())[ 4 ] ;
$themonth++ ;
$yymm = $theyear . sprintf( "%02d", $themonth ) ;
} else {
$theyear = substr( $yymm, 0, 2 ) ;
$themonth = substr( $yymm, 2 ) ;
}
# file used for bad metars or prevention of overwrites to ncfiles
open( OPN, ">>$datadir/rawmetars.$$.nc" ) ||
die "could not open $datadir/rawmetars.$$.nc: $!\n" ;
# set error handling to verbose only
$result = NetCDF::opts( VERBOSE ) ;
# set interrupt handler
$SIG{ 'INT' } = 'atexit' ;
$SIG{ 'KILL' } = 'atexit' ;
$SIG{ 'TERM' } = 'atexit' ;
$SIG{ 'QUIT' } = 'atexit' ;
# set defaults
$F = -99999 ;
$A = \$F ;
$S1 = "\0" ;
$AS1 = \$S1 ;
$S2 = "\0\0" ;
$AS2 = \$S2 ;
$S3 = "\0\0\0" ;
$AS3 = \$S3 ;
$S4 = "\0\0\0\0" ;
$AS4 = \$S4 ;
$S8 = "\0" x 8 ;
$AS8 = \$S8 ;
$S10 = "\0" x 10 ;
$AS10 = \$S10 ;
$S15 = "\0" x 15 ;
$AS15 = \$S15 ;
$S32 = "\0" x 32 ;
$AS32 = \$S32 ;
$S128 = "\0" x 128 ;
$AS128 = \$S128 ;
%CDL = (
"rep_type", 0, "stn_name", 1, "wmo_id", 2, "lat", 3, "lon", 4, "elev", 5,
"ob_hour", 6, "ob_min", 7, "ob_day", 8, "time_obs", 9, "time_nominal", 10,
"AUTO", 11, "UNITS", 12, "DIR", 13, "SPD", 14, "GUST", 15, "VRB", 16,
"DIRmin", 17, "DIRmax", 18, "prevail_VIS_SM", 19, "prevail_VIS_KM", 20,
"plus_VIS_SM", 21, "plus_VIS_KM", 22, "prevail_VIS_M", 23, "VIS_dir", 24,
"CAVOK", 25, "RVRNO", 26, "RV_designator", 27, "RV_above_max", 28,
"RV_below_min", 29, "RV_vrbl", 30, "RV_min", 31, "RV_max", 32,
"RV_visRange", 33, "WX", 34, "vert_VIS", 35, "cloud_type", 36, "cloud_hgt", 37,
"cloud_meters", 38, "cloud_phenom", 39, "T", 40, "TD", 41,
"hectoPasc_ALTIM", 42, "inches_ALTIM", 43, "NOSIG", 44, "TornadicType", 45,
"TornadicLOC", 46, "TornadicDIR", 47, "BTornadic_hh", 48, "BTornadic_mm", 49,
"ETornadic_hh", 50, "ETornadic_mm", 51, "AUTOindicator", 52,
"PKWND_dir", 53, "PKWND_spd", 54, "PKWND_hh", 55, "PKWND_mm", 56,
"WshfTime_hh", 57, "WshfTime_mm", 58, "Wshft_FROPA", 59, "VIS_TWR", 60,
"VIS_SFC", 61, "VISmin", 62, "VISmax", 63, "VIS_2ndSite", 64,
"VIS_2ndSite_LOC", 65, "LTG_OCNL", 66, "LTG_FRQ", 67, "LTG_CNS", 68,
"LTG_CG", 69, "LTG_IC", 70, "LTG_CC", 71, "LTG_CA", 72, "LTG_DSNT", 73,
"LTG_AP", 74, "LTG_VcyStn", 75, "LTG_DIR", 76, "Recent_WX", 77,
"Recent_WX_Bhh", 78, "Recent_WX_Bmm", 79, "Recent_WX_Ehh", 80,
"Recent_WX_Emm", 81, "Ceiling_min", 82, "Ceiling_max", 83,
"CIG_2ndSite_meters", 84, "CIG_2ndSite_LOC", 85, "PRESFR", 86, "PRESRR", 87,
"SLPNO", 88, "SLP", 89, "SectorVIS_DIR", 90, "SectorVIS", 91, "GR", 92,
"GRsize", 93, "VIRGA", 94, "VIRGAdir", 95, "SfcObscuration", 96,
"OctsSkyObscured", 97, "CIGNO", 98, "Ceiling_est", 99, "Ceiling", 100,
"VrbSkyBelow", 101, "VrbSkyLayerHgt", 102, "VrbSkyAbove", 103,
"Sign_cloud", 104, "Sign_dist", 105, "Sign_dir", 106, "ObscurAloft", 107,
"ObscurAloftSkyCond", 108, "ObscurAloftHgt", 109, "ACFTMSHP", 110,
"NOSPECI", 111, "FIRST", 112, "LAST", 113, "Cloud_low", 114,
"Cloud_medium", 115, "Cloud_high", 116, "SNINCR", 117, "SNINCR_TotalDepth", 118,
"SN_depth", 119, "SN_waterequiv", 120, "SunSensorOut", 121, "SunShineDur", 122,
"PRECIP_hourly", 123, "PRECIP_amt", 124, "PRECIP_24_amt", 125, "T_tenths", 126,
"TD_tenths", 127, "Tmax", 128, "Tmin", 129, "Tmax24", 130, "Tmin24", 131,
"char_Ptend", 132, "Ptend", 133, "PWINO", 134, "FZRANO", 135, "TSNO", 136,
"PNO", 137, "maintIndicator", 138, "PlainText", 139, "report", 140,
"remarks", 141 ) ;
# default netCDF record structure, contains all vars for the METAR reports
@defaultrec = ( $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $AS3, $A, $A,
$A, $A, $A, $A, $A, $A, $A, $A, $A, $AS2, $A, $A, [( $S3, $S3, $S3, $S3 )],
[( $F, $F, $F, $F )], [( $F, $F, $F, $F )], [( $F, $F, $F, $F )],
[( $F, $F, $F, $F )], [( $F, $F, $F, $F )], [( $F, $F, $F, $F )], $AS32, $A,
[( $S4, $S4, $S4, $S4, $S4, $S4 )], [( $F, $F, $F, $F, $F, $F )],
[( $F, $F, $F, $F, $F, $F )], [( $S4, $S4, $S4, $S4, $S4, $S4 )],
$A, $A, $A, $A, $A, $AS15, $AS10, $AS2, $A, $A, $A, $A, $AS4, $A, $A,
$A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $AS10, $A, $A, $A, $A, $A,
$A, $A, $A, $A, $A, $AS2, [( $S8, $S8, $S8 )], [( $F, $F, $F )],
[( $F, $F, $F )], [( $F, $F, $F )], [( $F, $F, $F )], $A, $A, $A, $A,
$A, $A, $A, $A, $AS2, $A, $A, $A, $A, $AS2, $AS8, $A, $A, $A, $A,
$AS3, $A, $AS3, $AS10, $AS10, $AS10, $AS8, $AS3, $A, $A, $A, $A, $A,
$AS1, $AS1, $AS1, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A,
$A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $AS128, $AS128, $AS128 ) ;
# two fold purpose array, if entry > 0, then var is requested and it's value
# is the position in the record, except first entry
@W = ( 0 ) x ( $#defaultrec +1 ) ;
$W[ 0 ] = -1 ;
# open cdl and create record structure according to variables
open( CDL, "$cdlfile" ) || die "could not open $cdlfile: $!\n" ;
$i = 0 ;
while( <CDL> ) {
if( s#^\s*(char|int|long|double|float) (\w{1,25})## ) {
( $number ) = $CDL{ $2 } ;
push( @rec, $defaultrec[ $number ] ) ;
$W[ $number ] = $i++ ;
}
}
close CDL ;
undef( @defaultrec ) ;
undef( %CDL ) ;
# read in station data
if( -e "etc/sfmetar_sa.tbl" ) {
$sfile = "etc/sfmetar_sa.tbl" ;
} elsif( -e "./sfmetar_sa.tbl" ) {
$sfile = "./sfmetar_sa.tbl" ;
} else {
die "Can't find sfmetar_sa.tbl station file.: $!\n" ;
}
open( STATION, "$sfile" ) || die "could not open $sfile: $!\n" ;
while( <STATION> ) {
s#^(\w{3,6})?\s+(\d{4,5}).{40}## ;
$id = $1 ;
$wmo_id = $2 ;
$wmo_id = "0" . $wmo_id if( length( $wmo_id ) == 4 ) ;
( $lat, $lon, $elev ) = split ;
$lat = sprintf( "%7.2f", $lat / 100 ) ;
$lon = sprintf( "%7.2f", $lon / 100) ;
# set these vars ( $wmo_id, $lat, $lon, $elev )
$STATIONS{ "$id" } = "$wmo_id $lat $lon $elev" ;
}
close STATION ;
# read in list of already processed reports if it exists
# open metar.lst, list of reports processed in the last 4 hours.
if( -e "$datadir/metar.lst" ) {
open( LST, "$datadir/metar.lst" ) ||
die "could not open $datadir/metar.lst: $!\n" ;
while( <LST> ) {
( $stn, $rtptime, $hr ) = split ;
$reportslist{ "$stn $rtptime" } = $hr ;
}
close LST ;
#unlink( "$datadir/metar.lst" ) ;
}
# Now begin parsing file and decoding observations breaking on cntrl C
$/ = "\cC" ;
# set select processing here from STDIN
START:
while( 1 ) {
open( STDIN, '-' ) ;
vec($rin,fileno(STDIN),1) = 1;
$timeout = 1200 ; # 20 minutes
$nfound = select( $rout = $rin, undef, undef, $timeout );
# timed out
if( ! $nfound ) {
print "Shut down, time out 20 minutes\n" ;
&atexit() ;
}
&atexit( "eof" ) if( eof( STDIN ) ) ;
# Process each line of metar bulletins, header first
$_ = <STDIN> ;
#next unless /METAR|SPECI/ ;
s#\cC## ;
s#\cM##g ;
s#\cA\n## ;
s#\c^##g ;
s#\d\d\d \n## ;
s#\w{4}\d{1,2} \w{4} (\d{2})(\d{2})(\d{2})?.*\n## ;
$tday = $1 ;
$thour = $2 ;
$thour = "23" if( $thour eq "24" ) ;
$tmin = $3 ;
$tmin = "00" unless( $tmin ) ;
next unless ( $tday && defined( $thour ) ) ;
$time_trans = thetime( "trans" ) ;
if( s#(METAR|SPECI) \d{4,6}Z?\n## ) {
$rep_type = $1 ;
} elsif( s#(METAR|SPECI)\s*\n## ) {
$rep_type = $1 ;
} else {
$rep_type = "METAR" ;
}
# Separate bulletins into reports
if( /=\n/ ) {
s#=\s+\n#=\n#g ;
@reports = split( /=\n/ ) ;
} else {
@reports = split ( /\n/ ) ;
}
for ( @reports ) { # Process each report in the bulletin
undef( $report ) ;
undef( $remarks ) ;
undef( $stn_name ) ;
undef( $ob_day ) ;
next if( /^\n/ ) ;
s#^(METAR|M E T A R|SPECI|TESTM|TESTS)\s*\n?## ;
if( /\n\w{4} \d{4,6}Z/ ) { # reports appended together wrongly
( $_, $tmp ) = split( "\n", $_ ) ;
print OPN "$tday$thour$tmin\n$tmp\n" ;
}
s#\n# #g ;
# save original report and remarks
if( s#(.*)( RMK| REMARKS)(.*)?#$1# ) {
$report = $1 ;
$remarks = $3 unless( ! $3 || $3 =~ /NIL/ ) ;
} else {
$report = $_ ;
}
$_ = "$_ " ;
$rep_type = $1 if( s#^(METAR|SPECI|TESTM|TESTS)\s+## ) ;
$stn_name = $1 if( s#^(\w{4})\s+## ) ;
next unless( $stn_name ) ;
#if( $stn_name =~ /CWDJ|GBYD/ ) {
#print $stn_name ;
#}
# get date hour minute
next unless( s#^(\d{4,6})Z\s+## );
if( length( $1 ) == 4 ) {
$rpt_time = $1 ;
if( $rpt_time =~ /^$tday/ ) {
$ob_min = "00" ;
$ob_hour = substr( $rpt_time, 2, 2 ) ;
$ob_day = substr( $rpt_time, 0, 2 ) ;
$rpt_time = $ob_hour . $ob_min ;
} else {
$ob_min = substr( $rpt_time, 2, 2 ) ;
$ob_hour = substr( $rpt_time, 0, 2 ) ;
$ob_day = $tday ;
}
} elsif( length( $1 ) == 5 ) {
$rpt_time = substr( $1, 1 ) ;
$ob_day = sprintf( "%02d", substr( $1, 0, 1 ) ) ;
$ob_hour = substr( $1, 1, 2 ) ;
$ob_min = substr( $1, 3, 2 ) ;
} else {
$rpt_time = substr( $1, 2 ) ;
$ob_day = substr( $1, 0, 2 ) ;
$ob_hour = substr( $1, 2, 2 ) ;
$ob_min = substr( $1, 4, 2 ) ;
}
if( $ob_min > 59 || $ob_hour > 23 || $ob_day > 31 ) {
print OPN "$tday$thour$tmin\n$report\n$remarks\n" ;
next ;
}
# Skip duplicate reports based on stn and time
if( defined( $reportslist{ "$stn_name $rpt_time" } ) ) {
next ;
} else {
# ob hr = 23 and ob min > 45
if( $ob_hour == 23 && $ob_min > 45 ) {
$ob_day = $tday ;
$yymmdd = $yymm . $tday ;
$ob_hour = $ob_min = "00" ;
# push report to next hour
} elsif( $ob_min > 45 ) {
$ob_min = "00" ;
$ob_hour = sprintf( "%02d", ++$ob_hour ) ;
$yymmdd = $yymm . $ob_day ;
# ob day != bulletin day
} elsif( $ob_day != $tday ) {
$yymmdd = thetime( "yesterday" ) ;
#$ob_day = substr( $yymmdd, 4 ) ;
# ob hr > bulletin hr
} elsif( $ob_hour > ( $thour +1 )) {
$yymmdd = thetime( "yesterday" ) ;
$ob_day = substr( $yymmdd, 4 ) ;
} else {
$yymmdd = $yymm . sprintf( "%02d", $ob_day ) ;
}
$hour = $ob_hour ;
$reportslist{ "$stn_name $rpt_time" } = "$hour" ;
$time_obs = thetime( "obs" ) ;
if( abs( $time_trans - $time_obs) > 10800 ) {
print OPN
"$tday$thour$tmin\n$report\n$remarks\n";
next ;
}
$time_nominal = thetime( "nominal" ) ;
}
# skip NIL reports
next if( s#NIL\s*## ) ;
# extract wmo_id, lat, lon, elev
if( $STATIONS{ "$stn_name" } ) {
( $wmo_id, $lat, $lon, $elev ) =
split( " ", $STATIONS{ "$stn_name" } ) ;
} elsif( $stn_name =~ /^K|^C/ ) { # US & Canadian stations
$tmp = substr( $stn_name, 1 ) ;
( $wmo_id, $lat, $lon, $elev ) =
split( " ", $STATIONS{ "$tmp" } )
if( $STATIONS{ "$tmp" } ) ;
}
$AUTO = 1 if( s#AUTO\s+## ) ;
# get wind direction and speed
if(
s#(E|W|N|S)?(\d{3}|VRB)(\d{2,3})(G)?(\d{2,3})?(KMH|KT|MPS|MPH)\s+## ) {
if( $2 eq "VRB" ) {
$VRB = 1 ;
} else {
$DIR = $2 ;
}
$SPD = $3 ;
$GUST = $5 if( $4 eq "G" ) ;
$UNITS = $6 ;
$UNITS = padstr( $UNITS, 3 ) ;
}
# get min|max wind direction
if( s#^(\d{3})V(\d{3})\s+## ) {
$DIRmin = $1 ;
$DIRmax = $2 ;
}
# some reports use a place holder for visibility
s#9999\s+## ;
# get visibility
$prevail_VIS_SM = 0.0 if( s#^M1/4SM\s+|<1/4SM\s+## ) ;
$prevail_VIS_KM = 0.0 if( s#^M1/4KM\s+|<1/4KM\s+## ) ;
$plus_VIS_SM = 1 if( s#^P(\d{1,3})SM\s+#$1SM # ) ;
$plus_VIS_KM = 1 if( s#^P(\d{1,3})KM\s+#$1KM # ) ;
if( s#^(\d{1,4}) (\d{1,3})/(\d{1,3})(SM|KM)\s+## ) {
$prevail_VIS_SM = $1 + ( $2 / $3 ) if( $4 eq "SM" ) ;
$prevail_VIS_KM = $1 + ( $2 / $3 ) if( $4 eq "KM" ) ;
} elsif( s#^(\d{1,3})/(\d{1,3})(KM|SM)\s+## ) {
$prevail_VIS_SM = $1 / $2 if( $3 eq "SM" ) ;
$prevail_VIS_KM = $1 / $2 if( $3 eq "KM" ) ;
} elsif( s#^(\d{1,4})(KM|SM)\s+## ) {
$prevail_VIS_SM = $1 if( $2 eq "SM" ) ;
$prevail_VIS_KM = $1 if( $2 eq "KM" ) ;
} elsif( s#^(\d{4})((NE)|(NW)|(SE)|(SW)|(N)|(S)|(E)|(W))\s+## ){
$prevail_VIS_M = $1 ;
$VIS_dir = $2 ;
$VIS_dir = padstr( $VIS_dir, 2 ) ;
}
# clear
$CAVOK = 1 if( s#CAVOK\s+## ) ;
# runway decoding here
$RVRNO = 1 if( s#RVRNO\s+## ) ;
for( $i = 0; $i < 4; $i++ ) {
if(
s#R(\d{2})(R|L|C)?/(M|P)?(\d{4})V?(M|P)?(\d{4})?(FT|N|D)?\s+## ){
if( $i == 0 ) {
@RV_designator = ( $S3, $S3, $S3, $S3 );
@RV_above_max = ( $F, $F, $F, $F ) ;
@RV_below_min = ( $F, $F, $F, $F ) ;
@RV_vrbl = ( $F, $F, $F, $F ) ;
@RV_min = ( $F, $F, $F, $F ) ;
@RV_max = ( $F, $F, $F, $F ) ;
@RV_visRange = ( $F, $F, $F, $F ) ;
}
$RV_designator[ $i ] = "$1$2" ;
$RV_designator[ $i ] =
padstr( $RV_designator[ $i ], 3 ) ;
$RV_above_max[ $i ] = 1
if( $3 eq "P" || $5 eq "P" ) ;
$RV_below_min[ $i ] = 1
if( $3 eq "M" || $5 eq "M" ) ;
$RV_vrbl[ $i ] = 1 if( $6 ne "" ) ;
if( $RV_vrbl[ $i ] ) {
$RV_min[ $i ] = $4 * 1;
$RV_max[ $i ] = $6 * 1;
} else {
$RV_visRange[ $i ] = $4 * 1;
}
$i++ ;
} else {
last ;
}
}
# Get weather conditions
for( $i = 0; $i < 4; $i++ ) {
# code table 4678
if(
s#^(\+|-|VC|PR)?(MI|BC|DR|BL|SH|TS|FZ)?(DZ|RA|SN|SG|IC|PE|PL|GR|GS|UP)?(BR|FG|FU|VA|DU|SA|HZ|PY)?(PO|SQ|FC|SS|DS)?\s+##
) {
last unless "$1$2$3$4$5" ;
$WX .= "$1$2$3$4$5 " ;
} else {
last ;
}
}
$WX = padstr( $WX, 32 )
if( defined( $WX ) ) ;
# Interpret cloud conditions
#$cloud_type[ 0 ] = $1 if( s#(CLR|SKC)\s+## ) ;
@cloud_type = ( "$1\0", $S4, $S4, $S4, $S4, $S4 )
if( s#^(CLR|SKC)\s+## ) ;
$vert_VIS = cloud_hgt2_meters( $1 ) if( s#^VV(\d{3})\s+## ) ;
for( $i = 0; $i < 6; $i++ ) {
# layers up to 6
if( s#^(\+|-)?(OVC|SCT|FEW|BKN)(\d{3})(\w{1,3})?\s+## ){
if( $i == 0 ) {
@cloud_type =
( $S4,$S4,$S4,$S4,$S4,$S4 ) ;
@cloud_hgt = ( $F,$F,$F,$F,$F,$F ) ;
@cloud_meters = ( $F,$F,$F,$F,$F,$F ) ;
@cloud_phenom =
( $S4,$S4,$S4,$S4,$S4,$S4 ) ;
}
$cloud_type[ $i ] = padstr( "$1$2", 4 ) ;
$cloud_hgt[ $i ] = $3 * 100 ;
$cloud_meters[ $i ] = cloud_hgt2_meters( $3 ) ;
$cloud_phenom[ $i ] = padstr( $4, 4 ) if( $4 ) ;
} else {
last ;
}
}
# get temperature and dew point
if( s#^(M)?(\d{2})/(M)?(\d{2})?\s+## ) {
$T = $2 ;
$T *= -1 if( $1 ) ;
$TD = $4 if( $4 ) ;
$TD *= -1 if( $3 ) ;
}
# get Altimeter settings
if( s#^(A|Q)(\d{4}\.?\d?)\s+## ) {
if( $1 eq "A" ) {
$inches_ALTIM = $2 * 0.01 ;
} else {
$hectoPasc_ALTIM = $2 ;
}
}
$NOSIG = 1 if( s#NOSIG## ) ;
# get remarks
if( defined( $remarks ) ) {
doRemarks( "$remarks " ) ;
} else {
$T_tenths = $T if( defined( $T ) ) ;
$TD_tenths = $TD if( defined( $TD ) ) ;
}
# debug output
printvars() if( $verbose ) ;
# we have a legal report, open a Netcdf file
$result = doNet( $hour ) ;
if( $result ) { # OK to write data
# set variable into dataref
setvars() ;
# enter report data into proper record location
$result = NetCDF::recput( $ncid, $recnum, [ @dataref ]);
if( $result ) {
print "NetCDF::recput result = $result\n" ;
chop $report
while( index( $report, "\0" ) != -1 ) ;
chop $remarks
while( index( $remarks, "\0" ) != -1 ) ;
print "$ncfile\n$report\n$remarks\n" ;
} else {
$recnum++ ;
}
}
# undefine vars
undefinevars() ;
# &atexit( "eof" ) if( eof( STDIN ) ) ;
} # end foreach report
} # end while( 1 )
&atexit( "eof" );
exit( 0 ) ; #should never get here
# Interpet Remarks
sub doRemarks {
( $_ ) = @_ ;
# get Tornado data if present
if( s#(TORNADO\w{0,2}|WATERSPOUTS*|FUNNEL CLOUDS*)\s+## ) {
$TornadicType = padstr( $1, 15 ) ;
if( s#(B|E)(\d\d)(\d\d)?\s+## ) {
if( $1 eq "B" ) {
$BTornadic_hh = $2 ;
$BTornadic_mm = $3 if( defined( $3 ) ) ;
} else {
$ETornadic_hh = $2 ;
$ETornadic_mm = $3 if( defined( $3 ) ) ;
}
}
$TornadicLOC = padstr( $1, 10 )
if( s#^(DSNT|VCY STN|VC STN|VCY|VC)\s+## ) ;
$TornadicDIR = padstr( $1, 2 )
if( s#^(NE|NW|SE|SW|N|S|E|W)\s+## ) ;
}
# get Automated reports
$AUTOindicator = padstr( $1, 4 )
if( s#(A01|A01A|A02|A02A|AO1|AO1A|AO2|AO2A|AOA)\s+## ) ;
# get Peak winds
if( s#PK WND (\d{3})(\d{1,3})/(\d\d)?(\d\d)\s+## ) {
$PKWND_dir = $1 ;
$PKWND_spd = $2 ;
$PKWND_hh = $3 if( defined( $3 ) ) ;
$PKWND_mm = $4 ;
}
# get Wind shift
if( s#WSHFT (\d\d)?(\d\d)\s+## ) {
$WshfTime_hh = $1 if( defined( $1 ) );
$WshfTime_mm = $2 ;
}
# get FROPO ( wind shift because of frontal passage )
$Wshft_FROPA = 1 if( s#FROPA\s+## ) ;
# Tower visibility
if( s#TWR (VIS|VSBY) (\d{1,3}) (\d{1,2})/(\d{1,2})\s+## ) {
$VIS_TWR = $2 + ( $3 / $4 ) ;
} elsif( s#TWR (VIS|VSBY) (\d{1,2})/(\d{1,2})\s+## ) {
$VIS_TWR = ( $2 / $3 ) ;
} elsif( s#TWR (VIS|VSBY) (\d{1,3})\s+## ) {
$VIS_TWR = $2 ;
}
# Surface visibility
if( s#SFC (VIS|VSBY) (\d{1,3}) (\d{1,2})/(\d{1,2})\s+## ) {
$VIS_SFC = $2 + ( $3 / $4 ) ;
} elsif( s#SFC (VIS|VSBY) (\d{1,2})/(\d{1,2})\s+## ) {
$VIS_SFC = ( $2 / $3 ) ;
} elsif( s#SFC (VIS|VSBY) (\d{1,3})\s+## ) {
$VIS_SFC = $2 ;
}
# Variable visibility
if( s#(VIS|VSBY) (\d{1,3}) (\d{1,2})/(\d{1,2})V(\d{1,3})
(\d{1,2})/(\d{1,2})\s+## ) {
$VISmin = $2 + ( $3 / $4 ) ;
$VISmax = $5 + ( $6 / $7 ) ;
} elsif( s#(VIS|VSBY) (\d{1,3})V(\d{1,3}) (\d{1,2})/(\d{1,2})\s+## ) {
$VISmin = $2 ;
$VISmax = $3 + ( $4 / $5 ) ;
} elsif( s#(VIS|VSBY) (\d{1,2})/(\d{1,2})V(\d{1,3}) (\d{1,2})/(\d{1,2})\s+## ) {
$VISmin = ( $2 / $3 ) ;
$VISmax = $4 + ( $5 / $6 ) ;
} elsif( s#(VIS|VSBY) (\d{1,3}) (\d{1,2})/(\d{1,2})V(\d{1,3})\s+## ) {
$VISmin = $2 + ( $3 / $4 ) ;
$VISmax = $5 ;
} elsif( s#(VIS|VSBY) (\d{1,3})V(\d{1,3})\s+## ) {
$VISmin = $2 ;
$VISmax = $3 ;
} elsif( s#(VIS|VSBY) (\d{1,2})/(\d{1,2})V(\d{1,3})\s+## ) {
$VISmin = ( $2 / $3 ) ;
$VISmax = $4 ;
}
# Second site visiblity
if( s#(VIS|VSBY) (\d{1,3}) (\d{1,2})/(\d{1,2}) (RY\d{1,2})\s+## ) {
$VIS_2ndSite = $2 + ( $3 / $4 ) ;
$VIS_2ndSite_LOC = padstr( $5, 10 ) ;
} elsif( s#(VIS|VSBY) (\d{1,3}) (RY\d{1,2})\s+## ) {
$VIS_2ndSite = $2 ;
$VIS_2ndSite_LOC = padstr( $3, 10 ) ;
} elsif( s#(VIS|VSBY) (\d{1,2})/(\d{1,2}) (RY\d{1,2})\s+## ) {
$VIS_2ndSite = ( $2 / $3 ) ;
$VIS_2ndSite_LOC = padstr( $4, 10 ) ;
}
# Lightning data ( Occasional,Frequent,Continuous) and
# (Cloud-Ground,In-Cloud,Cloud-Cloud,Cloud-Air)
if( s#(OCNL|FRQ|CNS) LTG\s?(CG|IC|CC|CA)\s?(DSNT|AP|VCY STN|VCNTY
STN)?\s?(NE|NW|SE|SW|N|S|E|W)?\s+## ) {
$LTG_OCNL = 1 if( $1 eq "OCNL" ) ;
$LTG_FRQ = 1 if( $1 eq "FRQ" ) ;
$LTG_CNS = 1 if( $1 eq "CNS" ) ;
$LTG_CG = 1 if( $2 eq "CG" ) ;
$LTG_IC = 1 if( $2 eq "IC" ) ;
$LTG_CC = 1 if( $2 eq "CC" ) ;
$LTG_CA = 1 if( $2 eq "CA" ) ;
$LTG_DSNT = 1 if( $3 eq "DSNT" ) ;
$LTG_AP = 1 if( $3 eq "AP" ) ;
$LTG_VcyStn = 1 if( $3 eq "VCY STN" || $3 eq "VCNTY STN" ) ;
$LTG_DIR = padstr( $4, 2 ) if( defined( $4 ) ) ;
}
# get min/max for Variable Ceiling
if( s#CIG (\d{1,4})V(\d{1,4})\s+## ) {
$Ceiling_min = $1 ;
$Ceiling_max = $2 ;
}
# ? about SKY condition at 2nd location
# get 2nd site ceiling and location
if( s#CIG (\d{3}) (RY\d{1,2})\s+## ) {
$CIG_2ndSite_meters = $1 * 10 ;
$CIG_2ndSite_LOC = $2 ;
}
# Presure falling rapidly
$PRESFR = 1 if( s#PRESFR/?\s+## ) ;
# Presure rising rapidly
$PRESRR = 1 if( s#PRESRR/?\s+## ) ;
# Sea-Level presure
$SLPNO = 1 if( s#SLPNO\s+## ) ;
if( s#SLP\s?(\d{3})\s+## ) {
if( $1 >= 550 ) {
$SLP = $1 / 10. + 900. ;
} else {
$SLP = $1 / 10. + 1000. ;
}
}
# Sector visibility
if( s#(VIS|VSBY) (NE|NW|SE|SW|N|S|E|W)(\d{1,3}) (\d{1,2})/(\d{1,2})\s+## ) {
$SectorVIS_DIR = padstr( $2, 2 ) ;
$SectorVIS = $3 + ( $4 / $5 ) ;
} elsif( s#(VIS|VSBY) (NE|NW|SE|SW|N|S|E|W) (\d{1,2})/(\d{1,2})\s+## ) {
$SectorVIS_DIR = padstr( $2, 2 ) ;
$SectorVIS = ( $3 / $4 ) ;
} elsif( s#(VIS|VSBY) (NE|NW|SE|SW|N|S|E|W)(\d{1,3})\s+## ) {
$SectorVIS_DIR = padstr( $2, 2 ) ;
$SectorVIS = $3 ;
}
# Hailstone activity and size
$GR = 1 if( s#GS\s+## ) ;
if( s#GR M1/4\s+## ) {
$GR = 1 ;
$GRsize = 1 / 8 ;
} elsif( s#GR (\d{1,3}) (\d{1,2})/(\d{1,2})\s+## ) {
$GR = 1 ;
$GRsize = $1 + ( $2 / $3 ) ;
} elsif( s#GR (\d{1,2})/(\d{1,2})\s+## ) {
$GR = 1 ;
$GRsize = ( $1 / $2 ) ;
} elsif( s#GR (\d{1,3})\s+## ) {
$GR = 1 ;
$GRsize = $1 ;
}
# VIRGA activity
if( s#VIRGA (DSNT )?(NE|NW|SE|SW|N|S|E|W)?\s+## ) {
$VIRGA = 1 ;
$VIRGAdir = padstr( $2, 2 ) if( $2 ) ;
}
# Surface-based Obscuring Phenomena SfcObscuration weather conditions
# code table 4678
if(
s#-X(VC|PR)?(MI|BC|DR|BL|SH|TS|FZ)?(DZ|RA|SN|SG|IC|PE|PL|GR|GS|UP)?(BR|FG|FU|VA|DU|SA|HZ|PY)?(PO|SQ|FC|SS|DS)?(\d)\s+##
) {
$SfcObscuration = padstr( "$1$2$3$4$5", 8 ) ;
$OctsSkyObscured = $6 ;
}
# get Ceiling_est or Ceiling height
$CIGNO = 1 if( s#CIGNO\s+## ) ;
if( s#CIG(E)?(\d{3})\s+## ) {
if( $1 eq "E" ) {
$Ceiling_est = $2 * 100 ;
} else {
$Ceiling = $2 * 100 ;
}
}
# Variable Sky conditions
if( s#(FEW|SCT|BKN|OVC)(\d{3})? V (FEW|SCT|BKN|OVC)\s+## ) {
$VrbSkyBelow = $1 ;
$VrbSkyLayerHgt = $2 * 100 if( defined( $2 ) ) ;
$VrbSkyAbove = $3 ;
}
# Significant Cloud Types
if( s#(CB|CBMAM|TCU|ACC|SCSL|ACSL|ROTOR CLD|ROPE|ROPE CLD)\s+## ) {
$Sign_cloud = padstr( $1, 10 ) ;
$Sign_dist = padstr( $1, 10 )
if( s#^(VCNTY STN|VCY STN|VC STN|VCY|VC|DSNT|OMT)\s+## ) ;
$Sign_dir = padstr( "$1$2$3", 10 )
if( s#^(NE|NW|SE|SW|N|S|E|W)(\-| MOV )?(NE|NW|SE|SW|N|S|E|W)?/?\s+## ) ;
}
# Obscuring Phenomena Aloft
if(
s#(VC|PR)?(MI|BC|DR|BL|SH|TS|FZ)?(DZ|RA|SN|SG|IC|PE|PL|GR|GS|UP)?(BR|FG|FU|VA|DU|SA|HZ|PY)?(PO|SQ|FC|SS|DS)?
(FEW|SCT|BKN|OVC)(\d{3})\s+## ) {
$ObscurAloft = padstr( "$1$2$3$4$5", 8 ) ;
$ObscurAloftSkyCond = $6 ;
$ObscurAloftHgt = $7 * 100 ;
}
# Air craft mishap ACFTMSHP
$ACFTMSHP = 1 if( s#\(?ACFT\s?MSHP\)?\s+## ) ;
# No changes in weather conditions until next report NOSPECI
$NOSPECI = 1 if( s#NOSPECI\s+## ) ;
# This is first report of the day FIRST
$FIRST = 1 if( s#FIRST\s+## ) ;
# This is last report in observation coverage LAST
$LAST = 1 if( s#LAST\s+## ) ;
# Cloud Types
if( s# 8/(\d|/)(\d|/)(\d|/)/?\s+# # ) {
$Cloud_low = $1 ;
$Cloud_medium = $2 ;
$Cloud_high = $3 ;
}
# Snow Increasing Rapidly SNINCR
if( s#SNINCR (\d{1,3})/(\d{1,3})\s+## ) {
$SNINCR = $1 ;
$SNINCR_TotalDepth = $2 ;
}
# Snow depth on ground
if( s# 4/(\d{1,3})\s+# # ) {
$SN_depth = $1 ;
}
# Water equivalent of snow on ground
$SN_waterequiv = $1 / 10 if( s# 933(\d{3})\s+# # ) ;
# Duration of sunshine
if( s# 98(\d{1,3}|///)\s+# # ) {
if( $1 eq "///" ) {
$SunSensorOut = 1 ;
} else {
$SunShineDur = $1 ;
}
}
# Hourly precipitation amount
$PRECIP_hourly = $1 / 100 if( s#P ?(\d{1,5})\s+## ) ;
# Precipitation amount
if( s# 6(\d{4}|////)\s+# # ) {
$PRECIP_amt = $1 / 100 if( $1 ne "////" ) ;
}
# 24 Hour Precipitation amount
if( s# 7(\d{4}|////)\s+# # ) {
$PRECIP_24_amt = $1 / 100 if( $1 ne "////" ) ;
}
# Temperature and Dew Point
if( s#T(0|1)(\d{3})(0|1)?(\d{3})?\s+## ) {
if( $1 == 0 ) {
$T_tenths = 0.1 * $2 ;
} else {
$T_tenths = -0.1 * $2 ;
}
if( defined( $3 ) && $3 == 0 ) {
$TD_tenths = 0.1 * $4 ;
} elsif( defined( $3 ) && $3 == 1 ) {
$TD_tenths = -0.1 * $4 ;
} else {
$TD_tenths = $TD if( defined( $TD ) ) ;
}
} else {
$T_tenths = $T if( defined( $T ) ) ;
$TD_tenths = $TD if( defined( $TD ) ) ;
}
# Maximum Temperature
if( s# 1(0|1|/)(\d{3}|///)\s+# # ) {
$Tmax = $2 / 10 if( $2 ne "///" ) ;
$Tmax *= -1.0 if( $1 == 1 ) ;
}
# Minimum Temperature
if( s# 2(0|1|/)(\d{3}|///)\s+# # ) {
$Tmin = $2 / 10 if( $2 ne "///" ) ;
$Tmin *= -1.0 if( $1 == 1 ) ;
}
# 24-Hour Maximum and Minimum Temperature
if( s# 4(0|1|/)(\d{3}|///)(0|1|/)(\d{3}|///)\s+# # ) {
$Tmax24 = $2 / 10 if( $2 ne "///" ) ;
$Tmax24 *= -1.0 if( $1 == 1 ) ;
$Tmin24 = $4 / 10 if( $4 ne "///" ) ;
$Tmin24 *= -1.0 if( $3 == 1 ) ;
}
# Presure Tendency
if( s# 5(0|1|2|3|4|5|6|7|8)(\d{3}/?|///)\s+# # ) {
$char_Ptend = $1 ;
$Ptend = $2 / 10 if( $2 ne "///" ) ;
}
# Sensor Status Indicators
# precipitation sensor not working PWINO
$PWINO = 1 if( s#PWINO\s+## ) ;
# Freezing Rain sensor not working FZRANO
$FZRANO = 1 if( s#FZRANO\s+## ) ;
# Lightning detection sensor not working TSNO
$TSNO = 1 if( s#TSNO\s+## ) ;
# Tipping bucket rain gauge is inoperative.
$PNO = 1 if( s#PNO\s+## ) ;
# Maintenance is needed on system Indicator
$maintIndicator = 1 if( s#\$\s+## ) ;
# Get Recent weather conditions with Beginning and Ending times, moved
# because the RE are too general and they match wrongly
# code table 4678
for( $i = 0; $i < 3; $i++ ) {
if(
s#(\+|-|VC|PR)?(MI|BC|DR|BL|SH|TS|FZ)?(DZ|RA|SN|SG|IC|PE|PL|GR|GS|UP)?(BR|FG|FU|VA|DU|SA|HZ|PY)?(PO|SQ|FC|SS|DS)?(B\d{2,4})(E\d{2,4})\s+##
) {
initReWX() if( $i == 0 ) ;
$Recent_WX[ $i ] = padstr( "$1$2$3$4$5", 8 ) ;
if( length( $6 ) == 5 ) {
$Recent_WX_Bhh[ $i ] = substr( $6, 1, 2 ) * 1 ;
$Recent_WX_Bmm[ $i ] = substr( $6, 3, 2 ) * 1 ;
} elsif( length( $6 ) == 3 ) {
$Recent_WX_Bmm[ $i ] = substr( $6, 1, 2 ) * 1 ;
}
if( length( $7 ) == 5 ) {
$Recent_WX_Ehh[ $i ] = substr( $7, 1, 2 ) * 1 ;
$Recent_WX_Emm[ $i ] = substr( $7, 3, 2 ) * 1 ;
} elsif( length( $7 ) == 3 ) {
$Recent_WX_Emm[ $i ] = substr( $7, 1, 2 ) * 1 ;
}
} elsif(
s#(\+|-|VC|PR)?(MI|BC|DR|BL|SH|TS|FZ)?(DZ|RA|SN|SG|IC|PE|PL|GR|GS|UP)?(BR|FG|FU|VA|DU|SA|HZ|PY)?(PO|SQ|FC|SS|DS)?(B|E)(\d{2,4})\s+##
) {
initReWX() if( $i == 0 ) ;
$Recent_WX[ $i ] = padstr( "$1$2$3$4$5", 8 ) ;
if( $6 eq "B" && ( length( $7 ) == 4 )) {
$Recent_WX_Bhh[ $i ] = substr( $7, 0, 2 ) * 1 ;
$Recent_WX_Bmm[ $i ] = substr( $7, 2, 2 ) * 1 ;
} elsif( $6 eq "B" && ( length( $7 ) == 2 )) {
$Recent_WX_Bmm[ $i ] = substr( $7, 0, 2 ) * 1 ;
} elsif( $6 eq "E" && ( length( $7 ) == 4 )) {
$Recent_WX_Ehh[ $i ] = substr( $7, 0, 2 ) * 1 ;
$Recent_WX_Emm[ $i ] = substr( $7, 2, 2 ) * 1 ;
} elsif( $6 eq "E" && ( length( $7 ) == 2 )) {
$Recent_WX_Emm[ $i ] = substr( $7, 0, 2 ) * 1 ;
}
} else {
last ;
}
}
# Plain Language remarks includes Volcanic eruptions
$PlainText = padstr( $1, 128 ) if( s#(\w.*)## ) ;
#print "Not decoded. $_ \n\n" if( $_ ) ;
} # end doRemarks
# convert cloud height to meters
sub cloud_hgt2_meters {
my( $value, $meters ) ;
( $value ) = @_ ;
if( $value == 999 ) {
$meters = 30000 ;
} else {
$meters = 30 * $value ;
}
} # end cloud_hgt2_meters
# undefine all report vars
sub undefinevars
{
# report vars
undef( $wmo_id ) ;
undef( $lat ) ;
undef( $lon ) ;
undef( $elev ) ;
undef( $ob_hour ) ;
undef( $ob_min ) ;
undef( $ob_day ) ;
undef( $time_obs ) ;
undef( $time_nominal ) ;
undef( $AUTO ) ;
undef( $GUST ) ;
undef( $VRB ) ;
undef( $DIR ) ;
undef( $SPD ) ;
undef( $UNITS ) ;
undef( $DIRmin ) ;
undef( $DIRmax ) ;
undef( $prevail_VIS_SM ) ;
undef( $prevail_VIS_KM ) ;
undef( $plus_VIS_SM ) ;
undef( $plus_VIS_KM ) ;
undef( $prevail_VIS_M ) ;
undef( $VIS_dir ) ;
undef( $CAVOK ) ;
undef( $RVRNO ) ;
undef( @RV_designator ) ;
undef( @RV_above_max ) ;
undef( @RV_below_min ) ;
undef( @RV_vrbl ) ;
undef( @RV_min ) ;
undef( @RV_max ) ;
undef( @RV_visRange ) ;
undef( $WX ) ;
undef( $vert_VIS ) ;
undef( @cloud_type ) ;
undef( @cloud_hgt ) ;
undef( @cloud_meters ) ;
undef( @cloud_phenom ) ;
undef( $T ) ;
undef( $TD ) ;
undef( $inches_ALTIM ) ;
undef( $hectoPasc_ALTIM ) ;
undef( $NOSIG ) ;
# remarks vars
undef( $TornadicType ) ;
undef( $TornadicLOC ) ;
undef( $TornadicDIR ) ;
undef( $BTornadic_hh ) ;
undef( $BTornadic_mm ) ;
undef( $ETornadic_hh ) ;
undef( $ETornadic_mm ) ;
undef( $AUTOindicator ) ;
undef( $PKWND_dir ) ;
undef( $PKWND_spd ) ;
undef( $PKWND_hh ) ;
undef( $PKWND_mm ) ;
undef( $WshfTime_hh ) ;
undef( $WshfTime_mm ) ;
undef( $Wshft_FROPA ) ;
undef( $VIS_TWR ) ;
undef( $VIS_SFC ) ;
undef( $VISmin ) ;
undef( $VISmax ) ;
undef( $VIS_2ndSite ) ;
undef( $VIS_2ndSite_LOC ) ;
undef( $LTG_OCNL ) ;
undef( $LTG_FRQ ) ;
undef( $LTG_CNS ) ;
undef( $LTG_CG ) ;
undef( $LTG_IC ) ;
undef( $LTG_CC ) ;
undef( $LTG_CA ) ;
undef( $LTG_DSNT ) ;
undef( $LTG_AP ) ;
undef( $LTG_VcyStn ) ;
undef( $LTG_DIR ) ;
# Recent_WX ReWX[3];
undef( @Recent_WX ) ;
undef( @Recent_WX_Bhh ) ;
undef( @Recent_WX_Bmm ) ;
undef( @Recent_WX_Ehh ) ;
undef( @Recent_WX_Emm ) ;
undef( $Ceiling_min ) ;
undef( $Ceiling_max ) ;
undef( $CIG_2ndSite_meters ) ;
undef( $CIG_2ndSite_LOC ) ;
undef( $PRESFR ) ;
undef( $PRESRR ) ;
undef( $SLPNO ) ;
undef( $SLP ) ;
undef( $SectorVIS_DIR ) ;
undef( $SectorVIS ) ;
undef( $GR ) ;
undef( $GRsize ) ;
undef( $VIRGA ) ;
undef( $VIRGAdir ) ;
undef( $SfcObscuration ) ;
undef( $OctsSkyObscured ) ;
undef( $CIGNO ) ;
undef( $Ceiling_est ) ;
undef( $Ceiling ) ;
undef( $VrbSkyBelow ) ;
undef( $VrbSkyLayerHgt ) ;
undef( $VrbSkyAbove ) ;
undef( $Sign_cloud ) ;
undef( $Sign_dist ) ;
undef( $Sign_dir ) ;
undef( $ObscurAloft ) ;
undef( $ObscurAloftSkyCond ) ;
undef( $ObscurAloftHgt ) ;
undef( $ACFTMSHP ) ;
undef( $NOSPECI ) ;
undef( $FIRST ) ;
undef( $LAST ) ;
undef( $Cloud_low ) ;
undef( $Cloud_medium ) ;
undef( $Cloud_high ) ;
undef( $SNINCR ) ;
undef( $SNINCR_TotalDepth ) ;
undef( $SN_depth ) ;
undef( $SN_waterequiv ) ;
undef( $SunSensorOut ) ;
undef( $SunShineDur ) ;
undef( $PRECIP_hourly ) ;
undef( $PRECIP_amt ) ;
undef( $PRECIP_24_amt ) ;
undef( $T_tenths ) ;
undef( $TD_tenths ) ;
undef( $Tmax ) ;
undef( $Tmin ) ;
undef( $Tmax24 ) ;
undef( $Tmin24 ) ;
undef( $char_Ptend ) ;
undef( $Ptend ) ;
undef( $PWINO ) ;
undef( $FZRANO ) ;
undef( $TSNO ) ;
undef( $PNO ) ;
undef( $maintIndicator ) ;
undef( $PlainText ) ;
} # end of undefinevARS
# setvars into record
sub setvars {
$remarks = padstr( $remarks, 128 ) if( defined( $remarks ) ) ;
$report = padstr( $report, 128 ) ;
undef( @dataref ) ;
@dataref = @rec ;
# report vars
$dataref[ $W[ 0 ] ] = \$rep_type if( $W[ 0 ] != -1 ) ;
$dataref[ $W[ 1 ] ] = \$stn_name ;
$dataref[ $W[ 2 ] ] = \$wmo_id if( $W[ 2 ] && defined( $wmo_id ) ) ;
$dataref[ $W[ 3 ] ] = \$lat if( $W[ 3 ] && defined( $lat ) ) ;
$dataref[ $W[ 4 ] ] = \$lon if( $W[ 4 ] && defined( $lon ) ) ;
$dataref[ $W[ 5 ] ] = \$elev if( $W[ 5 ] && defined( $elev ) ) ;
$dataref[ $W[ 6 ] ] = \$ob_hour if( $W[ 6 ] ) ;
$dataref[ $W[ 7 ] ] = \$ob_min if( $W[ 7 ] ) ;
$dataref[ $W[ 8 ] ] = \$ob_day if( $W[ 8 ] && defined( $ob_day ) ) ;
$dataref[ $W[ 9 ] ] = \$time_obs if( $W[ 9 ] && defined( $time_obs ) ) ;
$dataref[ $W[ 10 ] ] = \$time_nominal if( $W[ 10 ] && defined( $time_nominal ));
$dataref[ $W[ 11 ] ] = \$AUTO if( $W[ 11 ] && defined( $AUTO ) ) ;
$dataref[ $W[ 12 ] ] = \$UNITS if( $W[ 12 ] && defined( $UNITS ) ) ;
$dataref[ $W[ 13 ] ] = \$DIR if( $W[ 13 ] && defined( $DIR ) ) ;
$dataref[ $W[ 14 ] ] = \$SPD if( $W[ 14 ] && defined( $SPD ) ) ;
$dataref[ $W[ 15 ] ] = \$GUST if( $W[ 15 ] && defined( $GUST ) ) ;
$dataref[ $W[ 16 ] ] = \$VRB if( $W[ 16 ] && defined( $VRB ) ) ;
$dataref[ $W[ 17 ] ] = \$DIRmin if( $W[ 17 ] && defined( $DIRmin ) ) ;
$dataref[ $W[ 18 ] ] = \$DIRmax if( $W[ 18 ] && defined( $DIRmax ) ) ;
$dataref[ $W[ 19 ] ] = \$prevail_VIS_SM if( $W[ 19 ] &&
defined( $prevail_VIS_SM ) ) ;
$dataref[ $W[ 20 ] ] = \$prevail_VIS_KM if( $W[ 20 ] &&
defined( $prevail_VIS_KM ) ) ;
$dataref[ $W[ 21 ] ] = \$plus_VIS_SM if( $W[ 21 ] && defined( $plus_VIS_SM ) ) ;
$dataref[ $W[ 22 ] ] = \$plus_VIS_KM if( $W[ 22 ] && defined( $plus_VIS_KM ) ) ;
$dataref[ $W[ 23 ] ] = \$prevail_VIS_M if( $W[ 23 ] &&
defined( $prevail_VIS_M ) ) ;
$dataref[ $W[ 24 ] ] = \$VIS_dir if( $W[ 24 ] && defined( $VIS_dir ) ) ;
$dataref[ $W[ 25 ] ] = \$CAVOK if( $W[ 25 ] && defined( $CAVOK ) ) ;
$dataref[ $W[ 26 ] ] = \$RVRNO if( $W[ 26 ] && defined( $RVRNO ) ) ;
$dataref[ $W[ 27 ] ] = \@RV_designator if( $W[ 27 ] &&
defined( @RV_designator ) ) ;
$dataref[ $W[ 28 ] ] = \@RV_above_max if( $W[ 28 ] &&
defined( @RV_above_max ) ) ;
$dataref[ $W[ 29 ] ] = \@RV_below_min if( $W[ 29 ] &&
defined( @RV_below_min ) ) ;
$dataref[ $W[ 30 ] ] = \@RV_vrbl if( $W[ 30 ] && defined( @RV_vrbl ) ) ;
$dataref[ $W[ 31 ] ] = \@RV_min if( $W[ 31 ] && defined( @RV_min ) ) ;
$dataref[ $W[ 32 ] ] = \@RV_max if( $W[ 32 ] && defined( @RV_max ) ) ;
$dataref[ $W[ 33 ] ] = \@RV_visRange if( $W[ 33 ] && defined( @RV_visRange ) ) ;
$dataref[ $W[ 34 ] ] = \$WX if( $W[ 34 ] && defined( $WX ) ) ;
$dataref[ $W[ 35 ] ] = \$vert_VIS if( $W[ 35 ] && defined( $vert_VIS ) ) ;
$dataref[ $W[ 36 ] ] = \@cloud_type if( $W[ 36 ] && defined( @cloud_type ) ) ;
$dataref[ $W[ 37 ] ] = \@cloud_hgt if( $W[ 37 ] && defined( @cloud_hgt ) ) ;
$dataref[ $W[ 38 ] ] = \@cloud_meters if( $W[ 38 ] && defined( @cloud_meters ));
$dataref[ $W[ 39 ] ] = \@cloud_phenom if( $W[ 39 ] && defined( @cloud_phenom ));
$dataref[ $W[ 40 ] ] = \$T if( $W[ 40 ] && defined( $T ) ) ;
$dataref[ $W[ 41 ] ] = \$TD if( $W[ 41 ] && defined( $TD ) ) ;
$dataref[ $W[ 42 ] ] = \$hectoPasc_ALTIM if( $W[ 42 ] &&
defined( $hectoPasc_ALTIM ) ) ;
$dataref[ $W[ 43 ] ] = \$inches_ALTIM if( $W[ 43 ] && defined( $inches_ALTIM ));
$dataref[ $W[ 44 ] ] = \$NOSIG if( $W[ 44 ] && defined( $NOSIG ) ) ;
# remarks vars
$dataref[ $W[ 45 ] ] = \$TornadicType if( $W[ 45 ] && defined( $TornadicType ));
$dataref[ $W[ 46 ] ] = \$TornadicLOC if( $W[ 46 ] && defined( $TornadicLOC ) ) ;
$dataref[ $W[ 47 ] ] = \$TornadicDIR if( $W[ 47 ] && defined( $TornadicDIR ) ) ;
$dataref[ $W[ 48 ] ] = \$BTornadic_hh if( $W[ 48 ] && defined( $BTornadic_hh ));
$dataref[ $W[ 49 ] ] = \$BTornadic_mm if( $W[ 49 ] && defined( $BTornadic_mm ));
$dataref[ $W[ 50 ] ] = \$ETornadic_hh if( $W[ 50 ] && defined( $ETornadic_hh ));
$dataref[ $W[ 51 ] ] = \$ETornadic_mm if( $W[ 51 ] && defined( $ETornadic_mm ));
$dataref[ $W[ 52 ] ] = \$AUTOindicator if( $W[ 52 ] && defined($AUTOindicator));
$dataref[ $W[ 53 ] ] = \$PKWND_dir if( $W[ 53 ] && defined( $PKWND_dir ) ) ;
$dataref[ $W[ 54 ] ] = \$PKWND_spd if( $W[ 54 ] && defined( $PKWND_spd ) ) ;
$dataref[ $W[ 55 ] ] = \$PKWND_hh if( $W[ 55 ] && defined( $PKWND_hh ) ) ;
$dataref[ $W[ 56 ] ] = \$PKWND_mm if( $W[ 56 ] && defined( $PKWND_mm ) ) ;
$dataref[ $W[ 57 ] ] = \$WshfTime_hh if( $W[ 57 ] && defined( $WshfTime_hh ) ) ;
$dataref[ $W[ 58 ] ] = \$WshfTime_mm if( $W[ 58 ] && defined( $WshfTime_mm ) ) ;
$dataref[ $W[ 59 ] ] = \$Wshft_FROPA if( $W[ 59 ] && defined( $Wshft_FROPA ) ) ;
$dataref[ $W[ 60 ] ] = \$VIS_TWR if( $W[ 60 ] && defined( $VIS_TWR ) ) ;
$dataref[ $W[ 61 ] ] = \$VIS_SFC if( $W[ 61 ] && defined( $VIS_SFC ) ) ;
$dataref[ $W[ 62 ] ] = \$VISmin if( $W[ 62 ] && defined( $VISmin ) ) ;
$dataref[ $W[ 63 ] ] = \$VISmax if( $W[ 63 ] && defined( $VISmax ) ) ;
$dataref[ $W[ 64 ] ] = \$VIS_2ndSite if( $W[ 64 ] && defined( $VIS_2ndSite ) ) ;
$dataref[ $W[ 65 ] ] = \$VIS_2ndSite_LOC if( $W[ 65 ] &&
defined( $VIS_2ndSite_LOC ) ) ;
$dataref[ $W[ 66 ] ] = \$LTG_OCNL if( $W[ 66 ] && defined( $LTG_OCNL ) ) ;
$dataref[ $W[ 67 ] ] = \$LTG_FRQ if( $W[ 67 ] && defined( $LTG_FRQ ) ) ;
$dataref[ $W[ 68 ] ] = \$LTG_CNS if( $W[ 68 ] && defined( $LTG_CNS ) ) ;
$dataref[ $W[ 69 ] ] = \$LTG_CG if( $W[ 69 ] && defined( $LTG_CG ) ) ;
$dataref[ $W[ 70 ] ] = \$LTG_IC if( $W[ 70 ] && defined( $LTG_IC ) ) ;
$dataref[ $W[ 71 ] ] = \$LTG_CC if( $W[ 71 ] && defined( $LTG_CC ) ) ;
$dataref[ $W[ 72 ] ] = \$LTG_CA if( $W[ 72 ] && defined( $LTG_CA ) ) ;
$dataref[ $W[ 73 ] ] = \$LTG_DSNT if( $W[ 73 ] && defined( $LTG_DSNT ) ) ;
$dataref[ $W[ 74 ] ] = \$LTG_AP if( $W[ 74 ] && defined( $LTG_AP ) ) ;
$dataref[ $W[ 75 ] ] = \$LTG_VcyStn if( $W[ 75 ] && defined( $LTG_VcyStn ) ) ;
$dataref[ $W[ 76 ] ] = \$LTG_DIR if( $W[ 76 ] && defined( $LTG_DIR ) ) ;
# Recent_WX ReWX[3];
$dataref[ $W[ 77 ] ] = \@Recent_WX if( $W[ 77 ] && defined( @Recent_WX ) ) ;
$dataref[ $W[ 78 ] ] = \@Recent_WX_Bhh if( $W[ 78 ] &&
defined( @Recent_WX_Bhh ) ) ;
$dataref[ $W[ 79 ] ] = \@Recent_WX_Bmm if( $W[ 79 ] &&
defined( @Recent_WX_Bmm ) ) ;
$dataref[ $W[ 80 ] ] = \@Recent_WX_Ehh if( $W[ 80 ] &&
defined( @Recent_WX_Ehh ) ) ;
$dataref[ $W[ 81 ] ] = \@Recent_WX_Emm if( $W[ 81 ] &&
defined( @Recent_WX_Emm ) ) ;
$dataref[ $W[ 82 ] ] = \$Ceiling_min if( $W[ 82 ] && defined( $Ceiling_min ) ) ;
$dataref[ $W[ 83 ] ] = \$Ceiling_max if( $W[ 83 ] && defined( $Ceiling_max ) ) ;
$dataref[ $W[ 84 ] ] = \$CIG_2ndSite_meters if( $W[ 83 ] &&
defined( $CIG_2ndSite_meters ) ) ;
$dataref[ $W[ 85 ] ] = \$CIG_2ndSite_LOC if( $W[ 85 ] &&
defined( $CIG_2ndSite_LOC ) ) ;
$dataref[ $W[ 86 ] ] = \$PRESFR if( $W[ 86 ] && defined( $PRESFR ) ) ;
$dataref[ $W[ 87 ] ] = \$PRESRR if( $W[ 87 ] && defined( $PRESRR ) ) ;
$dataref[ $W[ 88 ] ] = \$SLPNO if( $W[ 88 ] && defined( $SLPNO ) ) ;
$dataref[ $W[ 89 ] ] = \$SLP if( $W[ 89 ] && defined( $SLP ) ) ;
$dataref[ $W[ 90 ] ] = \$SectorVIS_DIR if( $W[ 90 ] &&
defined( $SectorVIS_DIR ) ) ;
$dataref[ $W[ 91 ] ] = \$SectorVIS if( $W[ 91 ] && defined( $SectorVIS ) ) ;
$dataref[ $W[ 92 ] ] = \$GR if( $W[ 92 ] && defined( $GR ) ) ;
$dataref[ $W[ 93 ] ] = \$GRsize if( $W[ 93 ] && defined( $GRsize ) ) ;
$dataref[ $W[ 94 ] ] = \$VIRGA if( $W[ 94 ] && defined( $VIRGA ) ) ;
$dataref[ $W[ 95 ] ] = \$VIRGAdir if( $W[ 95 ] && defined( $VIRGAdir ) ) ;
$dataref[ $W[ 96 ] ] = \$SfcObscuration if( $W[ 96 ] &&
defined( $SfcObscuration ) ) ;
$dataref[ $W[ 97 ] ] = \$OctsSkyObscured if( $W[ 97 ] &&
defined( $OctsSkyObscured ) ) ;
$dataref[ $W[ 98 ] ] = \$CIGNO if( $W[ 98 ] && defined( $CIGNO ) ) ;
$dataref[ $W[ 99 ] ] = \$Ceiling_est if( $W[ 99 ] && defined( $Ceiling_est ) ) ;
$dataref[ $W[ 100 ] ] = \$Ceiling if( $W[ 100 ] && defined( $Ceiling ) ) ;
$dataref[ $W[ 101 ] ] = \$VrbSkyBelow if( $W[ 101 ] && defined( $VrbSkyBelow ));
$dataref[ $W[ 102 ] ] = \$VrbSkyLayerHgt if( $W[ 102 ] &&
defined( $VrbSkyLayerHgt ) ) ;
$dataref[ $W[ 103 ] ] = \$VrbSkyAbove if( $W[ 103 ] &&
defined( $VrbSkyAbove ) ) ;
$dataref[ $W[ 104 ] ] = \$Sign_cloud if( $W[ 104 ] && defined( $Sign_cloud ) ) ;
$dataref[ $W[ 105 ] ] = \$Sign_dist if( $W[ 105 ] && defined( $Sign_dist ) ) ;
$dataref[ $W[ 106 ] ] = \$Sign_dir if( $W[ 106 ] && defined( $Sign_dir ) ) ;
$dataref[ $W[ 107 ] ] = \$ObscurAloft if( $W[ 107 ] && defined( $ObscurAloft ));
$dataref[ $W[ 108 ] ] = \$ObscurAloftSkyCond if( $W[ 108 ] &&
defined( $ObscurAloftSkyCond ) ) ;
$dataref[ $W[ 109 ] ] = \$ObscurAloftHgt if( $W[ 109 ] &&
defined( $ObscurAloftHgt ) ) ;
$dataref[ $W[ 110 ] ] = \$ACFTMSHP if( $W[ 110 ] && defined( $ACFTMSHP ) ) ;
$dataref[ $W[ 111 ] ] = \$NOSPECI if( $W[ 111 ] && defined( $NOSPECI ) ) ;
$dataref[ $W[ 112 ] ] = \$FIRST if( $W[ 112 ] && defined( $FIRST ) ) ;
$dataref[ $W[ 113 ] ] = \$LAST if( $W[ 113 ] && defined( $LAST ) ) ;
$dataref[ $W[ 114 ] ] = \$Cloud_low if( $W[ 114 ] && defined( $Cloud_low ) ) ;
$dataref[ $W[ 115 ] ] = \$Cloud_medium if( $W[ 115 ] &&
defined( $Cloud_medium ) ) ;
$dataref[ $W[ 116 ] ] = \$Cloud_high if( $W[ 116 ] && defined( $Cloud_high ) ) ;
$dataref[ $W[ 117 ] ] = \$SNINCR if( $W[ 117 ] && defined( $SNINCR ) ) ;
$dataref[ $W[ 118 ] ] = \$SNINCR_TotalDepth if( $W[ 118 ] &&
defined( $SNINCR_TotalDepth ) ) ;
$dataref[ $W[ 119 ] ] = \$SN_depth if( $W[ 119 ] && defined( $SN_depth ) ) ;
$dataref[ $W[ 120 ] ] = \$SN_waterequiv if( $W[ 120 ] &&
defined( $SN_waterequiv ) ) ;
$dataref[ $W[ 121 ] ] = \$SunSensorOut if( $W[ 121 ] &&
defined( $SunSensorOut ) ) ;
$dataref[ $W[ 122 ] ] = \$SunShineDur if( $W[ 122 ] && defined( $SunShineDur ));
$dataref[ $W[ 123 ] ] = \$PRECIP_hourly if( $W[ 123 ] &&
defined( $PRECIP_hourly ) ) ;
$dataref[ $W[ 124 ] ] = \$PRECIP_amt if( $W[ 124 ] && defined( $PRECIP_amt ) ) ;
$dataref[ $W[ 125 ] ] = \$PRECIP_24_amt if( $W[ 125 ] &&
defined( $PRECIP_24_amt ) ) ;
$dataref[ $W[ 126 ] ] = \$T_tenths if( $W[ 126 ] && defined( $T_tenths ) ) ;
$dataref[ $W[ 127 ] ] = \$TD_tenths if( $W[ 127 ] && defined( $TD_tenths ) ) ;
$dataref[ $W[ 128 ] ] = \$Tmax if( $W[ 128 ] && defined( $Tmax ) ) ;
$dataref[ $W[ 129 ] ] = \$Tmin if( $W[ 129 ] && defined( $Tmin ) ) ;
$dataref[ $W[ 130 ] ] = \$Tmax24 if( $W[ 130 ] && defined( $Tmax24 ) ) ;
$dataref[ $W[ 131 ] ] = \$Tmin24 if( $W[ 131 ] && defined( $Tmin24 ) ) ;
$dataref[ $W[ 132 ] ] = \$char_Ptend if( $W[ 132 ] && defined( $char_Ptend ) ) ;
$dataref[ $W[ 133 ] ] = \$Ptend if( $W[ 133 ] && defined( $Ptend ) ) ;
$dataref[ $W[ 134 ] ] = \$PWINO if( $W[ 134 ] && defined( $PWINO ) ) ;
$dataref[ $W[ 135 ] ] = \$FZRANO if( $W[ 135 ] && defined( $FZRANO ) ) ;
$dataref[ $W[ 136 ] ] = \$TSNO if( $W[ 136 ] && defined( $TSNO ) ) ;
$dataref[ $W[ 137 ] ] = \$PNO if( $W[ 137 ] && defined( $PNO ) ) ;
$dataref[ $W[ 138 ] ] = \$maintIndicator if( $W[ 138 ] &&
defined( $maintIndicator ) ) ;
$dataref[ $W[ 139 ] ] = \$PlainText if( $W[ 139 ] && defined( $PlainText ) ) ;
# original report and remarks
$dataref[ $W[ 140 ] ] = \$report if( $W[ 140 ] && defined( $report ) ) ;
$dataref[ $W[ 141 ] ] = \$remarks if( $W[ 141 ] && defined( $remarks ) ) ;
} # end setvars
# create a netcdf file or reopen a existing one
sub doNet {
my( $hour, $file, $Id, $Num, $Time, $stn, $hr, $i ) ;
( $hour ) = @_ ;
$ncfile = $datadir . "/" . $yymmdd . $hour . "_metar.nc" ;
$metafile = $metadir . "/" . $yymmdd . $hour . "_metar.meta" ;
# writing to same file
return 1 if( $ncfile eq $lastNc ) ;
# current time
$thetime = time() ;
# save current file info
$Nets{ $lastNc } = "$ncid $recnum $thetime" if( $lastNc ) ;
# File is open, get ncfile id and recnum and reset the time
if( defined( $Nets{ $ncfile } ) ) { # already open for writes
( $ncid, $recnum, $ncTime ) = split( " ", $Nets{ $ncfile } ) ;
$ncTime = $thetime ;
$lastNc = $ncfile ;
return 1 ;
}
# close files with no activity for 20 minutes
foreach $file ( keys %Nets ) {
( $Id, $Num, $Time ) = split( " ", $Nets{ $file } ) ;
if( $thetime - $Time > 1200 ) {
print "Closing $file with ncid $Id, No write for > 1200 Sec\n" ;
$result = NetCDF::close( $Id ) ;
delete( $Nets{ $file } ) ;
} else {
$result = NetCDF::sync( $Id ) ;
}
}
# remove stn entries older than 4 hours
foreach $stn ( keys %reportslist ) {
( $hr ) = $reportslist{ $stn } ;
$hr = abs( $hour - $hr ) ;
delete( $reportslist{ $stn } ) if( $hr > 3 && $hr < 21 ) ;
}
# open or create ncfiles
if( -e $ncfile ) {
$ncid = NetCDF::open( "$ncfile", WRITE ) ;
$recNum_id = NetCDF::dimid( $ncid, "recNum" ) ;
$name_id = "xxxxxxxx" ;
$recnum = -1 ;
# get current value of recnum
NetCDF::diminq( $ncid, $recNum_id, $name_id, $recnum ) ;
} else {
die "Wrong or missing cdlfile parameter: $!\n" unless -e $cdlfile ;
system( "mkdir -p $datadir" ) if( ! -e $datadir ) ;
system( "$ncgen -o $ncfile $cdlfile" ) ;
$ncid = NetCDF::open( "$ncfile", WRITE ) ;
# NetCDF record counter
$recnum = 0 ;
# create metadata file and populate
print "metar metadata file = $metafile\n" ;
open( META, ">$metafile" ) ;
close META ;
}
$Nets{ $ncfile } = "$ncid $recnum $thetime" ;
$lastNc = $ncfile ;
print "Opening $ncfile with ncid $ncid\n" ;
# check for to many files open
if( $ncid > 25 ) {
foreach $file ( keys %Nets ) {
( $Id, $Num, $Time ) = split( " ", $Nets{ $file } ) ;
if( $ncid != $Id ) {
print "Closing $file with Id $Id, To many open files\n"
;
$result = NetCDF::close( $Id ) ;
delete( $Nets{ $file } ) ;
}
}
}
return 1 ;
} # end doNet
# print vars
sub printvars
{
# original report and remarks
print "report = $report \n" if( defined( $report ) ) ;
print "remarks = $remarks \n" if( defined( $remarks ) ) ;
print "\n" ;
# report vars
print "rep_type = $rep_type \n" if( defined( $rep_type ) ) ;
print "stn_name = $stn_name \n" if( defined( $stn_name ) ) ;
print "wmo_id = $wmo_id \n" if( defined( $wmo_id ) ) ;
print "lat = $lat \n" if( defined( $lat ) ) ;
print "lon = $lon \n" if( defined( $lon ) ) ;
print "elev = $elev \n" if( defined( $elev ) ) ;
print "ob_hour = $ob_hour \n" if( defined( $ob_hour ) ) ;
print "ob_min = $ob_min \n" if( defined( $ob_min ) ) ;
print "ob_day = $ob_day \n" if( defined( $ob_day ) ) ;
print "time_obs = $time_obs \n" if( defined( $time_obs ) ) ;
print "time_nominal = $time_nominal \n" if( defined( $time_nominal ) ) ;
print "AUTO = $AUTO \n" if( defined( $AUTO ) ) ;
print "GUST = $GUST \n" if( defined( $GUST ) ) ;
print "VRB = $VRB \n" if( defined( $VRB ) ) ;
print "DIR = $DIR \n" if( defined( $DIR ) ) ;
print "SPD = $SPD \n" if( defined( $SPD ) ) ;
print "UNITS = $UNITS \n" if( defined( $UNITS ) ) ;
print "DIRmin = $DIRmin \n" if( defined( $DIRmin ) ) ;
print "DIRmax = $DIRmax \n" if( defined( $DIRmax ) ) ;
print "prevail_VIS_SM = $prevail_VIS_SM \n" if( defined( $prevail_VIS_SM ) ) ;
print "prevail_VIS_KM = $prevail_VIS_KM \n" if( defined( $prevail_VIS_KM ) ) ;
print "plus_VIS_SM = $plus_VIS_SM \n" if( defined( $plus_VIS_SM ) ) ;
print "plus_VIS_KM = $plus_VIS_KM \n" if( defined( $plus_VIS_KM ) ) ;
print "prevail_VIS_M = $prevail_VIS_M \n" if( defined( $prevail_VIS_M ) ) ;
print "VIS_dir = $VIS_dir \n" if( defined( $VIS_dir ) ) ;
print "CAVOK = $CAVOK \n" if( defined( $CAVOK ) ) ;
print "RVRNO = $RVRNO \n" if( defined( $RVRNO ) ) ;
print "RV_designator = @RV_designator \n" if( defined( @RV_designator ) ) ;
print "RV_above_max = @RV_above_max \n" if( defined( @RV_above_max ) ) ;
print "RV_below_min = @RV_below_min \n" if( defined( @RV_below_min ) ) ;
print "RV_vrbl = @RV_vrbl \n" if( defined( @RV_vrbl ) ) ;
print "RV_min = @RV_min \n" if( defined( @RV_min ) ) ;
print "RV_max = @RV_max \n" if( defined( @RV_max ) ) ;
print "RV_visRange = @RV_visRange \n" if( defined( @RV_visRange ) ) ;
print "WX = $WX \n" if( defined( $WX ) ) ;
print "vert_VIS = $vert_VIS \n" if( defined( $vert_VIS ) ) ;
print "cloud_type = @cloud_type \n" if( defined( @cloud_type ) ) ;
print "cloud_hgt = @cloud_hgt \n" if( defined( @cloud_hgt ) ) ;
print "cloud_meters = @cloud_meters \n" if( defined( @cloud_meters ) ) ;
print "cloud_phenom = @cloud_phenom \n" if( defined( @cloud_phenom ) ) ;
print "T = $T \n" if( defined( $T ) ) ;
print "TD = $TD \n" if( defined( $TD ) ) ;
print "inches_ALTIM = $inches_ALTIM \n" if( defined( $inches_ALTIM ) ) ;
print "hectoPasc_ALTIM = $hectoPasc_ALTIM \n" if( defined( $hectoPasc_ALTIM )) ;
print "NOSIG = $NOSIG \n" if( defined( $NOSIG ) ) ;
# remarks vars
print "\n" ;
#print "remarks = $remarks \n" if( defined( $remarks ) ) ;
#print "\n" ;
print "TornadicType = $TornadicType \n" if( defined( $TornadicType ) ) ;
print "TornadicLOC = $TornadicLOC \n" if( defined( $TornadicLOC ) ) ;
print "TornadicDIR = $TornadicDIR \n" if( defined( $TornadicDIR ) ) ;
print "BTornadic_hh = $BTornadic_hh \n" if( defined( $BTornadic_hh ) ) ;
print "BTornadic_mm = $BTornadic_mm \n" if( defined( $BTornadic_mm ) ) ;
print "ETornadic_hh = $ETornadic_hh \n" if( defined( $ETornadic_hh ) ) ;
print "ETornadic_mm = $ETornadic_mm \n" if( defined( $ETornadic_mm ) ) ;
print "AUTOindicator = $AUTOindicator \n" if( defined( $AUTOindicator ) ) ;
print "PKWND_dir = $PKWND_dir \n" if( defined( $PKWND_dir ) ) ;
print "PKWND_spd = $PKWND_spd \n" if( defined( $PKWND_spd ) ) ;
print "PKWND_hh = $PKWND_hh \n" if( defined( $PKWND_hh ) ) ;
print "PKWND_mm = $PKWND_mm \n" if( defined( $PKWND_mm ) ) ;
print "WshfTime_hh = $WshfTime_hh \n" if( defined( $WshfTime_hh ) ) ;
print "WshfTime_mm = $WshfTime_mm \n" if( defined( $WshfTime_mm ) ) ;
print "Wshft_FROPA = $Wshft_FROPA \n" if( defined( $Wshft_FROPA ) ) ;
print "VIS_TWR = $VIS_TWR \n" if( defined( $VIS_TWR ) ) ;
print "VIS_SFC = $VIS_SFC \n" if( defined( $VIS_SFC ) ) ;
print "VISmin = $VISmin \n" if( defined( $VISmin ) ) ;
print "VISmax = $VISmax \n" if( defined( $VISmax ) ) ;
print "VIS_2ndSite = $VIS_2ndSite \n" if( defined( $VIS_2ndSite ) ) ;
print "VIS_2ndSite_LOC = $VIS_2ndSite_LOC \n" if( defined( $VIS_2ndSite_LOC )) ;
print "LTG_OCNL = $LTG_OCNL \n" if( defined( $LTG_OCNL ) ) ;
print "LTG_FRQ = $LTG_FRQ \n" if( defined( $LTG_FRQ ) ) ;
print "LTG_CNS = $LTG_CNS \n" if( defined( $LTG_CNS ) ) ;
print "LTG_CG = $LTG_CG \n" if( defined( $LTG_CG ) ) ;
print "LTG_IC = $LTG_IC \n" if( defined( $LTG_IC ) ) ;
print "LTG_CC = $LTG_CC \n" if( defined( $LTG_CC ) ) ;
print "LTG_CA = $LTG_CA \n" if( defined( $LTG_CA ) ) ;
print "LTG_DSNT = $LTG_DSNT \n" if( defined( $LTG_DSNT ) ) ;
print "LTG_AP = $LTG_AP \n" if( defined( $LTG_AP ) ) ;
print "LTG_VcyStn = $LTG_VcyStn \n" if( defined( $LTG_VcyStn ) ) ;
print "LTG_DIR = $LTG_DIR \n" if( defined( $LTG_DIR ) ) ;
# Recent_WX ReWX[3];
print "Recent_WX = @Recent_WX \n" if( defined( @Recent_WX ) ) ;
print "Recent_WX_Bhh = @Recent_WX_Bhh \n" if( defined( @Recent_WX_Bhh ) ) ;
print "Recent_WX_Bmm = @Recent_WX_Bmm \n" if( defined( @Recent_WX_Bmm ) ) ;
print "Recent_WX_Ehh = @Recent_WX_Ehh \n" if( defined( @Recent_WX_Ehh ) ) ;
print "Recent_WX_Emm = @Recent_WX_Emm \n" if( defined( @Recent_WX_Emm ) ) ;
print "Ceiling_min = $Ceiling_min \n" if( defined( $Ceiling_min ) ) ;
print "Ceiling_max = $Ceiling_max \n" if( defined( $Ceiling_max ) ) ;
print "CIG_2ndSite_meters = $CIG_2ndSite_meters \n"
if( defined( $CIG_2ndSite_meters ) ) ;
print "CIG_2ndSite_LOC = $CIG_2ndSite_LOC \n" if( defined( $CIG_2ndSite_LOC )) ;
print "PRESFR = $PRESFR \n" if( defined( $PRESFR ) ) ;
print "PRESRR = $PRESRR \n" if( defined( $PRESRR ) ) ;
print "SLPNO = $SLPNO \n" if( defined( $SLPNO ) ) ;
print "SLP = $SLP \n" if( defined( $SLP ) ) ;
print "SectorVIS_DIR = $SectorVIS_DIR \n" if( defined( $SectorVIS_DIR ) ) ;
print "SectorVIS = $SectorVIS \n" if( defined( $SectorVIS ) ) ;
print "GR = $GR \n" if( defined( $GR ) ) ;
print "GRsize = $GRsize \n" if( defined( $GRsize ) ) ;
print "VIRGA = $VIRGA \n" if( defined( $VIRGA ) ) ;
print "VIRGAdir = $VIRGAdir \n" if( defined( $VIRGAdir ) ) ;
print "SfcObscuration = $SfcObscuration \n" if( defined( $SfcObscuration ) ) ;
print "OctsSkyObscured = $OctsSkyObscured \n" if( defined( $OctsSkyObscured )) ;
print "CIGNO = $CIGNO \n" if( defined( $CIGNO ) ) ;
print "Ceiling_est = $Ceiling_est \n" if( defined( $Ceiling_est ) ) ;
print "Ceiling = $Ceiling \n" if( defined( $Ceiling ) ) ;
print "VrbSkyBelow = $VrbSkyBelow \n" if( defined( $VrbSkyBelow ) ) ;
print "VrbSkyLayerHgt = $VrbSkyLayerHgt \n" if( defined( $VrbSkyLayerHgt ) ) ;
print "VrbSkyAbove = $VrbSkyAbove \n" if( defined( $VrbSkyAbove ) ) ;
print "Sign_cloud = $Sign_cloud \n" if( defined( $Sign_cloud ) ) ;
print "Sign_dist = $Sign_dist \n" if( defined( $Sign_dist ) ) ;
print "Sign_dir = $Sign_dir \n" if( defined( $Sign_dir ) ) ;
print "ObscurAloft = $ObscurAloft \n" if( defined( $ObscurAloft ) ) ;
print "ObscurAloftSkyCond = $ObscurAloftSkyCond \n"
if( defined( $ObscurAloftSkyCond ) ) ;
print "ObscurAloftHgt = $ObscurAloftHgt \n" if( defined( $ObscurAloftHgt ) ) ;
print "ACFTMSHP = $ACFTMSHP \n" if( defined( $ACFTMSHP ) ) ;
print "NOSPECI = $NOSPECI \n" if( defined( $NOSPECI ) ) ;
print "FIRST = $FIRST \n" if( defined( $FIRST ) ) ;
print "LAST = $LAST \n" if( defined( $LAST ) ) ;
print "Cloud_low = $Cloud_low \n" if( defined( $Cloud_low ) ) ;
print "Cloud_medium = $Cloud_medium \n" if( defined( $Cloud_medium ) ) ;
print "Cloud_high = $Cloud_high \n" if( defined( $Cloud_high ) ) ;
print "SNINCR = $SNINCR \n" if( defined( $SNINCR ) ) ;
print "SNINCR_TotalDepth = $SNINCR_TotalDepth \n"
if( defined( $SNINCR_TotalDepth ) ) ;
print "SN_depth = $SN_depth \n" if( defined( $SN_depth ) ) ;
print "SN_waterequiv = $SN_waterequiv \n" if( defined( $SN_waterequiv ) ) ;
print "SunSensorOut = $SunSensorOut \n" if( defined( $SunSensorOut ) ) ;
print "SunShineDur = $SunShineDur \n" if( defined( $SunShineDur ) ) ;
print "PRECIP_hourly = $PRECIP_hourly \n" if( defined( $PRECIP_hourly ) ) ;
print "PRECIP_amt = $PRECIP_amt \n" if( defined( $PRECIP_amt ) ) ;
print "PRECIP_24_amt = $PRECIP_24_amt \n" if( defined( $PRECIP_24_amt ) ) ;
print "T_tenths = $T_tenths \n" if( defined( $T_tenths ) ) ;
print "TD_tenths = $TD_tenths \n" if( defined( $TD_tenths ) ) ;
print "Tmax = $Tmax \n" if( defined( $Tmax ) ) ;
print "Tmin = $Tmin \n" if( defined( $Tmin ) ) ;
print "Tmax24 = $Tmax24 \n" if( defined( $Tmax24 ) ) ;
print "Tmin24 = $Tmin24 \n" if( defined( $Tmin24 ) ) ;
print "char_Ptend = $char_Ptend \n" if( defined( $char_Ptend ) ) ;
print "Ptend = $Ptend \n" if( defined( $Ptend ) ) ;
print "PWINO = $PWINO \n" if( defined( $PWINO ) ) ;
print "FZRANO = $FZRANO \n" if( defined( $FZRANO ) ) ;
print "TSNO = $TSNO \n" if( defined( $TSNO ) ) ;
print "PNO = $PNO \n" if( defined( $PNO ) ) ;
print "maintIndicator = $maintIndicator \n" if( defined( $maintIndicator ) ) ;
print "PlainText Language = $PlainText \n" if( defined( $PlainText ) ) ;
print "\n" ;
} # end printvars
# execute at exit
sub atexit
{
local( $sig ) = @_ ;
if( $sig eq "eof" ) {
print "eof on STDIN --shutting down\n" ;
} elsif( defined( $sig )) {
print "Caught SIG$sig --shutting down\n" ;
}
# open metar.lst, list of reports processed in the last 4 hours.
open( LST, ">$datadir/metar.lst" ) ||
die "could not open $datadir/metar.lst: $!\n" ;
select( LST ) ;
# remove stn entries older than 4 hours
foreach $stn ( keys %reportslist ) {
( $hr ) = $reportslist{ $stn } ;
$hr = abs( $hour - $hr ) ;
print "$stn $reportslist{ $stn }\n" if( !( $hr > 3 && $hr < 21 ) ) ;
}
close LST ;
foreach $file ( keys %Nets ) {
( $ncid, $recnum, $nctime ) = split( " ", $Nets{ $file } ) ;
print STDOUT "Closing $file with ncid $ncid\n" ;
$result = NetCDF::close( $ncid ) ;
#print STDOUT "NetCDF::close result = $result\n" ;
}
close( OPN ) ;
close( STDOUT ) ;
close( STDERR ) ;
exit( 0 ) ;
}
# init Recent weather arrays
sub initReWX
{
# Recent_WX ReWX[3];
@Recent_WX = ( $S8, $S8, $S8 ) ;
@Recent_WX_Bhh = ( $F, $F, $F ) ;
@Recent_WX_Bmm = ( $F, $F, $F ) ;
@Recent_WX_Ehh = ( $F, $F, $F ) ;
@Recent_WX_Emm = ( $F, $F, $F ) ;
} # end initReWX
# pad str to correct length
sub padstr
{
( $str, $len ) = @_ ;
local( $size, $i ) ;
$size = length( $str ) ;
for( $i = $size; $i < $len; $i++ ) {
$str .= "\0" ;
#print "$str,\n" ;
}
if( $size > $len ) {
print STDOUT "String length is over $len chars long:\n $str\n" ;
$str = substr( $str, 0, $len ) ;
#exit 0 ;
}
return $str ;
}
sub thetime
{
my( $when, $add, $ss, $mm, $hh, $mday, $mon, $year, $wday, $yday, $isdst ) ;
( $when ) = @_ ;
$add = 0 ;
$mm = 0 ;
$hh = 0 ;
$mday = $ob_day ;
if( $when eq "tomorrow" ) {
$add = 86400 ;
} elsif( $when eq "yesterday" ) {
$add = -86400 ;
$mday = $tday ;
} elsif( $when eq "obs" ) {
$mm = $ob_min ;
$hh = $ob_hour ;
$year = substr( $yymmdd, 0, 2 ) ;
$mon = substr( $yymmdd, 2, 2 ) ;
$time = timegm(0, $mm, $hh, $mday, $mon -1, $year, 0, 0, 0) ;
return $time ;
} elsif( $when eq "nominal" ) {
$mm = $ob_min if( $ob_min > 14 && $ob_min < 45 ) ;
$hh = $hour ;
} elsif( $when eq "trans" ) {
$mm = $tmin ;
$hh = $thour ;
$mday = $tday ;
}
$time = timegm(0, $mm, $hh, $mday, $themonth -1, $theyear, 0, 0, 0) ;
return $time if( $when eq "obs" || $when eq "nominal" || $when eq "trans" ) ;
( $ss, $mm, $hh, $mday, $mon, $year, $wday, $yday, $isdst ) =
gmtime( $time + $add ) ;
$year = ( $year < 100 ? $year : $year - 100 ) ;
$year = sprintf( "%02d", $year ) ;
$mon++ ;
$mon = sprintf( "%02d", $mon ) ;
$mday = sprintf( "%02d", $mday ) ;
return "$year$mon$mday" ;
}