Integration of heat pump THZ 5.5 eco from tecalor (Stiebel Eltron) into Home Assistant

I have a Tecalor THZ heat pump running and I am testing Can Bus, while ISG pins are plugged parallel to my Can Bus wires. I adapted ‘ESP32 NodeMCU Development Board’ with attached ’ MCP2515 CAN Bus Module’. My Home Assistant is running on a Raspberry Pi 4. In the directory /config/esphome I stored the file ‘esphome-web-288ccc.yaml’ with the content below. When the log file is running in ESPHome I see all the messages running between ISG and THZ.
Up to now I am not able to trigger a sensor request. THZ is not answering to my requests. May be the reason is, that I defined my Can Bus node 0x180. I guess, THZ will only answer to requests from node ID 0x6a2, what is used by ISG. So, I have to try this option also.

Content of esphome-web-288ccc.yaml:

esphome:
  name: esphome-web-288ccc
  friendly_name: ESPHome Web 288ccc

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "yV2hpkUxilwEFPZXT8U5eD/HoyxdB3LsZJaGcwYAsZg="

ota:


wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Esphome-Web-288Ccc"
    password: "vWVSNEiAnHZA"

sensor:
  - platform: template
    id: hzg_aussentemp
    name: "HZG AUSSENTEMP"
    state_class: "measurement"
    device_class: temperature
    unit_of_measurement: "°C"
    icon: "mdi:thermometer-lines"
    update_interval: 30min

  - platform: template
    id: hzg_hk1_solltemp_tag
    name: "HZG HK1 SOLLTEMP TAG"
    state_class: "measurement"
    device_class: temperature
    unit_of_measurement: "°C"
    icon: "mdi:thermometer-lines"
    update_interval: 1min

  - platform: template
    id: hzg_ww_solltemp_tag
    name: "HZG WW SOLLTEMP TAG"
    state_class: "measurement"
    device_class: temperature
    unit_of_measurement: "°C"
    icon: "mdi:thermometer-lines"
    update_interval: 1min

  - platform: template
    id: hzg_betriebsart
    name: "HZG BETRIEBSART"
    state_class: "measurement"
    update_interval: 10min

captive_portal:
time:
  - platform: homeassistant
    id: homeassistant_time
    on_time:
      # alle 3 Minuten (180 s) am CAN Bus nach dem Sensor-Status fragen:
      - seconds: /60
        then:
          # Byte 0:   0x3: 1. Teil der CAN Bus ID der Heizung
          # Byte 1:   0x1: 1 steht für Anfrage an den CAN Bus
          # Byte 2/3: 0x00: gehört mit der 3 oben zur CAN Bus ID der Heizung
          #                 ergibt zusammen 0x180 hex(3*8 + 00)
          # Byte 4/5: 0xfa: ist immer so bei thz ???????? 
          # Byte 6-9: 0x00,0x0c: ID Außentemp, siehe elsterTabelle.inc
          # Byte 10-13: reserviert für die Antwort später (in °C *10)

          #Außentemperatur 1/10 °C et dec value - ok /10
          - canbus.send: 
              can_id: 0x680
              data: [0x31,0x00,0xfa,0x00,0x0c,0x00,0x00]
          
          - lambda: |-
              ESP_LOGD("myesp", "Timer-Anfrage von 0x680 (ESP) an 0x180: [0x31,0x00,0xfa,0x00,0x0c,0x00,0x00]");

          - delay: 200ms
  
# hier kommen die Antworten vom CAN Bus:
spi:
  id: McpSpi
  clk_pin: GPIO18
  mosi_pin: GPIO23
  miso_pin: GPIO19

