2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-08 01:14:19 +00:00

93_PWMR.pm : restructured readings

git-svn-id: https://svn.fhem.de/fhem/trunk@9817 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
jamesgo 2015-11-08 09:12:39 +00:00
parent e966257d92
commit 5814683d6f
2 changed files with 147 additions and 78 deletions

View File

@ -13,6 +13,9 @@
# 13.10.15 GA add event-on-change-reading
# 14.10.15 GA fix round energyusedp
# 15.10.15 GA add a_regexp_on, a regular expression for the on state of the actor
# 05.11.15 GA fix new reading desired-temp-until which substitutes modification date of desired-temp in the future
# events for desired-temp adjusted (no update of timestamp if temperature stays the same)
# module for PWM (Pulse Width Modulation) calculation
# this module defines a room for calculation
@ -107,10 +110,8 @@ PWMR_CalcDesiredTemp($)
{
my ($hash) = @_;
$hash->{STATE} = "Calculating";
if($hash->{INTERVAL} > 0) {
if ($hash->{INTERVAL} eq 300) {
if ($hash->{INTERVAL} == 300) {
# align interval to hh:00:ss, hh:05:ss, ... hh:55:ss
my $n = gettimeofday();
@ -129,21 +130,44 @@ PWMR_CalcDesiredTemp($)
}
my $name = $hash->{NAME};
if ($hash->{READINGS}{"desired-temp"}{TIME} gt TimeNow()) {
Log3 ($hash, 4, "PWMR_CalcDesiredTemp $name: desired-temp was manualy set until ".
$hash->{READINGS}{"desired-temp"}{TIME});
$hash->{STATE} = "ManualSetUntil";
return undef;
} else {
Log3 ($hash, 4, "PWMR_CalcDesiredTemp $name: calc desired-temp");
if (defined($hash->{READINGS}{"desired-temp-until"})) {
if ($hash->{READINGS}{"desired-temp-until"}{VAL} ne "no" ) {
if ($hash->{READINGS}{"desired-temp-until"}{VAL} gt TimeNow()) {
Log3 ($hash, 4, "PWMR_CalcDesiredTemp $name: desired-temp was manualy set until ".
$hash->{READINGS}{"desired-temp"}{TIME});
$hash->{STATE} = "ManualSetUntil";
return undef;
}
else
{
readingsSingleUpdate ($hash, "desired-temp-until", "no", 1);
Log3 ($hash, 4, "PWMR_CalcDesiredTemp $name: calc desired-temp");
}
}
}
#if ($hash->{READINGS}{"desired-temp"}{TIME} gt TimeNow()) {
# Log3 ($hash, 4, "PWMR_CalcDesiredTemp $name: desired-temp was manualy set until ".
# $hash->{READINGS}{"desired-temp"}{TIME});
#
# $hash->{STATE} = "ManualSetUntil";
# return undef;
#} else {
# Log3 ($hash, 4, "PWMR_CalcDesiredTemp $name: calc desired-temp");
#}
####################
# frost protection
if ($hash->{c_frostProtect} > 0) {
readingsSingleUpdate ($hash, "desired-temp", $hash->{c_tempFrostProtect}, 1);
if ($hash->{READINGS}{"desired-temp"}{VAL} ne $hash->{c_tempFrostProtect}) {
readingsSingleUpdate ($hash, "desired-temp", $hash->{c_tempFrostProtect}, 1);
} else {
readingsSingleUpdate ($hash, "desired-temp", $hash->{c_tempFrostProtect}, 0);
}
#$hash->{READINGS}{"desired-tem"}{TIME} = TimeNow();
#$hash->{READINGS}{"desired-temp"}{VAL} = $hash->{c_tempFrostProtect};
@ -160,6 +184,8 @@ PWMR_CalcDesiredTemp($)
if ($hash->{c_autoCalcTemp} > 0) {
$hash->{STATE} = "Calculating";
my @time = localtime();
my $wday = $time[6];
my $cmptime = sprintf ("%02d%02d", $time[2], $time[1]);
@ -202,7 +228,11 @@ PWMR_CalcDesiredTemp($)
Log3 ($hash, 4, "PWMR_CalcDesiredTemp $name: match i:$i $points[$i] ($tempV/$temperature)");
readingsSingleUpdate ($hash, "desired-temp", $temperature, 1);
if ($hash->{READINGS}{"desired-temp"}{VAL} ne $temperature) {
readingsSingleUpdate ($hash, "desired-temp", $temperature, 1);
} else {
readingsSingleUpdate ($hash, "desired-temp", $temperature, 0);
}
#$hash->{READINGS}{"desired-temp"}{TIME} = TimeNow();
#$hash->{READINGS}{"desired-temp"}{VAL} = $temperature;
@ -221,7 +251,11 @@ PWMR_CalcDesiredTemp($)
my $act_dtemp = $hash->{READINGS}{"desired-temp"}{VAL};
Log3 ($hash, 4, "PWMR_CalcDesiredTemp $name: use last value ($act_dtemp)");
readingsSingleUpdate ($hash, "desired-temp", $newTemp, 1);
if ($act_dtemp ne $newTemp) {
readingsSingleUpdate ($hash, "desired-temp", $newTemp, 1);
#} else {
# readingsSingleUpdate ($hash, "desired-temp", $newTemp, 0);
}
#$hash->{READINGS}{"desired-temp"}{TIME} = TimeNow();
#$hash->{READINGS}{"desired-temp"}{VAL} = $newTemp;
@ -237,7 +271,7 @@ PWMR_CalcDesiredTemp($)
$hash->{STATE} = "Manual";
}
DoTrigger($name, undef);
#DoTrigger($name, undef);
return undef;
}
@ -289,7 +323,7 @@ PWMR_Set($@)
# manualTempDuration
if ( $cmd eq "manualTempDuration" ) {
readingsSingleUpdate ($hash, "manualTempDuration", $a[2], 0);
readingsSingleUpdate ($hash, "manualTempDuration", $a[2], 1);
#$hash->{READINGS}{"manualTempDuration"}{VAL} = $a[2];
#$hash->{READINGS}{"manualTempDuration"}{TIME} = TimeNow();
@ -311,18 +345,29 @@ PWMR_Set($@)
$duration = int($a[3]) * 60;
}
#$hash->{READINGS}{$cmd}{TIME} = TimeNow();
# manual set desired-temp will be set for 1 hour (default)
# afterwards it will be overwritten by auto calc
my $now = time();
$hash->{READINGS}{$cmd}{TIME} = FmtDateTime($now + $duration);
$hash->{READINGS}{$cmd}{VAL} = $val;
readingsBeginUpdate ($hash);
readingsBulkUpdate ($hash, "desired-temp", $a[2]);
if ($hash->{c_autoCalcTemp} == 0) {
$hash->{STATE} = "Manual";
} else {
$hash->{STATE} = "ManualSetUntil";
readingsBulkUpdate ($hash, "desired-temp-until", FmtDateTime($now + $duration));
}
readingsEndUpdate($hash, 1);
#readingsSingleUpdate ($hash, "desired-temp", $a[2], 1);
$hash->{STATE} = "ManualSetUntil";
#$hash->{READINGS}{$cmd}{TIME} = FmtDateTime($now + $duration);
#$hash->{READINGS}{$cmd}{VAL} = $val;
#push @{$hash->{CHANGED}}, "$cmd: $val";
#DoTrigger($hash, undef);
return undef
}
@ -526,27 +571,26 @@ PWMR_SetRoom(@)
Log3 ($room, 4, "PWMR_SetRoom $name <$newState>");
my $nowR = TimeNow();
my $now = time();
$room->{READINGS}{energyused}{TIME} = $nowR;
$room->{READINGS}{energyusedp}{TIME} = $nowR;
if (!defined($room->{READINGS}{energyused}{VAL})) {
$room->{READINGS}{energyused}{VAL} = "";
my $energyused = "";
if (defined($room->{READINGS}{energyused}{VAL})) {
$energyused = substr ( $room->{READINGS}{energyused}{VAL}, -29);
}
my $energyused = substr ( $room->{READINGS}{energyused}{VAL}, -29);
# newState may be "", "on", "off"
if ($newState eq "") {
$energyused = $energyused.substr ( $energyused ,-1);
} else {
$energyused = $energyused.($newState eq "on" ? "1" : "0");
}
$room->{READINGS}{energyused}{VAL} = $energyused;
$room->{READINGS}{energyusedp}{VAL} = sprintf ("%.2f", ($energyused =~ tr/1//) /30);
readingsBeginUpdate ($room);
readingsBulkUpdate ($room, "energyused", $energyused);
readingsBulkUpdate ($room, "energyusedp", sprintf ("%.2f", ($energyused =~ tr/1//) /30));
readingsEndUpdate($room, 0);
return if ($newState eq "");
if ($newState eq "") {
return;
}
if ($room->{actor})
{
@ -555,12 +599,8 @@ PWMR_SetRoom(@)
Log3 ($room, 2, "PWMR_SetRoom $room->{NAME}: set $room->{actor} $newState");
$room->{actorState} = $newState;
readingsSingleUpdate ($room, "lastswitch", time(), 1);
$room->{READINGS}{lastswitch}{TIME} = $nowR;
$room->{READINGS}{lastswitch}{VAL} = $now;
push @{$room->{CHANGED}}, "actor $newState";
DoTrigger($name, undef);
} else {
Log3 ($room, 2, "PWMR_SetRoom $name: set $room->{actor} $newState failed ($ret)");
}
@ -630,20 +670,17 @@ PWMR_ReadRoom(@)
if (!$room->{READINGS}{"desired-temp"}{TIME})
{
$room->{READINGS}{"desired-temp"}{VAL} = 6.0;
$room->{READINGS}{"desired-temp"}{TIME} = TimeNow();
readingsSingleUpdate ($room, "desired-temp", 6.0, 0);
}
if (!$room->{READINGS}{oldpulse}{TIME})
{
$room->{READINGS}{oldpulse}{VAL} = 0.0;
$room->{READINGS}{oldpulse}{TIME} = TimeNow();
readingsSingleUpdate ($room, "oldpulse", 0.0, 0);
}
if (!$room->{READINGS}{lastswitch}{TIME})
{
$room->{READINGS}{lastswitch}{VAL} = time();
$room->{READINGS}{lastswitch}{TIME} = TimeNow();
readingsSingleUpdate ($room, "lastswitch", time(), 0);
}
$factor = $room->{FACTOR};
@ -850,6 +887,7 @@ PWMR_Attr(@)
$hash->{c_frostProtect} = 0;
} elsif ($attr eq "autoCalcTemp") {
$hash->{c_autoCalcTemp} = 1;
$hash->{STATE} = "Calculating";
}
}
@ -871,10 +909,15 @@ PWMR_Attr(@)
}
} elsif ($attr eq "autoCalcTemp") { # autoCalcTemp 0/1
if ($val eq 0 or $val eq 1) {
$hash->{c_autoCalcTemp} = $val;
if ($val eq 0) {
$hash->{c_autoCalcTemp} = 0;
$hash->{STATE} = "Manual";
} elsif ( $val eq 1) {
$hash->{c_autoCalcTemp} = 1;
$hash->{STATE} = "Calculating";
} elsif ($val eq "") {
$hash->{c_autoCalcTemp} = 1;
$hash->{STATE} = "Calculating";
} else {
return "valid values are 0 or 1";
}
@ -947,12 +990,18 @@ PWMR_Boost(@)
"temp($temperaturV) desired-temp($desiredTemp) -> boost");
my $now = time();
$room->{READINGS}{"desired-temp"}{TIME} = FmtDateTime($now + $boostDuration * 60);
$room->{READINGS}{"desired-temp"}{VAL} = $desiredTemp + $desiredOffset;
my $t = $room->{READINGS}{"desired-temp"}{VAL};
push @{$room->{CHANGED}}, "desired-temp $t";
DoTrigger($name, undef);
readingsBeginUpdate ($room);
readingsBulkUpdate ($room, "desired-temp", $desiredTemp + $desiredOffset);
readingsBulkUpdate ($room, "desired-temp-until", FmtDateTime($now + $boostDuration * 60));
readingsEndUpdate($room, 1);
#$room->{READINGS}{"desired-temp"}{TIME} = FmtDateTime($now + $boostDuration * 60);
#$room->{READINGS}{"desired-temp"}{VAL} = $desiredTemp + $desiredOffset;
#my $t = $room->{READINGS}{"desired-temp"}{VAL};
#push @{$room->{CHANGED}}, "desired-temp $t";
#DoTrigger($name, undef);
Log3 ($room, 4, "PWMR_Boost: $name ".
"set desiredtemp ".$room->{READINGS}{"desired-temp"}{TIME}." ".

View File

@ -6,6 +6,10 @@
#
# 21.09.15 GA update, use Log3
# 07.10.15 GA initial version published
# 13.10.15 GA add event-on-change-reading
# 13.10.15 GA add several readings
# 15.10.15 GA add reading for avg pulses
##############################################
# $Id:
@ -42,7 +46,6 @@ sub PWM_Set($@);
sub PWM_Define($$);
sub PWM_Calculate($);
sub PWM_Undef($$);
sub PWM_State($$$$);
sub PWM_CalcRoom(@);
my %roomsWaitOffset = ();
@ -57,9 +60,8 @@ PWM_Initialize($)
$hash->{SetFn} = "PWM_Set";
$hash->{DefFn} = "PWM_Define";
$hash->{UndefFn} = "PWM_Undef";
#$hash->{StateFn} = "PWM_State";
$hash->{AttrList} = "";
$hash->{AttrList} = "event-on-change-reading";
}
@ -77,6 +79,7 @@ PWM_Calculate($)
my %RoomsPulses = ();
my $roomsActive = 0;
my $newpulseSum = 0;
my $newpulseMax = 0;
my $wkey = "";
if($hash->{INTERVAL} > 0) {
@ -85,9 +88,11 @@ PWM_Calculate($)
Log3 ($hash, 3, "PWM_Calculate $name");
readingsBeginUpdate ($hash);
#$hash->{STATE} = "lastrun: ".TimeNow();
#$hash->{STATE} = "calculating";
readingsSingleUpdate ($hash, "lastrun", "calculating", 1);
readingsBulkUpdate ($hash, "lastrun", "calculating");
$hash->{STATE} = "lastrun: ".$hash->{READINGS}{lastrun}{TIME};
# loop over all devices
@ -127,6 +132,7 @@ PWM_Calculate($)
$roomsActive++;
$RoomsPulses{$d} = $newpulse;
$newpulseSum += $newpulse;
$newpulseMax = max($newpulseMax, $newpulse);
# $newstate ne "" -> state changed "on" -> "off" or "off" -> "on"
if ((int($hash->{MINONOFFTIME}) > 0) &&
@ -263,7 +269,6 @@ PWM_Calculate($)
#my $maxRoomsOn = $roomsActive * 0.6; # 11 rooms -> max 6 active
#$maxRoomsOn = (8 * 0.7) if ($roomsActive < 8);
# HERE
my $maxRoomsOn = $roomsActive - $hash->{NoRoomsToStayOff};
#
@ -309,8 +314,8 @@ PWM_Calculate($)
# $minRoomsOn = 0;
#}
# HERE
my $minRoomsOn = $hash->{NoRoomsToStayOn};
my $minRoomsOnList = "";
if ($minRoomsOn > 0) {
@ -322,9 +327,11 @@ PWM_Calculate($)
last if ($roomsCounted == $minRoomsOn);
Log3 ($hash, 3, "PWM_Calculate: loop $roomsCounted $room $RoomsPulses{$room}");
$minRoomsOnList .= "$room,";
$pulseSum += $RoomsPulses{$room};
$roomsCounted++;
}
$minRoomsOnList =~ s/,$//;
#if ($roomsActive == 0 or $hash->{NoRoomsToStayOnThreshold} == 0 or $newpulseSum/$roomsActive < $hash->{NoRoomsToStayOnThreshold}) {
@ -369,22 +376,36 @@ PWM_Calculate($)
#
# now process the calculated actions
#
my $cntRoomsOn = 0;
my $cntRoomsOff = 0;
my $pulseRoomsOn = 0;
my $pulseRoomsOff = 0;
foreach my $roomStay (sort keys %RoomsToStayOff) {
PWMR_SetRoom ($defs{$roomStay}, "");
$cntRoomsOff++;
$pulseRoomsOff += $RoomsPulses{$roomStay};
}
foreach my $roomStay (sort keys %RoomsToStayOn) {
PWMR_SetRoom ($defs{$roomStay}, "");
$cntRoomsOn++;
$pulseRoomsOn += $RoomsPulses{$roomStay};
}
foreach my $roomOff (sort keys %RoomsToSwitchOff) {
PWMR_SetRoom ($defs{$roomOff}, "off");
$cntRoomsOff++;
$pulseRoomsOff += $RoomsPulses{$roomOff};
}
foreach my $roomOn (sort keys %RoomsToSwitchOn) {
@ -393,7 +414,26 @@ PWM_Calculate($)
$roomsWaitOffset{$wkey} = 0;
PWMR_SetRoom ($defs{$roomOn}, "on");
$cntRoomsOn++;
$pulseRoomsOn += $RoomsPulses{$roomOn};
}
readingsBulkUpdate ($hash, "roomsActive", $roomsActive);
readingsBulkUpdate ($hash, "roomsOn", $cntRoomsOn);
readingsBulkUpdate ($hash, "roomsOff", $cntRoomsOff);
readingsBulkUpdate ($hash, "avgPulseRoomsOn", ($cntRoomsOn > 0 ? sprintf ("%.2f", $pulseRoomsOn / $cntRoomsOn) : 0));
readingsBulkUpdate ($hash, "avgPulseRoomsOff", ($cntRoomsOff > 0 ? sprintf ("%.2f", $pulseRoomsOff /$cntRoomsOff) : 0));
readingsBulkUpdate ($hash, "pulseMax", $newpulseMax);
readingsBulkUpdate ($hash, "pulseSum", $newpulseSum);
if ( $hash->{NoRoomsToStayOn} > 0) {
readingsBulkUpdate ($hash, "roomsToStayOn", $minRoomsOn);
readingsBulkUpdate ($hash, "roomsToStayOnList", $minRoomsOnList);
}
readingsEndUpdate($hash, 1);
# if(!$hash->{LOCAL}) {
# DoTrigger($name, undef) if($init_done);
@ -662,26 +702,6 @@ sub PWM_Undef($$)
return undef;
}
###################################
sub PWM_State($$$$)
{
my ($hash, $time, $var, $value) = @_;
my $name = $hash->{NAME};
Log3 ($hash, 3, "PWM States $name: $time $var $value");
$hash->{READINGS}{$var}{VAL} = $value;
$hash->{READINGS}{$var}{TIME} = $time;
#if ($var =~ /INTERVAL|SCOPE|CYCLETIME/)
#{
# Log3 ($hash, 3, "PWM States $name: set $var $value");
# $hash->{$var} = $value;
#}
return undef;
}
1;