diff --git a/include/MqttHandleHass.h b/include/MqttHandleHass.h index 33d9df8..45d11cf 100644 --- a/include/MqttHandleHass.h +++ b/include/MqttHandleHass.h @@ -25,7 +25,7 @@ enum { const char* const stateClasses[] = { 0, "measurement", "total_increasing" }; typedef struct { - uint8_t fieldId; // field id + FieldId_t fieldId; // field id uint8_t deviceClsId; // device class uint8_t stateClsId; // state class } byteAssign_fieldDeviceClass_t; @@ -57,7 +57,7 @@ public: private: void publish(const String& subtopic, const String& payload); - void publishField(std::shared_ptr inv, uint8_t channel, byteAssign_fieldDeviceClass_t fieldType, bool clear = false); + void publishField(std::shared_ptr inv, ChannelType_t type, ChannelNum_t channel, byteAssign_fieldDeviceClass_t fieldType, bool clear = false); void publishInverterButton(std::shared_ptr inv, const char* caption, const char* icon, const char* category, const char* deviceClass, const char* subTopic, const char* payload); void publishInverterNumber(std::shared_ptr inv, const char* caption, const char* icon, const char* category, const char* commandTopic, const char* stateTopic, const char* unitOfMeasure, int16_t min = 1, int16_t max = 100); void publishInverterBinarySensor(std::shared_ptr inv, const char* caption, const char* subTopic, const char* payload_on, const char* payload_off); diff --git a/include/MqttHandleInverter.h b/include/MqttHandleInverter.h index a4e49ce..9df43cb 100644 --- a/include/MqttHandleInverter.h +++ b/include/MqttHandleInverter.h @@ -10,16 +10,16 @@ public: void init(); void loop(); - static String getTopic(std::shared_ptr inv, uint8_t channel, uint8_t fieldId); + static String getTopic(std::shared_ptr inv, ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId); private: - void publishField(std::shared_ptr inv, uint8_t channel, uint8_t fieldId); + void publishField(std::shared_ptr inv, ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId); void onMqttMessage(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total); uint32_t _lastPublishStats[INV_MAX_COUNT]; uint32_t _lastPublish; - uint8_t _publishFields[14] = { + FieldId_t _publishFields[14] = { FLD_UDC, FLD_IDC, FLD_PDC, diff --git a/include/WebApi_prometheus.h b/include/WebApi_prometheus.h index 60e8e10..ac2478a 100644 --- a/include/WebApi_prometheus.h +++ b/include/WebApi_prometheus.h @@ -12,7 +12,7 @@ public: private: void onPrometheusMetricsGet(AsyncWebServerRequest* request); - void addField(AsyncResponseStream* stream, String& serial, uint8_t idx, std::shared_ptr inv, uint8_t channel, uint8_t fieldId, const char* channelName = NULL); + void addField(AsyncResponseStream* stream, String& serial, uint8_t idx, std::shared_ptr inv, ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId, const char* channelName = NULL); AsyncWebServer* _server; }; \ No newline at end of file diff --git a/include/WebApi_ws_live.h b/include/WebApi_ws_live.h index 5da1864..0cf1449 100644 --- a/include/WebApi_ws_live.h +++ b/include/WebApi_ws_live.h @@ -13,7 +13,7 @@ public: private: void generateJsonResponse(JsonVariant& root); - void addField(JsonObject& root, uint8_t idx, std::shared_ptr inv, uint8_t channel, uint8_t fieldId, String topic = ""); + void addField(JsonObject& root, uint8_t idx, std::shared_ptr inv, ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId, String topic = ""); void addTotalField(JsonObject& root, String name, float value, String unit, uint8_t digits); void onLivedataStatus(AsyncWebServerRequest* request); void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len); diff --git a/lib/Hoymiles/src/inverters/HM_1CH.h b/lib/Hoymiles/src/inverters/HM_1CH.h index 7599b68..9418646 100644 --- a/lib/Hoymiles/src/inverters/HM_1CH.h +++ b/lib/Hoymiles/src/inverters/HM_1CH.h @@ -13,24 +13,26 @@ public: private: const std::list byteAssignment = { - { CH1, FLD_UDC, UNIT_V, 2, 2, 10, false, 1 }, - { CH1, FLD_IDC, UNIT_A, 4, 2, 100, false, 2 }, - { CH1, FLD_PDC, UNIT_W, 6, 2, 10, false, 1 }, - { CH1, FLD_YD, UNIT_WH, 12, 2, 1, false, 0 }, - { CH1, FLD_YT, UNIT_KWH, 8, 4, 1000, false, 3 }, - { CH1, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH1, CMD_CALC, false, 3 }, + { 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 }, - { CH0, FLD_UAC, UNIT_V, 14, 2, 10, false, 1 }, - { CH0, FLD_IAC, UNIT_A, 22, 2, 100, false, 2 }, - { CH0, FLD_PAC, UNIT_W, 18, 2, 10, false, 1 }, - { CH0, FLD_PRA, UNIT_VA, 20, 2, 10, false, 1 }, - { CH0, FLD_F, UNIT_HZ, 16, 2, 100, false, 2 }, - { CH0, FLD_PF, UNIT_NONE, 24, 2, 1000, false, 3 }, - { CH0, FLD_T, UNIT_C, 26, 2, 10, true, 1 }, - { CH0, FLD_EVT_LOG, UNIT_NONE, 28, 2, 1, false, 0 }, - { CH0, FLD_YD, UNIT_WH, CALC_YD_CH0, 0, CMD_CALC, false, 0 }, - { CH0, FLD_YT, UNIT_KWH, CALC_YT_CH0, 0, CMD_CALC, false, 3 }, - { CH0, FLD_PDC, UNIT_W, CALC_PDC_CH0, 0, CMD_CALC, false, 1 }, - { CH0, FLD_EFF, UNIT_PCT, CALC_EFF_CH0, 0, 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/HM_2CH.h b/lib/Hoymiles/src/inverters/HM_2CH.h index 5ff5c06..6e8672c 100644 --- a/lib/Hoymiles/src/inverters/HM_2CH.h +++ b/lib/Hoymiles/src/inverters/HM_2CH.h @@ -12,31 +12,33 @@ public: private: const std::list byteAssignment = { - { CH1, FLD_UDC, UNIT_V, 2, 2, 10, false, 1 }, - { CH1, FLD_IDC, UNIT_A, 4, 2, 100, false, 2 }, - { CH1, FLD_PDC, UNIT_W, 6, 2, 10, false, 1 }, - { CH1, FLD_YD, UNIT_WH, 22, 2, 1, false, 0 }, - { CH1, FLD_YT, UNIT_KWH, 14, 4, 1000, false, 3 }, - { CH1, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH1, CMD_CALC, false, 3 }, + { 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, 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 }, - { CH2, FLD_UDC, UNIT_V, 8, 2, 10, false, 1 }, - { CH2, FLD_IDC, UNIT_A, 10, 2, 100, false, 2 }, - { CH2, FLD_PDC, UNIT_W, 12, 2, 10, false, 1 }, - { CH2, FLD_YD, UNIT_WH, 24, 2, 1, false, 0 }, - { CH2, FLD_YT, UNIT_KWH, 18, 4, 1000, false, 3 }, - { CH2, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH2, CMD_CALC, false, 3 }, + { TYPE_DC, CH1, FLD_UDC, UNIT_V, 8, 2, 10, false, 1 }, + { TYPE_DC, CH1, FLD_IDC, UNIT_A, 10, 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 }, - { CH0, FLD_UAC, UNIT_V, 26, 2, 10, false, 1 }, - { CH0, FLD_IAC, UNIT_A, 34, 2, 100, false, 2 }, - { CH0, FLD_PAC, UNIT_W, 30, 2, 10, false, 1 }, - { CH0, FLD_PRA, UNIT_VA, 32, 2, 10, false, 1 }, - { CH0, FLD_F, UNIT_HZ, 28, 2, 100, false, 2 }, - { CH0, FLD_PF, UNIT_NONE, 36, 2, 1000, false, 3 }, - { CH0, FLD_T, UNIT_C, 38, 2, 10, true, 1 }, - { CH0, FLD_EVT_LOG, UNIT_NONE, 40, 2, 1, false, 0 }, - { CH0, FLD_YD, UNIT_WH, CALC_YD_CH0, 0, CMD_CALC, false, 0 }, - { CH0, FLD_YT, UNIT_KWH, CALC_YT_CH0, 0, CMD_CALC, false, 3 }, - { CH0, FLD_PDC, UNIT_W, CALC_PDC_CH0, 0, CMD_CALC, false, 1 }, - { CH0, FLD_EFF, UNIT_PCT, CALC_EFF_CH0, 0, 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/HM_4CH.h b/lib/Hoymiles/src/inverters/HM_4CH.h index 2a511c5..eccc60f 100644 --- a/lib/Hoymiles/src/inverters/HM_4CH.h +++ b/lib/Hoymiles/src/inverters/HM_4CH.h @@ -12,45 +12,47 @@ public: private: const std::list byteAssignment = { - { CH1, FLD_UDC, UNIT_V, 2, 2, 10, false, 1 }, - { CH1, FLD_IDC, UNIT_A, 4, 2, 100, false, 2 }, - { CH1, FLD_PDC, UNIT_W, 8, 2, 10, false, 1 }, - { CH1, FLD_YD, UNIT_WH, 20, 2, 1, false, 0 }, - { CH1, FLD_YT, UNIT_KWH, 12, 4, 1000, false, 3 }, - { CH1, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH1, CMD_CALC, false, 3 }, + { 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, 8, 2, 10, false, 1 }, + { TYPE_DC, CH0, FLD_YD, UNIT_WH, 20, 2, 1, false, 0 }, + { TYPE_DC, CH0, FLD_YT, UNIT_KWH, 12, 4, 1000, false, 3 }, + { TYPE_DC, CH0, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH0, CMD_CALC, false, 3 }, - { CH2, FLD_UDC, UNIT_V, CALC_UDC_CH, CH1, CMD_CALC, false, 1 }, - { CH2, FLD_IDC, UNIT_A, 6, 2, 100, false, 2 }, - { CH2, FLD_PDC, UNIT_W, 10, 2, 10, false, 1 }, - { CH2, FLD_YD, UNIT_WH, 22, 2, 1, false, 0 }, - { CH2, FLD_YT, UNIT_KWH, 16, 4, 1000, false, 3 }, - { CH2, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH2, CMD_CALC, false, 3 }, + { TYPE_DC, CH1, FLD_UDC, UNIT_V, CALC_UDC_CH, CH0, CMD_CALC, false, 1 }, + { TYPE_DC, CH1, FLD_IDC, UNIT_A, 6, 2, 100, false, 2 }, + { TYPE_DC, CH1, FLD_PDC, UNIT_W, 10, 2, 10, false, 1 }, + { TYPE_DC, CH1, FLD_YD, UNIT_WH, 22, 2, 1, false, 0 }, + { TYPE_DC, CH1, FLD_YT, UNIT_KWH, 16, 4, 1000, false, 3 }, + { TYPE_DC, CH1, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH1, CMD_CALC, false, 3 }, - { CH3, FLD_UDC, UNIT_V, 24, 2, 10, false, 1 }, - { CH3, FLD_IDC, UNIT_A, 26, 2, 100, false, 2 }, - { CH3, FLD_PDC, UNIT_W, 30, 2, 10, false, 1 }, - { CH3, FLD_YD, UNIT_WH, 42, 2, 1, false, 0 }, - { CH3, FLD_YT, UNIT_KWH, 34, 4, 1000, false, 3 }, - { CH3, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH3, CMD_CALC, false, 3 }, + { TYPE_DC, CH2, FLD_UDC, UNIT_V, 24, 2, 10, false, 1 }, + { TYPE_DC, CH2, FLD_IDC, UNIT_A, 26, 2, 100, false, 2 }, + { TYPE_DC, CH2, FLD_PDC, UNIT_W, 30, 2, 10, false, 1 }, + { TYPE_DC, CH2, FLD_YD, UNIT_WH, 42, 2, 1, false, 0 }, + { TYPE_DC, CH2, FLD_YT, UNIT_KWH, 34, 4, 1000, false, 3 }, + { TYPE_DC, CH2, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH2, CMD_CALC, false, 3 }, - { CH4, FLD_UDC, UNIT_V, CALC_UDC_CH, CH3, CMD_CALC, false, 1 }, - { CH4, FLD_IDC, UNIT_A, 28, 2, 100, false, 2 }, - { CH4, FLD_PDC, UNIT_W, 32, 2, 10, false, 1 }, - { CH4, FLD_YD, UNIT_WH, 44, 2, 1, false, 0 }, - { CH4, FLD_YT, UNIT_KWH, 38, 4, 1000, false, 3 }, - { CH4, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH4, CMD_CALC, false, 3 }, + { TYPE_DC, CH3, FLD_UDC, UNIT_V, CALC_UDC_CH, CH2, CMD_CALC, false, 1 }, + { TYPE_DC, CH3, FLD_IDC, UNIT_A, 28, 2, 100, false, 2 }, + { TYPE_DC, CH3, FLD_PDC, UNIT_W, 32, 2, 10, false, 1 }, + { TYPE_DC, CH3, FLD_YD, UNIT_WH, 44, 2, 1, false, 0 }, + { TYPE_DC, CH3, FLD_YT, UNIT_KWH, 38, 4, 1000, false, 3 }, + { TYPE_DC, CH3, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH3, CMD_CALC, false, 3 }, - { CH0, FLD_UAC, UNIT_V, 46, 2, 10, false, 1 }, - { CH0, FLD_IAC, UNIT_A, 54, 2, 100, false, 2 }, - { CH0, FLD_PAC, UNIT_W, 50, 2, 10, false, 1 }, - { CH0, FLD_PRA, UNIT_VA, 52, 2, 10, false, 1 }, - { CH0, FLD_F, UNIT_HZ, 48, 2, 100, false, 2 }, - { CH0, FLD_PF, UNIT_NONE, 56, 2, 1000, false, 3 }, - { CH0, FLD_T, UNIT_C, 58, 2, 10, true, 1 }, - { CH0, FLD_EVT_LOG, UNIT_NONE, 60, 2, 1, false, 0 }, - { CH0, FLD_YD, UNIT_WH, CALC_YD_CH0, 0, CMD_CALC, false, 0 }, - { CH0, FLD_YT, UNIT_KWH, CALC_YT_CH0, 0, CMD_CALC, false, 3 }, - { CH0, FLD_PDC, UNIT_W, CALC_PDC_CH0, 0, CMD_CALC, false, 1 }, - { CH0, FLD_EFF, UNIT_PCT, CALC_EFF_CH0, 0, CMD_CALC, false, 3 } + { TYPE_AC, CH0, FLD_UAC, UNIT_V, 46, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_IAC, UNIT_A, 54, 2, 100, false, 2 }, + { TYPE_AC, CH0, FLD_PAC, UNIT_W, 50, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_PRA, UNIT_VA, 52, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_F, UNIT_HZ, 48, 2, 100, false, 2 }, + { TYPE_AC, CH0, FLD_PF, UNIT_NONE, 56, 2, 1000, false, 3 }, + + { TYPE_INV, CH0, FLD_T, UNIT_C, 58, 2, 10, true, 1 }, + { TYPE_INV, CH0, FLD_EVT_LOG, UNIT_NONE, 60, 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/HM_Abstract.cpp b/lib/Hoymiles/src/inverters/HM_Abstract.cpp index 73e02ce..63db599 100644 --- a/lib/Hoymiles/src/inverters/HM_Abstract.cpp +++ b/lib/Hoymiles/src/inverters/HM_Abstract.cpp @@ -40,14 +40,14 @@ bool HM_Abstract::sendAlarmLogRequest(HoymilesRadio* radio, bool force) } if (!force) { - if (Statistics()->hasChannelFieldValue(CH0, FLD_EVT_LOG)) { - if ((uint8_t)Statistics()->getChannelFieldValue(CH0, FLD_EVT_LOG) == _lastAlarmLogCnt) { + if (Statistics()->hasChannelFieldValue(TYPE_INV, CH0, FLD_EVT_LOG)) { + if ((uint8_t)Statistics()->getChannelFieldValue(TYPE_INV, CH0, FLD_EVT_LOG) == _lastAlarmLogCnt) { return false; } } } - _lastAlarmLogCnt = (uint8_t)Statistics()->getChannelFieldValue(CH0, FLD_EVT_LOG); + _lastAlarmLogCnt = (uint8_t)Statistics()->getChannelFieldValue(TYPE_INV, CH0, FLD_EVT_LOG); time_t now; time(&now); diff --git a/lib/Hoymiles/src/inverters/InverterAbstract.cpp b/lib/Hoymiles/src/inverters/InverterAbstract.cpp index 8c0677b..c979847 100644 --- a/lib/Hoymiles/src/inverters/InverterAbstract.cpp +++ b/lib/Hoymiles/src/inverters/InverterAbstract.cpp @@ -60,11 +60,14 @@ const char* InverterAbstract::name() bool InverterAbstract::isProducing() { - if (!Statistics()->hasChannelFieldValue(CH0, FLD_PAC)) { - return false; + float totalAc = 0; + for (auto& c : Statistics()->getChannelsByType(TYPE_AC)) { + if (Statistics()->hasChannelFieldValue(TYPE_AC, c, FLD_PAC)) { + totalAc += Statistics()->getChannelFieldValue(TYPE_AC, c, FLD_PAC); + } } - return Statistics()->getChannelFieldValue(CH0, FLD_PAC) > 0; + return totalAc > 0; } bool InverterAbstract::isReachable() diff --git a/lib/Hoymiles/src/parser/StatisticsParser.cpp b/lib/Hoymiles/src/parser/StatisticsParser.cpp index 117ced3..cccf760 100644 --- a/lib/Hoymiles/src/parser/StatisticsParser.cpp +++ b/lib/Hoymiles/src/parser/StatisticsParser.cpp @@ -49,19 +49,19 @@ void StatisticsParser::appendFragment(uint8_t offset, uint8_t* payload, uint8_t _statisticLength += len; } -const byteAssign_t* StatisticsParser::getAssignmentByChannelField(uint8_t channel, uint8_t fieldId) +const byteAssign_t* StatisticsParser::getAssignmentByChannelField(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId) { for (auto const& i : *_byteAssignment) { - if (i.ch == channel && i.fieldId == fieldId) { + if (i.type == type && i.ch == channel && i.fieldId == fieldId) { return &i; } } return NULL; } -float StatisticsParser::getChannelFieldValue(uint8_t channel, uint8_t fieldId) +float StatisticsParser::getChannelFieldValue(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId) { - const byteAssign_t* pos = getAssignmentByChannelField(channel, fieldId); + const byteAssign_t* pos = getAssignmentByChannelField(type, channel, fieldId); if (pos == NULL) { return 0; } @@ -97,40 +97,54 @@ float StatisticsParser::getChannelFieldValue(uint8_t channel, uint8_t fieldId) return 0; } -bool StatisticsParser::hasChannelFieldValue(uint8_t channel, uint8_t fieldId) +bool StatisticsParser::hasChannelFieldValue(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId) { - const byteAssign_t* pos = getAssignmentByChannelField(channel, fieldId); + const byteAssign_t* pos = getAssignmentByChannelField(type, channel, fieldId); return pos != NULL; } -const char* StatisticsParser::getChannelFieldUnit(uint8_t channel, uint8_t fieldId) +const char* StatisticsParser::getChannelFieldUnit(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId) { - const byteAssign_t* pos = getAssignmentByChannelField(channel, fieldId); + const byteAssign_t* pos = getAssignmentByChannelField(type, channel, fieldId); return units[pos->unitId]; } -const char* StatisticsParser::getChannelFieldName(uint8_t channel, uint8_t fieldId) +const char* StatisticsParser::getChannelFieldName(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId) { - const byteAssign_t* pos = getAssignmentByChannelField(channel, fieldId); + const byteAssign_t* pos = getAssignmentByChannelField(type, channel, fieldId); return fields[pos->fieldId]; } -uint8_t StatisticsParser::getChannelFieldDigits(uint8_t channel, uint8_t fieldId) +uint8_t StatisticsParser::getChannelFieldDigits(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId) { - const byteAssign_t* pos = getAssignmentByChannelField(channel, fieldId); + const byteAssign_t* pos = getAssignmentByChannelField(type, channel, fieldId); return pos->digits; } -uint8_t StatisticsParser::getChannelCount() +std::list StatisticsParser::getChannelTypes() { - uint8_t cnt = 0; - for (auto const &b: *_byteAssignment) { - if (b.ch > cnt) { - cnt = b.ch; + return { + TYPE_AC, + TYPE_DC, + TYPE_INV + }; +} + +const char* StatisticsParser::getChannelTypeName(ChannelType_t type) +{ + return channelsTypes[type]; +} + +std::list StatisticsParser::getChannelsByType(ChannelType_t type) +{ + std::list l; + for (auto const& b : *_byteAssignment) { + if (b.type == type) { + l.push_back(b.ch); } } - - return cnt; + l.unique(); + return l; } uint16_t StatisticsParser::getChannelMaxPower(uint8_t channel) @@ -140,7 +154,7 @@ uint16_t StatisticsParser::getChannelMaxPower(uint8_t channel) void StatisticsParser::setChannelMaxPower(uint8_t channel, uint16_t power) { - if (channel < CH4) { + if (channel < sizeof(_chanMaxPower) / sizeof(_chanMaxPower[0])) { _chanMaxPower[channel] = power; } } @@ -163,8 +177,8 @@ uint32_t StatisticsParser::getRxFailureCount() static float calcYieldTotalCh0(StatisticsParser* iv, uint8_t arg0) { float yield = 0; - for (uint8_t i = 1; i <= iv->getChannelCount(); i++) { - yield += iv->getChannelFieldValue(i, FLD_YT); + for (auto& channel : iv->getChannelsByType(TYPE_DC)) { + yield += iv->getChannelFieldValue(TYPE_DC, channel, FLD_YT); } return yield; } @@ -172,8 +186,8 @@ static float calcYieldTotalCh0(StatisticsParser* iv, uint8_t arg0) static float calcYieldDayCh0(StatisticsParser* iv, uint8_t arg0) { float yield = 0; - for (uint8_t i = 1; i <= iv->getChannelCount(); i++) { - yield += iv->getChannelFieldValue(i, FLD_YD); + for (auto& channel : iv->getChannelsByType(TYPE_DC)) { + yield += iv->getChannelFieldValue(TYPE_DC, channel, FLD_YD); } return yield; } @@ -181,14 +195,14 @@ static float calcYieldDayCh0(StatisticsParser* iv, uint8_t arg0) // arg0 = channel of source static float calcUdcCh(StatisticsParser* iv, uint8_t arg0) { - return iv->getChannelFieldValue(arg0, FLD_UDC); + return iv->getChannelFieldValue(TYPE_DC, static_cast(arg0), FLD_UDC); } static float calcPowerDcCh0(StatisticsParser* iv, uint8_t arg0) { float dcPower = 0; - for (uint8_t i = 1; i <= iv->getChannelCount(); i++) { - dcPower += iv->getChannelFieldValue(i, FLD_PDC); + for (auto& channel : iv->getChannelsByType(TYPE_DC)) { + dcPower += iv->getChannelFieldValue(TYPE_DC, channel, FLD_PDC); } return dcPower; } @@ -196,15 +210,19 @@ static float calcPowerDcCh0(StatisticsParser* iv, uint8_t arg0) // arg0 = channel static float calcEffiencyCh0(StatisticsParser* iv, uint8_t arg0) { - float acPower = iv->getChannelFieldValue(CH0, FLD_PAC); - float dcPower = 0; - for (uint8_t i = 1; i <= iv->getChannelCount(); i++) { - dcPower += iv->getChannelFieldValue(i, FLD_PDC); + float acPower = 0; + for (auto& channel : iv->getChannelsByType(TYPE_AC)) { + acPower += iv->getChannelFieldValue(TYPE_AC, channel, FLD_PAC); } + + float dcPower = 0; + for (auto& channel : iv->getChannelsByType(TYPE_DC)) { + dcPower += iv->getChannelFieldValue(TYPE_DC, channel, FLD_PDC); + } + if (dcPower > 0) { return acPower / dcPower * 100.0f; } - return 0.0; } @@ -212,8 +230,8 @@ static float calcEffiencyCh0(StatisticsParser* iv, uint8_t arg0) static float calcIrradiation(StatisticsParser* iv, uint8_t arg0) { if (NULL != iv) { - if (iv->getChannelMaxPower(arg0 - 1) > 0) - return iv->getChannelFieldValue(arg0, FLD_PDC) / iv->getChannelMaxPower(arg0 - 1) * 100.0f; + if (iv->getChannelMaxPower(arg0) > 0) + return iv->getChannelFieldValue(TYPE_DC, static_cast(arg0), FLD_PDC) / iv->getChannelMaxPower(arg0) * 100.0f; } return 0.0; } diff --git a/lib/Hoymiles/src/parser/StatisticsParser.h b/lib/Hoymiles/src/parser/StatisticsParser.h index cc7cb76..a8fa420 100644 --- a/lib/Hoymiles/src/parser/StatisticsParser.h +++ b/lib/Hoymiles/src/parser/StatisticsParser.h @@ -8,7 +8,7 @@ #define STATISTIC_PACKET_SIZE (4 * 16) // units -enum { +enum UnitId_t { UNIT_V = 0, UNIT_A, UNIT_W, @@ -23,7 +23,7 @@ enum { const char* const units[] = { "V", "A", "W", "Wh", "kWh", "Hz", "°C", "%", "var", "" }; // field types -enum { +enum FieldId_t { FLD_UDC = 0, FLD_IDC, FLD_PDC, @@ -55,7 +55,7 @@ enum { enum { CMD_CALC = 0xffff }; // CH0 is default channel (freq, ac, temp) -enum { +enum ChannelNum_t { CH0 = 0, CH1, CH2, @@ -63,10 +63,18 @@ enum { CH4 }; +enum ChannelType_t { + TYPE_AC = 0, + TYPE_DC, + TYPE_INV +}; +const char* const channelsTypes[] = { "AC", "DC", "INV" }; + typedef struct { - uint8_t ch; // channel 0 - 4 - uint8_t fieldId; // field id - uint8_t unitId; // uint id + ChannelType_t type; + ChannelNum_t ch; // channel 0 - 4 + FieldId_t fieldId; // field id + UnitId_t unitId; // uint id uint8_t start; // pos of first byte in buffer uint8_t num; // number of bytes in buffer uint16_t div; // divisor / calc command @@ -81,14 +89,16 @@ public: void setByteAssignment(const std::list* byteAssignment); - const byteAssign_t* getAssignmentByChannelField(uint8_t channel, uint8_t fieldId); - float getChannelFieldValue(uint8_t channel, uint8_t fieldId); - bool hasChannelFieldValue(uint8_t channel, uint8_t fieldId); - const char* getChannelFieldUnit(uint8_t channel, uint8_t fieldId); - const char* getChannelFieldName(uint8_t channel, uint8_t fieldId); - uint8_t getChannelFieldDigits(uint8_t channel, uint8_t fieldId); + const byteAssign_t* getAssignmentByChannelField(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId); + float getChannelFieldValue(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId); + bool hasChannelFieldValue(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId); + const char* getChannelFieldUnit(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId); + const char* getChannelFieldName(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId); + uint8_t getChannelFieldDigits(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId); - uint8_t getChannelCount(); + std::list getChannelTypes(); + const char* getChannelTypeName(ChannelType_t type); + std::list getChannelsByType(ChannelType_t type); uint16_t getChannelMaxPower(uint8_t channel); void setChannelMaxPower(uint8_t channel, uint16_t power); diff --git a/src/Display_Graphic.cpp b/src/Display_Graphic.cpp index aa192b9..23c826e 100644 --- a/src/Display_Graphic.cpp +++ b/src/Display_Graphic.cpp @@ -37,7 +37,8 @@ std::map }; DisplayGraphicClass::DisplayGraphicClass() -{} +{ +} DisplayGraphicClass::~DisplayGraphicClass() { @@ -88,7 +89,7 @@ void DisplayGraphicClass::printText(const char* text, uint8_t line) break; } - // get the font height, to calculate the textheight + // get the font height, to calculate the textheight _dispY += (_display->getMaxCharHeight()) + 1; // calculate the starting position of the text @@ -126,9 +127,11 @@ void DisplayGraphicClass::loop() isprod++; } - totalPower += inv->Statistics()->getChannelFieldValue(CH0, FLD_PAC); - totalYieldDay += inv->Statistics()->getChannelFieldValue(CH0, FLD_YD); - totalYieldTotal += inv->Statistics()->getChannelFieldValue(CH0, FLD_YT); + for (auto& c : inv->Statistics()->getChannelsByType(TYPE_AC)) { + totalPower += inv->Statistics()->getChannelFieldValue(TYPE_AC, c, FLD_PAC); + totalYieldDay += inv->Statistics()->getChannelFieldValue(TYPE_AC, c, FLD_YD); + totalYieldTotal += inv->Statistics()->getChannelFieldValue(TYPE_AC, c, FLD_YT); + } } _display->clearBuffer(); diff --git a/src/MqttHandleHass.cpp b/src/MqttHandleHass.cpp index 5afd6dd..916bdb2 100644 --- a/src/MqttHandleHass.cpp +++ b/src/MqttHandleHass.cpp @@ -65,13 +65,15 @@ void MqttHandleHassClass::publishConfig() publishInverterBinarySensor(inv, "Producing", "status/producing", "1", "0"); // Loop all channels - for (uint8_t c = 0; c <= inv->Statistics()->getChannelCount(); c++) { - for (uint8_t f = 0; f < DEVICE_CLS_ASSIGN_LIST_LEN; f++) { - bool clear = false; - if (c > 0 && !config.Mqtt_Hass_IndividualPanels) { - clear = true; + for (auto& t : inv->Statistics()->getChannelTypes()) { + for (auto& c : inv->Statistics()->getChannelsByType(t)) { + for (uint8_t f = 0; f < DEVICE_CLS_ASSIGN_LIST_LEN; f++) { + bool clear = false; + if (t == TYPE_DC && !config.Mqtt_Hass_IndividualPanels) { + clear = true; + } + publishField(inv, t, c, deviceFieldAssignment[f], clear); } - publishField(inv, c, deviceFieldAssignment[f], clear); } } @@ -79,32 +81,40 @@ void MqttHandleHassClass::publishConfig() } } -void MqttHandleHassClass::publishField(std::shared_ptr inv, uint8_t channel, byteAssign_fieldDeviceClass_t fieldType, bool clear) +void MqttHandleHassClass::publishField(std::shared_ptr inv, ChannelType_t type, ChannelNum_t channel, byteAssign_fieldDeviceClass_t fieldType, bool clear) { - if (!inv->Statistics()->hasChannelFieldValue(channel, fieldType.fieldId)) { + if (!inv->Statistics()->hasChannelFieldValue(type, channel, fieldType.fieldId)) { return; } String serial = inv->serialString(); String fieldName; - if (channel == CH0 && fieldType.fieldId == FLD_PDC) { + if (type == TYPE_AC && fieldType.fieldId == FLD_PDC) { fieldName = "PowerDC"; } else { - fieldName = inv->Statistics()->getChannelFieldName(channel, fieldType.fieldId); + fieldName = inv->Statistics()->getChannelFieldName(type, channel, fieldType.fieldId); + } + + String chanNum; + if (type == TYPE_DC) { + // TODO(tbnobody) + chanNum = static_cast(channel) + 1; + } else { + chanNum = channel; } String configTopic = "sensor/dtu_" + serial - + "/" + "ch" + String(channel) + "_" + fieldName + + "/" + "ch" + chanNum + "_" + fieldName + "/config"; if (!clear) { - String stateTopic = MqttSettings.getPrefix() + MqttHandleInverter.getTopic(inv, channel, fieldType.fieldId); + String stateTopic = MqttSettings.getPrefix() + MqttHandleInverter.getTopic(inv, type, channel, fieldType.fieldId); const char* devCls = deviceClasses[fieldType.deviceClsId]; const char* stateCls = stateClasses[fieldType.stateClsId]; String name; - if (channel == CH0) { + if (type != TYPE_DC) { name = String(inv->name()) + " " + fieldName; } else { name = String(inv->name()) + " CH" + String(channel) + " " + fieldName; @@ -115,7 +125,7 @@ void MqttHandleHassClass::publishField(std::shared_ptr inv, ui root[F("stat_t")] = stateTopic; root[F("uniq_id")] = serial + "_ch" + String(channel) + "_" + fieldName; - String unit_of_measure = inv->Statistics()->getChannelFieldUnit(channel, fieldType.fieldId); + String unit_of_measure = inv->Statistics()->getChannelFieldUnit(type, channel, fieldType.fieldId); if (unit_of_measure != "") { root[F("unit_of_meas")] = unit_of_measure; } diff --git a/src/MqttHandleInverter.cpp b/src/MqttHandleInverter.cpp index 46cc0d2..3703630 100644 --- a/src/MqttHandleInverter.cpp +++ b/src/MqttHandleInverter.cpp @@ -96,15 +96,18 @@ void MqttHandleInverterClass::loop() _lastPublishStats[i] = lastUpdate; // Loop all channels - for (uint8_t c = 0; c <= inv->Statistics()->getChannelCount(); c++) { - if (c > 0) { - INVERTER_CONFIG_T* inv_cfg = Configuration.getInverterConfig(inv->serial()); - if (inv_cfg != nullptr) { - MqttSettings.publish(inv->serialString() + "/" + String(c) + "/name", inv_cfg->channel[c - 1].Name); + for (auto& t : inv->Statistics()->getChannelTypes()) { + for (auto& c : inv->Statistics()->getChannelsByType(t)) { + if (t == TYPE_DC) { + INVERTER_CONFIG_T* inv_cfg = Configuration.getInverterConfig(inv->serial()); + if (inv_cfg != nullptr) { + // TODO(tbnobody) + MqttSettings.publish(inv->serialString() + "/" + String(static_cast(c) + 1) + "/name", inv_cfg->channel[c].Name); + } + } + for (uint8_t f = 0; f < sizeof(_publishFields) / sizeof(FieldId_t); f++) { + publishField(inv, t, c, _publishFields[f]); } - } - for (uint8_t f = 0; f < sizeof(_publishFields); f++) { - publishField(inv, c, _publishFields[f]); } } } @@ -116,31 +119,39 @@ void MqttHandleInverterClass::loop() } } -void MqttHandleInverterClass::publishField(std::shared_ptr inv, uint8_t channel, uint8_t fieldId) +void MqttHandleInverterClass::publishField(std::shared_ptr inv, ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId) { - String topic = getTopic(inv, channel, fieldId); + String topic = getTopic(inv, type, channel, fieldId); if (topic == "") { return; } - MqttSettings.publish(topic, String(inv->Statistics()->getChannelFieldValue(channel, fieldId))); + MqttSettings.publish(topic, String(inv->Statistics()->getChannelFieldValue(type, channel, fieldId))); } -String MqttHandleInverterClass::getTopic(std::shared_ptr inv, uint8_t channel, uint8_t fieldId) +String MqttHandleInverterClass::getTopic(std::shared_ptr inv, ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId) { - if (!inv->Statistics()->hasChannelFieldValue(channel, fieldId)) { + if (!inv->Statistics()->hasChannelFieldValue(type, channel, fieldId)) { return String(""); } String chanName; - if (channel == 0 && fieldId == FLD_PDC) { + if (type == TYPE_AC && fieldId == FLD_PDC) { chanName = "powerdc"; } else { - chanName = inv->Statistics()->getChannelFieldName(channel, fieldId); + chanName = inv->Statistics()->getChannelFieldName(type, channel, fieldId); chanName.toLowerCase(); } - return inv->serialString() + "/" + String(channel) + "/" + chanName; + String chanNum; + if (type == TYPE_DC) { + // TODO(tbnobody) + chanNum = static_cast(channel) + 1; + } else { + chanNum = channel; + } + + return inv->serialString() + "/" + chanNum + "/" + chanName; } void MqttHandleInverterClass::onMqttMessage(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) diff --git a/src/WebApi_inverter.cpp b/src/WebApi_inverter.cpp index cda8f33..1e844e4 100644 --- a/src/WebApi_inverter.cpp +++ b/src/WebApi_inverter.cpp @@ -59,7 +59,7 @@ void WebApiInverterClass::onInverterList(AsyncWebServerRequest* request) max_channels = INV_MAX_CHAN_COUNT; } else { obj[F("type")] = inv->typeName(); - max_channels = inv->Statistics()->getChannelCount(); + max_channels = inv->Statistics()->getChannelsByType(TYPE_DC).size(); } JsonArray channel = obj.createNestedArray("channel"); diff --git a/src/WebApi_prometheus.cpp b/src/WebApi_prometheus.cpp index 45f23ff..b200abf 100644 --- a/src/WebApi_prometheus.cpp +++ b/src/WebApi_prometheus.cpp @@ -63,39 +63,48 @@ void WebApiPrometheusClass::onPrometheusMetricsGet(AsyncWebServerRequest* reques serial.c_str(), i, name, inv->Statistics()->getLastUpdate() / 1000); // Loop all channels - for (uint8_t c = 0; c <= inv->Statistics()->getChannelCount(); c++) { - addField(stream, serial, i, inv, c, FLD_PAC); - addField(stream, serial, i, inv, c, FLD_UAC); - addField(stream, serial, i, inv, c, FLD_IAC); - if (c == 0) { - addField(stream, serial, i, inv, c, FLD_PDC, "PowerDC"); - } else { - addField(stream, serial, i, inv, c, FLD_PDC); + for (auto& t : inv->Statistics()->getChannelTypes()) { + for (auto& c : inv->Statistics()->getChannelsByType(t)) { + addField(stream, serial, i, inv, t, c, FLD_PAC); + addField(stream, serial, i, inv, t, c, FLD_UAC); + addField(stream, serial, i, inv, t, c, FLD_IAC); + if (t == TYPE_AC) { + addField(stream, serial, i, inv, t, c, FLD_PDC, "PowerDC"); + } else { + addField(stream, serial, i, inv, t, c, FLD_PDC); + } + addField(stream, serial, i, inv, t, c, FLD_UDC); + addField(stream, serial, i, inv, t, c, FLD_IDC); + addField(stream, serial, i, inv, t, c, FLD_YD); + addField(stream, serial, i, inv, t, c, FLD_YT); + addField(stream, serial, i, inv, t, c, FLD_F); + addField(stream, serial, i, inv, t, c, FLD_T); + addField(stream, serial, i, inv, t, c, FLD_PF); + addField(stream, serial, i, inv, t, c, FLD_PRA); + addField(stream, serial, i, inv, t, c, FLD_EFF); + addField(stream, serial, i, inv, t, c, FLD_IRR); } - addField(stream, serial, i, inv, c, FLD_UDC); - addField(stream, serial, i, inv, c, FLD_IDC); - addField(stream, serial, i, inv, c, FLD_YD); - addField(stream, serial, i, inv, c, FLD_YT); - addField(stream, serial, i, inv, c, FLD_F); - addField(stream, serial, i, inv, c, FLD_T); - addField(stream, serial, i, inv, c, FLD_PF); - addField(stream, serial, i, inv, c, FLD_PRA); - addField(stream, serial, i, inv, c, FLD_EFF); - addField(stream, serial, i, inv, c, FLD_IRR); } } stream->addHeader(F("Cache-Control"), F("no-cache")); request->send(stream); } -void WebApiPrometheusClass::addField(AsyncResponseStream* stream, String& serial, uint8_t idx, std::shared_ptr inv, uint8_t channel, uint8_t fieldId, const char* channelName) +void WebApiPrometheusClass::addField(AsyncResponseStream* stream, String& serial, uint8_t idx, std::shared_ptr inv, ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId, const char* channelName) { - if (inv->Statistics()->hasChannelFieldValue(channel, fieldId)) { - const char* chanName = (channelName == NULL) ? inv->Statistics()->getChannelFieldName(channel, fieldId) : channelName; - if (idx == 0 && channel == 0) { - stream->printf("# HELP opendtu_%s in %s\n", chanName, inv->Statistics()->getChannelFieldUnit(channel, fieldId)); + if (inv->Statistics()->hasChannelFieldValue(type, channel, fieldId)) { + const char* chanName = (channelName == NULL) ? inv->Statistics()->getChannelFieldName(type, channel, fieldId) : channelName; + if (idx == 0 && type == TYPE_AC && channel == 0) { + stream->printf("# HELP opendtu_%s in %s\n", chanName, inv->Statistics()->getChannelFieldUnit(type, channel, fieldId)); stream->printf("# TYPE opendtu_%s gauge\n", chanName); } - stream->printf("opendtu_%s{serial=\"%s\",unit=\"%d\",name=\"%s\",channel=\"%d\"} %f\n", chanName, serial.c_str(), idx, inv->name(), channel, inv->Statistics()->getChannelFieldValue(channel, fieldId)); + stream->printf("opendtu_%s{serial=\"%s\",unit=\"%d\",name=\"%s\",type=\"%s\",channel=\"%d\"} %f\n", + chanName, + serial.c_str(), + idx, + inv->name(), + inv->Statistics()->getChannelTypeName(type), + channel, + inv->Statistics()->getChannelFieldValue(type, channel, fieldId)); } } \ No newline at end of file diff --git a/src/WebApi_ws_live.cpp b/src/WebApi_ws_live.cpp index ae1ed18..737cefe 100644 --- a/src/WebApi_ws_live.cpp +++ b/src/WebApi_ws_live.cpp @@ -111,36 +111,39 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root) } // Loop all channels - for (uint8_t c = 0; c <= inv->Statistics()->getChannelCount(); c++) { - if (c > 0) { - INVERTER_CONFIG_T* inv_cfg = Configuration.getInverterConfig(inv->serial()); - if (inv_cfg != nullptr) { - invObject[String(c)][F("name")]["u"] = inv_cfg->channel[c - 1].Name; + for (auto& t : inv->Statistics()->getChannelTypes()) { + for (auto& c : inv->Statistics()->getChannelsByType(t)) { + if (t == TYPE_DC) { + INVERTER_CONFIG_T* inv_cfg = Configuration.getInverterConfig(inv->serial()); + if (inv_cfg != nullptr) { + // TODO(tbnobody) + invObject[String(static_cast(c) + 1)][F("name")]["u"] = inv_cfg->channel[c].Name; + } + } + addField(invObject, i, inv, t, c, FLD_PAC); + addField(invObject, i, inv, t, c, FLD_UAC); + addField(invObject, i, inv, t, c, FLD_IAC); + if (t == TYPE_AC) { + addField(invObject, i, inv, t, c, FLD_PDC, F("Power DC")); + } else { + addField(invObject, i, inv, t, c, FLD_PDC); + } + addField(invObject, i, inv, t, c, FLD_UDC); + addField(invObject, i, inv, t, c, FLD_IDC); + addField(invObject, i, inv, t, c, FLD_YD); + addField(invObject, i, inv, t, c, FLD_YT); + addField(invObject, i, inv, t, c, FLD_F); + addField(invObject, i, inv, t, c, FLD_T); + addField(invObject, i, inv, t, c, FLD_PF); + addField(invObject, i, inv, t, c, FLD_PRA); + addField(invObject, i, inv, t, c, FLD_EFF); + if (t == TYPE_DC && inv->Statistics()->getChannelMaxPower(c) > 0) { + addField(invObject, i, inv, t, c, FLD_IRR); } - } - addField(invObject, i, inv, c, FLD_PAC); - addField(invObject, i, inv, c, FLD_UAC); - addField(invObject, i, inv, c, FLD_IAC); - if (c == 0) { - addField(invObject, i, inv, c, FLD_PDC, F("Power DC")); - } else { - addField(invObject, i, inv, c, FLD_PDC); - } - addField(invObject, i, inv, c, FLD_UDC); - addField(invObject, i, inv, c, FLD_IDC); - addField(invObject, i, inv, c, FLD_YD); - addField(invObject, i, inv, c, FLD_YT); - addField(invObject, i, inv, c, FLD_F); - addField(invObject, i, inv, c, FLD_T); - addField(invObject, i, inv, c, FLD_PF); - addField(invObject, i, inv, c, FLD_PRA); - addField(invObject, i, inv, c, FLD_EFF); - if (c > 0 && inv->Statistics()->getChannelMaxPower(c - 1) > 0) { - addField(invObject, i, inv, c, FLD_IRR); } } - if (inv->Statistics()->hasChannelFieldValue(CH0, FLD_EVT_LOG)) { + if (inv->Statistics()->hasChannelFieldValue(TYPE_INV, CH0, FLD_EVT_LOG)) { invObject[F("events")] = inv->EventLog()->getEntryCount(); } else { invObject[F("events")] = -1; @@ -150,9 +153,11 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root) _newestInverterTimestamp = inv->Statistics()->getLastUpdate(); } - totalPower += inv->Statistics()->getChannelFieldValue(CH0, FLD_PAC); - totalYieldDay += inv->Statistics()->getChannelFieldValue(CH0, FLD_YD); - totalYieldTotal += inv->Statistics()->getChannelFieldValue(CH0, FLD_YT); + for (auto& c : inv->Statistics()->getChannelsByType(TYPE_AC)) { + totalPower += inv->Statistics()->getChannelFieldValue(TYPE_AC, c, FLD_PAC); + totalYieldDay += inv->Statistics()->getChannelFieldValue(TYPE_AC, c, FLD_YD); + totalYieldTotal += inv->Statistics()->getChannelFieldValue(TYPE_AC, c, FLD_YT); + } } JsonObject totalObj = root.createNestedObject("total"); @@ -172,18 +177,25 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root) } } -void WebApiWsLiveClass::addField(JsonObject& root, uint8_t idx, std::shared_ptr inv, uint8_t channel, uint8_t fieldId, String topic) +void WebApiWsLiveClass::addField(JsonObject& root, uint8_t idx, std::shared_ptr inv, ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId, String topic) { - if (inv->Statistics()->hasChannelFieldValue(channel, fieldId)) { + if (inv->Statistics()->hasChannelFieldValue(type, channel, fieldId)) { String chanName; if (topic == "") { - chanName = inv->Statistics()->getChannelFieldName(channel, fieldId); + chanName = inv->Statistics()->getChannelFieldName(type, channel, fieldId); } else { chanName = topic; } - root[String(channel)][chanName]["v"] = inv->Statistics()->getChannelFieldValue(channel, fieldId); - root[String(channel)][chanName]["u"] = inv->Statistics()->getChannelFieldUnit(channel, fieldId); - root[String(channel)][chanName]["d"] = inv->Statistics()->getChannelFieldDigits(channel, fieldId); + String chanNum; + if (type == TYPE_DC) { + // TODO(tbnobody) + chanNum = static_cast(channel) + 1; + } else { + chanNum = channel; + } + root[chanNum][chanName]["v"] = inv->Statistics()->getChannelFieldValue(type, channel, fieldId); + root[chanNum][chanName]["u"] = inv->Statistics()->getChannelFieldUnit(type, channel, fieldId); + root[chanNum][chanName]["d"] = inv->Statistics()->getChannelFieldDigits(type, channel, fieldId); } }