2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-03 16:56:54 +00:00

ESA2000 added

git-svn-id: https://svn.fhem.de/fhem/trunk@802 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2011-01-15 11:14:35 +00:00
parent 4d6d896969
commit 837e3a5398
4 changed files with 297 additions and 17 deletions

View File

@ -47,7 +47,7 @@ my %sets = (
my @ampllist = (24, 27, 30, 33, 36, 38, 40, 42); # rAmpl(dB) my @ampllist = (24, 27, 30, 33, 36, 38, 40, 42); # rAmpl(dB)
my $clientsSlowRF = ":FS20:FHT:FHT8V:KS300:USF1000:BS:HMS" . 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 $clientsHomeMatic = ":CUL_HM:HMS:";
my %matchListSlowRF = ( my %matchListSlowRF = (
@ -62,6 +62,7 @@ my %matchListSlowRF = (
"9:CUL_FHTTK" => "^T........", "9:CUL_FHTTK" => "^T........",
"A:CUL_RFR" => "^[0-9A-F]{4}U.", "A:CUL_RFR" => "^[0-9A-F]{4}U.",
"B:CUL_HOERMANN"=> "^R..........", "B:CUL_HOERMANN"=> "^R..........",
"C:ESA2000" => "^S................................\$",
); );
my %matchListHomeMatic = ( my %matchListHomeMatic = (
"1:CUL_HM" => "^A......................", "1:CUL_HM" => "^A......................",
@ -810,7 +811,7 @@ CUL_Parse($$$$$)
my $rssi; my $rssi;
my $dmsg = $rmsg; 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); my $l = length($dmsg);
$rssi = hex(substr($dmsg, $l-2, 2)); $rssi = hex(substr($dmsg, $l-2, 2));
$dmsg = substr($dmsg, 0, $l-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 "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 } elsif($fn eq "A" && $len >= 21) { # AskSin/BidCos/HomeMatic
; ;

223
fhem/FHEM/64_ESA2000.pm Normal file
View 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;

View File

@ -11,25 +11,37 @@ use warnings;
# - check "UNDEFINED" parameters for BS/USF1000/X10 # - check "UNDEFINED" parameters for BS/USF1000/X10
my %flogpar = ( my %flogpar = (
"CUL_EM:.*" => { GPLOT => "cul_em:Power,", FILTER => "%NAME:CNT:.*" }, "CUL_EM:.*"
"CUL_WS:.*" => { GPLOT => "hms:Temp/Hum,", FILTER => "%NAME" }, => { GPLOT => "cul_em:Power,", FILTER => "%NAME:CNT:.*" },
"CUL_FHTTK:.*" => { GPLOT => "fht80tf:Window,", FILTER => "%NAME" }, "CUL_WS:.*"
"FHT:.*" => { GPLOT => "fht:Temp/Act,", FILTER => "%NAME" }, => { GPLOT => "hms:Temp/Hum,", FILTER => "%NAME" },
"HMS:HMS100TFK_.*" => { GPLOT => "fht80tf:Contact,", FILTER => "%NAME" }, "CUL_FHTTK:.*"
"HMS:HMS100T._.*" => { GPLOT => "hms:Temp/Hum,", FILTER => "%NAME:T:.*" }, => { GPLOT => "fht80tf:Window,", FILTER => "%NAME" },
"KS300:.*" => { GPLOT => "ks300:Temp/Rain,ks300_2:Wind/Hum,", "FHT:.*"
FILTER => "%NAME:T:.*" }, => { 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: # Oregon sensors:
# * temperature # * 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 # * 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 # * 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 # * 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 sensors: Rain gauge
"OREGON:(PCR800|RGR918).*" => { GPLOT => "oregon_rain:RainRate", FILTER => "%NAME" }, "OREGON:(PCR800|RGR918).*"
=> { GPLOT => "oregon_rain:RainRate", FILTER => "%NAME" },
); );
##################################### #####################################

View File

@ -85,6 +85,7 @@
<a href="#EMEM">EMEM</a> &nbsp; <a href="#EMEM">EMEM</a> &nbsp;
<a href="#EMGZ">EMGZ</a> &nbsp; <a href="#EMGZ">EMGZ</a> &nbsp;
<a href="#EMWZ">EMWZ</a> &nbsp; <a href="#EMWZ">EMWZ</a> &nbsp;
<a href="#ESA2000">ESA2000</a> &nbsp;
<a href="#FHT">FHT</a> &nbsp; <a href="#FHT">FHT</a> &nbsp;
<a href="#FHT8V">FHT8V</a> &nbsp; <a href="#FHT8V">FHT8V</a> &nbsp;
<a href="#FHZ">FHZ</a> &nbsp; <a href="#FHZ">FHZ</a> &nbsp;
@ -2162,6 +2163,46 @@ A line ending with \ will be concatenated with the next one, so long lines
<br> <br>
</ul> </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 &lt;name&gt; ESA2000 &lt;code&gt;
[base1 base2]</code> <br>
<br>
&lt;code&gt; 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&auml;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> <a name="CUL_HM"></a>
<h3>CUL_HM</h3> <h3>CUL_HM</h3>
<ul> <ul>
@ -2169,7 +2210,8 @@ A line ending with \ will be concatenated with the next one, so long lines
Prerequisites: Prerequisites:
<ul> <ul>
<li>The <a href="#rfmode">rfmode </a> attribute of at least one attached <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>
<li>The protocol used by HomeMatic devices (BidCos, known as AskSin <li>The protocol used by HomeMatic devices (BidCos, known as AskSin
in the culfw) must be enabled in the culfw firmware. This is done in the culfw) must be enabled in the culfw firmware. This is done