diff --git a/docs/DeviceProfiles/olimex_esp32_gateway.json b/docs/DeviceProfiles/olimex_esp32_gateway.json new file mode 100644 index 000000000..a359573c6 --- /dev/null +++ b/docs/DeviceProfiles/olimex_esp32_gateway.json @@ -0,0 +1,47 @@ +[ + { + "name": "Olimex ESP32-Gateway", + "nrf24": { + "miso": 14, + "mosi": 13, + "clk": 12, + "irq": 15, + "en": 2, + "cs": 4 + }, + "eth": { + "enabled": true, + "phy_addr": 0, + "power": 12, + "mdc": 23, + "mdio": 18, + "type": 0, + "clk_mode": 3 + } + }, + { + "name": "Olimex ESP32-Gateway with SSH1106", + "nrf24": { + "miso": 14, + "mosi": 13, + "clk": 12, + "irq": 15, + "en": 2, + "cs": 4 + }, + "eth": { + "enabled": true, + "phy_addr": 0, + "power": 12, + "mdc": 23, + "mdio": 18, + "type": 0, + "clk_mode": 3 + }, + "display": { + "type": 3, + "data": 32, + "clk": 16 + } + } +] diff --git a/include/Datastore.h b/include/Datastore.h index 351a822ee..b4610bfc8 100644 --- a/include/Datastore.h +++ b/include/Datastore.h @@ -6,6 +6,7 @@ class DatastoreClass { public: + DatastoreClass(); void init(Scheduler& scheduler); // Sum of yield total of all enabled inverters, a inverter which is just disabled at night is also included @@ -81,4 +82,4 @@ class DatastoreClass { bool _isAtLeastOnePollEnabled = false; }; -extern DatastoreClass Datastore; \ No newline at end of file +extern DatastoreClass Datastore; diff --git a/include/InverterSettings.h b/include/InverterSettings.h index aad05ed79..6a36a7053 100644 --- a/include/InverterSettings.h +++ b/include/InverterSettings.h @@ -8,6 +8,7 @@ class InverterSettingsClass { public: + InverterSettingsClass(); void init(Scheduler& scheduler); private: diff --git a/include/MessageOutput.h b/include/MessageOutput.h index fc06f385c..6f2daa529 100644 --- a/include/MessageOutput.h +++ b/include/MessageOutput.h @@ -12,6 +12,7 @@ class MessageOutputClass : public Print { public: + MessageOutputClass(); void init(Scheduler& scheduler); size_t write(uint8_t c) override; size_t write(const uint8_t* buffer, size_t size) override; @@ -37,4 +38,4 @@ class MessageOutputClass : public Print { void serialWrite(message_t const& m); }; -extern MessageOutputClass MessageOutput; \ No newline at end of file +extern MessageOutputClass MessageOutput; diff --git a/include/MqttHandleDtu.h b/include/MqttHandleDtu.h index 01e179857..5afc87715 100644 --- a/include/MqttHandleDtu.h +++ b/include/MqttHandleDtu.h @@ -6,6 +6,7 @@ class MqttHandleDtuClass { public: + MqttHandleDtuClass(); void init(Scheduler& scheduler); private: @@ -14,4 +15,4 @@ class MqttHandleDtuClass { Task _loopTask; }; -extern MqttHandleDtuClass MqttHandleDtu; \ No newline at end of file +extern MqttHandleDtuClass MqttHandleDtu; diff --git a/include/MqttHandleHass.h b/include/MqttHandleHass.h index 41f7bf8c3..feb867435 100644 --- a/include/MqttHandleHass.h +++ b/include/MqttHandleHass.h @@ -51,6 +51,7 @@ const byteAssign_fieldDeviceClass_t deviceFieldAssignment[] = { class MqttHandleHassClass { public: + MqttHandleHassClass(); void init(Scheduler& scheduler); void publishConfig(); void forceUpdate(); @@ -79,4 +80,4 @@ class MqttHandleHassClass { bool _updateForced = false; }; -extern MqttHandleHassClass MqttHandleHass; \ No newline at end of file +extern MqttHandleHassClass MqttHandleHass; diff --git a/include/MqttHandleInverter.h b/include/MqttHandleInverter.h index 3925935f6..446f30afa 100644 --- a/include/MqttHandleInverter.h +++ b/include/MqttHandleInverter.h @@ -8,6 +8,7 @@ class MqttHandleInverterClass { public: + MqttHandleInverterClass(); void init(Scheduler& scheduler); static String getTopic(std::shared_ptr inv, const ChannelType_t type, const ChannelNum_t channel, const FieldId_t fieldId); @@ -39,4 +40,4 @@ class MqttHandleInverterClass { }; }; -extern MqttHandleInverterClass MqttHandleInverter; \ No newline at end of file +extern MqttHandleInverterClass MqttHandleInverter; diff --git a/include/MqttHandleInverterTotal.h b/include/MqttHandleInverterTotal.h index 193178180..ae4d66c47 100644 --- a/include/MqttHandleInverterTotal.h +++ b/include/MqttHandleInverterTotal.h @@ -5,6 +5,7 @@ class MqttHandleInverterTotalClass { public: + MqttHandleInverterTotalClass(); void init(Scheduler& scheduler); private: @@ -13,4 +14,4 @@ class MqttHandleInverterTotalClass { Task _loopTask; }; -extern MqttHandleInverterTotalClass MqttHandleInverterTotal; \ No newline at end of file +extern MqttHandleInverterTotalClass MqttHandleInverterTotal; diff --git a/include/WebApi.h b/include/WebApi.h index 5c6498f0c..299ed63cf 100644 --- a/include/WebApi.h +++ b/include/WebApi.h @@ -46,10 +46,6 @@ class WebApiClass { static void writeConfig(JsonVariant& retMsg, const WebApiError code = WebApiError::GenericSuccess, const String& message = "Settings saved!"); private: - void loop(); - - Task _loopTask; - AsyncWebServer _server; WebApiBatteryClass _webApiBattery; @@ -82,4 +78,4 @@ class WebApiClass { WebApiWsBatteryLiveClass _webApiWsBatteryLive; }; -extern WebApiClass WebApi; \ No newline at end of file +extern WebApiClass WebApi; diff --git a/include/WebApi_Huawei.h b/include/WebApi_Huawei.h index 021fa015e..57d00ed83 100644 --- a/include/WebApi_Huawei.h +++ b/include/WebApi_Huawei.h @@ -2,12 +2,12 @@ #pragma once #include +#include #include class WebApiHuaweiClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); void getJsonData(JsonVariant& root); private: void onStatus(AsyncWebServerRequest* request); diff --git a/include/WebApi_battery.h b/include/WebApi_battery.h index 2d85d5a13..7148fbdb2 100644 --- a/include/WebApi_battery.h +++ b/include/WebApi_battery.h @@ -2,12 +2,11 @@ #pragma once #include - +#include class WebApiBatteryClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onStatus(AsyncWebServerRequest* request); diff --git a/include/WebApi_config.h b/include/WebApi_config.h index edc8b2917..91243c18c 100644 --- a/include/WebApi_config.h +++ b/include/WebApi_config.h @@ -2,11 +2,11 @@ #pragma once #include +#include class WebApiConfigClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onConfigGet(AsyncWebServerRequest* request); @@ -16,4 +16,4 @@ class WebApiConfigClass { void onConfigUpload(AsyncWebServerRequest* request, String filename, size_t index, uint8_t* data, size_t len, bool final); AsyncWebServer* _server; -}; \ No newline at end of file +}; diff --git a/include/WebApi_device.h b/include/WebApi_device.h index 9fca20fd4..f74315e34 100644 --- a/include/WebApi_device.h +++ b/include/WebApi_device.h @@ -2,15 +2,15 @@ #pragma once #include +#include class WebApiDeviceClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onDeviceAdminGet(AsyncWebServerRequest* request); void onDeviceAdminPost(AsyncWebServerRequest* request); AsyncWebServer* _server; -}; \ No newline at end of file +}; diff --git a/include/WebApi_devinfo.h b/include/WebApi_devinfo.h index 6e5602bac..d1924ecc0 100644 --- a/include/WebApi_devinfo.h +++ b/include/WebApi_devinfo.h @@ -2,14 +2,14 @@ #pragma once #include +#include class WebApiDevInfoClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onDevInfoStatus(AsyncWebServerRequest* request); AsyncWebServer* _server; -}; \ No newline at end of file +}; diff --git a/include/WebApi_dtu.h b/include/WebApi_dtu.h index 98d286522..3acf4494d 100644 --- a/include/WebApi_dtu.h +++ b/include/WebApi_dtu.h @@ -2,16 +2,19 @@ #pragma once #include +#include class WebApiDtuClass { public: - void init(AsyncWebServer& server); - void loop(); + WebApiDtuClass(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onDtuAdminGet(AsyncWebServerRequest* request); void onDtuAdminPost(AsyncWebServerRequest* request); AsyncWebServer* _server; - bool _performReload = false; + + Task _applyDataTask; + void applyDataTaskCb(); }; diff --git a/include/WebApi_eventlog.h b/include/WebApi_eventlog.h index ccc1658ca..3cba7e5e5 100644 --- a/include/WebApi_eventlog.h +++ b/include/WebApi_eventlog.h @@ -2,14 +2,14 @@ #pragma once #include +#include class WebApiEventlogClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onEventlogStatus(AsyncWebServerRequest* request); AsyncWebServer* _server; -}; \ No newline at end of file +}; diff --git a/include/WebApi_firmware.h b/include/WebApi_firmware.h index 1b7e92366..fd9a96428 100644 --- a/include/WebApi_firmware.h +++ b/include/WebApi_firmware.h @@ -2,15 +2,15 @@ #pragma once #include +#include class WebApiFirmwareClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onFirmwareUpdateFinish(AsyncWebServerRequest* request); void onFirmwareUpdateUpload(AsyncWebServerRequest* request, String filename, size_t index, uint8_t* data, size_t len, bool final); AsyncWebServer* _server; -}; \ No newline at end of file +}; diff --git a/include/WebApi_gridprofile.h b/include/WebApi_gridprofile.h index 878165993..73c156540 100644 --- a/include/WebApi_gridprofile.h +++ b/include/WebApi_gridprofile.h @@ -2,15 +2,15 @@ #pragma once #include +#include class WebApiGridProfileClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onGridProfileStatus(AsyncWebServerRequest* request); void onGridProfileRawdata(AsyncWebServerRequest* request); AsyncWebServer* _server; -}; \ No newline at end of file +}; diff --git a/include/WebApi_inverter.h b/include/WebApi_inverter.h index a8605153f..b8f054256 100644 --- a/include/WebApi_inverter.h +++ b/include/WebApi_inverter.h @@ -2,11 +2,11 @@ #pragma once #include +#include class WebApiInverterClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onInverterList(AsyncWebServerRequest* request); @@ -16,4 +16,4 @@ class WebApiInverterClass { void onInverterOrder(AsyncWebServerRequest* request); AsyncWebServer* _server; -}; \ No newline at end of file +}; diff --git a/include/WebApi_limit.h b/include/WebApi_limit.h index c2d1a7d75..84d48d3a3 100644 --- a/include/WebApi_limit.h +++ b/include/WebApi_limit.h @@ -2,15 +2,15 @@ #pragma once #include +#include class WebApiLimitClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onLimitStatus(AsyncWebServerRequest* request); void onLimitPost(AsyncWebServerRequest* request); AsyncWebServer* _server; -}; \ No newline at end of file +}; diff --git a/include/WebApi_maintenance.h b/include/WebApi_maintenance.h index db6dcf196..02dc4702f 100644 --- a/include/WebApi_maintenance.h +++ b/include/WebApi_maintenance.h @@ -2,14 +2,14 @@ #pragma once #include +#include class WebApiMaintenanceClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onRebootPost(AsyncWebServerRequest* request); AsyncWebServer* _server; -}; \ No newline at end of file +}; diff --git a/include/WebApi_mqtt.h b/include/WebApi_mqtt.h index 00a2b0b70..6ec971c93 100644 --- a/include/WebApi_mqtt.h +++ b/include/WebApi_mqtt.h @@ -2,13 +2,13 @@ #pragma once #include +#include #define MQTT_JSON_DOC_SIZE 10240 class WebApiMqttClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onMqttStatus(AsyncWebServerRequest* request); @@ -17,4 +17,4 @@ class WebApiMqttClass { String getTlsCertInfo(const char* cert); AsyncWebServer* _server; -}; \ No newline at end of file +}; diff --git a/include/WebApi_network.h b/include/WebApi_network.h index 47ef8d9a1..7587bbbd3 100644 --- a/include/WebApi_network.h +++ b/include/WebApi_network.h @@ -2,11 +2,11 @@ #pragma once #include +#include class WebApiNetworkClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onNetworkStatus(AsyncWebServerRequest* request); @@ -14,4 +14,4 @@ class WebApiNetworkClass { void onNetworkAdminPost(AsyncWebServerRequest* request); AsyncWebServer* _server; -}; \ No newline at end of file +}; diff --git a/include/WebApi_ntp.h b/include/WebApi_ntp.h index 153aeeec5..75e02c549 100644 --- a/include/WebApi_ntp.h +++ b/include/WebApi_ntp.h @@ -2,11 +2,11 @@ #pragma once #include +#include class WebApiNtpClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onNtpStatus(AsyncWebServerRequest* request); @@ -16,4 +16,4 @@ class WebApiNtpClass { void onNtpTimePost(AsyncWebServerRequest* request); AsyncWebServer* _server; -}; \ No newline at end of file +}; diff --git a/include/WebApi_power.h b/include/WebApi_power.h index faed5c4e2..7d186eb4d 100644 --- a/include/WebApi_power.h +++ b/include/WebApi_power.h @@ -2,15 +2,15 @@ #pragma once #include +#include class WebApiPowerClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onPowerStatus(AsyncWebServerRequest* request); void onPowerPost(AsyncWebServerRequest* request); AsyncWebServer* _server; -}; \ No newline at end of file +}; diff --git a/include/WebApi_powerlimiter.h b/include/WebApi_powerlimiter.h index a983a51b3..7e076e0bb 100644 --- a/include/WebApi_powerlimiter.h +++ b/include/WebApi_powerlimiter.h @@ -2,12 +2,12 @@ #pragma once #include +#include class WebApiPowerLimiterClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onStatus(AsyncWebServerRequest* request); diff --git a/include/WebApi_powermeter.h b/include/WebApi_powermeter.h index 01b0d4ae3..64a5ab726 100644 --- a/include/WebApi_powermeter.h +++ b/include/WebApi_powermeter.h @@ -2,12 +2,12 @@ #pragma once #include +#include class WebApiPowerMeterClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onStatus(AsyncWebServerRequest* request); diff --git a/include/WebApi_prometheus.h b/include/WebApi_prometheus.h index 9fbf6e220..08e2221df 100644 --- a/include/WebApi_prometheus.h +++ b/include/WebApi_prometheus.h @@ -3,12 +3,12 @@ #include #include +#include #include class WebApiPrometheusClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onPrometheusMetricsGet(AsyncWebServerRequest* request); @@ -47,4 +47,4 @@ class WebApiPrometheusClass { { FLD_EFF, MetricType_t::GAUGE }, { FLD_IRR, MetricType_t::GAUGE }, }; -}; \ No newline at end of file +}; diff --git a/include/WebApi_security.h b/include/WebApi_security.h index 66e921018..b5981e3d4 100644 --- a/include/WebApi_security.h +++ b/include/WebApi_security.h @@ -2,11 +2,11 @@ #pragma once #include +#include class WebApiSecurityClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onSecurityGet(AsyncWebServerRequest* request); @@ -15,4 +15,4 @@ class WebApiSecurityClass { void onAuthenticateGet(AsyncWebServerRequest* request); AsyncWebServer* _server; -}; \ No newline at end of file +}; diff --git a/include/WebApi_sysstatus.h b/include/WebApi_sysstatus.h index f63edd2ce..32bdc7e3e 100644 --- a/include/WebApi_sysstatus.h +++ b/include/WebApi_sysstatus.h @@ -2,14 +2,14 @@ #pragma once #include +#include class WebApiSysstatusClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onSystemStatus(AsyncWebServerRequest* request); AsyncWebServer* _server; -}; \ No newline at end of file +}; diff --git a/include/WebApi_vedirect.h b/include/WebApi_vedirect.h index ed194117f..dd4ec90ac 100644 --- a/include/WebApi_vedirect.h +++ b/include/WebApi_vedirect.h @@ -2,12 +2,12 @@ #pragma once #include +#include class WebApiVedirectClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void onVedirectStatus(AsyncWebServerRequest* request); diff --git a/include/WebApi_webapp.h b/include/WebApi_webapp.h index da50d9635..401408c61 100644 --- a/include/WebApi_webapp.h +++ b/include/WebApi_webapp.h @@ -2,12 +2,12 @@ #pragma once #include +#include class WebApiWebappClass { public: - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: AsyncWebServer* _server; -}; \ No newline at end of file +}; diff --git a/include/WebApi_ws_Huawei.h b/include/WebApi_ws_Huawei.h index 3d1564e6e..c8248aeca 100644 --- a/include/WebApi_ws_Huawei.h +++ b/include/WebApi_ws_Huawei.h @@ -3,13 +3,13 @@ #include "ArduinoJson.h" #include +#include #include class WebApiWsHuaweiLiveClass { public: WebApiWsHuaweiLiveClass(); - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void generateJsonResponse(JsonVariant& root); @@ -19,8 +19,11 @@ class WebApiWsHuaweiLiveClass { AsyncWebServer* _server; AsyncWebSocket _ws; - uint32_t _lastWsCleanup = 0; - uint32_t _lastUpdateCheck = 0; - std::mutex _mutex; + + Task _wsCleanupTask; + void wsCleanupTaskCb(); + + Task _sendDataTask; + void sendDataTaskCb(); }; \ No newline at end of file diff --git a/include/WebApi_ws_battery.h b/include/WebApi_ws_battery.h index 4a4da4b52..9882649b9 100644 --- a/include/WebApi_ws_battery.h +++ b/include/WebApi_ws_battery.h @@ -3,13 +3,13 @@ #include "ArduinoJson.h" #include +#include #include class WebApiWsBatteryLiveClass { public: WebApiWsBatteryLiveClass(); - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void generateJsonResponse(JsonVariant& root); @@ -19,9 +19,14 @@ class WebApiWsBatteryLiveClass { AsyncWebServer* _server; AsyncWebSocket _ws; - uint32_t _lastWsCleanup = 0; uint32_t _lastUpdateCheck = 0; static constexpr uint16_t _responseSize = 1024 + 512; std::mutex _mutex; + + Task _wsCleanupTask; + void wsCleanupTaskCb(); + + Task _sendDataTask; + void sendDataTaskCb(); }; \ No newline at end of file diff --git a/include/WebApi_ws_console.h b/include/WebApi_ws_console.h index 4eea2c6a2..4289afd0f 100644 --- a/include/WebApi_ws_console.h +++ b/include/WebApi_ws_console.h @@ -1,17 +1,18 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#include - -class WebApiWsConsoleClass { -public: - WebApiWsConsoleClass(); - void init(AsyncWebServer& server); - void loop(); - -private: - AsyncWebServer* _server; - AsyncWebSocket _ws; - - uint32_t _lastWsCleanup = 0; -}; \ No newline at end of file +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +#include +#include + +class WebApiWsConsoleClass { +public: + WebApiWsConsoleClass(); + void init(AsyncWebServer& server, Scheduler& scheduler); + +private: + AsyncWebServer* _server; + AsyncWebSocket _ws; + + Task _wsCleanupTask; + void wsCleanupTaskCb(); +}; diff --git a/include/WebApi_ws_live.h b/include/WebApi_ws_live.h index 37c7fbde1..392ca8696 100644 --- a/include/WebApi_ws_live.h +++ b/include/WebApi_ws_live.h @@ -4,16 +4,16 @@ #include #include #include +#include class WebApiWsLiveClass { public: WebApiWsLiveClass(); - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void generateJsonResponse(JsonVariant& root); - void addField(JsonObject& root, uint8_t idx, std::shared_ptr inv, const ChannelType_t type, const ChannelNum_t channel, const FieldId_t fieldId, String topic = ""); + 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); void onLivedataStatus(AsyncWebServerRequest* request); void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len); @@ -22,9 +22,13 @@ class WebApiWsLiveClass { AsyncWebSocket _ws; uint32_t _lastWsPublish = 0; - uint32_t _lastInvUpdateCheck = 0; - uint32_t _lastWsCleanup = 0; uint32_t _newestInverterTimestamp = 0; std::mutex _mutex; -}; \ No newline at end of file + + Task _wsCleanupTask; + void wsCleanupTaskCb(); + + Task _sendDataTask; + void sendDataTaskCb(); +}; diff --git a/include/WebApi_ws_vedirect_live.h b/include/WebApi_ws_vedirect_live.h index f914c592f..3e0b81aba 100644 --- a/include/WebApi_ws_vedirect_live.h +++ b/include/WebApi_ws_vedirect_live.h @@ -3,14 +3,14 @@ #include "ArduinoJson.h" #include +#include #include #include class WebApiWsVedirectLiveClass { public: WebApiWsVedirectLiveClass(); - void init(AsyncWebServer& server); - void loop(); + void init(AsyncWebServer& server, Scheduler& scheduler); private: void generateJsonResponse(JsonVariant& root); @@ -21,9 +21,14 @@ class WebApiWsVedirectLiveClass { AsyncWebSocket _ws; uint32_t _lastWsPublish = 0; - uint32_t _lastWsCleanup = 0; uint32_t _dataAgeMillis = 0; static constexpr uint16_t _responseSize = 1024 + 128; std::mutex _mutex; + + Task _wsCleanupTask; + void wsCleanupTaskCb(); + + Task _sendDataTask; + void sendDataTaskCb(); }; \ No newline at end of file diff --git a/lib/Hoymiles/src/parser/DevInfoParser.cpp b/lib/Hoymiles/src/parser/DevInfoParser.cpp index d4f599003..fd6ed5cc7 100644 --- a/lib/Hoymiles/src/parser/DevInfoParser.cpp +++ b/lib/Hoymiles/src/parser/DevInfoParser.cpp @@ -137,6 +137,14 @@ time_t DevInfoParser::getFwBuildDateTime() const return timegm(&timeinfo); } +String DevInfoParser::getFwBuildDateTimeStr() const +{ + char timebuffer[32]; + const time_t t = getFwBuildDateTime(); + std::strftime(timebuffer, sizeof(timebuffer), "%Y-%m-%d %H:%M:%S", gmtime(&t)); + return timebuffer; +} + uint16_t DevInfoParser::getFwBootloaderVersion() const { HOY_SEMAPHORE_TAKE(); @@ -254,4 +262,4 @@ time_t DevInfoParser::timegm(const struct tm* t) result -= 3600; /*@ -matchanyintegral @*/ return (result); -} \ No newline at end of file +} diff --git a/lib/Hoymiles/src/parser/DevInfoParser.h b/lib/Hoymiles/src/parser/DevInfoParser.h index 89c40f862..239055251 100644 --- a/lib/Hoymiles/src/parser/DevInfoParser.h +++ b/lib/Hoymiles/src/parser/DevInfoParser.h @@ -21,6 +21,7 @@ class DevInfoParser : public Parser { uint16_t getFwBuildVersion() const; time_t getFwBuildDateTime() const; + String getFwBuildDateTimeStr() const; uint16_t getFwBootloaderVersion() const; uint32_t getHwPartNumber() const; @@ -43,4 +44,4 @@ class DevInfoParser : public Parser { uint8_t _payloadDevInfoSimple[DEV_INFO_SIZE] = {}; uint8_t _devInfoSimpleLength = 0; -}; \ No newline at end of file +}; diff --git a/lib/Hoymiles/src/parser/GridProfileParser.cpp b/lib/Hoymiles/src/parser/GridProfileParser.cpp index b6c1573b7..37cb1d4ac 100644 --- a/lib/Hoymiles/src/parser/GridProfileParser.cpp +++ b/lib/Hoymiles/src/parser/GridProfileParser.cpp @@ -390,7 +390,7 @@ std::vector GridProfileParser::getRawData() const { std::vector ret; HOY_SEMAPHORE_TAKE(); - for (uint8_t i = 0; i < GRID_PROFILE_SIZE; i++) { + for (uint8_t i = 0; i < _gridProfileLength; i++) { ret.push_back(_payloadGridProfile[i]); } HOY_SEMAPHORE_GIVE(); diff --git a/platformio.ini b/platformio.ini index 3bd1645fb..e145e14ee 100644 --- a/platformio.ini +++ b/platformio.ini @@ -37,13 +37,12 @@ build_unflags = lib_deps = https://github.com/yubox-node-org/ESPAsyncWebServer - bblanchon/ArduinoJson @ ^6.21.4 + bblanchon/ArduinoJson @ ^6.21.5 https://github.com/bertmelis/espMqttClient.git#v1.5.0 nrf24/RF24 @ ^1.4.8 olikraus/U8g2 @ ^2.35.9 buelowp/sunset @ ^1.1.7 https://github.com/arkhipenko/TaskScheduler#testing - https://github.com/arkhipenko/TaskScheduler#testing https://github.com/coryjfowler/MCP_CAN_lib plerup/EspSoftwareSerial @ ^8.0.1 https://github.com/dok-net/ghostl @ ^1.0.1 diff --git a/src/Datastore.cpp b/src/Datastore.cpp index 1d4c2eb05..5bfbb98ed 100644 --- a/src/Datastore.cpp +++ b/src/Datastore.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2023 Thomas Basler and others + * Copyright (C) 2023-2024 Thomas Basler and others */ #include "Datastore.h" #include "Configuration.h" @@ -8,12 +8,14 @@ DatastoreClass Datastore; +DatastoreClass::DatastoreClass() + : _loopTask(1 * TASK_SECOND, TASK_FOREVER, std::bind(&DatastoreClass::loop, this)) +{ +} + void DatastoreClass::init(Scheduler& scheduler) { scheduler.addTask(_loopTask); - _loopTask.setCallback(std::bind(&DatastoreClass::loop, this)); - _loopTask.setIterations(TASK_FOREVER); - _loopTask.setInterval(1 * TASK_SECOND); _loopTask.enable(); } diff --git a/src/Display_Graphic.cpp b/src/Display_Graphic.cpp index 04195fd66..7f5d94c37 100644 --- a/src/Display_Graphic.cpp +++ b/src/Display_Graphic.cpp @@ -35,6 +35,7 @@ static const char* const i18n_yield_total_kwh[] = { "total: %.1f kWh", "Ges.: %. static const char* const i18n_date_format[] = { "%m/%d/%Y %H:%M", "%d.%m.%Y %H:%M", "%d/%m/%Y %H:%M" }; DisplayGraphicClass::DisplayGraphicClass() + : _loopTask(TASK_IMMEDIATE, TASK_FOREVER, std::bind(&DisplayGraphicClass::loop, this)) { } @@ -55,8 +56,6 @@ void DisplayGraphicClass::init(Scheduler& scheduler, const DisplayType_t type, c _diagram.init(scheduler, _display); scheduler.addTask(_loopTask); - _loopTask.setCallback(std::bind(&DisplayGraphicClass::loop, this)); - _loopTask.setIterations(TASK_FOREVER); _loopTask.setInterval(_period); _loopTask.enable(); } diff --git a/src/Display_Graphic_Diagram.cpp b/src/Display_Graphic_Diagram.cpp index 498123b90..b52968829 100644 --- a/src/Display_Graphic_Diagram.cpp +++ b/src/Display_Graphic_Diagram.cpp @@ -8,6 +8,8 @@ #include DisplayGraphicDiagramClass::DisplayGraphicDiagramClass() + : _averageTask(1 * TASK_SECOND, TASK_FOREVER, std::bind(&DisplayGraphicDiagramClass::averageLoop, this)) + , _dataPointTask(TASK_IMMEDIATE, TASK_FOREVER, std::bind(&DisplayGraphicDiagramClass::dataPointLoop, this)) { } @@ -16,14 +18,9 @@ void DisplayGraphicDiagramClass::init(Scheduler& scheduler, U8G2* display) _display = display; scheduler.addTask(_averageTask); - _averageTask.setCallback(std::bind(&DisplayGraphicDiagramClass::averageLoop, this)); - _averageTask.setIterations(TASK_FOREVER); - _averageTask.setInterval(1 * TASK_SECOND); _averageTask.enable(); scheduler.addTask(_dataPointTask); - _dataPointTask.setCallback(std::bind(&DisplayGraphicDiagramClass::dataPointLoop, this)); - _dataPointTask.setIterations(TASK_FOREVER); updatePeriod(); _dataPointTask.enable(); } @@ -58,7 +55,7 @@ uint32_t DisplayGraphicDiagramClass::getSecondsPerDot() void DisplayGraphicDiagramClass::updatePeriod() { // Calculate seconds per datapoint - _dataPointTask.setInterval(Configuration.get().Display.Diagram.Duration * TASK_SECOND / MAX_DATAPOINTS ); + _dataPointTask.setInterval(Configuration.get().Display.Diagram.Duration * TASK_SECOND / MAX_DATAPOINTS); } void DisplayGraphicDiagramClass::redraw(uint8_t screenSaverOffsetX, uint8_t xPos, uint8_t yPos, uint8_t width, uint8_t height, bool isFullscreen) @@ -110,7 +107,9 @@ void DisplayGraphicDiagramClass::redraw(uint8_t screenSaverOffsetX, uint8_t xPos if (maxWatts > 0 && isFullscreen) { // draw y axis ticks - const uint16_t yAxisWattPerTick = maxWatts <= 100 ? 10 : maxWatts <= 1000 ? 100 : maxWatts < 5000 ? 500 : 1000; + const uint16_t yAxisWattPerTick = maxWatts <= 100 ? 10 : maxWatts <= 1000 ? 100 + : maxWatts < 5000 ? 500 + : 1000; const uint8_t yAxisTickSizePixel = height / (maxWatts / yAxisWattPerTick); for (int16_t tickYPos = graphPosY + height; tickYPos > graphPosY - arrow_size; tickYPos -= yAxisTickSizePixel) { diff --git a/src/InverterSettings.cpp b/src/InverterSettings.cpp index 02bef2f1e..cfc990cd1 100644 --- a/src/InverterSettings.cpp +++ b/src/InverterSettings.cpp @@ -25,6 +25,12 @@ InverterSettingsClass InverterSettings; +InverterSettingsClass::InverterSettingsClass() + : _settingsTask(INVERTER_UPDATE_SETTINGS_INTERVAL, TASK_FOREVER, std::bind(&InverterSettingsClass::settingsLoop, this)) + , _hoyTask(TASK_IMMEDIATE, TASK_FOREVER, std::bind(&InverterSettingsClass::hoyLoop, this)) +{ +} + void InverterSettingsClass::init(Scheduler& scheduler) { const CONFIG_T& config = Configuration.get(); @@ -94,14 +100,9 @@ void InverterSettingsClass::init(Scheduler& scheduler) } scheduler.addTask(_hoyTask); - _hoyTask.setCallback(std::bind(&InverterSettingsClass::hoyLoop, this)); - _hoyTask.setIterations(TASK_FOREVER); _hoyTask.enable(); scheduler.addTask(_settingsTask); - _settingsTask.setCallback(std::bind(&InverterSettingsClass::settingsLoop, this)); - _settingsTask.setIterations(TASK_FOREVER); - _settingsTask.setInterval(INVERTER_UPDATE_SETTINGS_INTERVAL); _settingsTask.enable(); } @@ -122,7 +123,7 @@ void InverterSettingsClass::settingsLoop() inv->setEnablePolling(inv_cfg.Poll_Enable && (SunPosition.isDayPeriod() || inv_cfg.Poll_Enable_Night)); inv->setEnableCommands(inv_cfg.Command_Enable && (SunPosition.isDayPeriod() || inv_cfg.Command_Enable_Night)); } - } +} void InverterSettingsClass::hoyLoop() { diff --git a/src/Led_Single.cpp b/src/Led_Single.cpp index 744c7b78d..40320b1f1 100644 --- a/src/Led_Single.cpp +++ b/src/Led_Single.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2023 Thomas Basler and others + * Copyright (C) 2023-2024 Thomas Basler and others */ #include "Led_Single.h" #include "Configuration.h" @@ -38,6 +38,8 @@ const uint8_t pwmTable[] = { #define LED_OFF 0 LedSingleClass::LedSingleClass() + : _setTask(LEDSINGLE_UPDATE_INTERVAL * TASK_MILLISECOND, TASK_FOREVER, std::bind(&LedSingleClass::setLoop, this)) + , _outputTask(TASK_IMMEDIATE, TASK_FOREVER, std::bind(&LedSingleClass::outputLoop, this)) { } @@ -62,14 +64,9 @@ void LedSingleClass::init(Scheduler& scheduler) if (ledActive) { scheduler.addTask(_outputTask); - _outputTask.setCallback(std::bind(&LedSingleClass::outputLoop, this)); - _outputTask.setIterations(TASK_FOREVER); _outputTask.enable(); scheduler.addTask(_setTask); - _setTask.setCallback(std::bind(&LedSingleClass::setLoop, this)); - _setTask.setInterval(LEDSINGLE_UPDATE_INTERVAL * TASK_MILLISECOND); - _setTask.setIterations(TASK_FOREVER); _setTask.enable(); } } diff --git a/src/MessageOutput.cpp b/src/MessageOutput.cpp index 027ce20c8..850dbccab 100644 --- a/src/MessageOutput.cpp +++ b/src/MessageOutput.cpp @@ -1,17 +1,20 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include #include "MessageOutput.h" MessageOutputClass MessageOutput; +MessageOutputClass::MessageOutputClass() + : _loopTask(TASK_IMMEDIATE, TASK_FOREVER, std::bind(&MessageOutputClass::loop, this)) +{ +} + void MessageOutputClass::init(Scheduler& scheduler) { scheduler.addTask(_loopTask); - _loopTask.setCallback(std::bind(&MessageOutputClass::loop, this)); - _loopTask.setIterations(TASK_FOREVER); _loopTask.enable(); } @@ -110,4 +113,4 @@ void MessageOutputClass::loop() _ws->textAll(std::make_shared(std::move(_lines.front()))); _lines.pop(); } -} \ No newline at end of file +} diff --git a/src/MqttHandleDtu.cpp b/src/MqttHandleDtu.cpp index c20ddb1e7..e8192b2e2 100644 --- a/src/MqttHandleDtu.cpp +++ b/src/MqttHandleDtu.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "MqttHandleDtu.h" #include "Configuration.h" @@ -10,11 +10,14 @@ MqttHandleDtuClass MqttHandleDtu; +MqttHandleDtuClass::MqttHandleDtuClass() + : _loopTask(TASK_IMMEDIATE, TASK_FOREVER, std::bind(&MqttHandleDtuClass::loop, this)) +{ +} + void MqttHandleDtuClass::init(Scheduler& scheduler) { scheduler.addTask(_loopTask); - _loopTask.setCallback(std::bind(&MqttHandleDtuClass::loop, this)); - _loopTask.setIterations(TASK_FOREVER); _loopTask.setInterval(Configuration.get().Mqtt.PublishInterval * TASK_SECOND); _loopTask.enable(); } @@ -35,4 +38,4 @@ void MqttHandleDtuClass::loop() MqttSettings.publish("dtu/rssi", String(WiFi.RSSI())); MqttSettings.publish("dtu/bssid", WiFi.BSSIDstr()); } -} \ No newline at end of file +} diff --git a/src/MqttHandleHass.cpp b/src/MqttHandleHass.cpp index 0f5c293c8..1df7237e6 100644 --- a/src/MqttHandleHass.cpp +++ b/src/MqttHandleHass.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "MqttHandleHass.h" #include "MqttHandleInverter.h" @@ -11,11 +11,14 @@ MqttHandleHassClass MqttHandleHass; +MqttHandleHassClass::MqttHandleHassClass() + : _loopTask(TASK_IMMEDIATE, TASK_FOREVER, std::bind(&MqttHandleHassClass::loop, this)) +{ +} + void MqttHandleHassClass::init(Scheduler& scheduler) { scheduler.addTask(_loopTask); - _loopTask.setCallback(std::bind(&MqttHandleHassClass::loop, this)); - _loopTask.setIterations(TASK_FOREVER); _loopTask.enable(); } @@ -53,7 +56,7 @@ void MqttHandleHassClass::publishConfig() const CONFIG_T& config = Configuration.get(); - // publish DTU sensors + // publish DTU sensors publishDtuSensor("IP", "", "diagnostic", "mdi:network-outline", "", ""); publishDtuSensor("WiFi Signal", "signal_strength", "diagnostic", "", "dBm", "rssi"); publishDtuSensor("Uptime", "duration", "diagnostic", "", "s", ""); @@ -421,5 +424,5 @@ void MqttHandleHassClass::publish(const String& subtopic, const String& payload) { String topic = Configuration.get().Mqtt.Hass.Topic; topic += subtopic; - MqttSettings.publishGeneric(topic.c_str(), payload.c_str(), Configuration.get().Mqtt.Hass.Retain); -} \ No newline at end of file + MqttSettings.publishGeneric(topic, payload, Configuration.get().Mqtt.Hass.Retain); +} diff --git a/src/MqttHandleInverter.cpp b/src/MqttHandleInverter.cpp index 881210963..53cf490b2 100644 --- a/src/MqttHandleInverter.cpp +++ b/src/MqttHandleInverter.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "MqttHandleInverter.h" #include "MessageOutput.h" @@ -18,6 +18,11 @@ MqttHandleInverterClass MqttHandleInverter; +MqttHandleInverterClass::MqttHandleInverterClass() + : _loopTask(TASK_IMMEDIATE, TASK_FOREVER, std::bind(&MqttHandleInverterClass::loop, this)) +{ +} + void MqttHandleInverterClass::init(Scheduler& scheduler) { using std::placeholders::_1; @@ -28,16 +33,14 @@ void MqttHandleInverterClass::init(Scheduler& scheduler) using std::placeholders::_6; const String topic = MqttSettings.getPrefix(); - MqttSettings.subscribe(String(topic + "+/cmd/" + TOPIC_SUB_LIMIT_PERSISTENT_RELATIVE).c_str(), 0, std::bind(&MqttHandleInverterClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6)); - MqttSettings.subscribe(String(topic + "+/cmd/" + TOPIC_SUB_LIMIT_PERSISTENT_ABSOLUTE).c_str(), 0, std::bind(&MqttHandleInverterClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6)); - MqttSettings.subscribe(String(topic + "+/cmd/" + TOPIC_SUB_LIMIT_NONPERSISTENT_RELATIVE).c_str(), 0, std::bind(&MqttHandleInverterClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6)); - MqttSettings.subscribe(String(topic + "+/cmd/" + TOPIC_SUB_LIMIT_NONPERSISTENT_ABSOLUTE).c_str(), 0, std::bind(&MqttHandleInverterClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6)); - MqttSettings.subscribe(String(topic + "+/cmd/" + TOPIC_SUB_POWER).c_str(), 0, std::bind(&MqttHandleInverterClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6)); - MqttSettings.subscribe(String(topic + "+/cmd/" + TOPIC_SUB_RESTART).c_str(), 0, std::bind(&MqttHandleInverterClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6)); + MqttSettings.subscribe(String(topic + "+/cmd/" + TOPIC_SUB_LIMIT_PERSISTENT_RELATIVE), 0, std::bind(&MqttHandleInverterClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6)); + MqttSettings.subscribe(String(topic + "+/cmd/" + TOPIC_SUB_LIMIT_PERSISTENT_ABSOLUTE), 0, std::bind(&MqttHandleInverterClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6)); + MqttSettings.subscribe(String(topic + "+/cmd/" + TOPIC_SUB_LIMIT_NONPERSISTENT_RELATIVE), 0, std::bind(&MqttHandleInverterClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6)); + MqttSettings.subscribe(String(topic + "+/cmd/" + TOPIC_SUB_LIMIT_NONPERSISTENT_ABSOLUTE), 0, std::bind(&MqttHandleInverterClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6)); + MqttSettings.subscribe(String(topic + "+/cmd/" + TOPIC_SUB_POWER), 0, std::bind(&MqttHandleInverterClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6)); + MqttSettings.subscribe(String(topic + "+/cmd/" + TOPIC_SUB_RESTART), 0, std::bind(&MqttHandleInverterClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6)); scheduler.addTask(_loopTask); - _loopTask.setCallback(std::bind(&MqttHandleInverterClass::loop, this)); - _loopTask.setIterations(TASK_FOREVER); _loopTask.setInterval(Configuration.get().Mqtt.PublishInterval * TASK_SECOND); _loopTask.enable(); } @@ -68,10 +71,7 @@ void MqttHandleInverterClass::loop() MqttSettings.publish(subtopic + "/device/fwbuildversion", String(inv->DevInfo()->getFwBuildVersion())); // Firmware Build DateTime - char timebuffer[32]; - const time_t t = inv->DevInfo()->getFwBuildDateTime(); - std::strftime(timebuffer, sizeof(timebuffer), "%Y-%m-%d %H:%M:%S", gmtime(&t)); - MqttSettings.publish(subtopic + "/device/fwbuilddatetime", String(timebuffer)); + MqttSettings.publish(subtopic + "/device/fwbuilddatetime", inv->DevInfo()->getFwBuildDateTimeStr()); // Hardware part number MqttSettings.publish(subtopic + "/device/hwpartnumber", String(inv->DevInfo()->getHwPartNumber())); @@ -246,4 +246,4 @@ void MqttHandleInverterClass::onMqttMessage(const espMqttClientTypes::MessagePro MessageOutput.println("Ignored because retained"); } } -} \ No newline at end of file +} diff --git a/src/MqttHandleInverterTotal.cpp b/src/MqttHandleInverterTotal.cpp index db584b264..5f5be6a92 100644 --- a/src/MqttHandleInverterTotal.cpp +++ b/src/MqttHandleInverterTotal.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2023 Thomas Basler and others + * Copyright (C) 2023-2024 Thomas Basler and others */ #include "MqttHandleInverterTotal.h" #include "Configuration.h" @@ -10,11 +10,14 @@ MqttHandleInverterTotalClass MqttHandleInverterTotal; +MqttHandleInverterTotalClass::MqttHandleInverterTotalClass() + : _loopTask(TASK_IMMEDIATE, TASK_FOREVER, std::bind(&MqttHandleInverterTotalClass::loop, this)) +{ +} + void MqttHandleInverterTotalClass::init(Scheduler& scheduler) { scheduler.addTask(_loopTask); - _loopTask.setCallback(std::bind(&MqttHandleInverterTotalClass::loop, this)); - _loopTask.setIterations(TASK_FOREVER); _loopTask.setInterval(Configuration.get().Mqtt.PublishInterval * TASK_SECOND); _loopTask.enable(); } diff --git a/src/NetworkSettings.cpp b/src/NetworkSettings.cpp index c8004f169..59ce8f75b 100644 --- a/src/NetworkSettings.cpp +++ b/src/NetworkSettings.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "NetworkSettings.h" #include "Configuration.h" @@ -12,7 +12,8 @@ #include NetworkSettingsClass::NetworkSettingsClass() - : _apIp(192, 168, 4, 1) + : _loopTask(TASK_IMMEDIATE, TASK_FOREVER, std::bind(&NetworkSettingsClass::loop, this)) + , _apIp(192, 168, 4, 1) , _apNetmask(255, 255, 255, 0) { _dnsServer.reset(new DNSServer()); @@ -29,8 +30,6 @@ void NetworkSettingsClass::init(Scheduler& scheduler) setupMode(); scheduler.addTask(_loopTask); - _loopTask.setCallback(std::bind(&NetworkSettingsClass::loop, this)); - _loopTask.setIterations(TASK_FOREVER); _loopTask.enable(); } diff --git a/src/SunPosition.cpp b/src/SunPosition.cpp index a3a9f47fb..f1e1bee4a 100644 --- a/src/SunPosition.cpp +++ b/src/SunPosition.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2023 Thomas Basler and others + * Copyright (C) 2023-2024 Thomas Basler and others */ #include "SunPosition.h" #include "Configuration.h" @@ -10,15 +10,13 @@ SunPositionClass SunPosition; SunPositionClass::SunPositionClass() + : _loopTask(5 * TASK_SECOND, TASK_FOREVER, std::bind(&SunPositionClass::loop, this)) { } void SunPositionClass::init(Scheduler& scheduler) { scheduler.addTask(_loopTask); - _loopTask.setCallback(std::bind(&SunPositionClass::loop, this)); - _loopTask.setIterations(TASK_FOREVER); - _loopTask.setInterval(5 * TASK_SECOND); _loopTask.enable(); } diff --git a/src/WebApi.cpp b/src/WebApi.cpp index 6485309fa..d00f08702 100644 --- a/src/WebApi.cpp +++ b/src/WebApi.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi.h" #include "Configuration.h" @@ -14,72 +14,36 @@ WebApiClass::WebApiClass() void WebApiClass::init(Scheduler& scheduler) { - _webApiConfig.init(_server); - _webApiDevice.init(_server); - _webApiDevInfo.init(_server); - _webApiDtu.init(_server); - _webApiEventlog.init(_server); - _webApiFirmware.init(_server); - _webApiGridprofile.init(_server); - _webApiInverter.init(_server); - _webApiLimit.init(_server); - _webApiMaintenance.init(_server); - _webApiMqtt.init(_server); - _webApiNetwork.init(_server); - _webApiNtp.init(_server); - _webApiPower.init(_server); - _webApiPrometheus.init(_server); - _webApiSecurity.init(_server); - _webApiSysstatus.init(_server); - _webApiWebapp.init(_server); - _webApiWsConsole.init(_server); - _webApiWsLive.init(_server); - _webApiBattery.init(_server); - _webApiPowerMeter.init(_server); - _webApiPowerLimiter.init(_server); - _webApiWsVedirectLive.init(_server); - _webApiVedirect.init(_server); - _webApiWsHuaweiLive.init(_server); - _webApiHuaweiClass.init(_server); - _webApiWsBatteryLive.init(_server); + _webApiConfig.init(_server, scheduler); + _webApiDevice.init(_server, scheduler); + _webApiDevInfo.init(_server, scheduler); + _webApiDtu.init(_server, scheduler); + _webApiEventlog.init(_server, scheduler); + _webApiFirmware.init(_server, scheduler); + _webApiGridprofile.init(_server, scheduler); + _webApiInverter.init(_server, scheduler); + _webApiLimit.init(_server, scheduler); + _webApiMaintenance.init(_server, scheduler); + _webApiMqtt.init(_server, scheduler); + _webApiNetwork.init(_server, scheduler); + _webApiNtp.init(_server, scheduler); + _webApiPower.init(_server, scheduler); + _webApiPrometheus.init(_server, scheduler); + _webApiSecurity.init(_server, scheduler); + _webApiSysstatus.init(_server, scheduler); + _webApiWebapp.init(_server, scheduler); + _webApiWsConsole.init(_server, scheduler); + _webApiWsLive.init(_server, scheduler); + _webApiBattery.init(_server, scheduler); + _webApiPowerMeter.init(_server, scheduler); + _webApiPowerLimiter.init(_server, scheduler); + _webApiWsVedirectLive.init(_server, scheduler); + _webApiVedirect.init(_server, scheduler); + _webApiWsHuaweiLive.init(_server, scheduler); + _webApiHuaweiClass.init(_server, scheduler); + _webApiWsBatteryLive.init(_server, scheduler); _server.begin(); - - scheduler.addTask(_loopTask); - _loopTask.setCallback(std::bind(&WebApiClass::loop, this)); - _loopTask.setIterations(TASK_FOREVER); - _loopTask.enable(); -} - -void WebApiClass::loop() -{ - _webApiBattery.loop(); - _webApiConfig.loop(); - _webApiDevice.loop(); - _webApiDevInfo.loop(); - _webApiDtu.loop(); - _webApiEventlog.loop(); - _webApiFirmware.loop(); - _webApiGridprofile.loop(); - _webApiInverter.loop(); - _webApiLimit.loop(); - _webApiMaintenance.loop(); - _webApiMqtt.loop(); - _webApiNetwork.loop(); - _webApiNtp.loop(); - _webApiPower.loop(); - _webApiPowerMeter.loop(); - _webApiPowerLimiter.loop(); - _webApiSecurity.loop(); - _webApiSysstatus.loop(); - _webApiWebapp.loop(); - _webApiWsConsole.loop(); - _webApiWsLive.loop(); - _webApiWsVedirectLive.loop(); - _webApiVedirect.loop(); - _webApiWsHuaweiLive.loop(); - _webApiHuaweiClass.loop(); - _webApiWsBatteryLive.loop(); } bool WebApiClass::checkCredentials(AsyncWebServerRequest* request) @@ -129,4 +93,4 @@ void WebApiClass::writeConfig(JsonVariant& retMsg, const WebApiError code, const } } -WebApiClass WebApi; \ No newline at end of file +WebApiClass WebApi; diff --git a/src/WebApi_Huawei.cpp b/src/WebApi_Huawei.cpp index c9cd1df46..778833d11 100644 --- a/src/WebApi_Huawei.cpp +++ b/src/WebApi_Huawei.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_Huawei.h" #include "Huawei_can.h" @@ -12,7 +12,7 @@ #include #include -void WebApiHuaweiClass::init(AsyncWebServer& server) +void WebApiHuaweiClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -24,10 +24,6 @@ void WebApiHuaweiClass::init(AsyncWebServer& server) _server->on("/api/huawei/limit/config", HTTP_POST, std::bind(&WebApiHuaweiClass::onPost, this, _1)); } -void WebApiHuaweiClass::loop() -{ -} - void WebApiHuaweiClass::getJsonData(JsonVariant& root) { const RectifierParameters_t * rp = HuaweiCan.get(); diff --git a/src/WebApi_battery.cpp b/src/WebApi_battery.cpp index f7b5ade3d..eec84d7b7 100644 --- a/src/WebApi_battery.cpp +++ b/src/WebApi_battery.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "ArduinoJson.h" @@ -13,7 +13,7 @@ #include "WebApi_errors.h" #include "helper.h" -void WebApiBatteryClass::init(AsyncWebServer& server) +void WebApiBatteryClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -24,10 +24,6 @@ void WebApiBatteryClass::init(AsyncWebServer& server) _server->on("/api/battery/config", HTTP_POST, std::bind(&WebApiBatteryClass::onAdminPost, this, _1)); } -void WebApiBatteryClass::loop() -{ -} - void WebApiBatteryClass::onStatus(AsyncWebServerRequest* request) { if (!WebApi.checkCredentialsReadonly(request)) { diff --git a/src/WebApi_config.cpp b/src/WebApi_config.cpp index 73df1e3d0..3372e4f45 100644 --- a/src/WebApi_config.cpp +++ b/src/WebApi_config.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_config.h" #include "Configuration.h" @@ -10,7 +10,7 @@ #include #include -void WebApiConfigClass::init(AsyncWebServer& server) +void WebApiConfigClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; using std::placeholders::_2; @@ -29,10 +29,6 @@ void WebApiConfigClass::init(AsyncWebServer& server) std::bind(&WebApiConfigClass::onConfigUpload, this, _1, _2, _3, _4, _5, _6)); } -void WebApiConfigClass::loop() -{ -} - void WebApiConfigClass::onConfigGet(AsyncWebServerRequest* request) { if (!WebApi.checkCredentials(request)) { @@ -186,4 +182,4 @@ void WebApiConfigClass::onConfigUpload(AsyncWebServerRequest* request, String fi // close the file handle as the upload is now done request->_tempFile.close(); } -} \ No newline at end of file +} diff --git a/src/WebApi_device.cpp b/src/WebApi_device.cpp index bb66563cd..010a539f9 100644 --- a/src/WebApi_device.cpp +++ b/src/WebApi_device.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_device.h" #include "Configuration.h" @@ -12,7 +12,7 @@ #include "helper.h" #include -void WebApiDeviceClass::init(AsyncWebServer& server) +void WebApiDeviceClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -22,10 +22,6 @@ void WebApiDeviceClass::init(AsyncWebServer& server) _server->on("/api/device/config", HTTP_POST, std::bind(&WebApiDeviceClass::onDeviceAdminPost, this, _1)); } -void WebApiDeviceClass::loop() -{ -} - void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request) { if (!WebApi.checkCredentials(request)) { diff --git a/src/WebApi_devinfo.cpp b/src/WebApi_devinfo.cpp index b5f3e3707..a27cb31ee 100644 --- a/src/WebApi_devinfo.cpp +++ b/src/WebApi_devinfo.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_devinfo.h" #include "WebApi.h" @@ -8,7 +8,7 @@ #include #include -void WebApiDevInfoClass::init(AsyncWebServer& server) +void WebApiDevInfoClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -17,10 +17,6 @@ void WebApiDevInfoClass::init(AsyncWebServer& server) _server->on("/api/devinfo/status", HTTP_GET, std::bind(&WebApiDevInfoClass::onDevInfoStatus, this, _1)); } -void WebApiDevInfoClass::loop() -{ -} - void WebApiDevInfoClass::onDevInfoStatus(AsyncWebServerRequest* request) { if (!WebApi.checkCredentialsReadonly(request)) { @@ -46,13 +42,9 @@ void WebApiDevInfoClass::onDevInfoStatus(AsyncWebServerRequest* request) root["hw_version"] = inv->DevInfo()->getHwVersion(); root["hw_model_name"] = inv->DevInfo()->getHwModelName(); root["max_power"] = inv->DevInfo()->getMaxPower(); - - char timebuffer[32]; - const time_t t = inv->DevInfo()->getFwBuildDateTime(); - std::strftime(timebuffer, sizeof(timebuffer), "%Y-%m-%d %H:%M:%S", gmtime(&t)); - root["fw_build_datetime"] = String(timebuffer); + root["fw_build_datetime"] = inv->DevInfo()->getFwBuildDateTimeStr(); } response->setLength(); request->send(response); -} \ No newline at end of file +} diff --git a/src/WebApi_dtu.cpp b/src/WebApi_dtu.cpp index 3aef58a92..adfd411c4 100644 --- a/src/WebApi_dtu.cpp +++ b/src/WebApi_dtu.cpp @@ -9,7 +9,12 @@ #include #include -void WebApiDtuClass::init(AsyncWebServer& server) +WebApiDtuClass::WebApiDtuClass() + : _applyDataTask(TASK_IMMEDIATE, TASK_ONCE, std::bind(&WebApiDtuClass::applyDataTaskCb, this)) +{ +} + +void WebApiDtuClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -17,22 +22,21 @@ void WebApiDtuClass::init(AsyncWebServer& 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)); + + scheduler.addTask(_applyDataTask); } -void WebApiDtuClass::loop() +void WebApiDtuClass::applyDataTaskCb() { - if (_performReload) { - // Execute stuff in main thread to avoid busy SPI bus - CONFIG_T& config = Configuration.get(); - Hoymiles.getRadioNrf()->setPALevel((rf24_pa_dbm_e)config.Dtu.Nrf.PaLevel); - Hoymiles.getRadioCmt()->setPALevel(config.Dtu.Cmt.PaLevel); - Hoymiles.getRadioNrf()->setDtuSerial(config.Dtu.Serial); - Hoymiles.getRadioCmt()->setDtuSerial(config.Dtu.Serial); - Hoymiles.getRadioCmt()->setCountryMode(static_cast(config.Dtu.Cmt.CountryMode)); - Hoymiles.getRadioCmt()->setInverterTargetFrequency(config.Dtu.Cmt.Frequency); - Hoymiles.setPollInterval(config.Dtu.PollInterval); - _performReload = false; - } + // Execute stuff in main thread to avoid busy SPI bus + CONFIG_T& config = Configuration.get(); + Hoymiles.getRadioNrf()->setPALevel((rf24_pa_dbm_e)config.Dtu.Nrf.PaLevel); + Hoymiles.getRadioCmt()->setPALevel(config.Dtu.Cmt.PaLevel); + Hoymiles.getRadioNrf()->setDtuSerial(config.Dtu.Serial); + Hoymiles.getRadioCmt()->setDtuSerial(config.Dtu.Serial); + Hoymiles.getRadioCmt()->setCountryMode(static_cast(config.Dtu.Cmt.CountryMode)); + Hoymiles.getRadioCmt()->setInverterTargetFrequency(config.Dtu.Cmt.Frequency); + Hoymiles.setPollInterval(config.Dtu.PollInterval); } void WebApiDtuClass::onDtuAdminGet(AsyncWebServerRequest* request) @@ -199,5 +203,5 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request) response->setLength(); request->send(response); - _performReload = true; + _applyDataTask.enable(); } diff --git a/src/WebApi_eventlog.cpp b/src/WebApi_eventlog.cpp index 0551978af..a92e515e7 100644 --- a/src/WebApi_eventlog.cpp +++ b/src/WebApi_eventlog.cpp @@ -1,13 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_eventlog.h" #include "WebApi.h" #include #include -void WebApiEventlogClass::init(AsyncWebServer& server) +void WebApiEventlogClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -16,10 +16,6 @@ void WebApiEventlogClass::init(AsyncWebServer& server) _server->on("/api/eventlog/status", HTTP_GET, std::bind(&WebApiEventlogClass::onEventlogStatus, this, _1)); } -void WebApiEventlogClass::loop() -{ -} - void WebApiEventlogClass::onEventlogStatus(AsyncWebServerRequest* request) { if (!WebApi.checkCredentialsReadonly(request)) { @@ -70,4 +66,4 @@ void WebApiEventlogClass::onEventlogStatus(AsyncWebServerRequest* request) response->setLength(); request->send(response); -} \ No newline at end of file +} diff --git a/src/WebApi_firmware.cpp b/src/WebApi_firmware.cpp index cbc4d7707..617fca067 100644 --- a/src/WebApi_firmware.cpp +++ b/src/WebApi_firmware.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_firmware.h" #include "Configuration.h" @@ -10,7 +10,7 @@ #include "helper.h" #include -void WebApiFirmwareClass::init(AsyncWebServer& server) +void WebApiFirmwareClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; using std::placeholders::_2; @@ -26,10 +26,6 @@ void WebApiFirmwareClass::init(AsyncWebServer& server) std::bind(&WebApiFirmwareClass::onFirmwareUpdateUpload, this, _1, _2, _3, _4, _5, _6)); } -void WebApiFirmwareClass::loop() -{ -} - void WebApiFirmwareClass::onFirmwareUpdateFinish(AsyncWebServerRequest* request) { if (!WebApi.checkCredentials(request)) { @@ -83,4 +79,4 @@ void WebApiFirmwareClass::onFirmwareUpdateUpload(AsyncWebServerRequest* request, } else { return; } -} \ No newline at end of file +} diff --git a/src/WebApi_gridprofile.cpp b/src/WebApi_gridprofile.cpp index a5793e772..587f46400 100644 --- a/src/WebApi_gridprofile.cpp +++ b/src/WebApi_gridprofile.cpp @@ -1,13 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_gridprofile.h" #include "WebApi.h" #include #include -void WebApiGridProfileClass::init(AsyncWebServer& server) +void WebApiGridProfileClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -17,10 +17,6 @@ void WebApiGridProfileClass::init(AsyncWebServer& server) _server->on("/api/gridprofile/rawdata", HTTP_GET, std::bind(&WebApiGridProfileClass::onGridProfileRawdata, this, _1)); } -void WebApiGridProfileClass::loop() -{ -} - void WebApiGridProfileClass::onGridProfileStatus(AsyncWebServerRequest* request) { if (!WebApi.checkCredentialsReadonly(request)) { @@ -91,4 +87,4 @@ void WebApiGridProfileClass::onGridProfileRawdata(AsyncWebServerRequest* request response->setLength(); request->send(response); -} \ No newline at end of file +} diff --git a/src/WebApi_inverter.cpp b/src/WebApi_inverter.cpp index 7538b2c03..f1bfc2aa5 100644 --- a/src/WebApi_inverter.cpp +++ b/src/WebApi_inverter.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_inverter.h" #include "Configuration.h" @@ -12,7 +12,7 @@ #include #include -void WebApiInverterClass::init(AsyncWebServer& server) +void WebApiInverterClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -25,10 +25,6 @@ void WebApiInverterClass::init(AsyncWebServer& server) _server->on("/api/inverter/order", HTTP_POST, std::bind(&WebApiInverterClass::onInverterOrder, this, _1)); } -void WebApiInverterClass::loop() -{ -} - void WebApiInverterClass::onInverterList(AsyncWebServerRequest* request) { if (!WebApi.checkCredentials(request)) { @@ -460,4 +456,4 @@ void WebApiInverterClass::onInverterOrder(AsyncWebServerRequest* request) response->setLength(); request->send(response); -} \ No newline at end of file +} diff --git a/src/WebApi_limit.cpp b/src/WebApi_limit.cpp index 8bf0c9426..be8e1202f 100644 --- a/src/WebApi_limit.cpp +++ b/src/WebApi_limit.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_limit.h" #include "WebApi.h" @@ -10,7 +10,7 @@ #include #include -void WebApiLimitClass::init(AsyncWebServer& server) +void WebApiLimitClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -20,10 +20,6 @@ void WebApiLimitClass::init(AsyncWebServer& server) _server->on("/api/limit/config", HTTP_POST, std::bind(&WebApiLimitClass::onLimitPost, this, _1)); } -void WebApiLimitClass::loop() -{ -} - void WebApiLimitClass::onLimitStatus(AsyncWebServerRequest* request) { if (!WebApi.checkCredentialsReadonly(request)) { @@ -156,4 +152,4 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request) response->setLength(); request->send(response); -} \ No newline at end of file +} diff --git a/src/WebApi_maintenance.cpp b/src/WebApi_maintenance.cpp index 0c62394cf..922b0ba09 100644 --- a/src/WebApi_maintenance.cpp +++ b/src/WebApi_maintenance.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_maintenance.h" @@ -9,7 +9,7 @@ #include "WebApi_errors.h" #include -void WebApiMaintenanceClass::init(AsyncWebServer& server) +void WebApiMaintenanceClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -18,10 +18,6 @@ void WebApiMaintenanceClass::init(AsyncWebServer& server) _server->on("/api/maintenance/reboot", HTTP_POST, std::bind(&WebApiMaintenanceClass::onRebootPost, this, _1)); } -void WebApiMaintenanceClass::loop() -{ -} - void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request) { if (!WebApi.checkCredentials(request)) { @@ -84,4 +80,4 @@ void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request) response->setLength(); request->send(response); } -} \ No newline at end of file +} diff --git a/src/WebApi_mqtt.cpp b/src/WebApi_mqtt.cpp index 8828547c9..bdb19ef01 100644 --- a/src/WebApi_mqtt.cpp +++ b/src/WebApi_mqtt.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_mqtt.h" #include "Configuration.h" @@ -15,7 +15,7 @@ #include "PowerMeter.h" #include -void WebApiMqttClass::init(AsyncWebServer& server) +void WebApiMqttClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -26,10 +26,6 @@ void WebApiMqttClass::init(AsyncWebServer& server) _server->on("/api/mqtt/config", HTTP_POST, std::bind(&WebApiMqttClass::onMqttAdminPost, this, _1)); } -void WebApiMqttClass::loop() -{ -} - void WebApiMqttClass::onMqttStatus(AsyncWebServerRequest* request) { if (!WebApi.checkCredentialsReadonly(request)) { diff --git a/src/WebApi_network.cpp b/src/WebApi_network.cpp index b95beb34f..ba9980539 100644 --- a/src/WebApi_network.cpp +++ b/src/WebApi_network.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_network.h" #include "Configuration.h" @@ -10,7 +10,7 @@ #include "helper.h" #include -void WebApiNetworkClass::init(AsyncWebServer& server) +void WebApiNetworkClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -21,10 +21,6 @@ void WebApiNetworkClass::init(AsyncWebServer& server) _server->on("/api/network/config", HTTP_POST, std::bind(&WebApiNetworkClass::onNetworkAdminPost, this, _1)); } -void WebApiNetworkClass::loop() -{ -} - void WebApiNetworkClass::onNetworkStatus(AsyncWebServerRequest* request) { if (!WebApi.checkCredentialsReadonly(request)) { @@ -246,4 +242,4 @@ void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request) NetworkSettings.enableAdminMode(); NetworkSettings.applyConfig(); -} \ No newline at end of file +} diff --git a/src/WebApi_ntp.cpp b/src/WebApi_ntp.cpp index 2eb4c087d..e0bcd6992 100644 --- a/src/WebApi_ntp.cpp +++ b/src/WebApi_ntp.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_ntp.h" #include "Configuration.h" @@ -11,7 +11,7 @@ #include "helper.h" #include -void WebApiNtpClass::init(AsyncWebServer& server) +void WebApiNtpClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -24,10 +24,6 @@ void WebApiNtpClass::init(AsyncWebServer& server) _server->on("/api/ntp/time", HTTP_POST, std::bind(&WebApiNtpClass::onNtpTimePost, this, _1)); } -void WebApiNtpClass::loop() -{ -} - void WebApiNtpClass::onNtpStatus(AsyncWebServerRequest* request) { if (!WebApi.checkCredentialsReadonly(request)) { diff --git a/src/WebApi_power.cpp b/src/WebApi_power.cpp index 697c1e87a..54fc664ef 100644 --- a/src/WebApi_power.cpp +++ b/src/WebApi_power.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_power.h" #include "WebApi.h" @@ -8,7 +8,7 @@ #include #include -void WebApiPowerClass::init(AsyncWebServer& server) +void WebApiPowerClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -18,10 +18,6 @@ void WebApiPowerClass::init(AsyncWebServer& server) _server->on("/api/power/config", HTTP_POST, std::bind(&WebApiPowerClass::onPowerPost, this, _1)); } -void WebApiPowerClass::loop() -{ -} - void WebApiPowerClass::onPowerStatus(AsyncWebServerRequest* request) { if (!WebApi.checkCredentialsReadonly(request)) { @@ -132,4 +128,4 @@ void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request) response->setLength(); request->send(response); -} \ No newline at end of file +} diff --git a/src/WebApi_powerlimiter.cpp b/src/WebApi_powerlimiter.cpp index c2c6456ba..25cb42e22 100644 --- a/src/WebApi_powerlimiter.cpp +++ b/src/WebApi_powerlimiter.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_powerlimiter.h" #include "VeDirectFrameHandler.h" @@ -16,7 +16,7 @@ #include "helper.h" #include "WebApi_errors.h" -void WebApiPowerLimiterClass::init(AsyncWebServer& server) +void WebApiPowerLimiterClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -27,10 +27,6 @@ void WebApiPowerLimiterClass::init(AsyncWebServer& server) _server->on("/api/powerlimiter/config", HTTP_POST, std::bind(&WebApiPowerLimiterClass::onAdminPost, this, _1)); } -void WebApiPowerLimiterClass::loop() -{ -} - void WebApiPowerLimiterClass::onStatus(AsyncWebServerRequest* request) { AsyncJsonResponse* response = new AsyncJsonResponse(); diff --git a/src/WebApi_powermeter.cpp b/src/WebApi_powermeter.cpp index d91f251b6..7340df464 100644 --- a/src/WebApi_powermeter.cpp +++ b/src/WebApi_powermeter.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_powermeter.h" #include "VeDirectFrameHandler.h" @@ -16,7 +16,7 @@ #include "WebApi.h" #include "helper.h" -void WebApiPowerMeterClass::init(AsyncWebServer& server) +void WebApiPowerMeterClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -28,10 +28,6 @@ void WebApiPowerMeterClass::init(AsyncWebServer& server) _server->on("/api/powermeter/testhttprequest", HTTP_POST, std::bind(&WebApiPowerMeterClass::onTestHttpRequest, this, _1)); } -void WebApiPowerMeterClass::loop() -{ -} - void WebApiPowerMeterClass::onStatus(AsyncWebServerRequest* request) { AsyncJsonResponse* response = new AsyncJsonResponse(false, 2048); diff --git a/src/WebApi_prometheus.cpp b/src/WebApi_prometheus.cpp index 5839dc802..275e568b9 100644 --- a/src/WebApi_prometheus.cpp +++ b/src/WebApi_prometheus.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_prometheus.h" #include "Configuration.h" @@ -11,7 +11,7 @@ #include #include "MessageOutput.h" -void WebApiPrometheusClass::init(AsyncWebServer& server) +void WebApiPrometheusClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -20,10 +20,6 @@ void WebApiPrometheusClass::init(AsyncWebServer& server) _server->on("/api/prometheus/metrics", HTTP_GET, std::bind(&WebApiPrometheusClass::onPrometheusMetricsGet, this, _1)); } -void WebApiPrometheusClass::loop() -{ -} - void WebApiPrometheusClass::onPrometheusMetricsGet(AsyncWebServerRequest* request) { if (!WebApi.checkCredentialsReadonly(request)) { diff --git a/src/WebApi_security.cpp b/src/WebApi_security.cpp index 8e6815d8e..205196812 100644 --- a/src/WebApi_security.cpp +++ b/src/WebApi_security.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_security.h" #include "Configuration.h" @@ -9,7 +9,7 @@ #include "helper.h" #include -void WebApiSecurityClass::init(AsyncWebServer& server) +void WebApiSecurityClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -20,10 +20,6 @@ void WebApiSecurityClass::init(AsyncWebServer& server) _server->on("/api/security/authenticate", HTTP_GET, std::bind(&WebApiSecurityClass::onAuthenticateGet, this, _1)); } -void WebApiSecurityClass::loop() -{ -} - void WebApiSecurityClass::onSecurityGet(AsyncWebServerRequest* request) { if (!WebApi.checkCredentials(request)) { @@ -122,4 +118,4 @@ void WebApiSecurityClass::onAuthenticateGet(AsyncWebServerRequest* request) response->setLength(); request->send(response); -} \ No newline at end of file +} diff --git a/src/WebApi_sysstatus.cpp b/src/WebApi_sysstatus.cpp index 8e67673b1..9c8223760 100644 --- a/src/WebApi_sysstatus.cpp +++ b/src/WebApi_sysstatus.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_sysstatus.h" #include "Configuration.h" @@ -20,7 +20,7 @@ #define AUTO_GIT_BRANCH "" #endif -void WebApiSysstatusClass::init(AsyncWebServer& server) +void WebApiSysstatusClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -29,10 +29,6 @@ void WebApiSysstatusClass::init(AsyncWebServer& server) _server->on("/api/system/status", HTTP_GET, std::bind(&WebApiSysstatusClass::onSystemStatus, this, _1)); } -void WebApiSysstatusClass::loop() -{ -} - void WebApiSysstatusClass::onSystemStatus(AsyncWebServerRequest* request) { if (!WebApi.checkCredentialsReadonly(request)) { @@ -87,4 +83,4 @@ void WebApiSysstatusClass::onSystemStatus(AsyncWebServerRequest* request) response->setLength(); request->send(response); -} \ No newline at end of file +} diff --git a/src/WebApi_vedirect.cpp b/src/WebApi_vedirect.cpp index b2276687e..088be259f 100644 --- a/src/WebApi_vedirect.cpp +++ b/src/WebApi_vedirect.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_vedirect.h" #include "VictronMppt.h" @@ -11,7 +11,7 @@ #include "WebApi_errors.h" #include "helper.h" -void WebApiVedirectClass::init(AsyncWebServer& server) +void WebApiVedirectClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; @@ -22,10 +22,6 @@ void WebApiVedirectClass::init(AsyncWebServer& server) _server->on("/api/vedirect/config", HTTP_POST, std::bind(&WebApiVedirectClass::onVedirectAdminPost, this, _1)); } -void WebApiVedirectClass::loop() -{ -} - void WebApiVedirectClass::onVedirectStatus(AsyncWebServerRequest* request) { if (!WebApi.checkCredentialsReadonly(request)) { diff --git a/src/WebApi_webapp.cpp b/src/WebApi_webapp.cpp index ea185b2d3..9203505b9 100644 --- a/src/WebApi_webapp.cpp +++ b/src/WebApi_webapp.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_webapp.h" @@ -22,7 +22,7 @@ extern const uint8_t file_site_webmanifest_end[] asm("_binary_webapp_dist_site_w #define ETAG_HTTP_HEADER_VAL "\"" AUTO_GIT_HASH "\"" // ETag value must be between quotes #endif -void WebApiWebappClass::init(AsyncWebServer& server) +void WebApiWebappClass::init(AsyncWebServer& server, Scheduler& scheduler) { _server = &server; @@ -94,7 +94,3 @@ void WebApiWebappClass::init(AsyncWebServer& server) request->send(response); }); } - -void WebApiWebappClass::loop() -{ -} diff --git a/src/WebApi_ws_Huawei.cpp b/src/WebApi_ws_Huawei.cpp index 174496551..1bf6870e9 100644 --- a/src/WebApi_ws_Huawei.cpp +++ b/src/WebApi_ws_Huawei.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_ws_Huawei.h" #include "AsyncJson.h" @@ -16,7 +16,7 @@ WebApiWsHuaweiLiveClass::WebApiWsHuaweiLiveClass() { } -void WebApiWsHuaweiLiveClass::init(AsyncWebServer& server) +void WebApiWsHuaweiLiveClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; using std::placeholders::_2; @@ -30,26 +30,33 @@ void WebApiWsHuaweiLiveClass::init(AsyncWebServer& server) _server->addHandler(&_ws); _ws.onEvent(std::bind(&WebApiWsHuaweiLiveClass::onWebsocketEvent, this, _1, _2, _3, _4, _5, _6)); + + scheduler.addTask(_wsCleanupTask); + _wsCleanupTask.setCallback(std::bind(&WebApiWsHuaweiLiveClass::wsCleanupTaskCb, this)); + _wsCleanupTask.setIterations(TASK_FOREVER); + _wsCleanupTask.setInterval(1 * TASK_SECOND); + _wsCleanupTask.enable(); + + scheduler.addTask(_sendDataTask); + _sendDataTask.setCallback(std::bind(&WebApiWsHuaweiLiveClass::sendDataTaskCb, this)); + _sendDataTask.setIterations(TASK_FOREVER); + _sendDataTask.setInterval(1 * TASK_SECOND); + _sendDataTask.enable(); } -void WebApiWsHuaweiLiveClass::loop() +void WebApiWsHuaweiLiveClass::wsCleanupTaskCb() { // see: https://github.com/me-no-dev/ESPAsyncWebServer#limiting-the-number-of-web-socket-clients - if (millis() - _lastWsCleanup > 1000) { - _ws.cleanupClients(); - _lastWsCleanup = millis(); - } + _ws.cleanupClients(); +} +void WebApiWsHuaweiLiveClass::sendDataTaskCb() +{ // do nothing if no WS client is connected if (_ws.count() == 0) { return; } - if (millis() - _lastUpdateCheck < 1000) { - return; - } - _lastUpdateCheck = millis(); - try { std::lock_guard lock(_mutex); DynamicJsonDocument root(1024); diff --git a/src/WebApi_ws_battery.cpp b/src/WebApi_ws_battery.cpp index f3ee725db..669df955f 100644 --- a/src/WebApi_ws_battery.cpp +++ b/src/WebApi_ws_battery.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_ws_battery.h" #include "AsyncJson.h" @@ -16,7 +16,7 @@ WebApiWsBatteryLiveClass::WebApiWsBatteryLiveClass() { } -void WebApiWsBatteryLiveClass::init(AsyncWebServer& server) +void WebApiWsBatteryLiveClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; using std::placeholders::_2; @@ -30,16 +30,28 @@ void WebApiWsBatteryLiveClass::init(AsyncWebServer& server) _server->addHandler(&_ws); _ws.onEvent(std::bind(&WebApiWsBatteryLiveClass::onWebsocketEvent, this, _1, _2, _3, _4, _5, _6)); + + scheduler.addTask(_wsCleanupTask); + _wsCleanupTask.setCallback(std::bind(&WebApiWsBatteryLiveClass::wsCleanupTaskCb, this)); + _wsCleanupTask.setIterations(TASK_FOREVER); + _wsCleanupTask.setInterval(1 * TASK_SECOND); + _wsCleanupTask.enable(); + + scheduler.addTask(_sendDataTask); + _sendDataTask.setCallback(std::bind(&WebApiWsBatteryLiveClass::sendDataTaskCb, this)); + _sendDataTask.setIterations(TASK_FOREVER); + _sendDataTask.setInterval(1 * TASK_SECOND); + _sendDataTask.enable(); } -void WebApiWsBatteryLiveClass::loop() +void WebApiWsBatteryLiveClass::wsCleanupTaskCb() { // see: https://github.com/me-no-dev/ESPAsyncWebServer#limiting-the-number-of-web-socket-clients - if (millis() - _lastWsCleanup > 1000) { - _ws.cleanupClients(); - _lastWsCleanup = millis(); - } + _ws.cleanupClients(); +} +void WebApiWsBatteryLiveClass::sendDataTaskCb() +{ // do nothing if no WS client is connected if (_ws.count() == 0) { return; diff --git a/src/WebApi_ws_console.cpp b/src/WebApi_ws_console.cpp index 541593815..aaca6d895 100644 --- a/src/WebApi_ws_console.cpp +++ b/src/WebApi_ws_console.cpp @@ -1,37 +1,37 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2022-2023 Thomas Basler and others - */ -#include "WebApi_ws_console.h" -#include "Configuration.h" -#include "MessageOutput.h" -#include "WebApi.h" -#include "defaults.h" - -WebApiWsConsoleClass::WebApiWsConsoleClass() - : _ws("/console") -{ -} - -void WebApiWsConsoleClass::init(AsyncWebServer& server) -{ - _server = &server; - _server->addHandler(&_ws); - MessageOutput.register_ws_output(&_ws); -} - -void WebApiWsConsoleClass::loop() -{ - // see: https://github.com/me-no-dev/ESPAsyncWebServer#limiting-the-number-of-web-socket-clients - if (millis() - _lastWsCleanup > 1000) { - _ws.cleanupClients(); - - if (Configuration.get().Security.AllowReadonly) { - _ws.setAuthentication("", ""); - } else { - _ws.setAuthentication(AUTH_USERNAME, Configuration.get().Security.Password); - } - - _lastWsCleanup = millis(); - } -} \ No newline at end of file +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2022-2024 Thomas Basler and others + */ +#include "WebApi_ws_console.h" +#include "Configuration.h" +#include "MessageOutput.h" +#include "WebApi.h" +#include "defaults.h" + +WebApiWsConsoleClass::WebApiWsConsoleClass() + : _ws("/console") + , _wsCleanupTask(1 * TASK_SECOND, TASK_FOREVER, std::bind(&WebApiWsConsoleClass::wsCleanupTaskCb, this)) +{ +} + +void WebApiWsConsoleClass::init(AsyncWebServer& server, Scheduler& scheduler) +{ + _server = &server; + _server->addHandler(&_ws); + MessageOutput.register_ws_output(&_ws); + + scheduler.addTask(_wsCleanupTask); + _wsCleanupTask.enable(); +} + +void WebApiWsConsoleClass::wsCleanupTaskCb() +{ + // see: https://github.com/me-no-dev/ESPAsyncWebServer#limiting-the-number-of-web-socket-clients + _ws.cleanupClients(); + + if (Configuration.get().Security.AllowReadonly) { + _ws.setAuthentication("", ""); + } else { + _ws.setAuthentication(AUTH_USERNAME, Configuration.get().Security.Password); + } +} diff --git a/src/WebApi_ws_live.cpp b/src/WebApi_ws_live.cpp index da92a27c8..867b7f8f9 100644 --- a/src/WebApi_ws_live.cpp +++ b/src/WebApi_ws_live.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022-2023 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_ws_live.h" #include "Configuration.h" @@ -17,10 +17,12 @@ WebApiWsLiveClass::WebApiWsLiveClass() : _ws("/livedata") + , _wsCleanupTask(1 * TASK_SECOND, TASK_FOREVER, std::bind(&WebApiWsLiveClass::wsCleanupTaskCb, this)) + , _sendDataTask(1 * TASK_SECOND, TASK_FOREVER, std::bind(&WebApiWsLiveClass::sendDataTaskCb, this)) { } -void WebApiWsLiveClass::init(AsyncWebServer& server) +void WebApiWsLiveClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; using std::placeholders::_2; @@ -34,33 +36,37 @@ void WebApiWsLiveClass::init(AsyncWebServer& server) _server->addHandler(&_ws); _ws.onEvent(std::bind(&WebApiWsLiveClass::onWebsocketEvent, this, _1, _2, _3, _4, _5, _6)); + + scheduler.addTask(_wsCleanupTask); + _wsCleanupTask.enable(); + + scheduler.addTask(_sendDataTask); + _sendDataTask.enable(); } -void WebApiWsLiveClass::loop() +void WebApiWsLiveClass::wsCleanupTaskCb() { // see: https://github.com/me-no-dev/ESPAsyncWebServer#limiting-the-number-of-web-socket-clients - if (millis() - _lastWsCleanup > 1000) { - _ws.cleanupClients(); - _lastWsCleanup = millis(); + _ws.cleanupClients(); + + if (Configuration.get().Security.AllowReadonly) { + _ws.setAuthentication("", ""); + } else { + _ws.setAuthentication(AUTH_USERNAME, Configuration.get().Security.Password); } +} +void WebApiWsLiveClass::sendDataTaskCb() +{ // do nothing if no WS client is connected if (_ws.count() == 0) { return; } - if (millis() - _lastInvUpdateCheck < 1000) { - return; - } - _lastInvUpdateCheck = millis(); - uint32_t maxTimeStamp = 0; for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { auto inv = Hoymiles.getInverterByPos(i); - - if (inv->Statistics()->getLastUpdate() > maxTimeStamp) { - maxTimeStamp = inv->Statistics()->getLastUpdate(); - } + maxTimeStamp = std::max(maxTimeStamp, inv->Statistics()->getLastUpdate()); } // Update on every inverter change or at least after 10 seconds @@ -76,13 +82,8 @@ void WebApiWsLiveClass::loop() String buffer; serializeJson(root, buffer); - if (Configuration.get().Security.AllowReadonly) { - _ws.setAuthentication("", ""); - } else { - _ws.setAuthentication(AUTH_USERNAME, Configuration.get().Security.Password); - } - _ws.textAll(buffer); + _newestInverterTimestamp = maxTimeStamp; } } catch (const std::bad_alloc& bad_alloc) { @@ -133,25 +134,25 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root) if (t == TYPE_DC) { chanTypeObj[String(static_cast(c))]["name"]["u"] = inv_cfg->channel[c].Name; } - addField(chanTypeObj, i, inv, t, c, FLD_PAC); - addField(chanTypeObj, i, inv, t, c, FLD_UAC); - addField(chanTypeObj, i, inv, t, c, FLD_IAC); + 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, i, inv, t, c, FLD_PDC, "Power DC"); + addField(chanTypeObj, inv, t, c, FLD_PDC, "Power DC"); } else { - addField(chanTypeObj, i, inv, t, c, FLD_PDC); + addField(chanTypeObj, inv, t, c, FLD_PDC); } - addField(chanTypeObj, i, inv, t, c, FLD_UDC); - addField(chanTypeObj, i, inv, t, c, FLD_IDC); - addField(chanTypeObj, i, inv, t, c, FLD_YD); - addField(chanTypeObj, i, inv, t, c, FLD_YT); - addField(chanTypeObj, i, inv, t, c, FLD_F); - addField(chanTypeObj, i, inv, t, c, FLD_T); - addField(chanTypeObj, i, inv, t, c, FLD_PF); - addField(chanTypeObj, i, inv, t, c, FLD_Q); - addField(chanTypeObj, i, inv, t, c, FLD_EFF); + 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, i, inv, t, c, FLD_IRR); + addField(chanTypeObj, inv, t, c, FLD_IRR); chanTypeObj[String(c)][inv->Statistics()->getChannelFieldName(t, c, FLD_IRR)]["max"] = inv->Statistics()->getStringMaxPower(c); } } @@ -162,10 +163,6 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root) } else { invObject["events"] = -1; } - - if (inv->Statistics()->getLastUpdate() > _newestInverterTimestamp) { - _newestInverterTimestamp = inv->Statistics()->getLastUpdate(); - } } JsonObject totalObj = root.createNestedObject("total"); @@ -206,7 +203,7 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root) } -void WebApiWsLiveClass::addField(JsonObject& root, uint8_t idx, std::shared_ptr inv, const ChannelType_t type, const ChannelNum_t channel, const FieldId_t fieldId, String topic) +void WebApiWsLiveClass::addField(JsonObject& root, std::shared_ptr inv, const ChannelType_t type, const ChannelNum_t channel, const FieldId_t fieldId, String topic) { if (inv->Statistics()->hasChannelFieldValue(type, channel, fieldId)) { String chanName; @@ -262,4 +259,4 @@ void WebApiWsLiveClass::onLivedataStatus(AsyncWebServerRequest* request) MessageOutput.printf("Unknown exception in /api/livedata/status. Reason: \"%s\".\r\n", exc.what()); WebApi.sendTooManyRequests(request); } -} \ No newline at end of file +} diff --git a/src/WebApi_ws_vedirect_live.cpp b/src/WebApi_ws_vedirect_live.cpp index b353f4a67..df59172e8 100644 --- a/src/WebApi_ws_vedirect_live.cpp +++ b/src/WebApi_ws_vedirect_live.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2022 Thomas Basler and others + * Copyright (C) 2022-2024 Thomas Basler and others */ #include "WebApi_ws_vedirect_live.h" #include "AsyncJson.h" @@ -17,7 +17,7 @@ WebApiWsVedirectLiveClass::WebApiWsVedirectLiveClass() { } -void WebApiWsVedirectLiveClass::init(AsyncWebServer& server) +void WebApiWsVedirectLiveClass::init(AsyncWebServer& server, Scheduler& scheduler) { using std::placeholders::_1; using std::placeholders::_2; @@ -31,16 +31,29 @@ void WebApiWsVedirectLiveClass::init(AsyncWebServer& server) _server->addHandler(&_ws); _ws.onEvent(std::bind(&WebApiWsVedirectLiveClass::onWebsocketEvent, this, _1, _2, _3, _4, _5, _6)); + + + scheduler.addTask(_wsCleanupTask); + _wsCleanupTask.setCallback(std::bind(&WebApiWsVedirectLiveClass::wsCleanupTaskCb, this)); + _wsCleanupTask.setIterations(TASK_FOREVER); + _wsCleanupTask.setInterval(1 * TASK_SECOND); + _wsCleanupTask.enable(); + + scheduler.addTask(_sendDataTask); + _sendDataTask.setCallback(std::bind(&WebApiWsVedirectLiveClass::sendDataTaskCb, this)); + _sendDataTask.setIterations(TASK_FOREVER); + _sendDataTask.setInterval(500 * TASK_MILLISECOND); + _sendDataTask.enable(); } -void WebApiWsVedirectLiveClass::loop() +void WebApiWsVedirectLiveClass::wsCleanupTaskCb() { // see: https://github.com/me-no-dev/ESPAsyncWebServer#limiting-the-number-of-web-socket-clients - if (millis() - _lastWsCleanup > 1000) { - _ws.cleanupClients(); - _lastWsCleanup = millis(); - } + _ws.cleanupClients(); +} +void WebApiWsVedirectLiveClass::sendDataTaskCb() +{ // do nothing if no WS client is connected if (_ws.count() == 0) { return; diff --git a/webapp/package.json b/webapp/package.json index f587c00fd..ab152cd4e 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -16,18 +16,18 @@ "bootstrap": "^5.3.2", "bootstrap-icons-vue": "^1.11.1", "mitt": "^3.0.1", - "sortablejs": "^1.15.1", + "sortablejs": "^1.15.2", "spark-md5": "^3.0.2", - "vue": "^3.4.13", + "vue": "^3.4.15", "vue-i18n": "^9.9.0", "vue-router": "^4.2.5" }, "devDependencies": { "@intlify/unplugin-vue-i18n": "^2.0.0", - "@rushstack/eslint-patch": "^1.6.1", + "@rushstack/eslint-patch": "^1.7.0", "@tsconfig/node18": "^18.2.2", "@types/bootstrap": "^5.2.10", - "@types/node": "^20.11.0", + "@types/node": "^20.11.5", "@types/pulltorefreshjs": "^0.1.7", "@types/sortablejs": "^1.15.7", "@types/spark-md5": "^3.0.4", @@ -38,10 +38,10 @@ "eslint-plugin-vue": "^9.20.1", "npm-run-all": "^4.1.5", "pulltorefreshjs": "^0.1.22", - "sass": "^1.69.7", - "terser": "^5.26.0", + "sass": "^1.70.0", + "terser": "^5.27.0", "typescript": "^5.3.3", - "vite": "^5.0.11", + "vite": "^5.0.12", "vite-plugin-compression": "^0.5.1", "vite-plugin-css-injected-by-js": "^3.3.1", "vue-tsc": "^1.8.27" diff --git a/webapp/src/App.vue b/webapp/src/App.vue index 8ace89a17..6fa6eeaa5 100644 --- a/webapp/src/App.vue +++ b/webapp/src/App.vue @@ -1,8 +1,6 @@ \ No newline at end of file + diff --git a/webapp/src/components/EventLog.vue b/webapp/src/components/EventLog.vue index db2b58382..93877536a 100644 --- a/webapp/src/components/EventLog.vue +++ b/webapp/src/components/EventLog.vue @@ -31,7 +31,7 @@ export default defineComponent({ computed: { timeInHours() { return (value: number) => { - return timestampToString(value); + return timestampToString(this.$i18n.locale, value)[0]; }; }, }, diff --git a/webapp/src/components/FirmwareInfo.vue b/webapp/src/components/FirmwareInfo.vue index abf65d850..907ba0fcd 100644 --- a/webapp/src/components/FirmwareInfo.vue +++ b/webapp/src/components/FirmwareInfo.vue @@ -32,12 +32,19 @@ {{ $t('firmwareinfo.FirmwareUpdate') }} - + {{ systemStatus.update_text }} - + + + +
+ +
+ {{ $t('firmwareinfo.ResetReason0') }} @@ -53,7 +60,7 @@ {{ $t('firmwareinfo.Uptime') }} - {{ timeInHours(systemStatus.uptime) }} + {{ $t('firmwareinfo.UptimeValue', timeInHours(systemStatus.uptime)) }} @@ -73,11 +80,21 @@ export default defineComponent({ }, props: { systemStatus: { type: Object as PropType, required: true }, + allowVersionInfo: Boolean, }, computed: { + modelAllowVersionInfo: { + get(): any { + return !!this.allowVersionInfo; + }, + set(value: any) { + this.$emit('update:allowVersionInfo', value); + }, + }, timeInHours() { return (value: number) => { - return timestampToString(value, true); + const [count, time] = timestampToString(this.$i18n.locale, value, true); + return {count, time}; }; }, versionInfoUrl(): string { diff --git a/webapp/src/components/GridProfile.vue b/webapp/src/components/GridProfile.vue index 6c93caece..3f2dbf10e 100644 --- a/webapp/src/components/GridProfile.vue +++ b/webapp/src/components/GridProfile.vue @@ -33,9 +33,9 @@ {{ value.n }} - + @@ -109,4 +109,4 @@ export default defineComponent({ }, }, }); - \ No newline at end of file + diff --git a/webapp/src/components/InverterChannelInfo.vue b/webapp/src/components/InverterChannelInfo.vue index c41829ad0..7f7a2316b 100644 --- a/webapp/src/components/InverterChannelInfo.vue +++ b/webapp/src/components/InverterChannelInfo.vue @@ -2,7 +2,7 @@
+ }" style="overflow: hidden">
{{ $t('inverterchannelinfo.General') }}
@@ -16,32 +16,24 @@ {{ $t('inverterchannelinfo.Phase', { num: channelNumber + 1 }) }}
-
-
- - - - - - - - - - - - - -
{{ $t('inverterchannelinfo.Property') }}{{ $t('inverterchannelinfo.Value') }}{{ $t('inverterchannelinfo.Unit') }}
-
+
+ + + + + + +
diff --git a/webapp/src/components/InverterTotalInfo.vue b/webapp/src/components/InverterTotalInfo.vue index a000db2b3..b7c671955 100644 --- a/webapp/src/components/InverterTotalInfo.vue +++ b/webapp/src/components/InverterTotalInfo.vue @@ -1,137 +1,110 @@ diff --git a/webapp/yarn.lock b/webapp/yarn.lock index 6f910e1b9..14f673bdd 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -408,10 +408,10 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.4.1.tgz#8311b77e6cce322865ba12ada8c3779369610d18" integrity sha512-eAhItDX9yQtZVM3yvXS/VR3qPqcnXvnLyx1pLXl4JzyNMBNO3KC986t/iAg2zcMzpAp9JSvxB5VZGnBiNoA98w== -"@rushstack/eslint-patch@^1.6.1": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.6.1.tgz#9ab8f811930d7af3e3d549183a50884f9eb83f36" - integrity sha512-UY+FGM/2jjMkzQLn8pxcHGMaVLh9aEitG3zY2CiY7XHdLiz3bZOwa6oDxNqEMv7zZkV+cj5DOdz0cQ1BP5Hjgw== +"@rushstack/eslint-patch@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.7.0.tgz#b5bc1e081428794f6a4d239707b359404be35ce2" + integrity sha512-Jh4t/593gxs0lJZ/z3NnasKlplXT2f+4y/LZYuaKZW5KAaiVFL/fThhs+17EbUd53jUVJ0QudYCBGbN/psvaqg== "@tsconfig/node18@^18.2.2": version "18.2.2" @@ -435,10 +435,10 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== -"@types/node@^20.11.0": - version "20.11.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.0.tgz#8e0b99e70c0c1ade1a86c4a282f7b7ef87c9552f" - integrity sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ== +"@types/node@^20.11.5": + version "20.11.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.5.tgz#be10c622ca7fcaa3cf226cf80166abc31389d86e" + integrity sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w== dependencies: undici-types "~5.26.4" @@ -599,13 +599,13 @@ estree-walker "^2.0.2" source-map-js "^1.0.2" -"@vue/compiler-core@3.4.13": - version "3.4.13" - resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.4.13.tgz#49f499034c25b0832845028ea3cd701fe5a17367" - integrity sha512-zGUdmB3j3Irn9z51GXLJ5s0EAHxmsm5/eXl0y6MBaajMeOAaiT4+zaDoxui4Ets98dwIRr8BBaqXXHtHSfm+KA== +"@vue/compiler-core@3.4.15": + version "3.4.15" + resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.4.15.tgz#be20d1bbe19626052500b48969302cb6f396d36e" + integrity sha512-XcJQVOaxTKCnth1vCxEChteGuwG6wqnUHxAm1DO3gCz0+uXKaJNx8/digSz4dLALCy8n2lKq24jSUs8segoqIw== dependencies: "@babel/parser" "^7.23.6" - "@vue/shared" "3.4.13" + "@vue/shared" "3.4.15" entities "^4.5.0" estree-walker "^2.0.2" source-map-js "^1.0.2" @@ -618,13 +618,13 @@ "@vue/compiler-core" "3.2.47" "@vue/shared" "3.2.47" -"@vue/compiler-dom@3.4.13": - version "3.4.13" - resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.4.13.tgz#66a80a6ee412a3d32b7175a146b75d9ec3d1c50c" - integrity sha512-XSNbpr5Rs3kCfVAmBqMu/HDwOS+RL6y28ZZjDlnDUuf146pRWt2sQkwhsOYc9uu2lxjjJy2NcyOkK7MBLVEc7w== +"@vue/compiler-dom@3.4.15": + version "3.4.15" + resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.4.15.tgz#753f5ed55f78d33dff04701fad4d76ff0cf81ee5" + integrity sha512-wox0aasVV74zoXyblarOM3AZQz/Z+OunYcIHe1OsGclCHt8RsRm04DObjefaI82u6XDzv+qGWZ24tIsRAIi5MQ== dependencies: - "@vue/compiler-core" "3.4.13" - "@vue/shared" "3.4.13" + "@vue/compiler-core" "3.4.15" + "@vue/shared" "3.4.15" "@vue/compiler-dom@^3.3.0": version "3.3.2" @@ -634,19 +634,19 @@ "@vue/compiler-core" "3.3.2" "@vue/shared" "3.3.2" -"@vue/compiler-sfc@3.4.13": - version "3.4.13" - resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.4.13.tgz#0f5f6db0e64f522c09995585453ae5f13ba54c60" - integrity sha512-SkpmQN8xIFBd5onT413DFSDdjxULJf6jmJg/t3w/DZ9I8ZzyNlLIBLO0qFLewVHyHCiAgpPZlWqSRZXYrawk3Q== +"@vue/compiler-sfc@3.4.15": + version "3.4.15" + resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.4.15.tgz#4e5811e681955fcec886cebbec483f6ae463a64b" + integrity sha512-LCn5M6QpkpFsh3GQvs2mJUOAlBQcCco8D60Bcqmf3O3w5a+KWS5GvYbrrJBkgvL1BDnTp+e8q0lXCLgHhKguBA== dependencies: "@babel/parser" "^7.23.6" - "@vue/compiler-core" "3.4.13" - "@vue/compiler-dom" "3.4.13" - "@vue/compiler-ssr" "3.4.13" - "@vue/shared" "3.4.13" + "@vue/compiler-core" "3.4.15" + "@vue/compiler-dom" "3.4.15" + "@vue/compiler-ssr" "3.4.15" + "@vue/shared" "3.4.15" estree-walker "^2.0.2" magic-string "^0.30.5" - postcss "^8.4.32" + postcss "^8.4.33" source-map-js "^1.0.2" "@vue/compiler-sfc@^3.2.47": @@ -673,13 +673,13 @@ "@vue/compiler-dom" "3.2.47" "@vue/shared" "3.2.47" -"@vue/compiler-ssr@3.4.13": - version "3.4.13" - resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.4.13.tgz#90fa9a4116f7974d7a4e43a8a67f3fc162e8720f" - integrity sha512-rwnw9SVBgD6eGKh8UucnwztieQo/R3RQrEGpE0b0cxb2xxvJeLs/fe7DoYlhEfaSyzM/qD5odkK87hl3G3oW+A== +"@vue/compiler-ssr@3.4.15": + version "3.4.15" + resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.4.15.tgz#a910a5b89ba4f0a776e40b63d69bdae2f50616cf" + integrity sha512-1jdeQyiGznr8gjFDadVmOJqZiLNSsMa5ZgqavkPZ8O2wjHv0tVuAEsw5hTdUoUW4232vpBbL/wJhzVW/JwY1Uw== dependencies: - "@vue/compiler-dom" "3.4.13" - "@vue/shared" "3.4.13" + "@vue/compiler-dom" "3.4.15" + "@vue/shared" "3.4.15" "@vue/devtools-api@^6.5.0": version "6.5.0" @@ -721,37 +721,37 @@ estree-walker "^2.0.2" magic-string "^0.25.7" -"@vue/reactivity@3.4.13": - version "3.4.13" - resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.4.13.tgz#7eeeb9d598512f66e06a6438fd53464014b5ae59" - integrity sha512-/ZdUOrGKkGVONzVJkfDqNcn2fLMvaa5VlYx2KwTbnRbX06YZ4GJE0PVTmWzIxtBYdpSTLLXgw3pDggO+96KXzg== +"@vue/reactivity@3.4.15": + version "3.4.15" + resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.4.15.tgz#ad9d9b83f5398d2e8660ad5cfc0f171e7679a9a1" + integrity sha512-55yJh2bsff20K5O84MxSvXKPHHt17I2EomHznvFiJCAZpJTNW8IuLj1xZWMLELRhBK3kkFV/1ErZGHJfah7i7w== dependencies: - "@vue/shared" "3.4.13" + "@vue/shared" "3.4.15" -"@vue/runtime-core@3.4.13": - version "3.4.13" - resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.4.13.tgz#776cad7c1d56ec5e92a48e040c8483b89f779542" - integrity sha512-Ov4d4At7z3goxqzSqQxdfVYEcN5HY4dM1uDYL6Hu/Es9Za9BEN602zyjWhhi2+BEki5F9NizRSvn02k/tqNWlg== +"@vue/runtime-core@3.4.15": + version "3.4.15" + resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.4.15.tgz#f81e2fd2108ea41a6d5c61c2462b11dfb754fdf0" + integrity sha512-6E3by5m6v1AkW0McCeAyhHTw+3y17YCOKG0U0HDKDscV4Hs0kgNT5G+GCHak16jKgcCDHpI9xe5NKb8sdLCLdw== dependencies: - "@vue/reactivity" "3.4.13" - "@vue/shared" "3.4.13" + "@vue/reactivity" "3.4.15" + "@vue/shared" "3.4.15" -"@vue/runtime-dom@3.4.13": - version "3.4.13" - resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.4.13.tgz#74aff1494bee49c037b9c5355d8998c793ac0977" - integrity sha512-ynde9p16eEV3u1VCxUre2e0nKzD0l3NzH0r599+bXeLT1Yhac8Atcot3iL9XNqwolxYCI89KBII+2MSVzfrz6w== +"@vue/runtime-dom@3.4.15": + version "3.4.15" + resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.4.15.tgz#108ef86aa7334ead5d6b9c56a7d93679e1e45406" + integrity sha512-EVW8D6vfFVq3V/yDKNPBFkZKGMFSvZrUQmx196o/v2tHKdwWdiZjYUBS+0Ez3+ohRyF8Njwy/6FH5gYJ75liUw== dependencies: - "@vue/runtime-core" "3.4.13" - "@vue/shared" "3.4.13" + "@vue/runtime-core" "3.4.15" + "@vue/shared" "3.4.15" csstype "^3.1.3" -"@vue/server-renderer@3.4.13": - version "3.4.13" - resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.4.13.tgz#b8c9cfb2147c0a01feba7f136d3a432848dafcab" - integrity sha512-hkw+UQyDZZtSn1q30nObMfc8beVEQv2pG08nghigxGw+iOWodR+tWSuJak0mzWAHlP/xt/qLc//dG6igfgvGEA== +"@vue/server-renderer@3.4.15": + version "3.4.15" + resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.4.15.tgz#34438f998e6f6370fac78883a75efe136631957f" + integrity sha512-3HYzaidu9cHjrT+qGUuDhFYvF/j643bHC6uUN9BgM11DVy+pM6ATsG6uPBLnkwOgs7BpJABReLmpL3ZPAsUaqw== dependencies: - "@vue/compiler-ssr" "3.4.13" - "@vue/shared" "3.4.13" + "@vue/compiler-ssr" "3.4.15" + "@vue/shared" "3.4.15" "@vue/shared@3.2.47": version "3.2.47" @@ -763,10 +763,10 @@ resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.3.2.tgz#774cd9b4635ce801b70a3fc3713779a5ef5d77c3" integrity sha512-0rFu3h8JbclbnvvKrs7Fe5FNGV9/5X2rPD7KmOzhLSUAiQH5//Hq437Gv0fR5Mev3u/nbtvmLl8XgwCU20/ZfQ== -"@vue/shared@3.4.13": - version "3.4.13" - resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.13.tgz#a1eefce5ddffe207d53eafbc07f4ebbea0a4768a" - integrity sha512-56crFKLPpzk85WXX1L1c0QzPOuoapWlPVys8eMG8kkRmqdMjWUqK8KpFdE2d7BQA4CEbXwyyHPq6MpFr8H9rcg== +"@vue/shared@3.4.15": + version "3.4.15" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.15.tgz#e7d2ea050c667480cb5e1a6df2ac13bcd03a8f30" + integrity sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g== "@vue/tsconfig@^0.5.1": version "0.5.1" @@ -2137,6 +2137,15 @@ postcss@^8.4.32: picocolors "^1.0.0" source-map-js "^1.0.2" +postcss@^8.4.33: + version "8.4.33" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742" + integrity sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg== + dependencies: + nanoid "^3.3.7" + picocolors "^1.0.0" + source-map-js "^1.0.2" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -2248,10 +2257,10 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" -sass@^1.69.7: - version "1.69.7" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.69.7.tgz#6e7e1c8f51e8162faec3e9619babc7da780af3b7" - integrity sha512-rzj2soDeZ8wtE2egyLXgOOHQvaC2iosZrkF6v3EUG+tBwEvhqUCzm0VP3k9gHF9LXbSrRhT5SksoI56Iw8NPnQ== +sass@^1.70.0: + version "1.70.0" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.70.0.tgz#761197419d97b5358cb25f9dd38c176a8a270a75" + integrity sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ== dependencies: chokidar ">=3.0.0 <4.0.0" immutable "^4.0.0" @@ -2319,10 +2328,10 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -sortablejs@^1.15.1: - version "1.15.1" - resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.15.1.tgz#9a35f52cdff449fb42ea8ecf222f3468d76e0a47" - integrity sha512-P5Cjvb0UG1ZVNiDPj/n4V+DinttXG6K8n7vM/HQf0C25K3YKQTQY6fsr/sEGsJGpQ9exmPxluHxKBc0mLKU1lQ== +sortablejs@^1.15.2: + version "1.15.2" + resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.15.2.tgz#4e9f7bda4718bd1838add9f1866ec77169149809" + integrity sha512-FJF5jgdfvoKn1MAKSdGs33bIqLi3LmsgVTliuX6iITj834F+JRQZN90Z93yql8h0K2t0RwDPBmxwlbZfDcxNZA== "source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.0.2: version "1.0.2" @@ -2441,10 +2450,10 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -terser@^5.26.0: - version "5.26.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.26.0.tgz#ee9f05d929f4189a9c28a0feb889d96d50126fe1" - integrity sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ== +terser@^5.27.0: + version "5.27.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.27.0.tgz#70108689d9ab25fef61c4e93e808e9fd092bf20c" + integrity sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2" @@ -2561,10 +2570,10 @@ vite-plugin-css-injected-by-js@^3.3.1: resolved "https://registry.yarnpkg.com/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-3.3.1.tgz#26b41f108c5554ee728359bdec01c68c93a48547" integrity sha512-PjM/X45DR3/V1K1fTRs8HtZHEQ55kIfdrn+dzaqNBFrOYO073SeSNCxp4j7gSYhV9NffVHaEnOL4myoko0ePAg== -vite@^5.0.11: - version "5.0.11" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.0.11.tgz#31562e41e004cb68e1d51f5d2c641ab313b289e4" - integrity sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA== +vite@^5.0.12: + version "5.0.12" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.0.12.tgz#8a2ffd4da36c132aec4adafe05d7adde38333c47" + integrity sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w== dependencies: esbuild "^0.19.3" postcss "^8.4.32" @@ -2631,16 +2640,16 @@ vue-tsc@^1.8.27: "@vue/language-core" "1.8.27" semver "^7.5.4" -vue@^3.4.13: - version "3.4.13" - resolved "https://registry.yarnpkg.com/vue/-/vue-3.4.13.tgz#aa522baf2344d1c4c54c769f66c0151f1872f1ff" - integrity sha512-FE3UZ0p+oUZTwz+SzlH/hDFg+XsVRFvwmx0LXjdD1pRK/cO4fu5v6ltAZji4za4IBih3dV78elUK3di8v3pWIg== +vue@^3.4.15: + version "3.4.15" + resolved "https://registry.yarnpkg.com/vue/-/vue-3.4.15.tgz#91f979844ffca9239dff622ba4c79c5d5524b88c" + integrity sha512-jC0GH4KkWLWJOEQjOpkqU1bQsBwf4R1rsFtw5GQJbjHVKWDzO6P0nWWBTmjp1xSemAioDFj1jdaK1qa3DnMQoQ== dependencies: - "@vue/compiler-dom" "3.4.13" - "@vue/compiler-sfc" "3.4.13" - "@vue/runtime-dom" "3.4.13" - "@vue/server-renderer" "3.4.13" - "@vue/shared" "3.4.13" + "@vue/compiler-dom" "3.4.15" + "@vue/compiler-sfc" "3.4.15" + "@vue/runtime-dom" "3.4.15" + "@vue/server-renderer" "3.4.15" + "@vue/shared" "3.4.15" webpack-sources@^3.2.3: version "3.2.3" diff --git a/webapp_dist/js/app.js.gz b/webapp_dist/js/app.js.gz index 27c4f9f4a..cdb5bb647 100644 Binary files a/webapp_dist/js/app.js.gz and b/webapp_dist/js/app.js.gz differ