From ffafa6f71931182efef47102942a39e28a5bffdd Mon Sep 17 00:00:00 2001 From: ElVit Date: Fri, 31 Jan 2025 16:47:35 +0100 Subject: [PATCH] Added commands to panasonic_heatpump --- components/panasonic_heatpump/commands.cpp | 218 ++++++++ components/panasonic_heatpump/commands.h | 42 ++ components/panasonic_heatpump/decode.cpp | 598 +++++++++++---------- components/panasonic_heatpump/decode.h | 225 ++++---- 4 files changed, 675 insertions(+), 408 deletions(-) create mode 100644 components/panasonic_heatpump/commands.cpp create mode 100644 components/panasonic_heatpump/commands.h diff --git a/components/panasonic_heatpump/commands.cpp b/components/panasonic_heatpump/commands.cpp new file mode 100644 index 0000000..90a0894 --- /dev/null +++ b/components/panasonic_heatpump/commands.cpp @@ -0,0 +1,218 @@ +#include "commands.h" + +#define REQUEST_DATA_SIZE 111 +#define REQUEST_INITIAL_SIZE 8 +#define REQUEST_OPTIONAL_SIZE 20 + +#define OPTIONALPCBQUERYTIME 1000 // send optional pcb query each second +#define OPTIONALPCBSAVETIME 300 // save each 5 minutes the current optional pcb state into flash to have valid values during reboot + + +namespace esphome +{ + namespace panasonic_heatpump + { + // ToDo: Use vector instead of byte[] + static uint8_t temp_command[REQUEST_DATA_SIZE] = { 0 }; + static uint8_t temp_command_optional[REQUEST_OPTIONAL_SIZE] = { + 0xF1, 0x11, 0x01, 0x50, 0x00, 0x00, 0x40, 0xFF, 0xFF, 0xE5, 0xFF, 0xFF, 0x00, 0xFF, 0xEB, + 0xFF, 0xFF, 0x00, 0x00, 0x00 + }; + + static const uint8_t InitialRequest[REQUEST_INITIAL_SIZE] = { + 0x31, 0x05, 0x10, 0x01, 0x00, 0x00, 0x00, 0xB9 + }; + static const uint8_t PeriodicalRequest[REQUEST_DATA_SIZE] = { + 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 + }; + static const uint8_t CommandRequest[REQUEST_DATA_SIZE] = { + 0xF1, 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, 0x92 + }; + + + std::vector PanasonicCommand::setCommand(uint8_t index, uint8_t newValue) + { + // initialize the command + memcpy(temp_command, CommandRequest, sizeof(CommandRequest)); + // set command byte + temp_command[index] = newValue; + // calculate and set set checksum + temp_command[REQUEST_DATA_SIZE - 1] = calcChecksum(temp_command, REQUEST_DATA_SIZE - 1); + + // convert to vector and return + return std::vector(temp_command, temp_command + REQUEST_DATA_SIZE); + } + + std::vector PanasonicCommand::setOptionalCommand(uint8_t index, uint8_t newValue) + { + // set command byte + temp_command_optional[index] = newValue; + // calculate and set set checksum + temp_command_optional[REQUEST_OPTIONAL_SIZE - 1] = calcChecksum(temp_command_optional, REQUEST_OPTIONAL_SIZE - 1); + + // convert to vector and return + return std::vector(temp_command_optional, temp_command_optional + REQUEST_OPTIONAL_SIZE); + } + + uint8_t PanasonicCommand::calcChecksum(uint8_t *command, int length) + { + uint8_t chk = 0; + for (int i = 0; i < length; i++) + { + chk += command[i]; + } + chk = (chk ^ 0xFF) + 01; + return chk; + } + + + uint8_t PanasonicCommand::setMultiply2(unsigned int input) + { + return input * 2; + } + + uint8_t PanasonicCommand::setMultiply4(unsigned int input) + { + return input * 4; + } + + uint8_t PanasonicCommand::setPlus1Multiply4(unsigned int input) + { + return (input + 1) * 4; + } + + uint8_t PanasonicCommand::setPlus1Multiply8(unsigned int input) + { + return (input + 1) * 8; + } + + uint8_t PanasonicCommand::setPlus1Multiply16(unsigned int input) + { + return (input + 1) * 16; + } + + uint8_t PanasonicCommand::setPlus1Multiply64(unsigned int input) + { + return (input + 1) * 64; + } + + uint8_t PanasonicCommand::setPlus1(unsigned int input) + { + return input + 1; + } + + uint8_t PanasonicCommand::setPlus73(unsigned int input) + { + return input + 73; + } + + uint8_t PanasonicCommand::setPlus128(unsigned int input) + { + return input + 128; + } + + uint8_t PanasonicCommand::setOperationMode(unsigned int input) + { + switch (input) + { + case 0: return 18; + case 1: return 19; + case 2: return 24; + case 3: return 33; + case 4: return 34; + case 5: return 35; + case 6: return 40; + } + return 0; + } + + uint8_t PanasonicCommand::setBivalentMode(unsigned int input) + { + switch (input) + { + case 0: return 101; + case 1: return 102; + case 2: return 104; + case 3: return 105; + case 4: return 108; + case 5: return 109; + } + return 0; + } + + //start of optional pcb commands + + uint8_t PanasonicCommand::temp2hex(float temp) + { + int hextemp = 0; + if (temp > 120) + { + hextemp = 0; + } + else if (temp < -78) + { + hextemp = 255; + } + else + { + uint8_t Uref = 255; + int constant = 3695; + int R25 = 6340; + uint8_t T25 = 25; + int Rf = 6480; + float K = 273.15; + float RT = R25 * exp(constant * (1 / (temp + K) - 1 / (T25 + K))); + hextemp = Uref * (RT / (Rf + RT)); + } + + return hextemp; + } + + uint8_t PanasonicCommand::setByte6(int val, int base, int bit) + { + return (temp_command_optional[6] & ~(base << bit)) | (val << bit); + } + + uint8_t PanasonicCommand::setDemandControl(unsigned int input) + { + switch (input) + { + case 0: return 0xEB; + case 1: return 0xB8; + case 2: return 0x85; + case 3: return 0x52; + case 4: return 0x2B; + } + return 0; + } + + std::string PanasonicCommand::toHexString(std::vector &data) + { + char cmdArr[400]; + + //ESP_LOGD("custom", "############ CMD: %s", to_hex_string(vec, REQUEST_DATA_SIZE)); + for (int i = 0; i < 10; i++) + { + if (i == 0) sprintf(cmdArr, "0x"); + if (i > 0) sprintf(cmdArr, "%s-", cmdArr); + sprintf(cmdArr, "%s-%02X", cmdArr, data[i]); + } + std::string cmdStr = cmdArr; + return cmdStr; + } + } // namespace panasonic_heatpump +} // namespace esphome \ No newline at end of file diff --git a/components/panasonic_heatpump/commands.h b/components/panasonic_heatpump/commands.h new file mode 100644 index 0000000..5ddf30f --- /dev/null +++ b/components/panasonic_heatpump/commands.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace esphome +{ + namespace panasonic_heatpump + { + class PanasonicCommand + { + public: + PanasonicCommand() = delete; + + static std::vector setCommand(uint8_t index, uint8_t newValue); + static std::vector setOptionalCommand(uint8_t index, uint8_t newValue); + static uint8_t calcChecksum(uint8_t *command, int length); + static uint8_t setMultiply2(unsigned int input); + static uint8_t setMultiply4(unsigned int input); + static uint8_t setPlus1Multiply4(unsigned int input); + static uint8_t setPlus1Multiply8(unsigned int input); + static uint8_t setPlus1Multiply16(unsigned int input); + static uint8_t setPlus1Multiply64(unsigned int input); + static uint8_t setPlus1(unsigned int input); + static uint8_t setPlus73(unsigned int input); + static uint8_t setPlus128(unsigned int input); + static uint8_t setOperationMode(unsigned int input); + static uint8_t setBivalentMode(unsigned int input); + static uint8_t temp2hex(float temp); + static uint8_t setByte6(int val, int base, int bit); + static uint8_t setDemandControl(unsigned int input); + static std::string toHexString(std::vector &data); + }; + } // namespace panasonic_heatpump +} // namespace esphome diff --git a/components/panasonic_heatpump/decode.cpp b/components/panasonic_heatpump/decode.cpp index 056d69a..7eec6a1 100644 --- a/components/panasonic_heatpump/decode.cpp +++ b/components/panasonic_heatpump/decode.cpp @@ -1,314 +1,320 @@ #include "decode.h" -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::OpModeDesc[]; -constexpr const char* const PanasonicDecode::Powerfulmode[]; -constexpr const char* const PanasonicDecode::Quietmode[]; -constexpr const char* const PanasonicDecode::Valve[]; -constexpr const char* const PanasonicDecode::MixingValve[]; -constexpr const char* const PanasonicDecode::ZonesState[]; -constexpr const char* const PanasonicDecode::HeatCoolModeDesc[]; -constexpr const char* const PanasonicDecode::SolarModeDesc[]; -constexpr const char* const PanasonicDecode::ZonesSensorType[]; -constexpr const char* const PanasonicDecode::LiquidType[]; -constexpr const char* const PanasonicDecode::ExtPadHeaterType[]; -constexpr const char* const PanasonicDecode::Bivalent[]; -constexpr const char* const PanasonicDecode::ModelNames[]; - -// stores the bytes #129 to #138 of known models in the same order as the ModelNames above -static const uint8_t KnownModels[NUMBER_OF_MODELS][10] = +namespace esphome { - 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 -}; - -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::getLeft5bits(uint8_t input) -{ - return ((input >> 3) - 1); -} - -int PanasonicDecode::getRight3bits(uint8_t input) -{ - return ((input & 0b111) - 1); -} - -int PanasonicDecode::getIntMinus1(uint8_t input) -{ - int value = (int)input - 1; - return value; -} - -int PanasonicDecode::getIntMinus128(uint8_t input) -{ - int value = (int)input - 128; - return value; -} - -float PanasonicDecode::getIntMinus1Div5(uint8_t input) -{ - return ((((float)input - 1) / 5), 1); -} - -float PanasonicDecode::getIntMinus1Div50(uint8_t input) -{ - return ((((float)input - 1) / 50), 2); -} - -int PanasonicDecode::getIntMinus1Times10(uint8_t input) -{ - int value = (int)input - 1; - return (value * 10); -} - -int PanasonicDecode::getIntMinus1Times50(uint8_t input) -{ - int value = (int)input - 1; - return (value * 50); -} - -int PanasonicDecode::getFirstByte(uint8_t input) -{ - return ((input >> 4) - 1); -} - -int PanasonicDecode::getSecondByte(uint8_t input) -{ - return ((input & 0b1111) - 1); -} - -int PanasonicDecode::getWord(uint8_t low, uint8_t hi) -{ - return ((hi << 8) + low) - 1; -} - -int PanasonicDecode::getUintt16(uint8_t input1, uint8_t input2) -{ - uint16_t value = static_cast((input2 << 8) | input1); - return (value - 1); -} - -// TOP15, TOP16, TOP38, TOP39, TOP40, TOP41 // -int PanasonicDecode::getPower(uint8_t input) -{ - int value = ((int)input - 1) * 200; - return value; -} - -// TOP4 // -int PanasonicDecode::getOpMode(uint8_t input) -{ - switch ((int)(input & 0b111111)) + namespace panasonic_heatpump { - case 18: - return 0; - case 19: - return 1; - case 25: - return 2; - case 33: - return 3; - case 34: - return 4; - case 35: - return 5; - case 41: - return 6; - case 26: - return 7; - case 42: - return 8; - default: - return -1; - } -} + 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::OpModeDesc[]; + constexpr const char* const PanasonicDecode::Powerfulmode[]; + constexpr const char* const PanasonicDecode::Quietmode[]; + constexpr const char* const PanasonicDecode::Valve[]; + constexpr const char* const PanasonicDecode::MixingValve[]; + constexpr const char* const PanasonicDecode::ZonesState[]; + constexpr const char* const PanasonicDecode::HeatCoolModeDesc[]; + constexpr const char* const PanasonicDecode::SolarModeDesc[]; + constexpr const char* const PanasonicDecode::ZonesSensorType[]; + constexpr const char* const PanasonicDecode::LiquidType[]; + constexpr const char* const PanasonicDecode::ExtPadHeaterType[]; + constexpr const char* const PanasonicDecode::Bivalent[]; + constexpr const char* const PanasonicDecode::ModelNames[]; -// TOP124 // -int PanasonicDecode::getBivalent(uint8_t input) -{ - switch ((int)input) - { - case 0x55: - return 0; - case 0x56: - return 1; - case 0x57: - return 2; - case 0x58: - return 3; - case 0x59: - return 4; - case 0x5A: - return 5; - default: - return -1; - } -} - -// TOP92 // -int PanasonicDecode::getModel(std::vector& data, uint8_t index) -{ - int result = -1; - 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] - }; - - for (size_t i = 0 ; i < NUMBER_OF_MODELS; i++) - { - if (memcmp(model, KnownModels[i], 10) == 0) + // stores the bytes #129 to #138 of known models in the same order as the ModelNames above + static const uint8_t KnownModels[NUMBER_OF_MODELS][10] = { - result = i; - break; + 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 + }; + + int PanasonicDecode::getBit1(uint8_t input) + { + return (input >> 7); } - } - return result; -} + int PanasonicDecode::getBit1and2(uint8_t input) + { + return ((input >> 6) - 1); + } -// TOP1 // -// input1 = data[169] -// input2 = data[170] -float PanasonicDecode::getPumpFlow(uint8_t input1, uint8_t input2) -{ - int PumpFlow2 = (int)input2; - float PumpFlow1 = (((float)input1 - 1) / 256); - float PumpFlow = PumpFlow2 + PumpFlow1; - return PumpFlow; -} + int PanasonicDecode::getBit3and4(uint8_t input) + { + return (((input >> 4) & 0b11) - 1); + } -// TOP5, TOP6 // -float PanasonicDecode::getFractional(uint8_t input, uint8_t shift) -{ - float result; - int fractional = (int)((input >> shift) & 0b111) - 1; - result = fractional * 0.25; - return result; -} + int PanasonicDecode::getBit5and6(uint8_t input) + { + return (((input >> 2) & 0b11) - 1); + } -// 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]; + int PanasonicDecode::getBit7and8(uint8_t input) + { + return ((input & 0b11) - 1); + } - 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; - } + int PanasonicDecode::getBit3and4and5(uint8_t input) + { + return (((input >> 3) & 0b111) - 1); + } - return error_string; -} + int PanasonicDecode::getLeft5bits(uint8_t input) + { + return ((input >> 3) - 1); + } -bool PanasonicDecode::getBoolState(uint8_t input) -{ - return input != 0; -} + int PanasonicDecode::getRight3bits(uint8_t input) + { + return ((input & 0b111) - 1); + } -std::string PanasonicDecode::getTextState(const char* const array[], int index) -{ - int size = atoi(array[0]); + int PanasonicDecode::getIntMinus1(uint8_t input) + { + int value = (int)input - 1; + return value; + } - if ((index < 0) || (index >= size)) - { - return "UNKNOWN"; - } + int PanasonicDecode::getIntMinus128(uint8_t input) + { + int value = (int)input - 128; + return value; + } - return array[index + 1]; -} + float PanasonicDecode::getIntMinus1Div5(uint8_t input) + { + return ((((float)input - 1) / 5), 1); + } + + float PanasonicDecode::getIntMinus1Div50(uint8_t input) + { + return ((((float)input - 1) / 50), 2); + } + + int PanasonicDecode::getIntMinus1Times10(uint8_t input) + { + int value = (int)input - 1; + return (value * 10); + } + + int PanasonicDecode::getIntMinus1Times50(uint8_t input) + { + int value = (int)input - 1; + return (value * 50); + } + + int PanasonicDecode::getFirstByte(uint8_t input) + { + return ((input >> 4) - 1); + } + + int PanasonicDecode::getSecondByte(uint8_t input) + { + return ((input & 0b1111) - 1); + } + + int PanasonicDecode::getWord(uint8_t low, uint8_t hi) + { + return ((hi << 8) + low) - 1; + } + + int PanasonicDecode::getUintt16(uint8_t input1, uint8_t input2) + { + uint16_t value = static_cast((input2 << 8) | input1); + return (value - 1); + } + + // TOP15, TOP16, TOP38, TOP39, TOP40, TOP41 // + int PanasonicDecode::getPower(uint8_t input) + { + int value = ((int)input - 1) * 200; + return value; + } + + // TOP4 // + int PanasonicDecode::getOpMode(uint8_t input) + { + switch ((int)(input & 0b111111)) + { + case 18: + return 0; + case 19: + return 1; + case 25: + return 2; + case 33: + return 3; + case 34: + return 4; + case 35: + return 5; + case 41: + return 6; + case 26: + return 7; + case 42: + return 8; + default: + return -1; + } + } + + // TOP124 // + int PanasonicDecode::getBivalent(uint8_t input) + { + switch ((int)input) + { + case 0x55: + return 0; + case 0x56: + return 1; + case 0x57: + return 2; + case 0x58: + return 3; + case 0x59: + return 4; + case 0x5A: + return 5; + default: + return -1; + } + } + + // TOP92 // + int PanasonicDecode::getModel(std::vector& data, uint8_t index) + { + int result = -1; + 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] + }; + + for (size_t i = 0 ; i < NUMBER_OF_MODELS; i++) + { + if (memcmp(model, KnownModels[i], 10) == 0) + { + result = i; + break; + } + } + + return result; + } + + // TOP1 // + // input1 = data[169] + // input2 = data[170] + float PanasonicDecode::getPumpFlow(uint8_t input1, uint8_t input2) + { + int PumpFlow2 = (int)input2; + float PumpFlow1 = (((float)input1 - 1) / 256); + float PumpFlow = PumpFlow2 + PumpFlow1; + return PumpFlow; + } + + // TOP5, TOP6 // + float PanasonicDecode::getFractional(uint8_t input, uint8_t shift) + { + float result; + int fractional = (int)((input >> shift) & 0b111) - 1; + result = fractional * 0.25; + return result; + } + + // 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 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; + } + + bool PanasonicDecode::getBoolState(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 "UNKNOWN"; + } + + return array[index + 1]; + } + } // namespace panasonic_heatpump +} // namespace esphome diff --git a/components/panasonic_heatpump/decode.h b/components/panasonic_heatpump/decode.h index ff21545..80131da 100644 --- a/components/panasonic_heatpump/decode.h +++ b/components/panasonic_heatpump/decode.h @@ -6,119 +6,120 @@ #include #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 -class PanasonicDecode +namespace esphome { -public: - PanasonicDecode() = delete; - - static int getBit1(uint8_t input); - static int getBit1and2(uint8_t input); - static int getBit3and4(uint8_t input); - static int getBit5and6(uint8_t input); - static int getBit7and8(uint8_t input); - static int getBit3and4and5(uint8_t input); - static int getLeft5bits(uint8_t input); - static int getRight3bits(uint8_t input); - static int getIntMinus1(uint8_t input); - static int getIntMinus128(uint8_t input); - static float getIntMinus1Div5(uint8_t input); - static float getIntMinus1Div50(uint8_t input); - static int getIntMinus1Times10(uint8_t input); - static int getIntMinus1Times50(uint8_t input); - static int getFirstByte(uint8_t input); - static int getSecondByte(uint8_t input); - static int getWord(uint8_t hi, uint8_t low); - static int getUintt16(uint8_t input1, uint8_t input2); - - static int getPower(uint8_t input); - static int getOpMode(uint8_t input); - static int getModel(std::vector& data, uint8_t index); - static int getBivalent(uint8_t input); - static float getPumpFlow(uint8_t input1, uint8_t input2); - static float getFractional(uint8_t input, uint8_t shift); - static std::string getErrorInfo(uint8_t errorType, uint8_t errorNumber); - - static bool getBoolState(uint8_t input); - static std::string getTextState(const char* const array[], int index); - - - static const constexpr char* const DisabledEnabled[] = {"2", "Disabled", "Enabled"}; - static const constexpr char* const BlockedFree[] = {"2", "Blocked", "Free"}; - static const constexpr char* const OffOn[] = {"2", "Off", "On"}; - static const constexpr char* const InactiveActive[] = {"2", "Inactive", "Active"}; - static const constexpr char* const PumpFlowRateMode[] = {"2", "DeltaT", "Max flow"}; - static const constexpr char* const HolidayState[] = {"3", "Off", "Scheduled", "Active"}; - static const constexpr char* const OpModeDesc[] = {"9", "Heat", "Cool", "Auto(heat)", "DHW", "Heat+DHW", "Cool+DHW", "Auto(heat)+DHW", "Auto(cool)", "Auto(cool)+DHW"}; - static const constexpr char* const Powerfulmode[] = {"4", "Off", "30min", "60min", "90min"}; - static const constexpr char* const Quietmode[] = {"4", "Off", "Level 1", "Level 2", "Level 3"}; - static const constexpr char* const Valve[] = {"2", "Room", "DHW"}; - static const constexpr char* const MixingValve[] = {"4", "Off", "Increase","Nothing","Decrease"}; - static const constexpr char* const ZonesState[] = {"3", "Zone1 active", "Zone2 active", "Zone1 and zone2 active"}; - static const constexpr char* const HeatCoolModeDesc[] = {"2", "Comp. Curve", "Direct"}; - static const constexpr char* const SolarModeDesc[] = {"3", "Disabled", "Buffer", "DHW"}; - static const constexpr char* const ZonesSensorType[] = {"4", "Water Temperature", "External Thermostat", "Internal Thermostat", "Thermistor"}; - static const constexpr char* const LiquidType[] = {"2", "Water", "Glycol"}; - static const constexpr char* const ExtPadHeaterType[] = {"3", "Disabled", "Type-A","Type-B"}; - static const constexpr char* const Bivalent[] = {"6", "Off", "Alternativ", "A-Off", "Parallel", "P-Off", "Parallel Advanced"}; - static const constexpr char* const ModelNames[] = + namespace panasonic_heatpump { - "51", //string representation of number of known models (last model number + 1) - "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 - }; -}; + class PanasonicDecode + { + public: + PanasonicDecode() = delete; + + static int getBit1(uint8_t input); + static int getBit1and2(uint8_t input); + static int getBit3and4(uint8_t input); + static int getBit5and6(uint8_t input); + static int getBit7and8(uint8_t input); + static int getBit3and4and5(uint8_t input); + static int getLeft5bits(uint8_t input); + static int getRight3bits(uint8_t input); + static int getIntMinus1(uint8_t input); + static int getIntMinus128(uint8_t input); + static float getIntMinus1Div5(uint8_t input); + static float getIntMinus1Div50(uint8_t input); + static int getIntMinus1Times10(uint8_t input); + static int getIntMinus1Times50(uint8_t input); + static int getFirstByte(uint8_t input); + static int getSecondByte(uint8_t input); + static int getWord(uint8_t hi, uint8_t low); + static int getUintt16(uint8_t input1, uint8_t input2); + + static int getPower(uint8_t input); + static int getOpMode(uint8_t input); + static int getModel(std::vector& data, uint8_t index); + static int getBivalent(uint8_t input); + static float getPumpFlow(uint8_t input1, uint8_t input2); + static float getFractional(uint8_t input, uint8_t shift); + static std::string getErrorInfo(uint8_t errorType, uint8_t errorNumber); + + static bool getBoolState(uint8_t input); + static std::string getTextState(const char* const array[], int index); + + static const constexpr char* const DisabledEnabled[] = {"2", "Disabled", "Enabled"}; + static const constexpr char* const BlockedFree[] = {"2", "Blocked", "Free"}; + static const constexpr char* const OffOn[] = {"2", "Off", "On"}; + static const constexpr char* const InactiveActive[] = {"2", "Inactive", "Active"}; + static const constexpr char* const PumpFlowRateMode[] = {"2", "DeltaT", "Max flow"}; + static const constexpr char* const HolidayState[] = {"3", "Off", "Scheduled", "Active"}; + static const constexpr char* const OpModeDesc[] = {"9", "Heat", "Cool", "Auto(heat)", "DHW", "Heat+DHW", "Cool+DHW", "Auto(heat)+DHW", "Auto(cool)", "Auto(cool)+DHW"}; + static const constexpr char* const Powerfulmode[] = {"4", "Off", "30min", "60min", "90min"}; + static const constexpr char* const Quietmode[] = {"4", "Off", "Level 1", "Level 2", "Level 3"}; + static const constexpr char* const Valve[] = {"2", "Room", "DHW"}; + static const constexpr char* const MixingValve[] = {"4", "Off", "Increase","Nothing","Decrease"}; + static const constexpr char* const ZonesState[] = {"3", "Zone1 active", "Zone2 active", "Zone1 and zone2 active"}; + static const constexpr char* const HeatCoolModeDesc[] = {"2", "Comp. Curve", "Direct"}; + static const constexpr char* const SolarModeDesc[] = {"3", "Disabled", "Buffer", "DHW"}; + static const constexpr char* const ZonesSensorType[] = {"4", "Water Temperature", "External Thermostat", "Internal Thermostat", "Thermistor"}; + static const constexpr char* const LiquidType[] = {"2", "Water", "Glycol"}; + static const constexpr char* const ExtPadHeaterType[] = {"3", "Disabled", "Type-A","Type-B"}; + static const constexpr char* const Bivalent[] = {"6", "Off", "Alternativ", "A-Off", "Parallel", "P-Off", "Parallel Advanced"}; + static const constexpr char* const ModelNames[] = + { + "51", //string representation of number of known models (last model number + 1) + "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 + }; + }; + } // namespace panasonic_heatpump +} // namespace esphome