canbus:
  - platform: mcp2515
    id: my_mcp2515
    spi_id: McpSpi
    cs_pin: GPIO5
    can_id: 0x680
    use_extended_id: false
    bit_rate: 20kbps
    on_frame:

      # Telegramme von CAN ID 0x6a2 (ISG) in die Sensoren einarbeiten
      - can_id: 0x6a2
        then:
          # - lambda: ist Kennung für folgenden C++ Code
          # Byte 0:   0xd: Empfänger-ID des ESP32
          # Byte 1:   0x2: 1 steht für Anfrage an den CAN Bus
          # Byte 2/3: 0x00: gehört mit 'd' oben zur CAN Bus ID des ESP32
          #                 ergibt zusammen 0x680 hex(d*8 + 0)
          # Byte 4/5: 0xfa
          # Byte 6-9: 0x00,0x0c: Sensor-ID lt. ElsterTable.inc
          # Byte 10-13: Sensorwert
          - lambda: |-
              //int wert0 =int(x[0]);
              //int wert1 =int(x[1]);
              //int wert2 =int(x[2]);
              //int wert3 =int(x[3]);
              //int wert4 =int(x[4]);
              //int wert5 =int(x[5]);
              //int wert6 =int(x[6]);
              //ESP_LOGD("myesp", "von 0x6a2 (ISG) Hex: %2.2x %2.2x %x %2.2x %2.2x %2.2x %2.2x", wert0, wert1, wert2, wert3, wert4, wert5, wert6);

              int ziel = (int(x[0] & 0xf0) << 3) + int(x[1]);
              int iart = int(x[0] & 0x0f);
              int fa_kenng =int(x[2]);
              int sensor_id = int( (x[3]<<8) + x[4] );
              float antwort = float(int( (x[5]<<8) + x[6] ));
              
              if( iart == 2 ) {

                float sensorwert;

                switch( sensor_id ){

                  default:
                    ESP_LOGD("myesp", "Antwort von 0x6a2 an 0x%x fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
                            , ziel, fa_kenng, sensor_id, antwort);
                    break;
                } // switch( sensor_id )

              } else if(iart == 0) {
                ESP_LOGD("myesp", "Schreiben von 0x6a2 an 0x%x art: %d fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
                        , ziel, iart, fa_kenng, sensor_id, antwort);
              } else {
                ESP_LOGD("myesp", "Anfrage von 0x6a2 an 0x%x art: %d fa_kenng: %2.2x sensor_id: 0x%4.4x"
                        , ziel, iart, fa_kenng, sensor_id );
              } // if( iart == 2)

      # Telegramme von CAN ID 0x180 (THZ) in die Sensoren einarbeiten
      - can_id: 0x180
        then:
          - lambda: |-  
              int ziel = (int(x[0] & 0xf0) << 3) + int(x[1]);
              int iart = int(x[0] & 0x0f);
              int fa_kenng =int(x[2]);
              int sensor_id = int( (x[3]<<8) + x[4] );
              float antwort = float(int( (x[5]<<8) + x[6] ));

              if( iart == 2 ) {
                float sensorwert;

                switch( sensor_id ) {
                  case 0x0003:
                    if( ziel == 0x680 ){
                      sensorwert = antwort / 10;
                      id(hzg_ww_solltemp_tag).publish_state(sensorwert);
                      ESP_LOGD("myesp", "hzg_ww_solltemp_tag (0x%4.4x): %f°C", sensor_id, sensorwert);
                    }
                    break;

                  case 0x000c:
                    if( ziel == 0x680 ){
                      sensorwert = antwort / 10;
                      id(hzg_aussentemp).publish_state(sensorwert);
                      ESP_LOGD("myesp", "hzg_aussentemp(0x%4.4x): %f°C", sensor_id, sensorwert);
                    }
                    break;

                  case 0x0012:
                    if( ziel == 0x680 ){
                      sensorwert = antwort;
                      id(hzg_betriebsart).publish_state(sensorwert);
                      ESP_LOGD("myesp", "hzg_betriebsart(0x%4.4x): %f°C", sensor_id, sensorwert);
                    }
                    break;

                  default:
                    if( ziel == 0x6a2 )
                      ESP_LOGD("myesp", "Antwort von 0x180 an 0x%x fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
                              , ziel, fa_kenng, sensor_id, antwort);
                    break;
                } // switch( sensor_id )

              //} else if(iart == 0) {
              //  ESP_LOGD("myesp", "Schreiben von 0x180 an 0x%x art: %d fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
              //          , ziel, iart, fa_kenng, sensor_id, antwort);
              //} else {
              //  ESP_LOGD("myesp", "Anfrage von 0x180 an 0x%x art: %d fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
              //          , ziel, iart, fa_kenng, sensor_id, antwort);
              } // if( iart == 2)

      # Telegramme von CAN ID 0x680 (ESP32)
      - can_id: 0x680
        then:
          - lambda: |-  
              int ziel = (int(x[0] & 0xf0) << 3) + int(x[1]);
              int iart = int(x[0] & 0x0f);
              int fa_kenng =int(x[2]);
              int sensor_id = int( (x[3]<<8) + x[4] );
              float antwort = float(int( (x[5]<<8) + x[6] ));

              if( iart == 2 ) {
                float sensorwert;

                switch( sensor_id ) {
                  default:
                    if( ziel == 0x6a2 )
                      ESP_LOGD("myesp", "Antwort von 0x680 (ESP) an 0x%x fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
                              , ziel, fa_kenng, sensor_id, antwort);
                    break;
                } // switch( sensor_id )

              } else if(iart == 0) {
                ESP_LOGD("myesp", "Schreiben von 0x680 (ESP) an 0x%x art: %d fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
                        , ziel, iart, fa_kenng, sensor_id, antwort);
              } else {
                ESP_LOGD("myesp", "Anfrage von 0x680 (ESP) an 0x%x art: %d fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
                        , ziel, iart, fa_kenng, sensor_id, antwort);
              } // if( iart == 2)


      - can_id: 0x6a1
        then:
          - lambda: |-  
              int ziel = (int(x[0] & 0xf0) << 3) + int(x[1]);
              int iart = int(x[0] & 0x0f);
              int fa_kenng =int(x[2]);
              int sensor_id = int( (x[3]<<8) + x[4] );
              float antwort = float(int( (x[5]<<8) + x[6] ));

              if( iart == 2 ) {
                float sensorwert;

                switch( sensor_id ){

                  default:
                    if( ziel == 0x6a2 )
                      ESP_LOGD("myesp", "Antwort von 0x6a1 an 0x%x fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
                              , ziel, fa_kenng, sensor_id, antwort);
                    break;
                } // switch( sensor_id )

              //} else {
              //  ESP_LOGD("myesp", "von 0x6a1 an 0x%x art: %d fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
              //          , ziel, iart, fa_kenng, sensor_id, antwort);
              } // if( iart == 2)

      - can_id: 0x301
        then:
          - lambda: |-  
              int ziel = (int(x[0] & 0xf0) << 3) + int(x[1]);
              int iart = int(x[0] & 0x0f);
              int fa_kenng =int(x[2]);
              int sensor_id = int( (x[3]<<8) + x[4] );
              float antwort = float(int( (x[5]<<8) + x[6] ));

              if( iart == 2 ) {
                float sensorwert;

                switch( sensor_id ){

                  case 0x0005:
                    if( ziel == 0x680 ){
                      sensorwert = antwort / 10;
                      id(hzg_hk1_solltemp_tag).publish_state(sensorwert);
                      ESP_LOGD("myesp", "hzg_hk1_solltemp_tag (0x%4.4x): %f°C", sensor_id, sensorwert);
                    }
                    break;

                  default:
                    if( ziel == 0x6a2 )
                      ESP_LOGD("myesp", "Antwort von 0x301 an 0x%x fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
                              , ziel, fa_kenng, sensor_id, antwort);
                    break;
                } // switch( sensor_id )

              //} else {
              //  ESP_LOGD("myesp", "von 0x301 an 0x%x art: %d fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
              //          , ziel, iart, fa_kenng, sensor_id, antwort);
              } // if( iart == 2)

      - can_id: 0x302
        then:
          - lambda: |-  
              int ziel = (int(x[0] & 0xf0) << 3) + int(x[1]);
              int iart = int(x[0] & 0x0f);
              int fa_kenng =int(x[2]);
              int sensor_id = int( (x[3]<<8) + x[4] );
              float antwort = float(int( (x[5]<<8) + x[6] ));

              if( iart == 2 ) {
                float sensorwert;

                switch( sensor_id ){

                  default:
                    if( ziel == 0x6a2 )
                      ESP_LOGD("myesp", "Antwort von 0x302 an 0x%x fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
                              , ziel, fa_kenng, sensor_id, antwort);
                    break;
                } // switch( sensor_id )

              //} else {
              //  ESP_LOGD("myesp", "von 0x302 an 0x%x art: %d fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
              //          , ziel, iart, fa_kenng, sensor_id, antwort);
              } // if( iart == 2)

      - can_id: 0x514
        then:
          - lambda: |-  
              int ziel = (int(x[0] & 0xf0) << 3) + int(x[1]);
              int iart = int(x[0] & 0x0f);
              int fa_kenng =int(x[2]);
              int sensor_id = int( (x[3]<<8) + x[4] );
              float antwort = float(int( (x[5]<<8) + x[6] ));

              if( iart == 2 ) {
                float sensorwert;

                switch( sensor_id ){

                  default:
                    if( ziel == 0x6a2 )
                      ESP_LOGD("myesp", "Antwort von 0x514 an 0x%x fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
                              , ziel, fa_kenng, sensor_id, antwort);
                    break;
                } // switch( sensor_id )

              //} else {
              //  ESP_LOGD("myesp", "von 0x514 an 0x%x art: %d fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
              //          , ziel, iart, fa_kenng, sensor_id, antwort);
              } // if( iart == 2)

      - can_id: 0x480
        then:
          - lambda: |-  
              int ziel = (int(x[0] & 0xf0) << 3) + int(x[1]);
              int iart = int(x[0] & 0x0f);
              int fa_kenng =int(x[2]);
              int sensor_id = int( (x[3]<<8) + x[4] );
              float antwort = float(int( (x[5]<<8) + x[6] ));

              if( iart == 2 ) {
                float sensorwert;

                switch( sensor_id ){

                  default:
                    if( ziel == 0x6a2 )
                      ESP_LOGD("myesp", "Antwort von 0x480 an 0x%x fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
                              , ziel, fa_kenng, sensor_id, antwort);
                    break;
                } // switch( sensor_id )

              //} else {
              //  ESP_LOGD("myesp", "von 0x480 an 0x%x art: %d fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
              //          , ziel, iart, fa_kenng, sensor_id, antwort);
              } // if( iart == 2)

      - can_id: 0x601
        then:
          - lambda: |-  
              int ziel = (int(x[0] & 0xf0) << 3) + int(x[1]);
              int iart = int(x[0] & 0x0f);
              int fa_kenng =int(x[2]);
              int sensor_id = int( (x[3]<<8) + x[4] );
              float antwort = float(int( (x[5]<<8) + x[6] ));

              if( iart == 2 ) {
                float sensorwert;

                switch( sensor_id ){

                  default:
                    if( ziel == 0x6a2 )
                      ESP_LOGD("myesp", "Antwort von 0x601 an 0x%x fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
                              , ziel, fa_kenng, sensor_id, antwort);
                    break;
                } // switch( sensor_id )

              //} else {
              //  ESP_LOGD("myesp", "von 0x601 an 0x%x art: %d fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
              //          , ziel, iart, fa_kenng, sensor_id, antwort);
              } // if( iart == 2)

      - can_id: 0x602
        then:
          - lambda: |-  
              int ziel = (int(x[0] & 0xf0) << 3) + int(x[1]);
              int iart = int(x[0] & 0x0f);
              int fa_kenng =int(x[2]);
              int sensor_id = int( (x[3]<<8) + x[4] );
              float antwort = float(int( (x[5]<<8) + x[6] ));

              if( iart == 2 ) {
                float sensorwert;

                switch( sensor_id ){

                  default:
                    if( ziel == 0x6a2 )
                      ESP_LOGD("myesp", "Antwort von 0x602 an 0x%x fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
                              , ziel, fa_kenng, sensor_id, antwort);
                    break;
                } // switch( sensor_id )

              //} else {
              //  ESP_LOGD("myesp", "von 0x602 an 0x%x art: %d fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
              //          , ziel, iart, fa_kenng, sensor_id, antwort);
              } // if( iart == 2)

      - can_id: 0x603
        then:
          - lambda: |-  
              int ziel = (int(x[0] & 0xf0) << 3) + int(x[1]);
              int iart = int(x[0] & 0x0f);
              int fa_kenng =int(x[2]);
              int sensor_id = int( (x[3]<<8) + x[4] );
              float antwort = float(int( (x[5]<<8) + x[6] ));

              if( iart == 2 ) {
                float sensorwert;

                switch( sensor_id ){

                  default:
                    if( ziel == 0x6a2 )
                      ESP_LOGD("myesp", "Antwort von 0x603 an 0x%x fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
                              , ziel, fa_kenng, sensor_id, antwort);
                    break;
                } // switch( sensor_id )

              //} else {
              //  ESP_LOGD("myesp", "von 0x603 an 0x%x art: %d fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
              //          , ziel, iart, fa_kenng, sensor_id, antwort);
              } // if( iart == 2)

      - can_id: 0x604
        then:
          - lambda: |-  
              int ziel = (int(x[0] & 0xf0) << 3) + int(x[1]);
              int iart = int(x[0] & 0x0f);
              int fa_kenng =int(x[2]);
              int sensor_id = int( (x[3]<<8) + x[4] );
              float antwort = float(int( (x[5]<<8) + x[6] ));

              if( iart == 2 ) {
                float sensorwert;

                switch( sensor_id ){

                  default:
                    if( ziel == 0x6a2 )
                      ESP_LOGD("myesp", "Antwort von 0x604 an 0x%x fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
                              , ziel, fa_kenng, sensor_id, antwort);
                    break;
                } // switch( sensor_id )

              //} else {
              //  ESP_LOGD("myesp", "von 0x604 an 0x%x art: %d fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
              //          , ziel, iart, fa_kenng, sensor_id, antwort);
              } // if( iart == 2)

      - can_id: 0x605
        then:
          - lambda: |-  
              int ziel = (int(x[0] & 0xf0) << 3) + int(x[1]);
              int iart = int(x[0] & 0x0f);
              int fa_kenng =int(x[2]);
              int sensor_id = int( (x[3]<<8) + x[4] );
              float antwort = float(int( (x[5]<<8) + x[6] ));

              if( iart == 2 ) {
                float sensorwert;

                switch( sensor_id ){

                  default:
                    if( ziel == 0x6a2 )
                      ESP_LOGD("myesp", "Antwort von 0x605 an 0x%x fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
                              , ziel, fa_kenng, sensor_id, antwort);
                    break;
                } // switch( sensor_id )

              //} else {
              //  ESP_LOGD("myesp", "von 0x605 an 0x%x art: %d fa_kenng: %2.2x sensor_id: 0x%4.4x Wert: %.0f"
              //          , ziel, iart, fa_kenng, sensor_id, antwort);
              } // if( iart == 2)
1 Like