mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-05-04 22:19:38 +00:00
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
This commit is contained in:
parent
1c3e577797
commit
300da4495c
3
CHANGED
3
CHANGED
@ -364,6 +364,9 @@
|
|||||||
|
|
||||||
- ==DATE== (4.3)
|
- ==DATE== (4.3)
|
||||||
- bugfix: KS300 state was wrong after the STATE bugfix
|
- 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
|
- TODO
|
||||||
emem -2.5kW / getDevData for emwz -1
|
emem -2.5kW / getDevData for emwz -1
|
||||||
|
@ -11,6 +11,7 @@ sub FHZ_Read($);
|
|||||||
sub FHZ_ReadAnswer($$);
|
sub FHZ_ReadAnswer($$);
|
||||||
sub FhzCrc(@);
|
sub FhzCrc(@);
|
||||||
sub CheckFhzCrc($);
|
sub CheckFhzCrc($);
|
||||||
|
sub XmitLimitCheck($$);
|
||||||
|
|
||||||
my $msgstart = pack('H*', "81");# Every msg starts wit this
|
my $msgstart = pack('H*', "81");# Every msg starts wit this
|
||||||
|
|
||||||
@ -46,6 +47,7 @@ my %codes = (
|
|||||||
my $def;
|
my $def;
|
||||||
my %msghist; # Used when more than one FHZ is attached
|
my %msghist; # Used when more than one FHZ is attached
|
||||||
my $msgcount = 0;
|
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
|
# 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");
|
push(@init, "set $name raw 04 01010100010000");
|
||||||
|
|
||||||
CommandChain(3, \@init);
|
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} = "";
|
$hash->{PARTIAL} = "";
|
||||||
|
|
||||||
DoInit($name);
|
DoInit($name);
|
||||||
|
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,6 +387,42 @@ FHZ_CompleteMsg($$)
|
|||||||
return pack('C*', 0x81, $len/2+2, ord(pack('H*',$fn)), FhzCrc(@data), @data);
|
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
|
sub
|
||||||
FHZ_Write($$$)
|
FHZ_Write($$$)
|
||||||
@ -406,11 +450,15 @@ FHZ_Write($$$)
|
|||||||
Log 5, "Sending " . unpack('H*', $bstring);
|
Log 5, "Sending " . unpack('H*', $bstring);
|
||||||
|
|
||||||
if(!$hash->{QUEUECNT}) {
|
if(!$hash->{QUEUECNT}) {
|
||||||
|
|
||||||
|
XmitLimitCheck($hash,$bstring);
|
||||||
$hash->{PortObj}->write($bstring);
|
$hash->{PortObj}->write($bstring);
|
||||||
|
|
||||||
##############
|
##############
|
||||||
# Write the next buffer not earlier than 0.22 seconds (= 65.6ms + 10ms +
|
# 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
|
# 65.6ms + 10ms + 65.6ms), else it will be discarded by the FHZ1X00 PC
|
||||||
InternalTimer(gettimeofday()+0.25, "FHZ_HandleWriteQueue", $hash, 1);
|
InternalTimer(gettimeofday()+0.25, "FHZ_HandleWriteQueue", $hash, 1);
|
||||||
|
|
||||||
} elsif($hash->{QUEUECNT} == 1) {
|
} elsif($hash->{QUEUECNT} == 1) {
|
||||||
$hash->{QUEUE} = [ $bstring ];
|
$hash->{QUEUE} = [ $bstring ];
|
||||||
} else {
|
} else {
|
||||||
@ -429,6 +477,7 @@ FHZ_HandleWriteQueue($)
|
|||||||
my $cnt = --$hash->{QUEUECNT};
|
my $cnt = --$hash->{QUEUECNT};
|
||||||
if($cnt > 0) {
|
if($cnt > 0) {
|
||||||
my $bstring = shift(@{$hash->{QUEUE}});
|
my $bstring = shift(@{$hash->{QUEUE}});
|
||||||
|
XmitLimitCheck($hash,$bstring);
|
||||||
$hash->{PortObj}->write($bstring);
|
$hash->{PortObj}->write($bstring);
|
||||||
InternalTimer(gettimeofday()+0.25, "FHZ_HandleWriteQueue", $hash, 1);
|
InternalTimer(gettimeofday()+0.25, "FHZ_HandleWriteQueue", $hash, 1);
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ my %codes = (
|
|||||||
"4" => "HMS100TFK", # Depending on the onboard jumper it is 4 or 5
|
"4" => "HMS100TFK", # Depending on the onboard jumper it is 4 or 5
|
||||||
"5" => "HMS100TFK",
|
"5" => "HMS100TFK",
|
||||||
"6" => "HMS100MG",
|
"6" => "HMS100MG",
|
||||||
|
"8" => "HMS100CO",
|
||||||
);
|
);
|
||||||
|
|
||||||
my %defptr;
|
my %defptr;
|
||||||
@ -30,12 +31,13 @@ HMS_Initialize($)
|
|||||||
# 810e047f0214a001a81f000001000000 HMS100TFK
|
# 810e047f0214a001a81f000001000000 HMS100TFK
|
||||||
# 810e048f0295a0010155000001000000 HMS100TFK (jumper)
|
# 810e048f0295a0010155000001000000 HMS100TFK (jumper)
|
||||||
# 810e04330216a001b4c5000001000000 HMS100MG
|
# 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->{DefFn} = "HMS_Define";
|
||||||
$hash->{UndefFn} = "HMS_Undef";
|
$hash->{UndefFn} = "HMS_Undef";
|
||||||
$hash->{ParseFn} = "HMS_Parse";
|
$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"; }
|
if ($status & 1) { $v[0] = "on"; }
|
||||||
$val = "Gas Detect: $v[0]";
|
$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 {
|
} else {
|
||||||
|
|
||||||
Log 4, "HMS Device $dev (Unknown type: $type)";
|
Log 4, "HMS Device $dev (Unknown type: $type)";
|
||||||
|
@ -21,7 +21,7 @@ EM_Initialize($)
|
|||||||
|
|
||||||
# Provider
|
# Provider
|
||||||
$hash->{WriteFn} = "EM_Write";
|
$hash->{WriteFn} = "EM_Write";
|
||||||
$hash->{Clients} = ":EMWZ:EMEM:";
|
$hash->{Clients} = ":EMWZ:EMEM:EMGZ:";
|
||||||
|
|
||||||
# Consumer
|
# Consumer
|
||||||
$hash->{DefFn} = "EM_Define";
|
$hash->{DefFn} = "EM_Define";
|
||||||
|
185
FHEM/63_EMGZ.pm
Normal file
185
FHEM/63_EMGZ.pm
Normal 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;
|
@ -537,7 +537,16 @@ split in multiple lines<br><br>
|
|||||||
messages, we just ignore messages which were sent out by our device for the
|
messages, we just ignore messages which were sent out by our device for the
|
||||||
next 3 seconds (or configured otherwise by filtertimeout).
|
next 3 seconds (or configured otherwise by filtertimeout).
|
||||||
<br>
|
<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>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
@ -749,6 +758,25 @@ split in multiple lines<br><br>
|
|||||||
<br>
|
<br>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<a name="EMGZ"></a>
|
||||||
|
<h4>Type EMGZ</h4>
|
||||||
|
<ul>
|
||||||
|
<code>define <name> EMGZ <device-number></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>
|
<a name="M232"></a>
|
||||||
<h4>Type M232</h4>
|
<h4>Type M232</h4>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user