# $Id$ ############################################################################## # # 59_Weather.pm # Copyright by Dr. Boris Neubert # e-mail: omega at online dot de # # This file is part of fhem. # # Fhem is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # Fhem is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with fhem. If not, see . # ############################################################################## package main; use strict; use warnings; use Time::HiRes qw(gettimeofday); use HttpUtils; use vars qw($FW_ss); use Blocking; # # uses the Yahoo! Weather API: http://developer.yahoo.com/weather/ # # Mapping / translation of current weather codes 0-47 my @YahooCodes_en = ( 'tornado', 'tropical storm', 'hurricane', 'severe thunderstorms', 'thunderstorms', 'mixed rain and snow', 'mixed rain and sleet', 'mixed snow and sleet', 'freezing drizzle', 'drizzle', 'freezing rain' ,'showers', 'showers', 'snow flurries', 'light snow showers', 'blowing snow', 'snow', 'hail', 'sleet', 'dust', 'foggy', 'haze', 'smoky', 'blustery', 'windy', 'cold', 'cloudy', 'mostly cloudy', # night 'mostly cloudy', # day 'partly cloudy', # night 'partly cloudy', # day 'clear', 'sunny', 'fair', #night 'fair', #day 'mixed rain and hail', 'hot', 'isolated thunderstorms', 'scattered thunderstorms', 'scattered thunderstorms', 'scattered showers', 'heavy snow', 'scattered snow showers', 'heavy snow', 'partly cloudy', 'thundershowers', 'snow showers', 'isolated thundershowers'); my @YahooCodes_de = ( 'Tornado', 'schwerer Sturm', 'Orkan', 'schwere Gewitter', 'Gewitter', 'Regen und Schnee', 'Regen und Graupel', 'Schnee und Graupel', 'Eisregen', 'Nieselregen', 'gefrierender Regen' ,'Schauer', 'Schauer', 'Schneetreiben', 'leichte Schneeschauer', 'Schneeverwehungen', 'Schnee', 'Hagel', 'Graupel', 'Staub', 'Nebel', 'Dunst', 'Smog', 'Sturm', 'windig', 'kalt', 'wolkig', 'überwiegend wolkig', # night 'überwiegend wolkig', # day 'teilweise wolkig', # night 'teilweise wolkig', # day 'klar', # night 'sonnig', 'heiter', # night 'heiter', # day 'Regen und Hagel', 'heiß', 'einzelne Gewitter', 'vereinzelt Gewitter', 'vereinzelt Gewitter', 'vereinzelt Schauer', 'starker Schneefall', 'vereinzelt Schneeschauer', 'starker Schneefall', 'teilweise wolkig', 'Gewitterregen', 'Schneeschauer', 'vereinzelt Gewitter'); my @YahooCodes_nl = ( 'tornado', 'zware storm', 'orkaan', 'hevig onweer', 'onweer', 'regen en sneeuw', 'regen en ijzel', 'sneeuw en ijzel', 'aanvriezende motregen', 'motregen', 'aanvriezende regen' ,'buien', 'buien', 'sneeuw windstoten', 'lichte sneeuwbuien', 'stuifsneeuw', 'sneeuw', 'hagel', 'ijzel', 'stof', 'mist', 'waas', 'smog', 'heftig', 'winderig', 'koud', 'bewolkt', 'overwegend bewolkt', # night 'overwegend bewolkt', # day 'gedeeltelijk bewolkt', # night 'gedeeltelijk bewolkt', # day 'helder', #night 'zonnig', 'mooi', #night 'mooi', #day 'regen en hagel', 'heet', 'plaatselijk onweer', 'af en toe onweer', 'af en toe onweer', 'af en toe regenbuien', 'hevige sneeuwval', 'af en toe sneeuwbuien', 'hevige sneeuwval', 'deels bewolkt', 'onweersbuien', 'sneeuwbuien', 'af en toe onweersbuien'); my %pressure_trend_txt_en = ( 0 => "steady", 1 => "rising", 2 => "falling" ); my %pressure_trend_txt_de = ( 0 => "gleichbleibend", 1 => "steigend", 2 => "fallend" ); my %pressure_trend_txt_nl = ( 0 => "stabiel", 1 => "stijgend", 2 => "dalend" ); my %pressure_trend_sym = ( 0 => "=", 1 => "+", 2 => "-" ); my @directions_txt_en = ('N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW'); my @directions_txt_de = ('N', 'NNO', 'NO', 'ONO', 'O', 'OSO', 'SO', 'SSO', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW'); my @directions_txt_nl = ('N', 'NNO', 'NO', 'ONO', 'O', 'OZO', 'ZO', 'ZZO', 'Z', 'ZZW', 'ZW', 'WZW', 'W', 'WNW', 'NW', 'NNW'); my %wdays_txt_en = ('Mon' => 'Mon', 'Tue' => 'Tue', 'Wed'=> 'Wed', 'Thu' => 'Thu', 'Fri' => 'Fri', 'Sat' => 'Sat', 'Sun' => 'Sun'); my %wdays_txt_de = ('Mon' => 'Mo', 'Tue' => 'Di', 'Wed'=> 'Mi', 'Thu' => 'Do', 'Fri' => 'Fr', 'Sat' => 'Sa', 'Sun' => 'So'); my %wdays_txt_nl = ('Mon' => 'Maa', 'Tue' => 'Din', 'Wed'=> 'Woe', 'Thu' => 'Don', 'Fri' => 'Vri', 'Sat' => 'Zat', 'Sun' => 'Zon'); my @iconlist = ( 'storm', 'storm', 'storm', 'thunderstorm', 'thunderstorm', 'rainsnow', 'sleet', 'snow', 'drizzle', 'drizzle', 'icy' ,'chance_of_rain', 'chance_of_rain', 'snowflurries', 'chance_of_snow', 'heavysnow', 'snow', 'sleet', 'sleet', 'dust', 'fog', 'haze', 'smoke', 'flurries', 'windy', 'icy', 'cloudy', 'mostlycloudy_night', 'mostlycloudy', 'partly_cloudy_night', 'partly_cloudy', 'sunny', 'sunny', 'mostly_clear_night', 'mostly_sunny', 'heavyrain', 'sunny', 'scatteredthunderstorms', 'scatteredthunderstorms', 'scatteredthunderstorms', 'scatteredshowers', 'heavysnow', 'chance_of_snow', 'heavysnow', 'partly_cloudy', 'heavyrain', 'chance_of_snow', 'scatteredshowers'); ################################### sub Weather_DebugCodes() { Debug "Weather Code List, see http://developer.yahoo.com/weather/#codes"; for(my $c= 0; $c<= 47; $c++) { Debug sprintf("%2d %30s %30s %30s %30s", $c, $iconlist[$c], $YahooCodes_en[$c], $YahooCodes_de[$c], $YahooCodes_nl[$c]); } } ##################################### sub Weather_Initialize($) { my ($hash) = @_; $hash->{DefFn} = "Weather_Define"; $hash->{UndefFn} = "Weather_Undef"; $hash->{GetFn} = "Weather_Get"; $hash->{SetFn} = "Weather_Set"; $hash->{AttrList}= "localicons ". $readingFnAttributes; #Weather_DebugCodes(); } ################################### sub latin1_to_utf8($) { # http://perldoc.perl.org/perluniintro.html, UNICODE IN OLDER PERLS my ($s)= @_; $s =~ s/([\x80-\xFF])/chr(0xC0|ord($1)>>6).chr(0x80|ord($1)&0x3F)/eg; return $s; } ################################### sub temperature_in_c($$) { my ($temperature, $unitsystem)= @_; return $unitsystem ne "SI" ? int(($temperature-32)*5/9+0.5) : $temperature; } sub wind_in_km_per_h($$) { my ($wind, $unitsystem)= @_; return $unitsystem ne "SI" ? int(1.609344*$wind+0.5) : $wind; } sub degrees_to_direction($@) { my ($degrees,@directions_txt_i18n) = @_; my $mod = int((($degrees + 11.25) % 360) / 22.5); return $directions_txt_i18n[$mod]; } ################################### sub Weather_UpdateReading($$$$) { my ($hash,$prefix,$key,$value)= @_; #Debug "DEBUG WEATHER: $prefix $key $value"; my $unitsystem= $hash->{READINGS}{unit_system}{VAL}; if($key eq "low") { $key= "low_c"; $value= temperature_in_c($value,$unitsystem); } elsif($key eq "high") { $key= "high_c"; $value= temperature_in_c($value,$unitsystem); } elsif($key eq "humidity") { # standardize reading - allow generic logging of humidity. $value=~ s/.*?(\d+).*/$1/; # extract numeric } my $reading= $prefix . $key; readingsBulkUpdate($hash,$reading,$value); if($reading eq "temp_c") { readingsBulkUpdate($hash,"temperature",$value); # additional entry for compatibility } if($reading eq "wind_condition") { $value=~ s/.*?(\d+).*/$1/; # extract numeric readingsBulkUpdate($hash,"wind",wind_in_km_per_h($value,$unitsystem)); # additional entry for compatibility } return 1; } ################################### sub Weather_RetrieveData($$) { my ($name, $blocking) = @_; my $hash = $defs{$name}; my $location= $hash->{LOCATION}; # WOEID [WHERE-ON-EARTH-ID], go to http://weather.yahoo.com to find out my $units= $hash->{UNITS}; my $url = "http://weather.yahooapis.com/forecastrss?w=" . $location . "&u=" . $units; if ($blocking) { #my $response = GetFileFromURL($url, 5, undef, 0); my $response = HttpUtils_BlockingGet( { url => $url, timeout => 5, #noshutdown => 0, } ); my %param = (hash => $hash, doTrigger => 0); Weather_RetrieveDataFinished(\%param, undef, $response); } else { HttpUtils_NonblockingGet( { url => $url, timeout => 5, #noshutdown => 0, hash => $hash, doTrigger => 1, callback => \&Weather_RetrieveDataFinished, } ); } } sub Weather_RetrieveDataFinished($$$) { my ( $param, $err, $xml ) = @_; my $hash = $param->{hash}; my $doTrigger = $param->{doTrigger}; my $name = $hash->{NAME}; my $urlResult; if (defined($xml) && $xml ne "") { my $fc = undef; my $lang= $hash->{LANG}; my @YahooCodes_i18n; my %wdays_txt_i18n; my @directions_txt_i18n; my %pressure_trend_txt_i18n; if($lang eq "de") { @YahooCodes_i18n= @YahooCodes_de; %wdays_txt_i18n= %wdays_txt_de; @directions_txt_i18n= @directions_txt_de; %pressure_trend_txt_i18n= %pressure_trend_txt_de; } elsif($lang eq "nl") { @YahooCodes_i18n= @YahooCodes_nl; %wdays_txt_i18n= %wdays_txt_nl; @directions_txt_i18n= @directions_txt_nl; %pressure_trend_txt_i18n= %pressure_trend_txt_nl; } else { @YahooCodes_i18n= @YahooCodes_en; %wdays_txt_i18n= %wdays_txt_en; @directions_txt_i18n= @directions_txt_en; %pressure_trend_txt_i18n= %pressure_trend_txt_en; } foreach my $l (split("<",$xml)) { #Debug "DEBUG WEATHER: line=\"$l\""; next if($l eq ""); # skip empty lines $l =~ s/(\/|\?)?>$//; # strip off /> and > my ($tag,$value)= split(" ", $l, 2); # split tag data=..... at the first blank next if(!defined($tag) || ($tag !~ /^yweather:/)); $fc= 0 if($tag eq "yweather:condition"); $fc++ if($tag eq "yweather:forecast"); my $prefix= $fc ? "fc" . $fc ."_" : ""; ### location if ($tag eq "yweather:location" ) { $value =~/city="(.*?)" .*country="(.*?)".*/; my $loc = ""; $loc = $1 if (defined($1)); $loc .= ", $2" if (defined($2)); $urlResult->{"readings"}->{"city"} = $loc; } ### current condition and forecast if (($tag eq "yweather:condition" ) || ($tag eq "yweather:forecast" )) { my $code = (($value =~/code="([0-9]*?)".*/) ? $1 : undef); if(defined($code)) { $urlResult->{"readings"}->{$prefix . "code"} = $code; my $text = $YahooCodes_i18n[$code]; if ($text) { $urlResult->{"readings"}->{$prefix . "condition"} = $text; } #### add icon logic here - generate from code $text = $iconlist[$code]; $urlResult->{"readings"}->{$prefix . "icon"} = $text if ($text); } } ### current condition if ($tag eq "yweather:condition" ) { my $temp = (($value =~/temp="(-?[0-9.]*?)".*/) ? $1 : undef); if(defined($temp)) { $urlResult->{"readings"}->{"temperature"} = $temp; $urlResult->{"readings"}->{"temp_c"} = $temp; $temp = int(( $temp * 9 / 5 ) + 32.5); # Celsius to Fahrenheit $urlResult->{"readings"}->{"temp_f"} = $temp; } my $datum = (($value =~/date=".*? ([0-9].*)".*/) ? $1 : undef); $urlResult->{"readings"}->{"current_date_time"} = $datum if (defined($1)); my $day = (($value =~/date="(.*?), .*/) ? $1 : undef); if(defined($day)) { $urlResult->{"readings"}->{"day_of_week"} = $wdays_txt_i18n{$day}; } } ### forecast if ($tag eq "yweather:forecast" ) { my $low_c = (($value =~/low="(-?[0-9.]*?)".*/) ? $1 : undef); if(defined($low_c)) { $urlResult->{"readings"}->{$prefix . "low_c"} = $low_c; } my $high_c = (($value =~/high="(-?[0-9.]*?)".*/) ? $1 : undef); if(defined($low_c)) { $urlResult->{"readings"}->{$prefix . "high_c"} = $high_c; } my $day1 = (($value =~/day="(.*?)" .*/) ? $1 : undef); # forecast if(defined($day1)) { $urlResult->{"readings"}->{$prefix . "day_of_week"} = $wdays_txt_i18n{$day1}; } } ### humidiy / Pressure if ($tag eq "yweather:atmosphere" ) { $value =~/humidity="([0-9.]*?)" .*visibility="([0-9.]*?|\s*?)" .*pressure="([0-9.]*?)" .*rising="([0-9.]*?)" .*/; if ($1) { $urlResult->{"readings"}->{"humidity"} = $1; } my $vis = (($2 eq "") ? " " : int($2+0.5)); # clear visibility field $urlResult->{"readings"}->{"visibility"} = $vis; if ($3) { $urlResult->{"readings"}->{"pressure"} = int($3+0.5); } if ($4) { $urlResult->{"readings"}->{"pressure_trend"} = $4; $urlResult->{"readings"}->{"pressure_trend_txt"} = $pressure_trend_txt_i18n{$4}; $urlResult->{"readings"}->{"pressure_trend_sym"} = $pressure_trend_sym{$4}; } } ### wind if ($tag eq "yweather:wind" ) { $value =~/chill="(-?[0-9.]*?)" .*direction="([0-9.]*?)" .*speed="([0-9.]*?)" .*/; $urlResult->{"readings"}->{"wind_chill"} = $1 if (defined($1)); $urlResult->{"readings"}->{"wind_direction"} = $2 if defined($2); my $windspeed= defined($3) ? int($3+0.5) : ""; $urlResult->{"readings"}->{"wind_speed"} = $windspeed; $urlResult->{"readings"}->{"wind"} = $windspeed;# duplicate for compatibility if (defined($2) & defined($3)) { my $wdir = degrees_to_direction($2,@directions_txt_i18n); $urlResult->{"readings"}->{"wind_condition"} = "Wind: $wdir $windspeed km/h"; # compatibility } } } } if (exists($urlResult->{readings})) { readingsBeginUpdate($hash); while ( (my $key, my $value) = each %{$urlResult->{readings}} ) { readingsBulkUpdate($hash, $key, $value); } my $temperature= $hash->{READINGS}{temperature}{VAL}; my $humidity= $hash->{READINGS}{humidity}{VAL}; my $wind= $hash->{READINGS}{wind}{VAL}; my $val= "T: $temperature H: $humidity W: $wind"; Log3 $hash, 4, "Weather ". $hash->{NAME} . ": $val"; readingsBulkUpdate($hash, "state", $val); readingsEndUpdate($hash, $doTrigger ? 1 : 0); } } ################################### sub Weather_GetUpdateLocal($) { my ($hash) = @_; my $name = $hash->{NAME}; Weather_RetrieveData($name, 1); return 1; } sub Weather_GetUpdateTimer($) { my ($hash) = @_; my $name = $hash->{NAME}; Weather_RetrieveData($name, 0); InternalTimer(gettimeofday()+$hash->{INTERVAL}, "Weather_GetUpdateTimer", $hash, 1); return 1; } # Perl Special: { $defs{Weather}{READINGS}{condition}{VAL} } # conditions: Mostly Cloudy, Overcast, Clear, Chance of Rain ################################### sub Weather_Get($@) { my ($hash, @a) = @_; return "argument is missing" if(int(@a) != 2); my $reading= $a[1]; my $value; if(defined($hash->{READINGS}{$reading})) { $value= $hash->{READINGS}{$reading}{VAL}; } else { my $rt= ""; if(defined($hash->{READINGS})) { $rt= join(" ", sort keys %{$hash->{READINGS}}); } return "Unknown reading $reading, choose one of " . $rt; } return "$a[0] $reading => $value"; } ################################### sub Weather_Set($@) { my ($hash, @a) = @_; my $cmd= $a[1]; # usage check if((@a == 2) && ($a[1] eq "update")) { RemoveInternalTimer($hash); Weather_GetUpdateTimer($hash); return undef; } else { return "Unknown argument $cmd, choose one of update"; } } ##################################### sub Weather_Define($$) { my ($hash, $def) = @_; # define Weather [interval] # define MyWeather Weather "Maintal,HE" 3600 my @a = split("[ \t][ \t]*", $def); return "syntax: define Weather [interval [en|de|nl]]" if(int(@a) < 3 && int(@a) > 5); $hash->{STATE} = "Initialized"; $hash->{fhem}{interfaces}= "temperature;humidity;wind"; my $name = $a[0]; my $location = $a[2]; my $interval = 3600; my $lang = "en"; if(int(@a)>=4) { $interval= $a[3]; } if(int(@a)==5) { $lang= $a[4]; } $hash->{LOCATION} = $location; $hash->{INTERVAL} = $interval; $hash->{LANG} = $lang; $hash->{UNITS} = "c"; # hardcoded to use degrees centigrade (Celsius) $hash->{READINGS}{current_date_time}{TIME}= TimeNow(); $hash->{READINGS}{current_date_time}{VAL}= "none"; Weather_GetUpdateLocal($hash); InternalTimer(gettimeofday()+$hash->{INTERVAL}, "Weather_GetUpdateTimer", $hash, 0); return undef; } ##################################### sub Weather_Undef($$) { my ($hash, $arg) = @_; RemoveInternalTimer($hash); return undef; } ##################################### # Icon Parameter use constant ICONHIGHT => 120; use constant ICONWIDTH => 175; use constant ICONSCALE => 0.5; ##################################### sub WeatherIconIMGTag($) { my $width= int(ICONSCALE*ICONWIDTH); my ($icon)= @_; my $url= FW_IconURL("weather/$icon"); my $style= " width=$width"; return "\"$icon\""; } ##################################### sub WeatherAsHtmlV($;$) { my ($d,$items) = @_; $d = "" if(!$d); $items = 6 if( !$items ); return "$d is not a Weather instance
" if(!$defs{$d} || $defs{$d}{TYPE} ne "Weather"); my $width= int(ICONSCALE*ICONWIDTH); my $ret = sprintf('', $width); $ret .= sprintf('', $width, WeatherIconIMGTag(ReadingsVal($d, "icon", "")), ReadingsVal($d, "condition", ""), ReadingsVal($d, "temp_c", ""), ReadingsVal($d, "humidity", ""), ReadingsVal($d, "wind_condition", "")); for(my $i=1; $i<$items; $i++) { $ret .= sprintf('', $width, WeatherIconIMGTag(ReadingsVal($d, "fc${i}_icon", "")), ReadingsVal($d, "fc${i}_day_of_week", ""), ReadingsVal($d, "fc${i}_condition", ""), ReadingsVal($d, "fc${i}_low_c", ""), ReadingsVal($d, "fc${i}_high_c", "")); } $ret .= "
%s%s
%s°C %s%%
%s
%s%s: %s
min %s°C max %s°C
"; return $ret; } sub WeatherAsHtml($;$) { my ($d,$i) = @_; WeatherAsHtmlV($d,$i); } sub WeatherAsHtmlH($;$) { my ($d,$items) = @_; $d = "" if(!$d); $items = 6 if( !$items ); return "$d is not a Weather instance
" if(!$defs{$d} || $defs{$d}{TYPE} ne "Weather"); my $width= int(ICONSCALE*ICONWIDTH); my $format= '
%s
%s
%s°C %s%%
%s
'; my $ret = ''; # icons $ret .= sprintf('', $width, WeatherIconIMGTag(ReadingsVal($d, "icon", ""))); for(my $i=1; $i<$items; $i++) { $ret .= sprintf('', $width, WeatherIconIMGTag(ReadingsVal($d, "fc${i}_icon", ""))); } $ret .= ''; # condition $ret .= sprintf('', ReadingsVal($d, "condition", "")); for(my $i=1; $i<$items; $i++) { $ret .= sprintf('', ReadingsVal($d, "fc${i}_day_of_week", ""), ReadingsVal($d, "fc${i}_condition", "")); } $ret .= ''; # temp/hum | min $ret .= sprintf('', ReadingsVal($d, "temp_c", ""), ReadingsVal($d, "humidity", "")); for(my $i=1; $i<$items; $i++) { $ret .= sprintf('', ReadingsVal($d, "fc${i}_low_c", "")); } $ret .= ''; # wind | max $ret .= sprintf('', ReadingsVal($d, "wind_condition", "")); for(my $i=1; $i<$items; $i++) { $ret .= sprintf('', ReadingsVal($d, "fc${i}_high_c", "")); } $ret .= "
%s%s
%s%s: %s
%s°C %s%%min %s°C
%smax %s°C
"; return $ret; } sub WeatherAsHtmlD($;$) { my ($d,$i) = @_; if($FW_ss) { WeatherAsHtmlV($d,$i); } else { WeatherAsHtmlH($d,$i); } } ##################################### 1; =pod =begin html

