LUXTRONIK2: minor changes, change of reading titles

git-svn-id: https://svn.fhem.de/fhem/trunk@4794 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
tpoitzsch
2014-02-02 14:10:15 +00:00
parent d98a4c08a2
commit a96a095dab

View File

@@ -37,11 +37,12 @@ use Time::HiRes qw/ time /;
use POSIX; use POSIX;
use Net::Telnet; use Net::Telnet;
#List of firmware versions that are known to be compatible with this modul # Modul Version for remote debugging
my $testedFirmware = "#V1.54C#"; my $modulVersion = "2014-02-02";
my $compatibleFirmware = "#V1.54C#";
#my $cc; # The Itmes Changed Counter #List of firmware versions that are known to be compatible with this modul
my $testedFirmware = "#V1.54C#V1.60#V1.69#";
my $compatibleFirmware = "#V1.54C#V1.60#V1.69#";
sub ######################################## sub ########################################
LUXTRONIK2_Initialize($) LUXTRONIK2_Initialize($)
@@ -50,11 +51,13 @@ LUXTRONIK2_Initialize($)
$hash->{DefFn} = "LUXTRONIK2_Define"; $hash->{DefFn} = "LUXTRONIK2_Define";
$hash->{UndefFn} = "LUXTRONIK2_Undefine"; $hash->{UndefFn} = "LUXTRONIK2_Undefine";
$hash->{NotifyFn} = "LUXTRONIK2_Notify";
$hash->{SetFn} = "LUXTRONIK2_Set"; $hash->{SetFn} = "LUXTRONIK2_Set";
$hash->{AttrFn} = "LUXTRONIK2_Attr"; $hash->{AttrFn} = "LUXTRONIK2_Attr";
$hash->{AttrList} = "disable:0,1 ". $hash->{AttrList} = "disable:0,1 ".
"allowSetParameter:0,1 ". "allowSetParameter:0,1 ".
"autoSynchClock:slider,10,5,300 ". "autoSynchClock:slider,10,5,300 ".
"doStatistics:0,1 ".
"ignoreFirmwareCheck:0,1 ". "ignoreFirmwareCheck:0,1 ".
"statusHTML ". "statusHTML ".
$readingFnAttributes; $readingFnAttributes;
@@ -85,9 +88,14 @@ LUXTRONIK2_Define($$)
#Get first data after 10 seconds #Get first data after 10 seconds
InternalTimer(gettimeofday() + 10, "LUXTRONIK2_GetUpdate", $hash, 0); InternalTimer(gettimeofday() + 10, "LUXTRONIK2_GetUpdate", $hash, 0);
#Reset temporary values (min and max reading durations) #Reset temporary values
$hash->{fhem}{durationFetchReadingsMin} = 0; $hash->{fhem}{durationFetchReadingsMin} = 0;
$hash->{fhem}{durationFetchReadingsMax} = 0; $hash->{fhem}{durationFetchReadingsMax} = 0;
$hash->{fhem}{alertFirmware} = 0;
$hash->{fhem}{statModeHotWater} = 0;
$hash->{fhem}{modulVersion} = $modulVersion;
Log3 $hash,5,"$name: LUXTRONIK2.pm version is $modulVersion.";
return undef; return undef;
} }
@@ -104,11 +112,61 @@ LUXTRONIK2_Undefine($$)
return undef; return undef;
} }
sub ########################################
LUXTRONIK2_Notify(@) {
my ($hash,$dev) = @_;
my $name = $hash->{NAME};
if ($dev->{NAME} eq "global" ) { # splitted to reduce CPU load
if (grep (m/^INITIALIZED|REREADCFG$/,@{$dev->{CHANGED}})){
# housekeeping
my %cleanUp = (
delayDeviceTime => "delayDeviceTimeCalc",
deviceTimeStartReadings => "deviceTimeCalc",
heatingSummerMode => "heatingLimit",
thresholdTemperatureSummerMode => "thresholdHeatingLimit",
lastDeviceClockSynch => "deviceTimeLastSync",
operatingHoursHeatPump => "counterHoursHeatPump",
operatingHoursSecondHeatSource1 => "counterHours2ndHeatSource1",
operatingHoursSecondHeatSource2 => "counterHours2ndHeatSource2",
operatingHoursSecondHeatSource3 => "counterHours2ndHeatSource3",
operatingHoursHeating => "counterHoursHeating",
operatingHoursHotWater => "counterHoursHotWater",
heatQuantityHeating => "counterHeatQHeating",
heatQuantityHotWater => "counterHeatQHotWater",
heatQuantityTotal => "counterHeatQTotal",
currentOperatingStatus1 => "opStateHeatPump1",
currentOperatingState1 => "opStateHeatPump1",
currentOperatingStatus2 => "opStateHeatPump3",
currentOperatingState2 => "opStateHeatPump2",
currentOperatingState3 => "opStateHeatPump3",
heatingOperatingMode => "opModeHeating",
heatingOperatingState => "opStateHeating",
hotWaterOperatingMode => "opModeHotWater",
hotWaterStatus => "opStateHotWater",
hotWaterState => "opStateHotWater",
heatingSystemCirculationPump => "heatingSystemCircPump",
hotWaterCirculationPumpExtern => "hotWaterCircPumpExtern" );
my $oldReading;
my $newReading;
while (($oldReading, $newReading) = each(%cleanUp)) {
if ( exists( $hash->{READINGS}{$oldReading} ) ) {
delete($hash->{READINGS}{$oldReading});
Log3 $name,2,"$name: !!! Change/fix in LUXTRONIK2-Modul: '$oldReading' is now '$newReading'";
}
}
}
}
return;
}
sub ######################################## sub ########################################
LUXTRONIK2_Set($$@) LUXTRONIK2_Set($$@)
{ {
my ($hash, $name, $cmd, $val) = @_; my ($hash, $name, $cmd, $val) = @_;
my $resultStr=""; my $resultStr = "";
if($cmd eq 'statusRequest') { if($cmd eq 'statusRequest') {
$hash->{LOCAL} = 1; $hash->{LOCAL} = 1;
@@ -116,6 +174,20 @@ LUXTRONIK2_Set($$@)
$hash->{LOCAL} = 0; $hash->{LOCAL} = 0;
return undef; return undef;
} }
elsif ($cmd eq 'deleteStatistics') {
if ( ($val eq "all" || $val eq "statGradientBoilerTempLoss")
&& exists($defs{$name}{READINGS}{statGradientBoilerTempLoss})) {
delete $defs{$name}{READINGS}{statGradientBoilerTempLoss};
$resultStr .= " statGradientBoilerTempLoss";
}
if ( $resultStr eq "" ) {
$resultStr = "$name: No statistics to delete";
} else {
$resultStr = "$name: Statistic value(s) deleted:" . $resultStr;
}
Log3 $hash, 3, $resultStr;
return $resultStr;
}
elsif($cmd eq 'INTERVAL' && int(@_)==4 ) { elsif($cmd eq 'INTERVAL' && int(@_)==4 ) {
$val = 30 if( $val < 30 ); $val = 30 if( $val < 30 );
$hash->{INTERVAL}=$val; $hash->{INTERVAL}=$val;
@@ -125,7 +197,7 @@ LUXTRONIK2_Set($$@)
#Check Firmware and Set-Paramter-lock #Check Firmware and Set-Paramter-lock
if ($cmd eq 'synchronizeClockHeatPump' || if ($cmd eq 'synchronizeClockHeatPump' ||
$cmd eq 'hotWaterTemperatureTarget' || $cmd eq 'hotWaterTemperatureTarget' ||
$cmd eq 'hotWaterOperatingMode') $cmd eq 'opModeHotWater')
{ {
my $firmware = ReadingsVal($name,"firmware",""); my $firmware = ReadingsVal($name,"firmware","");
my $firmwareCheck = LUXTRONIK2_checkFirmware($firmware); my $firmwareCheck = LUXTRONIK2_checkFirmware($firmware);
@@ -136,8 +208,8 @@ LUXTRONIK2_Set($$@)
# stop in case of untested firmware and firmware check enabled # stop in case of untested firmware and firmware check enabled
} elsif (AttrVal($name, "ignoreFirmwareCheck", 0)!= 1 && } elsif (AttrVal($name, "ignoreFirmwareCheck", 0)!= 1 &&
$firmwareCheck eq "fwNotTested") { $firmwareCheck eq "fwNotTested") {
Log3 $name, 3, $name." Error: Host firmware '$firmware' not tested for parameter setting. To test set 'ignoreFirmwareCheck' to 1"; Log3 $name, 3, $name." Error: Host firmware '$firmware' not tested for parameter setting. To test set attribute 'ignoreFirmwareCheck' to 1";
return "Firmware '$firmware' not compatible for parameter setting. To test set 'ignoreFirmwareCheck' to 1."; return "Firmware '$firmware' not compatible for parameter setting. To test set attribute 'ignoreFirmwareCheck' to 1.";
# stop in case setting of parameters is not enabled # stop in case setting of parameters is not enabled
} elsif ( AttrVal($name, "allowSetParameter", 0) != 1) { } elsif ( AttrVal($name, "allowSetParameter", 0) != 1) {
Log3 $name, 3, $name." Error: Setting of parameters not allowed. Please set attribut 'allowSetParameter' to 1"; Log3 $name, 3, $name." Error: Setting of parameters not allowed. Please set attribut 'allowSetParameter' to 1";
@@ -152,8 +224,8 @@ LUXTRONIK2_Set($$@)
Log3 $name, 3, "$name - $resultStr"; Log3 $name, 3, "$name - $resultStr";
return $resultStr; return $resultStr;
} elsif(int(@_)==4 && } elsif(int(@_)==4 &&
($cmd eq 'hotWaterTemperatureTarget' || ($cmd eq 'hotWaterTemperatureTarget'
$cmd eq 'hotWaterOperatingMode')) { || $cmd eq 'opModeHotWater')) {
$hash->{LOCAL} = 1; $hash->{LOCAL} = 1;
$resultStr = LUXTRONIK2_SetParameter ($hash, $cmd, $val); $resultStr = LUXTRONIK2_SetParameter ($hash, $cmd, $val);
$hash->{LOCAL} = 0; $hash->{LOCAL} = 0;
@@ -161,10 +233,11 @@ LUXTRONIK2_Set($$@)
} }
my $list = "statusRequest:noArg". my $list = "statusRequest:noArg".
" deleteStatistics:all,statGradientBoilerTempLoss".
" hotWaterTemperatureTarget:slider,30.0,0.5,65.0". " hotWaterTemperatureTarget:slider,30.0,0.5,65.0".
" hotWaterOperatingMode:Auto,Party,Off". " opModeHotWater:Auto,Party,Off".
" synchronizeClockHeatPump:noArg". " synchronizeClockHeatPump:noArg".
" INTERVAL:slider,60,30,1800"; " INTERVAL:slider,30,30,1800";
return "Unknown argument $cmd, choose one of $list"; return "Unknown argument $cmd, choose one of $list";
} }
@@ -184,6 +257,7 @@ LUXTRONIK2_Attr(@)
} }
} }
} }
return undef; return undef;
} }
@@ -204,7 +278,7 @@ LUXTRONIK2_GetUpdate($)
return undef if( AttrVal($name, "disable", 0 ) == 1 ); return undef if( AttrVal($name, "disable", 0 ) == 1 );
} }
$hash->{helper}{RUNNING_PID} = BlockingCall("LUXTRONIK2_DoUpdate", $name."|".$host, "LUXTRONIK2_UpdateDone", 20, "LUXTRONIK2_UpdateAborted", $hash) unless(exists($hash->{helper}{RUNNING_PID})); $hash->{helper}{RUNNING_PID} = BlockingCall("LUXTRONIK2_DoUpdate", $name."|".$host, "LUXTRONIK2_UpdateDone", 25, "LUXTRONIK2_UpdateAborted", $hash) unless(exists($hash->{helper}{RUNNING_PID}));
} }
@@ -254,16 +328,16 @@ LUXTRONIK2_DoUpdate($)
$socket->recv($result,4); $socket->recv($result,4);
$count = unpack("N", $result); $count = unpack("N", $result);
if($count > 0) { if($count > 0) {
Log3 $name, 4, "$name parameter on target changed, restart parameter reading after 5 seconds"; Log3 $name, 4, "$name: Parameter on target changed, restart parameter reading after 5 seconds";
$socket->close(); $socket->close();
return "$name|2|Status = $count - parameter on target changed, restart device reading after 5 seconds"; return "$name|2|Status = $count - parameter on target changed, restart device reading after 5 seconds";
} }
#(FOV) read next 4 bytes of response -> should be number_of_parameters > 0 #(FOV) read next 4 bytes of response -> should be count_calc_values > 0
$socket->recv($result,4); $socket->recv($result,4);
$count = unpack("N", $result); my $count_calc_values = unpack("N", $result);
if($count == 0) { if($count_calc_values == 0) {
Log3 $name, 2, "$name LUXTRONIK2_DoUpdate-Error: Fetching operational values - 0 values announced: ".length($result)." -> ".$count; Log3 $name, 2, "$name LUXTRONIK2_DoUpdate-Error: Fetching operational values - 0 values announced: ".length($result)." -> ".$count_calc_values;
$socket->close(); $socket->close();
return "$name|0|0 values read"; return "$name|0|0 values read";
} }
@@ -272,27 +346,27 @@ LUXTRONIK2_DoUpdate($)
my $i=1; my $i=1;
$result=""; $result="";
my $buf=""; my $buf="";
while($i<=$count) { while($i<=$count_calc_values) {
$socket->recv($buf,4); $socket->recv($buf,4);
$result.=$buf; $result.=$buf;
$i++; $i++;
} }
if(length($result) != $count*4) { if(length($result) != $count_calc_values*4) {
Log3 $name, 1, "$name LUXTRONIK2_DoUpdate-Error: operational values length check: ".length($result)." should have been ". $count * 4; Log3 $name, 1, "$name LUXTRONIK2_DoUpdate-Error: operational values length check: ".length($result)." should have been ". $count_calc_values * 4;
$socket->close(); $socket->close();
return "$name|0|Number of values read mismatch ( $!)\n"; return "$name|0|Number of values read mismatch ( $!)\n";
} }
#(FOV) unpack response in array #(FOV) unpack response in array
@heatpump_values = unpack("N$count", $result); @heatpump_values = unpack("N$count_calc_values", $result);
if(scalar(@heatpump_values) != $count) { if(scalar(@heatpump_values) != $count_calc_values) {
Log3 $name, 2, "$name LUXTRONIK2_DoUpdate-Error: unpacking problem by operation values: ".scalar(@heatpump_values)." instead of ".$count; Log3 $name, 2, "$name LUXTRONIK2_DoUpdate-Error: unpacking problem by operation values: ".scalar(@heatpump_values)." instead of ".$count_calc_values;
$socket->close(); $socket->close();
return "$name|0|Unpacking problem of operational values"; return "$name|0|Unpacking problem of operational values";
} }
Log3 $name, 5, "$name: $count operational values received"; Log3 $name, 5, "$name: $count_calc_values operational values received";
############################ ############################
#Fetch set parameters (FSP) #Fetch set parameters (FSP)
@@ -313,9 +387,9 @@ LUXTRONIK2_DoUpdate($)
#(FSP) read next 4 bytes of response -> should be number_of_parameters > 0 #(FSP) read next 4 bytes of response -> should be number_of_parameters > 0
$socket->recv($result,4); $socket->recv($result,4);
$count = unpack("N", $result); my $count_set_parameter = unpack("N", $result);
if($count == 0) { if($count_set_parameter == 0) {
Log3 $name, 2, "$name LUXTRONIK2_DoUpdate-Error: 0 parameter read: ".length($result)." -> ".$count; Log3 $name, 2, "$name LUXTRONIK2_DoUpdate-Error: 0 parameter read: ".length($result)." -> ".$count_set_parameter;
$socket->close(); $socket->close();
return "$name|0|0 parameter read"; return "$name|0|0 parameter read";
} }
@@ -324,25 +398,25 @@ LUXTRONIK2_DoUpdate($)
$i=1; $i=1;
$result=""; $result="";
$buf=""; $buf="";
while($i<=$count) { while($i<=$count_set_parameter) {
$socket->recv($buf,4); $socket->recv($buf,4);
$result.=$buf; $result.=$buf;
$i++; $i++;
} }
if(length($result) != $count*4) { if(length($result) != $count_set_parameter*4) {
Log3 $name, 1, "$name LUXTRONIK2_DoUpdate-Error: parameter length check: ".length($result)." should have been ". $count * 4; Log3 $name, 1, "$name LUXTRONIK2_DoUpdate-Error: parameter length check: ".length($result)." should have been ". $count_set_parameter * 4;
$socket->close(); $socket->close();
return "$name|0|Number of parameters read mismatch ( $!)\n"; return "$name|0|Number of parameters read mismatch ( $!)\n";
} }
@heatpump_parameters = unpack("N$count", $result); @heatpump_parameters = unpack("N$count_set_parameter", $result);
if(scalar(@heatpump_parameters) != $count) { if(scalar(@heatpump_parameters) != $count_set_parameter) {
Log3 $name, 2, "$name LUXTRONIK2_DoUpdate-Error: unpacking problem by set parameter: ".scalar(@heatpump_parameters)." instead of ".$count; Log3 $name, 2, "$name LUXTRONIK2_DoUpdate-Error: unpacking problem by set parameter: ".scalar(@heatpump_parameters)." instead of ".$count_set_parameter;
$socket->close(); $socket->close();
return "$name|0|Unpacking problem of set parameters"; return "$name|0|Unpacking problem of set parameters";
} }
Log3 $name, 5, "$name: $count set values received"; Log3 $name, 5, "$name: $count_set_parameter set values received";
goto SKIP_VISIBILITY_READING; goto SKIP_VISIBILITY_READING;
@@ -410,25 +484,25 @@ SKIP_VISIBILITY_READING:
my $return_str="$name"; my $return_str="$name";
# 1 - no error = 1 # 1 - no error = 1
$return_str .= "|1"; $return_str .= "|1";
# 2 - currentOperatingState1 # 2 - opStateHeatPump1
$return_str .= "|".$heatpump_values[117]; $return_str .= "|".$heatpump_values[117];
# 3 - currentOperatingState3 # 3 - opStateHeatPump3
$return_str .= "|".$heatpump_values[119]; $return_str .= "|".$heatpump_values[119];
# 4 - Stufe - Value 121 # 4 - Stufe - ID_WEB_HauptMenuAHP_Stufe
$return_str .= "|".$heatpump_values[121]; $return_str .= "|".$heatpump_values[121];
# 5 - Temperature Value 122 # 5 - Temperature Value - ID_WEB_HauptMenuAHP_Temp
$return_str .= "|".$heatpump_values[122]; $return_str .= "|".$heatpump_values[122];
# 6 - Verdichter1 # 6 - Compressor1
$return_str .= "|".$heatpump_values[44]; $return_str .= "|".$heatpump_values[44];
# 7 - hotWaterOperatingMode # 7 - opModeHotWater
$return_str .= "|".$heatpump_parameters[4]; $return_str .= "|".$heatpump_parameters[4];
# 8 - hotWaterMonitoring # 8 - hotWaterMonitoring
$return_str .= "|".$heatpump_values[124]; $return_str .= "|".$heatpump_values[124];
# 9 - hotWaterBoilerValve # 9 - hotWaterBoilerValve
$return_str .= "|".$heatpump_values[38]; $return_str .= "|".$heatpump_values[38];
# 10 - heatingOperatingMode # 10 - opModeHeating
$return_str .= "|".$heatpump_parameters[3]; $return_str .= "|".$heatpump_parameters[3];
# 11 - heatingSommerMode # 11 - heatingLimit
$return_str .= "|".$heatpump_parameters[699]; $return_str .= "|".$heatpump_parameters[699];
# 12 - ambientTemperature # 12 - ambientTemperature
$return_str .= "|".$heatpump_values[15]; $return_str .= "|".$heatpump_values[15];
@@ -452,9 +526,9 @@ SKIP_VISIBILITY_READING:
$fwvalue .= chr($heatpump_values[$fi]) if $heatpump_values[$fi]; $fwvalue .= chr($heatpump_values[$fi]) if $heatpump_values[$fi];
} }
$return_str .= "|".$fwvalue; $return_str .= "|".$fwvalue;
# 21 - thresholdTemperatureSummerMode # 21 - thresholdHeatingLimit
$return_str .= "|".$heatpump_parameters[700]; $return_str .= "|".$heatpump_parameters[700];
# 22 - readingsDeviceTime # 22 - rawDeviceTimeCalc
$return_str .= "|".$heatpump_values[134]; $return_str .= "|".$heatpump_values[134];
# 23 - heatSourceIN # 23 - heatSourceIN
$return_str .= "|".$heatpump_values[19]; $return_str .= "|".$heatpump_values[19];
@@ -464,40 +538,50 @@ SKIP_VISIBILITY_READING:
$return_str .= "|".$heatpump_values[18]; $return_str .= "|".$heatpump_values[18];
# 26 - hotGasTemperature # 26 - hotGasTemperature
$return_str .= "|".$heatpump_values[14]; $return_str .= "|".$heatpump_values[14];
# 27 - heatingSystemCirculationPump # 27 - heatingSystemCircPump
$return_str .= "|".$heatpump_values[39]; $return_str .= "|".$heatpump_values[39];
# 28 - hotWaterCirculatingPumpExtern # 28 - hotWaterCircPumpExtern
$return_str .= "|".$heatpump_values[46]; $return_str .= "|".$heatpump_values[46];
# 29 - readingStartTime # 29 - readingFhemStartTime
$return_str .= "|".$readingStartTime; $return_str .= "|".$readingStartTime;
# 30 - readingEndTime # 30 - readingFhemEndTime
$return_str .= "|".$readingEndTime; $return_str .= "|".$readingEndTime;
# 31 - typeHeatpump # 31 - typeHeatpump
$return_str .= "|".$heatpump_values[78]; $return_str .= "|".$heatpump_values[78];
# 32 - operatingHoursSecondHeatSource1 # 32 - counterHours2ndHeatSource1
$return_str .= "|".$heatpump_values[60]; $return_str .= "|".$heatpump_values[60];
# 33 - operatingHoursHeatpump # 33 - counterHoursHeatpump
$return_str .= "|".$heatpump_values[63]; $return_str .= "|".$heatpump_values[63];
# 34 - operatingHoursHeating # 34 - counterHoursHeating
$return_str .= "|".$heatpump_values[64]; $return_str .= "|".$heatpump_values[64];
# 35 - operatingHoursHotWater # 35 - counterHoursHotWater
$return_str .= "|".$heatpump_values[65]; $return_str .= "|".$heatpump_values[65];
# 36 - heatQuantityHeating # 36 - counterHeatQHeating
$return_str .= "|".$heatpump_values[151]; $return_str .= "|".$heatpump_values[151];
# 37 - heatQuantityHotWater # 37 - counterHeatQHeating
$return_str .= "|".$heatpump_values[152]; $return_str .= "|".$heatpump_values[152];
# 38 - operatingHoursSecondHeatSource2 # 38 - counterHours2ndHeatSource2
$return_str .= "|".$heatpump_values[61]; $return_str .= "|".$heatpump_values[61];
# 39 - operatingHoursSecondHeatSource3 # 39 - counterHours2ndHeatSource3
$return_str .= "|".$heatpump_values[62]; $return_str .= "|".$heatpump_values[62];
# 40 - currentOperatingState2 # 40 - opStateHeatPump2
$return_str .= "|".$heatpump_values[118]; $return_str .= "|".$heatpump_values[118];
# 41 - durationOperatingState # 41 - opStateHeatPump2Duration
$return_str .= "|".$heatpump_values[120]; $return_str .= "|".$heatpump_values[120];
# 42 - timeError0 # 42 - timeError0
$return_str .= "|".$heatpump_values[95]; $return_str .= "|".$heatpump_values[95];
# 43 - bivalentLevel # 43 - bivalentLevel
$return_str .= "|".$heatpump_values[79]; $return_str .= "|".$heatpump_values[79];
# 44 - Number of calculated values
$return_str .= "|".$count_calc_values;
# 45 - Number of set parameters
$return_str .= "|".$count_set_parameter;
# 46 - opStateHeating
$return_str .= "|".$heatpump_values[125];
# 47 - deltaHeatingReduction
$return_str .= "|".$heatpump_parameters[13];
# 48 - thresholdTemperatureSetBack
$return_str .= "|".$heatpump_parameters[111];
return $return_str; return $return_str;
} }
@@ -545,24 +629,37 @@ LUXTRONIK2_UpdateDone($)
16 => "Durchflussueberwachung", 16 => "Durchflussueberwachung",
17 => "Elektrische Zusatzheizung" ); 17 => "Elektrische Zusatzheizung" );
my %wpMode = ( 0 => "Automatik", my %wpMode = ( 0 => "Automatik",
1 => "Zusatzheizung", 1 => "Zusatzheizung",
2 => "Party", 2 => "Party",
3 => "Ferien", 3 => "Ferien",
4 => "Aus" ); 4 => "Aus" );
my %heatingState = ( 0 => "Abgesenkt",
1 => "Normal",
3 => "Aus");
my %wpType = ( 0 => "ERC", 1 => "SW1", my %wpType = ( 0 => "ERC", 1 => "SW1",
2 => "SW2", 3 => "WW1", 2 => "SW2", 3 => "WW1",
4 => "WW2", 5 => "L1I", 4 => "WW2", 5 => "L1I",
6 => "L2I", 7 => "L1A", 6 => "L2I", 7 => "L1A",
8 => "L2A", 9 => "KSW", 8 => "L2A", 9 => "KSW",
10 => "KLW", 11 => "SWC", 10 => "KLW", 11 => "SWC",
12 => "LWC", 13 => "L2G", 12 => "LWC", 13 => "L2G",
14 => "WZS", 15 => "L1I407", 14 => "WZS", 15 => "L1I407",
16 => "L2I407", 17 => "L1A407", 16 => "L2I407", 17 => "L1A407",
18 => "L2A407", 19 => "L2G407", 18 => "L2A407", 19 => "L2G407",
20 => "LWC407", 21 => "L1AREV", 20 => "LWC407", 21 => "L1AREV",
22 => "L2AREV", 23 => "WWC1", 22 => "L2AREV", 23 => "WWC1",
24 => "WWC2", 25 => "L2G404", 24 => "WWC2", 25 => "L2G404",
26 => "ERC" ); 26 => "WZW", 27 => "L1S",
28 => "L1H", 29 => "L2H",
30 => "WZWD", 31 => "ERC",
40 => "WWB_20", 41 => "LD5",
42 => "LD7", 43 => "SW 37_45",
44 => "SW 58_69", 45 => "SW 29_56",
46 => "LD5 (230V)", 47 => "LD7 (230 V)",
48 => "LD9", 49 => "LD5 REV",
50 => "LD7 REV", 51 => "LD5 REV 230V",
52 => "LD7 REV 230V", 53 => "LD9 REV 230V",
54 => "SW 291", 55 => "LW SEC" );
my $counterRetry = $hash->{fhem}{counterRetry}; my $counterRetry = $hash->{fhem}{counterRetry};
$counterRetry++; $counterRetry++;
@@ -582,84 +679,130 @@ LUXTRONIK2_UpdateDone($)
} }
elsif ($a[1]==1 ) { elsif ($a[1]==1 ) {
$counterRetry = 0; $counterRetry = 0;
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
#Operating status of heat pump # Temporary storage of values because needed several times
my $currentOperatingState1 = $wpOpStat1{$a[2]}; ############## my $ambientTemperature = LUXTRONIK2_CalcTemp($a[12]);
$currentOperatingState1 = "unbekannt (".$a[2].")" unless $currentOperatingState1; my $averageAmbientTemperature = LUXTRONIK2_CalcTemp($a[13]);
readingsBulkUpdate($hash,"currentOperatingState1",$currentOperatingState1); my $hotWaterTemperature = LUXTRONIK2_CalcTemp($a[14]);
my $thresholdHeatingLimit = LUXTRONIK2_CalcTemp($a[21]);
my $thresholdTemperatureSetBack = LUXTRONIK2_CalcTemp($a[48]);
my $flowTemperature = LUXTRONIK2_CalcTemp($a[15]);
my $returnTemperature = LUXTRONIK2_CalcTemp($a[16]);
my $currentOperatingState2 = "unknown ($a[40])"; ############## # if selected, do all the statistic calculations
if ( AttrVal($name,"doStatistics",0) == 1) {
$value = LUXTRONIK2_doStatisticBoiler ($hash, $a[22], $a[37]/10, $hotWaterTemperature);
if ($value ne "") {
readingsBulkUpdate($hash,"statGradientBoilerTempLoss",$value);
Log3 $name,3,"$name: statGradientBoilerTempLoss set to $value"
}
}
#Operating status of heat pump
my $opStateHeatPump1 = $wpOpStat1{$a[2]}; ##############
$opStateHeatPump1 = "unbekannt (".$a[2].")" unless $opStateHeatPump1;
readingsBulkUpdate($hash,"opStateHeatPump1",$opStateHeatPump1);
my $opStateHeatPump2 = "unknown ($a[40])"; ##############
my $prefix = ""; my $prefix = "";
if ($a[40] == 0 || $a[40] == 2) { $prefix = "seit ";} if ($a[40] == 0 || $a[40] == 2) { $prefix = "seit ";}
elsif ($a[40] == 1) { $prefix = "in ";} elsif ($a[40] == 1) { $prefix = "in ";}
if ($a[40] == 2) { #Sonderbehandlung bei WP-Fehlern if ($a[40] == 2) { #Sonderbehandlung bei WP-Fehlern
$currentOperatingState2 = $prefix . strftime "%d.%m.%Y %H:%M:%S", localtime($a[42]); $opStateHeatPump2 = $prefix . strftime "%d.%m.%Y %H:%M:%S", localtime($a[42]);
} else { } else {
$currentOperatingState2 = $prefix . LUXTRONIK2_FormatDuration($a[41]); $opStateHeatPump2 = $prefix . LUXTRONIK2_FormatDuration($a[41]);
} }
readingsBulkUpdate($hash,"currentOperatingState2",$currentOperatingState2); readingsBulkUpdate($hash,"opStateHeatPump2",$opStateHeatPump2);
my $currentOperatingState3 = $wpOpStat2{$a[3]}; ############## my $opStateHeatPump3 = $wpOpStat2{$a[3]}; ##############
# refine text of third state # refine text of third state
if ($a[3]==6) { if ($a[3]==6) {
$currentOperatingState3 = "Stufe ".$a[4]." ".LUXTRONIK2_CalcTemp($a[5])." &deg;C "; $opStateHeatPump3 = "Stufe ".$a[4]." ".LUXTRONIK2_CalcTemp($a[5])." C ";
} }
elsif ($a[3]==7) { elsif ($a[3]==7) {
if ($a[6]==1) {$currentOperatingState3 = "Abtauen (Kreisumkehr)";} if ($a[6]==1) {$opStateHeatPump3 = "Abtauen (Kreisumkehr)";}
else {$currentOperatingState3 = "Luftabtauen";} else {$opStateHeatPump3 = "Luftabtauen";}
} }
$currentOperatingState3 = "unbekannt (".$a[3].")" unless $currentOperatingState3; $opStateHeatPump3 = "unbekannt (".$a[3].")" unless $opStateHeatPump3;
readingsBulkUpdate($hash,"currentOperatingState3",$currentOperatingState3); readingsBulkUpdate($hash,"opStateHeatPump3",$opStateHeatPump3);
# Hot water operating mode # Hot water operating mode
$value = $wpMode{$a[7]}; $value = $wpMode{$a[7]};
$value = "unbekannt (".$a[7].")" unless $value; $value = "unbekannt (".$a[7].")" unless $value;
readingsBulkUpdate($hash,"hotWaterOperatingMode",$value); readingsBulkUpdate($hash,"opModeHotWater",$value);
# hotWaterStatus # opStateHotWater
if ($a[8]==0) {$value="Sperrzeit";} if ($a[8]==0) {$value="Sperrzeit";}
elsif ($a[8]==1 && $a[9]==1) {$value="Aufheizen";} elsif ($a[8]==1 && $a[9]==1) {$value="Aufheizen";}
elsif ($a[8]==1 && $a[9]==0) {$value="Temp.OK";} elsif ($a[8]==1 && $a[9]==0) {$value="Temp. OK";}
elsif ($a[8]==3) {$value="Aus";} elsif ($a[8]==3) {$value="Aus";}
else {$value = "unbekannt (".$a[8]."/".$a[9].")";} else {$value = "unbekannt (".$a[8]."/".$a[9].")";}
readingsBulkUpdate($hash,"hotWaterStatus",$value); readingsBulkUpdate($hash,"opStateHotWater",$value);
# Heating operating mode including summer mode and average ambient temperature # Heating operating mode
readingsBulkUpdate($hash,"heatingSummerMode",$a[11]?"on":"off");
my $thresholdTemperatureSummerMode=LUXTRONIK2_CalcTemp($a[21]);
readingsBulkUpdate($hash,"thresholdTemperatureSummerMode",$thresholdTemperatureSummerMode);
my $averageAmbientTemperature=LUXTRONIK2_CalcTemp($a[13]);
readingsBulkUpdate($hash,"averageAmbientTemperature",$averageAmbientTemperature);
# Heating operating mode
$value = $wpMode{$a[10]}; $value = $wpMode{$a[10]};
# Consider also summer mode $value = "unbekannt (".$a[10].")" unless $value;
readingsBulkUpdate($hash,"opModeHeating",$value);
# Heating operating state
# Consider also heating limit
if ($a[10] == 0 if ($a[10] == 0
&& $a[11] == 1 && $a[11] == 1
&& $averageAmbientTemperature >= $thresholdTemperatureSummerMode) && $averageAmbientTemperature >= $thresholdHeatingLimit) {
{$value = "Automatik - Sommerbetrieb (Aus)";} $value = "Heizungsgrenze (Aus)";
$value = "unbekannt (".$a[10].")" unless $value; } else {
readingsBulkUpdate($hash,"heatingOperatingMode",$value); $value = $heatingState{$a[46]};
$value = "unbekannt (".$a[46].")" unless $value;
# Consider heating reduction limit
if ($a[46] == 0) {
if ($thresholdTemperatureSetBack <= $ambientTemperature) {
$value .= " ".LUXTRONIK2_CalcTemp($a[47])." C";
} else {
$value = "Normal da < $thresholdTemperatureSetBack C";
}
}
}
readingsBulkUpdate($hash,"opStateHeating",$value);
# Device and reading times, delays and durations
$value = strftime "%Y-%m-%d %H:%M:%S", localtime($a[22]);
readingsBulkUpdate($hash, "deviceTimeCalc", $value);
my $delayDeviceTimeCalc=floor($a[29]-$a[22]+0.5);
readingsBulkUpdate($hash, "delayDeviceTimeCalc", $delayDeviceTimeCalc);
my $durationFetchReadings = floor(($a[30]-$a[29]+0.005)*100)/100;
readingsBulkUpdate($hash, "durationFetchReadings", $durationFetchReadings);
#Remember min and max reading durations, will be reset when initializing the device
if ($hash->{fhem}{durationFetchReadingsMin} == 0 || $hash->{fhem}{durationFetchReadingsMin} > $durationFetchReadings) {
$hash->{fhem}{durationFetchReadingsMin} = $durationFetchReadings;
}
if ($hash->{fhem}{durationFetchReadingsMax} < $durationFetchReadings) {
$hash->{fhem}{durationFetchReadingsMax} = $durationFetchReadings;
}
# Temperatures and flow rate
readingsBulkUpdate( $hash, "ambientTemperature", $ambientTemperature);
readingsBulkUpdate( $hash, "averageAmbientTemperature", $averageAmbientTemperature);
readingsBulkUpdate( $hash, "heatingLimit",$a[11]?"on":"off");
readingsBulkUpdate( $hash, "thresholdHeatingLimit", $thresholdHeatingLimit);
readingsBulkUpdate( $hash, "thresholdTemperatureSetBack", $thresholdTemperatureSetBack);
readingsBulkUpdate( $hash, "hotWaterTemperature", $hotWaterTemperature);
readingsBulkUpdate( $hash, "hotWaterTemperatureTarget",LUXTRONIK2_CalcTemp($a[25]));
readingsBulkUpdate( $hash, "flowTemperature", $flowTemperature);
readingsBulkUpdate( $hash, "returnTemperature", $returnTemperature);
readingsBulkUpdate( $hash, "returnTemperatureTarget",LUXTRONIK2_CalcTemp($a[17]));
readingsBulkUpdate( $hash, "returnTemperatureExtern",LUXTRONIK2_CalcTemp($a[18]));
readingsBulkUpdate( $hash, "flowRate",$a[19]);
readingsBulkUpdate( $hash, "heatSourceIN",LUXTRONIK2_CalcTemp($a[23]));
readingsBulkUpdate( $hash, "heatSourceOUT",LUXTRONIK2_CalcTemp($a[24]));
readingsBulkUpdate( $hash, "hotGasTemperature",LUXTRONIK2_CalcTemp($a[26]));
# Remaining temperatures and flow rate
readingsBulkUpdate($hash,"ambientTemperature",LUXTRONIK2_CalcTemp($a[12]));
my $hotWaterTemperature = LUXTRONIK2_CalcTemp($a[14]);
readingsBulkUpdate($hash,"hotWaterTemperature",$hotWaterTemperature);
readingsBulkUpdate($hash,"hotWaterTemperatureTarget",LUXTRONIK2_CalcTemp($a[25]));
readingsBulkUpdate($hash,"flowTemperature",LUXTRONIK2_CalcTemp($a[15]));
readingsBulkUpdate($hash,"returnTemperature",LUXTRONIK2_CalcTemp($a[16]));
readingsBulkUpdate($hash,"returnTemperatureTarget",LUXTRONIK2_CalcTemp($a[17]));
readingsBulkUpdate($hash,"returnTemperatureExtern",LUXTRONIK2_CalcTemp($a[18]));
readingsBulkUpdate($hash,"flowRate",$a[19]);
readingsBulkUpdate($hash,"heatSourceIN",LUXTRONIK2_CalcTemp($a[23]));
readingsBulkUpdate($hash,"heatSourceOUT",LUXTRONIK2_CalcTemp($a[24]));
readingsBulkUpdate($hash,"hotGasTemperature",LUXTRONIK2_CalcTemp($a[26]));
# Input / Output status # Input / Output status
readingsBulkUpdate($hash,"heatingSystemCirculationPump",$a[27]?"on":"off"); readingsBulkUpdate($hash,"heatingSystemCircPump",$a[27]?"on":"off");
readingsBulkUpdate($hash,"hotWaterCirculationPumpExtern",$a[28]?"on":"off"); readingsBulkUpdate($hash,"hotWaterCircPumpExtern",$a[28]?"on":"off");
readingsBulkUpdate($hash,"hotWaterSwitchingValve",$a[9]?"on":"off"); readingsBulkUpdate($hash,"hotWaterSwitchingValve",$a[9]?"on":"off");
# bivalentLevel # bivalentLevel
readingsBulkUpdate($hash,"bivalentLevel",$a[43]); readingsBulkUpdate($hash,"bivalentLevel",$a[43]);
# Firmware # Firmware
@@ -677,45 +820,38 @@ LUXTRONIK2_UpdateDone($)
$value = "unbekannt (".$a[31].")" unless $value; $value = "unbekannt (".$a[31].")" unless $value;
readingsBulkUpdate($hash,"typeHeatpump",$value); readingsBulkUpdate($hash,"typeHeatpump",$value);
# Device times during readings # Operating hours (seconds->hours) and heat quantities, write/create readings only if >0
$value = strftime "%Y-%m-%d %H:%M:%S", localtime($a[22]); if ($a[32]>0) {readingsBulkUpdate($hash,"counterHours2ndHeatSource1",floor($a[32]/360+0.5)/10);}
readingsBulkUpdate($hash, "deviceTimeStartReadings", $value); if ($a[38]>0) {readingsBulkUpdate($hash,"counterHours2ndHeatSource2",floor($a[38]/360+0.5)/10);}
my $delayDeviceTimeCalc=floor($a[29]-$a[22]+0.5); if ($a[39]>0) {readingsBulkUpdate($hash,"counterHours2ndHeatSource3",floor($a[39]/360+0.5)/10);}
readingsBulkUpdate($hash, "delayDeviceTimeCalc", $delayDeviceTimeCalc); if ($a[33]>0) {readingsBulkUpdate($hash,"counterHoursHeatPump",floor($a[33]/360+0.5)/10);}
my $durationFetchReadings = floor(($a[30]-$a[29]+0.005)*100)/100; if ($a[34]>0) {readingsBulkUpdate($hash,"counterHoursHeating",floor($a[34]/360+0.5)/10);}
readingsBulkUpdate($hash, "durationFetchReadings", $durationFetchReadings); if ($a[35]>0) {readingsBulkUpdate($hash,"counterHoursHotWater",floor($a[35]/360+0.5)/10);}
#Remember min and max reading durations, will be reset when initializing the device if ($a[36]>0) {readingsBulkUpdate($hash,"counterHeatQHeating",$a[36]/10);}
if ($hash->{fhem}{durationFetchReadingsMin} == 0 || $hash->{fhem}{durationFetchReadingsMin} > $durationFetchReadings) { if ($a[37]>0) {readingsBulkUpdate($hash,"counterHeatQHotWater",$a[37]/10);}
$hash->{fhem}{durationFetchReadingsMin} = $durationFetchReadings; if ($a[36]+$a[37]>0) {readingsBulkUpdate($hash,"counterHeatQTotal",($a[36]+$a[37])/10);}
} #WM[kW] = W<>remekapazit<69>t * (TVL-TRL) * Durchfluss [ccm/s]
if ($hash->{fhem}{durationFetchReadingsMax} < $durationFetchReadings) { $value = 4.18 * ($flowTemperature-$returnTemperature) * $a[19] / 36000;
$hash->{fhem}{durationFetchReadingsMax} = $durationFetchReadings; $value = floor( 10 * $value + 0.5) / 10;
} readingsBulkUpdate( $hash, "currentThermalOutput", $value);
#Operating hours (secondy->hours) and heat quantities, write/create readings only if >0 # HTML for floorplan
if ($a[32]>0) {readingsBulkUpdate($hash,"operatingHoursSecondHeatSource1",floor($a[32]/360+0.5)/10);} if(AttrVal($name, "statusHTML", "none") ne "none") {
if ($a[33]>0) {readingsBulkUpdate($hash,"operatingHoursHeatPump",floor($a[33]/360+0.5)/10);}
if ($a[34]>0) {readingsBulkUpdate($hash,"operatingHoursHeating",floor($a[34]/360+0.5)/10);}
if ($a[35]>0) {readingsBulkUpdate($hash,"operatingHoursHotWater",floor($a[35]/360+0.5)/10);}
if ($a[36]>0) {readingsBulkUpdate($hash,"heatQuantityHeating",$a[36]/10);}
if ($a[37]>0) {readingsBulkUpdate($hash,"heatQuantityHotWater",$a[37]/10);}
if ($a[36]+$a[37]>0) {readingsBulkUpdate($hash,"heatQuantityTotal",($a[36]+$a[37])/10);}
if ($a[38]>0) {readingsBulkUpdate($hash,"operatingHoursSecondHeatSource2",floor($a[38]/360+0.5)/10);}
if ($a[39]>0) {readingsBulkUpdate($hash,"operatingHoursSecondHeatSource3",floor($a[39]/360+0.5)/10);}
#HTML for floorplan
if(AttrVal($name, "statusHTML", "none") ne "none") {
$value = "<div class=fp_" . $a[0] . "_title>" . $a[0] . "</div>"; $value = "<div class=fp_" . $a[0] . "_title>" . $a[0] . "</div>";
$value .= "$currentOperatingState1 $currentOperatingState2<br>"; $value .= "$opStateHeatPump1<br>";
$value .= $currentOperatingState3 . "<br>"; $value .= "$opStateHeatPump2<br>";
$value .= "Brauchwasser: " . $hotWaterTemperature . "&deg;C"; $value .= "$opStateHeatPump3<br>";
$value .= "Brauchwasser: $hotWaterTemperature &deg;C";
readingsBulkUpdate($hash,"floorplanHTML",$value); readingsBulkUpdate($hash,"floorplanHTML",$value);
} }
# State update
readingsBulkUpdate($hash,"state","$currentOperatingState1 $currentOperatingState2 - $currentOperatingState3"); readingsBulkUpdate($hash,"state","$opStateHeatPump1 $opStateHeatPump2 - $opStateHeatPump3");
readingsEndUpdate($hash,1); readingsEndUpdate($hash,1);
$hash->{helper}{fetched_calc_values} = $a[44];
$hash->{helper}{fetched_parameters} = $a[45];
############################ ############################
#Auto Synchronize Device Clock #Auto Synchronize Device Clock
my $autoSynchClock = AttrVal($name, "autoSynchClock", 0); my $autoSynchClock = AttrVal($name, "autoSynchClock", 0);
@@ -756,7 +892,8 @@ LUXTRONIK2_UpdateAborted($)
my ($hash) = @_; my ($hash) = @_;
delete($hash->{helper}{RUNNING_PID}); delete($hash->{helper}{RUNNING_PID});
my $name = $hash->{NAME}; my $name = $hash->{NAME};
Log3 $hash, 1, "$name LUXTRONIK2_UpdateAborted: Timeout when connecting to host"; my $host = $hash->{HOST};
Log3 $hash, 1, "$name Error: Timeout when connecting to host $host";
} }
@@ -811,9 +948,9 @@ LUXTRONIK2_SetParameter($$$)
$setValue = int($realValue * 2) * 5; $setValue = int($realValue * 2) * 5;
$realValue = $setValue / 10; $realValue = $setValue / 10;
} }
elsif ($parameterName eq "hotWaterOperatingMode") { elsif ($parameterName eq "opModeHotWater") {
if (! exists($opMode{$realValue})) { if (! exists($opMode{$realValue})) {
return "$name Error: Wrong parameter given for hotWaterOperatingMode, use Automatik,Party,Off" return "$name Error: Wrong parameter given for opModeHotWater, use Automatik,Party,Off"
} }
$setParameter = 4; $setParameter = 4;
$setValue = $opMode{$realValue}; $setValue = $opMode{$realValue};
@@ -911,7 +1048,7 @@ LUXTRONIK2_synchronizeClock (@)
Log3 $name, 5, "$name: Run command 'date ".$newTime."'"; Log3 $name, 5, "$name: Run command 'date ".$newTime."'";
@output=$telnet->cmd('date '.$newTime); @output=$telnet->cmd('date '.$newTime);
$returnStr = "Internal clock of host $host corrected by $delay seconds. -> ".$output[0]; $returnStr = "Internal clock of host $host corrected by $delay seconds. -> ".$output[0];
readingsSingleUpdate($hash,"lastDeviceClockSynch",TimeNow,1); readingsSingleUpdate($hash,"deviceTimeLastSync",TimeNow,1);
} }
Log3 $name, 5, "$name: Close telnet connection."; Log3 $name, 5, "$name: Close telnet connection.";
@@ -926,10 +1063,10 @@ LUXTRONIK2_checkFirmware ($)
my ($myFirmware) = @_; my ($myFirmware) = @_;
#Firmware not tested #Firmware not tested
if (index("#".$myFirmware."#",$testedFirmware) == -1) { if (index($testedFirmware,"#".$myFirmware."#") == -1) {
return "fwNotTested"; return "fwNotTested";
#Firmware tested but not compatible #Firmware tested but not compatible
} elsif (index("#".$myFirmware."#",$compatibleFirmware) == -1) { } elsif (index($compatibleFirmware,"#".$myFirmware."#") == -1) {
return "fwNotCompatible"; return "fwNotCompatible";
#Firmware compatible #Firmware compatible
} else { } else {
@@ -937,6 +1074,90 @@ LUXTRONIK2_checkFirmware ($)
} }
} }
# Calculate hourly gradients of boiler based on hotWaterTemperature and counterHeatQHeating
sub ########################################
LUXTRONIK2_doStatisticBoiler ($$$$)
{
my ($hash,$time,$currHQ,$currTemp) = @_;
my $name = $hash->{NAME};
my $statModeHW = $hash->{fhem}{statModeHotWater};
my $minTemp = $hash->{fhem}{statHotWaterTempMin};
my $maxTemp = $hash->{fhem}{statHotWaterTempMax};
my $lastHQ = $hash->{fhem}{statHQHotWater};
my $value1 = 0;
my $value2 = 0;
my $value3 = 0;
# mode 0 = init hot water gradient calculation
if ($statModeHW == 0) { # -> Mode 1
Log3 $name, 4, "$name: Boiler statMode 0: Initialized";
$hash->{fhem}{statModeHotWater} = 1;
$hash->{fhem}{statStartTimeHotWater} = $time;
$hash->{fhem}{statHQHotWater} = $currHQ;
$hash->{fhem}{statHotWaterTempMax} = $currTemp;
$hash->{fhem}{statHotWaterTempMin} = $currTemp;
# mode 1 = wait till maximum of temperature is reached
} elsif ($statModeHW == 1) {
# wait until heat quantity does not change anymore
if ($lastHQ != $currHQ) {
Log3 $name, 4, "$name: Boiler statMode 1: Heat Quantity changed ($lastHQ -> $currHQ)";
$hash->{fhem}{statHQHotWater} = $currHQ;
$hash->{fhem}{statHotWaterTempMax} = $currTemp;
# and temperature is not rising anymore
} elsif ($maxTemp < $currTemp) {
Log3 $name, 4, "$name: Boiler statMode 1: Temperature increased ($maxTemp < $currTemp)";
$hash->{fhem}{statHotWaterTempMax} = $currTemp;
# and temperature is starting to decrease -> Mode 2
} elsif ($maxTemp - 0.2 > $currTemp) {
$value1 = $maxTemp - $minTemp; # delta against last hot water temperature
$value2 = ( $time - $hash->{fhem}{statStartTimeHotWater} ) / 60; # devided by delta time (minutes)
$value3 = floor(100 * $value1 / $value2 + 0.5) / 100; # rounded to 1/100th
$value2 = floor($value2 + 0.5); # rounded
Log3 $name, 4, "$name: Boiler statMode 1: Measurement finished, start new measurement (maximum = $maxTemp )";
$hash->{fhem}{statModeHotWater} = 2;
$hash->{fhem}{statStartTimeHotWater} = $time;
$hash->{fhem}{statHotWaterTempMin} = $currTemp;
return "DT/min: $value3 DT: $value1 Dmin: $value2";
} else {
Log3 $name, 4, "$name: Boiler statMode 1: Wait till temperature decreases (".($maxTemp-0.2)." <= $currTemp <= ".$maxTemp.")";
}
# mode 2 = wait till heat quantity changes or minimum of temperature reached
} elsif ($statModeHW == 2) {
# wait until heat quantity changes or temperature is raising again
if ($hash->{fhem}{statHQHotWater} != $currHQ
|| $minTemp + 0.2 < $currTemp) { # wait till change of heat quantity or rising temperature -> Mode 1
Log3 $name, 4, "$name: Boiler statMode 2: Heat quantiy changed or temperature raised ($lastHQ != $currHQ or $minTemp +0.2 < $currTemp)";
$value1 = $minTemp - $maxTemp; # delta against last hot water temperature
$value2 = ( $time - $hash->{fhem}{statStartTimeHotWater} ) / 3600; # devided by delta time (hours)
$value3 = floor(100 * $value1 / $value2 + 0.5) / 100; # rounded to 1/100th
$value2 = floor(100 * $value2 + 0.5) / 100; # rounded to 1/100th
Log3 $name, 4, "$name: Boiler statMode 2: Measurement finished, start new measurment (minimum = $minTemp)";
$hash->{fhem}{statModeHotWater} = 1;
$hash->{fhem}{statStartTimeHotWater} = $time;
$hash->{fhem}{statHotWaterTempMax} = $currTemp;
$hash->{fhem}{statHQHotWater} = $currHQ;
return "DT/h: $value3 DT: $value1 Dh: $value2";
} elsif ($minTemp > $currTemp) {
Log3 $name, 4, "$name: Boiler statMode 2: Temperature decreased ($minTemp > $currTemp)";
$hash->{fhem}{statHotWaterTempMin} = $currTemp;
} else {
Log3 $name, 4, "$name: Boiler statMode 2: Monitoring temperature change ($minTemp <= $currTemp <= ".($minTemp+0.2).")";
}
}
return "";
}
1; 1;
=pod =pod
@@ -945,10 +1166,10 @@ LUXTRONIK2_checkFirmware ($)
<a name="LUXTRONIK2"></a> <a name="LUXTRONIK2"></a>
<h3>LUXTRONIK2</h3> <h3>LUXTRONIK2</h3>
<ul> <ul>
Luxtronik 2.0 is a heating controller used in Alpha Innotec and Siemens Novelan heat pumps. Luxtronik 2.0 is a heating controller used in Alpha Innotec and Siemens Novelan (WPR NET) heat pumps.
It has a built-in ethernet port, so it can be directly integrated into a local area network (LAN). It has a built-in ethernet port, so it can be directly integrated into a local area network (LAN).
<br> <br>
<i>The modul is tested with firmware v1.54C.</i> <i>The modul is reported to work with firmware: V1.54C, V1.60, V1.69.</i>
<br>&nbsp; <br>&nbsp;
<br> <br>
@@ -966,11 +1187,12 @@ LUXTRONIK2_checkFirmware ($)
<a name="LUXTRONIK2set"></a> <a name="LUXTRONIK2set"></a>
<b>Set</b><br> <b>Set</b><br>
<ul>A firmware check assures before each set operation that a heat pump with untested firmware is not damaged accidently. <ul>A firmware check assures before each set operation that a heat pump with untested firmware is not damaged accidently.
<li><b>&lt;hotWaterOperatingMode&gt;</b> &lt;Mode:Auto|Party|Off&gt;- Operating Mode of domestic hot water boiler</li> <li>opModeHotWater &lt;Mode&gt;- Operating Mode of domestic hot water boiler (Auto | Party | Off)</li>
<li><b>&lt;hotWaterTemperatureTarget&gt;</b> &lt;temperature &deg;C&gt; - Target temperature of domestic hot water boiler</li> <li>hotWaterTemperatureTarget &lt;temperature&gt; - Target temperature of domestic hot water boiler in &deg;C</li>
<li><b>&lt;INTERVAL&gt;</b> &lt;seconds&gt; - Polling interval</li> <li>INTERVAL &lt;polling interval&gt; - Polling interval in seconds</li>
<li><b>&lt;statusRequest&gt;</b> - Update device information</li> <li>statusRequest - Update device information</li>
<li><b>&lt;synchClockHeatPump&gt;</b> - Synchronizes controller clock with FHEM time. <b>This change is lost in case of controller power off!!</b></li> <li>synchClockHeatPump - Synchronizes controller clock with FHEM time.<br>
<b>!! This change is lost in case of controller power off!!</b></li>
</ul> </ul>
<br> <br>
<a name="LUXTRONIK2get"></a> <a name="LUXTRONIK2get"></a>
@@ -986,13 +1208,16 @@ LUXTRONIK2_checkFirmware ($)
<li>statusHTML<br> <li>statusHTML<br>
If set, a HTML-formatted reading named "floorplanHTML" is created. It can be used with the <a href="#FLOORPLAN">FLOORPLAN</a> module.<br> If set, a HTML-formatted reading named "floorplanHTML" is created. It can be used with the <a href="#FLOORPLAN">FLOORPLAN</a> module.<br>
Currently, if the value of this attribute is not NULL, the corresponding reading consists of the current status of the heat pump and the temperature of the water.</li> Currently, if the value of this attribute is not NULL, the corresponding reading consists of the current status of the heat pump and the temperature of the water.</li>
<li>allowSetParameter &lt; 0 | 1 &gt;<br>f <li>doStatistics &lt; 0 | 1 &gt;<br>
Still Beta - Calculates statistic values: <i>statGradientBoilerTempLoss</i>
<li>allowSetParameter &lt; 0 | 1 &gt;<br>
The <a href="#LUXTRONIK2set">parameters</a> of the heat pump controller can only be changed if this attribut is set to 1.</li> The <a href="#LUXTRONIK2set">parameters</a> of the heat pump controller can only be changed if this attribut is set to 1.</li>
<li>autoSynchClock &lt;delay&gt;<br> <li>autoSynchClock &lt;delay&gt;<br>
Corrects the clock of the heatpump automatically if certain <i>delay</i> (10 s - 600 s) against the FHEM time is reached. Does a firmware check before.<br> Corrects the clock of the heatpump automatically if a certain <i>delay</i> (10 s - 600 s) against the FHEM time is exeeded. Does a firmware check before.<br>
<i>(A 'delayDeviceTimeCalc' &lt;= 2 s is due to the internal calculation interval of the heat pump controller)</i></li> <i>(A 'delayDeviceTimeCalc' &lt;= 2 s can be caused by the internal calculation interval of the heat pump controller.)</i></li>
<li>ignoreFirmwareCheck &lt; 0 | 1 &gt;<br> <li>ignoreFirmwareCheck &lt; 0 | 1 &gt;<br>
A firmware check assures before each set operation that a heatpump controller with untested firmware is not damaged accidently. If this attribute is set to 1, the firmware check is ignored and new firmware can be tested for compatibility.</li> A firmware check assures before each set operation that a heatpump controller with untested firmware is not damaged accidently.<br>
If this attribute is set to 1, the firmware check is ignored and new firmware can be tested for compatibility.</li>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li> <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
</ul> </ul>
<br> <br>
@@ -1006,9 +1231,9 @@ LUXTRONIK2_checkFirmware ($)
<a name="LUXTRONIK2"></a> <a name="LUXTRONIK2"></a>
<h3>LUXTRONIK2</h3> <h3>LUXTRONIK2</h3>
<ul> <ul>
Die Luxtronik 2.0 ist eine Heizungssteuerung, welche in W&auml;rmepumpen von Alpha Innotec und Siemens Novelan verbaut ist. Die Luxtronik 2.0 ist eine Heizungssteuerung, welche in W&auml;rmepumpen von Alpha Innotec und Siemens Novelan (WPR NET) verbaut ist.<br>
Sie besitzt einen Ethernet Anschluss, so dass sie direkt in lokale Netzwerke (LAN) integriert werden kann.<br> Sie besitzt einen Ethernet Anschluss, so dass sie direkt in lokale Netzwerke (LAN) integriert werden kann.<br>
<i>Das Modul wurde bisher mit der Steuerungs-Firmware v1.54C getestet.</i> <i>Das Modul wurde bisher mit folgender Steuerungs-Firmware getestet: V1.54C, V1.60, V1.69.</i>
<br>&nbsp; <br>&nbsp;
<br> <br>
@@ -1028,12 +1253,12 @@ LUXTRONIK2_checkFirmware ($)
<b>Set</b><br> <b>Set</b><br>
<ul> <ul>
Durch einen Firmware-Test wird vor jeder Set-Operation sichergestellt, dass W&auml;rmepumpen mit ungetester Firmware nicht unabsichtlich besch&auml;digt werden. Durch einen Firmware-Test wird vor jeder Set-Operation sichergestellt, dass W&auml;rmepumpen mit ungetester Firmware nicht unabsichtlich besch&auml;digt werden.
<li>hotWaterOperatingMode &lt;Betriebsmodus&gt; - Betriebsmodus des Hei<EFBFBD>wasserboilers ( Auto | Party | Off )</l> <li>opModeHotWater &lt;Betriebsmodus&gt; - Betriebsmodus des Hei&szlig;wasserboilers ( Auto | Party | Off )</l>
<li>hotWaterTemperatureTarget &lt;Temperatur&gt; - Soll-Temperatur des Hei<EFBFBD>wasserboilers in &deg;C</li> <li>hotWaterTemperatureTarget &lt;Temperatur&gt; - Soll-Temperatur des Hei&szlig;wasserboilers in &deg;C</li>
<li>INTERVAL &lt;Abfrageinterval&gt; - Abfrageinterval in Sekunden</li> <li>INTERVAL &lt;Abfrageinterval&gt; - Abfrageinterval in Sekunden</li>
<li>statusRequest - Aktualisieren der Ger<EFBFBD>tewerte</li> <li>statusRequest - Aktualisieren der Ger&auml;tewerte</li>
<li>synchClockHeatPump - Abgleich der Uhr der Steuerung mit der FHEM Zeit. <br> <li>synchClockHeatPump - Abgleich der Uhr der Steuerung mit der FHEM Zeit. <br>
<b>!! Diese <EFBFBD>nderung geht verloren, sobald die Steuerung ausgeschaltet wird!!</b></li> <b>!! Diese &Auml;nderung geht verloren, sobald die Steuerung ausgeschaltet wird!!</b></li>
</ul> </ul>
<br> <br>
@@ -1050,7 +1275,9 @@ LUXTRONIK2_checkFirmware ($)
<li>statusHTML<br> <li>statusHTML<br>
wenn gesetzt, dann wird ein HTML-formatierter Wert "floorplanHTML" erzeugt, welcher vom Modul <a href="#FLOORPLAN">FLOORPLAN</a> genutzt werden kann.<br> wenn gesetzt, dann wird ein HTML-formatierter Wert "floorplanHTML" erzeugt, welcher vom Modul <a href="#FLOORPLAN">FLOORPLAN</a> genutzt werden kann.<br>
Momentan wird nur gepr&uuml;ft, ob der Wert dieses Attributes ungleich NULL ist, der entsprechende Ger&auml;tewerte besteht aus dem aktuellen W&auml;rmepumpenstatus und der Heizwassertemperatur.</li> Momentan wird nur gepr&uuml;ft, ob der Wert dieses Attributes ungleich NULL ist, der entsprechende Ger&auml;tewerte besteht aus dem aktuellen W&auml;rmepumpenstatus und der Heizwassertemperatur.</li>
<li>allowSetParameter &lt; 0 | 1 &gt;<br> <li>doStatistics &lt; 0 | 1 &gt;<br>
Noch im Versuchsstadium - Berechnet statistische Werte: <i>statGradientBoilerTempLoss</i>
<li>allowSetParameter &lt; 0 | 1 &gt;<br>
Die internen <a href="#LUXTRONIK2set">Parameter</a> der W&auml;rmepumpensteuerung k&ouml;nnen nur ge&auml;ndert werden, wenn dieses Attribut auf 1 gesetzt ist.</li> Die internen <a href="#LUXTRONIK2set">Parameter</a> der W&auml;rmepumpensteuerung k&ouml;nnen nur ge&auml;ndert werden, wenn dieses Attribut auf 1 gesetzt ist.</li>
<li>autoSynchClock &lt;Zeitunterschied&gt;<br> <li>autoSynchClock &lt;Zeitunterschied&gt;<br>
Die Uhr der W&auml;rmepumpe wird automatisch korrigiert, wenn ein gewisser <i>Zeitunterschied</i> (10 s - 600 s) gegen&uuml;ber der FHEM Zeit erreicht ist. Zuvor wird die Kompatibilit&auml;t der Firmware &uuml;berpr&uuml;ft.<br> Die Uhr der W&auml;rmepumpe wird automatisch korrigiert, wenn ein gewisser <i>Zeitunterschied</i> (10 s - 600 s) gegen&uuml;ber der FHEM Zeit erreicht ist. Zuvor wird die Kompatibilit&auml;t der Firmware &uuml;berpr&uuml;ft.<br>