2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-08 13:24:56 +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
# 12.11.2015 Fix: wrong evaluation of Sensor String, when value was 0 than sensor timeout was detected
# 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;
@ -63,7 +68,7 @@ use vars qw($readingFnAttributes);
use vars qw(%attr);
use vars qw(%modules);
my $PID20_Version = "1.0.0.6";
my $PID20_Version = "1.0.0.8";
sub PID20_Calc($);
########################################
sub PID20_Log($$$)
@ -80,41 +85,55 @@ sub PID20_Log($$$)
sub PID20_Initialize($)
{
my ($hash) = @_;
$hash->{DefFn} = "PID20_Define";
$hash->{UndefFn} = "PID20_Undef";
$hash->{SetFn} = "PID20_Set";
$hash->{GetFn} = "PID20_Get";
$hash->{NotifyFn} = "PID20_Notify";
$hash->{DefFn} = 'PID20_Define';
$hash->{UndefFn} = 'PID20_Undef';
$hash->{SetFn} = 'PID20_Set';
$hash->{GetFn} = 'PID20_Get';
$hash->{NotifyFn} = 'PID20_Notify';
$hash->{AttrFn} = 'PID20_Attr';
$hash->{AttrList} =
"pidActorValueDecPlaces:0,1,2,3,4,5 "
. "pidActorInterval "
. "pidActorTreshold "
. "pidActorErrorAction:freeze,errorPos "
. "pidActorErrorPos "
. "pidActorKeepAlive "
. "pidActorLimitLower "
. "pidActorLimitUpper "
. "pidCalcInterval "
. "pidDeltaTreshold "
. "pidDesiredName "
. "pidFactor_P "
. "pidFactor_I "
. "pidFactor_D "
. "pidMeasuredName "
. "pidSensorTimeout "
. "pidReverseAction "
. "pidUpdateInterval "
# . "pidDebugEnable:0,1 ";
. "pidDebugSensor:0,1 "
. "pidDebugActuation:0,1 "
. "pidDebugCalc:0,1 "
. "pidDebugDelta:0,1 "
. "pidDebugUpdate:0,1 "
. "pidDebugNotify:0,1 "
. "disable:0,1 "
'pidActorValueDecPlaces:0,1,2,3,4,5 '
. 'pidActorInterval '
. 'pidActorTreshold '
. 'pidActorErrorAction:freeze,errorPos '
. 'pidActorErrorPos '
. 'pidActorKeepAlive '
. 'pidActorLimitLower '
. 'pidActorLimitUpper '
. 'pidActorCallBeforeSetting '
. 'pidCalcInterval '
. 'pidDeltaTreshold '
. 'pidDesiredName '
. 'pidFactor_P '
. 'pidFactor_I '
. 'pidFactor_D '
. 'pidMeasuredName '
. 'pidSensorTimeout '
. 'pidReverseAction '
. 'pidUpdateInterval '
. 'pidDebugSensor:0,1 '
. 'pidDebugActuation:0,1 '
. 'pidDebugCalc:0,1 '
. 'pidDebugDelta:0,1 '
. 'pidDebugUpdate:0,1 '
. 'pidDebugNotify:0,1 '
. 'disable:0,1 '
. $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($)
{
@ -159,6 +178,7 @@ sub PID20_Define($$$)
}
$hash->{helper}{sensor} = $sensor;
$hash->{VERSION} = $PID20_Version;
# defaults for regexp
if ( !$regexp )
{
@ -335,13 +355,14 @@ sub PID20_Set($@)
return 'Set start needs a <value> parameter'
if ( @a != 2 );
$hash->{helper}{stopped} = 0;
PID20_RestartTimer($hash,1);
}
when ('stop')
{
return 'Set stop needs a <value> parameter'
if ( @a != 2 );
$hash->{helper}{stopped} = 1;
PID20_Calc($name);
PID20_RestartTimer($hash,1);
}
when ('restart')
{
@ -355,6 +376,7 @@ sub PID20_Set($@)
if ( !defined($value) );
$hash->{helper}{stopped} = 0;
$hash->{helper}{adjust} = $value;
PID20_RestartTimer($hash,1);
PID20_Log $hash, 3, "set $name $cmd $value";
}
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 '' );
# sensor alive
if ( $sensorStr ne '' && $sensorTS )
if ( $sensorStr ne '' && $sensorTS )
{
my $timeDiff = PID20_TimeDiff($sensorTS);
$sensorIsAlive = 1 if ( $timeDiff <= $hash->{helper}{sensorTimeout} );
@ -645,14 +667,19 @@ sub PID20_Calc($)
{
$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
PID20_Log $hash, 5,
'actor:'
. $hash->{helper}{actor}
. ' actorCommand:'
. $hash->{helper}{actorCommand}
. ' actuation:'
. $actuation;
PID20_Log $hash, 5, 'actor:' . $hash->{helper}{actor} . ' actorCommand:' . $hash->{helper}{actorCommand}
. ' actuation:' . $actuation;
my $cmd = sprintf( "set %s %s %g", $hash->{helper}{actor}, $hash->{helper}{actorCommand}, $actuation );
# execute command
@ -692,9 +719,9 @@ sub PID20_Calc($)
} # end while
# ........ update statePID.
$stateStr = 'idle' if ( $stateStr eq '' && !$calcReq );
$stateStr = 'idle' 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);
#......... 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";
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;
=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>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>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>
<br/><br/>