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

Changes by Peter (HMS100CO and EMGZ) and CommandCounter (inspired by Peter)

git-svn-id: https://svn.fhem.de/fhem/trunk@130 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2007-12-23 15:57:37 +00:00
parent 9b494ef9b3
commit 21730103ff
6 changed files with 284 additions and 4 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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)";

View File

@ -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";

185
fhem/FHEM/63_EMGZ.pm Normal file
View File

@ -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 <name> <type> <value>, " .
"<type> 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 <name> EMGZ devicenumber"
if(@a != 3 || $a[2] !~ m,^[9]$,);
$hash->{DEVNR} = $a[2];
AssignIoPort($hash);
EMGZ_GetStatus($hash);
return undef;
}
1;

View File

@ -537,7 +537,16 @@ split in multiple lines<br><br>
messages, we just ignore messages which were sent out by our device for the
next 3 seconds (or configured otherwise by filtertimeout).
<br>
For GNU/Linux you may want to read our <a href="linux.html">hints for GNU/Linux</a> about <a href="linux.html#multipledevices">multiple USB devices</a>.
For GNU/Linux you may want to read our <a href="linux.html">hints for
GNU/Linux</a> about <a href="linux.html#multipledevices">multiple USB
devices</a>.<br>
<b>Note:</b>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.<br>
</ul>
<br>
@ -749,6 +758,25 @@ split in multiple lines<br><br>
<br>
</ul>
<a name="EMGZ"></a>
<h4>Type EMGZ</h4>
<ul>
<code>define &lt;name&gt; EMGZ &lt;device-number&gt;</code>
<br><br>
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.
<br><br>
Example:
<ul>
<code>define emgz EMGZ 9</code><br>
</ul>
<br>
</ul>
<a name="M232"></a>
<h4>Type M232</h4>