Weather


    Define
      define <name> Weather <location> [<interval> [<language>]]

      Defines a virtual device for weather forecasts.

      A Weather device periodically gathers current and forecast weather conditions from the Yahoo Weather API.

      The parameter location is the WOEID (WHERE-ON-EARTH-ID), go to http://weather.yahoo.com to find it out for your location.

      The optional parameter interval is the time between subsequent updates in seconds. It defaults to 3600 (1 hour).

      The optional language parameter may be one of de, en, nl, It determines the natural language in which the forecast information appears. It defaults to en. If you want to set the language you also have to set the interval.

      Examples:
            define MyWeather Weather 673513
            define Forecast Weather 673513 1800
           
      The module provides four additional functions WeatherAsHtml, WeatherAsHtmlV, WeatherAsHtmlH and WeatherAsHtmlD. The former two functions are identical: they return the HTML code for a vertically arranged weather forecast. The third function returns the HTML code for a horizontally arranged weather forecast. The latter function dynamically picks the orientation depending on wether a smallscreen style is set (vertical layout) or not (horizontal layout). Each version accepts an additional paramter to limit the numer of icons to display.

      Example:
            define MyWeatherWeblink weblink htmlCode { WeatherAsHtmlH("MyWeather") }
          

    Set
      set <name> update

      Forces the retrieval of the weather data. The next automatic retrieval is scheduled to occur interval seconds later.


    Get
      get <name> <reading>

      Valid readings and their meaning (? can be one of 1, 2, 3, 4, 5 and stands for today, tomorrow, etc.):
      cityname of town returned for location
      codecurrent condition code
      conditioncurrent condition
      current_date_timelast update of forecast on server
      fc?_codeforecast condition code
      fc?_conditionforecast condition
      fc?_day_of_weekday of week for day +?
      fc?_high_cforecasted daily high in degrees centigrade
      fc?_iconforecast icon
      fc?_low_cforecasted daily low in degrees centigrade
      humiditycurrent humidity in %
      iconrelative path for current icon
      pressureair pressure in hPa
      pressure_trendair pressure trend (0= steady, 1= rising, 2= falling)
      pressure_trend_txttextual representation of air pressure trend
      pressure_trend_symsymbolic representation of air pressure trend
      temperaturecurrent temperature in degrees centigrade
      temp_ccurrent temperature in degrees centigrade
      temp_fcurrent temperature in degrees Fahrenheit
      visibilityvisibility in km
      windwind speed in km/h
      wind_chillwind chill in degrees centigrade
      wind_conditionwind direction and speed
      wind_directiondirection wind comes from in degrees (0 = north wind)
      wind_speedsame as wind

    Attributes
