#include "decode.h" namespace esphome { namespace panasonic_heatpump { constexpr const char* const PanasonicDecode::DisabledEnabled[]; constexpr const char* const PanasonicDecode::BlockedFree[]; constexpr const char* const PanasonicDecode::OffOn[]; constexpr const char* const PanasonicDecode::InactiveActive[]; constexpr const char* const PanasonicDecode::PumpFlowRateMode[]; constexpr const char* const PanasonicDecode::HolidayState[]; constexpr const char* const PanasonicDecode::OperationMode[]; constexpr const char* const PanasonicDecode::PowerfulMode[]; constexpr const char* const PanasonicDecode::QuietMode[]; constexpr const char* const PanasonicDecode::ThreeWayValve[]; constexpr const char* const PanasonicDecode::TwoWayValve[]; constexpr const char* const PanasonicDecode::MixingValve[]; constexpr const char* const PanasonicDecode::ZoneState[]; constexpr const char* const PanasonicDecode::WaterTempControl[]; constexpr const char* const PanasonicDecode::SolarMode[]; constexpr const char* const PanasonicDecode::ZoneSensorType[]; constexpr const char* const PanasonicDecode::LiquidType[]; constexpr const char* const PanasonicDecode::ExtPadHeaterType[]; constexpr const char* const PanasonicDecode::BivalentMode[]; constexpr const char* const PanasonicDecode::HeatingControl[]; constexpr const char* const PanasonicDecode::SmartDHW[]; constexpr const char* const PanasonicDecode::QuietModePriority[]; constexpr const char* const PanasonicDecode::ModelNames[]; constexpr 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, 0x0B, 0x44, 0x34, 0x12, 0xD0, 0x0C, 0x34, 0x35}, // 50 {0xE2, 0xD5, 0x0C, 0x67, 0x00, 0x83, 0x92, 0x0C, 0x27, 0x98}, // 51 {0xE2, 0xD5, 0x0B, 0x34, 0x99, 0x83, 0x92, 0x0C, 0x27, 0x98}, // 52 {0x42, 0xD4, 0x0B, 0x83, 0x71, 0x32, 0xD2, 0x0C, 0x44, 0x55}, // 53 {0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0E, 0x94, 0x05}, // 54 {0x12, 0xD7, 0x0D, 0x98, 0x11, 0x33, 0x94, 0x0C, 0x83, 0x10}, // 55 {0xE2, 0xD5, 0x0B, 0x08, 0x95, 0x02, 0xD6, 0x0F, 0x67, 0x95}, // 56 {0xE2, 0xD5, 0x0D, 0x36, 0x99, 0x02, 0xD6, 0x10, 0x66, 0x95}, // 57 {0xE2, 0xD5, 0x0F, 0x99, 0x94, 0x02, 0xD6, 0x10, 0x68, 0x95}, // 58 {0xE2, 0xD5, 0x0C, 0x67, 0x00, 0x83, 0x92, 0x0C, 0x28, 0x98}, // 59 {0xE2, 0xCF, 0x0D, 0x86, 0x05, 0x12, 0xD0, 0x0E, 0x95, 0x05}, // 60 {0x12, 0xD7, 0x0C, 0x98, 0x14, 0x35, 0x94, 0x0D, 0x83, 0x10}, // 61 {0xE2, 0xD5, 0x0C, 0x08, 0x95, 0x02, 0xD6, 0x10, 0x67, 0x95}, // 62 {0xC2, 0xD3, 0x0D, 0x35, 0x65, 0xB2, 0xD3, 0x0B, 0x96, 0x65}, // 63 {0xE2, 0xD5, 0x0C, 0x29, 0x99, 0x83, 0x92, 0x0C, 0x29, 0x98}, // 64 {0x62, 0xD2, 0x0B, 0x45, 0x54, 0x42, 0xD2, 0x0B, 0x72, 0x66}, // 65 {0xE2, 0xCF, 0x0B, 0x82, 0x09, 0x12, 0xD0, 0x0B, 0x10, 0x11}, // 66 {0x42, 0xD4, 0x0B, 0x83, 0x71, 0x32, 0xD2, 0x0C, 0x45, 0x55}, // 67 {0x12, 0xD7, 0x0B, 0x47, 0x19, 0x37, 0x94, 0x0E, 0x83, 0x10}, // 68 {0xE2, 0xD5, 0x0D, 0x00, 0x09, 0x43, 0xD6, 0x0E, 0x07, 0x09}, // 69 {0xE2, 0xCF, 0x0B, 0x84, 0x05, 0x12, 0xD0, 0x0B, 0x93, 0x05}, // 70 {0xE2, 0xD5, 0x0B, 0x35, 0x99, 0x83, 0x92, 0x0D, 0x29, 0x98}, // 71 {0x12, 0xD7, 0x0B, 0x98, 0x14, 0x35, 0x94, 0x0D, 0x83, 0x10}, // 72 }; int PanasonicDecode::getBit1(uint8_t input) { return input >> 7; } int PanasonicDecode::getBit1and2(uint8_t input) { return (input >> 6) - 1; } int PanasonicDecode::getBit3and4(uint8_t input) { return ((input >> 4) & 0b11) - 1; } int PanasonicDecode::getBit5and6(uint8_t input) { return ((input >> 2) & 0b11) - 1; } int PanasonicDecode::getBit7and8(uint8_t input) { return (input & 0b11) - 1; } int PanasonicDecode::getBit3and4and5(uint8_t input) { return ((input >> 3) & 0b111) - 1; } int PanasonicDecode::getBit6and7and8(uint8_t input) { return (input & 0b111) - 1; } int PanasonicDecode::getByteMinus1(uint8_t input) { return (int)input - 1; } int PanasonicDecode::getByteMinus128(uint8_t input) { return (int)input - 128; } float PanasonicDecode::getByteMinus1Div2(uint8_t input) { return ((float)input - 1) / 2; } float PanasonicDecode::getByteMinus1Div5(uint8_t input) { return ((float)input - 1) / 5; } float PanasonicDecode::getByteMinus1Div50(uint8_t input) { return ((float)input - 1) / 50; } int PanasonicDecode::getByteMinus1Times10(uint8_t input) { return ((int)input - 1) * 10; } int PanasonicDecode::getByteMinus1Times50(uint8_t input) { return ((int)input - 1) * 50; } int PanasonicDecode::getByteMinus1Times200(uint8_t input) { return ((int)input - 1) * 200; } int PanasonicDecode::getHighNibbleMinus1(uint8_t input) { return (input >> 4) - 1; } int PanasonicDecode::getLowNibbleMinus1(uint8_t input) { return (input & 0b1111) - 1; } int PanasonicDecode::getWordMinus1(const std::vector& data, uint8_t index) { return ((data[index + 1] << 8) + data[index]) - 1; } int PanasonicDecode::getUintt16(const std::vector& data, uint8_t index) { return (static_cast((data[index + 1] << 8) | data[index])) - 1; } // TOP4 // int PanasonicDecode::getOperationMode(uint8_t input) { switch ((int)(input & 0b111111)) { case 0b100001: // 0x21 = tank return 0; case 0b010010: // 0x12 = heat return 1; case 0b100010: // 0x22 = heat+tank return 2; case 0b010011: // 0x13 = cool return 3; case 0b100011: // 0x23 = cool+tank return 4; case 0b011000: // 0x18 = auto return 5; case 0b101000: // 0x28 = auto-tank return 6; case 0b011001: // 0x19 = auto-heat return 7; case 0b101001: // 0x29 = auto-heat+tank return 8; case 0b011010: // 0x1A = auto-cool return 9; case 0b101010: // 0x2A = auto-cool+tank return 10; default: // unknown return -1; } } // TOP92 // int PanasonicDecode::getModel(const std::vector& data, uint8_t index) { // Ensure there are at least 10 bytes in data message after the start index if (index + 10 > data.size()) return -1; // Get model bytes from data message auto model = std::vector(data.begin() + index, data.begin() + index + 10); // Search model bytes in the list of known models and return the index for (size_t i = 0; i < NUMBER_OF_MODELS; i++) { if (std::equal(KnownModels[i], KnownModels[i] + 10, model.begin())) { return static_cast(i); } } return -1; } // TOP1 // // input1 = data[169] // input2 = data[170] float PanasonicDecode::getPumpFlow(const std::vector& data, uint8_t index) { return (((float)data[index] - 1) / 256) + ((int)data[index + 1]); } // TOP5, TOP6 // float PanasonicDecode::getFractional(uint8_t input, uint8_t shift) { return ((int)((input >> shift) & 0b111) - 1) * 0.25; } // TOP44 // // errorType = data[113] // errorNumber = data[114] std::string PanasonicDecode::getErrorInfo(uint8_t errorType, uint8_t errorNumber) { int error_type = (int)(errorType); int error_number = ((int)(errorNumber)) - 17; char error_string[10]; switch (error_type) { case 0xA1: // H type error sprintf(error_string, "H%02X", error_number); break; case 0xB1: // F type error sprintf(error_string, "F%02X", error_number); break; default: sprintf(error_string, "No error"); break; } return error_string; } bool PanasonicDecode::getBinaryState(uint8_t input) { return input != 0; } std::string PanasonicDecode::getTextState(const char* const array[], int index) { int size = atoi(array[0]); if ((index < 0) || (index >= size)) { return "UNDEFINED"; } return array[index + 1]; } } // namespace panasonic_heatpump } // namespace esphome