* started to implement POST api

* improved web serial console
* added multi inverter total values (published through MQTT)
* fixed: after boot there were transferred wrong data because of incorrect assignment (mqtt, visualization)
  -> not tested with sun
This commit is contained in:
lumapu 2022-09-10 02:19:25 +02:00
parent 9e1b6be70e
commit 6bd7e01f1a
13 changed files with 404 additions and 379 deletions

View file

@ -23,7 +23,9 @@ webApi::webApi(AsyncWebServer *srv, app *app, sysConfig_t *sysCfg, config_t *con
//-----------------------------------------------------------------------------
void webApi::setup(void) {
mSrv->on("/api", HTTP_GET, std::bind(&webApi::onApi, this, std::placeholders::_1));
mSrv->on("/api", HTTP_GET, std::bind(&webApi::onApi, this, std::placeholders::_1));
mSrv->on("/api", HTTP_POST, std::bind(&webApi::onApiPost, this, std::placeholders::_1)).onBody(
std::bind(&webApi::onApiPostBody, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
}
@ -59,6 +61,44 @@ void webApi::onApi(AsyncWebServerRequest *request) {
}
//-----------------------------------------------------------------------------
void webApi::onApiPost(AsyncWebServerRequest *request) {
DPRINTLN(DBG_VERBOSE, "onApiPost");
}
//-----------------------------------------------------------------------------
void webApi::onApiPostBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
DPRINTLN(DBG_VERBOSE, "onApiPostBody");
DynamicJsonDocument json(200);
AsyncJsonResponse* response = new AsyncJsonResponse(false, 200);
JsonObject root = response->getRoot();
DeserializationError err = deserializeJson(json, (const char *)data);
root[F("success")] = (err) ? false : true;
if(!err) {
String path = request->url().substring(5);
if(path == "ctrl")
root[F("success")] = setCtrl(json, root);
else {
root[F("success")] = false;
root[F("error")] = "Path not found: " + path;
}
}
else {
switch (err.code()) {
case DeserializationError::Ok: break;
case DeserializationError::InvalidInput: root[F("error")] = F("Invalid input"); break;
case DeserializationError::NoMemory: root[F("error")] = F("Not enough memory"); break;
default: root[F("error")] = F("Deserialization failed"); break;
}
}
response->setLength();
request->send(response);
}
//-----------------------------------------------------------------------------
void webApi::getNotFound(JsonObject obj, String url) {
JsonObject ep = obj.createNestedObject("avail_endpoints");
@ -227,43 +267,100 @@ void webApi::getLive(JsonObject obj) {
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
iv = mApp->mSys->getInverterByPos(i);
if(NULL != iv) {
JsonObject obj2 = invArr.createNestedObject();
obj2[F("name")] = String(iv->name);
obj2[F("channels")] = iv->channels;
obj2[F("power_limit_read")] = iv->actPowerLimit;
obj2[F("power_limit_active")] = NoPowerLimit != iv->powerLimit[1];
obj2[F("last_alarm")] = String(iv->lastAlarmMsg);
obj2[F("ts_last_success")] = iv->ts;
if(iv->isLiveDataAssignment()) {
JsonObject obj2 = invArr.createNestedObject();
obj2[F("name")] = String(iv->name);
obj2[F("channels")] = iv->channels;
obj2[F("power_limit_read")] = iv->actPowerLimit;
obj2[F("power_limit_active")] = NoPowerLimit != iv->powerLimit[1];
obj2[F("last_alarm")] = String(iv->lastAlarmMsg);
obj2[F("ts_last_success")] = iv->ts;
JsonArray ch = obj2.createNestedArray("ch");
JsonArray ch0 = ch.createNestedArray();
obj2[F("ch_names")][0] = "AC";
for (uint8_t fld = 0; fld < 11; fld++) {
pos = (iv->getPosByChFld(CH0, list[fld]));
ch0[fld] = (0xff != pos) ? iv->getValue(pos) : 0.0;
obj[F("ch0_fld_units")][fld] = (0xff != pos) ? String(iv->getUnit(pos)) : F("n/a");
obj[F("ch0_fld_names")][fld] = (0xff != pos) ? String(iv->getFieldName(pos)) : F("n/a");
}
JsonArray ch = obj2.createNestedArray("ch");
JsonArray ch0 = ch.createNestedArray();
obj2[F("ch_names")][0] = "AC";
for (uint8_t fld = 0; fld < 11; fld++) {
pos = (iv->getPosByChFld(CH0, list[fld]));
ch0[fld] = (0xff != pos) ? iv->getValue(pos) : 0.0;
obj[F("ch0_fld_units")][fld] = (0xff != pos) ? String(iv->getUnit(pos)) : F("n/a");
obj[F("ch0_fld_names")][fld] = (0xff != pos) ? String(iv->getFieldName(pos)) : F("n/a");
}
for(uint8_t j = 1; j <= iv->channels; j ++) {
obj2[F("ch_names")][j] = String(iv->chName[j-1]);
JsonArray cur = ch.createNestedArray();
for (uint8_t k = 0; k < 6; k++) {
switch(k) {
default: pos = (iv->getPosByChFld(j, FLD_UDC)); break;
case 1: pos = (iv->getPosByChFld(j, FLD_IDC)); break;
case 2: pos = (iv->getPosByChFld(j, FLD_PDC)); break;
case 3: pos = (iv->getPosByChFld(j, FLD_YD)); break;
case 4: pos = (iv->getPosByChFld(j, FLD_YT)); break;
case 5: pos = (iv->getPosByChFld(j, FLD_IRR)); break;
}
cur[k] = (0xff != pos) ? iv->getValue(pos) : 0.0;
if(1 == j) {
obj[F("fld_units")][k] = (0xff != pos) ? String(iv->getUnit(pos)) : F("n/a");
obj[F("fld_names")][k] = (0xff != pos) ? String(iv->getFieldName(pos)) : F("n/a");
for(uint8_t j = 1; j <= iv->channels; j ++) {
obj2[F("ch_names")][j] = String(iv->chName[j-1]);
JsonArray cur = ch.createNestedArray();
for (uint8_t k = 0; k < 6; k++) {
switch(k) {
default: pos = (iv->getPosByChFld(j, FLD_UDC)); break;
case 1: pos = (iv->getPosByChFld(j, FLD_IDC)); break;
case 2: pos = (iv->getPosByChFld(j, FLD_PDC)); break;
case 3: pos = (iv->getPosByChFld(j, FLD_YD)); break;
case 4: pos = (iv->getPosByChFld(j, FLD_YT)); break;
case 5: pos = (iv->getPosByChFld(j, FLD_IRR)); break;
}
cur[k] = (0xff != pos) ? iv->getValue(pos) : 0.0;
if(1 == j) {
obj[F("fld_units")][k] = (0xff != pos) ? String(iv->getUnit(pos)) : F("n/a");
obj[F("fld_names")][k] = (0xff != pos) ? String(iv->getFieldName(pos)) : F("n/a");
}
}
}
}
}
}
}
//-----------------------------------------------------------------------------
bool webApi::setCtrl(DynamicJsonDocument jsonIn, JsonObject jsonOut) {
uint8_t cmd = jsonIn[F("cmd")];
if(TX_REQ_DEVCONTROL == jsonIn[F("tx_request")]) {
DPRINTLN(DBG_INFO, F("devcontrol, cmd: 0x") + String(cmd, HEX));
if(ActivePowerContr == cmd) {
Inverter<> *iv = getInverter(jsonIn, jsonOut);
if(NULL != iv) {
JsonArray payload = jsonIn[F("payload")].as<JsonArray>();
iv->powerLimit[0] = payload[0];
iv->powerLimit[1] = payload[1];
}
}
else if(TurnOn == cmd) {
Inverter<> *iv = getInverter(jsonIn, jsonOut);
if(NULL != iv) {
iv->devControlCmd = TurnOn;
iv->devControlRequest = true;
}
else
return false;
}
else if(TurnOff == cmd) {
Inverter<> *iv = getInverter(jsonIn, jsonOut);
if(NULL != iv) {
iv->devControlCmd = TurnOff;
iv->devControlRequest = true;
}
else
return false;
}
else {
jsonOut["error"] = "unknown 'cmd' = " + String(cmd);
return false;
}
}
else {
jsonOut["error"] = "unknown 'tx_request'";
return false;
}
return true;
}
//-----------------------------------------------------------------------------
Inverter<> *webApi::getInverter(DynamicJsonDocument jsonIn, JsonObject jsonOut) {
uint8_t id = jsonIn[F("inverter")];
Inverter<> *iv = mApp->mSys->getInverterByPos(id);
if(NULL == iv)
jsonOut["error"] = F("inverter index to high: ") + String(id);
return iv;
}