Mit diesem Plugin ist es möglich die Daten aus Heliotherm Wärmepumpen (verbunden über die Serielle-Schnittstelle des Wiregate) ans KNX zu schicken.
Code:
#########################################
# HELIOTHERM #
# Communication with WP #
# V1.19 25.04.2014 #
# Author: C.Prenner #
#########################################
$plugin_info{$plugname.'_cycle'} = 120;
# DeBug Level
my $debug = 2;
my %GA_;
# GroupaddressSettings
$GA_{WD} = '13/7/2'; # WatchDog
$GA_{Temp_Aussen}='7/2/100';
$GA_{Temp_Vorlauf}='7/2/101';
$GA_{Temp_Ruecklauf}='7/2/102';
$GA_{Temp_Brauchwasser}='7/2/103';
$GA_{Temp_EQ_Eintritt}='7/2/105';
$GA_{Temp_Frischwasser}='7/2/104';
$GA_{Temp_Verdampfung}='7/2/106';
$GA_{Temp_Kondensation}='7/2/107';
$GA_{Stoerung}='7/5/1';
$GA_{Betriebsart}='7/5/2';
$GA_{Verdichteranforderung}='7/5/3';
$GA_{WW_Normaltemp}='7/5/4';
$GA_{WW_Minimaltemp}='7/5/5';
$GA_{HKR_Soll_Raum}='7/5/6';
$GA_{HKR_Aufheiztemp}='7/5/7';
$GA_{HKR_Absenktemp}='7/5/8';
$GA_{HKR_Heizgrenze}='7/5/9';
$GA_{Verdichter_Status}='7/5/10';
$GA_{Verdichter_Zeit}='7/5/11';
$GA_{Status_HKRPumpe}='7/5/12';
$GA_{Status_Frischwasserpumpe}='7/5/13';
$GA_{Status_EQPumpe}='7/5/14';
$GA_{Status_Verdichter}='7/5/15';
$GA_{Status_Warmwasser}='7/5/16';
$GA_{HKR_Soll}='7/5/17';
$GA_{Niederdruck}='7/5/18';
$GA_{Hochdruck}='7/5/19';
$GA_{Vierwegeventil_Luft}='7/5/20';
$GA_{Kurve_oHG}='7/5/21';
$GA_{Kurve_0}='7/5/22';
$GA_{Kurve_uHG}='7/5/23';
$GA_{Betriebsst_ges}='7/5/25';
$GA_{Betriebsst_HKR}='7/5/26';
$GA_{Betriebsst_WW}='7/5/27';
$GA_{Energiezaehler}='7/5/50';
$GA_{Entstoerung}='7/5/100';
my %Command;
# Adding Commands for LogIN and LogOUT
$Command{LIN}='LIN;';
$Command{LOUT}='LOUT;';
# Adding known MP Numbers
$Command{Temp_Aussen}='MP,NR=0;';
$Command{Temp_Brauchwasser}='MP,NR=2;';
$Command{Temp_Vorlauf}='MP,NR=3;';
$Command{Temp_Ruecklauf}='MP,NR=4;';
$Command{Temp_EQ_Eintritt}='MP,NR=6;';
$Command{Temp_Frischwasser}='MP,NR=11;';
$Command{Temp_Verdampfung}='MP,NR=12;';
$Command{Temp_Kondensation}='MP,NR=13;';
$Command{Niederdruck}='MP,NR=20;';
$Command{Hochdruck}='MP,NR=21;';
$Command{Status_HKRPumpe}='MP,NR=22;';
$Command{Status_EQPumpe}='MP,NR=24;';
$Command{Status_Warmwasser}='MP,NR=25;';
$Command{Status_Verdichter}='MP,NR=30;';
$Command{Stoerung}='MP,NR=31;';
$Command{Vierwegeventil_Luft}='MP,NR=32;';
$Command{Status_Frischwasserpumpe}='MP,NR=50;';
$Command{Verdichteranforderung}='MP,NR=56;';
$Command{HKR_Soll}='MP,NR=57;';
# Adding known SP Numbers
$Command{ID}='SP,NR=9;';
$Command{Verdichter_Status}='SP,NR=10;';
$Command{Verdichter_Zeit}='SP,NR=11;';
$Command{Betriebsart}='SP,Nr=13;';
$Command{Entstoerung}='SP,Nr=14;';
$Command{HKR_Soll_Raum}='SP,NR=69;';
$Command{HKR_Aufheiztemp}='SP,NR=71;';
$Command{HKR_Absenktemp}='SP,NR=72;';
$Command{HKR_Heizgrenze}='SP,NR=76;';
$Command{Kurve_oHG}='SP,Nr=80;';
$Command{Kurve_0}='SP,Nr=81;';
$Command{Kurve_uHG}='SP,Nr=82;';
$Command{WW_Normaltemp}='SP,NR=83;';
$Command{WW_Minimaltemp}='SP,NR=85;';
$Command{Betriebsst_WW}='SP,Nr=171;';
$Command{Betriebsst_HKR}='SP,Nr=172;';
$Command{Betriebsst_ges}='SP,Nr=173;';
$Command{MKR2_aktiviert}='SP,Nr=222;';
$Command{Energiezaehler}='SP,Nr=263;';
my $CtrlCom = "02FDD0E00000"; #Control Commando
my $RplyCom = "02FDE0D00000"; # Reply Commando
my $schnittstelle = '/dev/ttyS0'; # the device
my $timeout = "2500";
use Device::SerialPort;
my $serial;
if($debug>=1){plugin_log($plugname,"Schnittstelle: " . $schnittstelle . " öffnen");}
# init serial port
$serial = Device::SerialPort->new($schnittstelle) || die "Kann $schnittstelle nicht öffnen! ($!)\n";
$serial->baudrate(19200);
$serial->parity("none");
$serial->databits(8);
$serial->stopbits(1);
if($debug>=1){plugin_log($plugname,"Schnittstelle: " . $schnittstelle . " erfolgreich geöffnet");}
if ( Query(MakeQuery($Command{LIN})) == 'OK;' ) { # try LogIN - if Reply=OK; ->
if($debug>=1){plugin_log($plugname, " LogIn OK");}
# Getting values and write them to knx
knx_write($GA_{Stoerung},GetValue('Stoerung'),1.001);
knx_write($GA_{Temp_Aussen},GetValue('Temp_Aussen'),9.001);
knx_write($GA_{Temp_Vorlauf},GetValue('Temp_Vorlauf'),9.001);
knx_write($GA_{Temp_Ruecklauf},GetValue('Temp_Ruecklauf'),9.001);
knx_write($GA_{Temp_Brauchwasser},GetValue('Temp_Brauchwasser'),9.001);
knx_write($GA_{Temp_Frischwasser},GetValue('Temp_Frischwasser'),9.001);
knx_write($GA_{Temp_EQ_Eintritt},GetValue('Temp_EQ_Eintritt'),9.001);
knx_write($GA_{WW_Normaltemp},GetValue('WW_Normaltemp'),9.001);
knx_write($GA_{WW_Minimaltemp},GetValue('WW_Minimaltemp'),9.001);
knx_write($GA_{HKR_Soll_Raum},GetValue('HKR_Soll_Raum'),9.001);
knx_write($GA_{HKR_Aufheiztemp},GetValue('HKR_Aufheiztemp'),9.001);
knx_write($GA_{HKR_Absenktemp},GetValue('HKR_Absenktemp'),10.001);
knx_write($GA_{HKR_Heizgrenze},GetValue('HKR_Heizgrenze'),9.001);
knx_write($GA_{Verdichter_Status},GetValue('Verdichter_Status'),9.001);
knx_write($GA_{Verdichter_Zeit},GetValue('Verdichter_Zeit'),9.001);
knx_write($GA_{Status_HKRPumpe},GetValue('Status_HKRPumpe'),1.001);
knx_write($GA_{Status_Frischwasserpumpe},GetValue('Status_Frischwasserpumpe'),1.001);
knx_write($GA_{Status_EQPumpe},GetValue('Status_EQPumpe'),1.001);
knx_write($GA_{Status_Warmwasser},GetValue('Status_Warmwasser'),1.001);
knx_write($GA_{Status_Verdichter},GetValue('Status_Verdichter'),1.001);
knx_write($GA_{Betriebsart},GetValue('Betriebsart'),9.001);
knx_write($GA_{Verdichteranforderung},GetValue('Verdichteranforderung'),9.001);
knx_write($GA_{HKR_Soll},GetValue('HKR_Soll'),9.001);
knx_write($GA_{Temp_Verdampfung},GetValue('Temp_Verdampfung'),9.001);
knx_write($GA_{Temp_Kondensation},GetValue('Temp_Kondensation'),9.001);
knx_write($GA_{Kurve_oHG},GetValue('Kurve_oHG'),9.001);
knx_write($GA_{Kurve_0},GetValue('Kurve_0'),9.001);
knx_write($GA_{Kurve_uHG},GetValue('Kurve_uHG'),9.001);
knx_write($GA_{Betriebsst_WW},GetValue('Betriebsst_WW'),9.001);
knx_write($GA_{Betriebsst_HKR},GetValue('Betriebsst_HKR'),9.001);
knx_write($GA_{Betriebsst_ges},GetValue('Betriebsst_ges'),9.001);
knx_write($GA_{Niederdruck},GetValue('Niederdruck'),9.001);
knx_write($GA_{Hochdruck},GetValue('Hochdruck'),9.001);
Query(MakeQuery($Command{LOUT}));
knx_write($GA_{WD},1,1.001); # Heartbeat Heliotherm-Plugin
return 'OK';
}
else {
return 'ERROR';
}
sub GetValue { # get the Value within Data ..'VAL='.. ->returns Value
my $Data = MakeQuery($Command{$_[0]}); # build query for command
my $Reply = Query($Data); # send query - >
$Reply =~ /^.+VAL=(-?\d+(\.[0-9]+)?)[^,]?/; # get the reply after VAL=
my $Value = $1;
return $Value;
}
sub MakeQuery { # build query-string
my $QueryCommand = shift;
my $Lenght = length($QueryCommand)+1;
$QueryCommand =~ s/(.)/sprintf("%X",ord($1))/eg;
my $SendCommand = $CtrlCom . sprintf("%02X", $Lenght) . "7E" . $QueryCommand;
$SendCommand .= MakeCRC($SendCommand); # adding CRC
return $SendCommand;
}
sub MakeCRC { # Calculate CRC-Code
my $daten = shift;
my @array = map{ hex }( $daten=~/(..)/g );
my $crc = '0x01';
my $DataByte;
my $i;
foreach $DataByte (@array) {
$crc ^= $DataByte;
if ($DataByte & '0x80'){
$DataByte = ($DataByte << 1) | 1;
}
else {
$DataByte = $DataByte << 1;}
$crc ^= $DataByte;
}
# $crc ^= 0x30;
if ($crc > 256) {$crc -= 256;}
return sprintf("%X", $crc);
}
sub Query{ # sends the command and receives reply -> returns DataString
my $Data = pack("H*",$_[0]); # Translate to HEX values
$serial->write($Data); # Send Data
my $sin=''; #Serial Input
my $count=''; #Counter Input
my $reciv = ''; # received Data
$|=1; #$OUTPUT_AUTOFLUSH
my $exit=0;
while($exit < $timeout) { # read
($count, $sin) = $serial->read(8); #read byte
if($count > 0){ # data recived ?
$sin = unpack "H*", $sin;
$reciv .= $sin; # add that byte to received Data
$exit=0;
}
else{ $exit++ }
}
return GetData($reciv); # return extracted Data
}
sub GetData { # check if Data(HEX) is consistent (CRC) -> returns DataString or CRC_ERROR
my $RawData = $_[0];
my $Data = pack("H*",$RawData); # to String
my $CheckCRC = MakeCRC(substr($RawData, 0, -1)); # get CRC
if ( pack("H*",$CheckCRC) == chop($Data) ) { # CRC Valid
$Data = substr($Data, 8); # chop first 8 Letters (.ýàÐ..x~)
$Data =~ s/\r|\n//g; # remove CRLF
}
else {
$Data = 'CRC_ERROR'
}
return $Data;
}


Kommentar