00001 #! /usr/bin/perl
00002 # vim:ts=4:sw=4:ai:et:si:sts=4
00003
00004 use strict;
00005 use warnings;
00006
00007 use utf8;
00008 use encoding 'utf8';
00009 use English;
00010
00011 use File::Basename;
00012 use Cwd 'abs_path';
00013 use lib dirname(abs_path($0 or $PROGRAM_NAME)),
00014 '/usr/share/mythtv/mythweather/scripts/uk_bbc',
00015 '/usr/local/share/mythtv/mythweather/scripts/uk_bbc';
00016
00017 use XML::Simple;
00018 use LWP::Simple;
00019 use Getopt::Std;
00020 use File::Path;
00021
00022 use File::Basename;
00023 use lib dirname($0);
00024 use BBCLocation;
00025
00026 our ($opt_v, $opt_t, $opt_T, $opt_l, $opt_u, $opt_d, $opt_D);
00027
00028 my $name = 'BBC-Current-XML';
00029 my $version = 0.3;
00030 my $author = 'Gavin Hurlbut / Stuart Morgan';
00031 my $email = 'gjhurlbu@gmail.com / stuart@tase.co.uk';
00032 my $updateTimeout = 120*60;
00033 # 2 Hours, BBC updates infrequently ~3 hours
00034 my $retrieveTimeout = 30;
00035 my @types = ('cclocation', 'station_id', 'copyright',
00036 'observation_time', 'weather', 'temp', 'relative_humidity',
00037 'wind_dir', 'pressure', 'visibility', 'weather_icon',
00038 'appt', 'wind_spdgst');
00039 my $dir = "/tmp/uk_bbc";
00040 my $logdir = "/tmp/uk_bbc";
00041
00042 binmode(STDOUT, ":utf8");
00043
00044 if (!-d $logdir) {
00045 mkpath( $logdir, {mode => 0755} );
00046 }
00047
00048 getopts('Tvtlu:d:');
00049
00050 if (defined $opt_v) {
00051 print "$name,$version,$author,$email\n";
00052 log_print( $logdir, "-v\n" );
00053 exit 0;
00054 }
00055
00056 if (defined $opt_T) {
00057 print "$updateTimeout,$retrieveTimeout\n";
00058 log_print( $logdir, "-t\n" );
00059 exit 0;
00060 }
00061
00062 if (defined $opt_d) {
00063 $dir = $opt_d;
00064 }
00065
00066 if (!-d $dir) {
00067 mkpath( $dir, {mode => 0755} );
00068 }
00069
00070 if (defined $opt_l) {
00071 my $search = shift;
00072 log_print( $logdir, "-l $search\n" );
00073 my @results = BBCLocation::Search($search, $dir, $updateTimeout, $logdir);
00074 my $result;
00075
00076 foreach (@results) {
00077 print $_ . "\n";
00078 }
00079
00080 exit 0;
00081 }
00082
00083 if (defined $opt_t) {
00084 foreach (@types) {print; print "\n";}
00085 exit 0;
00086 }
00087
00088
00089 # we get here, we're doing an actual retrieval, everything must be defined
00090 my $locid = BBCLocation::FindLoc(shift, $dir, $updateTimeout, $logdir);
00091 if (!(defined $opt_u && defined $locid && !$locid eq "")) {
00092 die "Invalid usage";
00093 }
00094
00095 my $units = $opt_u;
00096 my $base_url = 'http://newsrss.bbc.co.uk/weather/forecast/';
00097 my $base_xml = '/ObservationsRSS.xml';
00098
00099 if ($locid =~ s/^(\d*)/$1/)
00100 {
00101 $base_url = $base_url . $1 .$base_xml;
00102 }
00103 else
00104 {
00105 die "Invalid Location ID";
00106 }
00107
00108 my $response = get $base_url;
00109 die unless defined $response;
00110
00111 my $xml = XMLin($response);
00112
00113 if (!$xml) {
00114 die "Not xml";
00115 }
00116
00117 # The required elements which aren't provided by this feed
00118 printf "appt::NA\n";
00119
00120 printf "copyright::From bbc.co.uk\n";
00121 printf "station_id::" . $locid . "\n";
00122 my $location = $xml->{channel}->{title};
00123 $location =~ s/.*?Observations for (.*)$/$1/s;
00124 printf "cclocation::" . $location . "\n";
00125
00126 my $item_title = $xml->{channel}->{item}->{title};
00127
00128 my $obs_time = $1 if ($item_title =~ /(^.*)\:.*/);
00129 printf "observation_time::" . $obs_time . "\n";
00130 my $weather_string = $item_title;
00131
00132 $weather_string =~ s/.*\:.*\n(.*)\..*/$1/s;
00133 $weather_string = ucfirst($weather_string);
00134 printf "weather::" . $weather_string . "\n";
00135
00136 if ($weather_string =~ /^cloudy$/i ||
00137 $weather_string =~ /^grey cloud$/i ||
00138 $weather_string =~ /^white cloud$/i) {
00139 printf "weather_icon::cloudy.png\n";
00140 }
00141 elsif ($weather_string =~ /^fog$/i ||
00142 $weather_string =~ /^foggy$/i ||
00143 $weather_string =~ /^mist$/i ||
00144 $weather_string =~ /^misty$/i) {
00145 printf "weather_icon::fog.png\n";
00146 }
00147 elsif ($weather_string =~ /^sunny$/i) {
00148 printf "weather_icon::sunny.png\n";
00149 }
00150 elsif ($weather_string =~ /^sunny intervals$/i ||
00151 $weather_string =~ /^partly cloudy$/i) {
00152 printf "weather_icon::pcloudy.png\n";
00153 }
00154 elsif ($weather_string =~ /^drizzle$/i ||
00155 $weather_string =~ /^light rain$/i ||
00156 $weather_string =~ /^light rain showers?$/i ||
00157 $weather_string =~ /^light showers?$/i) {
00158 printf "weather_icon::lshowers.png\n";
00159 }
00160 elsif ($weather_string =~ /^heavy rain$/i ||
00161 $weather_string =~ /^heavy showers?$/i ||
00162 $weather_string =~ /^heavy rain showers?$/i) {
00163 printf "weather_icon::showers.png\n";
00164 }
00165 elsif ($weather_string =~ /^thundery rain$/i ||
00166 $weather_string =~ /^thunder storm$/i ||
00167 $weather_string =~ /^thundery showers?$/i) {
00168 printf "weather_icon::thunshowers.png\n";
00169 }
00170 elsif ($weather_string =~ /^heavy snow$/i) {
00171 printf "weather_icon::snowshow.png\n";
00172 }
00173 elsif ($weather_string =~ /^light snow$/i ||
00174 $weather_string =~ /^light snow showers?$/i) {
00175 printf "weather_icon::flurries.png\n";
00176 }
00177 elsif ($weather_string =~ /^sleet$/i ||
00178 $weather_string =~ /^sleet showers?$/i ||
00179 $weather_string =~ /^hail showers?$/i) {
00180 printf "weather_icon::rainsnow.png\n";
00181 }
00182 elsif ($weather_string =~ /^clear$/i ||
00183 $weather_string =~ /^clear sky$/i) {
00184 printf "weather_icon::fair.png\n";
00185 }
00186 else {
00187 printf "weather_icon::unknown.png\n";
00188 }
00189
00190 my @data = split(/, /, $xml->{channel}->{item}->{description});
00191 foreach (@data) {
00192 my $datalabel;
00193 my $datavalue;
00194
00195 ($datalabel, $datavalue) = split(': ', $_);
00196 if ($datalabel =~ /Temperature/) {
00197 if ($units =~ /ENG/) {
00198 $datavalue =~ s/^.*?\((-?\d{1,2}).*/$1/;
00199 }
00200 elsif ($units =~ /SI/) {
00201 $datavalue =~ s/^(-?\d{1,2}).*/$1/;
00202 }
00203 $datalabel = "temp";
00204 }
00205 elsif ($datalabel =~ /Wind Direction/) {
00206 $datalabel = "wind_dir";
00207 }
00208 elsif ($datalabel =~ /Wind Speed/) {
00209 $datalabel = "wind_spdgst";
00210 $datavalue =~ s/^(\d{1,3})mph.*/$1/;
00211
00212 if ($units =~ /SI/) {
00213 $datavalue = int($datavalue * 1.609344 + .5);
00214 }
00215
00216 $datavalue = $datavalue . " (NA)";
00217 }
00218 elsif ($datalabel =~ /Relative Humidity/) {
00219 $datalabel = "relative_humidity";
00220 $datavalue =~ s/^(\d{1,3})%.*?/$1/;
00221 }
00222 elsif ($datalabel =~ /Pressure/) {
00223 $datavalue =~ s/^(\d*)mB.*?/$1/;
00224
00225 if ($units =~ /ENG/) {
00226 $datavalue = $datavalue * 0.0295301 + .5;
00227 }
00228
00229 $datalabel = "pressure";
00230 }
00231 elsif ($datalabel =~ /Visibility/) {
00232 $datalabel = "visibility";
00233 if ($datavalue =~ /^Very Poor/i) {
00234 $datavalue = "< 1";
00235 }
00236 elsif ($datavalue =~ /^Poor/i) {
00237 $datavalue = "1-4";
00238 }
00239 elsif ($datavalue =~ /^Moderate/i) {
00240 $datavalue = "4-10";
00241 }
00242 elsif ($datavalue =~ /^Good/i) {
00243 $datavalue = "10-20";
00244 }
00245 elsif ($datavalue =~ /^Very Good/i) {
00246 $datavalue = "20-40";
00247 }
00248 elsif ($datavalue =~ /^Excellent/i) {
00249 $datavalue = "40+";
00250 }
00251 else {
00252 $datavalue = "?";
00253 }
00254 }
00255 else {
00256 next;
00257 }
00258
00259 printf $datalabel . "::" . $datavalue . "\n";
00260 }
00261
00262 sub log_print {
00263 return if not defined $::opt_D;
00264 my $dir = shift;
00265
00266 open OF, ">>$dir/uk_bbc.log";
00267 print OF @_;
00268 close OF;
00269 }