diff --git a/Getting_Started.md b/Getting_Started.md index 4b3d55c2..bca334d3 100644 --- a/Getting_Started.md +++ b/Getting_Started.md @@ -218,19 +218,20 @@ When everything is wired up and the firmware is flashed, it is time to connect t To take control of your Ahoy DTU, you can directly call one of the following sub-pages (e.g. [http://ahoy-dtu/setup](http://ahoy-dtu/setup) or [http://192.168.1.1/setup](http://192.168.1.1/setup) ).
-| page | use | output | -| ---- | ------ | ------ | -| /uptime | displays the uptime of your Ahoy DTU | 0 Days, 01:37:34; now: 2022-08-21 11:13:53 | -| /reboot | reboots the Ahoy DTU | | -| /erase | erases the EEPROM | | -| /factory | resets to the factory defaults configured in config.h | | -| /setup | opens the setup page | | -| /save | | | -| /cmdstat | show stat from the home page | | -| /visualization | displays the information from your converter | | -| /livedata | displays the live data | | -| /json | gets live-data in JSON format | json output from the livedata | -| /api | | | +| page | use | output | default availability | +| ---- | ------ | ------ | ------ | +| /uptime | displays the uptime uf your Ahoy DTU | 0 Days, 01:37:34; now: 2022-08-21 11:13:53 | yes | +| /reboot | reboots the Ahoy DTU | | yes | +| /erase | erases the EEPROM | | yes | +| /factory | resets to the factory defaults configured in config.h | | yes | +| /setup | opens the setup page | | yes | +| /save | | | yes | +| /cmdstat | show stat from the home page | | yes | +| /visualization | displays the information from your converter | | yes | +| /livedata | displays the live data | | yes | +| /json | gets live-data in JSON format | json output from the livedata | no - enable via config_override.h | +| /metrics | gets live-data for prometheus | prometheus metrics from the livedata | no - enable via config_override.h | +| /api | | | yes | ## MQTT command to set the DTU without webinterface diff --git a/src/config/config.h b/src/config/config.h index b940ec80..66dc22f9 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -46,9 +46,15 @@ #define DEF_DEVICE_NAME "AHOY-DTU" // default pinout (GPIO Number) -#define DEF_CS_PIN 15 -#define DEF_CE_PIN 2 -#define DEF_IRQ_PIN 0 +#if defined(ESP32) + #define DEF_CS_PIN 15 + #define DEF_CE_PIN 2 + #define DEF_IRQ_PIN 0 +#else + #define DEF_CS_PIN 5 + #define DEF_CE_PIN 4 + #define DEF_IRQ_PIN 16 +#endif #define DEF_LED0_PIN 255 // off #define DEF_LED1_PIN 255 // off diff --git a/src/config/config_override_example.h b/src/config/config_override_example.h index 81c35dbf..443d8969 100644 --- a/src/config/config_override_example.h +++ b/src/config/config_override_example.h @@ -25,4 +25,12 @@ #undef DEF_RF24_IRQ_PIN #define DEF_RF24_IRQ_PIN 16 + +// To enable the json endpoint at /json +// #define ENABLE_JSON_EP + +// To enable the endpoint for prometheus to scrape data from at /metrics +// #define ENABLE_PROMETHEUS_EP + + #endif /*__CONFIG_OVERRIDE_H__*/ diff --git a/src/defines.h b/src/defines.h index b8f5a43c..389e4144 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 33 +#define VERSION_PATCH 34 //------------------------------------- typedef struct { diff --git a/src/web/web.cpp b/src/web/web.cpp index 0541cd14..6b4f9179 100644 --- a/src/web/web.cpp +++ b/src/web/web.cpp @@ -68,6 +68,12 @@ void web::setup(void) { mWeb->on("/live", HTTP_ANY, std::bind(&web::onLive, this, std::placeholders::_1)); mWeb->on("/api1", HTTP_POST, std::bind(&web::showWebApi, this, std::placeholders::_1)); +#ifdef ENABLE_JSON_EP + mWeb->on("/json", HTTP_ANY, std::bind(&web::showJson, this, std::placeholders::_1)); +#endif +#ifdef ENABLE_PROMETHEUS_EP + mWeb->on("/metrics", HTTP_ANY, std::bind(&web::showMetrics, this, std::placeholders::_1)); +#endif mWeb->on("/update", HTTP_GET, std::bind(&web::onUpdate, this, std::placeholders::_1)); mWeb->on("/update", HTTP_POST, std::bind(&web::showUpdate, this, std::placeholders::_1), @@ -641,3 +647,79 @@ void web::serialCb(String msg) { } } + + +//----------------------------------------------------------------------------- +#ifdef ENABLE_JSON_EP +void web::showJson(void) { + DPRINTLN(DBG_VERBOSE, F("web::showJson")); + String modJson; + + modJson = F("{\n"); + for(uint8_t id = 0; id < mMain->mSys->getNumInverters(); id++) { + Inverter<> *iv = mMain->mSys->getInverterByPos(id); + if(NULL != iv) { + char topic[40], val[25]; + snprintf(topic, 30, "\"%s\": {\n", iv->name); + modJson += String(topic); + for(uint8_t i = 0; i < iv->listLen; i++) { + snprintf(topic, 40, "\t\"ch%d/%s\"", iv->assign[i].ch, iv->getFieldName(i)); + snprintf(val, 25, "[%.3f, \"%s\"]", iv->getValue(i), iv->getUnit(i)); + modJson += String(topic) + ": " + String(val) + F(",\n"); + } + modJson += F("\t\"last_msg\": \"") + mMain->getDateTimeStr(iv->ts) + F("\"\n\t},\n"); + } + } + modJson += F("\"json_ts\": \"") + String(mMain->getDateTimeStr(mMain->mTimestamp)) + F("\"\n}\n"); + + mWeb->send(200, F("application/json"), modJson); +} +#endif + + +//----------------------------------------------------------------------------- +#ifdef ENABLE_PROMETHEUS_EP +std::pair web::convertToPromUnits(String shortUnit) { + + if(shortUnit == "A") return {"ampere", "gauge"}; + if(shortUnit == "V") return {"volt", "gauge"}; + if(shortUnit == "%") return {"ratio", "gauge"}; + if(shortUnit == "W") return {"watt", "gauge"}; + if(shortUnit == "Wh") return {"watt_daily", "counter"}; + if(shortUnit == "kWh") return {"watt_total", "counter"}; + if(shortUnit == "°C") return {"celsius", "gauge"}; + + return {"", "gauge"}; +} + + +//----------------------------------------------------------------------------- +void web::showMetrics(void) { + DPRINTLN(DBG_VERBOSE, F("web::showMetrics")); + String metrics; + char headline[80]; + + snprintf(headline, 80, "ahoy_solar_info{version=\"%s\",image=\"\",devicename=\"%s\"} 1", mVersion, mSysCfg->deviceName); + metrics += "# TYPE ahoy_solar_info gauge\n" + String(headline) + "\n"; + + for(uint8_t id = 0; id < mMain->mSys->getNumInverters(); id++) { + Inverter<> *iv = mMain->mSys->getInverterByPos(id); + if(NULL != iv) { + char type[60], topic[60], val[25]; + for(uint8_t i = 0; i < iv->listLen; i++) { + uint8_t channel = iv->assign[i].ch; + if(channel == 0) { + String promUnit, promType; + std::tie(promUnit, promType) = convertToPromUnits( iv->getUnit(i) ); + snprintf(type, 60, "# TYPE ahoy_solar_%s_%s %s", iv->getFieldName(i), promUnit.c_str(), promType.c_str()); + snprintf(topic, 60, "ahoy_solar_%s_%s{inverter=\"%s\"}", iv->getFieldName(i), promUnit.c_str(), iv->name); + snprintf(val, 25, "%.3f", iv->getValue(i)); + metrics += String(type) + "\n" + String(topic) + " " + String(val) + "\n"; + } + } + } + } + + mWeb->send(200, F("text/plain"), metrics); +} +#endif diff --git a/src/web/web.h b/src/web/web.h index 99805c8b..6e32f8b6 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -33,6 +33,14 @@ class web { void setProtection(bool protect); + + void onUpdate(AsyncWebServerRequest *request); + void showUpdate(AsyncWebServerRequest *request); + void showUpdate2(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final); + + void serialCb(String msg); + + private: void onConnect(AsyncEventSourceClient *client); void onIndex(AsyncWebServerRequest *request); @@ -51,13 +59,6 @@ class web { void onLive(AsyncWebServerRequest *request); void showWebApi(AsyncWebServerRequest *request); - void onUpdate(AsyncWebServerRequest *request); - void showUpdate(AsyncWebServerRequest *request); - void showUpdate2(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final); - - void serialCb(String msg); - - private: void onSerial(AsyncWebServerRequest *request); void onSystem(AsyncWebServerRequest *request); @@ -70,6 +71,15 @@ class web { } } +#ifdef ENABLE_JSON_EP + void showJson(void); +#endif + +#ifdef ENABLE_PROMETHEUS_EP + void showMetrics(void); + std::pair convertToPromUnits(String shortUnit); +#endif + AsyncWebServer *mWeb; AsyncEventSource *mEvts; bool mProtected; diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 7a78cec0..bdbea216 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -110,7 +110,7 @@ bool ahoywifi::loop(void) { //----------------------------------------------------------------------------- void ahoywifi::setupAp(const char *ssid, const char *pwd) { DPRINTLN(DBG_VERBOSE, F("app::setupAp")); - IPAddress apIp(192, 168, 1, 1); + IPAddress apIp(192, 168, 4, 1); DPRINTLN(DBG_INFO, F("\n---------\nAP MODE\nSSID: ") + String(ssid) + F("\nPWD: ")