MythTV  master
metoffice_fivedayapi.pl
Go to the documentation of this file.
1 #! /usr/bin/perl
2 # vim:ts=4:sw=4:ai:et:si:sts=4
3 
4 use strict;
5 use warnings;
6 
7 use utf8;
8 
9 use English;
10 
11 use File::Basename;
12 use Cwd 'abs_path';
13 use lib dirname(abs_path($0 or $PROGRAM_NAME)),
14  '/usr/share/mythtv/mythweather/scripts/uk_metoffice',
15  '/usr/local/share/mythtv/mythweather/scripts/uk_metoffice';
16 
17 use XML::Simple;
18 use LWP::Simple;
19 use Getopt::Std;
20 use File::Path;
21 use Switch;
22 
23 use DateTime;
24 use Date::Parse;
25 use Date::Calc qw(Day_of_Week);
26 use File::Basename;
27 use lib dirname($0);
28 use MetOffCommon qw(:DEFAULT $apikey);
29 
30 our ($opt_v, $opt_t, $opt_T, $opt_l, $opt_u, $opt_d, $opt_D);
31 
32 my $name = 'MetOffice-Forecast-API';
33 my $version = 0.3;
34 my $author = 'Stuart Morgan';
35 my $email = 'smorgan@mythtv.org';
36 
37 my $updateInterval = 3*60*60; # 3 Hours
38 my $retrieveTimeout = 30;
39 my @types = ('3dlocation', '6dlocation', 'station_id', 'copyright',
40  'copyrightlogo', 'weather_icon', 'updatetime',
41  'date-0', 'icon-0', 'low-0', 'high-0',
42  'date-1', 'icon-1', 'low-1', 'high-1',
43  'date-2', 'icon-2', 'low-2', 'high-2',
44  'date-3', 'icon-3', 'low-3', 'high-3',
45  'date-4', 'icon-4', 'low-4', 'high-4',
46  'date-5', 'icon-5', 'low-5', 'high-5');
47 my $dir = "/tmp/uk_metoffice";
48 my $logdir = "/tmp/uk_metoffice";
49 
50 binmode(STDOUT, ":utf8");
51 
52 if (!-d $logdir) {
53  mkpath( $logdir, {mode => 0755} );
54 }
55 
56 getopts('Tvtlu:d:');
57 
58 if (defined $opt_v) {
59  print "$name,$version,$author,$email\n";
60  log_print( $logdir, "-v\n" );
61  exit 0;
62 }
63 
64 if (defined $opt_T) {
65  print "$updateInterval,$retrieveTimeout\n";
66  log_print( $logdir, "-t\n" );
67  exit 0;
68 }
69 
70 if (defined $opt_d) {
71  $dir = $opt_d;
72 }
73 
74 if (!-d $dir) {
75  mkpath( $dir, {mode => 0755} );
76 }
77 
78 if (defined $opt_l) {
79  my $search = shift;
80  log_print( $logdir, "-l $search\n" );
81  my @results = MetOffCommon::Search($search, $dir, $updateInterval, $logdir);
82  my $result;
83 
84  foreach (@results) {
85  print $_ . "\n";
86  }
87 
88  exit 0;
89 }
90 
91 if (defined $opt_t) {
92  foreach (@types) {print; print "\n";}
93  exit 0;
94 }
95 
96 my $units = "SI";
97 if (defined $opt_u) {
98  $units = $opt_u;
99 }
100 
101 my $locid = shift;
102 # we get here, we're doing an actual retrieval, everything must be defined
103 #my $locid = MetOffLocation::FindLoc(shift, $dir, $updateInterval, $logdir);
104 if (!(defined $locid && !$locid eq "")) {
105  die "Invalid usage";
106 }
107 
108 my $base_args = '?res=daily&key=' . $MetOffCommon::api_key;
109 
110 # BEGIN workaround for API bug, may be removed when fixed, although it does no
111 # harm and possibly some benefits to it such as 6 days instead of the default
112 # 5
113 my $start_date = DateTime->now()->set_hour(0)->set_minute(0)->set_second(0);
114 if (DateTime->now()->hour() >= 18) {
115  $start_date->add( days => 1 );
116 }
117 my $end_date = $start_date->clone();
118 $end_date->add( days => 5 );
119 $base_args = $base_args . '&valid-from=' . $start_date . '&valid-to=' . $end_date;
120 # END workaround
121 
122 my $url = "";
123 
124 if ($locid =~ s/^(\d*)/$1/)
125 {
126  $url = $MetOffCommon::forecast_url . $1 . $base_args;
127 }
128 else
129 {
130  die "Invalid Location ID";
131 }
132 
133 
134 my $response = get $url;
135 die unless defined $response;
136 
137 my $xml = XMLin($response);
138 
139 if (!$xml) {
140  die "Not xml";
141 }
142 
143 printf "copyright::" . $MetOffCommon::copyright_str . "\n";
144 #printf "copyrightlogo::" . $MetOffCommon::copyright_logo . "\n";
145 printf "station_id::" . $locid . "\n";
146 my $location = $xml->{DV}->{Location}->{name};
147 printf "3dlocation::" . $location . "\n";
148 printf "6dlocation::" . $location . "\n";
149 printf "updatetime::" . localtime() . "\n";
150 
151 my $i = 0;
152 my $period;
153 
154 foreach $period (@{$xml->{DV}->{Location}->{Period}}) {
155 
156  if (ref($period->{Rep}) ne 'ARRAY') {
157  next;
158  }
159 
160  my ($ss,$mm,$hh,$day,$month,$year,$zone) = strptime($period->{value});
161  $year += 1900; # Returns year as offset from 1900
162  $month += 1; # Returns month starting at zero
163  my $dow = Day_of_Week($year,$month,$day);
164  $dow = $dow == 7 ? 0 : $dow;
165  printf "date-" . $i . "::" . $dow . "\n";
166 
167  my $daytime = $period->{Rep}[0];
168  my $nighttime = $period->{Rep}[1];
169 
170  my $iconname = "unknown";
171  switch ($daytime->{W}) { # Weather Type
172  case 0 { $iconname = "fair"; } # Clear sky
173  case 1 { $iconname = "sunny"; } # Sunny
174  case 2 { $iconname = "pcloudy"; } # Partly cloudy (night)
175  case 3 { $iconname = "pcloudy"; } # Sunny intervals
176  case 4 { $iconname = "dusthaze"; } # Dust
177  case 5 { $iconname = "fog"; } # Mist
178  case 6 { $iconname = "fog"; } # Fog
179  case 7 { $iconname = "mcloudy"; } # Medium-level cloud
180  case 8 { $iconname = "cloudy"; } # Low-level cloud
181  case 9 { $iconname = "lshowers"; } # Light rain shower (night)
182  case 10 { $iconname = "lshowers"; } # Light rain shower (day)
183  case 11 { $iconname = "lshowers"; } # Drizzle
184  case 12 { $iconname = "lshowers"; } # Light rain
185  case 13 { $iconname = "showers"; } # Heavy rain shower (night)
186  case 14 { $iconname = "showers"; } # Heavy rain shower (day)
187  case 15 { $iconname = "showers"; } # Heavy rain
188  case 16 { $iconname = "rainsnow"; } # Sleet shower (night)
189  case 17 { $iconname = "rainsnow"; } # Sleet shower (day)
190  case 18 { $iconname = "rainsnow"; } # Sleet
191  case 19 { $iconname = "rainsnow"; } # Hail shower (night)
192  case 20 { $iconname = "rainsnow"; } # Hail shower (day)
193  case 21 { $iconname = "rainsnow"; } # Hail
194  case 22 { $iconname = "flurries"; } # Light snow shower (night)
195  case 23 { $iconname = "flurries"; } # Light snow shower (day)
196  case 24 { $iconname = "flurries"; } # Light snow
197  case 25 { $iconname = "snowshow"; } # Heavy snow shower (night)
198  case 26 { $iconname = "snowshow"; } # Heavy snow shower (day)
199  case 27 { $iconname = "snowshow"; } # Heavy snow
200  case 28 { $iconname = "thunshowers"; } # Thundery shower (night)
201  case 29 { $iconname = "thunshowers"; } # Thundery shower (day)
202  case 30 { $iconname = "thunshowers"; } # Thunder storm
203  case 31 { $iconname = "thunshowers"; } # Tropical storm
204  case 33 { $iconname = "dusthaze"; } # Haze
205  }
206 
207  printf "icon-" . $i . "::" . $iconname . ".png\n";
208 
209  printf "low-" . $i . "::" . MetOffCommon::convert_temp($nighttime->{Nm}, $units) . "\n";
210  printf "high-" . $i . "::" . MetOffCommon::convert_temp($daytime->{Dm}, $units) . "\n";
211 
212  $i++;
213 }
214 
215 sub log_print {
216  return if not defined $::opt_D;
217  my $dir = shift;
218 
219  open OF, ">>$dir/uk_metoffice.log";
220  print OF @_;
221  close OF;
222 }