From 300da4495c6ceab6bf1f68a5625db06f3e899acf Mon Sep 17 00:00:00 2001 From: rudolfkoenig <> Date: Sun, 23 Dec 2007 15:57:37 +0000 Subject: [PATCH] Changes by Peter (HMS100CO and EMGZ) and CommandCounter (inspired by Peter) git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@130 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- CHANGED | 3 + FHEM/00_FHZ.pm | 49 ++++++++++++ FHEM/12_HMS.pm | 19 ++++- FHEM/60_EM.pm | 2 +- FHEM/63_EMGZ.pm | 185 +++++++++++++++++++++++++++++++++++++++++++ docs/commandref.html | 30 ++++++- 6 files changed, 284 insertions(+), 4 deletions(-) create mode 100644 FHEM/63_EMGZ.pm diff --git a/CHANGED b/CHANGED index 9e7aff7a7..441524afa 100644 --- a/CHANGED +++ b/CHANGED @@ -364,6 +364,9 @@ - ==DATE== (4.3) - bugfix: KS300 state was wrong after the STATE bugfix + - feature: HMS100CO (by Peter) + - feature: EMGZ (by Peter) + - feature: Generate warning if too many commands were sent in the last hour - TODO emem -2.5kW / getDevData for emwz -1 diff --git a/FHEM/00_FHZ.pm b/FHEM/00_FHZ.pm index ed784e1e6..e6258258d 100755 --- a/FHEM/00_FHZ.pm +++ b/FHEM/00_FHZ.pm @@ -11,6 +11,7 @@ sub FHZ_Read($); sub FHZ_ReadAnswer($$); sub FhzCrc(@); sub CheckFhzCrc($); +sub XmitLimitCheck($$); my $msgstart = pack('H*', "81");# Every msg starts wit this @@ -46,6 +47,7 @@ my %codes = ( my $def; my %msghist; # Used when more than one FHZ is attached my $msgcount = 0; +my $xmit_limit = 163; # Maximum nr of transmissions per hour (unconfirmed). ##################################### # Note: we are a data provider _and_ a consumer at the same time @@ -190,6 +192,11 @@ DoInit($) push(@init, "set $name raw 04 01010100010000"); CommandChain(3, \@init); + + # Reset the counter + my $hash = $defs{$name}; + delete($hash->{XMIT_TIME}); + delete($hash->{NR_CMD_LAST_H}); } ##################################### @@ -244,6 +251,7 @@ FHZ_Define($$) $hash->{PARTIAL} = ""; DoInit($name); + return undef; } @@ -379,6 +387,42 @@ FHZ_CompleteMsg($$) return pack('C*', 0x81, $len/2+2, ord(pack('H*',$fn)), FhzCrc(@data), @data); } + +##################################### +# Check if the 1% limit is reached and trigger notifies +sub +XmitLimitCheck($$) +{ + my ($hash,$bstring) = @_; + my $now = time(); + + $bstring = unpack('H*', $bstring); + return if($bstring =~ m/c90185$/); # fhtbuf + + if(!$hash->{XMIT_TIME}) { + $hash->{XMIT_TIME}[0] = $now; + $hash->{NR_CMD_LAST_H} = 1; + return; + } + + my $nowM1h = $now-3600; + my @b = grep { $_ > $nowM1h } @{$hash->{XMIT_TIME}}; + + if(@b > $xmit_limit) { + + my $me = $hash->{NAME}; + Log GetLogLevel($me,2), "FHZ TRANSMIT LIMIT EXCEEDED"; + DoTriger($me, "TRANSMIT LIMIT EXCEEDED"); + + } else { + + push(@b, $now); + + } + $hash->{XMIT_TIME} = \@b; + $hash->{NR_CMD_LAST_H} = int(@b); +} + ##################################### sub FHZ_Write($$$) @@ -406,11 +450,15 @@ FHZ_Write($$$) Log 5, "Sending " . unpack('H*', $bstring); if(!$hash->{QUEUECNT}) { + + XmitLimitCheck($hash,$bstring); $hash->{PortObj}->write($bstring); + ############## # Write the next buffer not earlier than 0.22 seconds (= 65.6ms + 10ms + # 65.6ms + 10ms + 65.6ms), else it will be discarded by the FHZ1X00 PC InternalTimer(gettimeofday()+0.25, "FHZ_HandleWriteQueue", $hash, 1); + } elsif($hash->{QUEUECNT} == 1) { $hash->{QUEUE} = [ $bstring ]; } else { @@ -429,6 +477,7 @@ FHZ_HandleWriteQueue($) my $cnt = --$hash->{QUEUECNT}; if($cnt > 0) { my $bstring = shift(@{$hash->{QUEUE}}); + XmitLimitCheck($hash,$bstring); $hash->{PortObj}->write($bstring); InternalTimer(gettimeofday()+0.25, "FHZ_HandleWriteQueue", $hash, 1); } diff --git a/FHEM/12_HMS.pm b/FHEM/12_HMS.pm index 740c960a4..d3a1f1c3a 100755 --- a/FHEM/12_HMS.pm +++ b/FHEM/12_HMS.pm @@ -12,6 +12,7 @@ my %codes = ( "4" => "HMS100TFK", # Depending on the onboard jumper it is 4 or 5 "5" => "HMS100TFK", "6" => "HMS100MG", + "8" => "HMS100CO", ); my %defptr; @@ -30,12 +31,13 @@ HMS_Initialize($) # 810e047f0214a001a81f000001000000 HMS100TFK # 810e048f0295a0010155000001000000 HMS100TFK (jumper) # 810e04330216a001b4c5000001000000 HMS100MG +# 810e04210218a00186e0000000000000 HMS100CO - $hash->{Match} = "^810e04....(1|5|9)[0-6]a001"; + $hash->{Match} = "^810e04....(1|5|9)[0-8]a001"; $hash->{DefFn} = "HMS_Define"; $hash->{UndefFn} = "HMS_Undef"; $hash->{ParseFn} = "HMS_Parse"; - $hash->{AttrList} = "do_not_notify:0,1 showtime:0,1 model;hms100-t,hms100-tf,hms100-wd,hms100-mg,hms100-tfk,rm100-2 loglevel:0,1,2,3,4,5,6"; + $hash->{AttrList} = "do_not_notify:0,1 showtime:0,1 model;hms100-t,hms100-tf,hms100-wd,hms100-mg,hms100-tfk,rm100-2,hms100-co loglevel:0,1,2,3,4,5,6"; } ##################################### @@ -178,6 +180,19 @@ HMS_Parse($$) if ($status & 1) { $v[0] = "on"; } $val = "Gas Detect: $v[0]"; + } elsif ($type eq "HMS100CO") { # By PAN + + @txt = ( "gas_detect", "battery"); + @sfx = ( "", ""); + + # Battery-low condition detect is not yet properly + # implemented. + my $status = hex(substr($val, 1, 1)); + $v[0] = ($status != "0") ? "on" : "off"; + $v[1] = "off"; + if ($status & 1) { $v[0] = "on"; } + $val = "CO Detect: $v[0]"; + } else { Log 4, "HMS Device $dev (Unknown type: $type)"; diff --git a/FHEM/60_EM.pm b/FHEM/60_EM.pm index b32a2e4ee..133d26838 100755 --- a/FHEM/60_EM.pm +++ b/FHEM/60_EM.pm @@ -21,7 +21,7 @@ EM_Initialize($) # Provider $hash->{WriteFn} = "EM_Write"; - $hash->{Clients} = ":EMWZ:EMEM:"; + $hash->{Clients} = ":EMWZ:EMEM:EMGZ:"; # Consumer $hash->{DefFn} = "EM_Define"; diff --git a/FHEM/63_EMGZ.pm b/FHEM/63_EMGZ.pm new file mode 100644 index 000000000..87ea2c715 --- /dev/null +++ b/FHEM/63_EMGZ.pm @@ -0,0 +1,185 @@ +############################################## +package main; + +use strict; +use warnings; +use Time::HiRes qw(gettimeofday); + +sub EMGZ_Get($@); +sub EMGZ_Set($@); +sub EMGZ_Define($$); +sub EMGZ_GetStatus($); + +################################### +sub +EMGZ_Initialize($) +{ + my ($hash) = @_; + + $hash->{GetFn} = "EMGZ_Get"; + $hash->{SetFn} = "EMGZ_Set"; + $hash->{DefFn} = "EMGZ_Define"; + + $hash->{AttrList} = "dummy:1,0 model;EM1000GZ loglevel:0,1,2,3,4,5,6"; +} + + +################################### +sub +EMGZ_GetStatus($) +{ + my ($hash) = @_; + + if(!$hash->{LOCAL}) { + InternalTimer(gettimeofday()+300, "EMGZ_GetStatus", $hash, 0); + } + + my $dnr = $hash->{DEVNR}; + my $name = $hash->{NAME}; + + return "Empty status: dummy IO device" if(IsIoDummy($name)); + + my $d = IOWrite($hash, sprintf("7a%02x", $dnr-1)); + if(!defined($d)) { + my $msg = "EMGZ $name read error (GetStatus 1)"; + Log GetLogLevel($name,2), $msg; + return $msg; + } + + + if($d eq ((pack('H*',"00") x 45) . pack('H*',"FF") x 6)) { + my $msg = "EMGZ no device no. $dnr present"; + Log GetLogLevel($name,2), $msg; + return $msg; + } + + my $pulses=w($d,13); + my $ec=w($d,49) / 10; + if($ec < 0) { # war <= + my $msg = "EMGZ read error (GetStatus 2)"; + Log GetLogLevel($name,2), $msg; + return $msg; + } + + $ec = 100; # fixed value + + my $cur_energy = $pulses / $ec; # ec = U/m^3 + my $cur_power = $cur_energy / 5 * 60; # 5minute interval scaled to 1h + + if($cur_power > 30) { # depending on "Anschlussleistung" + my $msg = "EMGZ Bogus reading: curr. power is reported to be $cur_power"; + Log GetLogLevel($name,2), $msg; + return $msg; + } + + my %vals; + $vals{"5min_pulses"} = $pulses; + $vals{"act_flow_m3"} = sprintf("%0.3f", $cur_energy); + $vals{"m3ph"} = sprintf("%.3f", $cur_power); + $vals{"alarm_PA"} = w($d,45) . " Watt"; # nonsens + $vals{"price_CF"} = sprintf("%.3f", w($d,47)/10000); + $vals{"Rperm3_EC"} = $ec; + + my $tn = TimeNow(); + my $idx = 0; + foreach my $k (keys %vals) { + my $v = $vals{$k}; + $hash->{CHANGED}[$idx++] = "$k: $v"; + $hash->{READINGS}{$k}{TIME} = $tn; + $hash->{READINGS}{$k}{VAL} = $v + } + + if(!$hash->{LOCAL}) { + DoTrigger($name, undef) if($init_done); + } + + $hash->{STATE} = "$cur_power m3ph"; + Log GetLogLevel($name,4), "EMGZ $name: $cur_power m3ph / $vals{act_flow_m3}"; + + return $hash->{STATE}; +} + +################################### +sub +EMGZ_Get($@) +{ + my ($hash, @a) = @_; + + return "argument is missing" if(int(@a) != 2); + + my $d = $hash->{DEVNR}; + my $msg; + + if($a[1] ne "status") { + return "unknown get value, valid is status"; + } + $hash->{LOCAL} = 1; + my $v = EMGZ_GetStatus($hash); + delete $hash->{LOCAL}; + + return "$a[0] $a[1] => $v"; +} + +sub +EMGZ_Set($@) +{ + my ($hash, @a) = @_; + my $u = "Usage: set , " . + " is one of price,alarm,rperkw"; + + return $u if(int(@a) != 3); + + my $name = $hash->{NAME}; + return "" if(IsIoDummy($name)); + + my $v = $a[2]; + my $d = $hash->{DEVNR}; + my $msg; + + if($a[1] eq "price") { + $v *= 10000; # Make display and input the same + $msg = sprintf("79%02x2f02%02x%02x", $d-1, $v%256, int($v/256)); + } elsif($a[1] eq "alarm") { + $msg = sprintf("79%02x2d02%02x%02x", $d-1, $v%256, int($v/256)); + } elsif($a[1] eq "rperkw") { + $v *= 10; # Make display and input the same + $msg = sprintf("79%02x3102%02x%02x", $d-1, $v%256, int($v/256)); + } else { + return $u; + } + + + my $ret = IOWrite($hash, $msg); + if(!defined($ret)) { + my $msg = "EMWZ $name read error (Set)"; + Log GetLogLevel($name,2), $msg; + return $msg; + } + + if(ord(substr($ret,0,1)) != 6) { + $ret = "EMGZ Error occured: " . unpack('H*', $ret); + Log GetLogLevel($name,2), $ret; + return $ret; + } + + return undef; +} + +############################# +sub +EMGZ_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + + return "syntax: define EMGZ devicenumber" + if(@a != 3 || $a[2] !~ m,^[9]$,); + $hash->{DEVNR} = $a[2]; + AssignIoPort($hash); + + + EMGZ_GetStatus($hash); + return undef; +} + +1; diff --git a/docs/commandref.html b/docs/commandref.html index fe75b1750..ad5df29bb 100644 --- a/docs/commandref.html +++ b/docs/commandref.html @@ -537,7 +537,16 @@ split in multiple lines

messages, we just ignore messages which were sent out by our device for the next 3 seconds (or configured otherwise by filtertimeout).
- For GNU/Linux you may want to read our hints for GNU/Linux about multiple USB devices. + For GNU/Linux you may want to read our hints for + GNU/Linux about multiple USB + devices.
+ + Note:The firmware of the FHZ1x00 will drop commands if the airtime + for the last hour would exceed 1% (which corresponds roughly to 163 + commands). For this purpose there is a command counter for the last hour + (see list FHZDEVICE), which triggers with "TRANSMIT LIMIT EXCEEDED" if + there were more than 163 commands in the last hour.
+
@@ -749,6 +758,25 @@ split in multiple lines


+ +

Type EMGZ

+
    + define <name> EMGZ <device-number> +

    + + Define up to 4 EM1000GZ attached to the EM1010PC. The device number must + be 9. + Defining an EMGZ will schedule an internal task, which reads the + status of the device every 5 minutes, and triggers notify/filelog commands. +

    + + Example: +
      + define emgz EMGZ 9
      +
    +
    +
+

Type M232