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:
parent
9b494ef9b3
commit
21730103ff
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)";
|
||||
|
@ -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
185
fhem/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
|
||||
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 <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>
|
||||
<h4>Type M232</h4>
|
||||
|
Loading…
Reference in New Issue
Block a user