=end html =begin html_DE

Weather


    Define
      define <name> Weather <location> [<interval> [<language>]]

      Bezechnet ein virtuelles Gerät für Wettervorhersagen.

      Eine solche virtuelle Wetterstation sammelt periodisch aktuelle und zukünftige Wetterdaten aus der Yahoo-Wetter-API.

      Der Parameter location entspricht der sechsstelligen WOEID (WHERE-ON-EARTH-ID). Die WOEID für den eigenen Standort kann auf http://weather.yahoo.com gefunden werden.

      Der optionale Parameter interval gibt die Dauer in Sekunden zwischen den einzelnen Aktualisierungen der Wetterdaten an. Der Standardwert ist 3600 (1 Stunde). Wird kein Wert angegeben, gilt der Standardwert.

      Der optionale Parameter für die möglichen Sprachen darf einen der folgende Werte annehmen: de, en oder nl. Er bezeichnet die natürliche Sprache, in der die Wetterinformationen dargestellt werden. Der Standardwert ist en. Wird für die Sprache kein Wert angegeben, gilt der Standardwert. Wird allerdings der Parameter für die Sprache gesetzt, muss ebenfalls ein Wert für das Abfrageintervall gesetzt werden.

      Beispiele:
            define MyWeather Weather 673513
            define Forecast Weather 673513 1800
           
      Das Modul unterstützt zusätzlich vier verschiedene Funktionen WeatherAsHtml, WeatherAsHtmlV, WeatherAsHtmlH und WeatherAsHtmlD. Die ersten beiden Funktionen sind identisch: sie erzeugen den HTML-Code für eine vertikale Darstellung des Wetterberichtes. Die dritte Funktion liefert den HTML-Code für eine horizontale Darstellung des Wetterberichtes. Die letztgenannte Funktion wählt automatisch eine Ausrichtung, die abhängig davon ist, ob ein Smallcreen Style ausgewählt ist (vertikale Darstellung) oder nicht (horizontale Darstellung). Alle vier Funnktionen akzeptieren einen zusätzlichen optionalen Paramter um die Anzahl der darzustellenden Icons anzugeben.

      Beispiel:
            define MyWeatherWeblink weblink htmlCode { WeatherAsHtmlH("MyWeather") }
          

    Set
      set <name> update

      Erzwingt eine Abfrage der Wetterdaten. Die darauffolgende Abfrage wird gemäß dem eingestellten Intervall interval Sekunden später durchgeführt.


    Get
      get <name> <reading>

      Gültige ausgelesene Daten (readings) und ihre Bedeutung (das ? kann einen der Werte 1, 2, 3 , 4 oder 5 annehmen und steht für heute, morgen, übermorgen etc.):

      cityName der Stadt, der aufgrund der WOEID übermittelt wird
      codeCode für die aktuellen Wetterverhältnisse
      conditionaktuelle Wetterverhältnisse
      current_date_timeZeitstempel der letzten Aktualisierung der Wetterdaten vom Server
      fc?_codeCode für die vorhergesagten Wetterverhältnisse
      fc?_conditionvorhergesagte Wetterverhältnisse
      fc?_day_of_weekWochentag des Tages, der durch ? dargestellt wird
      fc?_high_cvorhergesagte maximale Tagestemperatur in Grad Celsius
      fc?_iconIcon für Vorhersage
      fc?_low_cvorhergesagte niedrigste Tagestemperatur in Grad Celsius
      humiditygegenwärtige Luftfeuchtgkeit in %
      iconrelativer Pfad für das aktuelle Icon
      pressureLuftdruck in hPa
      pressure_trendLuftdrucktendenz (0= gleichbleibend, 1= steigend, 2= fallend)
      pressure_trend_txttextliche Darstellung der Luftdrucktendenz
      pressure_trend_symsymbolische Darstellung der Luftdrucktendenz
      temperaturegegenwärtige Temperatur in Grad Celsius
      temp_cgegenwärtige Temperatur in Grad Celsius
      temp_fgegenwärtige Temperatur in Grad Celsius
      visibilitySichtweite in km
      windWindgeschwindigkeit in km/h
      wind_chillgefühlte Temperatur in Grad Celsius
      wind_conditionWindrichtung und -geschwindigkeit
      wind_directionGradangabe der Windrichtung (0 = Nordwind)
      wind_speedWindgeschwindigkeit in km/h (mit wind identisch)

    Attribute
=end html_DE =cut