From d7c0b66087c8a5104104bb0cae2cfaca4950536d Mon Sep 17 00:00:00 2001 From: heikoranft <> Date: Sun, 3 Jan 2016 15:55:27 +0000 Subject: [PATCH] 89_HEATRONIC.pm: new feature set heating mode, set temperature, new reading ch_code git-svn-id: https://svn.fhem.de/fhem/trunk@10350 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 2 + fhem/FHEM/89_HEATRONIC.pm | 343 +++++++++++++++++++++++++++++++++++--- 2 files changed, 321 insertions(+), 24 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index cb75c0907..7bfc02dc3 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,7 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - change: 89_HEATRONIC: new feature: set heating mode, set temperature + new reading ch_code - bugfix: FB_CALLMONITOR: empty phonebooks will be recognized correctly, phonebook processing continues, when error occurs - change: FB_CALLMONITOR: attr fritzbox-remote-phonebook-exclude allows diff --git a/fhem/FHEM/89_HEATRONIC.pm b/fhem/FHEM/89_HEATRONIC.pm index 277a46fef..5b6814257 100644 --- a/fhem/FHEM/89_HEATRONIC.pm +++ b/fhem/FHEM/89_HEATRONIC.pm @@ -38,6 +38,13 @@ # 2014-07-03 found the reason for some weird controller data: the short message # with 9 Bytes accidentally has the correct CRC with length of 17 Bytes # -> fixed problem +# 2016-01-03 implemented patch created by Norbert S. junky-zs@gmx.de +# (thanks to Norbert) +# new function 'HEATRONIC_Set' +# new intenal functions 'WriteHC_Trequested', 'WriteHC_mode' +# new: proxy server handling +# fixed negative values of sol_Tcollector +# 2016-01-03 new: ch_operationcode @@ -56,6 +63,26 @@ # sol = solar # T = temperatur +#### examples for fhem.cfg and using heater-set functionality #### +# +# define Betriebsart dummy +# attr Betriebsart eventMap auto:auto comfort:heizen eco:sparen frost:frost +# attr Betriebsart room Heiz-System +# attr Betriebsart webCmd auto:comfort:eco:frost +# define notify_Betriebsart notify Betriebsart {\ +# my $modus=Value("Betriebsart");; \ +# {fhem("set Heizung hc1_mode_requested $modus")};; \ +# } +# define Heizen_Sollniveau dummy +# attr Heizen_Sollniveau setList state:slider,10,0.5,30,1 +# attr Heizen_Sollniveau webCmd state +# attr Heizen_Sollniveau room Heiz-System +# define notify_Heizen_Sollniveau notify Heizen_Sollniveau {\ +# my $value=Value("Heizen_Sollniveau");; \ +# {fhem("set Heizung hc1_Trequested $value")};; \ +# } +#### +# package main; @@ -69,6 +96,9 @@ sub HEATRONIC_Define($$); sub HEATRONIC_Undef($$); #sub HEATRONIC_Attr(@); sub HEATRONIC_Read($); +sub HEATRONIC_Set($@); +sub HEATRONIC_WriteHC_Trequested($$); +sub HEATRONIC_WriteHC_mode($$); sub HEATRONIC_DecodeMsg_CH1($$$); sub HEATRONIC_DecodeMsg_CH2($$$); sub HEATRONIC_DecodeMsg_HC($$$); @@ -102,6 +132,21 @@ my $fh; #my $debug; my $interval_ch_time; ++#define serial device (0) or proxy-server (1) ++my $PROXY_SERVER = 0; + ++# set telegramms and values ++my %HEATRONIC_sets = ( ++ "hc1_mode_requested" => {OPT => ""}, # values are set in 'HEATRONIC_Initialize' ++ "hc1_Trequested" => {OPT => ":slider,10,0.5,30,1"}, # min 10, 0.5 celsius stepwith, max 30 celsius ++); + ++my %HEATRONIC_set_mode_requested = ( ++ "frost" => 1, ++ "eco" => 2, ++ "comfort" => 3, ++ "auto" => 4 ++); sub @@ -115,6 +160,7 @@ HEATRONIC_Initialize($) $hash->{UndefFn} = "HEATRONIC_Undef"; # $hash->{AttrFn} = "HEATRONIC_Attr"; $hash->{ReadFn} = "HEATRONIC_Read"; + $hash->{SetFn} = "HEATRONIC_Set"; $hash->{AttrList} = "do_not_notify:1,0 loglevel:0,1,2,3,4,5,6 " ."log88001800:0,1 " @@ -127,6 +173,10 @@ HEATRONIC_Initialize($) ."minDiff_ch_Tflow_measured:0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0 " ."binary_operation:OR,AND " . $readingFnAttributes; + + # set option-list + my $optionList = join(",", sort keys %HEATRONIC_set_mode_requested); + $HEATRONIC_sets{"hc1_mode_requested"}{OPT} = ":$optionList"; } # if fmt =~"m/_betriebsart$/" @@ -139,17 +189,35 @@ HEATRONIC_Define($$) my @a = split("[ \t][ \t]*", $def); if(@a != 3) { - my $msg = "wrong syntax: define HEATRONIC "; + my $msg = "wrong syntax: define HEATRONIC or define HEATRONIC "; Log3 $hash, 2, $msg; return $msg; } + #Close Device to initialize properly + if (index($a[2], ':') == -1) { + delete $hash->{USBDev} if($hash->{USBDev}); + delete $hash->{FD}; + } + else { + ###proxy-server IP-adr and port found + $PROXY_SERVER = 1; + } DevIo_CloseDev($hash); + my $name=$a[0]; my $dev =$a[2]; + ###START###### Writing values to global hash ###############################################################START#### + $hash->{STATE} = "defined"; + $hash->{DeviceName} = $dev; - my $ret = DevIo_OpenDev($hash,0,0); + + $hash->{status}{FlagWritingSequence} = 0; + ####END####### Writing values to global hash ################################################################END##### + + my $ret = DevIo_OpenDev($hash,0,"HEATRONIC_DoInit"); + # my $ret = DevIo_OpenDev($hash,0,0); $fh = IO::File->new("/opt/fhem/log/junkers.log",">"); return $ret; @@ -175,6 +243,15 @@ sub HEATRONIC_DoInit($) { my ($hash) = @_; + my $name = $hash->{NAME}; + if ($PROXY_SERVER == 1) + { + my $init = unpack('C/a', "\02RX"); + #Send 'RX'-client registration to proxy + DevIo_SimpleWrite($hash, $init, 0); + } + $defs{$name}{STATE} = "Initialized"; + return undef; } @@ -462,6 +539,152 @@ HEATRONIC_Read($) +sub +HEATRONIC_Set($@) +{ + my ($hash, @a) = @_; + my $name = $hash->{NAME}; + my $log_str=""; + my $call_rtn=0; + + return "\"set $name\" needs at least an argument" if(@a < 2); + + if(!defined($HEATRONIC_sets{$a[1]})) { + my $msg = ""; + foreach my $para (sort keys %HEATRONIC_sets) { + $msg .= " $para" . $HEATRONIC_sets{$para}{OPT}; + } + return "Unknown argument $a[1], choose one of" . $msg; + } + + my ($val, $numeric_val); + + # check available 'value' as parameter at first + return "\"set $name $a[1]\" needs at least one parameter" if(@a < 2); + + $val = $a[2]; + $numeric_val = ($val =~ m/^[.0-9]+$/); + + if($a[1] =~ m/^hc.*Trequested$/) { + $log_str = "Argument must be numeric (between 10 and 30)"; + + # do error-handling if any + Log3 ($name, 1, $log_str) if(!$numeric_val || $val < 10 || $val > 30); + return $log_str if(!$numeric_val || $val < 10 || $val > 30); + + # execute command + $val *= 2; + $call_rtn = HEATRONIC_WriteHC_Trequested($hash, $val); + if ($call_rtn == 0) { + # repeat one time if failed + $call_rtn = HEATRONIC_WriteHC_Trequested($hash, $val); + } + # log command + $log_str = "HEATRONIC_WriteHC_Trequested".$a[2]." using value:".$val." success:".$call_rtn; + Log3 ($name, 5, $log_str); + } + elsif($a[1] =~ m/_mode_requested/) { + $val = $HEATRONIC_set_mode{$val}; + $log_str = "Unknown parameter for $a[1], use one of ".join(" ", sort keys %HEATRONIC_set_mode_requested); + + # do error-handling if any + Log3 ($name, 1, $log_str) if(!defined($val)); + return $log_str if(!defined($val)); + + # execute command + $call_rtn = HEATRONIC_WriteHC_mode($hash, $val); + if ($call_rtn == 0) { + # repeat one time if failed + $call_rtn = HEATRONIC_WriteHC_mode($hash, $val); + } + + # log command + $log_str = "HEATRONIC_WriteHC_mode:".$a[2]." using value:".$val." success:".$call_rtn; + Log3 ($name, 5, $log_str); + } + else { + Log3 $name, 3, "HEATRONIC_Set error: Cannot handle parameter"; + return "HEATRONIC_Set error: Cannot handle parameter"; + } +} + + + +sub +HEATRONIC_WriteHC_Trequested($$) +{ + my ($hash, $trequested) = @_; + my $name = $hash->{NAME}; + + if (!defined($hash)) { + return undef; + } + + # do not write if flag is set + if ($hash->{status}{FlagWritingSequence} == 1) { + return 0; + } + + $hash->{status}{FlagWritingSequence} = 1; + + ## send 1. netcom-bytes to 'ht_pitiny' | 'ht_piduino' (ht_transceiver) + # header= '#', ,'!' ,'S' ,0x11 + # header= 0x23,(len(data)+3),0x21,0x53,0x11 + # data = 0x10,0xff,0x11,0x00,0x65,tsoll + # block=header+data + my $block1 = "230921531110FF110065" . sprintf("%02x",$trequested); + DevIo_SimpleWrite($hash, $block1, 1); + + ## send 2. netcom-bytes to 'ht_pitiny' | 'ht_piduino' (ht_transceiver) + # header= 0x23,(len(data)+3),0x21,0x53,0x11 + # data = 0x10,0xff,0x07,0x00,0x79,tsoll + # block=header+data + my $block2 = "230921531110FF070079" . sprintf("%02x",$trequested); + DevIo_SimpleWrite($hash, $block2, 1); + + $hash->{status}{FlagWritingSequence} = 0; + return 1; +} + + + +sub +HEATRONIC_WriteHC_mode($$) +{ + my ($hash, $mode_requested) = @_; + my $name = $hash->{NAME}; + + if (!defined($hash)) { + return undef; + } + + # do not write if flag is set + if ($hash->{status}{FlagWritingSequence} == 1) { + return 0; + } + $hash->{status}{FlagWritingSequence} = 1; + + ## send 1. netcom-bytes to 'ht_pitiny' | 'ht_piduino' (ht_transceiver) + # header= '#', ,'!' ,'S' ,0x11 + # header= 0x23,(len(data)+3),0x21,0x53,0x11 + # data = 0x10,0xff,0x0e,0x00,0x65,mode_requested + # block=header+data + my $block1 = "230921531110FF0E0065" . sprintf("%02x",$mode_requested); + DevIo_SimpleWrite($hash, $block1, 1); + + ## send 2. netcom-bytes to 'ht_pitiny' | 'ht_piduino' (ht_transceiver) + # header= 0x23,(len(data)+3),0x21,0x53,0x11 + # data = 0x10,0xff,0x04,0x00,0x79,mode_requested + # block=header+data + my $block2 = "230921531110FF040079" . sprintf("%02x",$mode_requested); + DevIo_SimpleWrite($hash, $block2, 1); + + $hash->{status}{FlagWritingSequence} = 0; + return 1; +} + + + sub HEATRONIC_DecodeMsg_CH1($$$) { @@ -481,6 +704,7 @@ HEATRONIC_DecodeMsg_CH1($$$) my $ch_pump_circulation = (hex(substr($string,11*2,2)) & 0x80) ? 1 : 0; my $ch_burner_fan = (hex(substr($string,11*2,2)) & 0x01) ? 1 : 0; my $ch_mode = (hex(substr($string,9*2,2)) & 0x03); + my $ch_code = hex(substr($string,24*2,4)); my $ch_Tflow_measuredTS = ReadingsTimestamp( $name, "ch_Tflow_measured", undef ); my $interval_ch_Tflow_measured = AttrVal($name, "interval_ch_Tflow_measured", -1); @@ -516,6 +740,7 @@ HEATRONIC_DecodeMsg_CH1($$$) readingsBulkUpdate($hash, "ch_pump_cylinder", $ch_pump_cylinder); readingsBulkUpdate($hash, "ch_pump_circulation", $ch_pump_circulation); readingsBulkUpdate($hash, "ch_burner_power", $ch_burner_power); + readingsBulkUpdate($hash, "ch_code", $ch_operationcode); readingsEndUpdate($hash,1); return 1; @@ -756,14 +981,14 @@ HEATRONIC_DecodeMsg_SOL($$$) my $sol_Tcylinder_bottom = 0; if (hex(substr($string,5*2,2)) == 3) { - my $sol_Tcollector = hex(substr($string,10*2,2)); + $sol_Tcollector = hex(substr($string,10*2,2)); if ($sol_Tcollector != 255) { $sol_Tcollector = ($sol_Tcollector * 256 + hex(substr($string,11*2,2)))/10; } else { - $sol_Tcollector = hex(255-substr($string,11*2,2))/-10; + $sol_Tcollector = (255-hex(substr($string,11*2,2)))/-10; } $sol_Tcylinder_bottom = hex(substr($string,12*2,4))/10; @@ -868,19 +1093,50 @@ HEATRONIC_timeDiff($) {

