From 800e1d98ef400fcf26201f65694dc004dd75d2a2 Mon Sep 17 00:00:00 2001 From: immiimmi <> Date: Fri, 20 Feb 2015 19:52:45 +0000 Subject: [PATCH] 00_THZ.pm: write mode for old firmwares enabled; THZ_Set has been rewritten strongly git-svn-id: https://svn.fhem.de/fhem/trunk@8049 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/00_THZ.pm | 133 ++++++++++++++++++++++---------------------- 1 file changed, 68 insertions(+), 65 deletions(-) diff --git a/fhem/FHEM/00_THZ.pm b/fhem/FHEM/00_THZ.pm index 11c84ab0c..7d67d54cd 100644 --- a/fhem/FHEM/00_THZ.pm +++ b/fhem/FHEM/00_THZ.pm @@ -2,7 +2,7 @@ # 00_THZ # $Id$ # by immi 02/2015 -my $thzversion = "0.133+"; +my $thzversion = "0.134"; # this code is based on the hard work of Robert; I just tried to port it # http://robert.penz.name/heat-pump-lwz/ ######################################################################################## @@ -62,8 +62,14 @@ sub function_heatSetTemp($$); my %parsinghash = ( #msgtype => parsingrule - "01pxx206" => [["p37Fanstage1AirflowInlet: ", 4, 2, "hex", 1], [" p38Fanstage2AirflowInlet: ", 6, 2, "hex", 1], [" p39Fanstage3AirflowInlet: ", 8, 2, "hex", 1], - [" p40Fanstage1AirflowOutlet: ", 10, 2, "hex", 1], [" p41Fanstage2AirflowOutlet: ", 12, 2, "hex", 1], [" p42Fanstage3AirflowOutlet: ", 14, 2, "hex", 1], + + "01pxx206" => [["p37Fanstage1AirflowInlet: ", 4, 4, "hex", 1], [" p38Fanstage2AirflowInlet: ", 8, 4, "hex", 1], [" p39Fanstage3AirflowInlet: ", 12, 4, "hex", 1], + [" p40Fanstage1AirflowOutlet: ", 16, 4, "hex", 1], [" p41Fanstage2AirflowOutlet: ", 20, 4, "hex", 1], [" p42Fanstage3AirflowOutlet: ", 24, 4, "hex", 1], + [" p43UnschedVent3: ", 28, 4, "hex", 1], [" p44UnschedVent2: ", 32, 4, "hex", 1], [" p45UnschedVent1: ", 36, 4, "hex", 1], + [" p46UnschedVent0: ", 40, 4, "hex", 1], [" p75PassiveCooling: ", 44, 4, "hex", 1] + ], + "01pxx214" => [["p37Fanstage1AirflowInlet: ", 4, 2, "hex", 1], [" p38Fanstage2AirflowInlet: ", 6, 2, "hex", 1], [" p39Fanstage3AirflowInlet: ", 8, 2, "hex", 1], + [" p40Fanstage1AirflowOutlet: ", 10, 2, "hex", 1], [" p41Fanstage2AirflowOutlet: ", 12, 2, "hex", 1], [" p42Fanstage3AirflowOutlet: ", 14, 2, "hex", 1], [" p43UnschedVent3: ", 16, 4, "hex", 1], [" p44UnschedVent2: ", 20, 4, "hex", 1], [" p45UnschedVent1: ", 24, 4, "hex", 1], [" p46UnschedVent0: ", 28, 4, "hex", 1], [" p75PassiveCooling: ", 32, 2, "hex", 1] ], @@ -333,7 +339,7 @@ my %sets439 = ( "pHolidayEndMonth" => {cmd2=>"0A011F", argMin => "1", argMax => "12", type =>"0clean", unit =>""}, "pHolidayEndYear" => {cmd2=>"0A0120", argMin => "12", argMax => "20", type =>"0clean", unit =>""}, "pHolidayEndTime" => {cmd2=>"0A05D4", argMin => "00:00", argMax => "23:59", type =>"9holy", unit =>""}, # the answer look like 0A05D4-0D0A05D40029 for year 41 which is 10:15 - # "party-time" => {cmd2=>"0A05D1", argMin => "00:00", argMax => "23:59", type =>"8party", unit =>""}, # value 1Ch 28dec is 7 ; value 1Eh 30dec is 7:30 + #"party-time" => {cmd2=>"0A05D1", argMin => "00:00", argMax => "23:59", type =>"8party", unit =>""}, # value 1Ch 28dec is 7 ; value 1Eh 30dec is 7:30 "programHC1_Mo_0" => {cmd2=>"0B1410", argMin => "00:00", argMax => "24:00", type =>"7prog", unit =>""}, #1 is monday 0 is first prog; start and end; value 1Ch 28dec is 7 ; value 1Eh 30dec is 7:30 "programHC1_Mo_1" => {cmd2=>"0B1411", argMin => "00:00", argMax => "24:00", type =>"7prog", unit =>""}, "programHC1_Mo_2" => {cmd2=>"0B1412", argMin => "00:00", argMax => "24:00", type =>"7prog", unit =>""}, @@ -504,7 +510,6 @@ my %getsonly439 = ( "sElectrDHWTotal" => {cmd2=>"0A091C", cmd3=>"0A091D", type =>"1clean", unit =>" kWh"}, "sElectrHCDay" => {cmd2=>"0A091E", cmd3=>"0A091F", type =>"1clean", unit =>" Wh"}, "sElectrHCTotal" => {cmd2=>"0A0920", cmd3=>"0A0921", type =>"1clean", unit =>" kWh"}, - #"sAllE8" => {cmd2=>"E8"}, "party-time" => {cmd2=>"0A05D1", argMin => "00:00", argMax => "23:59", type =>"8party", unit =>""} # value 1Ch 28dec is 7 ; value 1Eh 30dec is 7:30 ); @@ -521,10 +526,7 @@ my %getsonly539 = ( #info from belu and godmorgon ); %getsonly539=(%getsonly539, %getsonly439); -my %getsonly206 = ( -# "outsideTemp" => {parent=>"sGlobal", unit =>" °C"}, -# "return" => {parent=>"sGlobal", unit =>" °C"}, - "pFan" => {cmd2=>"01", type =>"01pxx206", unit =>""}, +my %getsonly2xx = ( "pExpert" => {cmd2=>"02", type =>"02pxx206", unit =>""}, "pDefrostEva" => {cmd2=>"03", type =>"03pxx206", unit =>""}, "pDefrostAA" => {cmd2=>"04", type =>"04pxx206", unit =>""}, @@ -541,6 +543,7 @@ my %getsonly206 = ( "pDryHeat" => {cmd2=>"10", type =>"10pxx206", unit =>""}, "sSol" => {cmd2=>"16", type =>"16sol", unit =>""}, "p01-p12" => {cmd2=>"17", type =>"17pxx206", unit =>""}, + "sProgram" => {cmd2=>"EE", type =>"EEprg206", unit =>""}, "sDHW" => {cmd2=>"F3", type =>"F3dhw", unit =>""}, "sHC1" => {cmd2=>"F4", type =>"F4hc1", unit =>""}, "sHC2" => {cmd2=>"F5", type =>"F5hc2", unit =>""}, @@ -549,9 +552,17 @@ my %getsonly206 = ( "sLast10errors" => {cmd2=>"D1", type =>"D1last206", unit =>""}, "sGlobal" => {cmd2=>"FB", type =>"FBglob206", unit =>""}, #allFB "sTimedate" => {cmd2=>"FC", type =>"FCtime206", unit =>""}, - "sFirmware" => {cmd2=>"FD", type =>"FDfirm", unit =>""}, + ); +my %getsonly206 = ( + "pFan" => {cmd2=>"01", type =>"01pxx206", unit =>""}, + "sLast10errors" => {cmd2=>"D1", type =>"D1last206", unit =>""}, + "sFirmware" => {cmd2=>"FD", type =>"FDfirm", unit =>""}, "sFirmware-Id" => {cmd2=>"FE", type =>"FEfirmId", unit =>""}, ); +my %getsonly214 = ( + "pFan" => {cmd2=>"01", type =>"01pxx214", unit =>""}, + ); + my %sets=%sets439; my %gets=(%getsonly439, %sets); @@ -611,7 +622,7 @@ sub THZ_Initialize($) ."interval_sBoostHCTotal:0,3600,7200,28800,43200,86400 " ."interval_sFlowRate:0,3600,7200,28800,43200,86400 " ."interval_sDisplay:0,60,120,180,300 " - ."firmware:4.39,2.06,5.39 " + ."firmware:4.39,2.06,2.14,5.39 " . $readingFnAttributes; $data{FWEXT}{"/THZ_PrintcurveSVG"}{FUNC} = "THZ_PrintcurveSVG"; @@ -794,7 +805,7 @@ sub THZ_Set($@){ my $argMin = $cmdhash->{argMin}; #next line disables write back for old firmware if the attribute 206 is set. - return "set not allowed for old firmwares" if((AttrVal($hash->{NAME}, "firmware" , "4.39") eq "2.06")); + #return "set not allowed for old firmwares" if((AttrVal($hash->{NAME}, "firmware" , "4.39") eq "2.06")); # check the parameter range given ($cmdhash->{type}) { @@ -803,74 +814,63 @@ sub THZ_Set($@){ return "Argument does not match the allowed inerval Min $argMin ...... Max $argMax " if (($arg ne "n.a.") and ($arg1 ne "n.a.") and (($arg1 gt $argMax) or ($arg1 lt $argMin) or ($arg gt $argMax) or ($arg lt $argMin)) ) ; } when ("2opmode") { - $arg1=$arg; + $arg1=undef; $arg=$Rev_OpMode{$arg}; return "Unknown argument $arg1: $cmd supports " . join(" ", sort values %OpMode) if(!defined($arg)); } - default { + default {$arg1=undef; return "Argument does not match the allowed inerval Min $argMin ...... Max $argMax " if(($arg > $argMax) or ($arg < $argMin)); } } - + my $i=0; my $parsingrule; my $parent = $cmdhash->{parent}; #if I have a father read from it if(defined($parent) ) { my $parenthash=$gets{$parent}; - #read before write the register $cmdHex2 = $parenthash->{cmd2}; #overwrite $cmdHex2 with the parent - $cmdHex2=THZ_encodecommand($cmdHex2, "get"); + $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'"; return ($msg ."\n msg " . $err); } substr($msg, 0, 2, ""); #remove the checksum from the head of the payload - Log3 $hash->{NAME}, 3, "answer from THZ: $msg"; + Log3 $hash->{NAME}, 5, "read before write from THZ: $msg"; #-- - my $parsingrule = $parsinghash{$parenthash->{type}}; - my $i=0; + $parsingrule = $parsinghash{$parenthash->{type}}; for (@$parsingrule) { last if ((@$parsingrule[$i]->[0]) =~ m/$cmd/); $i++; } - my $pos = @$parsingrule[$i]->[1] ; - my $len = @$parsingrule[$i]->[2]; - my $pasringtype = @$parsingrule[$i]->[3]; - my $dec = @$parsingrule[$i]->[4]; - Log3 $hash->{NAME}, 3, "write register/pos/len/dec/arg to THZ: $cmdHex2 / $pos / $len / $dec / $arg"; } else { - #my $parsingrule = $parsinghash{$cmdhash->{type}} if(defined($msgtype)); - #my $pos = @$parsingrule[0]->[1] ; - #my $len = @$parsingrule[0]->[2]; - #my $pasringtype = @$parsingrule[0]->[3]; - #my $dec = @$parsingrule[0]->[4]; - #$msg = $cmdHex2 . "0000"; + $msg = $cmdHex2 . "0000"; + my $msgtype =$cmdhash->{type}; + $parsingrule = $parsinghash{$msgtype} if(defined($msgtype)); } - - - - # encode value depending on type - given ($cmdhash->{type}) { - when ("9holy") {$arg= time2quaters($arg)} - when ("8party") {$arg= time2quaters($arg1) *256 + time2quaters($arg)} #non funziona - when ("7prog") {$arg= time2quaters($arg) *256 + time2quaters($arg1)} - when ("6gradient") {$arg=$arg*100} - when ("5temp") {$arg=$arg*10} - when ("4temp") {$arg=$arg*10*256} - when (["2opmode", "0clean"]) {$arg=$arg*256} #doubble shift ;;; conversion done above for opmode - when ("1clean") { } - default { } - } - Log3 $hash->{NAME}, 5, "THZ_Set: '$cmd $arg' ... Check if port is open. State = '($hash->{STATE})'"; - $cmdHex2=THZ_encodecommand(($cmdHex2 . substr((sprintf("%04X", $arg)), -4)),"set"); #04X converts to hex and fills up 0s; for negative, it must be trunckated. - - #per vecchi firmware leggi 17, sovrascrivi parte del messaggio, encode; non so se lo implemento - + my $pos = @$parsingrule[$i]->[1] -2; #I removed the checksum + my $len = @$parsingrule[$i]->[2]; + 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 = 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); + $pos = @$parsingrule[($i+1)]->[1] -2; + substr($msg, $pos, $len, $arg1); + } + Log3 $hash->{NAME}, 5, "THZ_Set: '$cmd $arg $msg' ... Check if port is open. State = '($hash->{STATE})'"; + $cmdHex2=THZ_encodecommand($msg,"set"); ($err, $msg) = THZ_Get_Comunication($hash, $cmdHex2); #$err=undef; if (defined($err)) { return ($cmdHex2 . "-". $msg ."--" . $err);} else { + select(undef, undef, undef, 0.05); $msg=THZ_Get($hash, $name, $cmd); #take care of program of the week given ($a[1]) { @@ -939,7 +939,7 @@ sub THZ_Get($@){ my $parent = $cmdhash->{parent}; #if I have a father read from it if(defined($parent) ) { my ($seconds, $microseconds) = gettimeofday(); - my $seconds= abs($seconds - time_str2num(ReadingsTimestamp($name, $parent, "1970-01-01 01:00:00"))); + $seconds= abs($seconds - time_str2num(ReadingsTimestamp($name, $parent, "1970-01-01 01:00:00"))); my $risultato=ReadingsVal($name, $parent, 0); $risultato=THZ_Get($hash, $name, $parent) if ($seconds > 29 ); #update of the parent: if under 29sec use the current value my $parenthash=$gets{$parent}; my $parsingrule = $parsinghash{$parenthash->{type}}; @@ -1302,7 +1302,7 @@ sub THZ_Parse1($$) { my $length = length($message); Log3 $hash->{NAME}, 5, "Message length: $length"; my $parsingcmd = substr($message,2,2); - $parsingcmd = substr($message,2,6) if (($parsingcmd =~ m/(0A|0B|0C)/) and (AttrVal($hash->{NAME}, "firmware" , "4.39") ne "2.06")); + $parsingcmd = substr($message,2,6) if (($parsingcmd =~ m/(0A|0B|0C)/) and (AttrVal($hash->{NAME}, "firmware" , "4.39") ne "2.06") and (AttrVal($hash->{NAME}, "firmware" , "4.39") ne "2.14")); my $msgtype; my $parsingrule; my $parsingelement; @@ -1392,7 +1392,7 @@ sub THZ_debugread($){ my $indice= "FF"; unlink("data.txt"); #delete debuglog foreach $indice(@numbers) { - my $cmd = sprintf("%02X", $indice); + #my $cmd = sprintf("%02X", $indice); #my $cmd = sprintf("%04X", $indice); #my $cmd = "0A" . sprintf("%04X", $indice); my $cmd = $indice; @@ -1446,16 +1446,23 @@ sub THZ_Attr(@) { if ($attrVal eq "2.06") { THZ_RemoveInternalTimer("THZ_GetRefresh"); %sets = %sets206; - %gets = (%getsonly206, %sets); + %gets = (%getsonly2xx, %getsonly206, %sets); + THZ_Refresh_all_gets($hash); + } + elsif ($attrVal eq "2.14") { + THZ_RemoveInternalTimer("THZ_GetRefresh"); + %sets = %sets206; + %gets = (%getsonly2xx, %getsonly214, %sets); THZ_Refresh_all_gets($hash); } - if ($attrVal eq "5.39") { + elsif ($attrVal eq "5.39") { THZ_RemoveInternalTimer("THZ_GetRefresh"); %sets=%sets439; %gets=(%getsonly539, %sets); THZ_Refresh_all_gets($hash); } - if (($attrVal eq "4.39") or ($cmd eq "del") or (($attrVal ne "5.39") and ($attrVal ne "2.06")) ) { + #-- + if (($attrVal eq "4.39") or ($cmd eq "del") or (($attrVal ne "5.39") and ($attrVal ne "2.06") and ($attrVal ne "2.14"))) { THZ_RemoveInternalTimer("THZ_GetRefresh"); %sets=%sets439; %gets=(%getsonly439, %sets); @@ -1518,11 +1525,9 @@ sub THZ_RemoveInternalTimer($){ sub function_heatSetTemp($$) { my ($start, $stop) = @_; - my $insideTemp=(split ' ',ReadingsVal("Mythz","sHC1",24))[27]; - my $roomSetTemp =(split ' ',ReadingsVal("Mythz","sHC1",24))[21]; + my ($heatSetTemp, $roomSetTemp, $insideTemp) =(split ' ',ReadingsVal("Mythz","sHC1",0))[11,21,27]; $roomSetTemp ="1" if ($roomSetTemp == 0); #division by 0 is bad my $p13GradientHC1 = ReadingsVal("Mythz","p13GradientHC1",0.4); - my $heatSetTemp =(split ' ',ReadingsVal("Mythz","sHC1",17))[11]; my $p15RoomInfluenceHC1 = (split ' ',ReadingsVal("Mythz","p15RoomInfluenceHC1",0))[0]; my $outside_tempFiltered =(split ' ',ReadingsVal("Mythz","sGlobal",0))[65]; my $p14LowEndHC1 =(split ' ',ReadingsVal("Mythz","p14LowEndHC1",0))[0]; @@ -1623,16 +1628,14 @@ $ret .= '