MythWeather

MythWeather can be installed on the later versions of Mythbuntu by selecting it from the list of plug-in applications from the Mythbuntu configuration application (either run this app from the System menu choice or run it by selecting Mythbuntu setup from the frontend setup menu. Once MythWeather is installed, setup should be easy (or so you think). A good synopsis of the vanilla part of setup is given here:

     http://www.mythtv.org/wiki/MythWeather

Fortunately, all of the code that extracts weather data from remote sites via HTTP is written in Perl so that it can be easily modified. Unfortunately, it is quite badly written. If any of the extracted weather data changes in the slightest, the Perl code craps out and the MythWeather display either hangs or shows a blank screen.

The worst offender is the NWS XML extraction module that is used to obtain current weather information from the National Weather Service -- probably the one script you're most likely to want to use. Consequently, if you want to see the current weather, you'll probably have to patch the extraction module as follows (all changes are marked with #ew):

/usr/share/mythtv/mythweather/scripts/us_nws/nwsxml.pl:

     #! /usr/bin/perl -w
     use strict;
     use XML::Simple;
     use LWP::Simple;
     use Data::Dumper;
     use Getopt::Std;
     use NWSLocation;
     our ($opt_v, $opt_t, $opt_T, $opt_l, $opt_u, $opt_d); 
     my $name = 'NWS-XML';
     my $version = 0.2;
     my $author = 'Lucien Dunning';
     my $email = 'ldunning@gmail.com';
     my $updateTimeout = 15*60;
     my $retrieveTimeout = 30;
     my @types = ('cclocation', 'station_id', 'latitude', 'longitude',
             'observation_time', 'observation_time_rfc822', 'weather',
             'temperature_string', 'temp', 'relative_humidity', 'wind_string',
             'wind_dir', 'wind_degrees', 'wind_speed', 'wind_gust',
             'pressure_string', 'pressure', 'dewpoint_string', 'dewpoint',
             'heat_index_string', 'heat_index', 'windchill_string', 'windchill',
             'visibility', 'weather_icon', 'appt', 'wind_spdgst');
     my $dir = "./";
     getopts('Tvtlu:d:');
     if (defined $opt_v) {
         print "$name,$version,$author,$email\n";
         exit 0;
     }
     if (defined $opt_T) {
         print "$updateTimeout,$retrieveTimeout\n";
         exit 0;
     }
     if (defined $opt_l) {
         my $search = shift;
         NWSLocation::AddLocSearch($search);
         NWSLocation::AddStateSearch($search);
         NWSLocation::AddStationIdSearch($search);
         my $results = doSearch();
         my $result;
         while($result = shift @$results) {
             if ($result->{latitude} ne "NA" && $result->{longitude} ne "NA") {
                 print "$result->{station_id}::";
                 print "$result->{station_name}, $result->{state}\n";
             }
         }
      exit 0;
     }
     if (defined $opt_t) {
         foreach (@types) {print; print "\n";}
         exit 0;
     }
     if (defined $opt_d) {
         $dir = $opt_d;
     }
     # we get here, we're doing an actual retrieval, everything must be defined
     my $loc = shift;
     if (!(defined $opt_u && defined $loc && !$loc eq "")) {
         die "Invalid usage";
     }
     my $units = $opt_u;
     my $base_url = 'http://www.weather.gov/data/current_obs/';
     my $response = get $base_url . $loc . '.xml';
     die unless defined $response;
     my $xml = XMLin($response);
     foreach (@types) {
         my $label;
         my $key;
      $label = $_;
      if (/temp$/ || /dewpoint$/ || /heat_index$/ || /windchill$/) {
          $key = $ . 'f' if $units =~ /ENG/;
          $key = $ . 'c' if $units =~ /SI/;
      }
      elsif (/pressure$/) {
          $key = $ . 'in' if $units =~ /ENG/;
          $key = $ . 'mb' if $units =~ /SI/;
      }
      elsif (/wind_speed/) {
          if ($units =~ /ENG/) {
              $key = 'wind_mph';
          } else {
              $key = 'wind_kph';
              $xml->{$key} = int($xml->{'wind_mph'} * 1.609344 + .5);
          }
      } elsif (/wind_gust/) {
          if ($units =~ /ENG/ || $xml->{'wind_gust_mph'} eq 'NA') {
              $key = 'wind_gust_mph';
          } else {
              $key = 'wind_gust_kph';
              $xml->{$key} = int($xml->{'wind_gust_mph'} * 1.609344 + .5);
          }
      } elsif (/visibility/) {
          if ($units =~ /ENG/) {
              $key = 'visibility_mi';
          } else {
              $key = 'visibility_km';
              $xml->{$key} = int($xml->{'visibility_mi'} * 1.609344 + .5);
          }
      } elsif (/weather_icon/) {
          $key = 'weather_icon';
          $xml->{$key} = 'unknown.png';
          local FH;
          open(FH, "icons") or die "Cannot open icons";
          while(my $line = <FH>) {
              chomp $line;
              if ($line =~ /$xml->{'icon_url_name'}::/) {
                  $line =~ s/.:://;
                  $xml->{$key} = $line;
                  last;
              }
          }
      } elsif (/cclocation/) {
          $key = 'location';   
      } elsif (/appt$/) {
  #ew        if ($xml->{windchill_f} eq 'NA') {
          if (!defined($xml->{windchill_f}) || $xml->{windchill_f} eq 'NA') { #ew
              $key = 'heat_index_f' if ($units =~ /ENG/); 
              $key = 'heat_index_c' if ($units =~ /SI/);
          } else { 
              $key = 'windchill_f' if ($units =~ /ENG/); 
              $key = 'windchill_c' if ($units =~ /SI/);
          };
      
      } elsif (/wind_spdgst/) {
          # relying on this being after speed and gust
          $key = "wind_spdgst";
          if ($units =~ /ENG/ ) {
              if (defined($xml->{"wind_gust_mph"})) { #ew
                  $xml->{$key} = "$xml->{wind_mph} ($xml->{wind_gust_mph})"; #ew
              } else { #ew
                  $xml->{$key} = "$xml->{wind_mph} ($xml->{wind_mph})"; #ew
                  } #ew
          } else {
              if (defined($xml->{"wind_gust_kph"})) { #ew
                  $xml->{$key} = "$xml->{wind_kph} ($xml->{wind_gust_kph})"; #ew
              } else { #ew
                  $xml->{$key} = "$xml->{wind_kph} ($xml->{wind_kph})"; #ew
                  } #ew
          }
      } else {
          $key = $label;
      }
      if (defined($xml->{$key})) { #ew
          printf $label . "::" . $xml->{$key}. "\n";
      } #ew
      else { #ew
          if ($label =~ /string/i) { #ew
              printf $label . "::none\n"; #ew
          } #ew
          else { #ew
              printf $label . "::" . #ew
                  (($units =~ /ENG/) ? $xml->{"temp_f"} : $xml->{"temp_c"}) . #ew
                  "\n"; #ew
          } #ew
      } #ew

}

Once you install this copy of the script in the scripts directory:

     /usr/share/mythtv/mythweather/scripts/us_nws

You should make sure the permissions on nwsxml.pl look like this:

     -rwxr-xr-x 1 root root   4868 2009-09-11 21:51 nwsxml.pl

This will allow MythWeather to execute the script to extract weather data from the NWS. You should now be able to include the Current Conditions page in the list of pages to be shown by MythWeather.