2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-03 16:56:54 +00:00

- module Weather reworked

- added wrapper for readings update to fhem.pl

git-svn-id: https://svn.fhem.de/fhem/trunk@1255 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
borisneubert 2012-02-11 23:42:47 +00:00
parent 991243d9aa
commit 253bfd5319
2 changed files with 147 additions and 56 deletions

View File

@ -13,6 +13,7 @@ use warnings;
use Time::HiRes qw(gettimeofday); use Time::HiRes qw(gettimeofday);
use Weather::Google; use Weather::Google;
##################################### #####################################
sub Weather_Initialize($) { sub Weather_Initialize($) {
@ -25,7 +26,7 @@ sub Weather_Initialize($) {
$hash->{DefFn} = "Weather_Define"; $hash->{DefFn} = "Weather_Define";
$hash->{UndefFn} = "Weather_Undef"; $hash->{UndefFn} = "Weather_Undef";
$hash->{GetFn} = "Weather_Get"; $hash->{GetFn} = "Weather_Get";
$hash->{AttrList}= "loglevel:0,1,2,3,4,5"; $hash->{AttrList}= "loglevel:0,1,2,3,4,5 event-on-update-reading event-on-change-reading";
} }
@ -37,33 +38,36 @@ sub f_to_c($) {
} }
################################### ###################################
sub Weather_UpdateReading($$$$$$) { sub Weather_UpdateReading($$$$) {
my ($hash,$prefix,$key,$tn,$value,$n)= @_; my ($hash,$prefix,$key,$value)= @_;
return 0 if(!defined($value) || $value eq ""); return 0 if(!defined($value) || $value eq "");
#Log 1, "DEBUG WEATHER: $prefix $key $value";
if($key eq "temp") { if($key eq "low") {
$key= "temp_c"; $key= "low_c";
$value= f_to_c($value) if($hash->{READINGS}{unit_system}{VAL} ne "SI"); # assume F to C conversion required $value= f_to_c($value) if($hash->{READINGS}{unit_system}{VAL} ne "SI");
} elsif($key eq "low") {
$key= "low_c";
$value= f_to_c($value) if($hash->{READINGS}{unit_system}{VAL} ne "SI");
} elsif($key eq "high") { } elsif($key eq "high") {
$key= "high_c"; $key= "high_c";
$value= f_to_c($value) if($hash->{READINGS}{unit_system}{VAL} ne "SI"); $value= f_to_c($value) if($hash->{READINGS}{unit_system}{VAL} ne "SI");
} elsif($key eq "humidity") {
# standardize reading - allow generic logging of humidity.
$value=~ s/.*?(\d+).*/$1/; # extract numeric
} }
my $reading= $prefix . $key; my $reading= $prefix . $key;
my $r= $hash->{READINGS};
$r->{$reading}{TIME}= $tn;
$r->{$reading}{VAL} = $value;
my $name= $hash->{NAME};
# Log 1, "Weather $name: $reading= $value";
$hash->{CHANGED}[$n]= "$reading: $value";
readingsUpdate($hash,$reading,$value);
if($reading eq "temp_c") {
readingsUpdate($hash,"temperature",$value); # additional entry for compatability
}
if($key eq "wind_condition") {
$value=~ s/.*?(\d+).*/$1/; # extract numeric
readingsUpdate($hash,"wind",$value); # additional entry for compatability
}
return 1; return 1;
} }
@ -78,11 +82,8 @@ sub Weather_GetUpdate($)
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $n= 0;
readingsBeginUpdate($hash);
# time
my $tn = TimeNow();
# get weather information from Google weather API # get weather information from Google weather API
@ -93,43 +94,39 @@ sub Weather_GetUpdate($)
my $WeatherObj; my $WeatherObj;
Log 4, "$name: Updating weather information for $location, language $lang."; Log 4, "$name: Updating weather information for $location, language $lang.";
eval { eval {
$WeatherObj= new Weather::Google($location, {language => $lang}); $WeatherObj= new Weather::Google($location, {language => $lang});
}; };
if($@) { if($@) {
Log 1, "$name: Could not retrieve weather information."; Log 1, "$name: Could not retrieve weather information.";
return 0; return 0;
} }
# the current conditions contain temp_c and temp_f
my $current = $WeatherObj->current_conditions; my $current = $WeatherObj->current_conditions;
foreach my $condition ( keys ( %$current ) ) { foreach my $condition ( keys ( %$current ) ) {
my $value= $current->{$condition}; my $value= $current->{$condition};
Weather_UpdateReading($hash,"",$condition,$tn,$value,$n); Weather_UpdateReading($hash,"",$condition,$value);
$n++;
} }
my $fci= $WeatherObj->forecast_information; my $fci= $WeatherObj->forecast_information;
foreach my $i ( keys ( %$fci ) ) { foreach my $i ( keys ( %$fci ) ) {
my $reading= $i; my $reading= $i;
my $value= $fci->{$i}; my $value= $fci->{$i};
Weather_UpdateReading($hash,"",$i,$tn,$value,$n); Weather_UpdateReading($hash,"",$i,$value);
$n++;
} }
# the forecast conditions contain high and low (temperature)
for(my $t= 0; $t<= 3; $t++) { for(my $t= 0; $t<= 3; $t++) {
my $fcc= $WeatherObj->forecast_conditions($t); my $fcc= $WeatherObj->forecast_conditions($t);
my $prefix= sprintf("fc%d_", $t); my $prefix= sprintf("fc%d_", $t);
foreach my $condition ( keys ( %$fcc ) ) { foreach my $condition ( keys ( %$fcc ) ) {
my $value= $fcc->{$condition}; my $value= $fcc->{$condition};
Weather_UpdateReading($hash,$prefix,$condition,$tn,$value,$n); Weather_UpdateReading($hash,$prefix,$condition,$value);
$n++; }
}
} }
if(!$hash->{LOCAL}) { readingsEndUpdate($hash, defined($hash->{LOCAL} ? 0 : 1)); # DoTrigger, because sub is called by a timer instead of dispatch
DoTrigger($name, undef) if($init_done);
}
return 1; return 1;
} }
@ -151,9 +148,9 @@ sub Weather_Get($@) {
my $value; my $value;
if(defined($hash->{READINGS}{$reading})) { if(defined($hash->{READINGS}{$reading})) {
$value= $hash->{READINGS}{$reading}{VAL}; $value= $hash->{READINGS}{$reading}{VAL};
} else { } else {
return "no such reading: $reading"; return "no such reading: $reading";
} }
return "$a[0] $reading => $value"; return "$a[0] $reading => $value";
@ -175,16 +172,16 @@ sub Weather_Define($$) {
$hash->{STATE} = "Initialized"; $hash->{STATE} = "Initialized";
my $name = $a[0]; my $name = $a[0];
my $location = $a[2]; my $location = $a[2];
my $interval = 3600; my $interval = 3600;
my $lang = "en"; my $lang = "en";
if(int(@a)>=4) { $interval= $a[3]; } if(int(@a)>=4) { $interval= $a[3]; }
if(int(@a)==5) { $lang= $a[4]; } if(int(@a)==5) { $lang= $a[4]; }
$hash->{LOCATION} = $location; $hash->{LOCATION} = $location;
$hash->{INTERVAL} = $interval; $hash->{INTERVAL} = $interval;
$hash->{LANG} = $lang; $hash->{LANG} = $lang;
$hash->{READINGS}{current_date_time}{TIME}= TimeNow(); $hash->{READINGS}{current_date_time}{TIME}= TimeNow();
$hash->{READINGS}{current_date_time}{VAL}= "none"; $hash->{READINGS}{current_date_time}{VAL}= "none";

View File

@ -4,7 +4,7 @@
# #
# Copyright notice # Copyright notice
# #
# (c) 2005-20012 # (c) 2005-2012
# Copyright: Rudolf Koenig (r dot koenig at koeniglich dot de) # Copyright: Rudolf Koenig (r dot koenig at koeniglich dot de)
# All rights reserved # All rights reserved
# #
@ -2668,3 +2668,97 @@ setGlobalAttrBeforeFork()
} }
close(FH); close(FH);
} }
################################################################
#
# What follows are wrappers for commonly used core functions
# in device-specific modules.
# This part written by Boris Neubert omega at online dot de
#
################################################################
#
# Call readingsBeginUpdate before you start updating readings.
# The updated readings will all get the same timestamp,
# which is the time when you called this subroutine.
#
sub
readingsBeginUpdate($) {
my ($hash)= @_;
# get timestamp
$hash->{helper}{updating}{latestUpdate}= TimeNow();
return $hash->{helper}{updating}{latestUpdate};
}
#
# Call readingsEndUpdate when you are done updating readings.
# This optionally calls DoTrigger to propagate the changes.
# Rule: DoTrigger should only be called when the sub that
# changes the readings is not called by Dispatch.
#
sub
readingsEndUpdate($$) {
my ($hash,$dotrigger)= @_;
# turn off updating mode
delete $hash->{helper}{updating};
# propagate changes
if($dotrigger) {
DoTrigger($hash->{NAME}, undef) if($init_done);
}
return undef;
}
#
# Call readingsUpdate to update the reading.
# Example: readingsUpdate($hash,"temperature",$value);
#
sub
readingsUpdate($$$) {
my ($hash,$reading,$value)= @_;
my $name= $hash->{NAME};
# sanity check
defined($hash->{helper}{updating}) ||
die "fhem.pl: readingsUpdateReading: you must call readingsBeginUpdate first.";
# here we can add a lot of convenient functionality later:
# - create CHANGED events only for readings the user has subscribed to (e.g. see repchanged hash in 13_KS300.pm
# - create CHANGED events only for readings whose values have changed (are different from current entry)
# determine if an event should be created
my $readings= $hash->{READINGS};
my $changed= 1;
if(defined($attr{$name}{"event-on-change-reading"})) {
$changed= grep($_ eq $reading, split /,/,$attr{$name}{"event-on-change-reading"}) if($value eq $readings->{$reading}{VAL});
}
if(defined($attr{$name}{"event-on-update-reading"})) {
$changed= grep($_ eq $reading, split /,/,$attr{$name}{"event-on-update-reading"});
}
# update reading 5.x
$readings->{$reading}{TIME}= $hash->{helper}{updating}{latestUpdate};
$readings->{$reading}{VAL}= $value;
# update reading (upward compatibility), see http://fhemwiki.de/wiki/DevelopmentGuidelines#Struktur_im_Code
#$hash->{"readings"}{$reading}{"time"}= $hash->{helper}{updating}{latestUpdate};
#$hash->{"readings"}{$reading}{"value"}= $value;
# add to CHANGED hash
my $rv= "$reading: $value";
push(@{$hash->{CHANGED}}, $rv) if($changed);
return $rv;
}
1;