HEATRONIC

    - The HEATRONIC module interprets messages received from the HT-Bus of a Junkers Boiler. Possible Adapters are described in - http://www.mikrocontroller.net/topic/317004 (only in german). + The HEATRONIC module interprets messages received from the HT-Bus of a Junkers Boiler.
    + Possible Adapters are described in http://www.mikrocontroller.net/topic/317004 (only in german).

    Define:
    -
      define <name> HEATRONIC <device>

    +
      define <name> HEATRONIC <serial-device | <proxy-server IP-address:port> - Example:
      + Example for serial-device:
        define Boiler HEATRONIC /dev/ttyUSB0@9600

      + Example for proxy-server:
      +
        + define Boiler HEATRONIC 192.168.2.11:8088 +

    + + Set: +
      + set <name> <param> <value>
      +
        (only possible with ht_pitiny- or ht_piduino-adapters)

      + where param is one of: +
        +
      • hc1_Trequired <temp>
        + sets the 'heating' temperature-niveau for heating circuit 1 (permanent)
        + 0.5 celsius resolution - temperature between 10 and 30 celsius +
      • +
      • hc1_mode [ auto | comfort | eco | frost ]
        + sets the working mode for heating circuit 1
        +
          +
        • auto : the timer program is active and the summer configuration is in effect
        • +
        • comfort: manual by 'comfort' working mode, no timer program is in effect
        • +
        • eco : manual by 'eco' working mode, no timer program is in effect
        • +
        • frost : manual by 'frost' working mode, no timer program is in effect
        • +
      • +

      + Examples: +
        + set Boiler hc1_Trequired 22.5
        + set Boiler hc1_mode eco +

      +

    + Attributes:
    • interval_ch_time, interval_ch_Tflow_measured, interval_dhw_Tmeasured, interval_dhw_Tcylinder
      @@ -908,6 +1164,9 @@ HEATRONIC_timeDiff($) {
    • ch_mode
      current operation mode (0=off, 1=heating, 2=domestic hot water)

    • +
    • ch_code
      + current operation code or extended error code (see manual of boiler) +

    • ch_burner_fan
      status of burner fan (0=off, 1=running)

    • @@ -1003,18 +1262,51 @@ HEATRONIC_timeDiff($) {

      HEATRONIC

        - Das HEATRONIC Modul wertet die Nachrichten aus, die über den HT-Bus von einer Junkers-Heizung übertragen werden. Mögliche Adapter werden unter http://www.mikrocontroller.net/topic/317004 - vorgestellt. + Das HEATRONIC Modul wertet die Nachrichten aus, die über den HT-Bus von einer Junkers-Heizung übertragen werden.
        + Mögliche Adapter werden unter http://www.mikrocontroller.net/topic/317004 vorgestellt.

        -

        Define:
        -
          define <name> HEATRONIC <device>

        +
          define <name> HEATRONIC <serial-device> | <proxy-server IP-Adresse:port>

          - Beispiel:
          + Beispiel für serielles Gerät:
            define Heizung HEATRONIC /dev/ttyUSB0@9600

          + Beispiel für Proxy-Server:
          +
            + define Heizung HEATRONIC 192.168.2.11:8088 +

        + + Set: +
          + set <name> <param> <value> +
            (nur mit ht_pitiny- oder ht_piduino-Adapter möglich)
          +
          + wobei die Parameter folgende Werte haben: +
            +
          • hc1_Trequired <temp>
            + Setzt das 'Heizen' Temperatur-Niveau für Heizkreis 1 (permanent)
            + Auflösung 0.5 Celsius, Bereich: 10 bis 30 Celsius +
          • +
          • hc1_mode [ auto | comfort | eco | frost ]
            + Setzt die Betriebsart des Heizkreises 1
            +
              +
            • auto : Das Timerprogramm und die Sommerzeit-Umschaltung sind aktiv
            • +
            • comfort: Manueller 'comfort' Mode, Timerprogramm deaktiv
            • +
            • eco : Manueller 'eco' Mode, Timerprogramm deaktiv
            • +
            • frost : Manueller 'frost' Mode, Timerprogramm deaktiv
            • +
          • +
          +
          + Beispiele: +
            + set Boiler hc1_Trequired 22.5
            + set Boiler hc1_mode eco +
          +
          +
        +
        Attributes:
          @@ -1029,13 +1321,13 @@ HEATRONIC_timeDiff($) { Readings:
          • ch_Tflow_desired
            - benötigte Vorlauf-Temperatur (im Warmwasser-Modus max. Kesseltemperatur) + benötigte Vorlauf-Temperatur (im Warmwasser-Modus max. Kesseltemperatur)

          • ch_Tflow_measured
            aktuell gemessene Vorlauf-Temperatur

          • ch_Treturn
            - aktuell gemessene Rücklauf-Temperatur + aktuell gemessene Rücklauf-Temperatur

          • ch_Tmixer
            aktuell gemessene Mischer-Temperatur @@ -1043,20 +1335,23 @@ HEATRONIC_timeDiff($) {
          • ch_mode
            aktueller Betriebsmodus (0=aus, 1=Heizen, 2=Warmwasser)

          • +
          • ch_code
            + aktueller Betriebs-Code oder erweiterter Störungs-Code (siehe Heizungs-Anleitung) +

          • ch_burner_fan
            - Status Brenner-Gebläse (0=aus, 1=läuft) + Status Brenner-Gebläse (0=aus, 1=läuft)

          • ch_burner_operation
            Brenner-Status (0=off, 1=an)

          • ch_pump_heating
            - Status der Heizungspumpe(0=aus, 1=läuft) + Status der Heizungspumpe(0=aus, 1=läuft)

          • ch_pump_cylinder
            - Status der Speicherladepumpe (0=aus, 1=läuft) + Status der Speicherladepumpe (0=aus, 1=läuft)

          • ch_pump_circulation
            - Status der Zirkulationspumpe (0=aus, 1=läuft) + Status der Zirkulationspumpe (0=aus, 1=läuft)

          • ch_burner_power
            Brennerleistung in Prozent @@ -1066,7 +1361,7 @@ HEATRONIC_timeDiff($) {

          • ch_Toutside
            - Außentemperatur + Außentemperatur

          • ch_runtime_total
            Brennerlaufzeit in Minuten (Heizen und Warmwasser) @@ -1091,7 +1386,7 @@ HEATRONIC_timeDiff($) {

          • hc1_Tdesired .. hc4_Tdesired
            - benötigte Raumtemperatur Heizkreis 1-4 + benötigte Raumtemperatur Heizkreis 1-4

          • hc1_Tmeasured .. hc4_Tmeasured
            aktuell gemessene Raumtemperatur Heizkreis 1-4 @@ -1101,7 +1396,7 @@ HEATRONIC_timeDiff($) {

          • dhw_Tdesired
            - benötigte Warmwasser-Temperatur + benötigte Warmwasser-Temperatur

          • dhw_Tmeasured
            aktuell gemessene Warmwasser-Temperatur @@ -1120,10 +1415,10 @@ HEATRONIC_timeDiff($) { Kollektorertrag der letzten Stunde

          • sol_yield_2
            - Der Wert ist noch nicht bekannt. Der Name kann sich noch ändern. + Der Wert ist noch nicht bekannt. Der Name kann sich noch ändern.

          • sol_pump
            - Status der Solarpumpe (0=off, 1=läuft) + Status der Solarpumpe (0=off, 1=läuft)

          • sol_runtime
            Laufzeit der Solarpumpe in Minuten