diff --git a/include/WebApi_ws_live.h b/include/WebApi_ws_live.h index d4db9f41..631aaaae 100644 --- a/include/WebApi_ws_live.h +++ b/include/WebApi_ws_live.h @@ -12,7 +12,9 @@ public: void loop(); private: - void addField(JsonDocument& root, uint8_t idx, std::shared_ptr inv, uint8_t channel, uint8_t fieldId, String topic = ""); + void generateJsonResponse(JsonVariant& root); + void addField(JsonVariant& root, uint8_t idx, std::shared_ptr inv, uint8_t channel, uint8_t fieldId, String topic = ""); + void onLivedataStatus(AsyncWebServerRequest* request); void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len); AsyncWebServer* _server; diff --git a/src/WebApi_ws_live.cpp b/src/WebApi_ws_live.cpp index e0f923a2..7792ca6a 100644 --- a/src/WebApi_ws_live.cpp +++ b/src/WebApi_ws_live.cpp @@ -16,6 +16,7 @@ void WebApiWsLiveClass::init(AsyncWebServer* server) using namespace std::placeholders; _server = server; + _server->on("/api/livedata/status", HTTP_GET, std::bind(&WebApiWsLiveClass::onLivedataStatus, this, _1)); _server->addHandler(&_ws); _ws.onEvent(std::bind(&WebApiWsLiveClass::onWebsocketEvent, this, _1, _2, _3, _4, _5, _6)); @@ -52,51 +53,8 @@ void WebApiWsLiveClass::loop() if (millis() - _lastWsPublish > (10 * 1000) || (maxTimeStamp != _newestInverterTimestamp)) { DynamicJsonDocument root(40960); - // Loop all inverters - for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { - auto inv = Hoymiles.getInverterByPos(i); - - char buffer[sizeof(uint64_t) * 8 + 1]; - sprintf(buffer, "%0lx%08lx", - ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), - ((uint32_t)(inv->serial() & 0xFFFFFFFF))); - - root[i][F("serial")] = String(buffer); - root[i][F("name")] = inv->name(); - root[i][F("data_age")] = (millis() - inv->getLastStatsUpdate()) / 1000; - root[i][F("age_critical")] = ((millis() - inv->getLastStatsUpdate()) / 1000) > Configuration.get().Dtu_PollInterval * 5; - - // Loop all channels - for (uint8_t c = 0; c <= inv->Statistics()->getChannelCount(); c++) { - addField(root, i, inv, c, FLD_PAC); - addField(root, i, inv, c, FLD_UAC); - addField(root, i, inv, c, FLD_IAC); - if (c == 0) { - addField(root, i, inv, c, FLD_PDC, F("Power DC")); - } else { - addField(root, i, inv, c, FLD_PDC); - } - addField(root, i, inv, c, FLD_UDC); - addField(root, i, inv, c, FLD_IDC); - addField(root, i, inv, c, FLD_YD); - addField(root, i, inv, c, FLD_YT); - addField(root, i, inv, c, FLD_F); - addField(root, i, inv, c, FLD_T); - addField(root, i, inv, c, FLD_PCT); - addField(root, i, inv, c, FLD_EFF); - addField(root, i, inv, c, FLD_IRR); - } - - if (inv->Statistics()->hasChannelFieldValue(CH0, FLD_EVT_LOG)) { - root[i][F("events")] = inv->EventLog()->getEntryCount(); - } else { - root[i][F("events")] = -1; - } - - if (inv->getLastStatsUpdate() > _newestInverterTimestamp) { - _newestInverterTimestamp = inv->getLastStatsUpdate(); - } - } + JsonVariant var = root; + generateJsonResponse(var); size_t len = measureJson(root); AsyncWebSocketMessageBuffer* buffer = _ws.makeBuffer(len); // creates a buffer (len + 1) for you. @@ -109,7 +67,56 @@ void WebApiWsLiveClass::loop() } } -void WebApiWsLiveClass::addField(JsonDocument& root, uint8_t idx, std::shared_ptr inv, uint8_t channel, uint8_t fieldId, String topic) +void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root) +{ + // Loop all inverters + for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { + auto inv = Hoymiles.getInverterByPos(i); + + char buffer[sizeof(uint64_t) * 8 + 1]; + sprintf(buffer, "%0lx%08lx", + ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), + ((uint32_t)(inv->serial() & 0xFFFFFFFF))); + + root[i][F("serial")] = String(buffer); + root[i][F("name")] = inv->name(); + root[i][F("data_age")] = (millis() - inv->getLastStatsUpdate()) / 1000; + root[i][F("age_critical")] = ((millis() - inv->getLastStatsUpdate()) / 1000) > Configuration.get().Dtu_PollInterval * 5; + + // Loop all channels + for (uint8_t c = 0; c <= inv->Statistics()->getChannelCount(); c++) { + addField(root, i, inv, c, FLD_PAC); + addField(root, i, inv, c, FLD_UAC); + addField(root, i, inv, c, FLD_IAC); + if (c == 0) { + addField(root, i, inv, c, FLD_PDC, F("Power DC")); + } else { + addField(root, i, inv, c, FLD_PDC); + } + addField(root, i, inv, c, FLD_UDC); + addField(root, i, inv, c, FLD_IDC); + addField(root, i, inv, c, FLD_YD); + addField(root, i, inv, c, FLD_YT); + addField(root, i, inv, c, FLD_F); + addField(root, i, inv, c, FLD_T); + addField(root, i, inv, c, FLD_PCT); + addField(root, i, inv, c, FLD_EFF); + addField(root, i, inv, c, FLD_IRR); + } + + if (inv->Statistics()->hasChannelFieldValue(CH0, FLD_EVT_LOG)) { + root[i][F("events")] = inv->EventLog()->getEntryCount(); + } else { + root[i][F("events")] = -1; + } + + if (inv->getLastStatsUpdate() > _newestInverterTimestamp) { + _newestInverterTimestamp = inv->getLastStatsUpdate(); + } + } +} + +void WebApiWsLiveClass::addField(JsonVariant& root, uint8_t idx, std::shared_ptr inv, uint8_t channel, uint8_t fieldId, String topic) { if (inv->Statistics()->hasChannelFieldValue(channel, fieldId)) { String chanName; @@ -134,4 +141,15 @@ void WebApiWsLiveClass::onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketC sprintf(str, "Websocket: [%s][%u] disconnect", server->url(), client->id()); Serial.println(str); } +} + +void WebApiWsLiveClass::onLivedataStatus(AsyncWebServerRequest* request) +{ + AsyncJsonResponse* response = new AsyncJsonResponse(true, 40960U); + JsonVariant root = response->getRoot().as(); + + generateJsonResponse(root); + + response->setLength(); + request->send(response); } \ No newline at end of file