MythTV  master
NWSLocation.pm
Go to the documentation of this file.
1 
2 #TODO In its infinite wisdom, the XML the NWS gives us (NWS-Stations.xml) is
3 # not consistent wrt to lat lon. Some are in a +/- format, others in [NSEW]
4 # format, also, some aren't even listed. It seems unlikely that the NWS doesn't
5 # know that location of some of its weather stations and in fact they are on
6 # their website, so maybe write a script to grab missing ones and massage them
7 # all to a consistent format.
8 
9 package NWSLocation;
10 use English;
11 use strict;
12 use warnings;
13 
14 require Exporter;
15 use base qw(XML::SAX::Base);
16 use XML::Parser;
17 use Data::Dumper;
18 use File::Basename;
19 use Cwd 'abs_path';
20 
21 our @ISA = qw(Exporter);
22 our @EXPORT = qw(doSearch AddLatLonSearch AddStationIdSearch AddLocSearch);
23 our $VERSION = 0.1;
24 
25 my @latlonsearches;
26 my @stationidsearches;
27 my @locstrsearches;
28 my @statesearches;
29 my %currStation;
30 my $searchresults;
31 
32 sub doSearch {
33  my $xml_file = dirname(abs_path($0 or $PROGRAM_NAME)) . "/NWS-Stations.xml";
34 
35  my $parser = new XML::Parser( Style => 'Stream' );
36  open(XML, $xml_file) or die "cannot open NWS-Stations.xml file\n";
37  $parser->parse(*XML);
38  close(XML);
39  return $searchresults;
40 }
41 
42 sub StartDocument {
43  my $expat = shift;
44 
45  $expat->{finish} = 0;
46 
47 }
48 
49 sub StartTag {
50  my ($expat, $name, %atts) = @_;
51 
52  if ($name eq 'station') {
53  $expat->{CurrEntry} = {};
54  $expat->{MatchFound} = 0;
55  }
56 }
57 
58 sub Text {
59 
60  my $expat = shift;
61  my $text = $expat->{Text};
62  my $search;
63 
64  if ($expat->in_element('station_id')) {
65  $expat->{CurrEntry}->{station_id} = $text;
66  if (!$expat->{MatchFound}) {
67  foreach $search (@stationidsearches) {
68  if ($text =~ m/$search/i) {
69  $expat->{MatchFound} = 1;
70  return;
71  }
72  }
73  }
74  }
75 
76  if ($expat->in_element('state')) {
77  $expat->{CurrEntry}->{state} = $text;
78  if (!$expat->{MatchFound}) {
79  foreach $search (@statesearches) {
80  if ($text =~ m/$search/i) {
81  $expat->{MatchFound} = 1;
82  return;
83  }
84  }
85  }
86  }
87 
88  if ($expat->in_element('station_name')) {
89  $expat->{CurrEntry}->{station_name} = $text;
90  if (!$expat->{MatchFound}) {
91  foreach $search (@locstrsearches) {
92  if ($text =~ m/$search/i) {
93  $expat->{MatchFound} = 1;
94  return;
95  }
96  }
97  }
98  }
99 
100  # annoyingly, the lat/lon format is not consistent in the XML file,
101  # sometimes its in +/- format, other times N/S E/W, so we convert it right
102  # off to be unifrom in +/-
103  if ($expat->in_element('latitude')){
104  $text =~ s/(\d{1,3}([.]\d{1,3})?)([.]\d{1,3})?[N]/+$1/ or
105  $text =~ s/(\d{1,3}([.]\d{1,3})?)([.]\d{1,3})?[S]/-$1/;
106  $expat->{CurrEntry}->{latitude} = $text;
107  $expat->{currLat} = $text;
108  return;
109  }
110 
111  if ($expat->in_element('longitude')) {
112  $text =~ s/(\d{1,3}([.]\d{1,3})?)([.]\d{1,3})?[E]/+$1/ or
113  $text =~ s/(\d{1,3}([.]\d{1,3})?)([.]\d{1,3})?[W]/-$1/;
114  $expat->{CurrEntry}->{longitude} = $text;
115  if (!$expat->{MatchFound}) {
116  foreach $search (@latlonsearches) {
117  if ($search->[0] eq $expat->{currLat} && $search->[1] eq $text) {
118  $expat->{MatchFound} = 1;
119  return;
120  }
121  }
122  }
123  }
124 }
125 
126 sub EndTag {
127  my ($expat, $name) = @_;
128 
129  if ($name eq 'station' && $expat->{MatchFound}) {
130  push (@$searchresults, $expat->{CurrEntry});
131  if ($expat->{finish}) {
132  $expat->finish();
133  return;
134  }
135  }
136 
137 }
138 
139 sub AddLatLonSearch {
140  my ($lat, $lon) = @_;
141  push (@latlonsearches, [$lat, $lon]);
142 }
143 
144 sub AddStationIdSearch {
145  my $id = shift;
146  push (@stationidsearches, $id);
147 }
148 
149 sub AddLocSearch {
150  my $loc = shift;
151  push (@locstrsearches, $loc);
152 }
153 
154 sub AddStateSearch {
155  my $state = shift;
156  push (@statesearches, $state);
157 }
158 
159 1;