2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-19 00:26:03 +00:00

98_PID20 : bugfix: immediate update of readings after start/stop action

git-svn-id: https://svn.fhem.de/fhem/trunk@10491 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
john99sr 2016-01-13 22:40:36 +00:00
parent 3ca8120029
commit d6c408cf25

View File

@ -52,6 +52,11 @@
# V 1.0.0.6 # V 1.0.0.6
# 12.11.2015 Fix: wrong evaluation of Sensor String, when value was 0 than sensor timeout was detected # 12.11.2015 Fix: wrong evaluation of Sensor String, when value was 0 than sensor timeout was detected
# Feature: added <Internal> VERSION # Feature: added <Internal> VERSION
# V 1.0.0.7 Feature: new attribute pidActorCallBeforeSetting for user specific callback
# before setting a new value to actor
# V 1.0.0.8 Feature: attribute handling accelerates some actions
# Fix: update of state triggers force a notify
# Fix: adjust commandref
#################################################################################################### ####################################################################################################
package main; package main;
@ -63,7 +68,7 @@ use vars qw($readingFnAttributes);
use vars qw(%attr); use vars qw(%attr);
use vars qw(%modules); use vars qw(%modules);
my $PID20_Version = "1.0.0.6"; my $PID20_Version = "1.0.0.8";
sub PID20_Calc($); sub PID20_Calc($);
######################################## ########################################
sub PID20_Log($$$) sub PID20_Log($$$)
@ -80,41 +85,55 @@ sub PID20_Log($$$)
sub PID20_Initialize($) sub PID20_Initialize($)
{ {
my ($hash) = @_; my ($hash) = @_;
$hash->{DefFn} = "PID20_Define"; $hash->{DefFn} = 'PID20_Define';
$hash->{UndefFn} = "PID20_Undef"; $hash->{UndefFn} = 'PID20_Undef';
$hash->{SetFn} = "PID20_Set"; $hash->{SetFn} = 'PID20_Set';
$hash->{GetFn} = "PID20_Get"; $hash->{GetFn} = 'PID20_Get';
$hash->{NotifyFn} = "PID20_Notify"; $hash->{NotifyFn} = 'PID20_Notify';
$hash->{AttrFn} = 'PID20_Attr';
$hash->{AttrList} = $hash->{AttrList} =
"pidActorValueDecPlaces:0,1,2,3,4,5 " 'pidActorValueDecPlaces:0,1,2,3,4,5 '
. "pidActorInterval " . 'pidActorInterval '
. "pidActorTreshold " . 'pidActorTreshold '
. "pidActorErrorAction:freeze,errorPos " . 'pidActorErrorAction:freeze,errorPos '
. "pidActorErrorPos " . 'pidActorErrorPos '
. "pidActorKeepAlive " . 'pidActorKeepAlive '
. "pidActorLimitLower " . 'pidActorLimitLower '
. "pidActorLimitUpper " . 'pidActorLimitUpper '
. "pidCalcInterval " . 'pidActorCallBeforeSetting '
. "pidDeltaTreshold " . 'pidCalcInterval '
. "pidDesiredName " . 'pidDeltaTreshold '
. "pidFactor_P " . 'pidDesiredName '
. "pidFactor_I " . 'pidFactor_P '
. "pidFactor_D " . 'pidFactor_I '
. "pidMeasuredName " . 'pidFactor_D '
. "pidSensorTimeout " . 'pidMeasuredName '
. "pidReverseAction " . 'pidSensorTimeout '
. "pidUpdateInterval " . 'pidReverseAction '
. 'pidUpdateInterval '
# . "pidDebugEnable:0,1 "; . 'pidDebugSensor:0,1 '
. "pidDebugSensor:0,1 " . 'pidDebugActuation:0,1 '
. "pidDebugActuation:0,1 " . 'pidDebugCalc:0,1 '
. "pidDebugCalc:0,1 " . 'pidDebugDelta:0,1 '
. "pidDebugDelta:0,1 " . 'pidDebugUpdate:0,1 '
. "pidDebugUpdate:0,1 " . 'pidDebugNotify:0,1 '
. "pidDebugNotify:0,1 " . 'disable:0,1 '
. "disable:0,1 "
. $readingFnAttributes; . $readingFnAttributes;
} }
##########################
sub PID20_RestartTimer($$)
{
my ( $hash, $seconds ) = @_;
my $name = $hash->{NAME};
$seconds = 1 if ( $seconds <= 0 );
RemoveInternalTimer($name);
my $sdNextScan = gettimeofday() + $seconds;
InternalTimer( $sdNextScan, 'PID20_Calc', $name, 0 );
PID20_Log $hash, 5, 'name:'.$name.' seconds:'.$seconds;
}
######################################## ########################################
sub PID20_TimeDiff($) sub PID20_TimeDiff($)
{ {
@ -159,6 +178,7 @@ sub PID20_Define($$$)
} }
$hash->{helper}{sensor} = $sensor; $hash->{helper}{sensor} = $sensor;
$hash->{VERSION} = $PID20_Version; $hash->{VERSION} = $PID20_Version;
# defaults for regexp # defaults for regexp
if ( !$regexp ) if ( !$regexp )
{ {
@ -335,13 +355,14 @@ sub PID20_Set($@)
return 'Set start needs a <value> parameter' return 'Set start needs a <value> parameter'
if ( @a != 2 ); if ( @a != 2 );
$hash->{helper}{stopped} = 0; $hash->{helper}{stopped} = 0;
PID20_RestartTimer($hash,1);
} }
when ('stop') when ('stop')
{ {
return 'Set stop needs a <value> parameter' return 'Set stop needs a <value> parameter'
if ( @a != 2 ); if ( @a != 2 );
$hash->{helper}{stopped} = 1; $hash->{helper}{stopped} = 1;
PID20_Calc($name); PID20_RestartTimer($hash,1);
} }
when ('restart') when ('restart')
{ {
@ -355,6 +376,7 @@ sub PID20_Set($@)
if ( !defined($value) ); if ( !defined($value) );
$hash->{helper}{stopped} = 0; $hash->{helper}{stopped} = 0;
$hash->{helper}{adjust} = $value; $hash->{helper}{adjust} = $value;
PID20_RestartTimer($hash,1);
PID20_Log $hash, 3, "set $name $cmd $value"; PID20_Log $hash, 3, "set $name $cmd $value";
} }
when ("calc") # inofficial function, only for debugging purposes when ("calc") # inofficial function, only for debugging purposes
@ -467,7 +489,7 @@ sub PID20_Calc($)
$stateStr = "alarm - no $reading yet for $sensor" if ( $sensorStr eq '' && $stateStr eq '' ); $stateStr = "alarm - no $reading yet for $sensor" if ( $sensorStr eq '' && $stateStr eq '' );
# sensor alive # sensor alive
if ( $sensorStr ne '' && $sensorTS ) if ( $sensorStr ne '' && $sensorTS )
{ {
my $timeDiff = PID20_TimeDiff($sensorTS); my $timeDiff = PID20_TimeDiff($sensorTS);
$sensorIsAlive = 1 if ( $timeDiff <= $hash->{helper}{sensorTimeout} ); $sensorIsAlive = 1 if ( $timeDiff <= $hash->{helper}{sensorTimeout} );
@ -645,14 +667,19 @@ sub PID20_Calc($)
{ {
$readingUpdateReq = 1; # update the readings $readingUpdateReq = 1; # update the readings
my $actorCallBeforeSetting = AttrVal( $name, 'pidActorCallBeforeSetting', undef );
if ( defined($actorCallBeforeSetting) && exists &$actorCallBeforeSetting )
{
PID20_Log $hash, 5, 'start callback ' . $actorCallBeforeSetting . ' with actuation:' . $actuation;
no strict "refs";
$actuation = &$actorCallBeforeSetting( $name, $actuation );
use strict "refs";
PID20_Log $hash, 5, 'return value of ' . $actorCallBeforeSetting . ':' . $actuation;
}
#build command for fhem #build command for fhem
PID20_Log $hash, 5, PID20_Log $hash, 5, 'actor:' . $hash->{helper}{actor} . ' actorCommand:' . $hash->{helper}{actorCommand}
'actor:' . ' actuation:' . $actuation;
. $hash->{helper}{actor}
. ' actorCommand:'
. $hash->{helper}{actorCommand}
. ' actuation:'
. $actuation;
my $cmd = sprintf( "set %s %s %g", $hash->{helper}{actor}, $hash->{helper}{actorCommand}, $actuation ); my $cmd = sprintf( "set %s %s %g", $hash->{helper}{actor}, $hash->{helper}{actorCommand}, $actuation );
# execute command # execute command
@ -692,9 +719,9 @@ sub PID20_Calc($)
} # end while } # end while
# ........ update statePID. # ........ update statePID.
$stateStr = 'idle' if ( $stateStr eq '' && !$calcReq ); $stateStr = 'idle' if ( $stateStr eq '' && !$calcReq );
$stateStr = 'processing' if ( $stateStr eq '' && $calcReq ); $stateStr = 'processing' if ( $stateStr eq '' && $calcReq );
readingsSingleUpdate( $hash, 'state', $stateStr, 0 ); readingsSingleUpdate( $hash, 'state', $stateStr, 1 );
PID20_Log $hash, 2, "C1 stateStr:$stateStr calcReq:$calcReq" if ($DEBUG_Calc); PID20_Log $hash, 2, "C1 stateStr:$stateStr calcReq:$calcReq" if ($DEBUG_Calc);
#......... timer setup #......... timer setup
@ -705,6 +732,27 @@ sub PID20_Calc($)
#PID20_Log $hash, 2, "InternalTimer next:".FmtDateTime($next)." PID20_Calc name:$name DEBUG_Calc:$DEBUG_Calc"; #PID20_Log $hash, 2, "InternalTimer next:".FmtDateTime($next)." PID20_Calc name:$name DEBUG_Calc:$DEBUG_Calc";
return; return;
} }
########################################
# attribute handling
sub PID20_Attr($$$$)
{
my ( $command, $name, $attribute, $value ) = @_;
my $msg = undef;
my $hash = $defs{$name};
my $reUINT = '^([\\+]?\\d+)$';
PID20_Log $hash, 5, 'name:' . $name . ' attribute:' . $attribute . ' value:' . $value . ' command:' . $command;
if ( $attribute eq 'disable' )
{
# PID20_Log $hash, 5, 'disable';
PID20_RestartTimer($hash,2);
}
return $msg;
}
1; 1;
=pod =pod
@ -792,6 +840,21 @@ sub PID20_Calc($)
<li><b>pidSensorTimeout</b> - number of seconds to wait before sensor will be recognized n/a; default: 3600</li> <li><b>pidSensorTimeout</b> - number of seconds to wait before sensor will be recognized n/a; default: 3600</li>
<li><b>pidReverseAction</b> - reverse PID operation mode, possible values: 0,1; default: 0</li> <li><b>pidReverseAction</b> - reverse PID operation mode, possible values: 0,1; default: 0</li>
<li><b>pidUpdateInterval</b> - number of seconds to wait before an update will be forced for plotting; default: 300</li> <li><b>pidUpdateInterval</b> - number of seconds to wait before an update will be forced for plotting; default: 300</li>
<li><b>pidActorCallBeforeSetting</b> - an optional callback-function,which can manipulate the actorValue; default: not defined
<pre>
# Exampe for callback-function
# 1. argument = name of PID20
# 2. argument = current actor value
sub PIDActorSet($$)
{
my ( $name, $actValue ) = @_;
if ($actValue>70)
{
$actValue=100;
}
return $actValue;
}</pre>
</li>
</ul> </ul>
<br/><br/> <br/><br/>