From 2716f4c5df94a439dd3c8eca84496da08f52c67c Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Sat, 27 Jan 2024 01:09:55 +0100 Subject: [PATCH 01/57] Removed not required pointer to AsyncServer instance --- include/WebApi_config.h | 2 -- include/WebApi_device.h | 2 -- include/WebApi_devinfo.h | 2 -- include/WebApi_dtu.h | 2 -- include/WebApi_eventlog.h | 2 -- include/WebApi_firmware.h | 2 -- include/WebApi_gridprofile.h | 2 -- include/WebApi_inverter.h | 2 -- include/WebApi_limit.h | 2 -- include/WebApi_maintenance.h | 2 -- include/WebApi_mqtt.h | 2 -- include/WebApi_network.h | 2 -- include/WebApi_ntp.h | 2 -- include/WebApi_power.h | 2 -- include/WebApi_prometheus.h | 2 -- include/WebApi_security.h | 2 -- include/WebApi_sysstatus.h | 2 -- include/WebApi_webapp.h | 3 --- include/WebApi_ws_console.h | 1 - include/WebApi_ws_live.h | 1 - src/WebApi_config.cpp | 10 ++++------ src/WebApi_device.cpp | 6 ++---- src/WebApi_devinfo.cpp | 4 +--- src/WebApi_dtu.cpp | 6 ++---- src/WebApi_eventlog.cpp | 4 +--- src/WebApi_firmware.cpp | 4 +--- src/WebApi_gridprofile.cpp | 6 ++---- src/WebApi_inverter.cpp | 12 +++++------- src/WebApi_limit.cpp | 6 ++---- src/WebApi_maintenance.cpp | 4 +--- src/WebApi_mqtt.cpp | 8 +++----- src/WebApi_network.cpp | 8 +++----- src/WebApi_ntp.cpp | 12 +++++------- src/WebApi_power.cpp | 6 ++---- src/WebApi_prometheus.cpp | 4 +--- src/WebApi_security.cpp | 8 +++----- src/WebApi_sysstatus.cpp | 4 +--- src/WebApi_webapp.cpp | 18 ++++++++---------- src/WebApi_ws_console.cpp | 3 +-- src/WebApi_ws_live.cpp | 5 ++--- 40 files changed, 50 insertions(+), 127 deletions(-) diff --git a/include/WebApi_config.h b/include/WebApi_config.h index 91243c18c..f29dc8fcf 100644 --- a/include/WebApi_config.h +++ b/include/WebApi_config.h @@ -14,6 +14,4 @@ class WebApiConfigClass { void onConfigListGet(AsyncWebServerRequest* request); void onConfigUploadFinish(AsyncWebServerRequest* request); void onConfigUpload(AsyncWebServerRequest* request, String filename, size_t index, uint8_t* data, size_t len, bool final); - - AsyncWebServer* _server; }; diff --git a/include/WebApi_device.h b/include/WebApi_device.h index f74315e34..48976bce6 100644 --- a/include/WebApi_device.h +++ b/include/WebApi_device.h @@ -11,6 +11,4 @@ class WebApiDeviceClass { private: void onDeviceAdminGet(AsyncWebServerRequest* request); void onDeviceAdminPost(AsyncWebServerRequest* request); - - AsyncWebServer* _server; }; diff --git a/include/WebApi_devinfo.h b/include/WebApi_devinfo.h index d1924ecc0..e312ecdf0 100644 --- a/include/WebApi_devinfo.h +++ b/include/WebApi_devinfo.h @@ -10,6 +10,4 @@ class WebApiDevInfoClass { private: void onDevInfoStatus(AsyncWebServerRequest* request); - - AsyncWebServer* _server; }; diff --git a/include/WebApi_dtu.h b/include/WebApi_dtu.h index 3acf4494d..20f5274e6 100644 --- a/include/WebApi_dtu.h +++ b/include/WebApi_dtu.h @@ -13,8 +13,6 @@ class WebApiDtuClass { void onDtuAdminGet(AsyncWebServerRequest* request); void onDtuAdminPost(AsyncWebServerRequest* request); - AsyncWebServer* _server; - Task _applyDataTask; void applyDataTaskCb(); }; diff --git a/include/WebApi_eventlog.h b/include/WebApi_eventlog.h index 3cba7e5e5..e7fe9874a 100644 --- a/include/WebApi_eventlog.h +++ b/include/WebApi_eventlog.h @@ -10,6 +10,4 @@ class WebApiEventlogClass { private: void onEventlogStatus(AsyncWebServerRequest* request); - - AsyncWebServer* _server; }; diff --git a/include/WebApi_firmware.h b/include/WebApi_firmware.h index fd9a96428..990a5e064 100644 --- a/include/WebApi_firmware.h +++ b/include/WebApi_firmware.h @@ -11,6 +11,4 @@ class WebApiFirmwareClass { private: void onFirmwareUpdateFinish(AsyncWebServerRequest* request); void onFirmwareUpdateUpload(AsyncWebServerRequest* request, String filename, size_t index, uint8_t* data, size_t len, bool final); - - AsyncWebServer* _server; }; diff --git a/include/WebApi_gridprofile.h b/include/WebApi_gridprofile.h index 73c156540..cff4ddb86 100644 --- a/include/WebApi_gridprofile.h +++ b/include/WebApi_gridprofile.h @@ -11,6 +11,4 @@ class WebApiGridProfileClass { private: void onGridProfileStatus(AsyncWebServerRequest* request); void onGridProfileRawdata(AsyncWebServerRequest* request); - - AsyncWebServer* _server; }; diff --git a/include/WebApi_inverter.h b/include/WebApi_inverter.h index b8f054256..c316622e5 100644 --- a/include/WebApi_inverter.h +++ b/include/WebApi_inverter.h @@ -14,6 +14,4 @@ class WebApiInverterClass { void onInverterEdit(AsyncWebServerRequest* request); void onInverterDelete(AsyncWebServerRequest* request); void onInverterOrder(AsyncWebServerRequest* request); - - AsyncWebServer* _server; }; diff --git a/include/WebApi_limit.h b/include/WebApi_limit.h index 84d48d3a3..285be27cc 100644 --- a/include/WebApi_limit.h +++ b/include/WebApi_limit.h @@ -11,6 +11,4 @@ class WebApiLimitClass { private: void onLimitStatus(AsyncWebServerRequest* request); void onLimitPost(AsyncWebServerRequest* request); - - AsyncWebServer* _server; }; diff --git a/include/WebApi_maintenance.h b/include/WebApi_maintenance.h index 02dc4702f..5a00bbab8 100644 --- a/include/WebApi_maintenance.h +++ b/include/WebApi_maintenance.h @@ -10,6 +10,4 @@ class WebApiMaintenanceClass { private: void onRebootPost(AsyncWebServerRequest* request); - - AsyncWebServer* _server; }; diff --git a/include/WebApi_mqtt.h b/include/WebApi_mqtt.h index 6ec971c93..b259752b1 100644 --- a/include/WebApi_mqtt.h +++ b/include/WebApi_mqtt.h @@ -15,6 +15,4 @@ class WebApiMqttClass { void onMqttAdminGet(AsyncWebServerRequest* request); void onMqttAdminPost(AsyncWebServerRequest* request); String getTlsCertInfo(const char* cert); - - AsyncWebServer* _server; }; diff --git a/include/WebApi_network.h b/include/WebApi_network.h index 7587bbbd3..179fa4920 100644 --- a/include/WebApi_network.h +++ b/include/WebApi_network.h @@ -12,6 +12,4 @@ class WebApiNetworkClass { void onNetworkStatus(AsyncWebServerRequest* request); void onNetworkAdminGet(AsyncWebServerRequest* request); void onNetworkAdminPost(AsyncWebServerRequest* request); - - AsyncWebServer* _server; }; diff --git a/include/WebApi_ntp.h b/include/WebApi_ntp.h index 75e02c549..5ce040ede 100644 --- a/include/WebApi_ntp.h +++ b/include/WebApi_ntp.h @@ -14,6 +14,4 @@ class WebApiNtpClass { void onNtpAdminPost(AsyncWebServerRequest* request); void onNtpTimeGet(AsyncWebServerRequest* request); void onNtpTimePost(AsyncWebServerRequest* request); - - AsyncWebServer* _server; }; diff --git a/include/WebApi_power.h b/include/WebApi_power.h index 7d186eb4d..aed11b0ef 100644 --- a/include/WebApi_power.h +++ b/include/WebApi_power.h @@ -11,6 +11,4 @@ class WebApiPowerClass { private: void onPowerStatus(AsyncWebServerRequest* request); void onPowerPost(AsyncWebServerRequest* request); - - AsyncWebServer* _server; }; diff --git a/include/WebApi_prometheus.h b/include/WebApi_prometheus.h index 08e2221df..b3ee6a18c 100644 --- a/include/WebApi_prometheus.h +++ b/include/WebApi_prometheus.h @@ -17,8 +17,6 @@ class WebApiPrometheusClass { void addPanelInfo(AsyncResponseStream* stream, const String& serial, const uint8_t idx, std::shared_ptr inv, const ChannelType_t type, const ChannelNum_t channel); - AsyncWebServer* _server; - enum MetricType_t { NONE = 0, GAUGE, diff --git a/include/WebApi_security.h b/include/WebApi_security.h index b5981e3d4..ac76522a5 100644 --- a/include/WebApi_security.h +++ b/include/WebApi_security.h @@ -13,6 +13,4 @@ class WebApiSecurityClass { void onSecurityPost(AsyncWebServerRequest* request); void onAuthenticateGet(AsyncWebServerRequest* request); - - AsyncWebServer* _server; }; diff --git a/include/WebApi_sysstatus.h b/include/WebApi_sysstatus.h index 32bdc7e3e..c754ac0df 100644 --- a/include/WebApi_sysstatus.h +++ b/include/WebApi_sysstatus.h @@ -10,6 +10,4 @@ class WebApiSysstatusClass { private: void onSystemStatus(AsyncWebServerRequest* request); - - AsyncWebServer* _server; }; diff --git a/include/WebApi_webapp.h b/include/WebApi_webapp.h index 401408c61..abbff8b64 100644 --- a/include/WebApi_webapp.h +++ b/include/WebApi_webapp.h @@ -7,7 +7,4 @@ class WebApiWebappClass { public: void init(AsyncWebServer& server, Scheduler& scheduler); - -private: - AsyncWebServer* _server; }; diff --git a/include/WebApi_ws_console.h b/include/WebApi_ws_console.h index 4289afd0f..cf7beecce 100644 --- a/include/WebApi_ws_console.h +++ b/include/WebApi_ws_console.h @@ -10,7 +10,6 @@ class WebApiWsConsoleClass { void init(AsyncWebServer& server, Scheduler& scheduler); private: - AsyncWebServer* _server; AsyncWebSocket _ws; Task _wsCleanupTask; diff --git a/include/WebApi_ws_live.h b/include/WebApi_ws_live.h index 392ca8696..9adc848e1 100644 --- a/include/WebApi_ws_live.h +++ b/include/WebApi_ws_live.h @@ -18,7 +18,6 @@ class WebApiWsLiveClass { void onLivedataStatus(AsyncWebServerRequest* request); void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len); - AsyncWebServer* _server; AsyncWebSocket _ws; uint32_t _lastWsPublish = 0; diff --git a/src/WebApi_config.cpp b/src/WebApi_config.cpp index 3372e4f45..c275ffc71 100644 --- a/src/WebApi_config.cpp +++ b/src/WebApi_config.cpp @@ -19,12 +19,10 @@ void WebApiConfigClass::init(AsyncWebServer& server, Scheduler& scheduler) using std::placeholders::_5; using std::placeholders::_6; - _server = &server; - - _server->on("/api/config/get", HTTP_GET, std::bind(&WebApiConfigClass::onConfigGet, this, _1)); - _server->on("/api/config/delete", HTTP_POST, std::bind(&WebApiConfigClass::onConfigDelete, this, _1)); - _server->on("/api/config/list", HTTP_GET, std::bind(&WebApiConfigClass::onConfigListGet, this, _1)); - _server->on("/api/config/upload", HTTP_POST, + server.on("/api/config/get", HTTP_GET, std::bind(&WebApiConfigClass::onConfigGet, this, _1)); + server.on("/api/config/delete", HTTP_POST, std::bind(&WebApiConfigClass::onConfigDelete, this, _1)); + server.on("/api/config/list", HTTP_GET, std::bind(&WebApiConfigClass::onConfigListGet, this, _1)); + server.on("/api/config/upload", HTTP_POST, std::bind(&WebApiConfigClass::onConfigUploadFinish, this, _1), std::bind(&WebApiConfigClass::onConfigUpload, this, _1, _2, _3, _4, _5, _6)); } diff --git a/src/WebApi_device.cpp b/src/WebApi_device.cpp index 5f43b37dc..b29f71db0 100644 --- a/src/WebApi_device.cpp +++ b/src/WebApi_device.cpp @@ -16,10 +16,8 @@ void WebApiDeviceClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; - _server = &server; - - _server->on("/api/device/config", HTTP_GET, std::bind(&WebApiDeviceClass::onDeviceAdminGet, this, _1)); - _server->on("/api/device/config", HTTP_POST, std::bind(&WebApiDeviceClass::onDeviceAdminPost, this, _1)); + server.on("/api/device/config", HTTP_GET, std::bind(&WebApiDeviceClass::onDeviceAdminGet, this, _1)); + server.on("/api/device/config", HTTP_POST, std::bind(&WebApiDeviceClass::onDeviceAdminPost, this, _1)); } void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request) diff --git a/src/WebApi_devinfo.cpp b/src/WebApi_devinfo.cpp index a27cb31ee..212a7f7d5 100644 --- a/src/WebApi_devinfo.cpp +++ b/src/WebApi_devinfo.cpp @@ -12,9 +12,7 @@ void WebApiDevInfoClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; - _server = &server; - - _server->on("/api/devinfo/status", HTTP_GET, std::bind(&WebApiDevInfoClass::onDevInfoStatus, this, _1)); + server.on("/api/devinfo/status", HTTP_GET, std::bind(&WebApiDevInfoClass::onDevInfoStatus, this, _1)); } void WebApiDevInfoClass::onDevInfoStatus(AsyncWebServerRequest* request) diff --git a/src/WebApi_dtu.cpp b/src/WebApi_dtu.cpp index 7886afce6..aed098340 100644 --- a/src/WebApi_dtu.cpp +++ b/src/WebApi_dtu.cpp @@ -18,10 +18,8 @@ void WebApiDtuClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; - _server = &server; - - _server->on("/api/dtu/config", HTTP_GET, std::bind(&WebApiDtuClass::onDtuAdminGet, this, _1)); - _server->on("/api/dtu/config", HTTP_POST, std::bind(&WebApiDtuClass::onDtuAdminPost, this, _1)); + server.on("/api/dtu/config", HTTP_GET, std::bind(&WebApiDtuClass::onDtuAdminGet, this, _1)); + server.on("/api/dtu/config", HTTP_POST, std::bind(&WebApiDtuClass::onDtuAdminPost, this, _1)); scheduler.addTask(_applyDataTask); } diff --git a/src/WebApi_eventlog.cpp b/src/WebApi_eventlog.cpp index a92e515e7..51e85affa 100644 --- a/src/WebApi_eventlog.cpp +++ b/src/WebApi_eventlog.cpp @@ -11,9 +11,7 @@ void WebApiEventlogClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; - _server = &server; - - _server->on("/api/eventlog/status", HTTP_GET, std::bind(&WebApiEventlogClass::onEventlogStatus, this, _1)); + server.on("/api/eventlog/status", HTTP_GET, std::bind(&WebApiEventlogClass::onEventlogStatus, this, _1)); } void WebApiEventlogClass::onEventlogStatus(AsyncWebServerRequest* request) diff --git a/src/WebApi_firmware.cpp b/src/WebApi_firmware.cpp index 617fca067..9491f935d 100644 --- a/src/WebApi_firmware.cpp +++ b/src/WebApi_firmware.cpp @@ -19,9 +19,7 @@ void WebApiFirmwareClass::init(AsyncWebServer& server, Scheduler& scheduler) using std::placeholders::_5; using std::placeholders::_6; - _server = &server; - - _server->on("/api/firmware/update", HTTP_POST, + server.on("/api/firmware/update", HTTP_POST, std::bind(&WebApiFirmwareClass::onFirmwareUpdateFinish, this, _1), std::bind(&WebApiFirmwareClass::onFirmwareUpdateUpload, this, _1, _2, _3, _4, _5, _6)); } diff --git a/src/WebApi_gridprofile.cpp b/src/WebApi_gridprofile.cpp index 587f46400..60c340fa0 100644 --- a/src/WebApi_gridprofile.cpp +++ b/src/WebApi_gridprofile.cpp @@ -11,10 +11,8 @@ void WebApiGridProfileClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; - _server = &server; - - _server->on("/api/gridprofile/status", HTTP_GET, std::bind(&WebApiGridProfileClass::onGridProfileStatus, this, _1)); - _server->on("/api/gridprofile/rawdata", HTTP_GET, std::bind(&WebApiGridProfileClass::onGridProfileRawdata, this, _1)); + server.on("/api/gridprofile/status", HTTP_GET, std::bind(&WebApiGridProfileClass::onGridProfileStatus, this, _1)); + server.on("/api/gridprofile/rawdata", HTTP_GET, std::bind(&WebApiGridProfileClass::onGridProfileRawdata, this, _1)); } void WebApiGridProfileClass::onGridProfileStatus(AsyncWebServerRequest* request) diff --git a/src/WebApi_inverter.cpp b/src/WebApi_inverter.cpp index f1bfc2aa5..32a472350 100644 --- a/src/WebApi_inverter.cpp +++ b/src/WebApi_inverter.cpp @@ -16,13 +16,11 @@ void WebApiInverterClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; - _server = &server; - - _server->on("/api/inverter/list", HTTP_GET, std::bind(&WebApiInverterClass::onInverterList, this, _1)); - _server->on("/api/inverter/add", HTTP_POST, std::bind(&WebApiInverterClass::onInverterAdd, this, _1)); - _server->on("/api/inverter/edit", HTTP_POST, std::bind(&WebApiInverterClass::onInverterEdit, this, _1)); - _server->on("/api/inverter/del", HTTP_POST, std::bind(&WebApiInverterClass::onInverterDelete, this, _1)); - _server->on("/api/inverter/order", HTTP_POST, std::bind(&WebApiInverterClass::onInverterOrder, this, _1)); + server.on("/api/inverter/list", HTTP_GET, std::bind(&WebApiInverterClass::onInverterList, this, _1)); + server.on("/api/inverter/add", HTTP_POST, std::bind(&WebApiInverterClass::onInverterAdd, this, _1)); + server.on("/api/inverter/edit", HTTP_POST, std::bind(&WebApiInverterClass::onInverterEdit, this, _1)); + server.on("/api/inverter/del", HTTP_POST, std::bind(&WebApiInverterClass::onInverterDelete, this, _1)); + server.on("/api/inverter/order", HTTP_POST, std::bind(&WebApiInverterClass::onInverterOrder, this, _1)); } void WebApiInverterClass::onInverterList(AsyncWebServerRequest* request) diff --git a/src/WebApi_limit.cpp b/src/WebApi_limit.cpp index be8e1202f..1d9c111a5 100644 --- a/src/WebApi_limit.cpp +++ b/src/WebApi_limit.cpp @@ -14,10 +14,8 @@ void WebApiLimitClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; - _server = &server; - - _server->on("/api/limit/status", HTTP_GET, std::bind(&WebApiLimitClass::onLimitStatus, this, _1)); - _server->on("/api/limit/config", HTTP_POST, std::bind(&WebApiLimitClass::onLimitPost, this, _1)); + server.on("/api/limit/status", HTTP_GET, std::bind(&WebApiLimitClass::onLimitStatus, this, _1)); + server.on("/api/limit/config", HTTP_POST, std::bind(&WebApiLimitClass::onLimitPost, this, _1)); } void WebApiLimitClass::onLimitStatus(AsyncWebServerRequest* request) diff --git a/src/WebApi_maintenance.cpp b/src/WebApi_maintenance.cpp index 922b0ba09..ba257efa8 100644 --- a/src/WebApi_maintenance.cpp +++ b/src/WebApi_maintenance.cpp @@ -13,9 +13,7 @@ void WebApiMaintenanceClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; - _server = &server; - - _server->on("/api/maintenance/reboot", HTTP_POST, std::bind(&WebApiMaintenanceClass::onRebootPost, this, _1)); + server.on("/api/maintenance/reboot", HTTP_POST, std::bind(&WebApiMaintenanceClass::onRebootPost, this, _1)); } void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request) diff --git a/src/WebApi_mqtt.cpp b/src/WebApi_mqtt.cpp index 2361c44e8..a10d0d0b3 100644 --- a/src/WebApi_mqtt.cpp +++ b/src/WebApi_mqtt.cpp @@ -15,11 +15,9 @@ void WebApiMqttClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; - _server = &server; - - _server->on("/api/mqtt/status", HTTP_GET, std::bind(&WebApiMqttClass::onMqttStatus, this, _1)); - _server->on("/api/mqtt/config", HTTP_GET, std::bind(&WebApiMqttClass::onMqttAdminGet, this, _1)); - _server->on("/api/mqtt/config", HTTP_POST, std::bind(&WebApiMqttClass::onMqttAdminPost, this, _1)); + server.on("/api/mqtt/status", HTTP_GET, std::bind(&WebApiMqttClass::onMqttStatus, this, _1)); + server.on("/api/mqtt/config", HTTP_GET, std::bind(&WebApiMqttClass::onMqttAdminGet, this, _1)); + server.on("/api/mqtt/config", HTTP_POST, std::bind(&WebApiMqttClass::onMqttAdminPost, this, _1)); } void WebApiMqttClass::onMqttStatus(AsyncWebServerRequest* request) diff --git a/src/WebApi_network.cpp b/src/WebApi_network.cpp index ba9980539..12f637adc 100644 --- a/src/WebApi_network.cpp +++ b/src/WebApi_network.cpp @@ -14,11 +14,9 @@ void WebApiNetworkClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; - _server = &server; - - _server->on("/api/network/status", HTTP_GET, std::bind(&WebApiNetworkClass::onNetworkStatus, this, _1)); - _server->on("/api/network/config", HTTP_GET, std::bind(&WebApiNetworkClass::onNetworkAdminGet, this, _1)); - _server->on("/api/network/config", HTTP_POST, std::bind(&WebApiNetworkClass::onNetworkAdminPost, this, _1)); + server.on("/api/network/status", HTTP_GET, std::bind(&WebApiNetworkClass::onNetworkStatus, this, _1)); + server.on("/api/network/config", HTTP_GET, std::bind(&WebApiNetworkClass::onNetworkAdminGet, this, _1)); + server.on("/api/network/config", HTTP_POST, std::bind(&WebApiNetworkClass::onNetworkAdminPost, this, _1)); } void WebApiNetworkClass::onNetworkStatus(AsyncWebServerRequest* request) diff --git a/src/WebApi_ntp.cpp b/src/WebApi_ntp.cpp index e0bcd6992..02bbfb105 100644 --- a/src/WebApi_ntp.cpp +++ b/src/WebApi_ntp.cpp @@ -15,13 +15,11 @@ void WebApiNtpClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; - _server = &server; - - _server->on("/api/ntp/status", HTTP_GET, std::bind(&WebApiNtpClass::onNtpStatus, this, _1)); - _server->on("/api/ntp/config", HTTP_GET, std::bind(&WebApiNtpClass::onNtpAdminGet, this, _1)); - _server->on("/api/ntp/config", HTTP_POST, std::bind(&WebApiNtpClass::onNtpAdminPost, this, _1)); - _server->on("/api/ntp/time", HTTP_GET, std::bind(&WebApiNtpClass::onNtpTimeGet, this, _1)); - _server->on("/api/ntp/time", HTTP_POST, std::bind(&WebApiNtpClass::onNtpTimePost, this, _1)); + server.on("/api/ntp/status", HTTP_GET, std::bind(&WebApiNtpClass::onNtpStatus, this, _1)); + server.on("/api/ntp/config", HTTP_GET, std::bind(&WebApiNtpClass::onNtpAdminGet, this, _1)); + server.on("/api/ntp/config", HTTP_POST, std::bind(&WebApiNtpClass::onNtpAdminPost, this, _1)); + server.on("/api/ntp/time", HTTP_GET, std::bind(&WebApiNtpClass::onNtpTimeGet, this, _1)); + server.on("/api/ntp/time", HTTP_POST, std::bind(&WebApiNtpClass::onNtpTimePost, this, _1)); } void WebApiNtpClass::onNtpStatus(AsyncWebServerRequest* request) diff --git a/src/WebApi_power.cpp b/src/WebApi_power.cpp index 54fc664ef..b51967894 100644 --- a/src/WebApi_power.cpp +++ b/src/WebApi_power.cpp @@ -12,10 +12,8 @@ void WebApiPowerClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; - _server = &server; - - _server->on("/api/power/status", HTTP_GET, std::bind(&WebApiPowerClass::onPowerStatus, this, _1)); - _server->on("/api/power/config", HTTP_POST, std::bind(&WebApiPowerClass::onPowerPost, this, _1)); + server.on("/api/power/status", HTTP_GET, std::bind(&WebApiPowerClass::onPowerStatus, this, _1)); + server.on("/api/power/config", HTTP_POST, std::bind(&WebApiPowerClass::onPowerPost, this, _1)); } void WebApiPowerClass::onPowerStatus(AsyncWebServerRequest* request) diff --git a/src/WebApi_prometheus.cpp b/src/WebApi_prometheus.cpp index 3204b62c5..109e2fe0d 100644 --- a/src/WebApi_prometheus.cpp +++ b/src/WebApi_prometheus.cpp @@ -14,9 +14,7 @@ void WebApiPrometheusClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; - _server = &server; - - _server->on("/api/prometheus/metrics", HTTP_GET, std::bind(&WebApiPrometheusClass::onPrometheusMetricsGet, this, _1)); + server.on("/api/prometheus/metrics", HTTP_GET, std::bind(&WebApiPrometheusClass::onPrometheusMetricsGet, this, _1)); } void WebApiPrometheusClass::onPrometheusMetricsGet(AsyncWebServerRequest* request) diff --git a/src/WebApi_security.cpp b/src/WebApi_security.cpp index 205196812..b95ebb299 100644 --- a/src/WebApi_security.cpp +++ b/src/WebApi_security.cpp @@ -13,11 +13,9 @@ void WebApiSecurityClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; - _server = &server; - - _server->on("/api/security/config", HTTP_GET, std::bind(&WebApiSecurityClass::onSecurityGet, this, _1)); - _server->on("/api/security/config", HTTP_POST, std::bind(&WebApiSecurityClass::onSecurityPost, this, _1)); - _server->on("/api/security/authenticate", HTTP_GET, std::bind(&WebApiSecurityClass::onAuthenticateGet, this, _1)); + server.on("/api/security/config", HTTP_GET, std::bind(&WebApiSecurityClass::onSecurityGet, this, _1)); + server.on("/api/security/config", HTTP_POST, std::bind(&WebApiSecurityClass::onSecurityPost, this, _1)); + server.on("/api/security/authenticate", HTTP_GET, std::bind(&WebApiSecurityClass::onAuthenticateGet, this, _1)); } void WebApiSecurityClass::onSecurityGet(AsyncWebServerRequest* request) diff --git a/src/WebApi_sysstatus.cpp b/src/WebApi_sysstatus.cpp index 896e5d657..7bf2b73c1 100644 --- a/src/WebApi_sysstatus.cpp +++ b/src/WebApi_sysstatus.cpp @@ -20,9 +20,7 @@ void WebApiSysstatusClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; - _server = &server; - - _server->on("/api/system/status", HTTP_GET, std::bind(&WebApiSysstatusClass::onSystemStatus, this, _1)); + server.on("/api/system/status", HTTP_GET, std::bind(&WebApiSysstatusClass::onSystemStatus, this, _1)); } void WebApiSysstatusClass::onSystemStatus(AsyncWebServerRequest* request) diff --git a/src/WebApi_webapp.cpp b/src/WebApi_webapp.cpp index 9203505b9..db5cca43c 100644 --- a/src/WebApi_webapp.cpp +++ b/src/WebApi_webapp.cpp @@ -24,48 +24,46 @@ extern const uint8_t file_site_webmanifest_end[] asm("_binary_webapp_dist_site_w void WebApiWebappClass::init(AsyncWebServer& server, Scheduler& scheduler) { - _server = &server; - - _server->on("/", HTTP_GET, [](AsyncWebServerRequest* request) { + server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) { AsyncWebServerResponse* response = request->beginResponse_P(200, "text/html", file_index_html_start, file_index_html_end - file_index_html_start); response->addHeader("Content-Encoding", "gzip"); request->send(response); }); - _server->onNotFound([](AsyncWebServerRequest* request) { + server.onNotFound([](AsyncWebServerRequest* request) { AsyncWebServerResponse* response = request->beginResponse_P(200, "text/html", file_index_html_start, file_index_html_end - file_index_html_start); response->addHeader("Content-Encoding", "gzip"); request->send(response); }); - _server->on("/index.html", HTTP_GET, [](AsyncWebServerRequest* request) { + server.on("/index.html", HTTP_GET, [](AsyncWebServerRequest* request) { AsyncWebServerResponse* response = request->beginResponse_P(200, "text/html", file_index_html_start, file_index_html_end - file_index_html_start); response->addHeader("Content-Encoding", "gzip"); request->send(response); }); - _server->on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest* request) { + server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest* request) { AsyncWebServerResponse* response = request->beginResponse_P(200, "image/x-icon", file_favicon_ico_start, file_favicon_ico_end - file_favicon_ico_start); request->send(response); }); - _server->on("/favicon.png", HTTP_GET, [](AsyncWebServerRequest* request) { + server.on("/favicon.png", HTTP_GET, [](AsyncWebServerRequest* request) { AsyncWebServerResponse* response = request->beginResponse_P(200, "image/png", file_favicon_png_start, file_favicon_png_end - file_favicon_png_start); request->send(response); }); - _server->on("/zones.json", HTTP_GET, [](AsyncWebServerRequest* request) { + server.on("/zones.json", HTTP_GET, [](AsyncWebServerRequest* request) { AsyncWebServerResponse* response = request->beginResponse_P(200, "application/json", file_zones_json_start, file_zones_json_end - file_zones_json_start); response->addHeader("Content-Encoding", "gzip"); request->send(response); }); - _server->on("/site.webmanifest", HTTP_GET, [](AsyncWebServerRequest* request) { + server.on("/site.webmanifest", HTTP_GET, [](AsyncWebServerRequest* request) { AsyncWebServerResponse* response = request->beginResponse_P(200, "application/json", file_site_webmanifest_start, file_site_webmanifest_end - file_site_webmanifest_start); request->send(response); }); - _server->on("/js/app.js", HTTP_GET, [](AsyncWebServerRequest* request) { + server.on("/js/app.js", HTTP_GET, [](AsyncWebServerRequest* request) { #ifdef ETAG_HTTP_HEADER_VAL // check client If-None-Match header vs ETag/AUTO_GIT_HASH bool eTagMatch = false; diff --git a/src/WebApi_ws_console.cpp b/src/WebApi_ws_console.cpp index aaca6d895..1f1efcb20 100644 --- a/src/WebApi_ws_console.cpp +++ b/src/WebApi_ws_console.cpp @@ -16,8 +16,7 @@ WebApiWsConsoleClass::WebApiWsConsoleClass() void WebApiWsConsoleClass::init(AsyncWebServer& server, Scheduler& scheduler) { - _server = &server; - _server->addHandler(&_ws); + server.addHandler(&_ws); MessageOutput.register_ws_output(&_ws); scheduler.addTask(_wsCleanupTask); diff --git a/src/WebApi_ws_live.cpp b/src/WebApi_ws_live.cpp index 6f4bd38b8..8ac419013 100644 --- a/src/WebApi_ws_live.cpp +++ b/src/WebApi_ws_live.cpp @@ -27,10 +27,9 @@ void WebApiWsLiveClass::init(AsyncWebServer& server, Scheduler& scheduler) using std::placeholders::_5; using std::placeholders::_6; - _server = &server; - _server->on("/api/livedata/status", HTTP_GET, std::bind(&WebApiWsLiveClass::onLivedataStatus, this, _1)); + 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)); scheduler.addTask(_wsCleanupTask); From 97f006d8675d48a787acda9c31f830293fc9ad61 Mon Sep 17 00:00:00 2001 From: vaterlangen Date: Fri, 26 Jan 2024 22:16:09 +0100 Subject: [PATCH 02/57] fixed typo in OTA text --- webapp/src/locales/de.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/src/locales/de.json b/webapp/src/locales/de.json index 0767472a2..dbcd96a7a 100644 --- a/webapp/src/locales/de.json +++ b/webapp/src/locales/de.json @@ -550,7 +550,7 @@ "Back": "Zurück", "Retry": "Wiederholen", "OtaStatus": "OTA-Status", - "OtaSuccess": "Das Hochladen der Firmware war erfolgreich. Das Gerät wurde automatisch neu gestartet. Wenn das Gerät wieder erreichbar ist wird die automatisch Oberfläche neu geladen.", + "OtaSuccess": "Das Hochladen der Firmware war erfolgreich. Das Gerät wurde automatisch neu gestartet. Wenn das Gerät wieder erreichbar ist, wird die Oberfläche automatisch neu geladen.", "FirmwareUpload": "Firmware hochladen", "UploadProgress": "Hochlade-Fortschritt" }, From e752c433af434308dc93720e1cfeeac605135001 Mon Sep 17 00:00:00 2001 From: Stefan Oberhumer Date: Fri, 12 Jan 2024 12:02:39 +0100 Subject: [PATCH 03/57] Use http header ETag caching for all static content. Using the md5sum as ETag http header value should enable caching on all static http content. --- include/WebApi_webapp.h | 1 + src/WebApi_webapp.cpp | 112 ++++++++++++++++++++-------------------- 2 files changed, 58 insertions(+), 55 deletions(-) diff --git a/include/WebApi_webapp.h b/include/WebApi_webapp.h index 401408c61..33f30809c 100644 --- a/include/WebApi_webapp.h +++ b/include/WebApi_webapp.h @@ -10,4 +10,5 @@ class WebApiWebappClass { private: AsyncWebServer* _server; + void responseBinaryDataWithETagCache(AsyncWebServerRequest* request, const String &contentType, const String &contentEncoding, const uint8_t *content, size_t len); }; diff --git a/src/WebApi_webapp.cpp b/src/WebApi_webapp.cpp index 9203505b9..27ce8a3e4 100644 --- a/src/WebApi_webapp.cpp +++ b/src/WebApi_webapp.cpp @@ -3,6 +3,7 @@ * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_webapp.h" +#include extern const uint8_t file_index_html_start[] asm("_binary_webapp_dist_index_html_gz_start"); extern const uint8_t file_favicon_ico_start[] asm("_binary_webapp_dist_favicon_ico_start"); @@ -18,79 +19,80 @@ extern const uint8_t file_zones_json_end[] asm("_binary_webapp_dist_zones_json_g extern const uint8_t file_app_js_end[] asm("_binary_webapp_dist_js_app_js_gz_end"); extern const uint8_t file_site_webmanifest_end[] asm("_binary_webapp_dist_site_webmanifest_end"); -#ifdef AUTO_GIT_HASH -#define ETAG_HTTP_HEADER_VAL "\"" AUTO_GIT_HASH "\"" // ETag value must be between quotes -#endif +void WebApiWebappClass::responseBinaryDataWithETagCache(AsyncWebServerRequest *request, const String &contentType, const String &contentEncoding, const uint8_t *content, size_t len) +{ + auto _md5 = MD5Builder(); + _md5.begin(); + _md5.add(const_cast(content), len); + _md5.calculate(); + + String expectedEtag; + expectedEtag = "\""; + expectedEtag += _md5.toString(); + expectedEtag += "\""; + + bool eTagMatch = false; + if (request->hasHeader("If-None-Match")) { + const AsyncWebHeader* h = request->getHeader("If-None-Match"); + eTagMatch = h->value().equals(expectedEtag); + } + + // begin response 200 or 304 + AsyncWebServerResponse* response; + if (eTagMatch) { + response = request->beginResponse(304); + } else { + response = request->beginResponse_P(200, contentType, content, len); + if (contentEncoding.length() > 0) { + response->addHeader("Content-Encoding", contentEncoding); + } + } + + // HTTP requires cache headers in 200 and 304 to be identical + response->addHeader("Cache-Control", "public, must-revalidate"); + response->addHeader("ETag", expectedEtag); + + request->send(response); +} void WebApiWebappClass::init(AsyncWebServer& server, Scheduler& scheduler) { _server = &server; - _server->on("/", HTTP_GET, [](AsyncWebServerRequest* request) { - AsyncWebServerResponse* response = request->beginResponse_P(200, "text/html", file_index_html_start, file_index_html_end - file_index_html_start); - response->addHeader("Content-Encoding", "gzip"); - request->send(response); - }); + /* + We don't validate the request header "Accept-Encoding" if gzip compression is supported! + We just have the gzipped data available - so we ship them! + */ - _server->onNotFound([](AsyncWebServerRequest* request) { - AsyncWebServerResponse* response = request->beginResponse_P(200, "text/html", file_index_html_start, file_index_html_end - file_index_html_start); - response->addHeader("Content-Encoding", "gzip"); - request->send(response); + _server->on("/", HTTP_GET, [&](AsyncWebServerRequest* request) { + responseBinaryDataWithETagCache(request, "text/html", "gzip", file_index_html_start, file_index_html_end - file_index_html_start); }); - _server->on("/index.html", HTTP_GET, [](AsyncWebServerRequest* request) { - AsyncWebServerResponse* response = request->beginResponse_P(200, "text/html", file_index_html_start, file_index_html_end - file_index_html_start); - response->addHeader("Content-Encoding", "gzip"); - request->send(response); + _server->onNotFound([&](AsyncWebServerRequest* request) { + responseBinaryDataWithETagCache(request, "text/html", "gzip", file_index_html_start, file_index_html_end - file_index_html_start); }); - _server->on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest* request) { - AsyncWebServerResponse* response = request->beginResponse_P(200, "image/x-icon", file_favicon_ico_start, file_favicon_ico_end - file_favicon_ico_start); - request->send(response); + _server->on("/index.html", HTTP_GET, [&](AsyncWebServerRequest* request) { + responseBinaryDataWithETagCache(request, "text/html", "gzip", file_index_html_start, file_index_html_end - file_index_html_start); }); - _server->on("/favicon.png", HTTP_GET, [](AsyncWebServerRequest* request) { - AsyncWebServerResponse* response = request->beginResponse_P(200, "image/png", file_favicon_png_start, file_favicon_png_end - file_favicon_png_start); - request->send(response); + _server->on("/favicon.ico", HTTP_GET, [&](AsyncWebServerRequest* request) { + responseBinaryDataWithETagCache(request, "image/x-icon", "", file_favicon_ico_start, file_favicon_ico_end - file_favicon_ico_start); }); - _server->on("/zones.json", HTTP_GET, [](AsyncWebServerRequest* request) { - AsyncWebServerResponse* response = request->beginResponse_P(200, "application/json", file_zones_json_start, file_zones_json_end - file_zones_json_start); - response->addHeader("Content-Encoding", "gzip"); - request->send(response); + _server->on("/favicon.png", HTTP_GET, [&](AsyncWebServerRequest* request) { + responseBinaryDataWithETagCache(request, "image/png", "", file_favicon_png_start, file_favicon_png_end - file_favicon_png_start); }); - _server->on("/site.webmanifest", HTTP_GET, [](AsyncWebServerRequest* request) { - AsyncWebServerResponse* response = request->beginResponse_P(200, "application/json", file_site_webmanifest_start, file_site_webmanifest_end - file_site_webmanifest_start); - request->send(response); + _server->on("/zones.json", HTTP_GET, [&](AsyncWebServerRequest* request) { + responseBinaryDataWithETagCache(request, "application/json", "gzip", file_zones_json_start, file_zones_json_end - file_zones_json_start); }); - _server->on("/js/app.js", HTTP_GET, [](AsyncWebServerRequest* request) { -#ifdef ETAG_HTTP_HEADER_VAL - // check client If-None-Match header vs ETag/AUTO_GIT_HASH - bool eTagMatch = false; - if (request->hasHeader("If-None-Match")) { - const AsyncWebHeader* h = request->getHeader("If-None-Match"); - if (strncmp(ETAG_HTTP_HEADER_VAL, h->value().c_str(), strlen(ETAG_HTTP_HEADER_VAL)) == 0) { - eTagMatch = true; - } - } + _server->on("/site.webmanifest", HTTP_GET, [&](AsyncWebServerRequest* request) { + responseBinaryDataWithETagCache(request, "application/json", "", file_site_webmanifest_start, file_site_webmanifest_end - file_site_webmanifest_start); + }); - // begin response 200 or 304 - AsyncWebServerResponse* response; - if (eTagMatch) { - response = request->beginResponse(304); - } else { - response = request->beginResponse_P(200, "text/javascript", file_app_js_start, file_app_js_end - file_app_js_start); - response->addHeader("Content-Encoding", "gzip"); - } - // HTTP requires cache headers in 200 and 304 to be identical - response->addHeader("Cache-Control", "public, must-revalidate"); - response->addHeader("ETag", ETAG_HTTP_HEADER_VAL); -#else - AsyncWebServerResponse* response = request->beginResponse_P(200, "text/javascript", file_app_js_start, file_app_js_end - file_app_js_start); - response->addHeader("Content-Encoding", "gzip"); -#endif - request->send(response); + _server->on("/js/app.js", HTTP_GET, [&](AsyncWebServerRequest* request) { + responseBinaryDataWithETagCache(request, "text/javascript", "gzip", file_app_js_start, file_app_js_end - file_app_js_start); }); } From dfed23261ab497d8568b2e4f7d08d44e33a8012a Mon Sep 17 00:00:00 2001 From: Sabouflage Date: Tue, 30 Jan 2024 19:02:57 +0100 Subject: [PATCH 04/57] fix(mqtt): MQTTs LWT QoS config used also for TLS connections --- src/MqttSettings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MqttSettings.cpp b/src/MqttSettings.cpp index 09c883e03..82d0540b9 100644 --- a/src/MqttSettings.cpp +++ b/src/MqttSettings.cpp @@ -125,7 +125,7 @@ void MqttSettingsClass::performConnect() } else { static_cast(_mqttClient)->setCredentials(config.Mqtt.Username, config.Mqtt.Password); } - static_cast(_mqttClient)->setWill(willTopic.c_str(), 2, config.Mqtt.Retain, config.Mqtt.Lwt.Value_Offline); + static_cast(_mqttClient)->setWill(willTopic.c_str(), config.Mqtt.Lwt.Qos, config.Mqtt.Retain, config.Mqtt.Lwt.Value_Offline); static_cast(_mqttClient)->setClientId(clientId.c_str()); static_cast(_mqttClient)->setCleanSession(config.Mqtt.CleanSession); static_cast(_mqttClient)->onConnect(std::bind(&MqttSettingsClass::onMqttConnect, this, _1)); @@ -223,4 +223,4 @@ void MqttSettingsClass::createMqttClientObject() } } -MqttSettingsClass MqttSettings; \ No newline at end of file +MqttSettingsClass MqttSettings; From 5d7512e026d524ad1b30d635ba7d346c6912fea8 Mon Sep 17 00:00:00 2001 From: Sabouflage Date: Tue, 30 Jan 2024 19:03:23 +0100 Subject: [PATCH 05/57] fix(mqtt): setting MQTT LWT online message for frontend --- src/WebApi_mqtt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WebApi_mqtt.cpp b/src/WebApi_mqtt.cpp index 2361c44e8..e4b1f035b 100644 --- a/src/WebApi_mqtt.cpp +++ b/src/WebApi_mqtt.cpp @@ -79,7 +79,7 @@ void WebApiMqttClass::onMqttAdminGet(AsyncWebServerRequest* request) root["mqtt_client_cert"] = config.Mqtt.Tls.ClientCert; root["mqtt_client_key"] = config.Mqtt.Tls.ClientKey; root["mqtt_lwt_topic"] = config.Mqtt.Lwt.Topic; - root["mqtt_lwt_online"] = config.Mqtt.CleanSession; + root["mqtt_lwt_online"] = config.Mqtt.Lwt.Value_Online;; root["mqtt_lwt_offline"] = config.Mqtt.Lwt.Value_Offline; root["mqtt_lwt_qos"] = config.Mqtt.Lwt.Qos; root["mqtt_publish_interval"] = config.Mqtt.PublishInterval; From 557c5d645e2e8723116a0b063b2b8f586da638f5 Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Tue, 30 Jan 2024 22:29:12 +0100 Subject: [PATCH 06/57] Remove all files but the pin_mapping.json from filesystem on factory reset This allows to create more user defined files and get them deleted on factory reset. --- include/Utils.h | 1 + src/Utils.cpp | 16 ++++++++++++++++ src/WebApi_config.cpp | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/Utils.h b/include/Utils.h index 4d4bfee37..fddc2ab97 100644 --- a/include/Utils.h +++ b/include/Utils.h @@ -11,4 +11,5 @@ class Utils { static int getTimezoneOffset(); static void restartDtu(); static bool checkJsonAlloc(const DynamicJsonDocument& doc, const char* function, const uint16_t line); + static void removeAllFiles(); }; diff --git a/src/Utils.cpp b/src/Utils.cpp index 386e0ed1f..7ad072938 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -6,7 +6,9 @@ #include "Display_Graphic.h" #include "Led_Single.h" #include "MessageOutput.h" +#include "PinMapping.h" #include +#include uint32_t Utils::getChipId() { @@ -76,3 +78,17 @@ bool Utils::checkJsonAlloc(const DynamicJsonDocument& doc, const char* function, return true; } + +/// @brief Remove all files but the PINMAPPING_FILENAME +void Utils::removeAllFiles() +{ + auto root = LittleFS.open("/"); + auto file = root.getNextFileName(); + + while (file != "") { + if (file != PINMAPPING_FILENAME) { + LittleFS.remove(file); + } + file = root.getNextFileName(); + } +} diff --git a/src/WebApi_config.cpp b/src/WebApi_config.cpp index c275ffc71..29f353192 100644 --- a/src/WebApi_config.cpp +++ b/src/WebApi_config.cpp @@ -108,7 +108,7 @@ void WebApiConfigClass::onConfigDelete(AsyncWebServerRequest* request) response->setLength(); request->send(response); - LittleFS.remove(CONFIG_FILENAME); + Utils::removeAllFiles(); Utils::restartDtu(); } From c27ecc3620f656fbdfaa7e9f0f3deca6a371a373 Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Mon, 29 Jan 2024 22:46:40 +0100 Subject: [PATCH 07/57] BREAKING CHANGE: Web API Endpoint /api/livedata/status To reduce the heap usage it is necessary to send the inverters one by one instead of a huge response. A simple call to `/api/livedata/status` returns just some very general information. If detailed inverter information are required the inverter serial number has to appended `?inv=`. The websocket also returns only one inverter at a time. It as to be assembled at client side. --- include/WebApi_ws_live.h | 14 ++- src/WebApi_ws_live.cpp | 212 +++++++++++++++++++--------------- webapp/src/locales/de.json | 3 +- webapp/src/locales/en.json | 3 +- webapp/src/locales/fr.json | 3 +- webapp/src/views/HomeView.vue | 41 +++++-- 6 files changed, 167 insertions(+), 109 deletions(-) diff --git a/include/WebApi_ws_live.h b/include/WebApi_ws_live.h index 9adc848e1..05f8ab8f9 100644 --- a/include/WebApi_ws_live.h +++ b/include/WebApi_ws_live.h @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once +#include "Configuration.h" #include #include #include @@ -12,16 +13,19 @@ class WebApiWsLiveClass { void init(AsyncWebServer& server, Scheduler& scheduler); private: - void generateJsonResponse(JsonVariant& root); - void addField(JsonObject& root, std::shared_ptr inv, const ChannelType_t type, const ChannelNum_t channel, const FieldId_t fieldId, String topic = ""); - void addTotalField(JsonObject& root, const String& name, const float value, const String& unit, const uint8_t digits); + static void generateInverterCommonJsonResponse(JsonObject& root, std::shared_ptr inv); + static void generateInverterChannelJsonResponse(JsonObject& root, std::shared_ptr inv); + static void generateCommonJsonResponse(JsonVariant& root); + + static void addField(JsonObject& root, std::shared_ptr inv, const ChannelType_t type, const ChannelNum_t channel, const FieldId_t fieldId, String topic = ""); + static void addTotalField(JsonObject& root, const String& name, const float value, const String& unit, const uint8_t digits); + void onLivedataStatus(AsyncWebServerRequest* request); void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len); AsyncWebSocket _ws; - uint32_t _lastWsPublish = 0; - uint32_t _newestInverterTimestamp = 0; + uint32_t _lastPublishStats[INV_MAX_COUNT] = { 0 }; std::mutex _mutex; diff --git a/src/WebApi_ws_live.cpp b/src/WebApi_ws_live.cpp index 8ac419013..319506a3e 100644 --- a/src/WebApi_ws_live.cpp +++ b/src/WebApi_ws_live.cpp @@ -3,7 +3,6 @@ * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_ws_live.h" -#include "Configuration.h" #include "Datastore.h" #include "MessageOutput.h" #include "Utils.h" @@ -58,108 +57,50 @@ void WebApiWsLiveClass::sendDataTaskCb() return; } - uint32_t maxTimeStamp = 0; + // Loop all inverters for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { auto inv = Hoymiles.getInverterByPos(i); - maxTimeStamp = std::max(maxTimeStamp, inv->Statistics()->getLastUpdate()); - } + if (inv == nullptr) { + continue; + } - // Update on every inverter change or at least after 10 seconds - if (millis() - _lastWsPublish > (10 * 1000) || (maxTimeStamp != _newestInverterTimestamp)) { + const uint32_t lastUpdateInternal = inv->Statistics()->getLastUpdateFromInternal(); + if (!((lastUpdateInternal > 0 && lastUpdateInternal > _lastPublishStats[i]) || (millis() - _lastPublishStats[i] > (10 * 1000)))) { + continue; + } + + _lastPublishStats[i] = millis(); try { std::lock_guard lock(_mutex); - DynamicJsonDocument root(4096 * INV_MAX_COUNT); - if (Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) { - JsonVariant var = root; - generateJsonResponse(var); + DynamicJsonDocument root(4096); + if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) { + continue; + } + JsonVariant var = root; - String buffer; - serializeJson(root, buffer); + auto invArray = var.createNestedArray("inverters"); + auto invObject = invArray.createNestedObject(); - _ws.textAll(buffer); - _newestInverterTimestamp = maxTimeStamp; - } + generateCommonJsonResponse(var); + generateInverterCommonJsonResponse(invObject, inv); + generateInverterChannelJsonResponse(invObject, inv); + + String buffer; + serializeJson(root, buffer); + + _ws.textAll(buffer); } catch (const std::bad_alloc& bad_alloc) { MessageOutput.printf("Call to /api/livedata/status temporarely out of resources. Reason: \"%s\".\r\n", bad_alloc.what()); } catch (const std::exception& exc) { MessageOutput.printf("Unknown exception in /api/livedata/status. Reason: \"%s\".\r\n", exc.what()); } - - _lastWsPublish = millis(); } } -void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root) +void WebApiWsLiveClass::generateCommonJsonResponse(JsonVariant& root) { - JsonArray invArray = root.createNestedArray("inverters"); - - // Loop all inverters - for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { - auto inv = Hoymiles.getInverterByPos(i); - if (inv == nullptr) { - continue; - } - - JsonObject invObject = invArray.createNestedObject(); - INVERTER_CONFIG_T* inv_cfg = Configuration.getInverterConfig(inv->serial()); - if (inv_cfg == nullptr) { - continue; - } - - invObject["serial"] = inv->serialString(); - invObject["name"] = inv->name(); - invObject["order"] = inv_cfg->Order; - invObject["data_age"] = (millis() - inv->Statistics()->getLastUpdate()) / 1000; - invObject["poll_enabled"] = inv->getEnablePolling(); - invObject["reachable"] = inv->isReachable(); - invObject["producing"] = inv->isProducing(); - invObject["limit_relative"] = inv->SystemConfigPara()->getLimitPercent(); - if (inv->DevInfo()->getMaxPower() > 0) { - invObject["limit_absolute"] = inv->SystemConfigPara()->getLimitPercent() * inv->DevInfo()->getMaxPower() / 100.0; - } else { - invObject["limit_absolute"] = -1; - } - - // Loop all channels - for (auto& t : inv->Statistics()->getChannelTypes()) { - JsonObject chanTypeObj = invObject.createNestedObject(inv->Statistics()->getChannelTypeName(t)); - for (auto& c : inv->Statistics()->getChannelsByType(t)) { - if (t == TYPE_DC) { - chanTypeObj[String(static_cast(c))]["name"]["u"] = inv_cfg->channel[c].Name; - } - addField(chanTypeObj, inv, t, c, FLD_PAC); - addField(chanTypeObj, inv, t, c, FLD_UAC); - addField(chanTypeObj, inv, t, c, FLD_IAC); - if (t == TYPE_AC) { - addField(chanTypeObj, inv, t, c, FLD_PDC, "Power DC"); - } else { - addField(chanTypeObj, inv, t, c, FLD_PDC); - } - addField(chanTypeObj, inv, t, c, FLD_UDC); - addField(chanTypeObj, inv, t, c, FLD_IDC); - addField(chanTypeObj, inv, t, c, FLD_YD); - addField(chanTypeObj, inv, t, c, FLD_YT); - addField(chanTypeObj, inv, t, c, FLD_F); - addField(chanTypeObj, inv, t, c, FLD_T); - addField(chanTypeObj, inv, t, c, FLD_PF); - addField(chanTypeObj, inv, t, c, FLD_Q); - addField(chanTypeObj, inv, t, c, FLD_EFF); - if (t == TYPE_DC && inv->Statistics()->getStringMaxPower(c) > 0) { - addField(chanTypeObj, inv, t, c, FLD_IRR); - chanTypeObj[String(c)][inv->Statistics()->getChannelFieldName(t, c, FLD_IRR)]["max"] = inv->Statistics()->getStringMaxPower(c); - } - } - } - - if (inv->Statistics()->hasChannelFieldValue(TYPE_INV, CH0, FLD_EVT_LOG)) { - invObject["events"] = inv->EventLog()->getEntryCount(); - } else { - invObject["events"] = -1; - } - } - JsonObject totalObj = root.createNestedObject("total"); addTotalField(totalObj, "Power", Datastore.getTotalAcPowerEnabled(), "W", Datastore.getTotalAcPowerDigits()); addTotalField(totalObj, "YieldDay", Datastore.getTotalAcYieldDayEnabled(), "Wh", Datastore.getTotalAcYieldDayDigits()); @@ -169,10 +110,73 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root) struct tm timeinfo; hintObj["time_sync"] = !getLocalTime(&timeinfo, 5); hintObj["radio_problem"] = (Hoymiles.getRadioNrf()->isInitialized() && (!Hoymiles.getRadioNrf()->isConnected() || !Hoymiles.getRadioNrf()->isPVariant())) || (Hoymiles.getRadioCmt()->isInitialized() && (!Hoymiles.getRadioCmt()->isConnected())); - if (!strcmp(Configuration.get().Security.Password, ACCESS_POINT_PASSWORD)) { - hintObj["default_password"] = true; + hintObj["default_password"] = strcmp(Configuration.get().Security.Password, ACCESS_POINT_PASSWORD) == 0; +} + +void WebApiWsLiveClass::generateInverterCommonJsonResponse(JsonObject& root, std::shared_ptr inv) +{ + const INVERTER_CONFIG_T* inv_cfg = Configuration.getInverterConfig(inv->serial()); + if (inv_cfg == nullptr) { + return; + } + + root["serial"] = inv->serialString(); + root["name"] = inv->name(); + root["order"] = inv_cfg->Order; + root["data_age"] = (millis() - inv->Statistics()->getLastUpdate()) / 1000; + root["poll_enabled"] = inv->getEnablePolling(); + root["reachable"] = inv->isReachable(); + root["producing"] = inv->isProducing(); + root["limit_relative"] = inv->SystemConfigPara()->getLimitPercent(); + if (inv->DevInfo()->getMaxPower() > 0) { + root["limit_absolute"] = inv->SystemConfigPara()->getLimitPercent() * inv->DevInfo()->getMaxPower() / 100.0; } else { - hintObj["default_password"] = false; + root["limit_absolute"] = -1; + } +} + +void WebApiWsLiveClass::generateInverterChannelJsonResponse(JsonObject& root, std::shared_ptr inv) +{ + const INVERTER_CONFIG_T* inv_cfg = Configuration.getInverterConfig(inv->serial()); + if (inv_cfg == nullptr) { + return; + } + + // Loop all channels + for (auto& t : inv->Statistics()->getChannelTypes()) { + JsonObject chanTypeObj = root.createNestedObject(inv->Statistics()->getChannelTypeName(t)); + for (auto& c : inv->Statistics()->getChannelsByType(t)) { + if (t == TYPE_DC) { + chanTypeObj[String(static_cast(c))]["name"]["u"] = inv_cfg->channel[c].Name; + } + addField(chanTypeObj, inv, t, c, FLD_PAC); + addField(chanTypeObj, inv, t, c, FLD_UAC); + addField(chanTypeObj, inv, t, c, FLD_IAC); + if (t == TYPE_AC) { + addField(chanTypeObj, inv, t, c, FLD_PDC, "Power DC"); + } else { + addField(chanTypeObj, inv, t, c, FLD_PDC); + } + addField(chanTypeObj, inv, t, c, FLD_UDC); + addField(chanTypeObj, inv, t, c, FLD_IDC); + addField(chanTypeObj, inv, t, c, FLD_YD); + addField(chanTypeObj, inv, t, c, FLD_YT); + addField(chanTypeObj, inv, t, c, FLD_F); + addField(chanTypeObj, inv, t, c, FLD_T); + addField(chanTypeObj, inv, t, c, FLD_PF); + addField(chanTypeObj, inv, t, c, FLD_Q); + addField(chanTypeObj, inv, t, c, FLD_EFF); + if (t == TYPE_DC && inv->Statistics()->getStringMaxPower(c) > 0) { + addField(chanTypeObj, inv, t, c, FLD_IRR); + chanTypeObj[String(c)][inv->Statistics()->getChannelFieldName(t, c, FLD_IRR)]["max"] = inv->Statistics()->getStringMaxPower(c); + } + } + } + + if (inv->Statistics()->hasChannelFieldValue(TYPE_INV, CH0, FLD_EVT_LOG)) { + root["events"] = inv->EventLog()->getEntryCount(); + } else { + root["events"] = -1; } } @@ -217,10 +221,38 @@ void WebApiWsLiveClass::onLivedataStatus(AsyncWebServerRequest* request) try { std::lock_guard lock(_mutex); - AsyncJsonResponse* response = new AsyncJsonResponse(false, 4096 * INV_MAX_COUNT); + AsyncJsonResponse* response = new AsyncJsonResponse(false, 4096); auto& root = response->getRoot(); - generateJsonResponse(root); + JsonArray invArray = root.createNestedArray("inverters"); + + uint64_t serial = 0; + if (request->hasParam("inv")) { + String s = request->getParam("inv")->value(); + serial = strtoll(s.c_str(), NULL, 16); + } + + if (serial > 0) { + auto inv = Hoymiles.getInverterBySerial(serial); + if (inv != nullptr) { + JsonObject invObject = invArray.createNestedObject(); + generateInverterCommonJsonResponse(invObject, inv); + generateInverterChannelJsonResponse(invObject, inv); + } + } else { + // Loop all inverters + for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { + auto inv = Hoymiles.getInverterByPos(i); + if (inv == nullptr) { + continue; + } + + JsonObject invObject = invArray.createNestedObject(); + generateInverterCommonJsonResponse(invObject, inv); + } + } + + generateCommonJsonResponse(root); response->setLength(); request->send(response); diff --git a/webapp/src/locales/de.json b/webapp/src/locales/de.json index dbcd96a7a..ab48f2a7f 100644 --- a/webapp/src/locales/de.json +++ b/webapp/src/locales/de.json @@ -136,7 +136,8 @@ "Ok": "Ok", "Unknown": "Unbekannt", "ShowGridProfile": "Zeige Grid Profil", - "GridProfile": "Grid Profil" + "GridProfile": "Grid Profil", + "LoadingInverter": "Warte auf Daten... (kann bis zu 10 Sekunden dauern)" }, "eventlog": { "Start": "Begin", diff --git a/webapp/src/locales/en.json b/webapp/src/locales/en.json index 71ba094fb..8ccbb1bca 100644 --- a/webapp/src/locales/en.json +++ b/webapp/src/locales/en.json @@ -136,7 +136,8 @@ "Ok": "Ok", "Unknown": "Unknown", "ShowGridProfile": "Show Grid Profile", - "GridProfile": "Grid Profile" + "GridProfile": "Grid Profile", + "LoadingInverter": "Waiting for data... (can take up to 10 seconds)" }, "eventlog": { "Start": "Start", diff --git a/webapp/src/locales/fr.json b/webapp/src/locales/fr.json index a763e206d..3f7069498 100644 --- a/webapp/src/locales/fr.json +++ b/webapp/src/locales/fr.json @@ -136,7 +136,8 @@ "Ok": "OK", "Unknown": "Inconnu", "ShowGridProfile": "Show Grid Profile", - "GridProfile": "Grid Profile" + "GridProfile": "Grid Profile", + "LoadingInverter": "Waiting for data... (can take up to 10 seconds)" }, "eventlog": { "Start": "Départ", diff --git a/webapp/src/views/HomeView.vue b/webapp/src/views/HomeView.vue index d2fca8388..953d5cf49 100644 --- a/webapp/src/views/HomeView.vue +++ b/webapp/src/views/HomeView.vue @@ -103,20 +103,30 @@