mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-10 03:06:37 +00:00
THZ: z_Last_fhem_err implemented, aesthetics and DevIo (Forum #110125)
git-svn-id: https://svn.fhem.de/fhem/trunk@21871 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
18f5bc0b22
commit
3f9fb855e0
@ -1,8 +1,8 @@
|
||||
##############################################
|
||||
##############################################
|
||||
# 00_THZ
|
||||
# $Id$
|
||||
# by immi 10/2019
|
||||
my $thzversion = "0.182"; #
|
||||
# by immi 05/2020
|
||||
my $thzversion = "0.184";
|
||||
# this code is based on the hard work of Robert; I just tried to port it
|
||||
# http://robert.penz.name/heat-pump-lwz/
|
||||
########################################################################################
|
||||
@ -32,6 +32,7 @@ use Time::HiRes qw(gettimeofday);
|
||||
use feature ":5.10";
|
||||
use SetExtensions;
|
||||
use Blocking;
|
||||
use DevIo;
|
||||
|
||||
sub THZ_Read($);
|
||||
sub THZ_ReadAnswer($);
|
||||
@ -424,6 +425,7 @@ my %sets439539common = (
|
||||
"p25Hyst5" => {cmd2=>"0A05C4", argMin => "0", argMax => "5", type =>"5temp", unit =>" K"},
|
||||
"p29HystAsymmetry" => {cmd2=>"0A05C5", argMin => "1", argMax => "5", type =>"1clean", unit =>""},
|
||||
"p30integralComponent" => {cmd2=>"0A0162", argMin => "10", argMax => "999", type =>"1clean", unit =>" Kmin"},
|
||||
"p31MaxBoosterStgHtg" => {cmd2=>"0A059F", argMin => "0", argMax => "3", type =>"1clean", unit =>""},
|
||||
"p32HystDHW" => {cmd2=>"0A0140", argMin => "0", argMax => "10", type =>"5temp", unit =>" K"},
|
||||
"p33BoosterTimeoutDHW" => {cmd2=>"0A0588", argMin => "0", argMax => "200", type =>"1clean", unit =>" min"}, #during DHW heating
|
||||
"p79BoosterTimeoutHC" => {cmd2=>"0A05A0", argMin => "0", argMax => "60", type =>"1clean", unit =>" min"}, #delayed enabling of booster heater
|
||||
@ -708,7 +710,7 @@ my %sets206 = (
|
||||
"progHC2Saturday" => {parent=>"pHeatProg", argMin => "0", argMax => "1", type =>"pclean", unit =>""},
|
||||
"progHC2Sunday" => {parent=>"pHeatProg", argMin => "0", argMax => "1", type =>"pclean", unit =>""},
|
||||
"progFAN1StartTime" => {parent=>"pFanProg", argMin => "00:00", argMax => "23:59", type =>"ptime", unit =>""},
|
||||
"progFAN1EndTime" => {parent=>"pFanProg", argMin => "00:00", argMax => "23:59", type =>"ütime", unit =>""},
|
||||
"progFAN1EndTime" => {parent=>"pFanProg", argMin => "00:00", argMax => "23:59", type =>"ptime", unit =>""},
|
||||
"progFAN1Enable" => {parent=>"pFanProg", argMin => "0", argMax => "1", type =>"pclean", unit =>""},
|
||||
"progFAN1Monday" => {parent=>"pFanProg", argMin => "0", argMax => "1", type =>"pclean", unit =>""},
|
||||
"progFAN1Tuesday" => {parent=>"pFanProg", argMin => "0", argMax => "1", type =>"pclean", unit =>""},
|
||||
@ -860,7 +862,6 @@ my $internalHash;
|
||||
########################################################################################
|
||||
sub THZ_Initialize($) {
|
||||
my ($hash) = @_;
|
||||
require "$attr{global}{modpath}/FHEM/DevIo.pm";
|
||||
|
||||
# Provider
|
||||
$hash->{ReadFn} = "THZ_Read";
|
||||
@ -1021,7 +1022,6 @@ sub THZ_Write($$) {
|
||||
DevIo_SimpleWrite($hash, $bstring, 1);
|
||||
}
|
||||
|
||||
|
||||
#####################################
|
||||
# sub THZ_Read($)
|
||||
# called from the global loop, when the select for hash reports data
|
||||
@ -1057,7 +1057,6 @@ Log3 $name, 3, "$name/RAW: $msg - $err - $hash->{helper}{step}";
|
||||
}
|
||||
|
||||
|
||||
|
||||
#####################################
|
||||
#
|
||||
# THZ_Resethelper()
|
||||
@ -1074,7 +1073,6 @@ sub THZ_Resethelper($) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub THZ_Testloopapproach($) {
|
||||
my ($hash) = @_;
|
||||
my $cmd="sGlobal";
|
||||
@ -1090,10 +1088,8 @@ sub THZ_testtimer($) {
|
||||
my ($hash) = @_;
|
||||
my $counter=1;
|
||||
my $stringa = ("starttest \n");
|
||||
foreach my $a (keys %intAt)
|
||||
{
|
||||
if ($intAt{$a}{FN} eq "THZ_GetRefresh")
|
||||
{
|
||||
foreach my $a (keys %intAt) {
|
||||
if ($intAt{$a}{FN} eq "THZ_GetRefresh") {
|
||||
$stringa = $stringa . ("timer ". $counter ." ARG". $intAt{$a}{ARG} ."fn " . $intAt{$a}{FN} ."\n") ;
|
||||
$counter+=1;
|
||||
}
|
||||
@ -1111,8 +1107,7 @@ sub THZ_testtimer($) {
|
||||
########################################################################################
|
||||
sub THZ_Ready($) {
|
||||
my ($hash) = @_;
|
||||
if($hash->{STATE} eq "disconnected")
|
||||
{ #RemoveInternalTimer(0, "THZ_GetRefresh"); #non necessario in THZ_getrefresh non vengono piu' rinnoovati
|
||||
if($hash->{STATE} eq "disconnected") { #RemoveInternalTimer(0, "THZ_GetRefresh"); #non necessario in THZ_getrefresh non vengono piu' rinnoovati
|
||||
#THZ_testtimer($hash);
|
||||
select(undef, undef, undef, 0.010); #equivalent to sleep 10ms
|
||||
#Log3 $hash->{NAME}, 3, "THZ_Ready: readyevent";
|
||||
@ -1124,13 +1119,8 @@ sub THZ_Ready($) {
|
||||
my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags) = $po->status;
|
||||
return ($InBytes>0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################
|
||||
#
|
||||
# THZ_Set - provides a method for setting the heatpump
|
||||
@ -1159,31 +1149,10 @@ sub THZ_Set($@){
|
||||
#if (($value->{argMax} - $value->{argMin})<2 ) {$setList .= ":uzsuToggle," . join (",", ($value->{argMin} .. $value->{argMax})) . " ";}
|
||||
if (($value->{argMax} - $value->{argMin})<5 ) {$setList .= ":uzsuSelectRadio," . join (",", ($value->{argMin} .. $value->{argMax})) . " ";}
|
||||
else {$setList .= ":textField ";}
|
||||
#else {$setList .= ":slider,$value->{argMin},1,$value->{argMax} ";}
|
||||
#else {$setList .= ":knob,min:$value->{argMin},max:$value->{argMax},step:1 " ;}
|
||||
}
|
||||
elsif ($value->{type} eq "2opmode"){
|
||||
$setList .= ":" . join (",", (sort {lc $a cmp lc $b} values %OpMode)) . " ";
|
||||
#$setList .= ":uzsuSelectRadio," . join (",", (sort {lc $a cmp lc $b} values %OpMode)) . " ";
|
||||
#attr Mythz widgetOverride pOpMode:uzsuDropDown,automatic,standby
|
||||
}
|
||||
#elsif ($value->{type} eq "9holy"){
|
||||
#$setList .= ":time ";
|
||||
# $setList .= ":textField ";
|
||||
# }
|
||||
#elsif ($value->{type} eq "5temp") {
|
||||
# $setList .= ":slider,$value->{argMin},0.1,$value->{argMax},1 " ;
|
||||
#$setList .= ":knob,min:$value->{argMin},max:$value->{argMax},step:0.1 " ;
|
||||
#$setList .= ":knob,min:$value->{argMin},max:$value->{argMax},step:0.1,angleOffset:-125,angleArc:250 "
|
||||
#attr Mythz widgetOverride p01RoomTempDayHC1:knob,min:22,max:26,step:0.1,angleOffset:-125,angleArc:250
|
||||
#attr Mythz widgetOverride p01RoomTempDayHC1:slider,$value->{argMin},0.1,$value->{argMax}
|
||||
#attr Mythz widgetOverride p01RoomTempDayHC1:uzsuDropDown,21,29
|
||||
#attr Mythz widgetOverride p01RoomTempDayHC1:uzsuSelectRadio,44,234,21
|
||||
# }
|
||||
#elsif ($value->{type} eq "6gradient") {
|
||||
# $setList .= ":slider,$value->{argMin},0.01,$value->{argMax},1 " ;
|
||||
#$setList .= ":knob,min:$value->{argMin},max:$value->{argMax},step:0.01 " ;
|
||||
# }
|
||||
else {
|
||||
#$setList .= ":textField ";
|
||||
$setList .= " ";
|
||||
@ -1191,15 +1160,10 @@ sub THZ_Set($@){
|
||||
}
|
||||
return "Unknown argument $cmd, choose one of $setList";
|
||||
}
|
||||
|
||||
return "\"set $name $cmd\" needs at least one further argument: <value-to-be-modified>" if(!defined($arg));
|
||||
|
||||
|
||||
|
||||
my $cmdHex2 = $cmdhash->{cmd2};
|
||||
my $argMax = $cmdhash->{argMax};
|
||||
my $argMin = $cmdhash->{argMin};
|
||||
|
||||
#-- check the parameter range
|
||||
if ($cmdhash->{type} =~ /ptime/) {
|
||||
$arg1=undef;
|
||||
@ -1230,7 +1194,9 @@ sub THZ_Set($@){
|
||||
$cmdHex2=THZ_encodecommand($cmdHex2, "get"); #read before write the register
|
||||
($err, $msg) = THZ_Get_Comunication($hash, $cmdHex2);
|
||||
if (defined($err)) {
|
||||
Log3 $hash->{NAME}, 3, "THZ_Set: error reading register: '$err'";
|
||||
$err="THZ_Set: error reading register: '$err'";
|
||||
Log3 $hash->{NAME}, 3, $err;
|
||||
eadingsSingleUpdate($hash, "z_Last_fhem_err", $err, 0);
|
||||
return ($msg ."\n msg " . $err);
|
||||
}
|
||||
substr($msg, 0, 2, ""); #remove the checksum from the head of the payload
|
||||
@ -1253,7 +1219,6 @@ sub THZ_Set($@){
|
||||
my $parsingtype = @$parsingrule[$i]->[3];
|
||||
my $dec = @$parsingrule[$i]->[4];
|
||||
Log3 $hash->{NAME}, 5, "write command (parsed element/pos/len/dec/parsingtype): $i / $pos / $len / $dec / $parsingtype";
|
||||
|
||||
$arg *= $dec if ($dec != 1);
|
||||
$arg = time2quaters($arg) if ($parsingtype eq "quater");
|
||||
$arg= join('', (split(':', $arg))) if ($parsingtype eq "hex2time"); # only in firmware 2.x
|
||||
@ -1261,7 +1226,6 @@ sub THZ_Set($@){
|
||||
$arg=(hex(substr($msg, $pos, 1)) & (15-2**$1)) | (2**$1*$arg) if ($parsingtype =~ /bit(\d)/);
|
||||
$arg = substr((sprintf(("%0".$len."X"), $arg)), (-1*$len)); #04X converts to hex and fills up 0s; for negative, it must be trunckated.
|
||||
substr($msg, $pos, $len, $arg);
|
||||
|
||||
if (defined($arg1)) { #only in case of "8party" or "7prog"
|
||||
$arg1 = time2quaters($arg1);
|
||||
$arg1 = substr((sprintf(("%02X"), $arg1)), -2);
|
||||
@ -1273,17 +1237,15 @@ sub THZ_Set($@){
|
||||
($err, $msg) = THZ_Get_Comunication($hash, $cmdHex2);
|
||||
#$err=undef;
|
||||
if (defined($err)) {
|
||||
Log3 $hash->{NAME}, 3, "THZ_Set: Error msg: $err -- $cmdHex2 -> $msg";
|
||||
$err="THZ_Set: Error msg: $err -- $cmdHex2 -> $msg";
|
||||
Log3 $hash->{NAME}, 3, $err;
|
||||
readingsSingleUpdate($hash, "z_Last_fhem_err", $err, 0);
|
||||
return($cmdHex2 . "-". $msg ."--" . $err);
|
||||
}
|
||||
else {
|
||||
select(undef, undef, undef, 0.25);
|
||||
if (defined($gets{$cmd})) {
|
||||
$msg=THZ_Get($hash, $name, $cmd);
|
||||
}
|
||||
else {
|
||||
$msg=$cmd.": OK";
|
||||
}
|
||||
if (defined($gets{$cmd})) {$msg=THZ_Get($hash, $name, $cmd);}
|
||||
else {$msg=$cmd.": OK";}
|
||||
#because of F8 reset introduced by andre topic=33211 msg695420
|
||||
#take care of program of the week
|
||||
if ($a[1] =~ /Mo-So/){
|
||||
@ -1315,8 +1277,6 @@ sub THZ_Set($@){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
########################################################################################
|
||||
#
|
||||
# THZ_GetNB - NonBlocking Get parameter from heatpump
|
||||
@ -1350,7 +1310,6 @@ sub THZ_GetNB($){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
########################################################################################
|
||||
#
|
||||
# THZ_GetNBDone - Finish Function
|
||||
@ -1369,7 +1328,6 @@ sub THZ_GetNBDone($){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
########################################################################################
|
||||
#
|
||||
# THZ_GetNBAbort - Abort Function
|
||||
@ -1385,7 +1343,6 @@ sub THZ_GetNBAbort($){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
########################################################################################
|
||||
#
|
||||
# THZ_AvoidCollisions - prevents collisions between parent and child process is used at the beginning of THZ_Get and THZ_Set
|
||||
@ -1413,10 +1370,6 @@ sub THZ_AvoidCollisions($) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################
|
||||
#
|
||||
# THZ_Get - provides a method for polling the heatpump
|
||||
@ -1428,11 +1381,9 @@ sub THZ_Get($@) {
|
||||
my ($hash, @a) = @_;
|
||||
my $dev = $hash->{DeviceName};
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
return "\"get $name\" needs one parameter" if(@a != 2);
|
||||
my $cmd = $a[1];
|
||||
my ($err, $msg2) =("", " ");
|
||||
|
||||
if ($cmd eq "debug_read_raw_register_slow") {
|
||||
THZ_debugread($hash);
|
||||
return ("all raw registers read and saved");
|
||||
@ -1441,8 +1392,6 @@ sub THZ_Get($@) {
|
||||
$err=THZ_backup_readings($hash);
|
||||
return $err;
|
||||
}
|
||||
|
||||
|
||||
my $cmdhash = $gets{$cmd};
|
||||
#return "Unknown argument $cmd, choose one of " . join(" ", sort keys %gets) if(!defined($cmdhash));
|
||||
if(!defined($cmdhash)) {
|
||||
@ -1451,7 +1400,6 @@ sub THZ_Get($@) {
|
||||
$getList .= "zBackupParameters:noArg";
|
||||
return "Unknown argument $cmd, choose one of $getList";
|
||||
}
|
||||
|
||||
Log3 $hash->{NAME}, 5, "THZ_Get: Try to get '$cmd'";
|
||||
THZ_AvoidCollisions($hash);
|
||||
my $parent = $cmdhash->{parent}; #if I have a father read from it
|
||||
@ -1465,29 +1413,31 @@ sub THZ_Get($@) {
|
||||
my $i=0;
|
||||
for (@$parsingrule) {
|
||||
last if ((@$parsingrule[$i]->[0]) =~ m/$cmd/);
|
||||
$i++;}
|
||||
$i++;
|
||||
}
|
||||
$msg2=(split ' ', $risultato)[$i*2+1];
|
||||
Log3 $hash->{NAME}, 5, "THZ_split: $msg2 --- $risultato";
|
||||
}
|
||||
else {
|
||||
my $cmdHex2 = $cmdhash->{cmd2};
|
||||
if(defined($cmdHex2) ) {
|
||||
#empty
|
||||
if(defined($cmdHex2) ) {#empty
|
||||
($err, $msg2) = THZ_Get_Comunication($hash, THZ_encodecommand($cmdHex2,"get") );
|
||||
if (defined($err)) {
|
||||
Log3 $hash->{NAME}, 3, "THZ_Get: Error msg2: $err -- $cmdHex2 -> $msg2";
|
||||
$err="THZ_Get: Error msg2: $err -- $cmdHex2 -> $msg2";
|
||||
Log3 $hash->{NAME}, 3, $err;
|
||||
readingsSingleUpdate($hash, "z_Last_fhem_err", $err, 0);
|
||||
return ($msg2 ."\n msg2 " . $err);
|
||||
}
|
||||
$msg2 = THZ_Parse1($hash,$msg2);
|
||||
}
|
||||
|
||||
my $cmdHex3 = $cmdhash->{cmd3};
|
||||
if(defined($cmdHex3)) {
|
||||
my $msg3= " ";
|
||||
#empty
|
||||
my $msg3= " "; #empty
|
||||
($err, $msg3) = THZ_Get_Comunication($hash, THZ_encodecommand($cmdHex3,"get"));
|
||||
if (defined($err)) {
|
||||
Log3 $hash->{NAME}, 3, "THZ_Get: Error msg3: $err -- $cmdHex3 -> $msg3";
|
||||
$err="THZ_Get: Error msg3: $err -- $cmdHex3 -> $msg3";
|
||||
Log3 $hash->{NAME}, 3, $err;
|
||||
readingsSingleUpdate($hash, "z_Last_fhem_err", $err, 0);
|
||||
return ($msg3 ."\n msg3 " . $err);
|
||||
}
|
||||
$msg2 = THZ_Parse1($hash,$msg3) * 1000 + $msg2 ;
|
||||
@ -1495,16 +1445,11 @@ sub THZ_Get($@) {
|
||||
}
|
||||
my $unit = $cmdhash->{unit};
|
||||
$msg2 = $msg2 . $unit if(defined($unit)) ;
|
||||
|
||||
|
||||
my $activatetrigger =1;
|
||||
readingsSingleUpdate($hash, $cmd, $msg2, $activatetrigger);
|
||||
return ($msg2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################
|
||||
#
|
||||
# THZ_Get_Comunication- provides a method for comunication called from THZ_Get or THZ_Set
|
||||
@ -1517,23 +1462,17 @@ sub THZ_Get_Comunication($$) {
|
||||
my ($err, $msg) =("", " ");
|
||||
Log3 $hash->{NAME}, 5, "THZ_Get_Comunication: Check if port is open. State = '($hash->{STATE})'";
|
||||
if (!(($hash->{STATE}) eq "opened")) { return("closed connection", "");}
|
||||
|
||||
select(undef, undef, undef, 0.001);
|
||||
THZ_Write($hash, "02"); # step0 --> STX start of text
|
||||
($err, $msg) = THZ_ReadAnswer($hash);
|
||||
|
||||
#Expectedanswer0 is "10" DLE data link escape
|
||||
|
||||
if ($msg ne "10") {$err .= " THZ_Get_Com: error found at step0 $msg"; $err .=" NAK!!" if ($msg eq "15"); select(undef, undef, undef, 0.1); return($err, $msg) ;}
|
||||
else {
|
||||
THZ_Write($hash, $cmdHex); # step1 --> send request SOH start of heading -- Null -- ?? -- DLE data link escape -- EOT End of Text
|
||||
($err, $msg) = THZ_ReadAnswer($hash);
|
||||
}
|
||||
|
||||
if ((defined($err))) { $err .= " THZ_Get_Com: error found at step1 "; select(undef, undef, undef, 0.1); return($err, $msg) ;}
|
||||
|
||||
# Expectedanswer1 is "1002", DLE data link escape -- STX start of text
|
||||
|
||||
if ($msg eq "10") { ($err, $msg) = THZ_ReadAnswer($hash);}
|
||||
elsif ($msg eq "15") { $err .= " THZ_Get_Com: error found at step1 NAK!! "; select(undef, undef, undef, 0.1); return($err, $msg) ;}
|
||||
if ($msg eq "1002" || $msg eq "02") {
|
||||
@ -1541,21 +1480,11 @@ sub THZ_Get_Comunication($$) {
|
||||
($err, $msg) = THZ_ReadAnswer($hash); # Expectedanswer2 // read from the heatpump
|
||||
THZ_Write($hash, "10");
|
||||
}
|
||||
|
||||
if ((defined($err))) { $err .= " THZ_Get_Com: error found at step2"; select(undef, undef, undef, 0.1);}
|
||||
else {($err, $msg) = THZ_decode($msg);} #clean up and remove footer and header
|
||||
return($err, $msg) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################
|
||||
#
|
||||
# THZ_ReadAnswer- provides a method for simple read
|
||||
@ -1640,9 +1569,6 @@ sub quaters2time($) {
|
||||
return $time;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
####################################
|
||||
#
|
||||
# time2quarters - convert from time to quarters in hex; specific to the week programm registers
|
||||
@ -1662,8 +1588,6 @@ sub time2quaters($) {
|
||||
return ($num);
|
||||
}
|
||||
|
||||
|
||||
|
||||
####################################
|
||||
#
|
||||
# bitmap2string - convert from bitmap to concatenated string
|
||||
@ -1683,8 +1607,6 @@ sub bitmap2string($$) {
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
####################################
|
||||
#
|
||||
# THZ_replacebytes - replaces bytes in string
|
||||
@ -1708,15 +1630,17 @@ sub THZ_replacebytes($$$) {
|
||||
return ($new_stringa);
|
||||
}
|
||||
|
||||
|
||||
####################################
|
||||
#
|
||||
## usage THZ_overwritechecksum("0100XX". $cmd."1003"); not needed anymore
|
||||
#
|
||||
########################################################################################
|
||||
sub THZ_overwritechecksum($) {
|
||||
my ($stringa) = @_;
|
||||
my $checksumadded=substr($stringa,0,4) . THZ_checksum($stringa) . substr($stringa,6);
|
||||
return($checksumadded);
|
||||
}
|
||||
|
||||
|
||||
####################################
|
||||
#
|
||||
# THZ_encodecommand - creates a telegram for the heatpump with a given command
|
||||
@ -1745,10 +1669,6 @@ sub THZ_encodecommand($$) {
|
||||
return($header. $checksumadded .$footer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
####################################
|
||||
#
|
||||
# THZ_decode - decodes a telegram from the heatpump -- no parsing here
|
||||
@ -1771,12 +1691,10 @@ sub THZ_decode($) {
|
||||
$find = "2B18"; # - each sequece 2B 18 must be replaced with single byte 2B
|
||||
$replace = "2B";
|
||||
$message_orig=THZ_replacebytes($message_orig, $find, $replace);
|
||||
|
||||
#Check if answer is NAK
|
||||
if (length($message_orig) == 2 && $message_orig eq "15") {
|
||||
return("decode: NAK received from device",$message_orig);
|
||||
}
|
||||
|
||||
#check header and if ok 0100, check checksum and return the decoded msg
|
||||
my $header = substr($message_orig,0,4);
|
||||
if ($header eq "0100") {
|
||||
@ -1792,11 +1710,9 @@ sub THZ_decode($) {
|
||||
if ($header eq "0102") { return("decode: CRC error in request", $message_orig);}
|
||||
if ($header eq "0104") { return("decode: UNKNOWN Register REQUEST", $message_orig);}
|
||||
if ($header eq "0180") { return(undef, $message_orig);}
|
||||
|
||||
return("decode: new unknown answer " , $message_orig);
|
||||
}
|
||||
|
||||
|
||||
###############################
|
||||
#added by jakob do not know if needed
|
||||
#
|
||||
@ -1815,7 +1731,6 @@ local $SIG{__WARN__} = sub {
|
||||
};
|
||||
|
||||
|
||||
|
||||
#######################################
|
||||
#THZ_Parse1($) could be used in order to test an external config file; I do not know if I want it
|
||||
#e.g. {THZ_Parse1(undef,"F70B000500E6")}
|
||||
@ -1832,19 +1747,18 @@ sub THZ_Parse1($$) {
|
||||
my $parsingelement;
|
||||
# search for the type in %gets
|
||||
foreach my $cmdhash (values %gets) {
|
||||
if (defined ($cmdhash->{cmd2}) and ($cmdhash->{cmd2} eq $parsingcmd))
|
||||
{$msgtype = $cmdhash->{type} ;
|
||||
if (defined ($cmdhash->{cmd2}) and ($cmdhash->{cmd2} eq $parsingcmd)) {
|
||||
$msgtype = $cmdhash->{type} ;
|
||||
last
|
||||
}
|
||||
elsif (defined ($cmdhash->{cmd3}))
|
||||
{ if ($cmdhash->{cmd3} eq $parsingcmd)
|
||||
{$msgtype = $cmdhash->{type} ;
|
||||
elsif (defined ($cmdhash->{cmd3})){
|
||||
if ($cmdhash->{cmd3} eq $parsingcmd) {
|
||||
$msgtype = $cmdhash->{type} ;
|
||||
last
|
||||
}
|
||||
}
|
||||
}
|
||||
$parsingrule = $parsinghash{$msgtype} if(defined($msgtype));
|
||||
|
||||
my $ParsedMsg = $message;
|
||||
if(defined($parsingrule)) {
|
||||
$ParsedMsg = "";
|
||||
@ -1900,10 +1814,6 @@ sub THZ_Parse1($$) {
|
||||
return (undef, $ParsedMsg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
########################################################################################
|
||||
# only for debug
|
||||
#
|
||||
@ -1950,13 +1860,13 @@ sub THZ_debugread($){
|
||||
select(undef, undef, undef, 0.001);
|
||||
($err, $msg) = THZ_ReadAnswer($hash);
|
||||
THZ_Write($hash, "10");
|
||||
|
||||
if (defined($err)) {return ($msg ."\n" . $err);}
|
||||
else { #clean up and remove footer and header
|
||||
($err, $msg) = THZ_decode($msg);
|
||||
if (defined($err)) {
|
||||
$msg = THZ_Parse1($hash,$msg);
|
||||
$msg=$cmdHex2 ."-". $msg ."-". $err;}
|
||||
$msg=$cmdHex2 ."-". $msg ."-". $err;
|
||||
}
|
||||
my $activatetrigger =1;
|
||||
# readingsSingleUpdate($hash, $cmd, $msg, $activatetrigger);
|
||||
open (MYFILE, '>>data.txt');
|
||||
@ -1969,15 +1879,15 @@ sub THZ_debugread($){
|
||||
}
|
||||
|
||||
#######################################
|
||||
#
|
||||
#THZ_Attr($)
|
||||
#in case of change of attribute starting with interval_ refresh all
|
||||
#
|
||||
########################################################################################
|
||||
sub THZ_Attr(@) {
|
||||
my ($cmd, $name, $attrName, $attrVal) = @_;
|
||||
my $hash = $defs{$name};
|
||||
|
||||
$attrVal = "4.39" if (($cmd eq "del") and ($attrName eq "firmware"));
|
||||
|
||||
if ( $attrName eq "firmware" ) {
|
||||
if ($attrVal eq "2.06") {
|
||||
%sets = %sets206;
|
||||
@ -2005,44 +1915,30 @@ sub THZ_Attr(@) {
|
||||
THZ_Refresh_all_gets($hash);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( $attrName =~ /^interval_/ ) {
|
||||
#DevIo_CloseDev($hash);
|
||||
#sleep 1;
|
||||
#DevIo_OpenDev($hash, 1, "THZ_Refresh_all_gets");
|
||||
THZ_Refresh_all_gets($hash);
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#####################################
|
||||
sub THZ_Undef($$) {
|
||||
my ($hash, $arg) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
RemoveInternalTimer(0, "THZ_GetRefresh");
|
||||
#THZ_RemoveInternalTimer("THZ_GetRefresh");
|
||||
foreach my $d (sort keys %defs) {
|
||||
if(defined($defs{$d}) &&
|
||||
defined($defs{$d}{IODev}) &&
|
||||
$defs{$d}{IODev} == $hash)
|
||||
{
|
||||
if(defined($defs{$d}) && defined($defs{$d}{IODev}) && $defs{$d}{IODev} == $hash) {
|
||||
my $lev = ($reread_active ? 4 : 2);
|
||||
Log3 $hash->{NAME}, $lev, "deleting port for $d";
|
||||
delete $defs{$d}{IODev};
|
||||
}
|
||||
}
|
||||
|
||||
BlockingKill($hash->{helper}{RUNNING_PID}) if(defined($hash->{helper}{RUNNING_PID}));
|
||||
DevIo_CloseDev($hash);
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
##########################################
|
||||
# nearest rounds to the nearrest value multiple of the first argumen
|
||||
# nearest_ceil(10, 45); --> 50
|
||||
@ -2054,24 +1950,16 @@ sub nearest_ceil($$) {
|
||||
my $targ = abs(shift);
|
||||
my $Math1 = 0.5000000000003;
|
||||
my @res = map { $targ * POSIX::floor(($_ + $Math1 * $targ) / $targ) } @_;
|
||||
|
||||
return wantarray ? @res : $res[0];
|
||||
}
|
||||
|
||||
|
||||
sub nearest_floor($$) {
|
||||
my $targ = abs(shift);
|
||||
my $Math1 = 0.5000000000003;
|
||||
my @res = map { $targ * POSIX::ceil(($_ - $Math1 * $targ) / $targ) } @_;
|
||||
|
||||
return wantarray ? @res : $res[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
##########################################
|
||||
# THZ_RemoveInternalTimer($)
|
||||
# modified takes as an argument the function to be called, not the argument
|
||||
@ -2082,21 +1970,17 @@ sub nearest_floor($$) {
|
||||
# delete($intAt{$a}) if($intAt{$a}{FN} eq $callingfun);
|
||||
# }
|
||||
#}
|
||||
|
||||
################################
|
||||
#
|
||||
|
||||
sub function_heatSetTemp($$) {
|
||||
my ($start, $stop) = @_;
|
||||
my ($p13GradientHC1, $p14LowEndHC1, $p15RoomInfluenceHC1);
|
||||
my $pOpMode = " ";
|
||||
|
||||
my $devname; #normally Mythz but could be defined differently
|
||||
foreach (keys %defs) {
|
||||
$devname=$_;
|
||||
last if(($defs{$_}{TYPE}) =~ "THZ");
|
||||
}
|
||||
|
||||
if (AttrVal($devname, "firmware" , "4.39") =~ /^2/ ) {
|
||||
($p13GradientHC1, $p14LowEndHC1, $p15RoomInfluenceHC1) = (split ' ',ReadingsVal($devname,"pHeat1",0))[1,3,5];
|
||||
}
|
||||
@ -2113,12 +1997,10 @@ sub function_heatSetTemp($$) {
|
||||
$pOpMode ="DEMO: no data";
|
||||
$outside_tempFiltered = 0; $p14LowEndHC1 =0.5;
|
||||
}
|
||||
|
||||
my $a= 0.7 + ($roomSetTemp * (1 + $p13GradientHC1 * 0.87)) + $p14LowEndHC1 + ($p15RoomInfluenceHC1 * $p13GradientHC1 * ($roomSetTemp - $insideTemp) /10);
|
||||
my $a1= 0.7 + ($roomSetTemp * (1 + $p13GradientHC1 * 0.87)) + $p14LowEndHC1;
|
||||
my $b= -14 * $p13GradientHC1 / $roomSetTemp;
|
||||
my $c= -1 * $p13GradientHC1 /75;
|
||||
|
||||
my $Simul_heatSetTemp; my $Simul_heatSetTemp_simplified; my @ret;
|
||||
foreach ($start..$stop) {
|
||||
my $tmp =$_ * $_ * $c + $_ * $b;
|
||||
@ -2201,44 +2083,34 @@ polyline { stroke:black; fill:none; }
|
||||
<text x="751" y="155" class="ylabel" text-anchor="middle">20</text> <polyline points="751,19 751,140" class="hgrid"/>
|
||||
<g>
|
||||
END
|
||||
|
||||
$ret .= '<polyline points="44,140 49,140"/> <text x="39" y="144" class="ylabel" text-anchor="end">' . $v0min . '</text>';
|
||||
$ret .= '<polyline points="44,110 49,110"/> <text x="39" y="114" class="ylabel" text-anchor="end">' . $v1 . '</text>';
|
||||
$ret .= '<polyline points="44,80 49,80"/> <text x="39" y="84" class="ylabel" text-anchor="end">' . $v2 . '</text>';
|
||||
$ret .= '<polyline points="44,49 49,49"/> <text x="39" y="53" class="ylabel" text-anchor="end">' . $v3 . '</text>';
|
||||
$ret .= '<polyline points="44,19 49,19"/> <text x="39" y="23" class="ylabel" text-anchor="end">' . $v4 . '</text>';
|
||||
$ret .= '</g> <g>';
|
||||
$ret .= '<polyline points="751,140 756,140"/> <text x="760" y="144" class="ylabel">'. $v0min .'</text>';
|
||||
$ret .= '<polyline points="751,110 756,110"/> <text x="760" y="114" class="ylabel">'. $v1 .'</text>';
|
||||
$ret .= '<polyline points="751,80 756,80"/> <text x="760" y="84" class="ylabel">' . $v2 .'</text>';
|
||||
$ret .= '<polyline points="751,49 756,49"/> <text x="760" y="53" class="ylabel">' . $v3 .'</text>';
|
||||
$ret .= '<polyline points="751,19 756,19"/> <text x="760" y="23" class="ylabel">' . $v4 .'</text>';
|
||||
$ret .= '</g>' ."\n";
|
||||
|
||||
|
||||
$ret .= '<polyline points="44,140 49,140"/> <text x="39" y="144" class="ylabel" text-anchor="end">' . $v0min . '</text>'
|
||||
. '<polyline points="44,110 49,110"/> <text x="39" y="114" class="ylabel" text-anchor="end">' . $v1 . '</text>'
|
||||
. '<polyline points="44,80 49,80"/> <text x="39" y="84" class="ylabel" text-anchor="end">' . $v2 . '</text>'
|
||||
. '<polyline points="44,49 49,49"/> <text x="39" y="53" class="ylabel" text-anchor="end">' . $v3 . '</text>'
|
||||
. '<polyline points="44,19 49,19"/> <text x="39" y="23" class="ylabel" text-anchor="end">' . $v4 . '</text> </g> <g>'
|
||||
. '<polyline points="751,140 756,140"/> <text x="760" y="144" class="ylabel">' . $v0min . '</text>'
|
||||
. '<polyline points="751,110 756,110"/> <text x="760" y="114" class="ylabel">' . $v1 . '</text>'
|
||||
. '<polyline points="751,80 756,80"/> <text x="760" y="84" class="ylabel">' . $v2 . '</text>'
|
||||
. '<polyline points="751,49 756,49"/> <text x="760" y="53" class="ylabel">' . $v3 . '</text>'
|
||||
. '<polyline points="751,19 756,19"/> <text x="760" y="23" class="ylabel">' . $v4 . '</text></g>' ."\n";
|
||||
#labels ######################
|
||||
$ret .= '<text line_id="line_1" x="70" y="100" class="l1"> --- heat curve with insideTemp correction</text>' ;
|
||||
$ret .= '<text line_id="line_3" x="70" y="115" class="l3"> --- heat curve simplified</text>' ;
|
||||
$ret .= '<text line_id="line_0" x="70" y="130" class="l0"> --- working point: ';
|
||||
$ret .= 'outside_tempFiltered=' . $outside_tempFiltered . '°C heatSetTemp=' . $heatSetTemp . '°C </text>';
|
||||
$ret .= '<text line_id="line_3" x="650" y="50" class="title"> -'. $pOpMode . '- </text>' ." \n" ;
|
||||
|
||||
$ret .= '<text line_id="line_1" x="70" y="100" class="l1"> --- heat curve with insideTemp correction</text>'
|
||||
. '<text line_id="line_3" x="70" y="115" class="l3"> --- heat curve simplified</text>'
|
||||
. '<text line_id="line_0" x="70" y="130" class="l0"> --- working point: outside_tempFiltered='
|
||||
. $outside_tempFiltered . '°C heatSetTemp=' . $heatSetTemp . '°C </text>'
|
||||
. '<text line_id="line_3" x="650" y="50" class="title"> -'. $pOpMode . '- </text>' ." \n";
|
||||
#title ######################
|
||||
$ret .= '<text id="svg_title" x="400" y="14.4" class="title" text-anchor="middle">';
|
||||
$ret .= $titlestring .' </text>' . "\n";
|
||||
|
||||
$ret .= '<text id="svg_title" x="400" y="14.4" class="title" text-anchor="middle">'. $titlestring .' </text>' . "\n";
|
||||
#point ######################
|
||||
$ret .='<polyline id="line_0" style="stroke-width:2" class="l0" points="';
|
||||
my ($px,$py) = (sprintf("%.1f", (($outside_tempFiltered+15)*(750-49)/(15+20)+49)),sprintf("%.1f", (($heatSetTemp-$v4)*(140-19)/($v0min-$v4)+19)));
|
||||
$ret.= ($px-3) . "," . ($py) ." " . ($px) . "," . ($py-3) ." " . ($px+3) . "," . ($py) ." " . ($px) . "," . ($py+3) ." " . ($px-3) . "," . ($py) ." " . '"/>' . "\n";
|
||||
|
||||
#curve with inside temperature correction ######################
|
||||
$ret .='<polyline id="line_1" title="Heat Curve with insideTemp correction" style="stroke-width:1" class="l1" points="';
|
||||
foreach (@{$ycurvevalues}) {
|
||||
$ret.= (sprintf("%.1f", ($_->[0]+15)*(750-49)/(15+20)+49) ). "," . sprintf("%.1f", (($_->[1]-$v4)*(140-19)/($v0min-$v4)+19)) ." ";
|
||||
}
|
||||
$ret .= '"/> ' . "\n";
|
||||
|
||||
#curve without inside temperature correction ######################
|
||||
$ret .='<polyline id="line_3" title="Heat Curve simplified" style="stroke-width:1" class="l3" points="';
|
||||
foreach (@{$ycurvevalues}) {
|
||||
@ -2246,16 +2118,10 @@ $ret.= (sprintf("%.1f", ($_->[0]+15)*(750-49)/(15+20)+49) ). "," . sprintf("%.1f
|
||||
}
|
||||
$ret .= '"/> ' . "\n";
|
||||
$ret .= '</svg>';
|
||||
|
||||
my $FW_RETTYPE = "image/svg+xml";
|
||||
return ($FW_RETTYPE, $ret);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sub THZ_detailFn(@){
|
||||
my ($FW_wname, $d, $room, $pageHash) = @_; # pageHash is set for summaryFn.
|
||||
my $hash = $defs{$d}; #$d is the name of the defined device
|
||||
@ -2294,18 +2160,12 @@ sub THZ_backup_readings($){
|
||||
return "saved Readings in $backupfile";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1;
|
||||
|
||||
|
||||
=pod
|
||||
=item device
|
||||
=item summary Monitors and controls Tecalor/StiebelEltron heatpumps via RS232 or ser2net
|
||||
=item summary_DE Kommuniziert mittels RS232 oder ser2net mit einer Tecalor/SE Wärmepumpe
|
||||
=item summary_DE Kommuniziert mittels RS232 oder ser2net mit einer Tecalor/SE Wärmepumpe
|
||||
=item cloudfree
|
||||
=item openapi
|
||||
=begin html
|
||||
@ -2388,19 +2248,15 @@ sub THZ_backup_readings($){
|
||||
<a name="THZ"></a>
|
||||
<h3>THZ</h3>
|
||||
<ul>
|
||||
THZ Modul: Kommuniziert mittels einem seriellen Interface RS232/USB (z.B. /dev/ttyxx), oder mittels ser2net (z.B. 10.0.x.x:5555) mit einer Tecalor / Stiebel
|
||||
Eltron Wärmepumpe. <br>
|
||||
Getestet mit einer Tecalor THZ303/Sol (Serielle Geschwindigkeit 57600/115200@USB) und einer THZ403 (Serielle Geschwindigkeit 115200) mit identischer
|
||||
Firmware 4.39. <br>
|
||||
THZ Modul: Kommuniziert mittels einem seriellen Interface RS232/USB (z.B. /dev/ttyxx), oder mittels ser2net (z.B. 10.0.x.x:5555) mit einer Tecalor / Stiebel Eltron Wärmepumpe. <br>
|
||||
Getestet mit einer Tecalor THZ303/Sol (Serielle Geschwindigkeit 57600/115200@USB) und einer THZ403 (Serielle Geschwindigkeit 115200) mit identischer Firmware 4.39. <br>
|
||||
Getestet mit einer Stiebel LWZ404 (Serielle Geschwindigkeit 115200@USB) mit Firmware 5.39. <br>
|
||||
Getestet auf FritzBox, nas-qnap, Raspberry Pi and MacOS.<br>
|
||||
Dieses Modul funktioniert nicht mit äterer Firmware; Gleichwohl, das "parsing" könnte leicht angepasst werden da die Register gut
|
||||
beschrieben wurden.
|
||||
Dieses Modul funktioniert nicht mit älterer Firmware; Gleichwohl, das "parsing" könnte leicht angepasst werden da die Register gut beschrieben wurden.
|
||||
https://answers.launchpad.net/heatpumpmonitor/+question/100347 <br>
|
||||
Implementiert: Lesen der Statusinformation sowie Lesen und Schreiben einzelner Einstellungen.
|
||||
Genauere Beschreinung des Modules --> 00_THZ wiki http://www.fhemwiki.de/wiki/Tecalor_THZ_W%C3%A4rmepumpe
|
||||
<br><br>
|
||||
|
||||
<a name="THZdefine"></a>
|
||||
<b>Define</b>
|
||||
<ul>
|
||||
@ -2472,5 +2328,3 @@ sub THZ_backup_readings($){
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user