2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 06:39:11 +00:00

fhem.pl: better support for deviating reading/event timestamps (Forum #113652)

git-svn-id: https://svn.fhem.de/fhem/trunk@22631 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2020-08-19 16:54:17 +00:00
parent d7bbc0389d
commit a220dacb66
4 changed files with 45 additions and 24 deletions

View File

@ -3112,6 +3112,7 @@ FW_Notify($$)
#Add READINGS #Add READINGS
if($events) { # It gets deleted sometimes (?) if($events) { # It gets deleted sometimes (?)
my $tn = TimeNow(); my $tn = TimeNow();
my $ct = $dev->{CHANGETIME};
my $max = int(@{$events}); my $max = int(@{$events});
for(my $i = 0; $i < $max; $i++) { for(my $i = 0; $i < $max; $i++) {
if($events->[$i] !~ /: /) { if($events->[$i] !~ /: /) {
@ -3127,7 +3128,8 @@ FW_Notify($$)
next if($readingName !~ m/^[A-Za-z\d_\.\-\/:]+$/); # Forum #70608,70844 next if($readingName !~ m/^[A-Za-z\d_\.\-\/:]+$/); # Forum #70608,70844
push @data, FW_longpollInfo($h->{fmt}, push @data, FW_longpollInfo($h->{fmt},
"$dn-$readingName", $readingVal,$readingVal); "$dn-$readingName", $readingVal,$readingVal);
push @data, FW_longpollInfo($h->{fmt}, "$dn-$readingName-ts", $tn, $tn); my $t = (($ct && $ct->[$i]) ? $ct->[$i] : $tn);
push @data, FW_longpollInfo($h->{fmt}, "$dn-$readingName-ts", $t, $t);
} }
} }
} }

View File

@ -1279,12 +1279,14 @@ The following local attributes are used by a wider range of devices:
<a name="setreading"></a> <a name="setreading"></a>
<h3>setreading</h3> <h3>setreading</h3>
<ul> <ul>
<code>setreading &lt;devspec&gt; &lt;reading&gt; &lt;value&gt;</code> <code>setreading &lt;devspec&gt; [YYYY-MM-DD HH:MM:SS] &lt;reading&gt;
&lt;value&gt;</code>
<br><br> <br><br>
Set the reading &lt;reading&gt; for the device <code>&lt;name&gt;</code> to Set the reading &lt;reading&gt; for the device <code>&lt;name&gt;</code> to
&lt;value&gt; without sending out commands to the device, but triggering &lt;value&gt; without sending out commands to the device, but triggering
events and eventMap/stateFormat transformations as usual. See the set events and eventMap/stateFormat transformations as usual. See the set
command documentation for replacement description. command documentation for replacement description.<br>
If the timespec is omitted (default) the current time will be used.
<br><br> <br><br>
Examples: Examples:
<ul> <ul>

View File

@ -1361,12 +1361,14 @@ Die folgenden lokalen Attribute werden von mehreren Ger&auml;ten verwendet:
<a name="setreading"></a> <a name="setreading"></a>
<h3>setreading</h3> <h3>setreading</h3>
<ul> <ul>
<code>setreading &lt;devspec&gt; &lt;reading&gt; &lt;value&gt;</code> <code>setreading &lt;devspec&gt; [YYYY-MM-DD HH:MM:SS] &lt;reading&gt;
&lt;value&gt;</code>
<br><br> <br><br>
Der Befehl setzt das Reading &lt;reading&gt; auf den Wert &lt;value&gt; ohne Der Befehl setzt das Reading &lt;reading&gt; auf den Wert &lt;value&gt; ohne
Signale an das betroffene Ger&auml;t zu senden, generiert aber Ereignisse und Signale an das betroffene Ger&auml;t zu senden, generiert aber Ereignisse und
die &uuml;bliche eventMap und stateFormat Umwandlung wird auch die &uuml;bliche eventMap und stateFormat Umwandlung wird auch
durchgef&uuml;hrt. durchgef&uuml;hrt.<br>
Falls keine Zeit spezifiziert wurde, wird die aktuelle Uhrzeit verwendet.
<br> <br>
Siehe den Abschnitt &uuml;ber <a href="#devspec">Ger&auml;te-Spezifikation</a> Siehe den Abschnitt &uuml;ber <a href="#devspec">Ger&auml;te-Spezifikation</a>
f&uuml;r Details der &lt;devspec&gt; und die Beschreibung des set Befehls f&uuml;r Details der &lt;devspec&gt; und die Beschreibung des set Befehls

