diff --git a/include/WebApi_ws_live.h b/include/WebApi_ws_live.h index f06faa6..7f21f80 100644 --- a/include/WebApi_ws_live.h +++ b/include/WebApi_ws_live.h @@ -14,6 +14,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 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/src/WebApi_ws_live.cpp b/src/WebApi_ws_live.cpp index a5c5832..2c6f9c8 100644 --- a/src/WebApi_ws_live.cpp +++ b/src/WebApi_ws_live.cpp @@ -74,9 +74,17 @@ void WebApiWsLiveClass::loop() void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root) { JsonArray invArray = root.createNestedArray("inverters"); + + float totalPower = 0; + float totalYieldDay = 0; + float totalYieldTotal = 0; + // Loop all inverters for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { auto inv = Hoymiles.getInverterByPos(i); + if (inv == nullptr) { + continue; + } JsonObject invObject = invArray.createNestedObject(); @@ -123,7 +131,17 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root) if (inv->Statistics()->getLastUpdate() > _newestInverterTimestamp) { _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); } + + JsonObject totalObj = root.createNestedObject("total"); + // todo: Fixed hard coded name, unit and digits + addTotalField(totalObj, "Power", totalPower, "W", 1); + addTotalField(totalObj, "YieldDay", totalYieldDay, "Wh", 0); + addTotalField(totalObj, "YieldTotal", totalYieldTotal, "kWh", 2); } void WebApiWsLiveClass::addField(JsonObject& root, uint8_t idx, std::shared_ptr inv, uint8_t channel, uint8_t fieldId, String topic) @@ -141,6 +159,13 @@ void WebApiWsLiveClass::addField(JsonObject& root, uint8_t idx, std::shared_ptr< } } +void WebApiWsLiveClass::addTotalField(JsonObject& root, String name, float value, String unit, uint8_t digits) +{ + root[name]["v"] = value; + root[name]["u"] = unit; + root[name]["d"] = digits; +} + void WebApiWsLiveClass::onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len) { if (type == WS_EVT_CONNECT) { diff --git a/webapp/src/components/InverterTotalInfo.vue b/webapp/src/components/InverterTotalInfo.vue new file mode 100644 index 0000000..6369d60 --- /dev/null +++ b/webapp/src/components/InverterTotalInfo.vue @@ -0,0 +1,55 @@ + + + \ No newline at end of file diff --git a/webapp/src/types/LiveDataStatus.ts b/webapp/src/types/LiveDataStatus.ts index a57c0d4..d8189e9 100644 --- a/webapp/src/types/LiveDataStatus.ts +++ b/webapp/src/types/LiveDataStatus.ts @@ -31,6 +31,13 @@ export interface Inverter { [key: number]: InverterStatistics, }; +export interface Total { + Power: ValueObject, + YieldDay: ValueObject, + YieldTotal: ValueObject, +}; + export interface LiveData { inverters: Inverter[], + total: Total, } \ No newline at end of file diff --git a/webapp/src/views/HomeView.vue b/webapp/src/views/HomeView.vue index 0553633..6d8e147 100644 --- a/webapp/src/views/HomeView.vue +++ b/webapp/src/views/HomeView.vue @@ -1,5 +1,6 @@