Average added
git-svn-id: https://fhem.svn.sourceforge.net/svnroot/fhem/trunk/fhem@1081 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
1
CHANGED
1
CHANGED
@@ -12,6 +12,7 @@
|
|||||||
- feature: FritzBox 7270 ZIP file
|
- feature: FritzBox 7270 ZIP file
|
||||||
- buxgfix: prevent fhem from stalling if telnet times out in 66_ECMD.pm
|
- buxgfix: prevent fhem from stalling if telnet times out in 66_ECMD.pm
|
||||||
- feature: FHEMWEB longpoll mode, small fixes, tuned smallscreen mode
|
- feature: FHEMWEB longpoll mode, small fixes, tuned smallscreen mode
|
||||||
|
- feature: average module added
|
||||||
|
|
||||||
- 2011-07-08 (5.1)
|
- 2011-07-08 (5.1)
|
||||||
- feature: smallscreen optimizations for iPhone
|
- feature: smallscreen optimizations for iPhone
|
||||||
|
|||||||
@@ -159,7 +159,6 @@ FHT_Initialize($)
|
|||||||
# 810c0d20 0909a001 3232 7e006724 (NYI)
|
# 810c0d20 0909a001 3232 7e006724 (NYI)
|
||||||
$hash->{Match} = "^81..(04|09|0d)..(0909a001|83098301|c409c401)..";
|
$hash->{Match} = "^81..(04|09|0d)..(0909a001|83098301|c409c401)..";
|
||||||
$hash->{SetFn} = "FHT_Set";
|
$hash->{SetFn} = "FHT_Set";
|
||||||
$hash->{StateFn} = "FHT_SetState";
|
|
||||||
$hash->{DefFn} = "FHT_Define";
|
$hash->{DefFn} = "FHT_Define";
|
||||||
$hash->{UndefFn} = "FHT_Undef";
|
$hash->{UndefFn} = "FHT_Undef";
|
||||||
$hash->{ParseFn} = "FHT_Parse";
|
$hash->{ParseFn} = "FHT_Parse";
|
||||||
@@ -302,19 +301,6 @@ FHT_Set($@)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#####################################
|
|
||||||
sub
|
|
||||||
FHT_SetState($$$$)
|
|
||||||
{
|
|
||||||
my ($hash, $tim, $vt, $val) = @_;
|
|
||||||
|
|
||||||
return "Ignoring FHZ state" if($vt =~ m/^FHZ:/);
|
|
||||||
$vt =~ s/^FHZ://;
|
|
||||||
return "Undefined type $vt" if(!defined($c2b{$vt}) && !defined($warnings{$vt}));
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
sub
|
sub
|
||||||
FHT_Define($$)
|
FHT_Define($$)
|
||||||
|
|||||||
129
FHEM/98_average.pm
Normal file
129
FHEM/98_average.pm
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
##############################################
|
||||||
|
# Avarage computing
|
||||||
|
|
||||||
|
package main;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
##########################
|
||||||
|
sub
|
||||||
|
average_Initialize($)
|
||||||
|
{
|
||||||
|
my ($hash) = @_;
|
||||||
|
$hash->{DefFn} = "average_Define";
|
||||||
|
$hash->{NotifyFn} = "average_Notify";
|
||||||
|
$hash->{AttrList} = "disable:0,1";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
##########################
|
||||||
|
sub
|
||||||
|
average_Define($$$)
|
||||||
|
{
|
||||||
|
my ($hash, $def) = @_;
|
||||||
|
my ($name, $type, $re, $rest) = split("[ \t]+", $def, 4);
|
||||||
|
|
||||||
|
if(!$re || $rest) {
|
||||||
|
my $msg = "wrong syntax: define <name> average device[:event]";
|
||||||
|
return $msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Checking for misleading regexps
|
||||||
|
eval { "Hallo" =~ m/^$re$/ };
|
||||||
|
return "Bad regexp: $@" if($@);
|
||||||
|
$hash->{REGEXP} = $re;
|
||||||
|
$hash->{STATE} = "active";
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
##########################
|
||||||
|
sub
|
||||||
|
average_Notify($$)
|
||||||
|
{
|
||||||
|
my ($avg, $dev) = @_;
|
||||||
|
my $avgName = $avg->{NAME};
|
||||||
|
|
||||||
|
return "" if(AttrVal($avgName, "disable", undef));
|
||||||
|
|
||||||
|
my $devName = $dev->{NAME};
|
||||||
|
my $re = $avg->{REGEXP};
|
||||||
|
my $max = int(@{$dev->{CHANGED}});
|
||||||
|
my $tn;
|
||||||
|
|
||||||
|
my $trigger = "";
|
||||||
|
for (my $i = 0; $i < $max; $i++) {
|
||||||
|
my $s = $dev->{CHANGED}[$i];
|
||||||
|
|
||||||
|
################
|
||||||
|
# Filtering
|
||||||
|
next if(!defined($s));
|
||||||
|
my ($evName, $val) = split(" ", $s, 2); # resets $1
|
||||||
|
next if($devName !~ m/^$re$/ && "$devName:$s" !~ m/^$re$/ || $s =~ m/_avg_/);
|
||||||
|
$val = $1 if(defined($1));
|
||||||
|
next if(!defined($val) || $val !~ m/^(\d+\.?\d*)/);
|
||||||
|
$val = $1;
|
||||||
|
|
||||||
|
################
|
||||||
|
# Avg computing
|
||||||
|
$evName =~ s/[^A-Za-z_-].*//;
|
||||||
|
$tn = TimeNow() if(!$tn);
|
||||||
|
|
||||||
|
my $r = $dev->{READINGS};
|
||||||
|
my @dNow = split("[ :-]", $tn);
|
||||||
|
|
||||||
|
for(my $idx = 0; $idx <= 1; $idx++) {
|
||||||
|
|
||||||
|
my $secNow = 3600*$dNow[3] + 60*$dNow[4] + $dNow[5];
|
||||||
|
$secNow += $dNow[2]*86400 if($idx);
|
||||||
|
|
||||||
|
my $cumName = "${evName}_cum_" . ($idx ? "month" : "day");
|
||||||
|
my $avgName = "${evName}_avg_" . ($idx ? "month" : "day");
|
||||||
|
|
||||||
|
if(!$r->{$cumName}) {
|
||||||
|
$r->{$cumName}{VAL} = $secNow*$val;
|
||||||
|
$r->{$avgName}{VAL} = $val;
|
||||||
|
$r->{$cumName}{TIME} = $r->{$avgName}{TIME} = $tn;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
my @dLast = split("[ :-]", $r->{$cumName}{TIME});
|
||||||
|
my $secLast = 3600*$dLast[3] + 60*$dLast[4] + $dLast[5];
|
||||||
|
$secLast += $dLast[2]*86400 if($idx);
|
||||||
|
|
||||||
|
if($idx == 0 && ($dLast[2] == $dNow[2]) ||
|
||||||
|
$idx == 1 && ($dLast[1] == $dNow[1])) {
|
||||||
|
my $cum = $r->{$cumName}{VAL} + ($secNow-$secLast) * $val;
|
||||||
|
$r->{$cumName}{VAL} = $cum;
|
||||||
|
$r->{$avgName}{VAL} = sprintf("%0.1f", $cum/$secNow);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$trigger .= " $avgName:".$r->{$avgName}{VAL};
|
||||||
|
$r->{$cumName}{VAL} = $secNow*$val;
|
||||||
|
$r->{$avgName}{VAL} = $val;
|
||||||
|
|
||||||
|
}
|
||||||
|
$r->{$cumName}{TIME} = $r->{$avgName}{TIME} = $tn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$addNotifyCB{"avg:$devName"} = "average_Callback $devName $trigger"
|
||||||
|
if($trigger);
|
||||||
|
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
average_Callback($)
|
||||||
|
{
|
||||||
|
my ($arg) = @_;
|
||||||
|
my ($dev, @list) = split(" ", $arg);
|
||||||
|
|
||||||
|
my $n = 0;
|
||||||
|
for(my $n = 0; $n < @list; $n++) {
|
||||||
|
my ($name, $value) = split(":", $list[$n]);
|
||||||
|
$defs{$dev}{CHANGED}[$n] = "$name: $value";
|
||||||
|
}
|
||||||
|
DoTrigger($dev, undef);
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
||||||
@@ -149,6 +149,7 @@
|
|||||||
<a href="#SUNRISE_EL">SUNRISE_EL</a>
|
<a href="#SUNRISE_EL">SUNRISE_EL</a>
|
||||||
<a href="#at">at</a>
|
<a href="#at">at</a>
|
||||||
<a href="#autocreate">autocreate</a>
|
<a href="#autocreate">autocreate</a>
|
||||||
|
<a href="#average">average</a>
|
||||||
<a href="#dummy">dummy</a>
|
<a href="#dummy">dummy</a>
|
||||||
<a href="#dumpdef">dumpdef</a>
|
<a href="#dumpdef">dumpdef</a>
|
||||||
<a href="#holiday">holiday</a>
|
<a href="#holiday">holiday</a>
|
||||||
@@ -6829,6 +6830,68 @@ href="http://www.elv.de/output/controller.aspx?cid=74&detail=10&detail2=29870">U
|
|||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<a name="average"></a>
|
||||||
|
<h3>average</h3>
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
Compute additional average_day and average_month values.
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<a name="averagedefine"></a>
|
||||||
|
<b>Define</b>
|
||||||
|
<ul>
|
||||||
|
<code>define <name> average <regexp></code><br>
|
||||||
|
<br>
|
||||||
|
<ul>
|
||||||
|
The syntax for <regexp> is the same as the
|
||||||
|
regexp for <a href="#notify">notify</a>.<br>
|
||||||
|
If it matches, and the event is of the form "eventname number", then this
|
||||||
|
module computes the daily and monthly average, and generates an event of the form
|
||||||
|
<ul>
|
||||||
|
<device> <eventname>_avg_day: <computed_average>
|
||||||
|
</ul>
|
||||||
|
and
|
||||||
|
<ul>
|
||||||
|
<device> <eventname>_avg_month: <computed_average>
|
||||||
|
</ul>
|
||||||
|
at the beginning of the next day or month respectively.<br>
|
||||||
|
The current average and the cumulated values are stored in the device readings.
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
Example:<PRE>
|
||||||
|
# Compute the average for the temperature events of the ws1 device
|
||||||
|
define avg_temp_ws1 average ws1:temperature.*
|
||||||
|
|
||||||
|
# Compute the average for each temperature event
|
||||||
|
define avg_temp_ws1 average .*:temperature.*
|
||||||
|
|
||||||
|
# Compute the average for all temperature and humidity events
|
||||||
|
define avg_temp_ws1 average .*:(temperature|humidity).*
|
||||||
|
</PRE>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<a name="averageset"></a>
|
||||||
|
<b>Set</b> <ul>N/A</ul><br>
|
||||||
|
|
||||||
|
<a name="averageget"></a>
|
||||||
|
<b>Get</b> <ul>N/A</ul><br>
|
||||||
|
|
||||||
|
<a name="averageattr"></a>
|
||||||
|
<b>Attributes</b>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#disable">disable</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<a name="KM271events"></a>
|
||||||
|
<b>Generated events:</b>
|
||||||
|
<ul>
|
||||||
|
<li><eventname>_avg_day: $avg_day
|
||||||
|
<li><eventname>_avg_month: $avg_month
|
||||||
|
</ul>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
<a name="holiday"></a>
|
<a name="holiday"></a>
|
||||||
<h3>holiday</h3>
|
<h3>holiday</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
19
fhem.pl
19
fhem.pl
@@ -150,6 +150,7 @@ use vars qw(%cmds); # Global command name hash. To be expanded
|
|||||||
use vars qw(%data); # Hash for user data
|
use vars qw(%data); # Hash for user data
|
||||||
use vars qw($devcount); # To sort the devices
|
use vars qw($devcount); # To sort the devices
|
||||||
use vars qw(%defaultattr); # Default attributes, used by FHEM2FHEM
|
use vars qw(%defaultattr); # Default attributes, used by FHEM2FHEM
|
||||||
|
use vars qw(%addNotifyCB); # Used by event enhancers (e.g. avarage)
|
||||||
|
|
||||||
use vars qw($reread_active);
|
use vars qw($reread_active);
|
||||||
|
|
||||||
@@ -167,7 +168,7 @@ my $nextat; # Time when next timer will be triggered.
|
|||||||
my $intAtCnt=0;
|
my $intAtCnt=0;
|
||||||
my %duplicate; # Pool of received msg for multi-fhz/cul setups
|
my %duplicate; # Pool of received msg for multi-fhz/cul setups
|
||||||
my $duplidx=0; # helper for the above pool
|
my $duplidx=0; # helper for the above pool
|
||||||
my $cvsid = '$Id: fhem.pl,v 1.157 2011-10-18 08:31:19 rudolfkoenig Exp $';
|
my $cvsid = '$Id: fhem.pl,v 1.158 2011-10-23 09:23:55 rudolfkoenig Exp $';
|
||||||
my $namedef =
|
my $namedef =
|
||||||
"where <name> is either:\n" .
|
"where <name> is either:\n" .
|
||||||
"- a single device name\n" .
|
"- a single device name\n" .
|
||||||
@@ -2097,7 +2098,6 @@ DoTrigger($$)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
################
|
################
|
||||||
# Log/notify modules
|
# Log/notify modules
|
||||||
# If modifying a device in its own trigger, do not call the triggers from
|
# If modifying a device in its own trigger, do not call the triggers from
|
||||||
@@ -2126,6 +2126,21 @@ DoTrigger($$)
|
|||||||
delete($defs{$dev}{CHANGED}) if(!defined($defs{$dev}{INTRIGGER}));
|
delete($defs{$dev}{CHANGED}) if(!defined($defs{$dev}{INTRIGGER}));
|
||||||
|
|
||||||
Log 3, "NTFY return: $ret" if($ret);
|
Log 3, "NTFY return: $ret" if($ret);
|
||||||
|
|
||||||
|
# Enhancers like avarage need this
|
||||||
|
if(!defined($defs{$dev}{InNtfyCb}) && %addNotifyCB) {
|
||||||
|
$defs{$dev}{InNtfyCb}=1;
|
||||||
|
foreach my $cb (keys %addNotifyCB) {
|
||||||
|
my ($fn, $arg) = split(" ", $addNotifyCB{$cb}, 2);
|
||||||
|
delete $addNotifyCB{$cb};
|
||||||
|
no strict "refs";
|
||||||
|
&{$fn}($arg);
|
||||||
|
use strict "refs";
|
||||||
|
}
|
||||||
|
delete($defs{$dev}{CHANGED});
|
||||||
|
delete($defs{$dev}{InNtfyCb});
|
||||||
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user