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:
parent
d7bbc0389d
commit
a220dacb66
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 <devspec> <reading> <value></code>
|
<code>setreading <devspec> [YYYY-MM-DD HH:MM:SS] <reading>
|
||||||
|
<value></code>
|
||||||
<br><br>
|
<br><br>
|
||||||
Set the reading <reading> for the device <code><name></code> to
|
Set the reading <reading> for the device <code><name></code> to
|
||||||
<value> without sending out commands to the device, but triggering
|
<value> 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>
|
||||||
|
@ -1361,12 +1361,14 @@ Die folgenden lokalen Attribute werden von mehreren Geräten verwendet:
|
|||||||
<a name="setreading"></a>
|
<a name="setreading"></a>
|
||||||
<h3>setreading</h3>
|
<h3>setreading</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<code>setreading <devspec> <reading> <value></code>
|
<code>setreading <devspec> [YYYY-MM-DD HH:MM:SS] <reading>
|
||||||
|
<value></code>
|
||||||
<br><br>
|
<br><br>
|
||||||
Der Befehl setzt das Reading <reading> auf den Wert <value> ohne
|
Der Befehl setzt das Reading <reading> auf den Wert <value> ohne
|
||||||
Signale an das betroffene Gerät zu senden, generiert aber Ereignisse und
|
Signale an das betroffene Gerät zu senden, generiert aber Ereignisse und
|
||||||
die übliche eventMap und stateFormat Umwandlung wird auch
|
die übliche eventMap und stateFormat Umwandlung wird auch
|
||||||
durchgeführt.
|
durchgeführt.<br>
|
||||||
|
Falls keine Zeit spezifiziert wurde, wird die aktuelle Uhrzeit verwendet.
|
||||||
<br>
|
<br>
|
||||||
Siehe den Abschnitt über <a href="#devspec">Geräte-Spezifikation</a>
|
Siehe den Abschnitt über <a href="#devspec">Geräte-Spezifikation</a>
|
||||||
für Details der <devspec> und die Beschreibung des set Befehls
|
für Details der <devspec> und die Beschreibung des set Befehls
|
||||||
|
53
fhem/fhem.pl
53
fhem/fhem.pl
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user