Added api endpoint to get livedata in json format with get request

This commit is contained in:
Thomas Basler 2022-07-20 20:54:57 +02:00
parent 184183e979
commit 3f8ee18de9
2 changed files with 67 additions and 47 deletions

View File

@ -12,7 +12,9 @@ public:
void loop(); void loop();
private: private:
void addField(JsonDocument& root, uint8_t idx, std::shared_ptr<InverterAbstract> inv, uint8_t channel, uint8_t fieldId, String topic = ""); void generateJsonResponse(JsonVariant& root);
void addField(JsonVariant& root, uint8_t idx, std::shared_ptr<InverterAbstract> 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); void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
AsyncWebServer* _server; AsyncWebServer* _server;

View File

@ -16,6 +16,7 @@ void WebApiWsLiveClass::init(AsyncWebServer* server)
using namespace std::placeholders; using namespace std::placeholders;
_server = server; _server = server;
_server->on("/api/livedata/status", HTTP_GET, std::bind(&WebApiWsLiveClass::onLivedataStatus, this, _1));
_server->addHandler(&_ws); _server->addHandler(&_ws);
_ws.onEvent(std::bind(&WebApiWsLiveClass::onWebsocketEvent, this, _1, _2, _3, _4, _5, _6)); _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)) { if (millis() - _lastWsPublish > (10 * 1000) || (maxTimeStamp != _newestInverterTimestamp)) {
DynamicJsonDocument root(40960); DynamicJsonDocument root(40960);
// Loop all inverters JsonVariant var = root;
for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { generateJsonResponse(var);
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();
}
}
size_t len = measureJson(root); size_t len = measureJson(root);
AsyncWebSocketMessageBuffer* buffer = _ws.makeBuffer(len); // creates a buffer (len + 1) for you. 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<InverterAbstract> 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<InverterAbstract> inv, uint8_t channel, uint8_t fieldId, String topic)
{ {
if (inv->Statistics()->hasChannelFieldValue(channel, fieldId)) { if (inv->Statistics()->hasChannelFieldValue(channel, fieldId)) {
String chanName; String chanName;
@ -135,3 +142,14 @@ void WebApiWsLiveClass::onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketC
Serial.println(str); Serial.println(str);
} }
} }
void WebApiWsLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
{
AsyncJsonResponse* response = new AsyncJsonResponse(true, 40960U);
JsonVariant root = response->getRoot().as<JsonVariant>();
generateJsonResponse(root);
response->setLength();
request->send(response);
}