mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 12:49:34 +00:00
98_Modbus.pm: small bugfix regarding update timer
git-svn-id: https://svn.fhem.de/fhem/trunk@17880 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
1ed4a9cea9
commit
5834221233
@ -124,6 +124,7 @@
|
||||
# 2018-10-12 smaller bugfixes, new attributes enableQueueLengthReading and retriesAfterTimeout
|
||||
# 2018-11-05 use DevIO_IsOpen, check if fc6 can be used or fc16 needs to be used, rework open calls
|
||||
# 2018-11-10 fixed setExpr -> setexpr
|
||||
# 2018-12-01 fixed bug in startUpdateTimer when interval > timeout of a slave
|
||||
#
|
||||
#
|
||||
#
|
||||
@ -305,9 +306,9 @@ sub ModbusLD_Set($@);
|
||||
sub ModbusLD_GetUpdate($);
|
||||
sub ModbusLD_GetIOHash($);
|
||||
sub ModbusLD_DoRequest($$$;$$$);
|
||||
sub ModbusLD_StartUpdateTimer($;$);
|
||||
sub ModbusLD_StartUpdateTimer($);
|
||||
|
||||
my $Modbus_Version = '4.0.17 - 10.11.2018';
|
||||
my $Modbus_Version = '4.0.18 - 1.12.2018';
|
||||
my $Modbus_PhysAttrs =
|
||||
"queueDelay " .
|
||||
"queueMax " .
|
||||
@ -585,8 +586,6 @@ sub ModbusLD_Define($$)
|
||||
$hash->{MODBUSID} = $id;
|
||||
$hash->{MODE} = $mode;
|
||||
$hash->{PROTOCOL} = $proto;
|
||||
$hash->{INTERVAL} = $interval if ($interval);
|
||||
$hash->{RELAY} = $relay if ($relay);
|
||||
$hash->{'.getList'} = "";
|
||||
$hash->{'.setList'} = "";
|
||||
$hash->{".updateSetGet"} = 1;
|
||||
@ -594,6 +593,17 @@ sub ModbusLD_Define($$)
|
||||
$hash->{NOTIFYDEV} = "global"; # NotifyFn nur aufrufen wenn global events (INITIALIZED etc.)
|
||||
$hash->{MODULEVERSION} = "Modbus $Modbus_Version";
|
||||
|
||||
if ($interval) {
|
||||
$hash->{INTERVAL} = $interval;
|
||||
} else {
|
||||
delete $hash->{INTERVAL};
|
||||
}
|
||||
if ($relay) {
|
||||
$hash->{RELAY} = $relay;
|
||||
} else {
|
||||
delete $hash->{RELAY};
|
||||
}
|
||||
|
||||
if ($dest) { # Modbus über TCP mit IP Adresse (TCP oder auch RTU/ASCII über TCP)
|
||||
$dest .= ":502" if ($dest !~ /.*:[0-9]/); # add default port if no port specified
|
||||
$hash->{DeviceName} = $dest; # needed by DevIo to get Device, Port, Speed etc.
|
||||
@ -835,7 +845,7 @@ sub ModbusLD_Attr(@)
|
||||
Log3 $name, 3, "$name: no IODev for communication";
|
||||
}
|
||||
}
|
||||
ModbusLD_StartUpdateTimer($hash, 1); # first Update in 1 second or aligned if interval is defined
|
||||
ModbusLD_StartUpdateTimer($hash); # first Update in 1 second or aligned if interval is defined
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -1479,7 +1489,7 @@ sub Modbus_Notify($$)
|
||||
}
|
||||
# logical device going through an IO Device
|
||||
if ($hash->{TYPE} ne "Modbus" && $hash->{MODE} eq 'master') {
|
||||
ModbusLD_StartUpdateTimer($hash, 1); # logical device -> first Update in 1 second or aligned if interval is defined
|
||||
ModbusLD_StartUpdateTimer($hash); # logical device -> first Update in 1 second or aligned if interval is defined
|
||||
|
||||
# relay device to communicate through
|
||||
} elsif ($hash->{MODE} && $hash->{MODE} eq 'relay') { # Mode relay -> find / check relay device
|
||||
@ -3551,31 +3561,61 @@ sub Modbus_Send($$$;$)
|
||||
# set internal Timer to call GetUpdate if necessary
|
||||
# either at next interval
|
||||
# or if start is passed in start seconds (e.g. 2 seconds after Fhem init)
|
||||
sub ModbusLD_StartUpdateTimer($;$)
|
||||
# called from attr (disable, alignTime), set (interval, start), openCB,
|
||||
# notify (INITIALIZED|REREADCFG|MODIFIED|DEFINED) and getUpdate
|
||||
|
||||
# problem: when disconected while waiting for next update cycle,
|
||||
# StartUpdateTimer gets called after immediate reopen.
|
||||
# Timer should be set as short as possible (>= lastUpdate + Interval)
|
||||
# or if timeAlign, then
|
||||
|
||||
|
||||
# how to set timer after a new open?
|
||||
# if timer is still running, just keep it
|
||||
# but maybe alignTime was set in the meantime -> timer needs new alignment now or after next update
|
||||
# if alignTime didn't change, timer can be kept.
|
||||
#
|
||||
# if timer is not running and last update was longer ago than interval, schedule update to happen immediately
|
||||
#
|
||||
|
||||
sub ModbusLD_StartUpdateTimer($)
|
||||
{
|
||||
my ($hash, $start) = @_;
|
||||
my $nextTrigger;
|
||||
my $name = $hash->{NAME};
|
||||
my $now = gettimeofday();
|
||||
$start = 0 if (!$start);
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $now = gettimeofday();
|
||||
my $action = "updated timer";
|
||||
my $intvl = ($hash->{INTERVAL} ? $hash->{INTERVAL} : 0);
|
||||
my $delay;
|
||||
my $nextUpdate;
|
||||
|
||||
#Log3 $name, 5, "$name: StartUpdateTimer called from " . Modbus_Caller();
|
||||
|
||||
if ($hash->{INTERVAL} && $hash->{INTERVAL} > 0) {
|
||||
Log3 $name, 5, "$name: StartUpdateTimer called from " . Modbus_Caller();
|
||||
if ($intvl > 0) { # there is an interval -> set timer
|
||||
if ($hash->{TimeAlign}) {
|
||||
my $count = int(($now - $hash->{TimeAlign} + $start) / $hash->{INTERVAL});
|
||||
my $curCycle = $hash->{TimeAlign} + $count * $hash->{INTERVAL};
|
||||
$nextTrigger = $curCycle + $hash->{INTERVAL};
|
||||
# it doesn't matter when last update was, or if timer is still set. we can always calculate next update
|
||||
my $start = ($hash->{lastUpdate} ? 0 : 2); # first update at least 2 secs from now
|
||||
my $count = int(($now - $hash->{TimeAlign} + $start) / $intvl);
|
||||
$nextUpdate = $hash->{TimeAlign} + $count * $intvl + $intvl;
|
||||
|
||||
} elsif ($hash->{TRIGGERTIME} && $hash->{TRIGGERTIME} <= ($now + $intvl)) {
|
||||
# timer is still set and shorter than new calculation -> keep and log
|
||||
$action = "kept existing timer";
|
||||
$nextUpdate = $hash->{TRIGGERTIME};
|
||||
} elsif (!$hash->{lastUpdate}) {
|
||||
# first time timer is set
|
||||
$action = "initialisation";
|
||||
$nextUpdate = $now + 2;
|
||||
} else {
|
||||
$nextTrigger = $now + ($start ? $start : $hash->{INTERVAL});
|
||||
$nextUpdate = $hash->{lastUpdate} + $intvl;
|
||||
$nextUpdate = $now if ($nextUpdate < $now );
|
||||
}
|
||||
$hash->{TRIGGERTIME} = $nextTrigger;
|
||||
$hash->{TRIGGERTIME_FMT} = FmtDateTime($nextTrigger);
|
||||
$hash->{TRIGGERTIME} = $nextUpdate;
|
||||
$hash->{TRIGGERTIME_FMT} = FmtDateTime($nextUpdate);
|
||||
$delay = sprintf ("%.1f", $nextUpdate - $now);
|
||||
Log3 $name, 5, "$name: SetartUpdateTimer $action, will call GetUpdate in $delay sec at $hash->{TRIGGERTIME_FMT}, interval $intvl";
|
||||
RemoveInternalTimer("update:$name");
|
||||
InternalTimer($nextTrigger, "ModbusLD_GetUpdate", "update:$name", 0);
|
||||
Log3 $name, 4, "$name: SetUpdateTimer updated timer - will call GetUpdate in " .
|
||||
sprintf ("%.1f", $nextTrigger - $now) . " seconds at $hash->{TRIGGERTIME_FMT} - Interval $hash->{INTERVAL}";
|
||||
} else {
|
||||
InternalTimer($nextUpdate, "ModbusLD_GetUpdate", "update:$name", 0);
|
||||
|
||||
} else { # no interval -> no timer
|
||||
ModbusLD_StopUpdateTimer($hash);
|
||||
}
|
||||
return;
|
||||
@ -3593,6 +3633,7 @@ sub ModbusLD_StopUpdateTimer($)
|
||||
Log3 $name, 4, "$name: internal update interval timer stopped";
|
||||
delete $hash->{TRIGGERTIME};
|
||||
delete $hash->{TRIGGERTIME_FMT};
|
||||
$hash->{TRIGGERTIME_SAVED} = $hash->{TRIGGERTIME};
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -3617,7 +3658,10 @@ sub ModbusLD_GetUpdate($) {
|
||||
my $now = gettimeofday();
|
||||
|
||||
Log3 $name, 5, "$name: GetUpdate called from " . Modbus_Caller();
|
||||
$hash->{lastUpdate} = $now;
|
||||
if ($calltype eq "update") {
|
||||
delete $hash->{TRIGGERTIME};
|
||||
delete $hash->{TRIGGERTIME_FMT};
|
||||
ModbusLD_StartUpdateTimer($hash);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user