Yes indeed I am still working on this project, unfortunately not as fast as I would like.
So first of all I have implemented some sensors to show the values from the heatpump.
For now I have implemented only the first 20 heishamon topics.
But it should not be that difficult to implement the remaining topics.
Here is my esphome yaml file:
substitutions:
mdns_name: panasonic-heatpump
device_name: Panasonic Heatpump
#pin_status_led: GPIO8
pin_rx_hp: GPIO4 # heatpump reads data (RX) on this pin (green)
pin_tx_hp: GPIO3 # heatpump sends data (TX) on this pin (yellow)
pin_tx_cz: GPIO1 # WiFi module sends data (TX) on this pin (blue)
pin_rx_cz: GPIO0 # WiFi module reads data (RX) on this pin (white)
# CN-CNT Pinout (from top to bottom)
# 1 - +5V (250mA)
# 2 - 0-5V TX (from heatpump)
# 3 - 0-5V RX (to heatpump)
# 4 - +12V (250mA)
# 5 - GND
esp32:
board: esp32-c3-devkitm-1
variant: ESP32C3
framework:
type: arduino
esphome:
name: $mdns_name
friendly_name: $device_name
includes:
- custom_components/heishamon/decode.h
- custom_components/heishamon/decode.cpp
ota:
platform: esphome
password: !secret ota_password
id: ota_pass
api:
encryption:
key: !secret ha_api_key
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "${device_name} Fallback"
password: !secret fallback_password
web_server:
port: 80
auth:
username: !secret webserver_username
password: !secret webserver_password
captive_portal:
improv_serial:
logger:
uart:
- id: uart_hp
# switch rx and tx to read what the heatpump is sending
tx_pin: $pin_rx_hp
rx_pin: $pin_tx_hp
baud_rate: 9600
data_bits: 8
parity: EVEN
stop_bits: 1
debug:
direction: RX
dummy_receiver: true # needed if no uart component is available
after:
bytes: 203
sequence:
- lambda: |-
ESP_LOGD("custom", "Heatpump:");
UARTDebug::log_hex(direction, bytes, ',');
if (bytes.size() == 203)
{
id(top0).publish_state(toBool(getBit7and8(bytes[4])));
id(top1).publish_state(getPumpFlow(bytes[169], bytes[170]));
id(top2).publish_state(toBool(getBit1and2(bytes[4])));
id(top3).publish_state(toBool(getBit1and2(bytes[7])));
id(top4).publish_state(getOpMode(bytes[6]));
id(top5).publish_state(getIntMinus128(bytes[143]) + getFractional(bytes[118], 0));
id(top6).publish_state(getIntMinus128(bytes[144]) + getFractional(bytes[118], 3));
id(top7).publish_state(getIntMinus128(bytes[153]));
id(top8).publish_state(getIntMinus1(bytes[166]));
id(top9).publish_state(getIntMinus128(bytes[42]));
id(top10).publish_state(getIntMinus128(bytes[141]));
id(top11).publish_state(getWord(bytes[182], bytes[183]));
id(top12).publish_state(getWord(bytes[179], bytes[180]));
id(top13).publish_state(toBool(getBit1and2(bytes[5])));
id(top14).publish_state(getIntMinus128(bytes[142]));
id(top15).publish_state(getPower(bytes[194]));
id(top16).publish_state(getPower(bytes[193]));
id(top17).publish_state(getPowerfulmode(getRight3bits(bytes[7])));
id(top18).publish_state(getQuietmode(getBit3and4and5(bytes[7])));
id(top19).publish_state(getHolidayState(getBit3and4(bytes[5])));
id(top20).publish_state(getValve(getBit7and8(bytes[111])));
id(top92).publish_state(getModel(bytes, 129));
}
- uart.write: # Write rx to tx.
id: uart_cz
data: !lambda return bytes;
- id: uart_cz
# switch rx and tx to read what the WiFi module is sending
tx_pin: $pin_rx_cz
rx_pin: $pin_tx_cz
baud_rate: 9600
data_bits: 8
parity: EVEN
stop_bits: 1
debug:
direction: RX
dummy_receiver: true # needed if no uart component is available
after:
bytes: 203
sequence:
- lambda: |-
ESP_LOGD("custom", "CZ-TAW1:");
UARTDebug::log_hex(direction, bytes, ',');
- uart.write: # Write rx to tx.
id: uart_hp
data: !lambda return bytes;
# # If no CZ-TAW1 available write command to get new data every 5 seconds
# interval:
# - interval: 5s
# then:
# - uart.write:
# id: uart_hp
# data: [0x71, 0x6C, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12]
sensor:
- platform: wifi_signal
name: WiFi Signal
- platform: template
id: top1
name: "Pump_Flow"
unit_of_measurement: l/min
lambda: "return {};"
- platform: template
id: top5
name: "Main_Inlet_Temp"
unit_of_measurement: °C
lambda: "return {};"
- platform: template
id: top6
name: "Main_Outlet_Temp"
unit_of_measurement: °C
lambda: "return {};"
- platform: template
id: top7
name: "Main_Target_Temp"
unit_of_measurement: °C
lambda: "return {};"
- platform: template
id: top8
name: "Compressor_Freq"
unit_of_measurement: Hz
lambda: "return {};"
- platform: template
id: top9
name: "DHW_Target_Temp"
unit_of_measurement: °C
lambda: "return {};"
- platform: template
id: top10
name: "DHW_Temp"
unit_of_measurement: °C
lambda: "return {};"
- platform: template
id: top11
name: "Operations_Hours"
unit_of_measurement: h
lambda: "return {};"
- platform: template
id: top12
name: "Operations_Counter"
lambda: "return {};"
- platform: template
id: top14
name: "Outside_Temp"
unit_of_measurement: °C
lambda: "return {};"
- platform: template
id: top15
name: "Heat_Power_Production"
unit_of_measurement: W
lambda: "return {};"
- platform: template
id: top16
name: "Heat_Power_Consumption"
unit_of_measurement: W
lambda: "return {};"
text_sensor:
- platform: version
hide_timestamp: true
name: ESPHome Version
- platform: wifi_info
ip_address:
name: IP Addresse
icon: mdi:ip
- platform: template
id: top4
name: "Operating_Mode_State"
lambda: "return {};"
- platform: template
id: top17
name: "Powerful_Mode_Time"
lambda: "return {};"
- platform: template
id: top18
name: "Quiet_Mode_Level"
lambda: "return {};"
- platform: template
id: top19
name: "Holiday_Mode_State"
lambda: "return {};"
- platform: template
id: top20
name: "ThreeWay_Valve_State"
lambda: "return {};"
- platform: template
id: top92
name: "Heat_Pump_Model"
lambda: "return {};"
binary_sensor:
- platform: status
name: Status
- platform: template
id: top0
name: "Heatpump_State"
lambda: "return {};"
- platform: template
id: top2
name: "Force_DHW_State"
lambda: "return {};"
- platform: template
id: top3
name: "Quiet_Mode_Schedule"
lambda: "return {};"
- platform: template
id: top13
name: "Main_Schedule_State"
lambda: "return {};"
button:
- platform: restart
name: Neustart
The decode.h file:
#pragma once
#include <cstdint>
#include <cstdlib>
#include <string>
#include <cstring>
#include <vector>
#define NUMBER_OF_MODELS 51
#define NUMBER_OF_TOPICS 127
#define NUMBER_OF_TOPICS_EXTRA 6
#define NUMBER_OF_OPT_TOPICS 7
#define MAX_TOPIC_LEN 42
bool toBool(uint8_t input);
int getBit1(uint8_t input);
int getBit1and2(uint8_t input);
int getBit3and4(uint8_t input);
int getBit5and6(uint8_t input);
int getBit7and8(uint8_t input);
int getBit3and4and5(uint8_t input);
int getLeft5bits(uint8_t input);
int getRight3bits(uint8_t input);
int getIntMinus1(uint8_t input);
int getIntMinus128(uint8_t input);
float getIntMinus1Div5(uint8_t input);
float getIntMinus1Div50(uint8_t input);
int getIntMinus1Times10(uint8_t input);
int getIntMinus1Times50(uint8_t input);
int getPower(uint8_t input);
int getFirstByte(uint8_t input);
int getSecondByte(uint8_t input);
int getWord(uint8_t hi, uint8_t low);
int getUintt16(uint8_t input1, uint8_t input2);
float getPumpFlow(uint8_t input1, uint8_t input2);
float getFractional(uint8_t input, uint8_t shift);
std::string getOpMode(int input);
std::string getPowerfulmode(int input);
std::string getQuietmode(int input);
std::string getHolidayState(int input);
std::string getValve(int input);
std::string getErrorInfo(uint8_t errorType, uint8_t errorNumber);
std::string getBlockedFree(int input);
std::string getHeatCoolModeDesc(int input);
std::string getModel(std::vector<uint8_t>& data, uint8_t index);
std::string getZonesState(int input);
std::string getSolarModeDesc(int input);
std::string getPumpFlowRateMode(int input);
std::string getLiquidType(int input);
std::string getZonesSensorType(int input);
std::string getExtPadHeaterType(int input);
std::string getBivalent(int input);
std::string getMixingValveState(int input);
static const char *ModelNames[] =
{
"WH-MDC05H3E5", //0
"WH-MDC07H3E5", //1
"IDU:WH-SXC09H3E5, ODU:WH-UX09HE5", //2
"IDU:WH-SDC09H3E8, ODU:WH-UD09HE8", //3
"IDU:WH-SXC09H3E8, ODU:WH-UX09HE8", //4
"IDU:WH-SXC12H9E8, ODU:WH-UX12HE8", //5
"IDU:WH-SXC16H9E8, ODU:WH-UX16HE8", //6
"IDU:WH-SDC05H3E5, ODU:WH-UD05HE5", //7
"IDU:WH-SDC0709J3E5, ODU:WH-UD09JE5", //8
"WH-MDC05J3E5", //9
"WH-MDC09H3E5", //10
"WH-MXC09H3E5", //11
"IDU:WH-ADC0309J3E5, ODU:WH-UD09JE5", //12
"IDU:WH-ADC0916H9E8, ODU:WH-UX12HE8", //13
"IDU:WH-SQC09H3E8, ODU:WH-UQ09HE8", //14
"IDU:WH-SDC09H3E5, ODU:WH-UD09HE5", //15
"IDU:WH-ADC0309H3E5, ODU:WH-UD09HE5", //16
"IDU:WH-ADC0309J3E5, ODU:WH-UD05JE5", //17
"IDU:WH-SDC0709J3E5, ODU:WH-UD07JE5", //18
"IDU:WH-SDC07H3E5-1, ODU:WH-UD07HE5-1", //19
"WH-MDC07J3E5", //20
"WH-MDC09J3E5", //21
"IDU:WH-SDC0305J3E5, ODU:WH-UD05JE5", //22
"WH-MXC09J3E8", //23
"WH-MXC12J9E8", //24
"IDU:WH-ADC1216H6E5, ODU:WH-UD12HE5", //25
"IDU:WH-ADC0309J3E5C, ODU:WH-UD07JE5", //26
"WH-MDC07J3E5", //27
"WH-MDC05J3E5", //28
"IDU:WH-UQ12HE8, ODU:WH-SQC12H9E8", //29
"IDU:WH-SXC12H6E5, ODU:WH-UX12HE5", //30
"WH-MDC09J3E5", //31
"WH-MXC09J3E5", //32
"IDU:WH-ADC1216H6E5C ODU:WH-UD12HE5", //33
"IDU:WH-ADC0509L3E5 ODU:WH-WDG07LE5", //34
"IDU:WH-SXC09H3E8 ODU:WH-UX09HE8", //35
"IDU:WH-ADC0309K3E5AN ODU:WH-UDZ07KE5", //36
"IDU:WH-SDC0309K3E5 ODU:WH-UDZ05KE5", //37
"IDU:WH-SDC0509L3E5 ODU:WH-WDG09LE5", //38
"IDU:WH-SDC12H9E8 ODU:WH-UD12HE8", //39
"IDU:WH-SDC0309K3E5, ODU:WH-UDZ07KE5", //40
"IDU:WH-ADC0916H9E8, ODU:WH-UX16HE8", //41
"IDU:WH-ADC0912H9E8, ODU:WH-UX12HE8", //42
"WH-MXC16J9E8", //43
"WH-MXC12J6E5", //44
"IDU:WH-SQC09H3E8, ODU:WH-UQ09HE8", //45
"IDU:WH-ADC0309K3E5 ODU:WH-UDZ09KE5", //46
"IDU:WH-ADC0916H9E8, ODU:WH-UX12HE8", //47
"IDU:WH-SDC0509L3E5 ODU:WH-WDG07LE5", //48
"IDU:WH-SXC09H3E5, ODU:WH-UX09HE5", //49
"IDU:WH-SXC12H9E8, ODU:WH-UX12HE8", //50
};
//stores the bytes #129 to #138 of known models in the same order as the const above
static const uint8_t KnownModels[NUMBER_OF_MODELS][10] =
{
0xE2, 0xCF, 0x0B, 0x13, 0x33, 0x32, 0xD1, 0x0C, 0x16, 0x33, //0
0xE2, 0xCF, 0x0B, 0x14, 0x33, 0x42, 0xD1, 0x0B, 0x17, 0x33, //1
0xE2, 0xCF, 0x0D, 0x77, 0x09, 0x12, 0xD0, 0x0B, 0x05, 0x11, //2
0xE2, 0xCF, 0x0C, 0x88, 0x05, 0x12, 0xD0, 0x0B, 0x97, 0x05, //3
0xE2, 0xCF, 0x0D, 0x85, 0x05, 0x12, 0xD0, 0x0C, 0x94, 0x05, //4
0xE2, 0xCF, 0x0D, 0x86, 0x05, 0x12, 0xD0, 0x0C, 0x95, 0x05, //5
0xE2, 0xCF, 0x0D, 0x87, 0x05, 0x12, 0xD0, 0x0C, 0x96, 0x05, //6
0xE2, 0xCE, 0x0D, 0x71, 0x81, 0x72, 0xCE, 0x0C, 0x92, 0x81, //7
0x62, 0xD2, 0x0B, 0x43, 0x54, 0x42, 0xD2, 0x0B, 0x72, 0x66, //8
0xC2, 0xD3, 0x0B, 0x33, 0x65, 0xB2, 0xD3, 0x0B, 0x94, 0x65, //9
0xE2, 0xCF, 0x0B, 0x15, 0x33, 0x42, 0xD1, 0x0B, 0x18, 0x33, //10
0xE2, 0xCF, 0x0B, 0x41, 0x34, 0x82, 0xD1, 0x0B, 0x31, 0x35, //11
0x62, 0xD2, 0x0B, 0x45, 0x54, 0x42, 0xD2, 0x0B, 0x47, 0x55, //12
0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0D, 0x95, 0x05, //13
0xE2, 0xCF, 0x0B, 0x82, 0x05, 0x12, 0xD0, 0x0C, 0x91, 0x05, //14
0xE2, 0xCF, 0x0C, 0x55, 0x14, 0x12, 0xD0, 0x0B, 0x15, 0x08, //15
0xE2, 0xCF, 0x0C, 0x43, 0x00, 0x12, 0xD0, 0x0B, 0x15, 0x08, //16
0x62, 0xD2, 0x0B, 0x45, 0x54, 0x32, 0xD2, 0x0C, 0x45, 0x55, //17
0x62, 0xD2, 0x0B, 0x43, 0x54, 0x42, 0xD2, 0x0C, 0x46, 0x55, //18
0xE2, 0xCF, 0x0C, 0x54, 0x14, 0x12, 0xD0, 0x0B, 0x14, 0x08, //19
0xC2, 0xD3, 0x0B, 0x34, 0x65, 0xB2, 0xD3, 0x0B, 0x95, 0x65, //20
0xC2, 0xD3, 0x0B, 0x35, 0x65, 0xB2, 0xD3, 0x0B, 0x96, 0x65, //21
0x62, 0xD2, 0x0B, 0x41, 0x54, 0x32, 0xD2, 0x0C, 0x45, 0x55, //22
0x32, 0xD4, 0x0B, 0x87, 0x84, 0x73, 0x90, 0x0C, 0x84, 0x84, //23
0x32, 0xD4, 0x0B, 0x88, 0x84, 0x73, 0x90, 0x0C, 0x85, 0x84, //24
0xE2, 0xCF, 0x0B, 0x75, 0x09, 0x12, 0xD0, 0x0C, 0x06, 0x11, //25
0x42, 0xD4, 0x0B, 0x83, 0x71, 0x42, 0xD2, 0x0C, 0x46, 0x55, //26
0xC2, 0xD3, 0x0C, 0x34, 0x65, 0xB2, 0xD3, 0x0B, 0x95, 0x65, //27
0xC2, 0xD3, 0x0C, 0x33, 0x65, 0xB2, 0xD3, 0x0B, 0x94, 0x65, //28
0xE2, 0xCF, 0x0B, 0x83, 0x05, 0x12, 0xD0, 0x0D, 0x92, 0x05, //29
0xE2, 0xCF, 0x0C, 0x78, 0x09, 0x12, 0xD0, 0x0B, 0x06, 0x11, //30
0xC2, 0xD3, 0x0C, 0x35, 0x65, 0xB2, 0xD3, 0x0B, 0x96, 0x65, //31
0x32, 0xD4, 0x0B, 0x99, 0x77, 0x62, 0x90, 0x0B, 0x01, 0x78, //32
0x42, 0xD4, 0x0B, 0x15, 0x76, 0x12, 0xD0, 0x0B, 0x10, 0x11, //33
0xE2, 0xD5, 0x0C, 0x29, 0x99, 0x83, 0x92, 0x0C, 0x28, 0x98, //34
0xE2, 0xCF, 0x0D, 0x85, 0x05, 0x12, 0xD0, 0x0E, 0x94, 0x05, //35
0xE2, 0xD5, 0x0D, 0x36, 0x99, 0x02, 0xD6, 0x0F, 0x67, 0x95, //36
0xE2, 0xD5, 0x0B, 0x08, 0x95, 0x02, 0xD6, 0x0E, 0x66, 0x95, //37
0xE2, 0xD5, 0x0B, 0x34, 0x99, 0x83, 0x92, 0x0C, 0x29, 0x98, //38
0xE2, 0xCF, 0x0C, 0x89, 0x05, 0x12, 0xD0, 0x0C, 0x98, 0x05, //39
0xE2, 0xD5, 0x0B, 0x08, 0x95, 0x02, 0xD6, 0x0E, 0x67, 0x95, //40
0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0C, 0x96, 0x05, //41
0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0E, 0x95, 0x05, //42
0x32, 0xD4, 0x0B, 0x89, 0x84, 0x73, 0x90, 0x0C, 0x86, 0x84, //43
0x32, 0xD4, 0x0B, 0x00, 0x78, 0x62, 0x90, 0x0B, 0x02, 0x78, //44
0xE2, 0xCF, 0x0B, 0x82, 0x05, 0x12, 0xD0, 0x0D, 0x91, 0x05, //45
0xE2, 0xD5, 0x0D, 0x99, 0x94, 0x02, 0xD6, 0x0D, 0x68, 0x95, //46
0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0C, 0x95, 0x05, //47
0xE2, 0xD5, 0x0B, 0x34, 0x99, 0x83, 0x92, 0x0C, 0x28, 0x98, //48
0xE2, 0xCF, 0x0D, 0x77, 0x09, 0x12, 0xD0, 0x0C, 0x05, 0x11, //49
0xE2, 0xCF, 0x0D, 0x86, 0x05, 0x12, 0xD0, 0x0E, 0x95, 0x05, //50
};
The decode.cpp file:
#include "decode.h"
bool toBool(uint8_t input)
{
return input != 0;
}
int getBit1(uint8_t input)
{
return (input >> 7);
}
int getBit1and2(uint8_t input)
{
return ((input >> 6) - 1);
}
int getBit3and4(uint8_t input)
{
return (((input >> 4) & 0b11) - 1);
}
int getBit5and6(uint8_t input)
{
return (((input >> 2) & 0b11) - 1);
}
int getBit7and8(uint8_t input)
{
return ((input & 0b11) - 1);
}
int getBit3and4and5(uint8_t input)
{
return (((input >> 3) & 0b111) - 1);
}
int getLeft5bits(uint8_t input)
{
return ((input >> 3) - 1);
}
int getRight3bits(uint8_t input)
{
return ((input & 0b111) - 1);
}
int getIntMinus1(uint8_t input)
{
int value = (int)input - 1;
return value;
}
int getIntMinus128(uint8_t input)
{
int value = (int)input - 128;
return value;
}
float getIntMinus1Div5(uint8_t input)
{
return ((((float)input - 1) / 5), 1);
}
float getIntMinus1Div50(uint8_t input)
{
return ((((float)input - 1) / 50), 2);
}
int getIntMinus1Times10(uint8_t input)
{
int value = (int)input - 1;
return (value * 10);
}
int getIntMinus1Times50(uint8_t input)
{
int value = (int)input - 1;
return (value * 50);
}
int getPower(uint8_t input)
{
int value = ((int)input - 1) * 200;
return value;
}
int getFirstByte(uint8_t input)
{
return ((input >> 4) - 1);
}
int getSecondByte(uint8_t input)
{
return ((input & 0b1111) - 1);
}
int getWord(uint8_t low, uint8_t hi)
{
return ((hi << 8) + low) - 1;
}
int getUintt16(uint8_t input1, uint8_t input2)
{
uint16_t value = static_cast<uint16_t>((input2 << 8) | input1);
return (value - 1);
}
// input1 = data[169]
// input2 = data[170]
float getPumpFlow(uint8_t input1, uint8_t input2)
{ // TOP1 //
int PumpFlow2 = (int)input2;
float PumpFlow1 = (((float)input1 - 1) / 256);
float PumpFlow = PumpFlow2 + PumpFlow1;
return PumpFlow;
}
float getFractional(uint8_t input, uint8_t shift)
{
float result;
int fractional = (int)((input >> shift) & 0b111) - 1;
result = fractional * 0.25;
return result;
}
std::string getOpMode(int input)
{
switch ((input & 0b111111))
{
case 18:
return "Heat";
case 19:
return "Cool";
case 25:
return "Auto(heat)";
case 33:
return "DHW";
case 34:
return "Heat+DHW";
case 35:
return "Cool+DHW";
case 41:
return "Auto(heat)+DHW";
case 26:
return "Auto(cool)";
case 42:
return "Auto(cool)+DHW";
default:
return "UNKNOWN";
}
}
std::string getPowerfulmode(int input)
{
switch (input)
{
case 0:
return "Off";
case 1:
return "30min";
case 2:
return "60min";
case 3:
return "90min";
default:
return "UNKNOWN";
}
}
std::string getQuietmode(int input)
{
switch (input)
{
case 0:
return "Off";
case 1:
return "Level 1";
case 2:
return "Level 2";
case 3:
return "Level 3";
default:
return "UNKNOWN";
}
}
std::string getHolidayState(int input)
{
switch (input)
{
case 0:
return "Off";
case 1:
return "Scheduled";
case 2:
return "Active";
default:
return "UNKNOWN";
}
}
std::string getValve(int input)
{
switch (input)
{
case 0:
return "Room";
case 1:
return "DHW";
default:
return "UNKNOWN";
}
}
// errorType = data[113]
// errorNumber = data[114]
std::string getErrorInfo(uint8_t errorType, uint8_t errorNumber)
{ // TOP44 //
int error_type = (int)(errorType);
int error_number = ((int)(errorNumber)) - 17;
char error_string[10];
switch (error_type)
{
case 177: // B1=F type error
sprintf(error_string, "F%02X", error_number);
break;
case 161: // A1=H type error
sprintf(error_string, "H%02X", error_number);
break;
default:
sprintf(error_string, "No error");
break;
}
return error_string;
}
std::string getBlockedFree(int input)
{
switch (input)
{
case 0:
return "Blocked";
case 1:
return "Free";
default:
return "UNKNOWN";
}
}
std::string getHeatCoolModeDesc(int input)
{
switch (input)
{
case 0:
return "Comp. Curve";
case 1:
return "Directe";
default:
return "UNKNOWN";
}
}
std::string getModel(std::vector<uint8_t>& data, uint8_t index)
{ // TOP92 //
uint8_t model[10] = { data[index], data[index+1], data[index+2], data[index+3], data[index+4], data[index+5], data[index+6], data[index+7], data[index+8], data[index+9] };
int result = -1;
std::string returnValue = "UNKNOWN";
for (unsigned int i = 0 ; i < sizeof(KnownModels) / sizeof(KnownModels[0]) ; i++)
{
if (memcmp(model, KnownModels[i], 10) == 0)
{
result = i;
}
}
if (result >= 0 && result < sizeof(ModelNames) / sizeof(ModelNames[0]))
{
returnValue = ModelNames[result];
}
return returnValue;
}
std::string getZonesState(int input)
{
switch (input)
{
case 0:
return "Zone1 active";
case 1:
return "Zone2 active";
case 2:
return "Zone1 and zone2 active";
default:
return "UNKNOWN";
}
}
std::string getSolarModeDesc(int input)
{
switch (input)
{
case 0:
return "Disabled";
case 1:
return "Buffer";
case 2:
return "DHW";
default:
return "UNKNOWN";
}
}
std::string getPumpFlowRateMode(int input)
{
switch (input)
{
case 0:
return "DeltaT";
case 1:
return "Max flow";
default:
return "UNKNOWN";
}
}
std::string getLiquidType(int input)
{
switch (input)
{
case 0:
return "Water";
case 1:
return "Glycol";
default:
return "UNKNOWN";
}
}
std::string getZonesSensorType(int input)
{
switch (input)
{
case 0:
return "Water Temperature";
case 1:
return "External Thermostat";
case 2:
return "Internal Thermostat";
case 3:
return "Thermistor";
default:
return "UNKNOWN";
}
}
std::string getExtPadHeaterType(int input)
{
switch (input)
{
case 0:
return "Disabled";
case 1:
return "Type-A";
case 2:
return "Type-B";
default:
return "UNKNOWN";
}
}
std::string getBivalent(int input)
{
switch (input)
{
case 0:
return "Off";
case 1:
return "Alternativ";
case 2:
return "A-Off";
case 3:
return "Parallel";
case 4:
return "P-Off";
case 5:
return "Parallel Advanced";
default:
return "UNKNOWN";
}
}
std::string getMixingValveState(int input)
{
switch (input)
{
case 0:
return "Off";
case 1:
return "Increase";
case 2:
return "Nothing";
case 3:
return "Decrease";
default:
return "UNKNOWN";
}
}
The files must be located as follows:
esphome
├── panasonic_heatpump.yaml
└── custom_components
└── heishamon
├── decode.h
└── decode.cpp