KM271
git-svn-id: https://svn.fhem.de/fhem/trunk@588 2b470e98-0d58-463d-a4d8-8e2adae1ed80
@ -546,7 +546,7 @@
|
|||||||
- feature: Command save retains now the order of the old config file
|
- feature: Command save retains now the order of the old config file
|
||||||
- feature: List parameter added (list .* RFR_MSGCNT)
|
- feature: List parameter added (list .* RFR_MSGCNT)
|
||||||
|
|
||||||
- =DATE= (4.9)
|
- 2010-03-13 (4.9)
|
||||||
- bugfix: changed the fhem prompt from FHZ> to fhem>
|
- bugfix: changed the fhem prompt from FHZ> to fhem>
|
||||||
- bugfix: CUL_RFR fixes (chaining RFR's should work)
|
- bugfix: CUL_RFR fixes (chaining RFR's should work)
|
||||||
- bugfix: Path in the examples fixed (got corrupted)
|
- bugfix: Path in the examples fixed (got corrupted)
|
||||||
@ -576,3 +576,6 @@
|
|||||||
- feature: pgm3: DBLog added for everything except UserDefs
|
- feature: pgm3: DBLog added for everything except UserDefs
|
||||||
(Gerhard Pfeffer / MartinH)
|
(Gerhard Pfeffer / MartinH)
|
||||||
- feature: pgm2 style changes, SVG in background, optional compression
|
- feature: pgm2 style changes, SVG in background, optional compression
|
||||||
|
|
||||||
|
- =DATE= (5.0)
|
||||||
|
- feature: KM271: Read only
|
||||||
|
450
fhem/FHEM/00_KM271.pm
Executable file
@ -0,0 +1,450 @@
|
|||||||
|
##############################################
|
||||||
|
package main;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Time::HiRes qw(gettimeofday);
|
||||||
|
|
||||||
|
sub KM271_Read($);
|
||||||
|
sub KM271_Ready($);
|
||||||
|
sub KM271_OpenDev($);
|
||||||
|
sub KM271_CloseDev($);
|
||||||
|
sub KM271_SimpleWrite(@);
|
||||||
|
sub KM271_SimpleRead($);
|
||||||
|
sub KM271_crc($);
|
||||||
|
sub KM271_setbits($$);
|
||||||
|
sub KM271_Reading($$);
|
||||||
|
|
||||||
|
my %sets = (
|
||||||
|
);
|
||||||
|
|
||||||
|
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 =
|
||||||
|
(
|
||||||
|
"8000" => 'Betriebswerte_1_HK1', # 76, 4 [repeat]
|
||||||
|
"8001" => 'Betriebswerte_2_HK1', # 0 (22:33), 2 (7:33)
|
||||||
|
"8002" => 'Vorlaufsolltemperatur_HK1', # 50-65
|
||||||
|
"8003" => 'Vorlaufisttemperatur_HK1', # Schwingt um soll herum
|
||||||
|
"8004" => 'Raumsolltemperatur_HK1', # 34 (22:33) 42 (7:33)
|
||||||
|
"8005" => 'Raumisttemperatur_HK1',
|
||||||
|
"8006" => 'Einschaltoptimierungszeit_HK1',
|
||||||
|
"8007" => 'Ausschaltoptimierungszeit_HK1',
|
||||||
|
"8008" => 'Pumpenleistung_HK1', # 0/100 == Ladepumpe
|
||||||
|
"8009" => 'Mischerstellung_HK1',
|
||||||
|
"800a" => 'nicht_belegt',
|
||||||
|
"800b" => 'nicht_belegt',
|
||||||
|
"800c" => 'Heizkennlinie_HK1_bei_+_10_Grad', # bei Umschaltung tag/nacht
|
||||||
|
"800d" => 'Heizkennlinie_HK1_bei_0_Grad', # bei Umschaltung tag/nacht
|
||||||
|
"800e" => 'Heizkennlinie_HK1_bei_-_10_Grad', # bei Umschaltung tag/nacht
|
||||||
|
"800f" => 'nicht_belegt',
|
||||||
|
"8010" => 'nicht_belegt',
|
||||||
|
"8011" => 'nicht_belegt',
|
||||||
|
|
||||||
|
"8112" => 'Betriebswerte_1_HK2',
|
||||||
|
"8113" => 'Betriebswerte_1_HK2',
|
||||||
|
"8114" => 'Vorlaufsolltemperatur_HK2',
|
||||||
|
"8115" => 'Vorlaufisttemperatur_HK2',
|
||||||
|
"8116" => 'Raumsolltemperatur_HK2',
|
||||||
|
"8117" => 'Raumisttemperatur_HK2',
|
||||||
|
"8118" => 'Einschaltoptimierungszeit_HK2',
|
||||||
|
"8119" => 'Ausschaltoptimierungszeit_HK2',
|
||||||
|
"811a" => 'Pumpenleistung_HK2',
|
||||||
|
"811b" => 'Mischerstellung_HK2',
|
||||||
|
"811c" => 'nicht_belegt',
|
||||||
|
"811d" => 'nicht_belegt',
|
||||||
|
"811e" => 'Heizkennlinie_HK2_bei_+_10_Grad', # == HK1 - (1 bis 3)
|
||||||
|
"811f" => 'Heizkennlinie_HK2_bei_0_Grad', # == HK1 - (1 bis 3)
|
||||||
|
"8120" => 'Heizkennlinie_HK2_bei_-_10_Grad', # == HK1 - (1 bis 3)
|
||||||
|
"8121" => 'nicht_belegt',
|
||||||
|
"8122" => 'nicht_belegt',
|
||||||
|
"8123" => 'nicht_belegt',
|
||||||
|
|
||||||
|
"8424" => 'Betriebswerte_1_WW',
|
||||||
|
"8425" => 'Betriebswerte_2_WW', # 0 64 96 104 225 228
|
||||||
|
"8426" => 'Warmwassersolltemperatur', # 10/55
|
||||||
|
"8427" => 'Warmwasseristtemperatur', # 32-55
|
||||||
|
"8428" => 'Warmwasseroptimierungszeit',
|
||||||
|
"8429" => 'Ladepumpe', # 0 1 (an/aus?)
|
||||||
|
|
||||||
|
# 1377, page 13
|
||||||
|
"882a" => 'Kesselvorlaufsolltemperatur',
|
||||||
|
"882b" => 'Kesselvorlaufisttemperatur', # == Vorlaufisttemperatur_HK1
|
||||||
|
"882c" => 'Brennereinschalttemperatur', # 5-81
|
||||||
|
"882d" => 'Brennerausschalttemperatur', # 19-85
|
||||||
|
"882e" => 'Kesselintegral_1', # 0-23
|
||||||
|
"882f" => 'Kesselintegral_2', # 0-255
|
||||||
|
"8830" => 'Kesselfehler',
|
||||||
|
"8831" => 'Kesselbetrieb', # 0 2 32 34
|
||||||
|
"8832" => 'Brenneransteuerung', # 0 1 (an/aus?)
|
||||||
|
"8833" => 'Abgastemperatur',
|
||||||
|
"8834" => 'modulare_Brenner_Stellwert',
|
||||||
|
"8835" => 'nicht_belegt',
|
||||||
|
"8836" => 'Brennerlaufzeit_1_Minuten_Byte2',
|
||||||
|
"8837" => 'Brennerlaufzeit_1_Minuten_Byte1', # 176
|
||||||
|
"8838" => 'Brennerlaufzeit_1_Minuten_Byte0', # 0-255 (Minuten)
|
||||||
|
"8839" => 'Brennerlaufzeit_2_Minuten_Byte2',
|
||||||
|
"883a" => 'Brennerlaufzeit_2_Minuten_Byte1',
|
||||||
|
"883b" => 'Brennerlaufzeit_2_Minuten_Byte0',
|
||||||
|
|
||||||
|
# 1377, page 16
|
||||||
|
"893c" => 'Aussentemperatur', # 0 1 254 255
|
||||||
|
"893d" => 'gedaempfte_Aussentemperatur', # 0 1 2
|
||||||
|
"893e" => 'Versionsnummer_VK',
|
||||||
|
"893f" => 'Versionsnummer_NK',
|
||||||
|
"8940" => 'Modulkennung',
|
||||||
|
"8941" => 'nicht_belegt',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
# 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_ignore = (
|
||||||
|
"Vorlaufisttemperatur_HK1" => 1, # 23%
|
||||||
|
"Kesselvorlaufisttemperatur" => 1, # 23%, same as Vorlaufisttemperatur_HK1
|
||||||
|
"Kesselintegral_1" => 1, # 8%, ??
|
||||||
|
"Kesselintegral_2" => 1, # 38%, ??
|
||||||
|
);
|
||||||
|
|
||||||
|
my @km271_Betriebswerte_1_HK = (
|
||||||
|
"Ausschaltoptimierung", "Einschaltoptimierung", "Automatik",
|
||||||
|
"Warmwasservorrang", "Estrichtrocknung", "Ferien", "Frostschutz", "Manuell",
|
||||||
|
);
|
||||||
|
my @km271_Betriebswerte_2_HK = (
|
||||||
|
"Sommer", "Tag", "keine Kommunikation mit FB", "FB fehlerhhaft",
|
||||||
|
"Fehler Vorlauffühler", "maximaler Vorlauf", "externer Störeingang", "frei",
|
||||||
|
);
|
||||||
|
my @km271_Betriebswerte_1_WW = (
|
||||||
|
"Automatik", "Desinfektion", "Nachladung", "Ferien", "Fehler Desinfektion",
|
||||||
|
"Fehler Fuehler", "Fehler WW bleibt kalt", "Fehler Anode",
|
||||||
|
);
|
||||||
|
my @km271_Betriebswerte_2_WW = (
|
||||||
|
"Laden", "Manuell", "Nachladen", "Ausschaltoptimierung",
|
||||||
|
"Einschaltoptimierung", "Tag", "Warm", "Vorrang",
|
||||||
|
);
|
||||||
|
my @km271_Kesselbetrieb = (
|
||||||
|
"Tag", "Automatik", "Sommer", "Bit3", "Bit4", "Bit5", "Bit6", "Bit7",
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sub
|
||||||
|
KM271_Initialize($)
|
||||||
|
{
|
||||||
|
my ($hash) = @_;
|
||||||
|
|
||||||
|
$hash->{ReadFn} = "KM271_Read";
|
||||||
|
$hash->{ReadyFn} = "KM271_Ready";
|
||||||
|
|
||||||
|
$hash->{DefFn} = "KM271_Define";
|
||||||
|
$hash->{UndefFn} = "KM271_Undef";
|
||||||
|
$hash->{SetFn} = "KM271_Set";
|
||||||
|
$hash->{AttrList}= "do_not_notify:1,0 all_km271_events loglevel:0,1,2,3,4,5,6";
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
sub
|
||||||
|
KM271_Define($$)
|
||||||
|
{
|
||||||
|
my ($hash, $def) = @_;
|
||||||
|
my @a = split("[ \t][ \t]*", $def);
|
||||||
|
|
||||||
|
return "wrong syntax: define <name> KM271 [devicename|none]"
|
||||||
|
if(@a != 3);
|
||||||
|
|
||||||
|
KM271_CloseDev($hash);
|
||||||
|
my $name = $a[0];
|
||||||
|
my $dev = $a[2];
|
||||||
|
|
||||||
|
if($dev eq "none") {
|
||||||
|
Log 1, "KM271 device is none, commands will be echoed only";
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hash->{DeviceName} = $dev;
|
||||||
|
my $ret = KM271_OpenDev($hash);
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
sub
|
||||||
|
KM271_Undef($$)
|
||||||
|
{
|
||||||
|
my ($hash, $arg) = @_;
|
||||||
|
KM271_CloseDev($hash);
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
sub
|
||||||
|
KM271_Set($@)
|
||||||
|
{
|
||||||
|
my ($hash, @a) = @_;
|
||||||
|
|
||||||
|
return "\"set KM271\" needs at least one parameter" if(@a < 2);
|
||||||
|
return "Unknown argument $a[1], choose one of " . join(" ", sort keys %sets)
|
||||||
|
if(!defined($sets{$a[1]}));
|
||||||
|
|
||||||
|
my $name = shift @a;
|
||||||
|
my $type = shift @a;
|
||||||
|
my $arg = join("", @a);
|
||||||
|
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
# called from the global loop, when the select for hash->{FD} reports data
|
||||||
|
sub
|
||||||
|
KM271_Read($)
|
||||||
|
{
|
||||||
|
my ($hash) = @_;
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
|
||||||
|
my $buf = KM271_SimpleRead($hash);
|
||||||
|
Log GetLogLevel($name,5), "KM271 RAW: " . unpack('H*', $buf);
|
||||||
|
|
||||||
|
if(!defined($buf)) {
|
||||||
|
Log 1, "$name: EOF";
|
||||||
|
KM271_CloseDev($hash);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$buf = unpack('H*', $buf);
|
||||||
|
if($buf eq "02") {
|
||||||
|
$hash->{PARTIAL} = "";
|
||||||
|
KM271_SimpleWrite($hash, $dle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hash->{PARTIAL} .= $buf;
|
||||||
|
my $len = length($hash->{PARTIAL});
|
||||||
|
return if($hash->{PARTIAL} !~ m/^(.*)1003(..)$/);
|
||||||
|
my ($data, $crc) = ($1, $2);
|
||||||
|
if(KM271_crc($data) ne $crc) {
|
||||||
|
Log 1, "Wrong CRC in $hash->{PARTIAL}: $crc vs. ". KM271_crc($data);
|
||||||
|
$hash->{PARTIAL} = "";
|
||||||
|
KM271_SimpleWrite($hash, $nak);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
KM271_SimpleWrite($hash, $dle);
|
||||||
|
|
||||||
|
$data =~ s/1010/10/g;
|
||||||
|
if($data =~ m/^(8...)(..)/) {
|
||||||
|
my ($fn, $arg) = ($1, $2);
|
||||||
|
|
||||||
|
my $msg = $km271_trhash{$fn};
|
||||||
|
$msg = "UNKNOWN_$fn" if(!$msg);
|
||||||
|
my $tn = TimeNow();
|
||||||
|
my $val = hex($arg);
|
||||||
|
my $ignore = $km271_ignore{$msg};
|
||||||
|
|
||||||
|
|
||||||
|
if($msg =~ m/Aussentemperatur/) {
|
||||||
|
$val = $val-256 if($val > 128);
|
||||||
|
|
||||||
|
} elsif($msg =~ m/Brennerlaufzeit_(.)_Minuten_Byte(.)/) {
|
||||||
|
my ($idx, $no) = ($1, $2);
|
||||||
|
|
||||||
|
if($no == 2 || $no == 1) {
|
||||||
|
$ignore = 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$msg = "Brennerlaufzeit_${idx}_Minuten";
|
||||||
|
$val = KM271_Reading($hash, $msg . "_Byte2") * 65536 +
|
||||||
|
KM271_Reading($hash, $msg . "_Byte1") * 256 +
|
||||||
|
$val;
|
||||||
|
}
|
||||||
|
|
||||||
|
} elsif($msg =~ m/Betriebswerte_1_HK/) {
|
||||||
|
$val = KM271_setbits($val, \@km271_Betriebswerte_1_HK);
|
||||||
|
|
||||||
|
} elsif($msg =~ m/Betriebswerte_2_HK/) {
|
||||||
|
$val = KM271_setbits($val, \@km271_Betriebswerte_2_HK);
|
||||||
|
|
||||||
|
} elsif($msg =~ m/Betriebswerte_1_WW/) {
|
||||||
|
$val = KM271_setbits($val, \@km271_Betriebswerte_1_WW);
|
||||||
|
|
||||||
|
} elsif($msg =~ m/Betriebswerte_2_WW/) {
|
||||||
|
$val = KM271_setbits($val, \@km271_Betriebswerte_2_WW);
|
||||||
|
|
||||||
|
} elsif($msg =~ m/Brenneransteuerung/) {
|
||||||
|
$val = ($val ? "an" : "aus");
|
||||||
|
|
||||||
|
} elsif($msg =~ m/Kesselbetrieb/) {
|
||||||
|
$val = KM271_setbits($val, \@km271_Kesselbetrieb);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Log GetLogLevel($name,4), "KM271 $name: $msg $val";
|
||||||
|
$hash->{READINGS}{$msg}{TIME} = $tn;
|
||||||
|
$hash->{READINGS}{$msg}{VAL} = $val;
|
||||||
|
if(KM271_attr($name, "all_km271_events") || !$ignore) {
|
||||||
|
DoTrigger($name, "$msg: $val");
|
||||||
|
}
|
||||||
|
|
||||||
|
} elsif($data eq "04000701c4024192") {
|
||||||
|
# No data message
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log 1, "$name: UNKNOWN $data";
|
||||||
|
|
||||||
|
}
|
||||||
|
$hash->{PARTIAL} = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
sub
|
||||||
|
KM271_Ready($)
|
||||||
|
{
|
||||||
|
my ($hash) = @_;
|
||||||
|
|
||||||
|
# This is relevant for windows/USB only
|
||||||
|
my $po = $hash->{Dev};
|
||||||
|
my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags) = $po->status;
|
||||||
|
return ($InBytes>0);
|
||||||
|
}
|
||||||
|
|
||||||
|
########################
|
||||||
|
sub
|
||||||
|
KM271_SimpleWrite(@)
|
||||||
|
{
|
||||||
|
my ($hash, $msg) = @_;
|
||||||
|
$hash->{Dev}->write($msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
########################
|
||||||
|
sub
|
||||||
|
KM271_SimpleRead($)
|
||||||
|
{
|
||||||
|
my ($hash) = @_;
|
||||||
|
|
||||||
|
return $hash->{Dev}->input() if($hash->{Dev});
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
########################
|
||||||
|
sub
|
||||||
|
KM271_CloseDev($)
|
||||||
|
{
|
||||||
|
my ($hash) = @_;
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
my $dev = $hash->{DeviceName};
|
||||||
|
|
||||||
|
return if(!$dev); # "none"
|
||||||
|
|
||||||
|
if($hash->{Dev}) {
|
||||||
|
$hash->{Dev}->close() ;
|
||||||
|
delete($hash->{Dev});
|
||||||
|
|
||||||
|
}
|
||||||
|
delete($selectlist{"$name.$dev"});
|
||||||
|
delete($readyfnlist{"$name.$dev"});
|
||||||
|
delete($hash->{FD});
|
||||||
|
}
|
||||||
|
|
||||||
|
########################
|
||||||
|
sub
|
||||||
|
KM271_OpenDev($)
|
||||||
|
{
|
||||||
|
my ($hash) = @_;
|
||||||
|
my $dev = $hash->{DeviceName};
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
my $po;
|
||||||
|
|
||||||
|
$hash->{PARTIAL} = "";
|
||||||
|
Log 3, "KM271 opening $name device $dev";
|
||||||
|
|
||||||
|
if ($^O=~/Win/) {
|
||||||
|
require Win32::SerialPort;
|
||||||
|
$po = new Win32::SerialPort ($dev);
|
||||||
|
} else {
|
||||||
|
require Device::SerialPort;
|
||||||
|
$po = new Device::SerialPort ($dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$po) {
|
||||||
|
Log(3, "Can't open $dev: $!");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
$hash->{Dev} = $po;
|
||||||
|
if( $^O =~ /Win/ ) {
|
||||||
|
$readyfnlist{"$name.$dev"} = $hash;
|
||||||
|
} else {
|
||||||
|
$hash->{FD} = $po->FILENO;
|
||||||
|
delete($readyfnlist{"$name.$dev"});
|
||||||
|
$selectlist{"$name.$dev"} = $hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
$po->reset_error();
|
||||||
|
$po->baudrate(2400);
|
||||||
|
$po->databits(8);
|
||||||
|
$po->parity('none');
|
||||||
|
$po->stopbits(1);
|
||||||
|
$po->handshake('none');
|
||||||
|
$po->write($logmode);
|
||||||
|
|
||||||
|
$hash->{STATE} = "Initialized";
|
||||||
|
|
||||||
|
Log 3, "$dev opened";
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
KM271_setbits($$)
|
||||||
|
{
|
||||||
|
my ($val, $arr) = @_;
|
||||||
|
my $bit = 1;
|
||||||
|
my @ret;
|
||||||
|
|
||||||
|
for(my $idx = 0; $idx < 8; $idx++) {
|
||||||
|
push(@ret, $arr->[$idx]) if($val & $bit);
|
||||||
|
$bit *= 2;
|
||||||
|
}
|
||||||
|
return "keine Bits gesetzt" if(!@ret);
|
||||||
|
return join(",", @ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
KM271_crc($)
|
||||||
|
{
|
||||||
|
my $in = shift;
|
||||||
|
my $x = 0;
|
||||||
|
foreach my $a (split("", pack('H*', $in))) {
|
||||||
|
$x ^= ord($a);
|
||||||
|
}
|
||||||
|
$x ^= 0x10;
|
||||||
|
$x ^= 0x03;
|
||||||
|
return sprintf("%02x", $x);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
KM271_attr($$)
|
||||||
|
{
|
||||||
|
my ($name, $attr) = @_;
|
||||||
|
return $attr{$name}{$attr} if($attr{$name} && $attr{$name}{$attr});
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
KM271_Reading($$)
|
||||||
|
{
|
||||||
|
my ($hash, $msg) = @_;
|
||||||
|
return $hash->{READINGS}{$msg}{VAL}
|
||||||
|
if($hash->{READINGS} && $hash->{READINGS}{$msg});
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
1;
|
@ -56,4 +56,6 @@
|
|||||||
Peter's RRD support. See the HOWTO
|
Peter's RRD support. See the HOWTO
|
||||||
- serial.pm
|
- serial.pm
|
||||||
Serial line analyzer
|
Serial line analyzer
|
||||||
|
- km271.pl
|
||||||
|
Plain Buderus Logamatic 2107 communication module (KM271) logger
|
||||||
|
See the 00_KM271.pm fhem module for its successor.
|
||||||
|
192
fhem/contrib/km271.pl
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Time::HiRes qw(gettimeofday);
|
||||||
|
|
||||||
|
sub kmcrc($);
|
||||||
|
sub fmt_now();
|
||||||
|
|
||||||
|
|
||||||
|
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 %trhash =
|
||||||
|
(
|
||||||
|
"8000" => 'Betriebswerte_1_HK1', # 76, 4 [repeat]
|
||||||
|
"8001" => 'Betriebswerte_2_HK1', # 0 (22:33), 2 (7:33)
|
||||||
|
"8002" => 'Vorlaufsolltemperatur_HK1', # 50-65
|
||||||
|
"8003" => 'Vorlaufisttemperatur_HK1', # Schwingt um soll herum
|
||||||
|
"8004" => 'Raumsolltemperatur_HK1', # 34 (22:33) 42 (7:33)
|
||||||
|
"8005" => 'Raumisttemperatur_HK1',
|
||||||
|
"8006" => 'Einschaltoptimierungszeit_HK1',
|
||||||
|
"8007" => 'Ausschaltoptimierungszeit_HK1',
|
||||||
|
"8008" => 'Pumpenleistung_HK1', # 0/100 == Ladepumpe
|
||||||
|
"8009" => 'Mischerstellung_HK1',
|
||||||
|
"800a" => 'nicht_belegt',
|
||||||
|
"800b" => 'nicht_belegt',
|
||||||
|
"800c" => 'Heizkennlinie_HK1_bei_+_10_Grad', # bei Umschaltung tag/nacht
|
||||||
|
"800d" => 'Heizkennlinie_HK1_bei_0_Grad', # bei Umschaltung tag/nacht
|
||||||
|
"800e" => 'Heizkennlinie_HK1_bei_-_10_Grad', # bei Umschaltung tag/nacht
|
||||||
|
"800f" => 'nicht_belegt',
|
||||||
|
"8010" => 'nicht_belegt',
|
||||||
|
"8011" => 'nicht_belegt',
|
||||||
|
|
||||||
|
"8112" => 'Betriebswerte_1_HK2',
|
||||||
|
"8113" => 'Betriebswerte_1_HK2',
|
||||||
|
"8114" => 'Vorlaufsolltemperatur_HK2',
|
||||||
|
"8115" => 'Vorlaufisttemperatur_HK2',
|
||||||
|
"8116" => 'Raumsolltemperatur_HK2',
|
||||||
|
"8117" => 'Raumisttemperatur_HK2',
|
||||||
|
"8118" => 'Einschaltoptimierungszeit_HK2',
|
||||||
|
"8119" => 'Ausschaltoptimierungszeit_HK2',
|
||||||
|
"811a" => 'Pumpenleistung_HK2',
|
||||||
|
"811b" => 'Mischerstellung_HK2',
|
||||||
|
"811c" => 'nicht_belegt',
|
||||||
|
"811d" => 'nicht_belegt',
|
||||||
|
"811e" => 'Heizkennlinie_HK2_bei_+_10_Grad', # == HK1 - (1 bis 3)
|
||||||
|
"811f" => 'Heizkennlinie_HK2_bei_0_Grad', # == HK1 - (1 bis 3)
|
||||||
|
"8120" => 'Heizkennlinie_HK2_bei_-_10_Grad', # == HK1 - (1 bis 3)
|
||||||
|
"8121" => 'nicht_belegt',
|
||||||
|
"8122" => 'nicht_belegt',
|
||||||
|
"8123" => 'nicht_belegt',
|
||||||
|
|
||||||
|
"8424" => 'Betriebswerte_1_WW',
|
||||||
|
"8425" => 'Betriebswerte_2_WW', # 0 64 96 104 225 228
|
||||||
|
"8426" => 'Warmwassersolltemperatur', # 10/55
|
||||||
|
"8427" => 'Warmwasseristtemperatur', # 32-55
|
||||||
|
"8428" => 'Warmwasseroptimierungszeit',
|
||||||
|
"8429" => 'Ladepumpe', # 0 1 (an/aus?)
|
||||||
|
|
||||||
|
# 1377, page 13
|
||||||
|
"882a" => 'Kesselvorlaufsolltemperatur',
|
||||||
|
"882b" => 'Kesselvorlaufisttemperatur', # == Vorlaufisttemperatur_HK1
|
||||||
|
"882c" => 'Brennereinschalttemperatur', # 5-81
|
||||||
|
"882d" => 'Brennerausschalttemperatur', # 19-85
|
||||||
|
"882e" => 'Kesselintegral_1', # 0-23
|
||||||
|
"882f" => 'Kesselintegral_2', # 0-255
|
||||||
|
"8830" => 'Kesselfehler',
|
||||||
|
"8831" => 'Kesselbetrieb', # 0 2 32 34
|
||||||
|
"8832" => 'Brenneransteuerung', # 0 1 (an/aus?)
|
||||||
|
"8833" => 'Abgastemperatur',
|
||||||
|
"8834" => 'modulare_Brenner_Stellwert',
|
||||||
|
"8835" => 'nicht_belegt',
|
||||||
|
"8836" => 'Brennerlaufzeit_1_Stunden_2',
|
||||||
|
"8837" => 'Brennerlaufzeit_1_Stunden_1', # 176
|
||||||
|
"8838" => 'Brennerlaufzeit_1_Stunden_0', # 0-255 (Minuten)
|
||||||
|
"8839" => 'Brennerlaufzeit_2_Stunden_2',
|
||||||
|
"883a" => 'Brennerlaufzeit_2_Stunden_1',
|
||||||
|
"883b" => 'Brennerlaufzeit_2_Stunden_0',
|
||||||
|
|
||||||
|
# 1377, page 16
|
||||||
|
"893c" => 'Aussentemperatur', # 0 1 254 255
|
||||||
|
"893d" => 'gedaempfte_Aussentemperatur', # 0 1 2
|
||||||
|
"893e" => 'Versionsnummer_VK',
|
||||||
|
"893f" => 'Versionsnummer_NK',
|
||||||
|
"8940" => 'Modulkennung',
|
||||||
|
"8941" => 'nicht_belegt',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
die("Usage: km271.pl <device>\n") if(int(@ARGV) != 1);
|
||||||
|
|
||||||
|
require Device::SerialPort;
|
||||||
|
my $po = new Device::SerialPort($ARGV[0]);
|
||||||
|
die("Can't open $ARGV[0]: $!\n") if(!$po);
|
||||||
|
|
||||||
|
$po->reset_error();
|
||||||
|
$po->baudrate(2400);
|
||||||
|
$po->databits(8);
|
||||||
|
$po->parity('none');
|
||||||
|
$po->stopbits(1);
|
||||||
|
$po->handshake('none');
|
||||||
|
|
||||||
|
my $fdin = $po->FILENO;
|
||||||
|
printf("Setting device into logmode\n");
|
||||||
|
$po->write($logmode);
|
||||||
|
|
||||||
|
|
||||||
|
$| = 1;
|
||||||
|
my $tbuf = "";
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
my ($rout, $rin) = ('', '');
|
||||||
|
|
||||||
|
vec($rin, $fdin, 1) = 1;
|
||||||
|
|
||||||
|
my $nfound = select($rout=$rin, undef, undef, undef);
|
||||||
|
die("Select error: $!\n") if(!defined($nfound) || $nfound < 0);
|
||||||
|
|
||||||
|
if(vec($rout, $fdin, 1)) {
|
||||||
|
my $buf = $po->input();
|
||||||
|
if(!defined($buf)) {
|
||||||
|
printf("EOF on dev\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$buf = unpack('H*', $buf);
|
||||||
|
#printf("%s DEV %s\n", fmt_now(), $buf);
|
||||||
|
if($buf eq "02") {
|
||||||
|
$tbuf = "";
|
||||||
|
$po->write($dle);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tbuf .= $buf;
|
||||||
|
my $len = length($tbuf);
|
||||||
|
next if($tbuf !~ m/^(.*)1003(..)$/);
|
||||||
|
my ($data, $crc) = ($1, $2);
|
||||||
|
if(kmcrc($data) ne $crc) {
|
||||||
|
printf("Wrong CRC in $tbuf ($crc vs. %s)\n", kmcrc($data));
|
||||||
|
$tbuf = "";
|
||||||
|
$po->write($nak);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
$po->write($dle);
|
||||||
|
|
||||||
|
$data =~ s/1010/10/g;
|
||||||
|
if($data =~ m/^(8...)(..)/) {
|
||||||
|
my ($fn, $arg) = ($1, $2);
|
||||||
|
printf("%s %s %d\n", fmt_now(), $trhash{$fn}, hex($arg));
|
||||||
|
} elsif($data eq "04000701c4024192") {
|
||||||
|
# No data message
|
||||||
|
} else {
|
||||||
|
printf("%s UNKNOWN %s\n", fmt_now(), $data);
|
||||||
|
}
|
||||||
|
$tbuf = "";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
kmcrc($)
|
||||||
|
{
|
||||||
|
my $in = shift;
|
||||||
|
my $x = 0;
|
||||||
|
foreach my $a (split("", pack('H*', $in))) {
|
||||||
|
$x ^= ord($a);
|
||||||
|
}
|
||||||
|
$x ^= 0x10;
|
||||||
|
$x ^= 0x03;
|
||||||
|
return sprintf("%02x", $x);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
fmt_now()
|
||||||
|
{
|
||||||
|
my $now = gettimeofday()+0.0;
|
||||||
|
my @t = localtime($now);
|
||||||
|
my $t = sprintf("%04d-%02d-%02d_%02d:%02d:%02d.%03d",
|
||||||
|
$t[5]+1900, $t[4]+1, $t[3], $t[2], $t[1], $t[0],
|
||||||
|
($now-int($now)) * 1000);
|
||||||
|
return $t;
|
||||||
|
}
|
||||||
|
|
@ -73,40 +73,42 @@
|
|||||||
<a href="#CUL">CUL</a>
|
<a href="#CUL">CUL</a>
|
||||||
<a href="#CUL_EM">CUL_EM</a>
|
<a href="#CUL_EM">CUL_EM</a>
|
||||||
<a href="#CUL_FHTTK">CUL_FHTTK</a>
|
<a href="#CUL_FHTTK">CUL_FHTTK</a>
|
||||||
<a href="#CUL_WS">CUL_WS</a>
|
|
||||||
<a href="#CUL_RFR">CUL_RFR</a>
|
<a href="#CUL_RFR">CUL_RFR</a>
|
||||||
|
<a href="#CUL_WS">CUL_WS</a>
|
||||||
|
<a href="#DS18S20">DS18S20</a>
|
||||||
<a href="#DbLog">DbLog</a>
|
<a href="#DbLog">DbLog</a>
|
||||||
<a href="#EM">EM</a>
|
<a href="#EM">EM</a>
|
||||||
<a href="#EMEM">EMEM</a>
|
<a href="#EMEM">EMEM</a>
|
||||||
<a href="#EMGZ">EMGZ</a>
|
<a href="#EMGZ">EMGZ</a>
|
||||||
<a href="#EMWZ">EMWZ</a>
|
<a href="#EMWZ">EMWZ</a>
|
||||||
|
<a href="#FHEMRENDERER">FHEMRENDERER</a>
|
||||||
|
<a href="#FHEMWEB">FHEMWEB</a>
|
||||||
<a href="#FHT">FHT</a>
|
<a href="#FHT">FHT</a>
|
||||||
<a href="#FHZ">FHZ</a>
|
<a href="#FHZ">FHZ</a>
|
||||||
<a href="#FS20">FS20</a>
|
<a href="#FS20">FS20</a>
|
||||||
<a href="#HMS">HMS</a>
|
<a href="#HMS">HMS</a>
|
||||||
<a href="#FHEMWEB">FHEMWEB</a>
|
|
||||||
<a href="#IPWE">IPWE</a>
|
<a href="#IPWE">IPWE</a>
|
||||||
|
<a href="#KM271">KM271</a>
|
||||||
<a href="#KS300">KS300</a>
|
<a href="#KS300">KS300</a>
|
||||||
|
<a href="#LGTV">LGTV</a>
|
||||||
<a href="#LIRC">LIRC</a>
|
<a href="#LIRC">LIRC</a>
|
||||||
<a href="#M232">M232</a>
|
<a href="#M232">M232</a>
|
||||||
<a href="#M232Counter">M232Counter</a>
|
<a href="#M232Counter">M232Counter</a>
|
||||||
<a href="#M232Voltage">M232Voltage</a>
|
<a href="#M232Voltage">M232Voltage</a>
|
||||||
<a href="#OWFS">OWFS</a>
|
<a href="#OWFS">OWFS</a>
|
||||||
<a href="#OWTEMP">OWTEMP</a>
|
<a href="#OWTEMP">OWTEMP</a>
|
||||||
<a href="#DS18S20">DS18S20</a>
|
|
||||||
<a href="#SCIVT">SCIVT</a>
|
<a href="#SCIVT">SCIVT</a>
|
||||||
<a href="#structure">structure</a>
|
|
||||||
<a href="#WS2000">WS2000</a>
|
|
||||||
<a href="#WS3600">WS3600</a>
|
|
||||||
<a href="#SISPM">SISPM</a>
|
<a href="#SISPM">SISPM</a>
|
||||||
<a href="#SIS_PMS">SIS_PMS</a>
|
<a href="#SIS_PMS">SIS_PMS</a>
|
||||||
<a href="#WS300">WS300</a>
|
|
||||||
<a href="#Weather">Weather</a>
|
|
||||||
<a href="#USF1000">USF1000</a>
|
<a href="#USF1000">USF1000</a>
|
||||||
|
<a href="#WS2000">WS2000</a>
|
||||||
|
<a href="#WS300">WS300</a>
|
||||||
|
<a href="#WS3600">WS3600</a>
|
||||||
|
<a href="#Weather">Weather</a>
|
||||||
<a href="#X10">X10</a>
|
<a href="#X10">X10</a>
|
||||||
|
<a href="#structure">structure</a>
|
||||||
<a href="#xxLG7000">xxLG7000</a>
|
<a href="#xxLG7000">xxLG7000</a>
|
||||||
<a href="#LGTV">LGTV</a>
|
|
||||||
<a href="#FHEMRENDERER">FHEMRENDERER</a>
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@ -2160,6 +2162,138 @@ A line ending with \ will be concatenated with the next one, so long lines
|
|||||||
<br>
|
<br>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<a name="KM271"></a>
|
||||||
|
<h3>KM271</h3>
|
||||||
|
<ul>
|
||||||
|
KM271 is the name of the communication device for the Buderus Logamatic 2105
|
||||||
|
or 2107 heating controller. It is connected via a serial line to the fhem
|
||||||
|
computer. The fhem module sets the communication device into log-mode, which
|
||||||
|
then will generate an event on change of the inner parameters. There are
|
||||||
|
about 20.000 events a day, the FHEM module ignores about 90% of them, if the
|
||||||
|
<a href="#all_km271_events">all_km271_events</a> attribute is not set.<br>
|
||||||
|
<br>
|
||||||
|
Following events are known:
|
||||||
|
<div id="block">
|
||||||
|
<pre> Betriebswerte_1_HK1
|
||||||
|
Betriebswerte_2_HK1
|
||||||
|
Vorlaufsolltemperatur_HK1
|
||||||
|
Vorlaufisttemperatur_HK1
|
||||||
|
Raumsolltemperatur_HK1
|
||||||
|
Raumisttemperatur_HK1
|
||||||
|
Einschaltoptimierungszeit_HK1
|
||||||
|
Ausschaltoptimierungszeit_HK1
|
||||||
|
Pumpenleistung_HK1
|
||||||
|
Mischerstellung_HK1
|
||||||
|
Heizkennlinie_HK1_bei_+_10_Grad
|
||||||
|
Heizkennlinie_HK1_bei_0_Grad
|
||||||
|
Heizkennlinie_HK1_bei_-_10_Grad
|
||||||
|
|
||||||
|
Betriebswerte_1_HK2
|
||||||
|
Betriebswerte_1_HK2
|
||||||
|
Vorlaufsolltemperatur_HK2
|
||||||
|
Vorlaufisttemperatur_HK2
|
||||||
|
Raumsolltemperatur_HK2
|
||||||
|
Raumisttemperatur_HK2
|
||||||
|
Einschaltoptimierungszeit_HK2
|
||||||
|
Ausschaltoptimierungszeit_HK2
|
||||||
|
Pumpenleistung_HK2
|
||||||
|
Mischerstellung_HK2
|
||||||
|
Heizkennlinie_HK2_bei_+_10_Grad
|
||||||
|
Heizkennlinie_HK2_bei_0_Grad
|
||||||
|
Heizkennlinie_HK2_bei_-_10_Grad
|
||||||
|
|
||||||
|
Betriebswerte_1_WW
|
||||||
|
Betriebswerte_2_WW
|
||||||
|
Warmwassersolltemperatur
|
||||||
|
Warmwasseristtemperatur
|
||||||
|
Warmwasseroptimierungszeit
|
||||||
|
Ladepumpe
|
||||||
|
|
||||||
|
Kesselvorlaufsolltemperatur
|
||||||
|
Kesselvorlaufisttemperatur
|
||||||
|
Brennereinschalttemperatur
|
||||||
|
Brennerausschalttemperatur
|
||||||
|
Kesselintegral_1
|
||||||
|
Kesselintegral_2
|
||||||
|
Kesselfehler
|
||||||
|
Kesselbetrieb
|
||||||
|
Brenneransteuerung
|
||||||
|
Abgastemperatur
|
||||||
|
modulare_Brenner_Stellwert
|
||||||
|
Brennerlaufzeit_1_Minuten_Byte2
|
||||||
|
Brennerlaufzeit_1_Minuten_Byte1
|
||||||
|
Brennerlaufzeit_1_Minuten_Byte0
|
||||||
|
Brennerlaufzeit_2_Minuten_Byte2
|
||||||
|
Brennerlaufzeit_2_Minuten_Byte1
|
||||||
|
Brennerlaufzeit_2_Minuten_Byte0
|
||||||
|
|
||||||
|
Aussentemperatur
|
||||||
|
gedaempfte_Aussentemperatur
|
||||||
|
Versionsnummer_VK
|
||||||
|
Versionsnummer_NK
|
||||||
|
Modulkennung
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
As I cannot explain all the values, I logged data for a period and plotted
|
||||||
|
each received value in the following logs:
|
||||||
|
<ul>
|
||||||
|
<li><a href="km271/km271_Aussentemperatur.png">Aussentemperatur</a></li>
|
||||||
|
<li><a href="km271/km271_Betriebswerte.png">Betriebswerte</a></li>
|
||||||
|
<li><a href="km271/km271_Brenneransteuerung.png">Brenneransteuerung</a></li>
|
||||||
|
<li><a href="km271/km271_Brennerlaufzeit.png">Brennerlaufzeit</a></li>
|
||||||
|
<li><a href="km271/km271_Brennerschalttemperatur.png">Brennerschalttemperatur</a></li>
|
||||||
|
<li><a href="km271/km271_Heizkennlinie.png">Heizkennlinie</a></li>
|
||||||
|
<li><a href="km271/km271_Kesselbetrieb.png">Kesselbetrieb</a></li>
|
||||||
|
<li><a href="km271/km271_Kesselintegral.png">Kesselintegral</a></li>
|
||||||
|
<li><a href="km271/km271_Ladepumpe.png">Ladepumpe</a></li>
|
||||||
|
<li><a href="km271/km271_Raumsolltemperatur_HK1.png">Raumsolltemperatur_HK1</a></li>
|
||||||
|
<li><a href="km271/km271_Vorlauftemperatur.png">Vorlauftemperatur</a></li>
|
||||||
|
<li><a href="km271/km271_Warmwasser.png">Warmwasser</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<b>Define</b>
|
||||||
|
<ul>
|
||||||
|
<code>define <name> KM271 <serial-device-name></code>
|
||||||
|
<br><br>
|
||||||
|
Example:
|
||||||
|
<ul>
|
||||||
|
<code>define KM271 KM271 /dev/ttyS0</code><br>
|
||||||
|
</ul>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<b>Set </b>
|
||||||
|
<ul>
|
||||||
|
Not yet implemented
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<b>Get</b>
|
||||||
|
<ul>
|
||||||
|
N/A
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<b>Attributes</b>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#do_not_notify">do_not_notify</a></li>
|
||||||
|
<li><a href="#loglevel">loglevel</a></li>
|
||||||
|
<a name="all_km271_events"></a>
|
||||||
|
<li>all_km271_events<br>
|
||||||
|
If this attribute is set to 1, do not ignore following events:<br>
|
||||||
|
Vorlaufisttemperatur_HK1, Kesselvorlaufisttemperatur,
|
||||||
|
Kesselintegral_1, "Kesselintegral_2<br>
|
||||||
|
These events account for ca. 92% of all events.</li>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
<a name="KS300"></a>
|
<a name="KS300"></a>
|
||||||
<h3>KS300</h3>
|
<h3>KS300</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
BIN
fhem/docs/km271/km271_Aussentemperatur.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
fhem/docs/km271/km271_Betriebswerte.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
fhem/docs/km271/km271_Brenneransteuerung.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
fhem/docs/km271/km271_Brennerlaufzeit.png
Normal file
After Width: | Height: | Size: 8.4 KiB |
BIN
fhem/docs/km271/km271_Brennerschalttemperatur.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
fhem/docs/km271/km271_Heizkennlinie.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
fhem/docs/km271/km271_Kesselbetrieb.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
fhem/docs/km271/km271_Kesselintegral.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
fhem/docs/km271/km271_Ladepumpe.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
fhem/docs/km271/km271_Raumsolltemperatur_HK1.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
fhem/docs/km271/km271_Vorlauftemperatur.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
fhem/docs/km271/km271_Warmwasser.png
Normal file
After Width: | Height: | Size: 7.2 KiB |