You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

270 lines
11 KiB

//-----------------------------------------------------------------------------
// 2022 Ahoy, https://www.mikrocontroller.net/topic/525778
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
//-----------------------------------------------------------------------------
#if defined(ESP32) && defined(F)
#undef F
#define F(sl) (sl)
#endif
#include "webApi.h"
//-----------------------------------------------------------------------------
webApi::webApi(AsyncWebServer *srv, app *app, sysConfig_t *sysCfg, config_t *config, statistics_t *stat, char version[]) {
mSrv = srv;
mApp = app;
mSysCfg = sysCfg;
mConfig = config;
mStat = stat;
mVersion = version;
}
//-----------------------------------------------------------------------------
void webApi::setup(void) {
mSrv->on("/api", HTTP_GET, std::bind(&webApi::onApi, this, std::placeholders::_1));
}
//-----------------------------------------------------------------------------
void webApi::loop(void) {
}
//-----------------------------------------------------------------------------
void webApi::onApi(AsyncWebServerRequest *request) {
AsyncJsonResponse* response = new AsyncJsonResponse(false, 2048);
JsonObject root = response->getRoot();
String path = request->url().substring(5);
if(path == "system") getSystem(root);
else if(path == "statistics") getStatistics(root);
else if(path == "inverter/list") getInverterList(root);
else if(path == "mqtt") getMqtt(root);
else if(path == "ntp") getNtp(root);
else if(path == "pinout") getPinout(root);
else if(path == "radio") getRadio(root);
else if(path == "serial") getSerial(root);
else if(path == "index") getIndex(root);
else if(path == "setup") getSetup(root);
else if(path == "live") getLive(root);
else
getNotFound(root, F("http://") + request->host() + F("/api/"));
response->setLength();
response->addHeader("Access-Control-Allow-Origin", "*");
response->addHeader("Access-Control-Allow-Headers", "content-type");
request->send(response);
}
//-----------------------------------------------------------------------------
void webApi::getSystem(JsonObject obj) {
obj[F("ssid")] = mSysCfg->stationSsid;
obj[F("device_name")] = mSysCfg->deviceName;
obj[F("version")] = String(mVersion);
obj[F("build")] = String(AUTO_GIT_HASH);
obj[F("ts_uptime")] = mApp->getUptime();
obj[F("ts_now")] = mApp->getTimestamp();
}
//-----------------------------------------------------------------------------
void webApi::getStatistics(JsonObject obj) {
obj[F("rx_success")] = mStat->rxSuccess;
obj[F("rx_fail")] = mStat->rxFail;
obj[F("frame_cnt")] = mStat->frmCnt;
obj[F("tx_cnt")] = mApp->mSys->Radio.mSendCnt;
}
//-----------------------------------------------------------------------------
void webApi::getInverterList(JsonObject obj) {
JsonArray invArr = obj.createNestedArray(F("inverter"));
Inverter<> *iv;
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
iv = mApp->mSys->getInverterByPos(i);
if(NULL != iv) {
JsonObject obj2 = invArr.createNestedObject();
obj2[F("id")] = i;
obj2[F("name")] = String(iv->name);
obj2[F("serial")] = String(iv->serial.u64, HEX);
obj2[F("channels")] = iv->channels;
obj2[F("version")] = String(iv->fwVersion);
for(uint8_t j = 0; j < iv->channels; j ++) {
obj2[F("ch_max_power")][j] = iv->chMaxPwr[j];
obj2[F("ch_name")][j] = iv->chName[j];
}
obj2[F("power_limit")] = iv->powerLimit[0];
obj2[F("power_limit_option")] = iv->powerLimit[1];
}
}
obj[F("interval")] = String(mConfig->sendInterval);
obj[F("retries")] = String(mConfig->maxRetransPerPyld);
obj[F("max_num_inverters")] = MAX_NUM_INVERTERS;
}
//-----------------------------------------------------------------------------
void webApi::getMqtt(JsonObject obj) {
obj[F("broker")] = String(mConfig->mqtt.broker);
obj[F("port")] = String(mConfig->mqtt.port);
obj[F("user")] = String(mConfig->mqtt.user);
obj[F("pwd")] = (strlen(mConfig->mqtt.pwd) > 0) ? F("{PWD}") : String("");
obj[F("topic")] = String(mConfig->mqtt.topic);
}
//-----------------------------------------------------------------------------
void webApi::getNtp(JsonObject obj) {
obj[F("addr")] = String(mConfig->ntpAddr);
obj[F("port")] = String(mConfig->ntpPort);
}
//-----------------------------------------------------------------------------
void webApi::getPinout(JsonObject obj) {
obj[F("cs")] = mConfig->pinCs;
obj[F("ce")] = mConfig->pinCe;
obj[F("irq")] = mConfig->pinIrq;
}
//-----------------------------------------------------------------------------
void webApi::getRadio(JsonObject obj) {
obj[F("power_level")] = mConfig->amplifierPower;
}
//-----------------------------------------------------------------------------
void webApi::getSerial(JsonObject obj) {
obj[F("interval")] = (uint16_t)mConfig->serialInterval;
obj[F("show_live_data")] = mConfig->serialShowIv;
obj[F("debug")] = mConfig->serialDebug;
}
//-----------------------------------------------------------------------------
void webApi::getNotFound(JsonObject obj, String url) {
JsonObject ep = obj.createNestedObject("avail_endpoints");
ep[F("system")] = url + F("system");
ep[F("statistics")] = url + F("statistics");
ep[F("inverter/list")] = url + F("inverter/list");
ep[F("mqtt")] = url + F("mqtt");
ep[F("ntp")] = url + F("ntp");
ep[F("pinout")] = url + F("pinout");
ep[F("radio")] = url + F("radio");
ep[F("serial")] = url + F("serial");
ep[F("index")] = url + F("index");
ep[F("setup")] = url + F("setup");
ep[F("live")] = url + F("live");
}
//-----------------------------------------------------------------------------
void webApi::getIndex(JsonObject obj) {
getSystem(obj.createNestedObject(F("system")));
getStatistics(obj.createNestedObject(F("statistics")));
obj["refresh_interval"] = SEND_INTERVAL;
JsonArray inv = obj.createNestedArray(F("inverter"));
Inverter<> *iv;
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
iv = mApp->mSys->getInverterByPos(i);
if(NULL != iv) {
JsonObject invObj = inv.createNestedObject();
invObj[F("id")] = i;
invObj[F("name")] = String(iv->name);
invObj[F("version")] = String(iv->fwVersion);
invObj[F("is_avail")] = iv->isAvailable(mApp->getTimestamp());
invObj[F("is_producing")] = iv->isProducing(mApp->getTimestamp());
invObj[F("ts_last_success")] = iv->getLastTs();
}
}
JsonArray warn = obj.createNestedArray(F("warnings"));
if(!mApp->mSys->Radio.isChipConnected())
warn.add(F("your NRF24 module can't be reached, check the wiring and pinout"));
if(!mApp->mqttIsConnected())
warn.add(F("MQTT is not connected"));
JsonArray info = obj.createNestedArray(F("infos"));
if(mApp->getRebootRequestState())
info.add(F("reboot your ESP to apply all your configuration changes!"));
if(!mApp->getSettingsValid())
info.add(F("your settings are invalid"));
if(mApp->mqttIsConnected())
info.add(F("MQTT is connected"));
}
//-----------------------------------------------------------------------------
void webApi::getSetup(JsonObject obj) {
getSystem(obj.createNestedObject(F("system")));
getInverterList(obj.createNestedObject(F("inverter")));
getMqtt(obj.createNestedObject(F("mqtt")));
getNtp(obj.createNestedObject(F("ntp")));
getPinout(obj.createNestedObject(F("pinout")));
getRadio(obj.createNestedObject(F("radio")));
getSerial(obj.createNestedObject(F("serial")));
}
//-----------------------------------------------------------------------------
void webApi::getLive(JsonObject obj) {
JsonArray invArr = obj.createNestedArray(F("inverter"));
uint8_t list[] = {FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_PCT, FLD_T, FLD_YT, FLD_YD, FLD_PDC, FLD_EFF, FLD_PRA, FLD_ALARM_MES_ID};
Inverter<> *iv;
uint8_t pos;
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
iv = mApp->mSys->getInverterByPos(i);
if(NULL != iv) {
JsonObject obj2 = invArr.createNestedObject();
obj2[F("id")] = i;
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();
for (uint8_t fld = 0; fld < 11; fld++) {
pos = (iv->getPosByChFld(CH0, list[fld]));
if (0xff != pos) {
JsonObject dat = ch0.createNestedObject();
dat[F("value")] = iv->getValue(pos);
dat[F("unit")] = String(iv->getUnit(pos));
dat[F("name")] = String(iv->getFieldName(pos));
}
}
for(uint8_t j = 0; j < iv->channels; j ++) {
obj2[F("ch_names")][j] = iv->chName[j];
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;
if(0xff != pos) {
obj2[F("fld_units")][k] = String(iv->getUnit(pos));
obj2[F("fld_names")][k] = String(iv->getFieldName(pos));
}
}
}
}
}
}