First version of very simple websocket api

This commit is contained in:
Thomas Basler 2022-06-16 01:44:42 +02:00
parent 1ea2990fe9
commit af00158e14
4 changed files with 86 additions and 0 deletions

View File

@ -8,6 +8,7 @@
#include "WebApi_ntp.h"
#include "WebApi_sysstatus.h"
#include "WebApi_webapp.h"
#include "WebApi_ws_live.h"
#include <ESPAsyncWebServer.h>
class WebApiClass {
@ -29,6 +30,7 @@ private:
WebApiNtpClass _webApiNtp;
WebApiSysstatusClass _webApiSysstatus;
WebApiWebappClass _webApiWebapp;
WebApiWsLiveClass _webApiWsLive;
void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);

15
include/WebApi_ws_live.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
#include "ArduinoJson.h"
#include <ESPAsyncWebServer.h>
#include <Hoymiles.h>
class WebApiWsLiveClass {
public:
void init(AsyncWebSocket* ws);
void loop();
private:
AsyncWebSocket* _ws;
void addField(JsonDocument& root, uint8_t idx, std::shared_ptr<InverterAbstract> inv, uint8_t channel, uint8_t fieldId);
};

View File

@ -28,6 +28,8 @@ void WebApiClass::init()
_webApiSysstatus.init(&_server);
_webApiWebapp.init(&_server);
_webApiWsLive.init(&_ws);
_server.onNotFound(std::bind(&WebApiClass::onNotFound, this, _1));
_server.begin();
}
@ -43,6 +45,8 @@ void WebApiClass::loop()
_webApiSysstatus.loop();
_webApiWebapp.loop();
_webApiWsLive.loop();
// see: https://github.com/me-no-dev/ESPAsyncWebServer#limiting-the-number-of-web-socket-clients
_ws.cleanupClients();
}

65
src/WebApi_ws_live.cpp Normal file
View File

@ -0,0 +1,65 @@
#include "WebApi_ws_live.h"
#include "AsyncJson.h"
#include <Every.h>
void WebApiWsLiveClass::init(AsyncWebSocket* ws)
{
_ws = ws;
}
void WebApiWsLiveClass::loop()
{
EVERY_N_SECONDS(10)
{
// do nothing if no WS client is connected
if (_ws->count() == 0) {
return;
}
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]["serial"] = String(buffer);
root[i]["name"] = inv->name();
// Loop all channels
for (uint8_t c = 0; c <= inv->getChannelCount(); c++) {
addField(root, i, inv, c, FLD_UDC);
addField(root, i, inv, c, FLD_IDC);
addField(root, i, inv, c, FLD_PDC);
addField(root, i, inv, c, FLD_YD);
addField(root, i, inv, c, FLD_YT);
addField(root, i, inv, c, FLD_UAC);
addField(root, i, inv, c, FLD_IAC);
addField(root, i, inv, c, FLD_PAC);
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);
}
}
size_t len = measureJson(root);
AsyncWebSocketMessageBuffer* buffer = _ws->makeBuffer(len); // creates a buffer (len + 1) for you.
if (buffer) {
serializeJson(root, (char*)buffer->get(), len + 1);
_ws->textAll(buffer);
}
}
}
void WebApiWsLiveClass::addField(JsonDocument& root, uint8_t idx, std::shared_ptr<InverterAbstract> inv, uint8_t channel, uint8_t fieldId)
{
if (inv->hasValue(channel, fieldId)) {
root[idx][String(channel)][inv->getName(channel, fieldId)]["v"] = inv->getValue(channel, fieldId);
root[idx][String(channel)][inv->getName(channel, fieldId)]["u"] = inv->getUnit(channel, fieldId);
}
}