00001 #! /usr/bin/perl -w
00002
00003 #
00004 # Based on nwsxml.pl by Lucien Dunning
00005 #
00006
00007 use strict;
00008 use XML::Simple;
00009 use LWP::Simple;
00010 # Ideally we would use the If-Modified-Since header
00011 # to reduce server load, but they ignore it
00012 #use HTTP::Cache::Transparent;
00013 use Getopt::Std;
00014 use File::Basename;
00015 use lib dirname($0);
00016 use BBCLocation;
00017
00018 our ($opt_v, $opt_t, $opt_T, $opt_l, $opt_u, $opt_d);
00019
00020 my $name = 'BBC-Current-XML';
00021 my $version = 0.1;
00022 my $author = 'Stuart Morgan';
00023 my $email = 'stuart@tase.co.uk';
00024 my $updateTimeout = 120*60;
00025 # 2 Hours, BBC updates infrequently ~3 hours
00026 # Given that the option to update in the background now exists
00027 # potentially we could be hitting the server 12 times in a day
00028 my $retrieveTimeout = 30;
00029 my @types = ('cclocation', 'station_id', 'copyright',
00030 'observation_time', 'weather', 'temp', 'relative_humidity',
00031 'wind_dir', 'pressure', 'visibility', 'weather_icon',
00032 'appt', 'wind_spdgst');
00033 my $dir = "./";
00034
00035 getopts('Tvtlu:d:');
00036
00037 if (defined $opt_v) {
00038 print "$name,$version,$author,$email\n";
00039 exit 0;
00040 }
00041
00042 if (defined $opt_T) {
00043 print "$updateTimeout,$retrieveTimeout\n";
00044 exit 0;
00045 }
00046
00047 if (defined $opt_l) {
00048
00049 my $search = shift;
00050 my @results = BBCLocation::Search($search);
00051 my $result;
00052
00053 foreach (@results) {
00054 print $_ . "\n";
00055 }
00056
00057 exit 0;
00058 }
00059
00060 if (defined $opt_t) {
00061 foreach (@types) {print; print "\n";}
00062 exit 0;
00063 }
00064
00065 if (defined $opt_d) {
00066 $dir = $opt_d;
00067 }
00068
00069
00070 # we get here, we're doing an actual retrieval, everything must be defined
00071 my $locid = shift;
00072 if (!(defined $opt_u && defined $locid && !$locid eq "")) {
00073 die "Invalid usage";
00074 }
00075
00076 my $units = $opt_u;
00077 my $base_url;
00078
00079 my $local_base_url = 'http://feeds.bbc.co.uk/weather/feeds/rss/obs/id/';
00080 my $world_base_url = 'http://feeds.bbc.co.uk/weather/feeds/rss/obs/world/';
00081
00082 if ($locid =~ s/^W(.*)/$1/)
00083 {
00084 $base_url = $world_base_url;
00085 }
00086 elsif ($locid =~ s/^L(.*)/$1/)
00087 {
00088 $base_url = $local_base_url;
00089 }
00090 else
00091 {
00092 die "Invalid Location ID";
00093 }
00094
00095 my $response = get $base_url . $locid . '.xml';
00096 die unless defined $response;
00097
00098 my $xml = XMLin($response);
00099
00100 if (!$xml) {
00101 die "Not xml";
00102 }
00103
00104 # The required elements which aren't provided by this feed
00105 printf "appt::NA\n";
00106
00107 printf "copyright::From bbc.co.uk\n";
00108 printf "station_id::" . $locid . "\n";
00109 my $location = $xml->{channel}->{title};
00110 $location =~ s/.*?Observations for (.*)$/$1/s;
00111 printf "cclocation::" . $location . "\n";
00112
00113 my $item_title = $xml->{channel}->{item}->{title};
00114 $item_title =~ s/\n
00115
00116 my $obs_time = $item_title;
00117 $obs_time =~ s/^(.*?)\:.*/$1/s;
00118 printf "observation_time::" . $obs_time . "\n";
00119 my $weather_string = $item_title;
00120 $weather_string =~ s/.*?\: (.*?)\..*/$1/s;
00121 $weather_string = ucfirst($weather_string);
00122 printf "weather::" . $weather_string . "\n";
00123
00124 if ($weather_string =~ /^cloudy$/i) {
00125 printf "weather_icon::cloudy.png\n";
00126 }
00127 elsif ($weather_string =~ /^foggy$/i ||
00128 $weather_string =~ /^misty$/i) {
00129 printf "weather_icon::fog.png\n";
00130 }
00131 elsif ($weather_string =~ /^sunny$/i) {
00132 printf "weather_icon::sunny.png\n";
00133 }
00134 elsif ($weather_string =~ /^sunny intervals$/i ||
00135 $weather_string =~ /^partly cloudy$/i) {
00136 printf "weather_icon::pcloudy.png\n";
00137 }
00138 elsif ($weather_string =~ /^drizzle$/i ||
00139 $weather_string =~ /^light rain$/i ||
00140 $weather_string =~ /^light showers$/i) {
00141 printf "weather_icon::lshowers.png\n";
00142 }
00143 elsif ($weather_string =~ /^heavy rain$/i ||
00144 $weather_string =~ /^heavy showers$/i) {
00145 printf "weather_icon::showers.png\n";
00146 }
00147 elsif ($weather_string =~ /^thundery rain$/i ||
00148 $weather_string =~ /^thundery showers$/i) {
00149 printf "weather_icon::thunshowers.png\n";
00150 }
00151 elsif ($weather_string =~ /^heavy snow$/i) {
00152 printf "weather_icon::snowshow.png\n";
00153 }
00154 elsif ($weather_string =~ /^light snow$/i ||
00155 $weather_string =~ /^light snow showers$/i) {
00156 printf "weather_icon::flurries.png\n";
00157 }
00158 elsif ($weather_string =~ /^sleet$/i ||
00159 $weather_string =~ /^sleet showers$/i ||
00160 $weather_string =~ /^hail showers$/i) {
00161 printf "weather_icon::rainsnow.png\n";
00162 }
00163 elsif ($weather_string =~ /^clear$/i) {
00164 printf "weather_icon::fair.png\n";
00165 }
00166 else {
00167 printf "weather_icon::unknown.png\n";
00168 }
00169
00170 my @data = split(/, /, $xml->{channel}->{item}->{description});
00171 foreach (@data) {
00172 my $datalabel;
00173 my $datavalue;
00174
00175 ($datalabel, $datavalue) = split(': ', $_);
00176 if ($datalabel =~ /Temperature/) {
00177 if ($units =~ /ENG/) {
00178 $datavalue =~ s/^.*?\((-?\d{1,2}).*/$1/;
00179 }
00180 elsif ($units =~ /SI/) {
00181 $datavalue =~ s/^(-?\d{1,2}).*/$1/;
00182 }
00183 $datalabel = "temp";
00184 }
00185 elsif ($datalabel =~ /Wind Direction/) {
00186 $datalabel = "wind_dir";
00187 }
00188 elsif ($datalabel =~ /Wind Speed/) {
00189 $datalabel = "wind_spdgst";
00190 $datavalue =~ s/^(\d{1,3}) mph.*/$1/;
00191
00192 if ($units =~ /SI/) {
00193 $datavalue = int($datavalue * 1.609344 + .5);
00194 }
00195
00196 $datavalue = $datavalue . " (NA)";
00197 }
00198 elsif ($datalabel =~ /Relative Humidity/) {
00199 $datalabel = "relative_humidity";
00200 $datavalue =~ s/^(\d{1,3})%.*?/$1/;
00201 }
00202 elsif ($datalabel =~ /Pressure/) {
00203 $datavalue =~ s/^(\d*)mB.*?/$1/;
00204
00205 if ($units =~ /ENG/) {
00206 $datavalue = $datavalue * 0.0295301 + .5;
00207 }
00208
00209 $datalabel = "pressure";
00210 }
00211 elsif ($datalabel =~ /Visibility/) {
00212 $datalabel = "visibility";
00213 if ($datavalue =~ /^Very Poor/i) {
00214 $datavalue = "< 1";
00215 }
00216 elsif ($datavalue =~ /^Poor/i) {
00217 $datavalue = "1-4";
00218 }
00219 elsif ($datavalue =~ /^Moderate/i) {
00220 $datavalue = "4-10";
00221 }
00222 elsif ($datavalue =~ /^Good/i) {
00223 $datavalue = "10-20";
00224 }
00225 elsif ($datavalue =~ /^Very Good/i) {
00226 $datavalue = "20-40";
00227 }
00228 elsif ($datavalue =~ /^Excellent/i) {
00229 $datavalue = "40+";
00230 }
00231 else {
00232 $datavalue = "?";
00233 }
00234 }
00235 else {
00236 next;
00237 }
00238
00239 printf $datalabel . "::" . $datavalue . "\n";
00240 }