mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-03 04:36:36 +00:00
ESA2000 added
git-svn-id: https://svn.fhem.de/fhem/trunk@802 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
4d6d896969
commit
837e3a5398
@ -47,7 +47,7 @@ my %sets = (
|
||||
my @ampllist = (24, 27, 30, 33, 36, 38, 40, 42); # rAmpl(dB)
|
||||
|
||||
my $clientsSlowRF = ":FS20:FHT:FHT8V:KS300:USF1000:BS:HMS" .
|
||||
":CUL_EM:CUL_WS:CUL_FHTTK:CUL_RFR:CUL_HOERMANN:";
|
||||
":CUL_EM:CUL_WS:CUL_FHTTK:CUL_RFR:CUL_HOERMANN:ESA2000:";
|
||||
my $clientsHomeMatic = ":CUL_HM:HMS:";
|
||||
|
||||
my %matchListSlowRF = (
|
||||
@ -62,6 +62,7 @@ my %matchListSlowRF = (
|
||||
"9:CUL_FHTTK" => "^T........",
|
||||
"A:CUL_RFR" => "^[0-9A-F]{4}U.",
|
||||
"B:CUL_HOERMANN"=> "^R..........",
|
||||
"C:ESA2000" => "^S................................\$",
|
||||
);
|
||||
my %matchListHomeMatic = (
|
||||
"1:CUL_HM" => "^A......................",
|
||||
@ -810,7 +811,7 @@ CUL_Parse($$$$$)
|
||||
my $rssi;
|
||||
|
||||
my $dmsg = $rmsg;
|
||||
if($dmsg =~ m/^[AFTKEHR]([A-F0-9][A-F0-9])+$/) { # RSSI
|
||||
if($dmsg =~ m/^[AFTKEHRS]([A-F0-9][A-F0-9])+$/) { # RSSI
|
||||
my $l = length($dmsg);
|
||||
$rssi = hex(substr($dmsg, $l-2, 2));
|
||||
$dmsg = substr($dmsg, 0, $l-2);
|
||||
@ -880,7 +881,9 @@ CUL_Parse($$$$$)
|
||||
|
||||
} elsif($fn eq "E" && $len >= 11) { # CUL_EM / Native
|
||||
;
|
||||
} elsif($fn eq "R" && $len >= 11) { # CUL_EM / Native
|
||||
} elsif($fn eq "R" && $len >= 11) { # CUL_HOERMANN / Native
|
||||
;
|
||||
} elsif($fn eq "S" && $len >= 33) { # CUL_ESA / ESA2000 / Native
|
||||
;
|
||||
} elsif($fn eq "A" && $len >= 21) { # AskSin/BidCos/HomeMatic
|
||||
;
|
||||
|
223
fhem/FHEM/64_ESA2000.pm
Normal file
223
fhem/FHEM/64_ESA2000.pm
Normal file
@ -0,0 +1,223 @@
|
||||
##############################################
|
||||
# (c) by STefan Mayer (stefan(at)clumsy.ch) #
|
||||
# #
|
||||
# please feel free to contact me for any #
|
||||
# changes, improvments, suggestions, etc #
|
||||
# #
|
||||
##############################################
|
||||
|
||||
package main;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my %codes = (
|
||||
"19fa" => "ESA2000_LED",
|
||||
);
|
||||
|
||||
|
||||
#####################################
|
||||
sub
|
||||
ESA2000_Initialize($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
|
||||
# S0119FA011E00007D6E003100000007C9 ESA2000_LED
|
||||
|
||||
$hash->{Match} = "^S................................\$";
|
||||
$hash->{DefFn} = "ESA2000_Define";
|
||||
$hash->{UndefFn} = "ESA2000_Undef";
|
||||
$hash->{ParseFn} = "ESA2000_Parse";
|
||||
$hash->{AttrList} = "IODev do_not_notify:0,1 showtime:0,1 model:esa2000-led loglevel:0,1,2,3,4,5,6 ignore:0,1 base_1 base_2";
|
||||
}
|
||||
|
||||
#####################################
|
||||
sub
|
||||
ESA2000_Define($$)
|
||||
{
|
||||
my ($hash, $def) = @_;
|
||||
my @a = split("[ \t][ \t]*", $def);
|
||||
|
||||
return "wrong syntax: define <name> ESA2000 CODE" if(int(@a) != 3);
|
||||
$a[2] = lc($a[2]);
|
||||
return "Define $a[0]: wrong CODE format: specify a 4 digit hex value"
|
||||
if($a[2] !~ m/^[a-f0-9][a-f0-9][a-f0-9][a-f0-9]$/);
|
||||
|
||||
|
||||
$hash->{CODE} = $a[2];
|
||||
$modules{ESA2000}{defptr}{$a[2]} = $hash;
|
||||
AssignIoPort($hash);
|
||||
return undef;
|
||||
}
|
||||
|
||||
#####################################
|
||||
sub
|
||||
ESA2000_Undef($$)
|
||||
{
|
||||
my ($hash, $name) = @_;
|
||||
delete($modules{ESA2000}{defptr}{$hash->{CODE}})
|
||||
if(defined($hash->{CODE}) &&
|
||||
defined($modules{ESA2000}{defptr}{$hash->{CODE}}));
|
||||
return undef;
|
||||
}
|
||||
|
||||
#####################################
|
||||
sub
|
||||
ESA2000_Parse($$)
|
||||
{
|
||||
my ($hash, $msg) = @_;
|
||||
|
||||
# 0123456789012345678901234567890123456789
|
||||
# S0119FA011E00007D6E003100000007C9F9 ESA2000_LED
|
||||
$msg = lc($msg);
|
||||
my $seq = substr($msg, 1, 2);
|
||||
my $cde = substr($msg, 3, 4);
|
||||
my $dev = substr($msg, 7, 4);
|
||||
my $val = substr($msg, 11, 22);
|
||||
|
||||
Log 5, "ESA2000 msg $msg";
|
||||
Log 5, "ESA2000 seq $seq";
|
||||
Log 5, "ESA2000 device $dev";
|
||||
Log 5, "ESA2000 code $cde";
|
||||
|
||||
my $type = "";
|
||||
foreach my $c (keys %codes) {
|
||||
$c = lc($c);
|
||||
if($cde =~ m/$c/) {
|
||||
$type = $codes{$c};
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
if(!defined($modules{ESA2000}{defptr}{$dev})) {
|
||||
Log 3, "Unknown ESA2000 device $dev, please define it";
|
||||
$type = "ESA2000" if(!$type);
|
||||
return "UNDEFINED ${type}_$dev ESA2000 $dev";
|
||||
}
|
||||
|
||||
my $def = $modules{ESA2000}{defptr}{$dev};
|
||||
my $name = $def->{NAME};
|
||||
return "" if(IsIgnored($name));
|
||||
|
||||
my $now = TimeNow();
|
||||
my (@v, @txt);
|
||||
|
||||
if($type eq "ESA2000_LED") {
|
||||
|
||||
@txt = ( "repeat", "sequence", "total_ticks", "actual_ticks", "ticks_kwh", "raw", "total_kwh", "actual_kwh", "diff_kwh", "diff_sec", "diff_ticks", "last_sec", "raw_total_kwh", "max_kwh", "day_kwh", "month_kwh", "year_kwh" );
|
||||
|
||||
|
||||
# Codierung Hex
|
||||
$v[0] = int(hex($seq) / 128) ? "+" : "-"; # repeated
|
||||
$v[1] = hex($seq) % 128;
|
||||
$v[2] = hex(substr($val,0,8));
|
||||
$v[3] = hex(substr($val,8,4));
|
||||
$v[4] = hex(substr($val,18,4)) ^ 25; # XOR 25, whyever bit 1,4,5 are swapped?!?! Probably a (receive-) error in CUL-FW?
|
||||
|
||||
$v[5] = sprintf("CNT: %d%s CUM: %d CUR: %d TICKS: %d",
|
||||
$v[1], $v[0], $v[2], $v[3], $v[4]);
|
||||
$v[11] = time();
|
||||
if (defined($def->{READINGS}{$txt[11]}{VAL})) {
|
||||
$v[9] = $v[11] - $def->{READINGS}{$txt[11]}{VAL}; # seconds since last update
|
||||
}
|
||||
if(defined($v[9]) && $v[9] != 0) {
|
||||
$v[7] = $v[3]/$v[4]/$v[9]*3600; # calculate kW/h since last update
|
||||
} else {
|
||||
$v[7] = -1;
|
||||
}
|
||||
$v[8] = $v[3]/$v[4]; # calculate kWh diff from readings (raw from device....), whats this relly?
|
||||
if(defined($def->{READINGS}{$txt[2]}{VAL})) {
|
||||
$v[10] = $v[2] - $def->{READINGS}{$txt[2]}{VAL}; # shoudl be the same as actual_ticks if no packets are lost
|
||||
}
|
||||
if(defined($v[10])) {
|
||||
$v[6] = $v[10]/$v[4] + (defined($def->{READINGS}{$txt[6]}{VAL}) ? $def->{READINGS}{$txt[6]}{VAL} : 0); # cumulate kWh to ensure tick-changes are calculated correctly (does this ever happen?)
|
||||
if(defined($def->{READINGS}{$txt[14]}{TIME})) {
|
||||
if(substr($now,0,10) eq substr($def->{READINGS}{$txt[14]}{TIME},0,10)) { # a bit clumsy, I agree, but it works and its logical and this is pearl, right?
|
||||
$v[14] = $v[10]/$v[4] + (defined($def->{READINGS}{$txt[14]}{VAL}) ? $def->{READINGS}{$txt[14]}{VAL} : 0); # cumulate kWh to ensure tick-changes are calculated correctly (does this ever happen?)
|
||||
} else {
|
||||
$v[14] = $v[10]/$v[4]
|
||||
}
|
||||
} else {
|
||||
$v[14] = $v[10]/$v[4]
|
||||
}
|
||||
if(defined($def->{READINGS}{$txt[15]}{TIME})) {
|
||||
if(substr($now,0,7) eq substr($def->{READINGS}{$txt[15]}{TIME},0,7)) { # a bit clumsy, I agree, but it works and its logical and this is pearl, right?
|
||||
$v[15] = $v[10]/$v[4] + (defined($def->{READINGS}{$txt[15]}{VAL}) ? $def->{READINGS}{$txt[15]}{VAL} : 0); # cumulate kWh to ensure tick-changes are calculated correctly (does this ever happen?)
|
||||
} else {
|
||||
$v[15] = $v[10]/$v[4]
|
||||
}
|
||||
} else {
|
||||
$v[15] = $v[10]/$v[4]
|
||||
}
|
||||
if(defined($def->{READINGS}{$txt[16]}{TIME})) {
|
||||
if(substr($now,0,4) eq substr($def->{READINGS}{$txt[16]}{TIME},0,4)) { # a bit clumsy, I agree, but it works and its logical and this is pearl, right?
|
||||
$v[16] = $v[10]/$v[4] + (defined($def->{READINGS}{$txt[16]}{VAL}) ? $def->{READINGS}{$txt[16]}{VAL} : 0); # cumulate kWh to ensure tick-changes are calculated correctly (does this ever happen?)
|
||||
} else {
|
||||
$v[16] = $v[10]/$v[4]
|
||||
}
|
||||
} else {
|
||||
$v[16] = $v[10]/$v[4]
|
||||
}
|
||||
} else {
|
||||
$v[6] = 0;
|
||||
}
|
||||
|
||||
$v[12] = $v[2]/$v[4]; # calculate kWh total since reset of device (does only make sense if ticks per kWh does not change!!)
|
||||
if(defined($def->{READINGS}{$txt[13]}{VAL})) {
|
||||
if($v[7] >= $def->{READINGS}{$txt[13]}{VAL}) {
|
||||
$v[13] = $v[7]; # update max kw/h
|
||||
}
|
||||
} else {
|
||||
$v[13] = $v[7]; # update max kw/h
|
||||
}
|
||||
|
||||
|
||||
# add counter_1 and counter_2 (Hoch- und Niedertarif Basiswerte)
|
||||
if(defined($attr{$name}) &&
|
||||
defined($attr{$name}{"count_1"}) &&
|
||||
($attr{$name}{"count_1"}>0)) {
|
||||
$v[13] = $v[12] + $attr{$name}{"count_1"};
|
||||
}
|
||||
|
||||
if(defined($attr{$name}) &&
|
||||
defined($attr{$name}{"count_2"}) &&
|
||||
($attr{$name}{"count_2"}>0)) {
|
||||
$v[13] = $v[12] + $attr{$name}{"count_2"};
|
||||
}
|
||||
|
||||
$val = sprintf("CNT: %d%s CUM: %0.3f CUR: %0.3f TICKS: %d",
|
||||
$v[1], $v[0], $v[6], $v[7], $v[4]);
|
||||
|
||||
} else {
|
||||
|
||||
Log 3, "ESA2000 Device $dev (Unknown type: $type)";
|
||||
return "";
|
||||
|
||||
}
|
||||
|
||||
|
||||
my $max = int(@txt);
|
||||
|
||||
if ( (defined($def->{READINGS}{"sequence"}{VAL}) ? $def->{READINGS}{"sequence"}{VAL} : "") ne $v[1] ) {
|
||||
Log GetLogLevel($name,4), "ESA2000 $name: $val";
|
||||
for( my $i = 0; $i < $max; $i++) {
|
||||
if ( $v[$i] ) {
|
||||
$def->{READINGS}{$txt[$i]}{TIME} = $now;
|
||||
$def->{READINGS}{$txt[$i]}{VAL} = $v[$i];
|
||||
$def->{CHANGED}[$i] = "$txt[$i]: $v[$i]";
|
||||
}
|
||||
}
|
||||
$def->{READINGS}{type}{TIME} = $now;
|
||||
$def->{READINGS}{type}{VAL} = $type;
|
||||
|
||||
$def->{STATE} = $val;
|
||||
$def->{CHANGED}[$max++] = $val;
|
||||
} else {
|
||||
Log GetLogLevel($name,4), "(ESA2000/DISCARDED $name: $val)";
|
||||
return "($name)";
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
1;
|
@ -11,25 +11,37 @@ use warnings;
|
||||
# - check "UNDEFINED" parameters for BS/USF1000/X10
|
||||
|
||||
my %flogpar = (
|
||||
"CUL_EM:.*" => { GPLOT => "cul_em:Power,", FILTER => "%NAME:CNT:.*" },
|
||||
"CUL_WS:.*" => { GPLOT => "hms:Temp/Hum,", FILTER => "%NAME" },
|
||||
"CUL_FHTTK:.*" => { GPLOT => "fht80tf:Window,", FILTER => "%NAME" },
|
||||
"FHT:.*" => { GPLOT => "fht:Temp/Act,", FILTER => "%NAME" },
|
||||
"HMS:HMS100TFK_.*" => { GPLOT => "fht80tf:Contact,", FILTER => "%NAME" },
|
||||
"HMS:HMS100T._.*" => { GPLOT => "hms:Temp/Hum,", FILTER => "%NAME:T:.*" },
|
||||
"KS300:.*" => { GPLOT => "ks300:Temp/Rain,ks300_2:Wind/Hum,",
|
||||
FILTER => "%NAME:T:.*" },
|
||||
"CUL_EM:.*"
|
||||
=> { GPLOT => "cul_em:Power,", FILTER => "%NAME:CNT:.*" },
|
||||
"CUL_WS:.*"
|
||||
=> { GPLOT => "hms:Temp/Hum,", FILTER => "%NAME" },
|
||||
"CUL_FHTTK:.*"
|
||||
=> { GPLOT => "fht80tf:Window,", FILTER => "%NAME" },
|
||||
"FHT:.*"
|
||||
=> { GPLOT => "fht:Temp/Act,", FILTER => "%NAME" },
|
||||
"HMS:HMS100TFK_.*"
|
||||
=> { GPLOT => "fht80tf:Contact,", FILTER => "%NAME" },
|
||||
"HMS:HMS100T._.*"
|
||||
=> { GPLOT => "hms:Temp/Hum,", FILTER => "%NAME:T:.*" },
|
||||
"KS300:.*"
|
||||
=> { GPLOT => "ks300:Temp/Rain,ks300_2:Wind/Hum,", FILTER => "%NAME:T:.*" },
|
||||
# Oregon sensors:
|
||||
# * temperature
|
||||
"OREGON:(THR128|THWR288A|THN132N).*" => { GPLOT => "oregon_hms_t:Temp,", FILTER => "%NAME" },
|
||||
"OREGON:(THR128|THWR288A|THN132N).*"
|
||||
=> { GPLOT => "oregon_hms_t:Temp,", FILTER => "%NAME" },
|
||||
# * temperature, humidity
|
||||
"OREGON:(THGR228N|THGR810|THGR918|THGR328N|RTGR328N|WTGR800_T).*" => { GPLOT => "oregon_hms:Temp/Hum,", FILTER => "%NAME" },
|
||||
"OREGON:(THGR228N|THGR810|THGR918|THGR328N|RTGR328N|WTGR800_T).*"
|
||||
=> { GPLOT => "oregon_hms:Temp/Hum,", FILTER => "%NAME" },
|
||||
# * temperature, humidity, pressure
|
||||
"OREGON:(BTHR918N|BTHR918|BTHR918N).*" => { GPLOT => "oregon_temp_press:Temp/Press,oregon_hms:Temp/Hum,", FILTER => "%NAME" },
|
||||
"OREGON:(BTHR918N|BTHR918|BTHR918N).*"
|
||||
=> { GPLOT => "oregon_temp_press:Temp/Press,oregon_hms:Temp/Hum,",
|
||||
FILTER => "%NAME" },
|
||||
# * anenometer
|
||||
"OREGON:(WGR800|WGR918|WTGR800_A).*" => { GPLOT => "oregon_wind:WindDir/WindSpeed,", FILTER => "%NAME" },
|
||||
"OREGON:(WGR800|WGR918|WTGR800_A).*"
|
||||
=> { GPLOT => "oregon_wind:WindDir/WindSpeed,", FILTER => "%NAME" },
|
||||
# * Oregon sensors: Rain gauge
|
||||
"OREGON:(PCR800|RGR918).*" => { GPLOT => "oregon_rain:RainRate", FILTER => "%NAME" },
|
||||
"OREGON:(PCR800|RGR918).*"
|
||||
=> { GPLOT => "oregon_rain:RainRate", FILTER => "%NAME" },
|
||||
);
|
||||
|
||||
#####################################
|
||||
|
@ -85,6 +85,7 @@
|
||||
<a href="#EMEM">EMEM</a>
|
||||
<a href="#EMGZ">EMGZ</a>
|
||||
<a href="#EMWZ">EMWZ</a>
|
||||
<a href="#ESA2000">ESA2000</a>
|
||||
<a href="#FHT">FHT</a>
|
||||
<a href="#FHT8V">FHT8V</a>
|
||||
<a href="#FHZ">FHZ</a>
|
||||
@ -2162,6 +2163,46 @@ A line ending with \ will be concatenated with the next one, so long lines
|
||||
<br>
|
||||
</ul>
|
||||
|
||||
|
||||
<a name="ESA2000"></a>
|
||||
<h3>ESA2000</h3>
|
||||
<ul>
|
||||
The ESA2000 module interprets ESA2000 type of messages received by the CUL,
|
||||
currently only for ESA2000 LED devices.
|
||||
<br><br>
|
||||
|
||||
<a name="ESA2000define"></a>
|
||||
<b>Define</b>
|
||||
<ul>
|
||||
<code>define <name> ESA2000 <code>
|
||||
[base1 base2]</code> <br>
|
||||
<br>
|
||||
<code> is the 4 digit HEX code identifying the devices.<br><br>
|
||||
|
||||
<b>base1/2</b> is added to the total kwh as a base (Hoch- und Niedertarifzählerstand).
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<a name="CUL_EMset"></a>
|
||||
<b>Set</b> <ul>N/A</ul><br>
|
||||
|
||||
<a name="CUL_EMget"></a>
|
||||
<b>Get</b> <ul>N/A</ul><br>
|
||||
|
||||
<a name="CUL_EMattr"></a>
|
||||
<b>Attributes</b>
|
||||
<ul>
|
||||
<li><a href="#ignore">ignore</a></li><br>
|
||||
<li><a href="#do_not_notify">do_not_notify</a></li><br>
|
||||
<li><a href="#showtime">showtime</a></li><br>
|
||||
<li><a href="#loglevel">loglevel</a></li><br>
|
||||
<li><a href="#model">model</a> (ESA2000_LED)</li><br>
|
||||
<li><a href="#IODev">IODev</a></li><br>
|
||||
</ul>
|
||||
<br>
|
||||
</ul>
|
||||
|
||||
|
||||
<a name="CUL_HM"></a>
|
||||
<h3>CUL_HM</h3>
|
||||
<ul>
|
||||
@ -2169,7 +2210,8 @@ A line ending with \ will be concatenated with the next one, so long lines
|
||||
Prerequisites:
|
||||
<ul>
|
||||
<li>The <a href="#rfmode">rfmode </a> attribute of at least one attached
|
||||
CUL/CUN device must be set to HomeMatic.
|
||||
CUL/CUN device must be set to HomeMatic. Note: in this mode you will
|
||||
receive <b/>only</b> HomeMatic messages.
|
||||
</li>
|
||||
<li>The protocol used by HomeMatic devices (BidCos, known as AskSin
|
||||
in the culfw) must be enabled in the culfw firmware. This is done
|
||||
|
Loading…
x
Reference in New Issue
Block a user