View File

@ -111,7 +111,7 @@ sub TimeNow();
sub Value($); sub Value($);
sub WriteStatefile(); sub WriteStatefile();
sub XmlEscape($); sub XmlEscape($);
sub addEvent($$); sub addEvent($$;$);
sub addToDevAttrList($$); sub addToDevAttrList($$);
sub applyGlobalAttrFromEnv(); sub applyGlobalAttrFromEnv();
sub delFromDevAttrList($$); sub delFromDevAttrList($$);
@ -150,7 +150,7 @@ sub perlSyntaxCheck($%);
sub readingsBeginUpdate($); sub readingsBeginUpdate($);
sub readingsBulkUpdate($$$@); sub readingsBulkUpdate($$$@);
sub readingsEndUpdate($$); sub readingsEndUpdate($$);
sub readingsSingleUpdate($$$$); sub readingsSingleUpdate($$$$;$);
sub readingsDelete($$); sub readingsDelete($$);
sub redirectStdinStdErr(); sub redirectStdinStdErr();
sub rejectDuplicate($$$); sub rejectDuplicate($$$);
@ -457,7 +457,8 @@ my %ra = (
"set" => { Fn=>"CommandSet", "set" => { Fn=>"CommandSet",
Hlp=>"<devspec> <type-specific>,transmit code for <devspec>" }, Hlp=>"<devspec> <type-specific>,transmit code for <devspec>" },
"setreading" => { Fn=>"CommandSetReading", "setreading" => { Fn=>"CommandSetReading",
Hlp=>"<devspec> <reading> <value>,set reading for <devspec>" }, Hlp=>"<devspec> [YYYY-MM-DD HH:MM:SS] <reading> <value>,".
"set reading for <devspec>" },
"setstate"=> { Fn=>"CommandSetstate", "setstate"=> { Fn=>"CommandSetstate",
Hlp=>"<devspec> <state>,set the state shown in the command list" }, Hlp=>"<devspec> <state>,set the state shown in the command list" },
"setuuid" => { Fn=>"CommandSetuuid", Hlp=>"" }, "setuuid" => { Fn=>"CommandSetuuid", Hlp=>"" },
@ -2416,9 +2417,16 @@ sub
CommandSetReading($$) CommandSetReading($$)
{ {
my ($cl, $def) = @_; my ($cl, $def) = @_;
my $timestamp;
if($def =~ m/^([^ ]+) +(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d) +([^ ]+) +(.*)$/) {
$def = "$1 $3 $4";
$timestamp = $2;
}
my @a = split(" ", $def, 3); my @a = split(" ", $def, 3);
return "Usage: setreading <name> <reading> <value>\n$namedef" if(@a != 3); return "Usage: setreading <name> [YYYY-MM-DD HH:MM:SS] <reading> <value>\n".
$namedef if(@a != 3);
my $err; my $err;
my @b = @a; my @b = @a;
@ -2443,7 +2451,7 @@ CommandSetReading($$)
Log 1, "'setreading $def' called form userReadings is prohibited"; Log 1, "'setreading $def' called form userReadings is prohibited";
return; return;
} else { } else {
readingsSingleUpdate($hash, $b1, $b[2], 1); readingsSingleUpdate($hash, $b1, $b[2], 1, $timestamp);
} }
} }
return join("\n", @rets); return join("\n", @rets);
@ -3732,6 +3740,12 @@ DoTrigger($$@)
################ ################
# Inform # Inform
if($hash->{CHANGED}) { # It gets deleted sometimes (?) if($hash->{CHANGED}) { # It gets deleted sometimes (?)
my $tn = $now;
if($attr{global}{mseclog}) {
my ($seconds, $microseconds) = gettimeofday();
$tn .= sprintf(".%03d", $microseconds/1000);
}
my $ct = $hash->{CHANGETIME};
foreach my $c (keys %inform) { foreach my $c (keys %inform) {
my $dc = $defs{$c}; my $dc = $defs{$c};
if(!$dc || $dc->{NR} != $inform{$c}{NR}) { if(!$dc || $dc->{NR} != $inform{$c}{NR}) {
@ -3739,18 +3753,14 @@ DoTrigger($$@)
next; next;
} }
next if($inform{$c}{type} eq "raw"); next if($inform{$c}{type} eq "raw");
my $tn = $now;
if($attr{global}{mseclog}) {
my ($seconds, $microseconds) = gettimeofday();
$tn .= sprintf(".%03d", $microseconds/1000);
}
my $re = $inform{$c}{regexp}; my $re = $inform{$c}{regexp};
my $events = deviceEvents($hash, $inform{$c}{type} =~ m/WithState/); my $events = deviceEvents($hash, $inform{$c}{type} =~ m/WithState/);
$max = int(@{$events}); $max = int(@{$events});
for(my $i = 0; $i < $max; $i++) { for(my $i = 0; $i < $max; $i++) {
my $event = $events->[$i]; my $event = $events->[$i];
my $t = (($ct && $ct->[$i]) ? $ct->[$i] : $tn);
next if($re && !($dev =~ m/$re/ || "$dev:$event" =~ m/$re/)); next if($re && !($dev =~ m/$re/ || "$dev:$event" =~ m/$re/));
addToWritebuffer($dc,($inform{$c}{type} eq "timer" ? "$tn " : ""). addToWritebuffer($dc,($inform{$c}{type} eq "timer" ? "$t " : "").
"$hash->{TYPE} $dev $event\n"); "$hash->{TYPE} $dev $event\n");
} }
} }
@ -4612,10 +4622,14 @@ setReadingsVal($$$$)
} }
sub sub
addEvent($$) addEvent($$;$)
{ {
my ($hash,$event) = @_; my ($hash,$event,$timestamp) = @_;
push(@{$hash->{CHANGED}}, $event); push(@{$hash->{CHANGED}}, $event);
if($timestamp) {
$hash->{CHANGETIME} = [] if(!defined($hash->{CHANGETIME}));
$hash->{CHANGETIME}->[@{$hash->{CHANGED}}-1] = $timestamp;
}
} }
sub sub
@ -4817,7 +4831,7 @@ readingsBulkUpdateIfChanged($$$@) # Forum #58797
sub sub
readingsBulkUpdate($$$@) readingsBulkUpdate($$$@)
{ {
my ($hash,$reading,$value,$changed)= @_; my ($hash,$reading,$value,$changed,$timestamp)= @_;
my $name= $hash->{NAME}; my $name= $hash->{NAME};
return if(!defined($reading) || !defined($value)); return if(!defined($reading) || !defined($value));
@ -4947,7 +4961,8 @@ readingsBulkUpdate($$$@)
} }
setReadingsVal($hash, $reading, $value, $hash->{".updateTimestamp"}) setReadingsVal($hash, $reading, $value,
$timestamp ? $timestamp : $hash->{".updateTimestamp"})
if($update_timestamp); if($update_timestamp);
my $rv = "$reading: $value"; my $rv = "$reading: $value";
@ -4956,7 +4971,7 @@ readingsBulkUpdate($$$@)
$rv = $value; $rv = $value;
$hash->{CHANGEDWITHSTATE} = []; $hash->{CHANGEDWITHSTATE} = [];
} }
addEvent($hash, $rv); addEvent($hash, $rv, $timestamp);
} }
return $rv; return $rv;
} }
@ -4965,11 +4980,11 @@ readingsBulkUpdate($$$@)
# this is a shorthand call # this is a shorthand call
# #
sub sub
readingsSingleUpdate($$$$) readingsSingleUpdate($$$$;$)
{ {
my ($hash,$reading,$value,$dotrigger)= @_; my ($hash,$reading,$value,$dotrigger,$timestamp)= @_;
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
my $rv = readingsBulkUpdate($hash,$reading,$value); my $rv = readingsBulkUpdate($hash, $reading, $value, undef, $timestamp);
readingsEndUpdate($hash,$dotrigger); readingsEndUpdate($hash,$dotrigger);
return $rv; return $rv;
} }