mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-03 04:36:36 +00:00
Internal parsing rewrite, Sending data should work now
git-svn-id: https://svn.fhem.de/fhem/trunk@606 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
7eb5d9deb1
commit
4280910524
@ -1,4 +1,10 @@
|
||||
##############################################
|
||||
# Thx to Himtronics
|
||||
# http://www.mikrocontroller.net/topic/141831
|
||||
# http://www.mikrocontroller.net/attachment/63563/km271-protokoll.txt
|
||||
# Buderus documents: 63011376, 63011377, 63011378
|
||||
# e.g. http://www.buderus.de/pdf/unterlagen/0063061377.pdf
|
||||
|
||||
package main;
|
||||
|
||||
use strict;
|
||||
@ -12,148 +18,161 @@ sub KM271_CloseDev($);
|
||||
sub KM271_SimpleWrite(@);
|
||||
sub KM271_SimpleRead($);
|
||||
sub KM271_crc($);
|
||||
sub KM271_setbits($$$);
|
||||
sub KM271_Reading($$);
|
||||
|
||||
my $stx = pack('H*', "02");
|
||||
my $dle = pack('H*', "10");
|
||||
my $etx = pack('H*', "03");
|
||||
my $nak = pack('H*', "15");
|
||||
my $logmode = pack('H*', "EE00001003FD");
|
||||
|
||||
# Thx to Himtronics
|
||||
# http://www.mikrocontroller.net/topic/141831
|
||||
# http://www.mikrocontroller.net/attachment/63563/km271-protokoll.txt
|
||||
# Buderus documents: 63011376, 63011377, 63011378
|
||||
# http://www.buderus.de/pdf/unterlagen/0063061377.pdf
|
||||
my %km271_trhash =
|
||||
(
|
||||
"007e" => "Manuell_WW",
|
||||
"0085" => "Manuell_ZirkulationsPumpe",
|
||||
"0093" => "Manuell_Uhrzeit",
|
||||
|
||||
"0300" => "Tagwechsel_1",
|
||||
"0307" => "Tagwechsel_2",
|
||||
"030e" => "Tagwechsel_3",
|
||||
"0315" => "Tagwechsel_4",
|
||||
|
||||
"0400" => "NoData",
|
||||
|
||||
"8000" => 'HK1_Betriebswerte1', # 76, 4 [repeat]
|
||||
"8001" => 'HK1_Betriebswerte2', # 0 (22:33), 2 (7:33)
|
||||
"8002" => 'HK1_Vorlaufsolltemperatur', # 50-65
|
||||
"8003" => 'HK1_Vorlaufisttemperatur', # Schwingt um soll herum
|
||||
"8004" => 'HK1_Raumsolltemperatur', # 34 (22:33) 42 (7:33)
|
||||
"8005" => 'HK1_Raumisttemperatur',
|
||||
"8006" => 'HK1_Einschaltoptimierungszeit',
|
||||
"8007" => 'HK1_Ausschaltoptimierungszeit',
|
||||
"8008" => 'HK1_Pumpenleistung', # 0/100 == Ladepumpe
|
||||
"8009" => 'HK1_Mischerstellung',
|
||||
"800c" => 'HK1_Heizkennlinie_bei_+_10_Grad', # bei Umschaltung tag/nacht
|
||||
"800d" => 'HK1_Heizkennlinie_bei_0_Grad', # bei Umschaltung tag/nacht
|
||||
"800e" => 'HK1_Heizkennlinie_bei_-_10_Grad', # bei Umschaltung tag/nacht
|
||||
|
||||
"8112" => 'HK2_Betriebswerte1',
|
||||
"8113" => 'HK2_Betriebswerte2',
|
||||
"8114" => 'HK2_Vorlaufsolltemperatur',
|
||||
"8115" => 'HK2_Vorlaufisttemperatur',
|
||||
"8116" => 'HK2_Raumsolltemperatur',
|
||||
"8117" => 'HK2_Raumisttemperatur',
|
||||
"8118" => 'HK2_Einschaltoptimierungszeit',
|
||||
"8119" => 'HK2_Ausschaltoptimierungszeit',
|
||||
"811a" => 'HK2_Pumpenleistung',
|
||||
"811b" => 'HK2_Mischerstellung',
|
||||
"811e" => 'HK2_Heizkennlinie_bei_+_10_Grad', # == HK1 - (1 bis 3 Grad)
|
||||
"811f" => 'HK2_Heizkennlinie_bei_0_Grad', # == HK1 - (1 bis 3 Grad)
|
||||
"8120" => 'HK2_Heizkennlinie_bei_-_10_Grad', # == HK1 - (1 bis 3 Grad)
|
||||
|
||||
# 1377, page 11
|
||||
"8424" => 'WW_Betriebswerte1',
|
||||
"8425" => 'WW_Betriebswerte2', # 0 64 96 104 225 228
|
||||
"8426" => 'WW_Solltemperatur', # 10/55
|
||||
"8427" => 'WW_Isttemperatur', # 32-55
|
||||
"8428" => 'WW_Einschaltoptimierungszeit',
|
||||
"8429" => 'WW_Ladepumpe', # 0 1 (an/aus?)
|
||||
|
||||
# 1377, page 13
|
||||
"882a" => 'Kessel_Vorlaufsolltemperatur',
|
||||
"882b" => 'Kessel_Vorlaufisttemperatur', # == Vorlaufisttemperatur_HK1
|
||||
"882c" => 'Brenner_Einschalttemperatur', # 5-81
|
||||
"882d" => 'Brenner_Ausschalttemperatur', # 19-85
|
||||
"882e" => 'Kessel_IntegralHB', # 0-23
|
||||
"882f" => 'Kessel_IntegralLB', # 0-255
|
||||
"8830" => 'Kessel_Fehler',
|
||||
"8831" => 'Kessel_Betrieb', # 0 2 32 34
|
||||
"8832" => 'Brenner_Ansteuerung', # 0 1 (an/aus?)
|
||||
"8833" => 'Abgastemperatur',
|
||||
"8834" => 'Brenner_Stellwert',
|
||||
"8836" => 'Brenner_Laufzeit1_Minuten2',
|
||||
"8837" => 'Brenner_Laufzeit1_Minuten1', # 176
|
||||
"8838" => 'Brenner_Laufzeit1_Minuten0', # 0-255 (Minuten)
|
||||
"8839" => 'Brenner_Laufzeit2_Minuten2',
|
||||
"883a" => 'Brenner_Laufzeit2_Minuten1',
|
||||
"883b" => 'Brenner_Laufzeit2_Minuten0',
|
||||
|
||||
# 1377, page 16
|
||||
"893c" => 'Aussentemperatur', # 0 1 254 255
|
||||
"893d" => 'Aussentemperatur_gedaempft', # 0 1 2
|
||||
"893e" => 'Versionsnummer_VK',
|
||||
"893f" => 'Versionsnummer_NK',
|
||||
"8940" => 'Modulkennung',
|
||||
);
|
||||
|
||||
|
||||
# Do not generate fhem events for the following high volume telegrams
|
||||
# the % represents the relative nr of messages in an unfiltered stream.
|
||||
# You can switch them on with attr all_km271_events
|
||||
my %km271_noevent = (
|
||||
"HK1_Vorlaufisttemperatur" => 1, # 23% of all messages
|
||||
"HK2_Vorlaufisttemperatur" => 1,
|
||||
"Kesselvorlaufisttemperatur" => 1, # 23%, same as Vorlaufisttemperatur_HK1
|
||||
"Kessel_IntegralHB" => 1, # 8%, ??
|
||||
"Kessel_IntegralLB" => 1, # 38%, ??
|
||||
);
|
||||
|
||||
my @km271_HK_Betriebswerte1 = (
|
||||
"Ausschaltoptimierung", "Einschaltoptimierung", "Automatik",
|
||||
"Warmwasservorrang", "Estrichtrocknung", "Ferien", "Frostschutz", "Manuell",
|
||||
);
|
||||
my @km271_HK_Betriebswerte2 = (
|
||||
"Sommer", "Tag", "keine Kommunikation mit FB", "FB fehlerhhaft",
|
||||
"Fehler Vorlauffühler", "maximaler Vorlauf", "externer Störeingang", "frei",
|
||||
);
|
||||
my @km271_WW_Betriebswerte1 = (
|
||||
"Automatik", "Desinfektion", "Nachladung", "Ferien", "Fehler Desinfektion",
|
||||
"Fehler Fuehler", "Fehler WW bleibt kalt", "Fehler Anode",
|
||||
);
|
||||
my @km271_WW_Betriebswerte2 = (
|
||||
"Laden", "Manuell", "Nachladen", "Ausschaltoptimierung",
|
||||
"Einschaltoptimierung", "Tag", "Warm", "Vorrang",
|
||||
);
|
||||
my @km271_Kessel_Betrieb = (
|
||||
"Tag", "Automatik", "Sommer", "Bit3", "Bit4", "Bit5", "Bit6", "Bit7",
|
||||
);
|
||||
my @km271_WW_Ladepumpe = (
|
||||
"Ladepumpe", "Zirkulationspumpe", "Absenkung Solar",
|
||||
"Bit3", "Bit4", "Bit5", "Bit6", "Bit7",
|
||||
);
|
||||
|
||||
|
||||
my %km271_set_betriebsart = (
|
||||
"manuell_nacht"=>0,
|
||||
"manuell_tag" =>1,
|
||||
"automatik" =>2,
|
||||
);
|
||||
sub KM271_setbits($$);
|
||||
sub KM271_GetReading($$);
|
||||
sub KM271_SetReading($$$$$);
|
||||
|
||||
my %km271_sets = (
|
||||
"hk1_nachtsoll" => "07006565%02x656565", # 0.5 celsius
|
||||
"hk1_tagsoll" => "0700656565%02x6565", # 0.5 celsius
|
||||
"hk1_betriebsart" => "070065656565%02x65",
|
||||
|
||||
"ww_soll" => "0C07656565%02x6565", # 1.0 celsius
|
||||
"ww_betriebsart" => "0C0E%02x6565656565",
|
||||
|
||||
"logmode" => "EE0000",
|
||||
);
|
||||
|
||||
|
||||
# Message address:byte_offset in the message
|
||||
# Attributes:
|
||||
# d:x (divide), p:x (add), bf:x (bitfield), a:x (array) ne (generate no event)
|
||||
# mb:x (multi-byte-message, x-bytes, low byte), s (signed value)
|
||||
|
||||
my %km271_tr = (
|
||||
"CFG_SommerAb" => "0000:1", # 6510242a021e
|
||||
"CFG_Raum_Temp_Nacht" => "0000:2,d:2",
|
||||
"CFG_Raum_Temp_Tag" => "0000:3,d:2",
|
||||
"CFG_Betriebsart" => "0000:4,a:4",
|
||||
"CFG_Auslegung" => "000e:4", # 01045a054d65
|
||||
"CFG_FrostAb" => "0015:2", # 030104650005
|
||||
"CFG_Raum_Temp_Aufschalt" => "0015:0,s",
|
||||
"CFG_Absenkungsart" => "001c:1,a:6", # 0c0101656565
|
||||
"CFG_Fernbedienung" => "0031:4,a:0", # 656565fc0104
|
||||
"CFG_Raum_Temp_Offset" => "0031:3,s", #
|
||||
"CFG_GebaeudeArt" => "0070:2,p:1", # f66502066565
|
||||
"CFG_WW_Temperatur" => "007e:3", # 65fb28373c65
|
||||
"CFG_ZirkPumpe" => "0085:5", # 026565016502
|
||||
"CFG_Warmwasser" => "0085:3,a:0",
|
||||
"CFG_Display_Lang" => "0093:0,a:3", # 000302656565
|
||||
"CFG_Display" => "0093:1,a:1",
|
||||
"CFG_MaxAus" => "009a:3", # 65016554050c
|
||||
"CFG_PumpLogik" => "00a1:0", # 2a0565656509
|
||||
"CFG_Abgastemp" => "00a1:5,p:-9,a:5",
|
||||
"CFG_Programm" => "0100:0,a:2", # 01ffff00ffff
|
||||
"CFG_UrlaubsTage" => "0169:3", # 01ffff03ffff
|
||||
"CFG_UhrDiff" => "01e0:1,s", # 010065656565
|
||||
|
||||
"HK1_Betriebswerte1" => "8000:0,bf:0",
|
||||
"HK1_Betriebswerte2" => "8001:0,bf:1",
|
||||
"HK1_Vorlaufsolltemperatur" => "8002:0",
|
||||
"HK1_Vorlaufisttemperatur" => "8003:0,ne", # 23% of all messages
|
||||
"HK1_Raumsolltemperatur" => "8004:0,d:2",
|
||||
"HK1_Raumisttemperatur" => "8005:0,d:2",
|
||||
"HK1_Einschaltoptimierungszeit" => "8006:0",
|
||||
"HK1_Ausschaltoptimierungszeit" => "8007:0",
|
||||
"HK1_Pumpenleistung" => "8008:0",
|
||||
"HK1_Mischerstellung" => "8009:0",
|
||||
"HK1_Heizkennlinie_bei_+_10_Grad" => "800c:0",
|
||||
"HK1_Heizkennlinie_bei_0_Grad" => "800d:0",
|
||||
"HK1_Heizkennlinie_bei_-_10_Grad" => "800e:0",
|
||||
"HK2_Betriebswerte1" => "8112:0,bf:0",
|
||||
"HK2_Betriebswerte2" => "8113:0,bf:1",
|
||||
"HK2_Vorlaufsolltemperatur" => "8114:0",
|
||||
"HK2_Vorlaufisttemperatur" => "8115:0,ne",
|
||||
"HK2_Raumsolltemperatur" => "8116:0,d:2",
|
||||
"HK2_Raumisttemperatur" => "8117:0,d:2",
|
||||
"HK2_Einschaltoptimierungszeit" => "8118:0",
|
||||
"HK2_Ausschaltoptimierungszeit" => "8119:0",
|
||||
"HK2_Pumpenleistung" => "811a:0",
|
||||
"HK2_Mischerstellung" => "811b:0",
|
||||
"HK2_Heizkennlinie_bei_+_10_Grad" => "811e:0",
|
||||
"HK2_Heizkennlinie_bei_0_Grad" => "811f:0",
|
||||
"HK2_Heizkennlinie_bei_-_10_Grad" => "8120:0",
|
||||
"WW_Betriebswerte1" => "8424:0,bf:2",
|
||||
"WW_Betriebswerte2" => "8425:0,bf:3",
|
||||
"WW_Solltemperatur" => "8426:0",
|
||||
"WW_Isttemperatur" => "8427:0",
|
||||
"WW_Einschaltoptimierungszeit" => "8428:0",
|
||||
"WW_Ladepumpe" => "8429:0,bf:5",
|
||||
"Kessel_Vorlaufsolltemperatur" => "882a:0",
|
||||
"Kessel_Vorlaufisttemperatur" => "882b:0,ne", # 23% of all messages
|
||||
"Brenner_Einschalttemperatur" => "882c:0",
|
||||
"Brenner_Ausschalttemperatur" => "882d:0",
|
||||
"Kessel_Integral1" => "882e:0,ne",
|
||||
"Kessel_Integral" => "882f:0,ne,mb:2", # 46% of all messages
|
||||
"Kessel_Fehler" => "8830:0,bf:6",
|
||||
"Kessel_Betrieb" => "8831:0,bf:4",
|
||||
"Brenner_Ansteuerung" => "8832:0,a:0",
|
||||
"Abgastemperatur" => "8833:0",
|
||||
"Brenner_Stellwert" => "8834:0",
|
||||
"Brenner_Laufzeit1_Minuten2" => "8836:0,ne",
|
||||
"Brenner_Laufzeit1_Minuten1" => "8837:0,ne",
|
||||
"Brenner_Laufzeit1_Minuten" => "8838:0,ne,mb:3",
|
||||
"Brenner_Laufzeit2_Minuten2" => "8839:0,ne",
|
||||
"Brenner_Laufzeit2_Minuten1" => "883a:0,ne",
|
||||
"Brenner_Laufzeit2_Minuten" => "883b:0,ne:mb:3",
|
||||
"Aussentemperatur" => "893c:0,s",
|
||||
"Aussentemperatur_gedaempft" => "893d:0,s",
|
||||
"Versionsnummer_VK" => "893e:0",
|
||||
"Versionsnummer_NK" => "893f:0",
|
||||
"Modulkennung" => "8940:0",
|
||||
);
|
||||
my %km271_rev;
|
||||
|
||||
my @km271_bitarrays = (
|
||||
# 0 - HK_Betriebswerte1
|
||||
[ "leer", "Ausschaltoptimierung", "Einschaltoptimierung", "Automatik",
|
||||
"Warmwasservorrang", "Estrichtrocknung", "Ferien", "Frostschutz",
|
||||
"Manuell" ],
|
||||
# 1 - HK_Betriebswerte2
|
||||
[ "leer", "Sommer", "Tag", "keine Kommunikation mit FB", "FB fehlerhaft",
|
||||
"Fehler Vorlauffuehler", "maximaler Vorlauf",
|
||||
"externer Stoehreingang", "frei" ],
|
||||
# 2 - WW_Betriebswerte1
|
||||
[ "aus", "Automatik", "Desinfektion", "Nachladung", "Ferien",
|
||||
"Fehler Desinfektion", "Fehler Fuehler", "Fehler WW bleibt kalt",
|
||||
"Fehler Anode" ],
|
||||
# 3 - WW_Betriebswerte2
|
||||
[ "aus", "Laden", "Manuell", "Nachladen", "Ausschaltoptimierung",
|
||||
"Einschaltoptimierung", "Tag", "Warm", "Vorrang" ],
|
||||
# 4 - Kessel_Betrieb
|
||||
[ "aus", "Tag", "Automatik", "Sommer",
|
||||
"Bit3", "Bit4", "Bit5", "Bit6", "Bit7" ],
|
||||
# 5 - WW_Ladepumpe
|
||||
[ "aus", "Ladepumpe", "Zirkulationspumpe", "Absenkung Solar",
|
||||
"Bit3", "Bit4", "Bit5", "Bit6", "Bit7" ],
|
||||
# 6 - Kessel_Fehler
|
||||
[ "keine", "Bit1", "Bit2", "Bit3", "Bit4",
|
||||
"Abgastemperatur ueberschritten", "Bit6", "Bit7" ],
|
||||
);
|
||||
|
||||
my @km271_arrays = (
|
||||
# 0 - Brenner_Ansteuerung , CFG_Fernbedienung, CFG_Warmwasser
|
||||
[ "aus", "an" ],
|
||||
# 1 - CFG_Display
|
||||
[ "Automatik", "Kessel", "Warmwasser", "Aussen" ],
|
||||
# 2 - CFG_Programm
|
||||
[ "Eigen1", "Familie", "Frueh", "Spaet", "Vormit", "Nachmit",
|
||||
"Mittag", "Single", "Senior" ],
|
||||
# 3 - CFG_Display_Lang
|
||||
[ "DE", "FR", "IT", "NL", "EN", "PL" ],
|
||||
# 4 - CFG_Betriebsart
|
||||
[ "Nacht", "Tag", "Automatik" ],
|
||||
# 5 - CFG_Abgastemp
|
||||
[ "Aus","50","55","60","65","70","75","80","85","90","95","100","105",
|
||||
"110","115","120","125","130","135","140","145","150","155","160","165",
|
||||
"170","175","180","185","190","195","200","205","210","215","220","225",
|
||||
"230","235","240","245","250" ],
|
||||
# 6 - CFG_Absenkungsart
|
||||
[ "Abschalt","Reduziert","Raumhal","Aussenhal"]
|
||||
);
|
||||
|
||||
my %km271_set_betriebsart = (
|
||||
"nacht" => 0,
|
||||
"tag" => 1,
|
||||
"automatik" => 2,
|
||||
);
|
||||
|
||||
|
||||
sub
|
||||
@ -170,6 +189,13 @@ KM271_Initialize($)
|
||||
$hash->{AttrList}= "do_not_notify:1,0 all_km271_events loglevel:0,1,2,3,4,5,6";
|
||||
my @a = ();
|
||||
$hash->{SENDBUFFER} = \@a;
|
||||
|
||||
%km271_rev = ();
|
||||
foreach my $k (sort keys %km271_tr) { # Reverse map
|
||||
my $v = $km271_tr{$k};
|
||||
my ($addr, $b) = split("[:,]", $v);
|
||||
$km271_rev{$addr}{$b} = $k;
|
||||
}
|
||||
}
|
||||
|
||||
#####################################
|
||||
@ -212,30 +238,38 @@ KM271_Set($@)
|
||||
{
|
||||
my ($hash, @a) = @_;
|
||||
|
||||
return "\"set KM271\" needs at least one parameter" if(@a < 2);
|
||||
return "\"set KM271\" needs at least an argument" if(@a < 2);
|
||||
|
||||
my $fmt = $km271_sets{$a[1]};
|
||||
return "Unknown argument $a[1], choose one of " .
|
||||
join(" ", sort keys %km271_sets) if(!defined($fmt));
|
||||
my $val = $a[2];
|
||||
my $numeric_arg = ($val =~ m/^[.0-9]+$/);
|
||||
|
||||
my ($val, $numeric_val);
|
||||
if($fmt =~ m/%/) {
|
||||
return "\"set KM271 $a[1]\" needs at least one parameter" if(@a < 3);
|
||||
$val = $a[2];
|
||||
$numeric_val = ($val =~ m/^[.0-9]+$/);
|
||||
}
|
||||
|
||||
|
||||
if($a[1] =~ m/^hk.*soll$/) {
|
||||
return "Argument must be numeric (between 10 and 30)" if(!$numeric_arg);
|
||||
return "Argument must be numeric (between 10 and 30)" if(!$numeric_val);
|
||||
$val *= 2;
|
||||
}
|
||||
if($a[1] =~ m/^ww.*soll$/) {
|
||||
return "Argument must be numeric (between 30 and 60)" if(!$numeric_arg);
|
||||
return "Argument must be numeric (between 30 and 60)" if(!$numeric_val);
|
||||
}
|
||||
|
||||
if($a[1] =~ m/_betriebsart/) {
|
||||
$val = $km271_set_betriebsart{$val};
|
||||
return "Unknown arg, use one of " .
|
||||
join(" ", sort keys %km271_set_betriebsart) if(!defined($val));
|
||||
}
|
||||
my $data = sprintf($fmt, $val);
|
||||
|
||||
my $data = ($val ? sprintf($fmt, $val) : $fmt);
|
||||
|
||||
push @{$hash->{SENDBUFFER}}, $data;
|
||||
KM271_SimpleWrite($hash, $stx) if(!$hash->{WAITING});
|
||||
KM271_SimpleWrite($hash, "02") if(!$hash->{WAITING});
|
||||
|
||||
return undef;
|
||||
}
|
||||
@ -251,7 +285,7 @@ KM271_Read($)
|
||||
my ($data, $crc);
|
||||
|
||||
my $buf = KM271_SimpleRead($hash);
|
||||
Log GetLogLevel($name,5), "KM271 RAW: " . unpack('H*', $buf);
|
||||
Log 5, "KM271RAW: " . unpack('H*', $buf);
|
||||
|
||||
if(!defined($buf)) {
|
||||
Log 1, "$name: EOF";
|
||||
@ -259,32 +293,40 @@ KM271_Read($)
|
||||
return;
|
||||
}
|
||||
|
||||
if($buf eq "02") { # KM271: Want to send
|
||||
$hash->{PARTIAL} = "";
|
||||
KM271_SimpleWrite($hash, $dle); # We are ready
|
||||
$hash->{WAITING} = 1;
|
||||
return;
|
||||
}
|
||||
$buf = unpack('H*', $buf);
|
||||
|
||||
if(!$hash->{WAITING}) { # Send data
|
||||
if(@{$hash->{SENDBUFFER}} || $hash->{DATASENT}) { # Send data
|
||||
|
||||
if($buf eq "02") { # KM271 Wants to send, override
|
||||
KM271_SimpleWrite($hash, "02");
|
||||
return;
|
||||
}
|
||||
|
||||
if($buf eq "10") {
|
||||
if($hash->{DATASENT}) { # ACK Data
|
||||
if($hash->{DATASENT}) {
|
||||
delete($hash->{DATASENT});
|
||||
KM271_SimpleWrite($hash, "02") if(@{$hash->{SENDBUFFER}});
|
||||
return;
|
||||
}
|
||||
$data = pop @{ $hash->{SENDBUFFER} };
|
||||
$data =~ s/10/1010/g;
|
||||
$crc = KM271_crc($data);
|
||||
KM271_SimpleWrite($hash, $data."1003$crc"); # Send the data
|
||||
$hash->{DATASENT} = 1;
|
||||
}
|
||||
|
||||
if($buf eq "15" && $hash->{DATASENT}) { # NACK from the KM271
|
||||
if($buf eq "15") { # NACK from the KM271
|
||||
Log 1, "$name: NACK!";
|
||||
delete($hash->{DATASENT});
|
||||
KM271_SimpleWrite($hash, "02") if(@{$hash->{SENDBUFFER}});
|
||||
return;
|
||||
}
|
||||
|
||||
} elsif($buf eq "02") { # KM271 Wants to send
|
||||
KM271_SimpleWrite($hash, "10"); # We are ready
|
||||
$hash->{PARTIAL} = "";
|
||||
$hash->{WAITING} = 1;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -292,93 +334,70 @@ KM271_Read($)
|
||||
my $len = length($hash->{PARTIAL});
|
||||
return if($hash->{PARTIAL} !~ m/^(.*)1003(..)$/);
|
||||
($data, $crc) = ($1, $2);
|
||||
$hash->{PARTIAL} = "";
|
||||
delete($hash->{WAITING});
|
||||
|
||||
if(KM271_crc($data) ne $crc) {
|
||||
Log 1, "Wrong CRC in $hash->{PARTIAL}: $crc vs. ". KM271_crc($data);
|
||||
$hash->{PARTIAL} = "";
|
||||
KM271_SimpleWrite($hash, $nak);
|
||||
KM271_SimpleWrite($hash, "15"); # NAK
|
||||
KM271_SimpleWrite($hash, "02") if(@{$hash->{SENDBUFFER}}); # want to send
|
||||
return;
|
||||
}
|
||||
KM271_SimpleWrite($hash, $dle); # Data received ok
|
||||
delete($hash->{WAITING});
|
||||
if($hash->{SENDBUFFER}) {
|
||||
KM271_SimpleWrite($hash, $stx)
|
||||
}
|
||||
|
||||
KM271_SimpleWrite($hash, "10"); # ACK, Data received ok
|
||||
|
||||
|
||||
$data =~ s/1010/10/g;
|
||||
|
||||
|
||||
if($data !~ m/^(....)(.*)/) {
|
||||
Log 1, "$name: Bogus message: $data";
|
||||
return;
|
||||
}
|
||||
|
||||
######################################
|
||||
# Analyze the data
|
||||
my ($fn, $arg) = ($1, $2);
|
||||
my $msg = $km271_trhash{$fn};
|
||||
$msg = "UNKNOWN_$fn" if(!$msg);
|
||||
my $msghash = $km271_rev{$fn};
|
||||
my $all_events = KM271_attr($name, "all_km271_events") ;
|
||||
my $tn = TimeNow();
|
||||
my $val = unpack('H*', $arg);
|
||||
my $gen_notify = $km271_noevent{$msg} ? 0 : 1;
|
||||
$gen_notify = KM271_attr($name, "all_km271_events")
|
||||
if(!$gen_notify);
|
||||
|
||||
#Log 1, "$data" if($fn ne "0400");
|
||||
|
||||
if($msg eq "NoData") {
|
||||
$gen_notify = 0;
|
||||
if($msghash) {
|
||||
foreach my $off (keys %{$msghash}) {
|
||||
|
||||
} elsif($msg =~ m/^UNKNOWN/) {
|
||||
$val = $data;
|
||||
$gen_notify = 0;
|
||||
|
||||
} elsif($msg =~ m/Aussentemperatur/) {
|
||||
$val = $val-256 if($val > 128);
|
||||
my $key = $msghash->{$off};
|
||||
my $val = hex(substr($arg, $off*2, 2));
|
||||
my $ntfy = 1;
|
||||
my @postprocessing = split(",", $km271_tr{$key});
|
||||
shift @postprocessing;
|
||||
while(@postprocessing) {
|
||||
my ($f,$farg) = split(":", shift @postprocessing);
|
||||
|
||||
} elsif($msg =~ m/Brenner_Laufzeit(.)_Minuten(.)/) {
|
||||
my ($idx, $no) = ($1, $2);
|
||||
|
||||
if($no == 2 || $no == 1) {
|
||||
$gen_notify = 0;
|
||||
|
||||
} else {
|
||||
$msg = "Brenner_Laufzeit${idx}_Minuten";
|
||||
$val = KM271_Reading($hash, $msg . "2") * 65536 +
|
||||
KM271_Reading($hash, $msg . "1") * 256 +
|
||||
$val;
|
||||
if($f eq "d") { $val /= $farg; }
|
||||
elsif($f eq "p") { $val += $farg; }
|
||||
elsif($f eq "ne") { $ntfy = $all_events; }
|
||||
elsif($f eq "s") { $val = $val-256 if($val > 128); }
|
||||
elsif($f eq "bf") { $val = KM271_setbits($val, $farg); }
|
||||
elsif($f eq "a") { $val = $km271_arrays[$farg][$val]; }
|
||||
elsif($f eq "mb") {
|
||||
$val += KM271_GetReading($hash, $key."1") * 256;
|
||||
$val += KM271_GetReading($hash, $key."2") * 65536 if($farg == 3);
|
||||
}
|
||||
}
|
||||
KM271_SetReading($hash, $tn, $key, $val, $ntfy);
|
||||
}
|
||||
|
||||
} elsif($msg =~ m/HK._Betriebswerte/) {
|
||||
$val = KM271_setbits($val, \@km271_HK_Betriebswerte1, "leer");
|
||||
} elsif($fn eq "0400") {
|
||||
KM271_SetReading($hash, $tn, "NoData", $arg, 0);
|
||||
|
||||
} elsif($msg =~ m/HK._Betriebswerte2/) {
|
||||
$val = KM271_setbits($val, \@km271_HK_Betriebswerte2, "leer");
|
||||
} elsif($all_events) {
|
||||
KM271_SetReading($hash, $tn, "UNKNOWN_$fn", $data, 1);
|
||||
|
||||
} elsif($msg =~ m/WW_Betriebswerte1/) {
|
||||
$val = KM271_setbits($val, \@km271_WW_Betriebswerte1, "aus");
|
||||
|
||||
} elsif($msg =~ m/WW_Betriebswerte2/) {
|
||||
$val = KM271_setbits($val, \@km271_WW_Betriebswerte2, "aus");
|
||||
|
||||
} elsif($msg =~ m/Brenner_Ansteuerung/) {
|
||||
$val = ($val ? "an" : "aus");
|
||||
|
||||
} elsif($msg =~ m/Kessel_Betrieb/) {
|
||||
$val = KM271_setbits($val, \@km271_Kessel_Betrieb, "aus");
|
||||
|
||||
} elsif($msg =~ m/WW_Ladepumpe/) {
|
||||
$val = KM271_setbits($val, \@km271_WW_Ladepumpe, "aus");
|
||||
|
||||
} elsif($msg =~ m/HK?_Raum.*temperatur/) {
|
||||
$val = $val/2;
|
||||
} else { # Just ignore
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
$val = $arg if(length($arg) > 2);
|
||||
|
||||
Log GetLogLevel($name,4), "KM271 $name: $msg $val";
|
||||
$hash->{READINGS}{$msg}{TIME} = $tn;
|
||||
$hash->{READINGS}{$msg}{VAL} = $val;
|
||||
DoTrigger($name, "$msg: $val") if($gen_notify);
|
||||
|
||||
$hash->{PARTIAL} = "";
|
||||
}
|
||||
|
||||
#####################################
|
||||
@ -398,7 +417,8 @@ sub
|
||||
KM271_SimpleWrite(@)
|
||||
{
|
||||
my ($hash, $msg) = @_;
|
||||
$hash->{Dev}->write($msg) if($hash->{DeviceName});
|
||||
Log 3, "KM271 SimpleWrite $msg" if(length($msg) != 2);
|
||||
$hash->{Dev}->write(pack('H*',$msg)) if($hash->{DeviceName});
|
||||
}
|
||||
|
||||
########################
|
||||
@ -406,7 +426,6 @@ sub
|
||||
KM271_SimpleRead($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
|
||||
return $hash->{Dev}->input() if($hash->{Dev});
|
||||
return undef;
|
||||
}
|
||||
@ -429,6 +448,7 @@ KM271_CloseDev($)
|
||||
delete($selectlist{"$name.$dev"});
|
||||
delete($readyfnlist{"$name.$dev"});
|
||||
delete($hash->{FD});
|
||||
delete($hash->{DeviceName});
|
||||
}
|
||||
|
||||
########################
|
||||
@ -473,26 +493,22 @@ KM271_OpenDev($)
|
||||
|
||||
$hash->{STATE} = "Initialized";
|
||||
|
||||
#$po->write($logmode);
|
||||
push @{$hash->{SENDBUFFER}}, "EE0000";
|
||||
KM271_SimpleWrite($hash, $stx);
|
||||
KM271_SimpleWrite($hash, "02"); # STX
|
||||
|
||||
Log 3, "$dev opened";
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub
|
||||
KM271_setbits($$$)
|
||||
KM271_setbits($$)
|
||||
{
|
||||
my ($val, $arr, $nulltxt) = @_;
|
||||
my $bit = 1;
|
||||
my ($val, $arridx) = @_;
|
||||
my @ret;
|
||||
|
||||
for(my $idx = 0; $idx < 8; $idx++) {
|
||||
push(@ret, $arr->[$idx]) if($val & $bit);
|
||||
$bit *= 2;
|
||||
for(my $idx = 1; $idx <= 8; $idx++) {
|
||||
push(@ret, $km271_bitarrays[$arridx][$idx]) if($val & (1<<($idx-1)));
|
||||
}
|
||||
return $nulltxt if(!@ret);
|
||||
return $km271_bitarrays[$arridx][0] if(!int(@ret));
|
||||
return join(",", @ret);
|
||||
}
|
||||
|
||||
@ -518,7 +534,7 @@ KM271_attr($$)
|
||||
}
|
||||
|
||||
sub
|
||||
KM271_Reading($$)
|
||||
KM271_GetReading($$)
|
||||
{
|
||||
my ($hash, $msg) = @_;
|
||||
return $hash->{READINGS}{$msg}{VAL}
|
||||
@ -526,5 +542,16 @@ KM271_Reading($$)
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub
|
||||
KM271_SetReading($$$$$)
|
||||
{
|
||||
my ($hash,$tn,$key,$val,$ntfy) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
Log GetLogLevel($name,4), "$name: $key $val" if($key ne "NoData");
|
||||
$hash->{READINGS}{$key}{TIME} = $tn;
|
||||
$hash->{READINGS}{$key}{VAL} = $val;
|
||||
DoTrigger($name, "$key: $val") if($ntfy);
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user