diff --git a/lib/Hoymiles/src/Hoymiles.cpp b/lib/Hoymiles/src/Hoymiles.cpp index 32074e8..5867527 100644 --- a/lib/Hoymiles/src/Hoymiles.cpp +++ b/lib/Hoymiles/src/Hoymiles.cpp @@ -6,6 +6,9 @@ #include "inverters/HM_1CH.h" #include "inverters/HM_2CH.h" #include "inverters/HM_4CH.h" +#include "inverters/HMS_1CH.h" +#include "inverters/HMS_2CH.h" +#include "inverters/HMS_4CH.h" #include #define HOY_SEMAPHORE_TAKE() xSemaphoreTake(_xSemaphore, portMAX_DELAY) @@ -85,7 +88,13 @@ void HoymilesClass::loop() std::shared_ptr HoymilesClass::addInverter(const char* name, uint64_t serial) { std::shared_ptr i = nullptr; - if (HM_4CH::isValidSerial(serial)) { + if (HMS_4CH::isValidSerial(serial)) { + i = std::make_shared(serial); + } else if (HMS_2CH::isValidSerial(serial)) { + i = std::make_shared(serial); + } else if (HMS_1CH::isValidSerial(serial)) { + i = std::make_shared(serial); + } else if (HM_4CH::isValidSerial(serial)) { i = std::make_shared(serial); } else if (HM_2CH::isValidSerial(serial)) { i = std::make_shared(serial); diff --git a/lib/Hoymiles/src/HoymilesRadio.h b/lib/Hoymiles/src/HoymilesRadio.h index 6963361..e80975c 100644 --- a/lib/Hoymiles/src/HoymilesRadio.h +++ b/lib/Hoymiles/src/HoymilesRadio.h @@ -8,6 +8,7 @@ #include #include #include +#include // number of fragments hold in buffer #define FRAGMENT_BUFFER_SIZE 30 diff --git a/lib/Hoymiles/src/inverters/HMS_1CH.cpp b/lib/Hoymiles/src/inverters/HMS_1CH.cpp new file mode 100644 index 0000000..a4e05c9 --- /dev/null +++ b/lib/Hoymiles/src/inverters/HMS_1CH.cpp @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2023 Thomas Basler and others + */ +#include "HMS_1CH.h" + +HMS_1CH::HMS_1CH(uint64_t serial) + : HMS_Abstract(serial) {}; + +bool HMS_1CH::isValidSerial(uint64_t serial) +{ + // serial >= 0x112400000000 && serial <= 0x112499999999 + uint16_t preSerial = (serial >> 32) & 0xffff; + return preSerial == 0x1124; +} + +String HMS_1CH::typeName() +{ + return "HMS-300, HMS-350, HMS-400, HMS-450, HMS-500"; +} + +const std::list* HMS_1CH::getByteAssignment() +{ + return &byteAssignment; +} \ No newline at end of file diff --git a/lib/Hoymiles/src/inverters/HMS_1CH.h b/lib/Hoymiles/src/inverters/HMS_1CH.h new file mode 100644 index 0000000..8db300c --- /dev/null +++ b/lib/Hoymiles/src/inverters/HMS_1CH.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +#include "HMS_Abstract.h" +#include + +class HMS_1CH : public HMS_Abstract { +public: + explicit HMS_1CH(uint64_t serial); + static bool isValidSerial(uint64_t serial); + String typeName(); + const std::list* getByteAssignment(); + +private: + const std::list byteAssignment = { + { TYPE_DC, CH0, FLD_UDC, UNIT_V, 2, 2, 10, false, 1 }, + { TYPE_DC, CH0, FLD_IDC, UNIT_A, 4, 2, 100, false, 2 }, + { TYPE_DC, CH0, FLD_PDC, UNIT_W, 6, 2, 10, false, 1 }, + { TYPE_DC, CH0, FLD_YD, UNIT_WH, 12, 2, 1, false, 0 }, + { TYPE_DC, CH0, FLD_YT, UNIT_KWH, 8, 4, 1000, false, 3 }, + { TYPE_DC, CH0, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH0, CMD_CALC, false, 3 }, + + { TYPE_AC, CH0, FLD_UAC, UNIT_V, 14, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_IAC, UNIT_A, 22, 2, 100, false, 2 }, + { TYPE_AC, CH0, FLD_PAC, UNIT_W, 18, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_PRA, UNIT_VA, 20, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_F, UNIT_HZ, 16, 2, 100, false, 2 }, + { TYPE_AC, CH0, FLD_PF, UNIT_NONE, 24, 2, 1000, false, 3 }, + + { TYPE_INV, CH0, FLD_T, UNIT_C, 26, 2, 10, true, 1 }, + { TYPE_INV, CH0, FLD_EVT_LOG, UNIT_NONE, 28, 2, 1, false, 0 }, + + { TYPE_AC, CH0, FLD_YD, UNIT_WH, CALC_YD_CH0, 0, CMD_CALC, false, 0 }, + { TYPE_AC, CH0, FLD_YT, UNIT_KWH, CALC_YT_CH0, 0, CMD_CALC, false, 3 }, + { TYPE_AC, CH0, FLD_PDC, UNIT_W, CALC_PDC_CH0, 0, CMD_CALC, false, 1 }, + { TYPE_AC, CH0, FLD_EFF, UNIT_PCT, CALC_EFF_CH0, 0, CMD_CALC, false, 3 } + }; +}; \ No newline at end of file diff --git a/lib/Hoymiles/src/inverters/HMS_2CH.cpp b/lib/Hoymiles/src/inverters/HMS_2CH.cpp new file mode 100644 index 0000000..a3ee7ce --- /dev/null +++ b/lib/Hoymiles/src/inverters/HMS_2CH.cpp @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2023 Thomas Basler and others + */ +#include "HMS_2CH.h" + +HMS_2CH::HMS_2CH(uint64_t serial) + : HMS_Abstract(serial) {}; + +bool HMS_2CH::isValidSerial(uint64_t serial) +{ + // serial >= 0x114400000000 && serial <= 0x114499999999 + uint16_t preSerial = (serial >> 32) & 0xffff; + return preSerial == 0x1144; +} + +String HMS_2CH::typeName() +{ + return "HMS-600, HMS-700, HMS-800, HMS-900, HMS-1000"; +} + +const std::list* HMS_2CH::getByteAssignment() +{ + return &byteAssignment; +} \ No newline at end of file diff --git a/lib/Hoymiles/src/inverters/HMS_2CH.h b/lib/Hoymiles/src/inverters/HMS_2CH.h new file mode 100644 index 0000000..1815a68 --- /dev/null +++ b/lib/Hoymiles/src/inverters/HMS_2CH.h @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +#include "HMS_Abstract.h" +#include + +class HMS_2CH : public HMS_Abstract { +public: + explicit HMS_2CH(uint64_t serial); + static bool isValidSerial(uint64_t serial); + String typeName(); + const std::list* getByteAssignment(); + +private: + const std::list byteAssignment = { + { TYPE_DC, CH0, FLD_UDC, UNIT_V, 2, 2, 10, false, 1 }, + { TYPE_DC, CH0, FLD_IDC, UNIT_A, 6, 2, 100, false, 2 }, + { TYPE_DC, CH0, FLD_PDC, UNIT_W, 10, 2, 10, false, 1 }, + { TYPE_DC, CH0, FLD_YT, UNIT_KWH, 14, 4, 1000, false, 3 }, + { TYPE_DC, CH0, FLD_YD, UNIT_WH, 22, 2, 1, false, 0 }, + { TYPE_DC, CH0, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH0, CMD_CALC, false, 3 }, + + { TYPE_DC, CH1, FLD_UDC, UNIT_V, 4, 2, 10, false, 1 }, + { TYPE_DC, CH1, FLD_IDC, UNIT_A, 8, 2, 100, false, 2 }, + { TYPE_DC, CH1, FLD_PDC, UNIT_W, 12, 2, 10, false, 1 }, + { TYPE_DC, CH1, FLD_YT, UNIT_KWH, 18, 4, 1000, false, 3 }, + { TYPE_DC, CH1, FLD_YD, UNIT_WH, 24, 2, 1, false, 0 }, + { TYPE_DC, CH1, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH1, CMD_CALC, false, 3 }, + + { TYPE_AC, CH0, FLD_UAC, UNIT_V, 26, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_IAC, UNIT_A, 34, 2, 100, false, 2 }, + { TYPE_AC, CH0, FLD_PAC, UNIT_W, 30, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_PRA, UNIT_VA, 32, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_F, UNIT_HZ, 28, 2, 100, false, 2 }, + { TYPE_AC, CH0, FLD_PF, UNIT_NONE, 36, 2, 1000, false, 3 }, + + { TYPE_INV, CH0, FLD_T, UNIT_C, 38, 2, 10, true, 1 }, + { TYPE_INV, CH0, FLD_EVT_LOG, UNIT_NONE, 40, 2, 1, false, 0 }, + + { TYPE_AC, CH0, FLD_YD, UNIT_WH, CALC_YD_CH0, 0, CMD_CALC, false, 0 }, + { TYPE_AC, CH0, FLD_YT, UNIT_KWH, CALC_YT_CH0, 0, CMD_CALC, false, 3 }, + { TYPE_AC, CH0, FLD_PDC, UNIT_W, CALC_PDC_CH0, 0, CMD_CALC, false, 1 }, + { TYPE_AC, CH0, FLD_EFF, UNIT_PCT, CALC_EFF_CH0, 0, CMD_CALC, false, 3 } + }; +}; \ No newline at end of file diff --git a/lib/Hoymiles/src/inverters/HMS_4CH.cpp b/lib/Hoymiles/src/inverters/HMS_4CH.cpp new file mode 100644 index 0000000..c9f01f2 --- /dev/null +++ b/lib/Hoymiles/src/inverters/HMS_4CH.cpp @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2023 Thomas Basler and others + */ +#include "HMS_4CH.h" + +HMS_4CH::HMS_4CH(uint64_t serial) + : HMS_Abstract(serial) {}; + +bool HMS_4CH::isValidSerial(uint64_t serial) +{ + // serial >= 0x114400000000 && serial <= 0x114499999999 + uint16_t preSerial = (serial >> 32) & 0xffff; + return preSerial == 0x1164; +} + +String HMS_4CH::typeName() +{ + return "HMS-1600, HMS-1800, HMS-2000"; +} + +const std::list* HMS_4CH::getByteAssignment() +{ + return &byteAssignment; +} \ No newline at end of file diff --git a/lib/Hoymiles/src/inverters/HMS_4CH.h b/lib/Hoymiles/src/inverters/HMS_4CH.h new file mode 100644 index 0000000..f7e9bce --- /dev/null +++ b/lib/Hoymiles/src/inverters/HMS_4CH.h @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +#include "HMS_Abstract.h" + +class HMS_4CH : public HMS_Abstract { +public: + explicit HMS_4CH(uint64_t serial); + static bool isValidSerial(uint64_t serial); + String typeName(); + const std::list* getByteAssignment(); + +private: + const std::list byteAssignment = { + { TYPE_DC, CH0, FLD_UDC, UNIT_V, 2, 2, 10, false, 1 }, + { TYPE_DC, CH0, FLD_IDC, UNIT_A, 6, 2, 100, false, 2 }, + { TYPE_DC, CH0, FLD_PDC, UNIT_W, 10, 2, 10, false, 1 }, + { TYPE_DC, CH0, FLD_YD, UNIT_WH, 22, 2, 1, false, 0 }, + { TYPE_DC, CH0, FLD_YT, UNIT_KWH, 14, 4, 1000, false, 3 }, + { TYPE_DC, CH0, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH0, CMD_CALC, false, 3 }, + + { TYPE_DC, CH1, FLD_UDC, UNIT_V, 4, 2, 10, false, 1 }, + { TYPE_DC, CH1, FLD_IDC, UNIT_A, 8, 2, 100, false, 2 }, + { TYPE_DC, CH1, FLD_PDC, UNIT_W, 12, 2, 10, false, 1 }, + { TYPE_DC, CH1, FLD_YD, UNIT_WH, 24, 2, 1, false, 0 }, + { TYPE_DC, CH1, FLD_YT, UNIT_KWH, 18, 4, 1000, false, 3 }, + { TYPE_DC, CH1, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH1, CMD_CALC, false, 3 }, + + { TYPE_DC, CH2, FLD_UDC, UNIT_V, 26, 2, 10, false, 1 }, + { TYPE_DC, CH2, FLD_IDC, UNIT_A, 30, 2, 100, false, 2 }, + { TYPE_DC, CH2, FLD_PDC, UNIT_W, 34, 2, 10, false, 1 }, + { TYPE_DC, CH2, FLD_YD, UNIT_WH, 46, 2, 1, false, 0 }, + { TYPE_DC, CH2, FLD_YT, UNIT_KWH, 38, 4, 1000, false, 3 }, + { TYPE_DC, CH2, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH2, CMD_CALC, false, 3 }, + + { TYPE_DC, CH3, FLD_UDC, UNIT_V, 28, 2, 10, false, 1 }, + { TYPE_DC, CH3, FLD_IDC, UNIT_A, 32, 2, 100, false, 2 }, + { TYPE_DC, CH3, FLD_PDC, UNIT_W, 36, 2, 10, false, 1 }, + { TYPE_DC, CH3, FLD_YD, UNIT_WH, 48, 2, 1, false, 0 }, + { TYPE_DC, CH3, FLD_YT, UNIT_KWH, 42, 4, 1000, false, 3 }, + { TYPE_DC, CH3, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH3, CMD_CALC, false, 3 }, + + { TYPE_AC, CH0, FLD_UAC, UNIT_V, 50, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_IAC, UNIT_A, 58, 2, 100, false, 2 }, + { TYPE_AC, CH0, FLD_PAC, UNIT_W, 54, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_PRA, UNIT_VA, 56, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_F, UNIT_HZ, 52, 2, 100, false, 2 }, + { TYPE_AC, CH0, FLD_PF, UNIT_NONE, 60, 2, 1000, false, 3 }, + + { TYPE_INV, CH0, FLD_T, UNIT_C, 62, 2, 10, true, 1 }, + { TYPE_INV, CH0, FLD_EVT_LOG, UNIT_NONE, 64, 2, 1, false, 0 }, + + { TYPE_AC, CH0, FLD_YD, UNIT_WH, CALC_YD_CH0, 0, CMD_CALC, false, 0 }, + { TYPE_AC, CH0, FLD_YT, UNIT_KWH, CALC_YT_CH0, 0, CMD_CALC, false, 3 }, + { TYPE_AC, CH0, FLD_PDC, UNIT_W, CALC_PDC_CH0, 0, CMD_CALC, false, 1 }, + { TYPE_AC, CH0, FLD_EFF, UNIT_PCT, CALC_EFF_CH0, 0, CMD_CALC, false, 3 } + }; +}; \ No newline at end of file diff --git a/lib/Hoymiles/src/inverters/HMS_Abstract.cpp b/lib/Hoymiles/src/inverters/HMS_Abstract.cpp new file mode 100644 index 0000000..c0070a9 --- /dev/null +++ b/lib/Hoymiles/src/inverters/HMS_Abstract.cpp @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2023 Thomas Basler and others + */ +#include "HMS_Abstract.h" + +HMS_Abstract::HMS_Abstract(uint64_t serial) + : HM_Abstract(serial) {}; diff --git a/lib/Hoymiles/src/inverters/HMS_Abstract.h b/lib/Hoymiles/src/inverters/HMS_Abstract.h new file mode 100644 index 0000000..20bfa5f --- /dev/null +++ b/lib/Hoymiles/src/inverters/HMS_Abstract.h @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +#include "HM_Abstract.h" + +class HMS_Abstract : public HM_Abstract { +public: + explicit HMS_Abstract(uint64_t serial); +}; \ No newline at end of file