diff --git a/CHANGED b/CHANGED index 059ef9561..0a8fc3d65 100644 --- a/CHANGED +++ b/CHANGED @@ -1,5 +1,7 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - change: 19_Revolt: allow adjustment of energy value, filtering of + implausible values - bugfix: 72_XiaomiDevice: better handling of definition w/ missing token - change: 32_withings: add in_bed for sleep trackers, ignore inactive users - change: 57_Calendar: new attribute quirks with ignoreDtStamp value. diff --git a/FHEM/19_Revolt.pm b/FHEM/19_Revolt.pm index 5aa9eb79c..0657ab7a0 100644 --- a/FHEM/19_Revolt.pm +++ b/FHEM/19_Revolt.pm @@ -14,53 +14,52 @@ use Date::Parse; ##################################### -sub -Revolt_Initialize($) +sub Revolt_Initialize($) { my ($hash) = @_; -# r00C5E100303203C85921FF $hash->{Match} = "^r......................\$"; $hash->{DefFn} = "Revolt_Define"; $hash->{UndefFn} = "Revolt_Undef"; $hash->{ParseFn} = "Revolt_Parse"; $hash->{AttrList} = "IODev ". + "EnergyAdjustValue ". $readingFnAttributes; } ##################################### -sub -Revolt_Define($$) +sub Revolt_Define($$) { my ($hash, $def) = @_; my @a = split("[ \t][ \t]*", $def); return "wrong syntax: define Revolt " if(int(@a) != 3); $a[2] = lc($a[2]); - return "Define $a[0]: wrong format: specify a 4 digit hex value" - if($a[2] !~ m/^[a-f0-9][a-f0-9][a-f0-9][a-f0-9]$/); + return "Define $a[0]: wrong format: specify a 4 digit hex value" if($a[2] !~ m/^[a-f0-9][a-f0-9][a-f0-9][a-f0-9]$/); $hash->{ID} = $a[2]; #$hash->{STATE} = "Initialized"; $modules{REVOLT}{defptr}{$a[2]} = $hash; AssignIoPort($hash); + + my $name = $a[0]; + $attr{$name}{"event-aggregator"} = "power::none:median:120,energy::none:median:120,avgpower::none:median:120" if(!defined($attr{$name}{"event-aggregator"})); + $attr{$name}{"stateFormat"} = "P: power E: energy V: voltage C: current Pf: pf" if(!defined($attr{$name}{"stateFormat"})); + return undef; } ##################################### -sub -Revolt_Undef($$) +sub Revolt_Undef($$) { my ($hash, $name) = @_; - delete($modules{REVOLT}{defptr}{$hash->{ID}}) - if(defined($hash->{ID}) && - defined($modules{REVOLT}{defptr}{$hash->{ID}})); + delete($modules{REVOLT}{defptr}{$hash->{ID}}) if(defined($hash->{ID}) && + defined($modules{REVOLT}{defptr}{$hash->{ID}})); return undef; } ##################################### -sub -Revolt_Parse($$) +sub Revolt_Parse($$) { my ($hash, $msg) = @_; @@ -71,15 +70,14 @@ Revolt_Parse($$) my $val = substr($msg, 11, 22); my $id = substr($msg, 1, 4); my $voltage = hex(substr($msg, 5, 2)); - my $current = hex(substr($msg, 7, 4))*0.01; + my $current = hex(substr($msg, 7, 4)) * 0.01; my $freq = hex(substr($msg, 11, 2)); - my $power = hex(substr($msg, 13, 4))*0.1; - my $pf = hex(substr($msg, 17, 2))*0.01; - my $energy = hex(substr($msg, 19, 4))*0.01; - my $lastval; - my $avg; - + my $power = hex(substr($msg, 13, 4)) * 0.1; + my $pf = hex(substr($msg, 17, 2)) * 0.01; + my $energy = hex(substr($msg, 19, 4)) * 0.01; + my $lastval = 0.0; my $type = ""; + my $energyAdj = $energy; if(!defined($modules{REVOLT}{defptr}{$id})) { Log3 undef,3, "Unknown Revolt device $id, please define it"; @@ -91,38 +89,59 @@ Revolt_Parse($$) my $name = $def->{NAME}; return "" if(IsIgnored($name)); - my $state; - $state="P: ".sprintf("%5.1f",$power)." E: ".sprintf("%6.2f",$energy)." V: ".sprintf("%3d",$voltage)." C: ".sprintf("%6.2f",$current)." F: $freq Pf: ".sprintf("%4.2f",$pf); - - readingsBeginUpdate($def); - + # check if data is invalid if (defined($def->{READINGS}{".lastenergy"})) { - $lastval=$def->{READINGS}{".lastenergy"}{VAL}; - if ($lastval != $energy) { - $avg=(($lastval-$energy)*1000.0*3600.0)/(str2time($def->{READINGS}{".lastenergy"}{TIME})-gettimeofday()); - readingsBulkUpdate($def,".lastenergy", $energy,1); - readingsBulkUpdate($def,"avgpower", sprintf("%.2f",$avg),1); - } - } else { - readingsBulkUpdate($def,".lastenergy", $energy,1); + $lastval = $def->{READINGS}{".lastenergy"}{VAL}; + } + else { + readingsSingleUpdate($def,".lastenergy", $energy, 1); + } + + # adjust energy value + $energy -= AttrVal($name, "EnergyAdjustValue", 0); + + my $isInvalid = 0; + my $energydiff = 0; + my $maxenergy = 0; + + if (defined($def->{READINGS}{"energy"})) { + my $timediff = gettimeofday() - str2time($def->{READINGS}{"energy"}{TIME}); + $energydiff = $energy - $def->{READINGS}{"energy"}{VAL}; + $maxenergy = 3.65 * ($timediff / 3600.0); } - readingsBulkUpdate($def,"state", $state,1); - Log3 $name,4, "$name: $state"; - readingsBulkUpdate($def,"voltage", $voltage,1); - #Log3 $def,3, "$name:voltage $voltage"; - readingsBulkUpdate($def,"current", $current,1); - #Log3 $def,3, "$name:current $current"; - readingsBulkUpdate($def,"frequency", $freq,1); - #Log3 $def,3, "$name:frequency $freq"; - readingsBulkUpdate($def,"power", $power,1); - #Log3 $def,3, "$name:power $power"; - readingsBulkUpdate($def,"pf", $pf,1); - #Log3 $def,3, "$name:Pf $pf"; - readingsBulkUpdate($def,"energy", $energy,1); - #Log3 $def,3, "$name:energy $energy"; - - readingsEndUpdate($def, 1); + if (0 == $pf) { + $pf = 0.0001; + } + if (($freq > 55) || ($power > 3650) || ($current > 16) || + ((($power / $voltage / $pf) > 0.00999) && (0 == $current)) || + ($energydiff > $maxenergy)) { + $isInvalid = 1; + } + + if (0 == $isInvalid) { + #my $state = "P: ".sprintf("%5.1f", $power)." E: ".sprintf("%6.2f", $energy)." V: ".sprintf("%3d", $voltage)." C: ".sprintf("%6.2f", $current)." F: $freq Pf: ".sprintf("%4.2f", $pf); + + readingsBeginUpdate($def); + + my $timediff = gettimeofday() - str2time($def->{READINGS}{".lastenergy"}{TIME}); + if (($lastval != $energy) && (($energy - $lastval) < (3.65 * ($timediff / 3600.0)))) { + my $avg = (($energy - $lastval) * 1000.0 * 3600.0) / $timediff; + readingsBulkUpdate($def, ".lastenergy", $energy, 1); + readingsBulkUpdate($def, "avgpower", sprintf("%.2f", $avg), 1); + #Log3 $def,3, "$name:timediff $timediff, lastval $lastval, energy $energy, avg $avg"; + } + + readingsBulkUpdate($def, "state", "active", 0); + readingsBulkUpdate($def, "voltage", $voltage, 1); + readingsBulkUpdate($def, "current", $current, 1); + readingsBulkUpdate($def, "frequency", $freq, 1); + readingsBulkUpdate($def, "power", $power, 1); + readingsBulkUpdate($def, "pf", $pf, 1); + readingsBulkUpdate($def, "energy", $energy, 1); + + readingsEndUpdate($def, 1); + } return $name; } @@ -150,9 +169,16 @@ Revolt_Parse($$) Note: devices are autocreated on reception of the first message.

+ + Attributes +
    +
  • EnergyAdjustValue: adjust the energy reading (energy = energy - EnergyAdjustValue)
  • +
+
Readings
    +
  • avgpower [W]
  • energy [kWh]
  • power [W]
  • voltage [V]