Merge remote-tracking branch 'tbnobody/OpenDTU/master' into merge-v24.4.12
This commit is contained in:
commit
fdc5054480
@ -39,8 +39,6 @@
|
|||||||
#define POWERMETER_MAX_HTTP_JSON_PATH_STRLEN 256
|
#define POWERMETER_MAX_HTTP_JSON_PATH_STRLEN 256
|
||||||
#define POWERMETER_HTTP_TIMEOUT 1000
|
#define POWERMETER_HTTP_TIMEOUT 1000
|
||||||
|
|
||||||
#define JSON_BUFFER_SIZE 15360
|
|
||||||
|
|
||||||
struct CHANNEL_CONFIG_T {
|
struct CHANNEL_CONFIG_T {
|
||||||
uint16_t MaxChannelPower;
|
uint16_t MaxChannelPower;
|
||||||
char Name[CHAN_MAX_NAME_STRLEN];
|
char Name[CHAN_MAX_NAME_STRLEN];
|
||||||
|
|||||||
@ -66,10 +66,10 @@ private:
|
|||||||
void publishInverterNumber(std::shared_ptr<InverterAbstract> inv, const char* caption, const char* icon, const char* category, const char* commandTopic, const char* stateTopic, const char* unitOfMeasure, const int16_t min = 1, const int16_t max = 100);
|
void publishInverterNumber(std::shared_ptr<InverterAbstract> inv, const char* caption, const char* icon, const char* category, const char* commandTopic, const char* stateTopic, const char* unitOfMeasure, const int16_t min = 1, const int16_t max = 100);
|
||||||
void publishInverterBinarySensor(std::shared_ptr<InverterAbstract> inv, const char* caption, const char* subTopic, const char* payload_on, const char* payload_off);
|
void publishInverterBinarySensor(std::shared_ptr<InverterAbstract> inv, const char* caption, const char* subTopic, const char* payload_on, const char* payload_off);
|
||||||
|
|
||||||
static void createInverterInfo(DynamicJsonDocument& doc, std::shared_ptr<InverterAbstract> inv);
|
static void createInverterInfo(JsonDocument& doc, std::shared_ptr<InverterAbstract> inv);
|
||||||
static void createDtuInfo(DynamicJsonDocument& doc);
|
static void createDtuInfo(JsonDocument& doc);
|
||||||
|
|
||||||
static void createDeviceInfo(DynamicJsonDocument& doc, const String& name, const String& identifiers, const String& configuration_url, const String& manufacturer, const String& model, const String& sw_version, const String& via_device = "");
|
static void createDeviceInfo(JsonDocument& doc, const String& name, const String& identifiers, const String& configuration_url, const String& manufacturer, const String& model, const String& sw_version, const String& via_device = "");
|
||||||
|
|
||||||
static String getDtuUniqueId();
|
static String getDtuUniqueId();
|
||||||
static String getDtuUrl();
|
static String getDtuUrl();
|
||||||
|
|||||||
@ -10,7 +10,6 @@ public:
|
|||||||
static uint64_t generateDtuSerial();
|
static uint64_t generateDtuSerial();
|
||||||
static int getTimezoneOffset();
|
static int getTimezoneOffset();
|
||||||
static void restartDtu();
|
static void restartDtu();
|
||||||
static bool checkJsonAlloc(const DynamicJsonDocument& doc, const char* function, const uint16_t line);
|
static bool checkJsonAlloc(const JsonDocument& doc, const char* function, const uint16_t line);
|
||||||
static bool checkJsonOverflow(const DynamicJsonDocument& doc, const char* function, const uint16_t line);
|
|
||||||
static void removeAllFiles();
|
static void removeAllFiles();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
#include "WebApi_webapp.h"
|
#include "WebApi_webapp.h"
|
||||||
#include "WebApi_ws_console.h"
|
#include "WebApi_ws_console.h"
|
||||||
#include "WebApi_ws_live.h"
|
#include "WebApi_ws_live.h"
|
||||||
|
#include <AsyncJson.h>
|
||||||
#include "WebApi_ws_vedirect_live.h"
|
#include "WebApi_ws_vedirect_live.h"
|
||||||
#include "WebApi_vedirect.h"
|
#include "WebApi_vedirect.h"
|
||||||
#include "WebApi_ws_Huawei.h"
|
#include "WebApi_ws_Huawei.h"
|
||||||
@ -45,6 +46,10 @@ public:
|
|||||||
|
|
||||||
static void writeConfig(JsonVariant& retMsg, const WebApiError code = WebApiError::GenericSuccess, const String& message = "Settings saved!");
|
static void writeConfig(JsonVariant& retMsg, const WebApiError code = WebApiError::GenericSuccess, const String& message = "Settings saved!");
|
||||||
|
|
||||||
|
static bool parseRequestData(AsyncWebServerRequest* request, AsyncJsonResponse* response, JsonDocument& json_document);
|
||||||
|
static uint64_t parseSerialFromRequest(AsyncWebServerRequest* request, String param_name = "inv");
|
||||||
|
static bool sendJsonResponse(AsyncWebServerRequest* request, AsyncJsonResponse* response, const char* function, const uint16_t line);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AsyncWebServer _server;
|
AsyncWebServer _server;
|
||||||
|
|
||||||
|
|||||||
@ -5,10 +5,11 @@ enum WebApiError {
|
|||||||
GenericBase = 1000,
|
GenericBase = 1000,
|
||||||
GenericSuccess,
|
GenericSuccess,
|
||||||
GenericNoValueFound,
|
GenericNoValueFound,
|
||||||
GenericDataTooLarge,
|
GenericDataTooLarge, // not used anymore
|
||||||
GenericParseError,
|
GenericParseError,
|
||||||
GenericValueMissing,
|
GenericValueMissing,
|
||||||
GenericWriteFailed,
|
GenericWriteFailed,
|
||||||
|
GenericInternalServerError,
|
||||||
|
|
||||||
DtuBase = 2000,
|
DtuBase = 2000,
|
||||||
DtuSerialZero,
|
DtuSerialZero,
|
||||||
|
|||||||
@ -4,8 +4,6 @@
|
|||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <TaskSchedulerDeclarations.h>
|
#include <TaskSchedulerDeclarations.h>
|
||||||
|
|
||||||
#define MQTT_JSON_DOC_SIZE 10240
|
|
||||||
|
|
||||||
class WebApiMqttClass {
|
class WebApiMqttClass {
|
||||||
public:
|
public:
|
||||||
void init(AsyncWebServer& server, Scheduler& scheduler);
|
void init(AsyncWebServer& server, Scheduler& scheduler);
|
||||||
|
|||||||
@ -12,7 +12,7 @@ public:
|
|||||||
void init(AsyncWebServer& server, Scheduler& scheduler);
|
void init(AsyncWebServer& server, Scheduler& scheduler);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void generateJsonResponse(JsonVariant& root);
|
void generateCommonJsonResponse(JsonVariant& root);
|
||||||
void onLivedataStatus(AsyncWebServerRequest* request);
|
void onLivedataStatus(AsyncWebServerRequest* request);
|
||||||
void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
|
void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ public:
|
|||||||
void init(AsyncWebServer& server, Scheduler& scheduler);
|
void init(AsyncWebServer& server, Scheduler& scheduler);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void generateJsonResponse(JsonVariant& root);
|
void generateCommonJsonResponse(JsonVariant& root);
|
||||||
void onLivedataStatus(AsyncWebServerRequest* request);
|
void onLivedataStatus(AsyncWebServerRequest* request);
|
||||||
void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
|
void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ public:
|
|||||||
void init(AsyncWebServer& server, Scheduler& scheduler);
|
void init(AsyncWebServer& server, Scheduler& scheduler);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void generateJsonResponse(JsonVariant& root, bool fullUpdate);
|
void generateCommonJsonResponse(JsonVariant& root, bool fullUpdate);
|
||||||
static void populateJson(const JsonObject &root, const VeDirectMpptController::data_t &mpptData);
|
static void populateJson(const JsonObject &root, const VeDirectMpptController::data_t &mpptData);
|
||||||
void onLivedataStatus(AsyncWebServerRequest* request);
|
void onLivedataStatus(AsyncWebServerRequest* request);
|
||||||
void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
|
void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "TimeoutHelper.h"
|
|
||||||
#include "commands/CommandAbstract.h"
|
#include "commands/CommandAbstract.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include <memory>
|
|
||||||
#include <ThreadSafeQueue.h>
|
#include <ThreadSafeQueue.h>
|
||||||
|
#include <TimeoutHelper.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class HoymilesRadio {
|
class HoymilesRadio {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -70,7 +70,7 @@ bool HMT_4CH::isValidSerial(const uint64_t serial)
|
|||||||
|
|
||||||
String HMT_4CH::typeName() const
|
String HMT_4CH::typeName() const
|
||||||
{
|
{
|
||||||
return F("HMT-1600/1800/2000-4T");
|
return "HMT-1600/1800/2000-4T";
|
||||||
}
|
}
|
||||||
|
|
||||||
const byteAssign_t* HMT_4CH::getByteAssignment() const
|
const byteAssign_t* HMT_4CH::getByteAssignment() const
|
||||||
|
|||||||
@ -84,7 +84,7 @@ bool HMT_6CH::isValidSerial(const uint64_t serial)
|
|||||||
|
|
||||||
String HMT_6CH::typeName() const
|
String HMT_6CH::typeName() const
|
||||||
{
|
{
|
||||||
return F("HMT-1800/2250-6T");
|
return "HMT-1800/2250-6T";
|
||||||
}
|
}
|
||||||
|
|
||||||
const byteAssign_t* HMT_6CH::getByteAssignment() const
|
const byteAssign_t* HMT_6CH::getByteAssignment() const
|
||||||
|
|||||||
0
lib/ThreadSafeQueue/README.md
Normal file
0
lib/ThreadSafeQueue/README.md
Normal file
13
lib/ThreadSafeQueue/library.json
Normal file
13
lib/ThreadSafeQueue/library.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "ThreadSafeQueue",
|
||||||
|
"keywords": "queue, threadsafe",
|
||||||
|
"description": "An Arduino for ESP32 thread safe queue implementation",
|
||||||
|
"authors": {
|
||||||
|
"name": "Thomas Basler"
|
||||||
|
},
|
||||||
|
"version": "0.0.1",
|
||||||
|
"frameworks": "arduino",
|
||||||
|
"platforms": [
|
||||||
|
"espressif32"
|
||||||
|
]
|
||||||
|
}
|
||||||
0
lib/TimeoutHelper/README.md
Normal file
0
lib/TimeoutHelper/README.md
Normal file
13
lib/TimeoutHelper/library.json
Normal file
13
lib/TimeoutHelper/library.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "TimeoutHelper",
|
||||||
|
"keywords": "timeout",
|
||||||
|
"description": "An Arduino for ESP32 timeout helper",
|
||||||
|
"authors": {
|
||||||
|
"name": "Thomas Basler"
|
||||||
|
},
|
||||||
|
"version": "0.0.1",
|
||||||
|
"frameworks": "arduino",
|
||||||
|
"platforms": [
|
||||||
|
"espressif32"
|
||||||
|
]
|
||||||
|
}
|
||||||
26
patches/async_tcp/event_queue_size.patch
Normal file
26
patches/async_tcp/event_queue_size.patch
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
diff --color -ruN a/.pio/libdeps/$$$env$$$/AsyncTCP-esphome/src/AsyncTCP.cpp b/.pio/libdeps/$$$env$$$/AsyncTCP-esphome/src/AsyncTCP.cpp
|
||||||
|
--- a/.pio/libdeps/$$$env$$$/AsyncTCP-esphome/src/AsyncTCP.cpp
|
||||||
|
+++ b/.pio/libdeps/$$$env$$$/AsyncTCP-esphome/src/AsyncTCP.cpp
|
||||||
|
@@ -97,7 +97,7 @@
|
||||||
|
|
||||||
|
static inline bool _init_async_event_queue(){
|
||||||
|
if(!_async_queue){
|
||||||
|
- _async_queue = xQueueCreate(32, sizeof(lwip_event_packet_t *));
|
||||||
|
+ _async_queue = xQueueCreate(CONFIG_ASYNC_TCP_EVENT_QUEUE_SIZE, sizeof(lwip_event_packet_t *));
|
||||||
|
if(!_async_queue){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
diff --color -ruN a/.pio/libdeps/$$$env$$$/AsyncTCP-esphome/src/AsyncTCP.h b/.pio/libdeps/$$$env$$$/AsyncTCP-esphome/src/AsyncTCP.h
|
||||||
|
--- a/.pio/libdeps/$$$env$$$/AsyncTCP-esphome/src/AsyncTCP.h
|
||||||
|
+++ b/.pio/libdeps/$$$env$$$/AsyncTCP-esphome/src/AsyncTCP.h
|
||||||
|
@@ -53,6 +53,10 @@
|
||||||
|
#define CONFIG_ASYNC_TCP_STACK_SIZE 8192 * 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#ifndef CONFIG_ASYNC_TCP_EVENT_QUEUE_SIZE
|
||||||
|
+#define CONFIG_ASYNC_TCP_EVENT_QUEUE_SIZE 32
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
class AsyncClient;
|
||||||
|
|
||||||
|
#define ASYNC_MAX_ACK_TIME 5000
|
||||||
@ -1,13 +0,0 @@
|
|||||||
diff --git a/.pio/libdeps/$$$env$$$/ESP Async WebServer/src/AsyncWebSocket.cpp b/.pio/libdeps/$$$env$$$/ESP Async WebServer/src/AsyncWebSocket.cpp
|
|
||||||
index 12be5f8..8505f73 100644
|
|
||||||
--- a/.pio/libdeps/$$$env$$$/ESP Async WebServer/src/AsyncWebSocket.cpp
|
|
||||||
+++ b/.pio/libdeps/$$$env$$$/ESP Async WebServer/src/AsyncWebSocket.cpp
|
|
||||||
@@ -737,7 +737,7 @@ void AsyncWebSocketClient::binary(const __FlashStringHelper *data, size_t len)
|
|
||||||
IPAddress AsyncWebSocketClient::remoteIP() const
|
|
||||||
{
|
|
||||||
if (!_client)
|
|
||||||
- return IPAddress(0U);
|
|
||||||
+ return IPAddress((uint32_t)0);
|
|
||||||
|
|
||||||
return _client->remoteIP();
|
|
||||||
}
|
|
||||||
@ -19,12 +19,13 @@ extra_configs =
|
|||||||
custom_ci_action = generic,generic_esp32,generic_esp32s3,generic_esp32s3_usb
|
custom_ci_action = generic,generic_esp32,generic_esp32s3,generic_esp32s3_usb
|
||||||
|
|
||||||
framework = arduino
|
framework = arduino
|
||||||
platform = espressif32@6.5.0
|
platform = espressif32@6.6.0
|
||||||
|
|
||||||
build_flags =
|
build_flags =
|
||||||
-DPIOENV=\"$PIOENV\"
|
-DPIOENV=\"$PIOENV\"
|
||||||
-D_TASK_STD_FUNCTION=1
|
-D_TASK_STD_FUNCTION=1
|
||||||
-D_TASK_THREAD_SAFE=1
|
-D_TASK_THREAD_SAFE=1
|
||||||
|
-DCONFIG_ASYNC_TCP_EVENT_QUEUE_SIZE=128
|
||||||
-Wall -Wextra -Wunused -Wmisleading-indentation -Wduplicated-cond -Wlogical-op -Wnull-dereference
|
-Wall -Wextra -Wunused -Wmisleading-indentation -Wduplicated-cond -Wlogical-op -Wnull-dereference
|
||||||
; Have to remove -Werror because of
|
; Have to remove -Werror because of
|
||||||
; https://github.com/espressif/arduino-esp32/issues/9044 and
|
; https://github.com/espressif/arduino-esp32/issues/9044 and
|
||||||
@ -36,8 +37,8 @@ build_unflags =
|
|||||||
-std=gnu++11
|
-std=gnu++11
|
||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
mathieucarbou/ESP Async WebServer @ 2.8.1
|
mathieucarbou/ESP Async WebServer @ 2.9.0
|
||||||
bblanchon/ArduinoJson @ ^6.21.5
|
bblanchon/ArduinoJson @ ^7.0.4
|
||||||
https://github.com/bertmelis/espMqttClient.git#v1.6.0
|
https://github.com/bertmelis/espMqttClient.git#v1.6.0
|
||||||
nrf24/RF24 @ ^1.4.8
|
nrf24/RF24 @ ^1.4.8
|
||||||
olikraus/U8g2 @ ^2.35.15
|
olikraus/U8g2 @ ^2.35.15
|
||||||
@ -64,7 +65,7 @@ board_build.embed_files =
|
|||||||
webapp_dist/js/app.js.gz
|
webapp_dist/js/app.js.gz
|
||||||
webapp_dist/site.webmanifest
|
webapp_dist/site.webmanifest
|
||||||
|
|
||||||
custom_patches =
|
custom_patches = async_tcp
|
||||||
|
|
||||||
monitor_filters = esp32_exception_decoder, time, log2file, colorize
|
monitor_filters = esp32_exception_decoder, time, log2file, colorize
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
@ -92,13 +93,13 @@ build_flags = ${env.build_flags}
|
|||||||
|
|
||||||
[env:generic_esp32c3]
|
[env:generic_esp32c3]
|
||||||
board = esp32-c3-devkitc-02
|
board = esp32-c3-devkitc-02
|
||||||
custom_patches = ${env.custom_patches},esp32c3
|
custom_patches = ${env.custom_patches}
|
||||||
build_flags = ${env.build_flags}
|
build_flags = ${env.build_flags}
|
||||||
|
|
||||||
|
|
||||||
[env:generic_esp32c3_usb]
|
[env:generic_esp32c3_usb]
|
||||||
board = esp32-c3-devkitc-02
|
board = esp32-c3-devkitc-02
|
||||||
custom_patches = ${env.custom_patches},esp32c3
|
custom_patches = ${env.custom_patches}
|
||||||
build_flags = ${env.build_flags}
|
build_flags = ${env.build_flags}
|
||||||
-DARDUINO_USB_MODE=1
|
-DARDUINO_USB_MODE=1
|
||||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||||
|
|||||||
@ -25,17 +25,13 @@ bool ConfigurationClass::write()
|
|||||||
}
|
}
|
||||||
config.Cfg.SaveCount++;
|
config.Cfg.SaveCount++;
|
||||||
|
|
||||||
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
JsonDocument doc;
|
||||||
|
|
||||||
if (!Utils::checkJsonAlloc(doc, __FUNCTION__, __LINE__)) {
|
JsonObject cfg = doc["cfg"].to<JsonObject>();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonObject cfg = doc.createNestedObject("cfg");
|
|
||||||
cfg["version"] = config.Cfg.Version;
|
cfg["version"] = config.Cfg.Version;
|
||||||
cfg["save_count"] = config.Cfg.SaveCount;
|
cfg["save_count"] = config.Cfg.SaveCount;
|
||||||
|
|
||||||
JsonObject wifi = doc.createNestedObject("wifi");
|
JsonObject wifi = doc["wifi"].to<JsonObject>();
|
||||||
wifi["ssid"] = config.WiFi.Ssid;
|
wifi["ssid"] = config.WiFi.Ssid;
|
||||||
wifi["password"] = config.WiFi.Password;
|
wifi["password"] = config.WiFi.Password;
|
||||||
wifi["ip"] = IPAddress(config.WiFi.Ip).toString();
|
wifi["ip"] = IPAddress(config.WiFi.Ip).toString();
|
||||||
@ -47,10 +43,10 @@ bool ConfigurationClass::write()
|
|||||||
wifi["hostname"] = config.WiFi.Hostname;
|
wifi["hostname"] = config.WiFi.Hostname;
|
||||||
wifi["aptimeout"] = config.WiFi.ApTimeout;
|
wifi["aptimeout"] = config.WiFi.ApTimeout;
|
||||||
|
|
||||||
JsonObject mdns = doc.createNestedObject("mdns");
|
JsonObject mdns = doc["mdns"].to<JsonObject>();
|
||||||
mdns["enabled"] = config.Mdns.Enabled;
|
mdns["enabled"] = config.Mdns.Enabled;
|
||||||
|
|
||||||
JsonObject ntp = doc.createNestedObject("ntp");
|
JsonObject ntp = doc["ntp"].to<JsonObject>();
|
||||||
ntp["server"] = config.Ntp.Server;
|
ntp["server"] = config.Ntp.Server;
|
||||||
ntp["timezone"] = config.Ntp.Timezone;
|
ntp["timezone"] = config.Ntp.Timezone;
|
||||||
ntp["timezone_descr"] = config.Ntp.TimezoneDescr;
|
ntp["timezone_descr"] = config.Ntp.TimezoneDescr;
|
||||||
@ -58,7 +54,7 @@ bool ConfigurationClass::write()
|
|||||||
ntp["longitude"] = config.Ntp.Longitude;
|
ntp["longitude"] = config.Ntp.Longitude;
|
||||||
ntp["sunsettype"] = config.Ntp.SunsetType;
|
ntp["sunsettype"] = config.Ntp.SunsetType;
|
||||||
|
|
||||||
JsonObject mqtt = doc.createNestedObject("mqtt");
|
JsonObject mqtt = doc["mqtt"].to<JsonObject>();
|
||||||
mqtt["enabled"] = config.Mqtt.Enabled;
|
mqtt["enabled"] = config.Mqtt.Enabled;
|
||||||
mqtt["verbose_logging"] = config.Mqtt.VerboseLogging;
|
mqtt["verbose_logging"] = config.Mqtt.VerboseLogging;
|
||||||
mqtt["hostname"] = config.Mqtt.Hostname;
|
mqtt["hostname"] = config.Mqtt.Hostname;
|
||||||
@ -70,27 +66,27 @@ bool ConfigurationClass::write()
|
|||||||
mqtt["publish_interval"] = config.Mqtt.PublishInterval;
|
mqtt["publish_interval"] = config.Mqtt.PublishInterval;
|
||||||
mqtt["clean_session"] = config.Mqtt.CleanSession;
|
mqtt["clean_session"] = config.Mqtt.CleanSession;
|
||||||
|
|
||||||
JsonObject mqtt_lwt = mqtt.createNestedObject("lwt");
|
JsonObject mqtt_lwt = mqtt["lwt"].to<JsonObject>();
|
||||||
mqtt_lwt["topic"] = config.Mqtt.Lwt.Topic;
|
mqtt_lwt["topic"] = config.Mqtt.Lwt.Topic;
|
||||||
mqtt_lwt["value_online"] = config.Mqtt.Lwt.Value_Online;
|
mqtt_lwt["value_online"] = config.Mqtt.Lwt.Value_Online;
|
||||||
mqtt_lwt["value_offline"] = config.Mqtt.Lwt.Value_Offline;
|
mqtt_lwt["value_offline"] = config.Mqtt.Lwt.Value_Offline;
|
||||||
mqtt_lwt["qos"] = config.Mqtt.Lwt.Qos;
|
mqtt_lwt["qos"] = config.Mqtt.Lwt.Qos;
|
||||||
|
|
||||||
JsonObject mqtt_tls = mqtt.createNestedObject("tls");
|
JsonObject mqtt_tls = mqtt["tls"].to<JsonObject>();
|
||||||
mqtt_tls["enabled"] = config.Mqtt.Tls.Enabled;
|
mqtt_tls["enabled"] = config.Mqtt.Tls.Enabled;
|
||||||
mqtt_tls["root_ca_cert"] = config.Mqtt.Tls.RootCaCert;
|
mqtt_tls["root_ca_cert"] = config.Mqtt.Tls.RootCaCert;
|
||||||
mqtt_tls["certlogin"] = config.Mqtt.Tls.CertLogin;
|
mqtt_tls["certlogin"] = config.Mqtt.Tls.CertLogin;
|
||||||
mqtt_tls["client_cert"] = config.Mqtt.Tls.ClientCert;
|
mqtt_tls["client_cert"] = config.Mqtt.Tls.ClientCert;
|
||||||
mqtt_tls["client_key"] = config.Mqtt.Tls.ClientKey;
|
mqtt_tls["client_key"] = config.Mqtt.Tls.ClientKey;
|
||||||
|
|
||||||
JsonObject mqtt_hass = mqtt.createNestedObject("hass");
|
JsonObject mqtt_hass = mqtt["hass"].to<JsonObject>();
|
||||||
mqtt_hass["enabled"] = config.Mqtt.Hass.Enabled;
|
mqtt_hass["enabled"] = config.Mqtt.Hass.Enabled;
|
||||||
mqtt_hass["retain"] = config.Mqtt.Hass.Retain;
|
mqtt_hass["retain"] = config.Mqtt.Hass.Retain;
|
||||||
mqtt_hass["topic"] = config.Mqtt.Hass.Topic;
|
mqtt_hass["topic"] = config.Mqtt.Hass.Topic;
|
||||||
mqtt_hass["individual_panels"] = config.Mqtt.Hass.IndividualPanels;
|
mqtt_hass["individual_panels"] = config.Mqtt.Hass.IndividualPanels;
|
||||||
mqtt_hass["expire"] = config.Mqtt.Hass.Expire;
|
mqtt_hass["expire"] = config.Mqtt.Hass.Expire;
|
||||||
|
|
||||||
JsonObject dtu = doc.createNestedObject("dtu");
|
JsonObject dtu = doc["dtu"].to<JsonObject>();
|
||||||
dtu["serial"] = config.Dtu.Serial;
|
dtu["serial"] = config.Dtu.Serial;
|
||||||
dtu["poll_interval"] = config.Dtu.PollInterval;
|
dtu["poll_interval"] = config.Dtu.PollInterval;
|
||||||
dtu["verbose_logging"] = config.Dtu.VerboseLogging;
|
dtu["verbose_logging"] = config.Dtu.VerboseLogging;
|
||||||
@ -99,14 +95,14 @@ bool ConfigurationClass::write()
|
|||||||
dtu["cmt_frequency"] = config.Dtu.Cmt.Frequency;
|
dtu["cmt_frequency"] = config.Dtu.Cmt.Frequency;
|
||||||
dtu["cmt_country_mode"] = config.Dtu.Cmt.CountryMode;
|
dtu["cmt_country_mode"] = config.Dtu.Cmt.CountryMode;
|
||||||
|
|
||||||
JsonObject security = doc.createNestedObject("security");
|
JsonObject security = doc["security"].to<JsonObject>();
|
||||||
security["password"] = config.Security.Password;
|
security["password"] = config.Security.Password;
|
||||||
security["allow_readonly"] = config.Security.AllowReadonly;
|
security["allow_readonly"] = config.Security.AllowReadonly;
|
||||||
|
|
||||||
JsonObject device = doc.createNestedObject("device");
|
JsonObject device = doc["device"].to<JsonObject>();
|
||||||
device["pinmapping"] = config.Dev_PinMapping;
|
device["pinmapping"] = config.Dev_PinMapping;
|
||||||
|
|
||||||
JsonObject display = device.createNestedObject("display");
|
JsonObject display = device["display"].to<JsonObject>();
|
||||||
display["powersafe"] = config.Display.PowerSafe;
|
display["powersafe"] = config.Display.PowerSafe;
|
||||||
display["screensaver"] = config.Display.ScreenSaver;
|
display["screensaver"] = config.Display.ScreenSaver;
|
||||||
display["rotation"] = config.Display.Rotation;
|
display["rotation"] = config.Display.Rotation;
|
||||||
@ -115,15 +111,15 @@ bool ConfigurationClass::write()
|
|||||||
display["diagram_duration"] = config.Display.Diagram.Duration;
|
display["diagram_duration"] = config.Display.Diagram.Duration;
|
||||||
display["diagram_mode"] = config.Display.Diagram.Mode;
|
display["diagram_mode"] = config.Display.Diagram.Mode;
|
||||||
|
|
||||||
JsonArray leds = device.createNestedArray("led");
|
JsonArray leds = device["led"].to<JsonArray>();
|
||||||
for (uint8_t i = 0; i < PINMAPPING_LED_COUNT; i++) {
|
for (uint8_t i = 0; i < PINMAPPING_LED_COUNT; i++) {
|
||||||
JsonObject led = leds.createNestedObject();
|
JsonObject led = leds.add<JsonObject>();
|
||||||
led["brightness"] = config.Led_Single[i].Brightness;
|
led["brightness"] = config.Led_Single[i].Brightness;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArray inverters = doc.createNestedArray("inverters");
|
JsonArray inverters = doc["inverters"].to<JsonArray>();
|
||||||
for (uint8_t i = 0; i < INV_MAX_COUNT; i++) {
|
for (uint8_t i = 0; i < INV_MAX_COUNT; i++) {
|
||||||
JsonObject inv = inverters.createNestedObject();
|
JsonObject inv = inverters.add<JsonObject>();
|
||||||
inv["serial"] = config.Inverter[i].Serial;
|
inv["serial"] = config.Inverter[i].Serial;
|
||||||
inv["name"] = config.Inverter[i].Name;
|
inv["name"] = config.Inverter[i].Name;
|
||||||
inv["order"] = config.Inverter[i].Order;
|
inv["order"] = config.Inverter[i].Order;
|
||||||
@ -136,21 +132,21 @@ bool ConfigurationClass::write()
|
|||||||
inv["zero_day"] = config.Inverter[i].ZeroYieldDayOnMidnight;
|
inv["zero_day"] = config.Inverter[i].ZeroYieldDayOnMidnight;
|
||||||
inv["yieldday_correction"] = config.Inverter[i].YieldDayCorrection;
|
inv["yieldday_correction"] = config.Inverter[i].YieldDayCorrection;
|
||||||
|
|
||||||
JsonArray channel = inv.createNestedArray("channel");
|
JsonArray channel = inv["channel"].to<JsonArray>();
|
||||||
for (uint8_t c = 0; c < INV_MAX_CHAN_COUNT; c++) {
|
for (uint8_t c = 0; c < INV_MAX_CHAN_COUNT; c++) {
|
||||||
JsonObject chanData = channel.createNestedObject();
|
JsonObject chanData = channel.add<JsonObject>();
|
||||||
chanData["name"] = config.Inverter[i].channel[c].Name;
|
chanData["name"] = config.Inverter[i].channel[c].Name;
|
||||||
chanData["max_power"] = config.Inverter[i].channel[c].MaxChannelPower;
|
chanData["max_power"] = config.Inverter[i].channel[c].MaxChannelPower;
|
||||||
chanData["yield_total_offset"] = config.Inverter[i].channel[c].YieldTotalOffset;
|
chanData["yield_total_offset"] = config.Inverter[i].channel[c].YieldTotalOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject vedirect = doc.createNestedObject("vedirect");
|
JsonObject vedirect = doc["vedirect"].to<JsonObject>();
|
||||||
vedirect["enabled"] = config.Vedirect.Enabled;
|
vedirect["enabled"] = config.Vedirect.Enabled;
|
||||||
vedirect["verbose_logging"] = config.Vedirect.VerboseLogging;
|
vedirect["verbose_logging"] = config.Vedirect.VerboseLogging;
|
||||||
vedirect["updates_only"] = config.Vedirect.UpdatesOnly;
|
vedirect["updates_only"] = config.Vedirect.UpdatesOnly;
|
||||||
|
|
||||||
JsonObject powermeter = doc.createNestedObject("powermeter");
|
JsonObject powermeter = doc["powermeter"].to<JsonObject>();
|
||||||
powermeter["enabled"] = config.PowerMeter.Enabled;
|
powermeter["enabled"] = config.PowerMeter.Enabled;
|
||||||
powermeter["verbose_logging"] = config.PowerMeter.VerboseLogging;
|
powermeter["verbose_logging"] = config.PowerMeter.VerboseLogging;
|
||||||
powermeter["interval"] = config.PowerMeter.Interval;
|
powermeter["interval"] = config.PowerMeter.Interval;
|
||||||
@ -162,9 +158,9 @@ bool ConfigurationClass::write()
|
|||||||
powermeter["sdmaddress"] = config.PowerMeter.SdmAddress;
|
powermeter["sdmaddress"] = config.PowerMeter.SdmAddress;
|
||||||
powermeter["http_individual_requests"] = config.PowerMeter.HttpIndividualRequests;
|
powermeter["http_individual_requests"] = config.PowerMeter.HttpIndividualRequests;
|
||||||
|
|
||||||
JsonArray powermeter_http_phases = powermeter.createNestedArray("http_phases");
|
JsonArray powermeter_http_phases = powermeter["http_phases"].to<JsonArray>();
|
||||||
for (uint8_t i = 0; i < POWERMETER_MAX_PHASES; i++) {
|
for (uint8_t i = 0; i < POWERMETER_MAX_PHASES; i++) {
|
||||||
JsonObject powermeter_phase = powermeter_http_phases.createNestedObject();
|
JsonObject powermeter_phase = powermeter_http_phases.add<JsonObject>();
|
||||||
|
|
||||||
powermeter_phase["enabled"] = config.PowerMeter.Http_Phase[i].Enabled;
|
powermeter_phase["enabled"] = config.PowerMeter.Http_Phase[i].Enabled;
|
||||||
powermeter_phase["url"] = config.PowerMeter.Http_Phase[i].Url;
|
powermeter_phase["url"] = config.PowerMeter.Http_Phase[i].Url;
|
||||||
@ -179,7 +175,7 @@ bool ConfigurationClass::write()
|
|||||||
powermeter_phase["sign_inverted"] = config.PowerMeter.Http_Phase[i].SignInverted;
|
powermeter_phase["sign_inverted"] = config.PowerMeter.Http_Phase[i].SignInverted;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject powerlimiter = doc.createNestedObject("powerlimiter");
|
JsonObject powerlimiter = doc["powerlimiter"].to<JsonObject>();
|
||||||
powerlimiter["enabled"] = config.PowerLimiter.Enabled;
|
powerlimiter["enabled"] = config.PowerLimiter.Enabled;
|
||||||
powerlimiter["verbose_logging"] = config.PowerLimiter.VerboseLogging;
|
powerlimiter["verbose_logging"] = config.PowerLimiter.VerboseLogging;
|
||||||
powerlimiter["solar_passtrough_enabled"] = config.PowerLimiter.SolarPassThroughEnabled;
|
powerlimiter["solar_passtrough_enabled"] = config.PowerLimiter.SolarPassThroughEnabled;
|
||||||
@ -206,7 +202,7 @@ bool ConfigurationClass::write()
|
|||||||
powerlimiter["full_solar_passthrough_start_voltage"] = config.PowerLimiter.FullSolarPassThroughStartVoltage;
|
powerlimiter["full_solar_passthrough_start_voltage"] = config.PowerLimiter.FullSolarPassThroughStartVoltage;
|
||||||
powerlimiter["full_solar_passthrough_stop_voltage"] = config.PowerLimiter.FullSolarPassThroughStopVoltage;
|
powerlimiter["full_solar_passthrough_stop_voltage"] = config.PowerLimiter.FullSolarPassThroughStopVoltage;
|
||||||
|
|
||||||
JsonObject battery = doc.createNestedObject("battery");
|
JsonObject battery = doc["battery"].to<JsonObject>();
|
||||||
battery["enabled"] = config.Battery.Enabled;
|
battery["enabled"] = config.Battery.Enabled;
|
||||||
battery["verbose_logging"] = config.Battery.VerboseLogging;
|
battery["verbose_logging"] = config.Battery.VerboseLogging;
|
||||||
battery["provider"] = config.Battery.Provider;
|
battery["provider"] = config.Battery.Provider;
|
||||||
@ -215,7 +211,7 @@ bool ConfigurationClass::write()
|
|||||||
battery["mqtt_topic"] = config.Battery.MqttSocTopic;
|
battery["mqtt_topic"] = config.Battery.MqttSocTopic;
|
||||||
battery["mqtt_voltage_topic"] = config.Battery.MqttVoltageTopic;
|
battery["mqtt_voltage_topic"] = config.Battery.MqttVoltageTopic;
|
||||||
|
|
||||||
JsonObject huawei = doc.createNestedObject("huawei");
|
JsonObject huawei = doc["huawei"].to<JsonObject>();
|
||||||
huawei["enabled"] = config.Huawei.Enabled;
|
huawei["enabled"] = config.Huawei.Enabled;
|
||||||
huawei["verbose_logging"] = config.Huawei.VerboseLogging;
|
huawei["verbose_logging"] = config.Huawei.VerboseLogging;
|
||||||
huawei["can_controller_frequency"] = config.Huawei.CAN_Controller_Frequency;
|
huawei["can_controller_frequency"] = config.Huawei.CAN_Controller_Frequency;
|
||||||
@ -228,6 +224,10 @@ bool ConfigurationClass::write()
|
|||||||
huawei["upper_power_limit"] = config.Huawei.Auto_Power_Upper_Power_Limit;
|
huawei["upper_power_limit"] = config.Huawei.Auto_Power_Upper_Power_Limit;
|
||||||
huawei["stop_batterysoc_threshold"] = config.Huawei.Auto_Power_Stop_BatterySoC_Threshold;
|
huawei["stop_batterysoc_threshold"] = config.Huawei.Auto_Power_Stop_BatterySoC_Threshold;
|
||||||
|
|
||||||
|
if (!Utils::checkJsonAlloc(doc, __FUNCTION__, __LINE__)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Serialize JSON to file
|
// Serialize JSON to file
|
||||||
if (serializeJson(doc, f) == 0) {
|
if (serializeJson(doc, f) == 0) {
|
||||||
MessageOutput.println("Failed to write file");
|
MessageOutput.println("Failed to write file");
|
||||||
@ -242,11 +242,7 @@ bool ConfigurationClass::read()
|
|||||||
{
|
{
|
||||||
File f = LittleFS.open(CONFIG_FILENAME, "r", false);
|
File f = LittleFS.open(CONFIG_FILENAME, "r", false);
|
||||||
|
|
||||||
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
JsonDocument doc;
|
||||||
|
|
||||||
if (!Utils::checkJsonAlloc(doc, __FUNCTION__, __LINE__)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the JSON document
|
// Deserialize the JSON document
|
||||||
const DeserializationError error = deserializeJson(doc, f);
|
const DeserializationError error = deserializeJson(doc, f);
|
||||||
@ -254,6 +250,10 @@ bool ConfigurationClass::read()
|
|||||||
MessageOutput.println("Failed to read file, using default configuration");
|
MessageOutput.println("Failed to read file, using default configuration");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Utils::checkJsonAlloc(doc, __FUNCTION__, __LINE__)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
JsonObject cfg = doc["cfg"];
|
JsonObject cfg = doc["cfg"];
|
||||||
config.Cfg.Version = cfg["version"] | CONFIG_VERSION;
|
config.Cfg.Version = cfg["version"] | CONFIG_VERSION;
|
||||||
config.Cfg.SaveCount = cfg["save_count"] | 0;
|
config.Cfg.SaveCount = cfg["save_count"] | 0;
|
||||||
@ -495,11 +495,7 @@ void ConfigurationClass::migrate()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
JsonDocument doc;
|
||||||
|
|
||||||
if (!Utils::checkJsonAlloc(doc, __FUNCTION__, __LINE__)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the JSON document
|
// Deserialize the JSON document
|
||||||
const DeserializationError error = deserializeJson(doc, f);
|
const DeserializationError error = deserializeJson(doc, f);
|
||||||
@ -508,6 +504,10 @@ void ConfigurationClass::migrate()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Utils::checkJsonAlloc(doc, __FUNCTION__, __LINE__)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (config.Cfg.Version < 0x00011700) {
|
if (config.Cfg.Version < 0x00011700) {
|
||||||
JsonArray inverters = doc["inverters"];
|
JsonArray inverters = doc["inverters"];
|
||||||
for (uint8_t i = 0; i < INV_MAX_COUNT; i++) {
|
for (uint8_t i = 0; i < INV_MAX_COUNT; i++) {
|
||||||
|
|||||||
@ -51,9 +51,9 @@ void InverterSettingsClass::init(Scheduler& scheduler)
|
|||||||
|
|
||||||
if (PinMapping.isValidCmt2300Config()) {
|
if (PinMapping.isValidCmt2300Config()) {
|
||||||
Hoymiles.initCMT(pin.cmt_sdio, pin.cmt_clk, pin.cmt_cs, pin.cmt_fcs, pin.cmt_gpio2, pin.cmt_gpio3);
|
Hoymiles.initCMT(pin.cmt_sdio, pin.cmt_clk, pin.cmt_cs, pin.cmt_fcs, pin.cmt_gpio2, pin.cmt_gpio3);
|
||||||
MessageOutput.println(F(" Setting country mode... "));
|
MessageOutput.println(" Setting country mode... ");
|
||||||
Hoymiles.getRadioCmt()->setCountryMode(static_cast<CountryModeId_t>(config.Dtu.Cmt.CountryMode));
|
Hoymiles.getRadioCmt()->setCountryMode(static_cast<CountryModeId_t>(config.Dtu.Cmt.CountryMode));
|
||||||
MessageOutput.println(F(" Setting CMT target frequency... "));
|
MessageOutput.println(" Setting CMT target frequency... ");
|
||||||
Hoymiles.getRadioCmt()->setInverterTargetFrequency(config.Dtu.Cmt.Frequency);
|
Hoymiles.getRadioCmt()->setInverterTargetFrequency(config.Dtu.Cmt.Frequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -124,10 +124,8 @@ void MqttHandleVedirectHassClass::publishSensor(const char *caption, const char
|
|||||||
statTopic.concat("/");
|
statTopic.concat("/");
|
||||||
statTopic.concat(subTopic);
|
statTopic.concat(subTopic);
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
root["name"] = caption;
|
root["name"] = caption;
|
||||||
root["stat_t"] = statTopic;
|
root["stat_t"] = statTopic;
|
||||||
root["uniq_id"] = serial + "_" + sensorId;
|
root["uniq_id"] = serial + "_" + sensorId;
|
||||||
@ -140,7 +138,7 @@ void MqttHandleVedirectHassClass::publishSensor(const char *caption, const char
|
|||||||
root["unit_of_meas"] = unitOfMeasurement;
|
root["unit_of_meas"] = unitOfMeasurement;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject deviceObj = root.createNestedObject("dev");
|
JsonObject deviceObj = root["dev"].to<JsonObject>();
|
||||||
createDeviceInfo(deviceObj, mpptData);
|
createDeviceInfo(deviceObj, mpptData);
|
||||||
|
|
||||||
if (Configuration.get().Mqtt.Hass.Expire) {
|
if (Configuration.get().Mqtt.Hass.Expire) {
|
||||||
@ -153,7 +151,9 @@ void MqttHandleVedirectHassClass::publishSensor(const char *caption, const char
|
|||||||
root["stat_cla"] = stateClass;
|
root["stat_cla"] = stateClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Utils::checkJsonOverflow(root, __FUNCTION__, __LINE__)) { return; }
|
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
serializeJson(root, buffer);
|
serializeJson(root, buffer);
|
||||||
@ -182,10 +182,7 @@ void MqttHandleVedirectHassClass::publishBinarySensor(const char *caption, const
|
|||||||
statTopic.concat("/");
|
statTopic.concat("/");
|
||||||
statTopic.concat(subTopic);
|
statTopic.concat(subTopic);
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
root["name"] = caption;
|
root["name"] = caption;
|
||||||
root["uniq_id"] = serial + "_" + sensorId;
|
root["uniq_id"] = serial + "_" + sensorId;
|
||||||
root["stat_t"] = statTopic;
|
root["stat_t"] = statTopic;
|
||||||
@ -196,10 +193,12 @@ void MqttHandleVedirectHassClass::publishBinarySensor(const char *caption, const
|
|||||||
root["icon"] = icon;
|
root["icon"] = icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject deviceObj = root.createNestedObject("dev");
|
JsonObject deviceObj = root["dev"].to<JsonObject>();
|
||||||
createDeviceInfo(deviceObj, mpptData);
|
createDeviceInfo(deviceObj, mpptData);
|
||||||
|
|
||||||
if (Utils::checkJsonOverflow(root, __FUNCTION__, __LINE__)) { return; }
|
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
serializeJson(root, buffer);
|
serializeJson(root, buffer);
|
||||||
|
|||||||
@ -144,10 +144,7 @@ void MqttHandleBatteryHassClass::publishSensor(const char* caption, const char*
|
|||||||
// statTopic.concat("/");
|
// statTopic.concat("/");
|
||||||
statTopic.concat(subTopic);
|
statTopic.concat(subTopic);
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
root["name"] = caption;
|
root["name"] = caption;
|
||||||
root["stat_t"] = statTopic;
|
root["stat_t"] = statTopic;
|
||||||
root["uniq_id"] = serial + "_" + sensorId;
|
root["uniq_id"] = serial + "_" + sensorId;
|
||||||
@ -160,7 +157,7 @@ void MqttHandleBatteryHassClass::publishSensor(const char* caption, const char*
|
|||||||
root["unit_of_meas"] = unitOfMeasurement;
|
root["unit_of_meas"] = unitOfMeasurement;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject deviceObj = root.createNestedObject("dev");
|
JsonObject deviceObj = root["dev"].to<JsonObject>();
|
||||||
createDeviceInfo(deviceObj);
|
createDeviceInfo(deviceObj);
|
||||||
|
|
||||||
if (Configuration.get().Mqtt.Hass.Expire) {
|
if (Configuration.get().Mqtt.Hass.Expire) {
|
||||||
@ -173,7 +170,9 @@ void MqttHandleBatteryHassClass::publishSensor(const char* caption, const char*
|
|||||||
root["stat_cla"] = stateClass;
|
root["stat_cla"] = stateClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Utils::checkJsonOverflow(root, __FUNCTION__, __LINE__)) { return; }
|
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
serializeJson(root, buffer);
|
serializeJson(root, buffer);
|
||||||
@ -201,10 +200,8 @@ void MqttHandleBatteryHassClass::publishBinarySensor(const char* caption, const
|
|||||||
// statTopic.concat("/");
|
// statTopic.concat("/");
|
||||||
statTopic.concat(subTopic);
|
statTopic.concat(subTopic);
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
root["name"] = caption;
|
root["name"] = caption;
|
||||||
root["uniq_id"] = serial + "_" + sensorId;
|
root["uniq_id"] = serial + "_" + sensorId;
|
||||||
root["stat_t"] = statTopic;
|
root["stat_t"] = statTopic;
|
||||||
@ -215,10 +212,12 @@ void MqttHandleBatteryHassClass::publishBinarySensor(const char* caption, const
|
|||||||
root["icon"] = icon;
|
root["icon"] = icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject deviceObj = root.createNestedObject("dev");
|
auto deviceObj = root["dev"].to<JsonObject>();
|
||||||
createDeviceInfo(deviceObj);
|
createDeviceInfo(deviceObj);
|
||||||
|
|
||||||
if (Utils::checkJsonOverflow(root, __FUNCTION__, __LINE__)) { return; }
|
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
serializeJson(root, buffer);
|
serializeJson(root, buffer);
|
||||||
|
|||||||
@ -137,10 +137,7 @@ void MqttHandleHassClass::publishInverterField(std::shared_ptr<InverterAbstract>
|
|||||||
name = "CH" + chanNum + " " + fieldName;
|
name = "CH" + chanNum + " " + fieldName;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
root["name"] = name;
|
root["name"] = name;
|
||||||
root["stat_t"] = stateTopic;
|
root["stat_t"] = stateTopic;
|
||||||
@ -163,6 +160,10 @@ void MqttHandleHassClass::publishInverterField(std::shared_ptr<InverterAbstract>
|
|||||||
root["stat_cla"] = stateCls;
|
root["stat_cla"] = stateCls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String buffer;
|
String buffer;
|
||||||
serializeJson(root, buffer);
|
serializeJson(root, buffer);
|
||||||
publish(configTopic, buffer);
|
publish(configTopic, buffer);
|
||||||
@ -185,10 +186,7 @@ void MqttHandleHassClass::publishInverterButton(std::shared_ptr<InverterAbstract
|
|||||||
|
|
||||||
const String cmdTopic = MqttSettings.getPrefix() + serial + "/" + subTopic;
|
const String cmdTopic = MqttSettings.getPrefix() + serial + "/" + subTopic;
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
root["name"] = caption;
|
root["name"] = caption;
|
||||||
root["uniq_id"] = serial + "_" + buttonId;
|
root["uniq_id"] = serial + "_" + buttonId;
|
||||||
@ -204,6 +202,10 @@ void MqttHandleHassClass::publishInverterButton(std::shared_ptr<InverterAbstract
|
|||||||
|
|
||||||
createInverterInfo(root, inv);
|
createInverterInfo(root, inv);
|
||||||
|
|
||||||
|
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String buffer;
|
String buffer;
|
||||||
serializeJson(root, buffer);
|
serializeJson(root, buffer);
|
||||||
publish(configTopic, buffer);
|
publish(configTopic, buffer);
|
||||||
@ -227,10 +229,7 @@ void MqttHandleHassClass::publishInverterNumber(
|
|||||||
const String cmdTopic = MqttSettings.getPrefix() + serial + "/" + commandTopic;
|
const String cmdTopic = MqttSettings.getPrefix() + serial + "/" + commandTopic;
|
||||||
const String statTopic = MqttSettings.getPrefix() + serial + "/" + stateTopic;
|
const String statTopic = MqttSettings.getPrefix() + serial + "/" + stateTopic;
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
root["name"] = caption;
|
root["name"] = caption;
|
||||||
root["uniq_id"] = serial + "_" + buttonId;
|
root["uniq_id"] = serial + "_" + buttonId;
|
||||||
@ -246,6 +245,10 @@ void MqttHandleHassClass::publishInverterNumber(
|
|||||||
|
|
||||||
createInverterInfo(root, inv);
|
createInverterInfo(root, inv);
|
||||||
|
|
||||||
|
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String buffer;
|
String buffer;
|
||||||
serializeJson(root, buffer);
|
serializeJson(root, buffer);
|
||||||
publish(configTopic, buffer);
|
publish(configTopic, buffer);
|
||||||
@ -265,10 +268,7 @@ void MqttHandleHassClass::publishInverterBinarySensor(std::shared_ptr<InverterAb
|
|||||||
|
|
||||||
const String statTopic = MqttSettings.getPrefix() + serial + "/" + subTopic;
|
const String statTopic = MqttSettings.getPrefix() + serial + "/" + subTopic;
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
root["name"] = caption;
|
root["name"] = caption;
|
||||||
root["uniq_id"] = serial + "_" + sensorId;
|
root["uniq_id"] = serial + "_" + sensorId;
|
||||||
@ -278,6 +278,10 @@ void MqttHandleHassClass::publishInverterBinarySensor(std::shared_ptr<InverterAb
|
|||||||
|
|
||||||
createInverterInfo(root, inv);
|
createInverterInfo(root, inv);
|
||||||
|
|
||||||
|
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String buffer;
|
String buffer;
|
||||||
serializeJson(root, buffer);
|
serializeJson(root, buffer);
|
||||||
publish(configTopic, buffer);
|
publish(configTopic, buffer);
|
||||||
@ -293,10 +297,7 @@ void MqttHandleHassClass::publishDtuSensor(const char* name, const char* device_
|
|||||||
topic = id;
|
topic = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
root["name"] = name;
|
root["name"] = name;
|
||||||
root["uniq_id"] = getDtuUniqueId() + "_" + id;
|
root["uniq_id"] = getDtuUniqueId() + "_" + id;
|
||||||
@ -322,6 +323,8 @@ void MqttHandleHassClass::publishDtuSensor(const char* name, const char* device_
|
|||||||
|
|
||||||
createDtuInfo(root);
|
createDtuInfo(root);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
String buffer;
|
String buffer;
|
||||||
const String configTopic = "sensor/" + getDtuUniqueId() + "/" + id + "/config";
|
const String configTopic = "sensor/" + getDtuUniqueId() + "/" + id + "/config";
|
||||||
serializeJson(root, buffer);
|
serializeJson(root, buffer);
|
||||||
@ -339,10 +342,7 @@ void MqttHandleHassClass::publishDtuBinarySensor(const char* name, const char* d
|
|||||||
topic = String("dtu/") + "/" + id;
|
topic = String("dtu/") + "/" + id;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
root["name"] = name;
|
root["name"] = name;
|
||||||
root["uniq_id"] = getDtuUniqueId() + "_" + id;
|
root["uniq_id"] = getDtuUniqueId() + "_" + id;
|
||||||
@ -359,13 +359,17 @@ void MqttHandleHassClass::publishDtuBinarySensor(const char* name, const char* d
|
|||||||
|
|
||||||
createDtuInfo(root);
|
createDtuInfo(root);
|
||||||
|
|
||||||
|
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String buffer;
|
String buffer;
|
||||||
const String configTopic = "binary_sensor/" + getDtuUniqueId() + "/" + id + "/config";
|
const String configTopic = "binary_sensor/" + getDtuUniqueId() + "/" + id + "/config";
|
||||||
serializeJson(root, buffer);
|
serializeJson(root, buffer);
|
||||||
publish(configTopic, buffer);
|
publish(configTopic, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MqttHandleHassClass::createInverterInfo(DynamicJsonDocument& root, std::shared_ptr<InverterAbstract> inv)
|
void MqttHandleHassClass::createInverterInfo(JsonDocument& root, std::shared_ptr<InverterAbstract> inv)
|
||||||
{
|
{
|
||||||
createDeviceInfo(
|
createDeviceInfo(
|
||||||
root,
|
root,
|
||||||
@ -378,7 +382,7 @@ void MqttHandleHassClass::createInverterInfo(DynamicJsonDocument& root, std::sha
|
|||||||
getDtuUniqueId());
|
getDtuUniqueId());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MqttHandleHassClass::createDtuInfo(DynamicJsonDocument& root)
|
void MqttHandleHassClass::createDtuInfo(JsonDocument& root)
|
||||||
{
|
{
|
||||||
createDeviceInfo(
|
createDeviceInfo(
|
||||||
root,
|
root,
|
||||||
@ -391,12 +395,12 @@ void MqttHandleHassClass::createDtuInfo(DynamicJsonDocument& root)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MqttHandleHassClass::createDeviceInfo(
|
void MqttHandleHassClass::createDeviceInfo(
|
||||||
DynamicJsonDocument& root,
|
JsonDocument& root,
|
||||||
const String& name, const String& identifiers, const String& configuration_url,
|
const String& name, const String& identifiers, const String& configuration_url,
|
||||||
const String& manufacturer, const String& model, const String& sw_version,
|
const String& manufacturer, const String& model, const String& sw_version,
|
||||||
const String& via_device)
|
const String& via_device)
|
||||||
{
|
{
|
||||||
auto object = root.createNestedObject("dev");
|
auto object = root["dev"].to<JsonObject>();
|
||||||
|
|
||||||
object["name"] = name;
|
object["name"] = name;
|
||||||
object["ids"] = identifiers;
|
object["ids"] = identifiers;
|
||||||
|
|||||||
@ -112,10 +112,7 @@ void MqttHandlePowerLimiterHassClass::publishSelect(
|
|||||||
const String cmdTopic = MqttSettings.getPrefix() + "powerlimiter/cmd/" + commandTopic;
|
const String cmdTopic = MqttSettings.getPrefix() + "powerlimiter/cmd/" + commandTopic;
|
||||||
const String statTopic = MqttSettings.getPrefix() + "powerlimiter/status/" + stateTopic;
|
const String statTopic = MqttSettings.getPrefix() + "powerlimiter/status/" + stateTopic;
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
root["name"] = caption;
|
root["name"] = caption;
|
||||||
root["uniq_id"] = selectId;
|
root["uniq_id"] = selectId;
|
||||||
@ -125,15 +122,17 @@ void MqttHandlePowerLimiterHassClass::publishSelect(
|
|||||||
root["ent_cat"] = category;
|
root["ent_cat"] = category;
|
||||||
root["cmd_t"] = cmdTopic;
|
root["cmd_t"] = cmdTopic;
|
||||||
root["stat_t"] = statTopic;
|
root["stat_t"] = statTopic;
|
||||||
JsonArray options = root.createNestedArray("options");
|
JsonArray options = root["options"].to<JsonArray>();
|
||||||
options.add("0");
|
options.add("0");
|
||||||
options.add("1");
|
options.add("1");
|
||||||
options.add("2");
|
options.add("2");
|
||||||
|
|
||||||
JsonObject deviceObj = root.createNestedObject("dev");
|
JsonObject deviceObj = root["dev"].to<JsonObject>();
|
||||||
createDeviceInfo(deviceObj);
|
createDeviceInfo(deviceObj);
|
||||||
|
|
||||||
if (Utils::checkJsonOverflow(root, __FUNCTION__, __LINE__)) { return; }
|
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String buffer;
|
String buffer;
|
||||||
serializeJson(root, buffer);
|
serializeJson(root, buffer);
|
||||||
@ -155,10 +154,7 @@ void MqttHandlePowerLimiterHassClass::publishNumber(
|
|||||||
const String cmdTopic = MqttSettings.getPrefix() + "powerlimiter/cmd/" + commandTopic;
|
const String cmdTopic = MqttSettings.getPrefix() + "powerlimiter/cmd/" + commandTopic;
|
||||||
const String statTopic = MqttSettings.getPrefix() + "powerlimiter/status/" + stateTopic;
|
const String statTopic = MqttSettings.getPrefix() + "powerlimiter/status/" + stateTopic;
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
root["name"] = caption;
|
root["name"] = caption;
|
||||||
root["uniq_id"] = numberId;
|
root["uniq_id"] = numberId;
|
||||||
@ -178,10 +174,12 @@ void MqttHandlePowerLimiterHassClass::publishNumber(
|
|||||||
root["exp_aft"] = config.Mqtt.PublishInterval * 3;
|
root["exp_aft"] = config.Mqtt.PublishInterval * 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject deviceObj = root.createNestedObject("dev");
|
JsonObject deviceObj = root["dev"].to<JsonObject>();
|
||||||
createDeviceInfo(deviceObj);
|
createDeviceInfo(deviceObj);
|
||||||
|
|
||||||
if (Utils::checkJsonOverflow(root, __FUNCTION__, __LINE__)) { return; }
|
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String buffer;
|
String buffer;
|
||||||
serializeJson(root, buffer);
|
serializeJson(root, buffer);
|
||||||
|
|||||||
@ -8,8 +8,6 @@
|
|||||||
#include <LittleFS.h>
|
#include <LittleFS.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define JSON_BUFFER_SIZE 6144
|
|
||||||
|
|
||||||
#ifndef DISPLAY_TYPE
|
#ifndef DISPLAY_TYPE
|
||||||
#define DISPLAY_TYPE 0U
|
#define DISPLAY_TYPE 0U
|
||||||
#endif
|
#endif
|
||||||
@ -234,7 +232,7 @@ bool PinMappingClass::init(const String& deviceMapping)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
JsonDocument doc;
|
||||||
// Deserialize the JSON document
|
// Deserialize the JSON document
|
||||||
DeserializationError error = deserializeJson(doc, f);
|
DeserializationError error = deserializeJson(doc, f);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
|||||||
@ -69,9 +69,9 @@ void Utils::restartDtu()
|
|||||||
ESP.restart();
|
ESP.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Utils::checkJsonAlloc(const DynamicJsonDocument& doc, const char* function, const uint16_t line)
|
bool Utils::checkJsonAlloc(const JsonDocument& doc, const char* function, const uint16_t line)
|
||||||
{
|
{
|
||||||
if (doc.capacity() == 0) {
|
if (doc.overflowed()) {
|
||||||
MessageOutput.printf("Alloc failed: %s, %d\r\n", function, line);
|
MessageOutput.printf("Alloc failed: %s, %d\r\n", function, line);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -79,16 +79,6 @@ bool Utils::checkJsonAlloc(const DynamicJsonDocument& doc, const char* function,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Utils::checkJsonOverflow(const DynamicJsonDocument& doc, const char* function, const uint16_t line)
|
|
||||||
{
|
|
||||||
if (doc.overflowed()) {
|
|
||||||
MessageOutput.printf("DynamicJsonDocument overflowed: %s, %d\r\n", function, line);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Remove all files but the PINMAPPING_FILENAME
|
/// @brief Remove all files but the PINMAPPING_FILENAME
|
||||||
void Utils::removeAllFiles()
|
void Utils::removeAllFiles()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "WebApi.h"
|
#include "WebApi.h"
|
||||||
#include "Configuration.h"
|
#include "Configuration.h"
|
||||||
|
#include "MessageOutput.h"
|
||||||
#include "defaults.h"
|
#include "defaults.h"
|
||||||
#include <AsyncJson.h>
|
#include <AsyncJson.h>
|
||||||
|
|
||||||
@ -93,4 +94,58 @@ void WebApiClass::writeConfig(JsonVariant& retMsg, const WebApiError code, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WebApiClass::parseRequestData(AsyncWebServerRequest* request, AsyncJsonResponse* response, JsonDocument& json_document)
|
||||||
|
{
|
||||||
|
auto& retMsg = response->getRoot();
|
||||||
|
retMsg["type"] = "warning";
|
||||||
|
|
||||||
|
if (!request->hasParam("data", true)) {
|
||||||
|
retMsg["message"] = "No values found!";
|
||||||
|
retMsg["code"] = WebApiError::GenericNoValueFound;
|
||||||
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const String json = request->getParam("data", true)->value();
|
||||||
|
const DeserializationError error = deserializeJson(json_document, json);
|
||||||
|
if (error) {
|
||||||
|
retMsg["message"] = "Failed to parse data!";
|
||||||
|
retMsg["code"] = WebApiError::GenericParseError;
|
||||||
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t WebApiClass::parseSerialFromRequest(AsyncWebServerRequest* request, String param_name)
|
||||||
|
{
|
||||||
|
if (request->hasParam(param_name)) {
|
||||||
|
String s = request->getParam(param_name)->value();
|
||||||
|
return strtoll(s.c_str(), NULL, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebApiClass::sendJsonResponse(AsyncWebServerRequest* request, AsyncJsonResponse* response, const char* function, const uint16_t line)
|
||||||
|
{
|
||||||
|
bool ret_val = true;
|
||||||
|
if (response->overflowed()) {
|
||||||
|
auto& root = response->getRoot();
|
||||||
|
|
||||||
|
root.clear();
|
||||||
|
root["message"] = String("500 Internal Server Error: ") + function + ", " + line;
|
||||||
|
root["code"] = WebApiError::GenericInternalServerError;
|
||||||
|
root["type"] = "danger";
|
||||||
|
response->setCode(500);
|
||||||
|
MessageOutput.printf("WebResponse failed: %s, %d\r\n", function, line);
|
||||||
|
ret_val = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
response->setLength();
|
||||||
|
request->send(response);
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
WebApiClass WebApi;
|
WebApiClass WebApi;
|
||||||
|
|||||||
@ -93,7 +93,7 @@ void WebApiHuaweiClass::onPost(AsyncWebServerRequest* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
DeserializationError error = deserializeJson(root, json);
|
DeserializationError error = deserializeJson(root, json);
|
||||||
float value;
|
float value;
|
||||||
uint8_t online = true;
|
uint8_t online = true;
|
||||||
@ -164,12 +164,9 @@ void WebApiHuaweiClass::onPost(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
retMsg["type"] = "success";
|
WebApi.writeConfig(retMsg);
|
||||||
retMsg["message"] = "Settings saved!";
|
|
||||||
retMsg["code"] = WebApiError::GenericSuccess;
|
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -229,7 +226,7 @@ void WebApiHuaweiClass::onAdminPost(AsyncWebServerRequest* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
DeserializationError error = deserializeJson(root, json);
|
DeserializationError error = deserializeJson(root, json);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
@ -268,8 +265,7 @@ void WebApiHuaweiClass::onAdminPost(AsyncWebServerRequest* request)
|
|||||||
config.Huawei.Auto_Power_Stop_BatterySoC_Threshold = root["stop_batterysoc_threshold"];
|
config.Huawei.Auto_Power_Stop_BatterySoC_Threshold = root["stop_batterysoc_threshold"];
|
||||||
WebApi.writeConfig(retMsg);
|
WebApi.writeConfig(retMsg);
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
|
|
||||||
// TODO(schlimmchen): HuaweiCan has no real concept of the fact that the
|
// TODO(schlimmchen): HuaweiCan has no real concept of the fact that the
|
||||||
// config might change. at least not regarding CAN parameters. until that
|
// config might change. at least not regarding CAN parameters. until that
|
||||||
|
|||||||
@ -80,7 +80,7 @@ void WebApiBatteryClass::onAdminPost(AsyncWebServerRequest* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
DeserializationError error = deserializeJson(root, json);
|
DeserializationError error = deserializeJson(root, json);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
@ -94,8 +94,7 @@ void WebApiBatteryClass::onAdminPost(AsyncWebServerRequest* request)
|
|||||||
if (!root.containsKey("enabled") || !root.containsKey("provider")) {
|
if (!root.containsKey("enabled") || !root.containsKey("provider")) {
|
||||||
retMsg["message"] = "Values are missing!";
|
retMsg["message"] = "Values are missing!";
|
||||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,8 +109,7 @@ void WebApiBatteryClass::onAdminPost(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
WebApi.writeConfig(retMsg);
|
WebApi.writeConfig(retMsg);
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
|
|
||||||
Battery.updateSettings();
|
Battery.updateSettings();
|
||||||
MqttHandleBatteryHass.forceUpdate();
|
MqttHandleBatteryHass.forceUpdate();
|
||||||
|
|||||||
@ -53,51 +53,24 @@ void WebApiConfigClass::onConfigDelete(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
|
JsonDocument root;
|
||||||
|
if (!WebApi.parseRequestData(request, response, root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& retMsg = response->getRoot();
|
auto& retMsg = response->getRoot();
|
||||||
retMsg["type"] = "warning";
|
|
||||||
|
|
||||||
if (!request->hasParam("data", true)) {
|
|
||||||
retMsg["message"] = "No values found!";
|
|
||||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String json = request->getParam("data", true)->value();
|
|
||||||
|
|
||||||
if (json.length() > 1024) {
|
|
||||||
retMsg["message"] = "Data too large!";
|
|
||||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
|
||||||
const DeserializationError error = deserializeJson(root, json);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
retMsg["message"] = "Failed to parse data!";
|
|
||||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(root.containsKey("delete"))) {
|
if (!(root.containsKey("delete"))) {
|
||||||
retMsg["message"] = "Values are missing!";
|
retMsg["message"] = "Values are missing!";
|
||||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root["delete"].as<bool>() == false) {
|
if (root["delete"].as<bool>() == false) {
|
||||||
retMsg["message"] = "Not deleted anything!";
|
retMsg["message"] = "Not deleted anything!";
|
||||||
retMsg["code"] = WebApiError::ConfigNotDeleted;
|
retMsg["code"] = WebApiError::ConfigNotDeleted;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,8 +78,7 @@ void WebApiConfigClass::onConfigDelete(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Configuration resettet. Rebooting now...";
|
retMsg["message"] = "Configuration resettet. Rebooting now...";
|
||||||
retMsg["code"] = WebApiError::ConfigSuccess;
|
retMsg["code"] = WebApiError::ConfigSuccess;
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
|
|
||||||
Utils::removeAllFiles();
|
Utils::removeAllFiles();
|
||||||
Utils::restartDtu();
|
Utils::restartDtu();
|
||||||
@ -120,7 +92,7 @@ void WebApiConfigClass::onConfigListGet(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
auto& root = response->getRoot();
|
auto& root = response->getRoot();
|
||||||
auto data = root.createNestedArray("configs");
|
auto data = root["configs"].to<JsonArray>();
|
||||||
|
|
||||||
File rootfs = LittleFS.open("/");
|
File rootfs = LittleFS.open("/");
|
||||||
File file = rootfs.openNextFile();
|
File file = rootfs.openNextFile();
|
||||||
@ -128,15 +100,14 @@ void WebApiConfigClass::onConfigListGet(AsyncWebServerRequest* request)
|
|||||||
if (file.isDirectory()) {
|
if (file.isDirectory()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
JsonObject obj = data.createNestedObject();
|
JsonObject obj = data.add<JsonObject>();
|
||||||
obj["name"] = String(file.name());
|
obj["name"] = String(file.name());
|
||||||
|
|
||||||
file = rootfs.openNextFile();
|
file = rootfs.openNextFile();
|
||||||
}
|
}
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiConfigClass::onConfigUploadFinish(AsyncWebServerRequest* request)
|
void WebApiConfigClass::onConfigUploadFinish(AsyncWebServerRequest* request)
|
||||||
|
|||||||
@ -26,15 +26,15 @@ void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
auto& root = response->getRoot();
|
auto& root = response->getRoot();
|
||||||
const CONFIG_T& config = Configuration.get();
|
const CONFIG_T& config = Configuration.get();
|
||||||
const PinMapping_t& pin = PinMapping.get();
|
const PinMapping_t& pin = PinMapping.get();
|
||||||
|
|
||||||
auto curPin = root.createNestedObject("curPin");
|
auto curPin = root["curPin"].to<JsonObject>();
|
||||||
curPin["name"] = config.Dev_PinMapping;
|
curPin["name"] = config.Dev_PinMapping;
|
||||||
|
|
||||||
auto nrfPinObj = curPin.createNestedObject("nrf24");
|
auto nrfPinObj = curPin["nrf24"].to<JsonObject>();
|
||||||
nrfPinObj["clk"] = pin.nrf24_clk;
|
nrfPinObj["clk"] = pin.nrf24_clk;
|
||||||
nrfPinObj["cs"] = pin.nrf24_cs;
|
nrfPinObj["cs"] = pin.nrf24_cs;
|
||||||
nrfPinObj["en"] = pin.nrf24_en;
|
nrfPinObj["en"] = pin.nrf24_en;
|
||||||
@ -42,7 +42,7 @@ void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request)
|
|||||||
nrfPinObj["miso"] = pin.nrf24_miso;
|
nrfPinObj["miso"] = pin.nrf24_miso;
|
||||||
nrfPinObj["mosi"] = pin.nrf24_mosi;
|
nrfPinObj["mosi"] = pin.nrf24_mosi;
|
||||||
|
|
||||||
auto cmtPinObj = curPin.createNestedObject("cmt");
|
auto cmtPinObj = curPin["cmt"].to<JsonObject>();
|
||||||
cmtPinObj["clk"] = pin.cmt_clk;
|
cmtPinObj["clk"] = pin.cmt_clk;
|
||||||
cmtPinObj["cs"] = pin.cmt_cs;
|
cmtPinObj["cs"] = pin.cmt_cs;
|
||||||
cmtPinObj["fcs"] = pin.cmt_fcs;
|
cmtPinObj["fcs"] = pin.cmt_fcs;
|
||||||
@ -50,7 +50,7 @@ void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request)
|
|||||||
cmtPinObj["gpio2"] = pin.cmt_gpio2;
|
cmtPinObj["gpio2"] = pin.cmt_gpio2;
|
||||||
cmtPinObj["gpio3"] = pin.cmt_gpio3;
|
cmtPinObj["gpio3"] = pin.cmt_gpio3;
|
||||||
|
|
||||||
auto ethPinObj = curPin.createNestedObject("eth");
|
auto ethPinObj = curPin["eth"].to<JsonObject>();
|
||||||
ethPinObj["enabled"] = pin.eth_enabled;
|
ethPinObj["enabled"] = pin.eth_enabled;
|
||||||
ethPinObj["phy_addr"] = pin.eth_phy_addr;
|
ethPinObj["phy_addr"] = pin.eth_phy_addr;
|
||||||
ethPinObj["power"] = pin.eth_power;
|
ethPinObj["power"] = pin.eth_power;
|
||||||
@ -59,19 +59,19 @@ void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request)
|
|||||||
ethPinObj["type"] = pin.eth_type;
|
ethPinObj["type"] = pin.eth_type;
|
||||||
ethPinObj["clk_mode"] = pin.eth_clk_mode;
|
ethPinObj["clk_mode"] = pin.eth_clk_mode;
|
||||||
|
|
||||||
auto displayPinObj = curPin.createNestedObject("display");
|
auto displayPinObj = curPin["display"].to<JsonObject>();
|
||||||
displayPinObj["type"] = pin.display_type;
|
displayPinObj["type"] = pin.display_type;
|
||||||
displayPinObj["data"] = pin.display_data;
|
displayPinObj["data"] = pin.display_data;
|
||||||
displayPinObj["clk"] = pin.display_clk;
|
displayPinObj["clk"] = pin.display_clk;
|
||||||
displayPinObj["cs"] = pin.display_cs;
|
displayPinObj["cs"] = pin.display_cs;
|
||||||
displayPinObj["reset"] = pin.display_reset;
|
displayPinObj["reset"] = pin.display_reset;
|
||||||
|
|
||||||
auto ledPinObj = curPin.createNestedObject("led");
|
auto ledPinObj = curPin["led"].to<JsonObject>();
|
||||||
for (uint8_t i = 0; i < PINMAPPING_LED_COUNT; i++) {
|
for (uint8_t i = 0; i < PINMAPPING_LED_COUNT; i++) {
|
||||||
ledPinObj["led" + String(i)] = pin.led[i];
|
ledPinObj["led" + String(i)] = pin.led[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
auto display = root.createNestedObject("display");
|
auto display = root["display"].to<JsonObject>();
|
||||||
display["rotation"] = config.Display.Rotation;
|
display["rotation"] = config.Display.Rotation;
|
||||||
display["power_safe"] = config.Display.PowerSafe;
|
display["power_safe"] = config.Display.PowerSafe;
|
||||||
display["screensaver"] = config.Display.ScreenSaver;
|
display["screensaver"] = config.Display.ScreenSaver;
|
||||||
@ -80,25 +80,25 @@ void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request)
|
|||||||
display["diagramduration"] = config.Display.Diagram.Duration;
|
display["diagramduration"] = config.Display.Diagram.Duration;
|
||||||
display["diagrammode"] = config.Display.Diagram.Mode;
|
display["diagrammode"] = config.Display.Diagram.Mode;
|
||||||
|
|
||||||
auto leds = root.createNestedArray("led");
|
auto leds = root["led"].to<JsonArray>();
|
||||||
for (uint8_t i = 0; i < PINMAPPING_LED_COUNT; i++) {
|
for (uint8_t i = 0; i < PINMAPPING_LED_COUNT; i++) {
|
||||||
auto led = leds.createNestedObject();
|
auto led = leds.add<JsonObject>();
|
||||||
led["brightness"] = config.Led_Single[i].Brightness;
|
led["brightness"] = config.Led_Single[i].Brightness;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto victronPinObj = curPin.createNestedObject("victron");
|
auto victronPinObj = curPin["victron"].to<JsonObject>();
|
||||||
victronPinObj["rx"] = pin.victron_rx;
|
victronPinObj["rx"] = pin.victron_rx;
|
||||||
victronPinObj["tx"] = pin.victron_tx;
|
victronPinObj["tx"] = pin.victron_tx;
|
||||||
victronPinObj["rx2"] = pin.victron_rx2;
|
victronPinObj["rx2"] = pin.victron_rx2;
|
||||||
victronPinObj["tx2"] = pin.victron_tx2;
|
victronPinObj["tx2"] = pin.victron_tx2;
|
||||||
|
|
||||||
JsonObject batteryPinObj = curPin.createNestedObject("battery");
|
auto batteryPinObj = curPin["battery"].to<JsonObject>();
|
||||||
batteryPinObj["rx"] = pin.battery_rx;
|
batteryPinObj["rx"] = pin.battery_rx;
|
||||||
batteryPinObj["rxen"] = pin.battery_rxen;
|
batteryPinObj["rxen"] = pin.battery_rxen;
|
||||||
batteryPinObj["tx"] = pin.battery_tx;
|
batteryPinObj["tx"] = pin.battery_tx;
|
||||||
batteryPinObj["txen"] = pin.battery_txen;
|
batteryPinObj["txen"] = pin.battery_txen;
|
||||||
|
|
||||||
JsonObject huaweiPinObj = curPin.createNestedObject("huawei");
|
auto huaweiPinObj = curPin["huawei"].to<JsonObject>();
|
||||||
huaweiPinObj["miso"] = pin.huawei_miso;
|
huaweiPinObj["miso"] = pin.huawei_miso;
|
||||||
huaweiPinObj["mosi"] = pin.huawei_mosi;
|
huaweiPinObj["mosi"] = pin.huawei_mosi;
|
||||||
huaweiPinObj["clk"] = pin.huawei_clk;
|
huaweiPinObj["clk"] = pin.huawei_clk;
|
||||||
@ -106,8 +106,7 @@ void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request)
|
|||||||
huaweiPinObj["cs"] = pin.huawei_cs;
|
huaweiPinObj["cs"] = pin.huawei_cs;
|
||||||
huaweiPinObj["power"] = pin.huawei_power;
|
huaweiPinObj["power"] = pin.huawei_power;
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
|
void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
|
||||||
@ -116,45 +115,19 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
|
JsonDocument root;
|
||||||
|
if (!WebApi.parseRequestData(request, response, root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& retMsg = response->getRoot();
|
auto& retMsg = response->getRoot();
|
||||||
retMsg["type"] = "warning";
|
|
||||||
|
|
||||||
if (!request->hasParam("data", true)) {
|
|
||||||
retMsg["message"] = "No values found!";
|
|
||||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String json = request->getParam("data", true)->value();
|
|
||||||
|
|
||||||
if (json.length() > MQTT_JSON_DOC_SIZE) {
|
|
||||||
retMsg["message"] = "Data too large!";
|
|
||||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument root(MQTT_JSON_DOC_SIZE);
|
|
||||||
const DeserializationError error = deserializeJson(root, json);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
retMsg["message"] = "Failed to parse data!";
|
|
||||||
retMsg["code"] = WebApiError::GenericParseError;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(root.containsKey("curPin")
|
if (!(root.containsKey("curPin")
|
||||||
|| root.containsKey("display"))) {
|
|| root.containsKey("display"))) {
|
||||||
retMsg["message"] = "Values are missing!";
|
retMsg["message"] = "Values are missing!";
|
||||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,8 +135,7 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Pin mapping must between 1 and " STR(DEV_MAX_MAPPING_NAME_STRLEN) " characters long!";
|
retMsg["message"] = "Pin mapping must between 1 and " STR(DEV_MAX_MAPPING_NAME_STRLEN) " characters long!";
|
||||||
retMsg["code"] = WebApiError::HardwarePinMappingLength;
|
retMsg["code"] = WebApiError::HardwarePinMappingLength;
|
||||||
retMsg["param"]["max"] = DEV_MAX_MAPPING_NAME_STRLEN;
|
retMsg["param"]["max"] = DEV_MAX_MAPPING_NAME_STRLEN;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,8 +166,7 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
WebApi.writeConfig(retMsg);
|
WebApi.writeConfig(retMsg);
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
|
|
||||||
if (performRestart) {
|
if (performRestart) {
|
||||||
Utils::restartDtu();
|
Utils::restartDtu();
|
||||||
|
|||||||
@ -23,13 +23,7 @@ void WebApiDevInfoClass::onDevInfoStatus(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
auto& root = response->getRoot();
|
auto& root = response->getRoot();
|
||||||
|
auto serial = WebApi.parseSerialFromRequest(request);
|
||||||
uint64_t serial = 0;
|
|
||||||
if (request->hasParam("inv")) {
|
|
||||||
String s = request->getParam("inv")->value();
|
|
||||||
serial = strtoll(s.c_str(), NULL, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto inv = Hoymiles.getInverterBySerial(serial);
|
auto inv = Hoymiles.getInverterBySerial(serial);
|
||||||
|
|
||||||
if (inv != nullptr) {
|
if (inv != nullptr) {
|
||||||
@ -43,6 +37,5 @@ void WebApiDevInfoClass::onDevInfoStatus(AsyncWebServerRequest* request)
|
|||||||
root["fw_build_datetime"] = inv->DevInfo()->getFwBuildDateTimeStr();
|
root["fw_build_datetime"] = inv->DevInfo()->getFwBuildDateTimeStr();
|
||||||
}
|
}
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,10 +63,10 @@ void WebApiDtuClass::onDtuAdminGet(AsyncWebServerRequest* request)
|
|||||||
root["cmt_country"] = config.Dtu.Cmt.CountryMode;
|
root["cmt_country"] = config.Dtu.Cmt.CountryMode;
|
||||||
root["cmt_chan_width"] = Hoymiles.getRadioCmt()->getChannelWidth();
|
root["cmt_chan_width"] = Hoymiles.getRadioCmt()->getChannelWidth();
|
||||||
|
|
||||||
auto data = root.createNestedArray("country_def");
|
auto data = root["country_def"].to<JsonArray>();
|
||||||
auto countryDefs = Hoymiles.getRadioCmt()->getCountryFrequencyList();
|
auto countryDefs = Hoymiles.getRadioCmt()->getCountryFrequencyList();
|
||||||
for (const auto& definition : countryDefs) {
|
for (const auto& definition : countryDefs) {
|
||||||
auto obj = data.createNestedObject();
|
auto obj = data.add<JsonObject>();
|
||||||
obj["freq_default"] = definition.definition.Freq_Default;
|
obj["freq_default"] = definition.definition.Freq_Default;
|
||||||
obj["freq_min"] = definition.definition.Freq_Min;
|
obj["freq_min"] = definition.definition.Freq_Min;
|
||||||
obj["freq_max"] = definition.definition.Freq_Max;
|
obj["freq_max"] = definition.definition.Freq_Max;
|
||||||
@ -74,8 +74,7 @@ void WebApiDtuClass::onDtuAdminGet(AsyncWebServerRequest* request)
|
|||||||
obj["freq_legal_max"] = definition.definition.Freq_Legal_Max;
|
obj["freq_legal_max"] = definition.definition.Freq_Legal_Max;
|
||||||
}
|
}
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
|
void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
|
||||||
@ -85,37 +84,12 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
|
JsonDocument root;
|
||||||
|
if (!WebApi.parseRequestData(request, response, root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& retMsg = response->getRoot();
|
auto& retMsg = response->getRoot();
|
||||||
retMsg["type"] = "warning";
|
|
||||||
|
|
||||||
if (!request->hasParam("data", true)) {
|
|
||||||
retMsg["message"] = "No values found!";
|
|
||||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String json = request->getParam("data", true)->value();
|
|
||||||
|
|
||||||
if (json.length() > 1024) {
|
|
||||||
retMsg["message"] = "Data too large!";
|
|
||||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
|
||||||
const DeserializationError error = deserializeJson(root, json);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
retMsg["message"] = "Failed to parse data!";
|
|
||||||
retMsg["code"] = WebApiError::GenericParseError;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(root.containsKey("serial")
|
if (!(root.containsKey("serial")
|
||||||
&& root.containsKey("pollinterval")
|
&& root.containsKey("pollinterval")
|
||||||
@ -126,8 +100,7 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
|
|||||||
&& root.containsKey("cmt_country"))) {
|
&& root.containsKey("cmt_country"))) {
|
||||||
retMsg["message"] = "Values are missing!";
|
retMsg["message"] = "Values are missing!";
|
||||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,40 +110,35 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
|
|||||||
if (serial == 0) {
|
if (serial == 0) {
|
||||||
retMsg["message"] = "Serial cannot be zero!";
|
retMsg["message"] = "Serial cannot be zero!";
|
||||||
retMsg["code"] = WebApiError::DtuSerialZero;
|
retMsg["code"] = WebApiError::DtuSerialZero;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root["pollinterval"].as<uint32_t>() == 0) {
|
if (root["pollinterval"].as<uint32_t>() == 0) {
|
||||||
retMsg["message"] = "Poll interval must be greater zero!";
|
retMsg["message"] = "Poll interval must be greater zero!";
|
||||||
retMsg["code"] = WebApiError::DtuPollZero;
|
retMsg["code"] = WebApiError::DtuPollZero;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root["nrf_palevel"].as<uint8_t>() > 3) {
|
if (root["nrf_palevel"].as<uint8_t>() > 3) {
|
||||||
retMsg["message"] = "Invalid power level setting!";
|
retMsg["message"] = "Invalid power level setting!";
|
||||||
retMsg["code"] = WebApiError::DtuInvalidPowerLevel;
|
retMsg["code"] = WebApiError::DtuInvalidPowerLevel;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root["cmt_palevel"].as<int8_t>() < -10 || root["cmt_palevel"].as<int8_t>() > 20) {
|
if (root["cmt_palevel"].as<int8_t>() < -10 || root["cmt_palevel"].as<int8_t>() > 20) {
|
||||||
retMsg["message"] = "Invalid power level setting!";
|
retMsg["message"] = "Invalid power level setting!";
|
||||||
retMsg["code"] = WebApiError::DtuInvalidPowerLevel;
|
retMsg["code"] = WebApiError::DtuInvalidPowerLevel;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root["cmt_country"].as<uint8_t>() >= CountryModeId_t::CountryModeId_Max) {
|
if (root["cmt_country"].as<uint8_t>() >= CountryModeId_t::CountryModeId_Max) {
|
||||||
retMsg["message"] = "Invalid country setting!";
|
retMsg["message"] = "Invalid country setting!";
|
||||||
retMsg["code"] = WebApiError::DtuInvalidCmtCountry;
|
retMsg["code"] = WebApiError::DtuInvalidCmtCountry;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,8 +151,7 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["code"] = WebApiError::DtuInvalidCmtFrequency;
|
retMsg["code"] = WebApiError::DtuInvalidCmtFrequency;
|
||||||
retMsg["param"]["min"] = FrequencyDefinition.Freq_Min;
|
retMsg["param"]["min"] = FrequencyDefinition.Freq_Min;
|
||||||
retMsg["param"]["max"] = FrequencyDefinition.Freq_Max;
|
retMsg["param"]["max"] = FrequencyDefinition.Freq_Max;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,8 +167,8 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
WebApi.writeConfig(retMsg);
|
WebApi.writeConfig(retMsg);
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
|
|
||||||
_applyDataTask.enable();
|
_applyDataTask.enable();
|
||||||
|
_applyDataTask.restart();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,14 +20,9 @@ void WebApiEventlogClass::onEventlogStatus(AsyncWebServerRequest* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 2048);
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
auto& root = response->getRoot();
|
auto& root = response->getRoot();
|
||||||
|
auto serial = WebApi.parseSerialFromRequest(request);
|
||||||
uint64_t serial = 0;
|
|
||||||
if (request->hasParam("inv")) {
|
|
||||||
String s = request->getParam("inv")->value();
|
|
||||||
serial = strtoll(s.c_str(), NULL, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
AlarmMessageLocale_t locale = AlarmMessageLocale_t::EN;
|
AlarmMessageLocale_t locale = AlarmMessageLocale_t::EN;
|
||||||
if (request->hasParam("locale")) {
|
if (request->hasParam("locale")) {
|
||||||
@ -47,10 +42,10 @@ void WebApiEventlogClass::onEventlogStatus(AsyncWebServerRequest* request)
|
|||||||
uint8_t logEntryCount = inv->EventLog()->getEntryCount();
|
uint8_t logEntryCount = inv->EventLog()->getEntryCount();
|
||||||
|
|
||||||
root["count"] = logEntryCount;
|
root["count"] = logEntryCount;
|
||||||
JsonArray eventsArray = root.createNestedArray("events");
|
JsonArray eventsArray = root["events"].to<JsonArray>();
|
||||||
|
|
||||||
for (uint8_t logEntry = 0; logEntry < logEntryCount; logEntry++) {
|
for (uint8_t logEntry = 0; logEntry < logEntryCount; logEntry++) {
|
||||||
JsonObject eventsObject = eventsArray.createNestedObject();
|
JsonObject eventsObject = eventsArray.add<JsonObject>();
|
||||||
|
|
||||||
AlarmLogEntry_t entry;
|
AlarmLogEntry_t entry;
|
||||||
inv->EventLog()->getLogEntry(logEntry, entry, locale);
|
inv->EventLog()->getLogEntry(logEntry, entry, locale);
|
||||||
@ -62,6 +57,5 @@ void WebApiEventlogClass::onEventlogStatus(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,32 +21,26 @@ void WebApiGridProfileClass::onGridProfileStatus(AsyncWebServerRequest* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 8192);
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
auto& root = response->getRoot();
|
auto& root = response->getRoot();
|
||||||
|
auto serial = WebApi.parseSerialFromRequest(request);
|
||||||
uint64_t serial = 0;
|
|
||||||
if (request->hasParam("inv")) {
|
|
||||||
String s = request->getParam("inv")->value();
|
|
||||||
serial = strtoll(s.c_str(), NULL, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto inv = Hoymiles.getInverterBySerial(serial);
|
auto inv = Hoymiles.getInverterBySerial(serial);
|
||||||
|
|
||||||
if (inv != nullptr) {
|
if (inv != nullptr) {
|
||||||
root["name"] = inv->GridProfile()->getProfileName();
|
root["name"] = inv->GridProfile()->getProfileName();
|
||||||
root["version"] = inv->GridProfile()->getProfileVersion();
|
root["version"] = inv->GridProfile()->getProfileVersion();
|
||||||
|
|
||||||
auto jsonSections = root.createNestedArray("sections");
|
auto jsonSections = root["sections"].to<JsonArray>();
|
||||||
auto profSections = inv->GridProfile()->getProfile();
|
auto profSections = inv->GridProfile()->getProfile();
|
||||||
|
|
||||||
for (auto &profSection : profSections) {
|
for (auto &profSection : profSections) {
|
||||||
auto jsonSection = jsonSections.createNestedObject();
|
auto jsonSection = jsonSections.add<JsonObject>();
|
||||||
jsonSection["name"] = profSection.SectionName;
|
jsonSection["name"] = profSection.SectionName;
|
||||||
|
|
||||||
auto jsonItems = jsonSection.createNestedArray("items");
|
auto jsonItems = jsonSection["items"].to<JsonArray>();
|
||||||
|
|
||||||
for (auto &profItem : profSection.items) {
|
for (auto &profItem : profSection.items) {
|
||||||
auto jsonItem = jsonItems.createNestedObject();
|
auto jsonItem = jsonItems.add<JsonObject>();
|
||||||
|
|
||||||
jsonItem["n"] = profItem.Name;
|
jsonItem["n"] = profItem.Name;
|
||||||
jsonItem["u"] = profItem.Unit;
|
jsonItem["u"] = profItem.Unit;
|
||||||
@ -55,8 +49,7 @@ void WebApiGridProfileClass::onGridProfileStatus(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiGridProfileClass::onGridProfileRawdata(AsyncWebServerRequest* request)
|
void WebApiGridProfileClass::onGridProfileRawdata(AsyncWebServerRequest* request)
|
||||||
@ -65,24 +58,17 @@ void WebApiGridProfileClass::onGridProfileRawdata(AsyncWebServerRequest* request
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 4096);
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
auto& root = response->getRoot();
|
auto& root = response->getRoot();
|
||||||
|
auto serial = WebApi.parseSerialFromRequest(request);
|
||||||
uint64_t serial = 0;
|
|
||||||
if (request->hasParam("inv")) {
|
|
||||||
String s = request->getParam("inv")->value();
|
|
||||||
serial = strtoll(s.c_str(), NULL, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto inv = Hoymiles.getInverterBySerial(serial);
|
auto inv = Hoymiles.getInverterBySerial(serial);
|
||||||
|
|
||||||
if (inv != nullptr) {
|
if (inv != nullptr) {
|
||||||
auto raw = root.createNestedArray("raw");
|
auto raw = root["raw"].to<JsonArray>();
|
||||||
auto data = inv->GridProfile()->getRawData();
|
auto data = inv->GridProfile()->getRawData();
|
||||||
|
|
||||||
copyArray(&data[0], data.size(), raw);
|
copyArray(&data[0], data.size(), raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,15 +29,15 @@ void WebApiInverterClass::onInverterList(AsyncWebServerRequest* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 768 * INV_MAX_COUNT);
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
auto& root = response->getRoot();
|
auto& root = response->getRoot();
|
||||||
JsonArray data = root.createNestedArray("inverter");
|
JsonArray data = root["inverter"].to<JsonArray>();
|
||||||
|
|
||||||
const CONFIG_T& config = Configuration.get();
|
const CONFIG_T& config = Configuration.get();
|
||||||
|
|
||||||
for (uint8_t i = 0; i < INV_MAX_COUNT; i++) {
|
for (uint8_t i = 0; i < INV_MAX_COUNT; i++) {
|
||||||
if (config.Inverter[i].Serial > 0) {
|
if (config.Inverter[i].Serial > 0) {
|
||||||
JsonObject obj = data.createNestedObject();
|
JsonObject obj = data.add<JsonObject>();
|
||||||
obj["id"] = i;
|
obj["id"] = i;
|
||||||
obj["name"] = String(config.Inverter[i].Name);
|
obj["name"] = String(config.Inverter[i].Name);
|
||||||
obj["order"] = config.Inverter[i].Order;
|
obj["order"] = config.Inverter[i].Order;
|
||||||
@ -67,9 +67,9 @@ void WebApiInverterClass::onInverterList(AsyncWebServerRequest* request)
|
|||||||
max_channels = inv->Statistics()->getChannelsByType(TYPE_DC).size();
|
max_channels = inv->Statistics()->getChannelsByType(TYPE_DC).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArray channel = obj.createNestedArray("channel");
|
JsonArray channel = obj["channel"].to<JsonArray>();
|
||||||
for (uint8_t c = 0; c < max_channels; c++) {
|
for (uint8_t c = 0; c < max_channels; c++) {
|
||||||
JsonObject chanData = channel.createNestedObject();
|
JsonObject chanData = channel.add<JsonObject>();
|
||||||
chanData["name"] = config.Inverter[i].channel[c].Name;
|
chanData["name"] = config.Inverter[i].channel[c].Name;
|
||||||
chanData["max_power"] = config.Inverter[i].channel[c].MaxChannelPower;
|
chanData["max_power"] = config.Inverter[i].channel[c].MaxChannelPower;
|
||||||
chanData["yield_total_offset"] = config.Inverter[i].channel[c].YieldTotalOffset;
|
chanData["yield_total_offset"] = config.Inverter[i].channel[c].YieldTotalOffset;
|
||||||
@ -77,8 +77,7 @@ void WebApiInverterClass::onInverterList(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
|
void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
|
||||||
@ -88,44 +87,18 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
|
JsonDocument root;
|
||||||
|
if (!WebApi.parseRequestData(request, response, root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& retMsg = response->getRoot();
|
auto& retMsg = response->getRoot();
|
||||||
retMsg["type"] = "warning";
|
|
||||||
|
|
||||||
if (!request->hasParam("data", true)) {
|
|
||||||
retMsg["message"] = "No values found!";
|
|
||||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String json = request->getParam("data", true)->value();
|
|
||||||
|
|
||||||
if (json.length() > 1024) {
|
|
||||||
retMsg["message"] = "Data too large!";
|
|
||||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
|
||||||
const DeserializationError error = deserializeJson(root, json);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
retMsg["message"] = "Failed to parse data!";
|
|
||||||
retMsg["code"] = WebApiError::GenericParseError;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(root.containsKey("serial")
|
if (!(root.containsKey("serial")
|
||||||
&& root.containsKey("name"))) {
|
&& root.containsKey("name"))) {
|
||||||
retMsg["message"] = "Values are missing!";
|
retMsg["message"] = "Values are missing!";
|
||||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,8 +108,7 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
|
|||||||
if (serial == 0) {
|
if (serial == 0) {
|
||||||
retMsg["message"] = "Serial must be a number > 0!";
|
retMsg["message"] = "Serial must be a number > 0!";
|
||||||
retMsg["code"] = WebApiError::InverterSerialZero;
|
retMsg["code"] = WebApiError::InverterSerialZero;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,8 +116,7 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Name must between 1 and " STR(INV_MAX_NAME_STRLEN) " characters long!";
|
retMsg["message"] = "Name must between 1 and " STR(INV_MAX_NAME_STRLEN) " characters long!";
|
||||||
retMsg["code"] = WebApiError::InverterNameLength;
|
retMsg["code"] = WebApiError::InverterNameLength;
|
||||||
retMsg["param"]["max"] = INV_MAX_NAME_STRLEN;
|
retMsg["param"]["max"] = INV_MAX_NAME_STRLEN;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,8 +126,7 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Only " STR(INV_MAX_COUNT) " inverters are supported!";
|
retMsg["message"] = "Only " STR(INV_MAX_COUNT) " inverters are supported!";
|
||||||
retMsg["code"] = WebApiError::InverterCount;
|
retMsg["code"] = WebApiError::InverterCount;
|
||||||
retMsg["param"]["max"] = INV_MAX_COUNT;
|
retMsg["param"]["max"] = INV_MAX_COUNT;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,8 +137,7 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
WebApi.writeConfig(retMsg, WebApiError::InverterAdded, "Inverter created!");
|
WebApi.writeConfig(retMsg, WebApiError::InverterAdded, "Inverter created!");
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
|
|
||||||
auto inv = Hoymiles.addInverter(inverter->Name, inverter->Serial);
|
auto inv = Hoymiles.addInverter(inverter->Name, inverter->Serial);
|
||||||
|
|
||||||
@ -188,51 +157,24 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
|
JsonDocument root;
|
||||||
|
if (!WebApi.parseRequestData(request, response, root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& retMsg = response->getRoot();
|
auto& retMsg = response->getRoot();
|
||||||
retMsg["type"] = "warning";
|
|
||||||
|
|
||||||
if (!request->hasParam("data", true)) {
|
|
||||||
retMsg["message"] = "No values found!";
|
|
||||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String json = request->getParam("data", true)->value();
|
|
||||||
|
|
||||||
if (json.length() > 1024) {
|
|
||||||
retMsg["message"] = "Data too large!";
|
|
||||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
|
||||||
const DeserializationError error = deserializeJson(root, json);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
retMsg["message"] = "Failed to parse data!";
|
|
||||||
retMsg["code"] = WebApiError::GenericParseError;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(root.containsKey("id") && root.containsKey("serial") && root.containsKey("name") && root.containsKey("channel"))) {
|
if (!(root.containsKey("id") && root.containsKey("serial") && root.containsKey("name") && root.containsKey("channel"))) {
|
||||||
retMsg["message"] = "Values are missing!";
|
retMsg["message"] = "Values are missing!";
|
||||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root["id"].as<uint8_t>() > INV_MAX_COUNT - 1) {
|
if (root["id"].as<uint8_t>() > INV_MAX_COUNT - 1) {
|
||||||
retMsg["message"] = "Invalid ID specified!";
|
retMsg["message"] = "Invalid ID specified!";
|
||||||
retMsg["code"] = WebApiError::InverterInvalidId;
|
retMsg["code"] = WebApiError::InverterInvalidId;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,8 +184,7 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
|
|||||||
if (serial == 0) {
|
if (serial == 0) {
|
||||||
retMsg["message"] = "Serial must be a number > 0!";
|
retMsg["message"] = "Serial must be a number > 0!";
|
||||||
retMsg["code"] = WebApiError::InverterSerialZero;
|
retMsg["code"] = WebApiError::InverterSerialZero;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,8 +192,7 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Name must between 1 and " STR(INV_MAX_NAME_STRLEN) " characters long!";
|
retMsg["message"] = "Name must between 1 and " STR(INV_MAX_NAME_STRLEN) " characters long!";
|
||||||
retMsg["code"] = WebApiError::InverterNameLength;
|
retMsg["code"] = WebApiError::InverterNameLength;
|
||||||
retMsg["param"]["max"] = INV_MAX_NAME_STRLEN;
|
retMsg["param"]["max"] = INV_MAX_NAME_STRLEN;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,8 +200,7 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
|
|||||||
if (channelArray.size() == 0 || channelArray.size() > INV_MAX_CHAN_COUNT) {
|
if (channelArray.size() == 0 || channelArray.size() > INV_MAX_CHAN_COUNT) {
|
||||||
retMsg["message"] = "Invalid amount of max channel setting given!";
|
retMsg["message"] = "Invalid amount of max channel setting given!";
|
||||||
retMsg["code"] = WebApiError::InverterInvalidMaxChannel;
|
retMsg["code"] = WebApiError::InverterInvalidMaxChannel;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,8 +232,7 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
WebApi.writeConfig(retMsg, WebApiError::InverterChanged, "Inverter changed!");
|
WebApi.writeConfig(retMsg, WebApiError::InverterChanged, "Inverter changed!");
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
|
|
||||||
std::shared_ptr<InverterAbstract> inv = Hoymiles.getInverterBySerial(old_serial);
|
std::shared_ptr<InverterAbstract> inv = Hoymiles.getInverterBySerial(old_serial);
|
||||||
|
|
||||||
@ -333,51 +271,24 @@ void WebApiInverterClass::onInverterDelete(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
|
JsonDocument root;
|
||||||
|
if (!WebApi.parseRequestData(request, response, root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& retMsg = response->getRoot();
|
auto& retMsg = response->getRoot();
|
||||||
retMsg["type"] = "warning";
|
|
||||||
|
|
||||||
if (!request->hasParam("data", true)) {
|
|
||||||
retMsg["message"] = "No values found!";
|
|
||||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String json = request->getParam("data", true)->value();
|
|
||||||
|
|
||||||
if (json.length() > 1024) {
|
|
||||||
retMsg["message"] = "Data too large!";
|
|
||||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
|
||||||
const DeserializationError error = deserializeJson(root, json);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
retMsg["message"] = "Failed to parse data!";
|
|
||||||
retMsg["code"] = WebApiError::GenericParseError;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(root.containsKey("id"))) {
|
if (!(root.containsKey("id"))) {
|
||||||
retMsg["message"] = "Values are missing!";
|
retMsg["message"] = "Values are missing!";
|
||||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root["id"].as<uint8_t>() > INV_MAX_COUNT - 1) {
|
if (root["id"].as<uint8_t>() > INV_MAX_COUNT - 1) {
|
||||||
retMsg["message"] = "Invalid ID specified!";
|
retMsg["message"] = "Invalid ID specified!";
|
||||||
retMsg["code"] = WebApiError::InverterInvalidId;
|
retMsg["code"] = WebApiError::InverterInvalidId;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,8 +301,7 @@ void WebApiInverterClass::onInverterDelete(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
WebApi.writeConfig(retMsg, WebApiError::InverterDeleted, "Inverter deleted!");
|
WebApi.writeConfig(retMsg, WebApiError::InverterDeleted, "Inverter deleted!");
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
|
|
||||||
MqttHandleHass.forceUpdate();
|
MqttHandleHass.forceUpdate();
|
||||||
}
|
}
|
||||||
@ -403,43 +313,17 @@ void WebApiInverterClass::onInverterOrder(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
|
JsonDocument root;
|
||||||
|
if (!WebApi.parseRequestData(request, response, root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& retMsg = response->getRoot();
|
auto& retMsg = response->getRoot();
|
||||||
retMsg["type"] = "warning";
|
|
||||||
|
|
||||||
if (!request->hasParam("data", true)) {
|
|
||||||
retMsg["message"] = "No values found!";
|
|
||||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String json = request->getParam("data", true)->value();
|
|
||||||
|
|
||||||
if (json.length() > 1024) {
|
|
||||||
retMsg["message"] = "Data too large!";
|
|
||||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
|
||||||
const DeserializationError error = deserializeJson(root, json);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
retMsg["message"] = "Failed to parse data!";
|
|
||||||
retMsg["code"] = WebApiError::GenericParseError;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(root.containsKey("order"))) {
|
if (!(root.containsKey("order"))) {
|
||||||
retMsg["message"] = "Values are missing!";
|
retMsg["message"] = "Values are missing!";
|
||||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,6 +341,5 @@ void WebApiInverterClass::onInverterOrder(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
WebApi.writeConfig(retMsg, WebApiError::InverterOrdered, "Inverter order saved!");
|
WebApi.writeConfig(retMsg, WebApiError::InverterOrdered, "Inverter order saved!");
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,8 +47,7 @@ void WebApiLimitClass::onLimitStatus(AsyncWebServerRequest* request)
|
|||||||
root[serial]["limit_set_status"] = limitStatus;
|
root[serial]["limit_set_status"] = limitStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
|
void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
|
||||||
@ -58,45 +57,19 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
|
JsonDocument root;
|
||||||
|
if (!WebApi.parseRequestData(request, response, root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& retMsg = response->getRoot();
|
auto& retMsg = response->getRoot();
|
||||||
retMsg["type"] = "warning";
|
|
||||||
|
|
||||||
if (!request->hasParam("data", true)) {
|
|
||||||
retMsg["message"] = "No values found!";
|
|
||||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String json = request->getParam("data", true)->value();
|
|
||||||
|
|
||||||
if (json.length() > 1024) {
|
|
||||||
retMsg["message"] = "Data too large!";
|
|
||||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
|
||||||
const DeserializationError error = deserializeJson(root, json);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
retMsg["message"] = "Failed to parse data!";
|
|
||||||
retMsg["code"] = WebApiError::GenericParseError;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(root.containsKey("serial")
|
if (!(root.containsKey("serial")
|
||||||
&& root.containsKey("limit_value")
|
&& root.containsKey("limit_value")
|
||||||
&& root.containsKey("limit_type"))) {
|
&& root.containsKey("limit_type"))) {
|
||||||
retMsg["message"] = "Values are missing!";
|
retMsg["message"] = "Values are missing!";
|
||||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,8 +79,7 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
|
|||||||
if (serial == 0) {
|
if (serial == 0) {
|
||||||
retMsg["message"] = "Serial must be a number > 0!";
|
retMsg["message"] = "Serial must be a number > 0!";
|
||||||
retMsg["code"] = WebApiError::LimitSerialZero;
|
retMsg["code"] = WebApiError::LimitSerialZero;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,8 +87,7 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Limit must between 0 and " STR(MAX_INVERTER_LIMIT) "!";
|
retMsg["message"] = "Limit must between 0 and " STR(MAX_INVERTER_LIMIT) "!";
|
||||||
retMsg["code"] = WebApiError::LimitInvalidLimit;
|
retMsg["code"] = WebApiError::LimitInvalidLimit;
|
||||||
retMsg["param"]["max"] = MAX_INVERTER_LIMIT;
|
retMsg["param"]["max"] = MAX_INVERTER_LIMIT;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,8 +98,7 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
retMsg["message"] = "Invalid type specified!";
|
retMsg["message"] = "Invalid type specified!";
|
||||||
retMsg["code"] = WebApiError::LimitInvalidType;
|
retMsg["code"] = WebApiError::LimitInvalidType;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,8 +109,7 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
|
|||||||
if (inv == nullptr) {
|
if (inv == nullptr) {
|
||||||
retMsg["message"] = "Invalid inverter specified!";
|
retMsg["message"] = "Invalid inverter specified!";
|
||||||
retMsg["code"] = WebApiError::LimitInvalidInverter;
|
retMsg["code"] = WebApiError::LimitInvalidInverter;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +119,5 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Settings saved!";
|
retMsg["message"] = "Settings saved!";
|
||||||
retMsg["code"] = WebApiError::GenericSuccess;
|
retMsg["code"] = WebApiError::GenericSuccess;
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,44 +22,18 @@ void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
|
JsonDocument root;
|
||||||
|
if (!WebApi.parseRequestData(request, response, root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& retMsg = response->getRoot();
|
auto& retMsg = response->getRoot();
|
||||||
retMsg["type"] = "warning";
|
|
||||||
|
|
||||||
if (!request->hasParam("data", true)) {
|
|
||||||
retMsg["message"] = "No values found!";
|
|
||||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String json = request->getParam("data", true)->value();
|
|
||||||
|
|
||||||
if (json.length() > MQTT_JSON_DOC_SIZE) {
|
|
||||||
retMsg["message"] = "Data too large!";
|
|
||||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument root(MQTT_JSON_DOC_SIZE);
|
|
||||||
const DeserializationError error = deserializeJson(root, json);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
retMsg["message"] = "Failed to parse data!";
|
|
||||||
retMsg["code"] = WebApiError::GenericParseError;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(root.containsKey("reboot"))) {
|
if (!(root.containsKey("reboot"))) {
|
||||||
retMsg["message"] = "Values are missing!";
|
retMsg["message"] = "Values are missing!";
|
||||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,14 +42,12 @@ void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Reboot triggered!";
|
retMsg["message"] = "Reboot triggered!";
|
||||||
retMsg["code"] = WebApiError::MaintenanceRebootTriggered;
|
retMsg["code"] = WebApiError::MaintenanceRebootTriggered;
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
Utils::restartDtu();
|
Utils::restartDtu();
|
||||||
} else {
|
} else {
|
||||||
retMsg["message"] = "Reboot cancled!";
|
retMsg["message"] = "Reboot cancled!";
|
||||||
retMsg["code"] = WebApiError::MaintenanceRebootCancled;
|
retMsg["code"] = WebApiError::MaintenanceRebootCancled;
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,7 @@ void WebApiMqttClass::onMqttStatus(AsyncWebServerRequest* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
auto& root = response->getRoot();
|
auto& root = response->getRoot();
|
||||||
const CONFIG_T& config = Configuration.get();
|
const CONFIG_T& config = Configuration.get();
|
||||||
|
|
||||||
@ -55,8 +55,7 @@ void WebApiMqttClass::onMqttStatus(AsyncWebServerRequest* request)
|
|||||||
root["mqtt_hass_topic"] = config.Mqtt.Hass.Topic;
|
root["mqtt_hass_topic"] = config.Mqtt.Hass.Topic;
|
||||||
root["mqtt_hass_individualpanels"] = config.Mqtt.Hass.IndividualPanels;
|
root["mqtt_hass_individualpanels"] = config.Mqtt.Hass.IndividualPanels;
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiMqttClass::onMqttAdminGet(AsyncWebServerRequest* request)
|
void WebApiMqttClass::onMqttAdminGet(AsyncWebServerRequest* request)
|
||||||
@ -65,7 +64,7 @@ void WebApiMqttClass::onMqttAdminGet(AsyncWebServerRequest* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
auto& root = response->getRoot();
|
auto& root = response->getRoot();
|
||||||
const CONFIG_T& config = Configuration.get();
|
const CONFIG_T& config = Configuration.get();
|
||||||
|
|
||||||
@ -94,8 +93,7 @@ void WebApiMqttClass::onMqttAdminGet(AsyncWebServerRequest* request)
|
|||||||
root["mqtt_hass_topic"] = config.Mqtt.Hass.Topic;
|
root["mqtt_hass_topic"] = config.Mqtt.Hass.Topic;
|
||||||
root["mqtt_hass_individualpanels"] = config.Mqtt.Hass.IndividualPanels;
|
root["mqtt_hass_individualpanels"] = config.Mqtt.Hass.IndividualPanels;
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
||||||
@ -104,38 +102,13 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
|
JsonDocument root;
|
||||||
|
if (!WebApi.parseRequestData(request, response, root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& retMsg = response->getRoot();
|
auto& retMsg = response->getRoot();
|
||||||
retMsg["type"] = "warning";
|
|
||||||
|
|
||||||
if (!request->hasParam("data", true)) {
|
|
||||||
retMsg["message"] = "No values found!";
|
|
||||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String json = request->getParam("data", true)->value();
|
|
||||||
|
|
||||||
if (json.length() > MQTT_JSON_DOC_SIZE) {
|
|
||||||
retMsg["message"] = "Data too large!";
|
|
||||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument root(MQTT_JSON_DOC_SIZE);
|
|
||||||
const DeserializationError error = deserializeJson(root, json);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
retMsg["message"] = "Failed to parse data!";
|
|
||||||
retMsg["code"] = WebApiError::GenericParseError;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(root.containsKey("mqtt_enabled")
|
if (!(root.containsKey("mqtt_enabled")
|
||||||
&& root.containsKey("mqtt_verbose_logging")
|
&& root.containsKey("mqtt_verbose_logging")
|
||||||
@ -162,8 +135,7 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
|||||||
&& root.containsKey("mqtt_hass_individualpanels"))) {
|
&& root.containsKey("mqtt_hass_individualpanels"))) {
|
||||||
retMsg["message"] = "Values are missing!";
|
retMsg["message"] = "Values are missing!";
|
||||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,8 +144,7 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "MqTT Server must between 1 and " STR(MQTT_MAX_HOSTNAME_STRLEN) " characters long!";
|
retMsg["message"] = "MqTT Server must between 1 and " STR(MQTT_MAX_HOSTNAME_STRLEN) " characters long!";
|
||||||
retMsg["code"] = WebApiError::MqttHostnameLength;
|
retMsg["code"] = WebApiError::MqttHostnameLength;
|
||||||
retMsg["param"]["max"] = MQTT_MAX_HOSTNAME_STRLEN;
|
retMsg["param"]["max"] = MQTT_MAX_HOSTNAME_STRLEN;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,48 +152,42 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Username must not be longer than " STR(MQTT_MAX_USERNAME_STRLEN) " characters!";
|
retMsg["message"] = "Username must not be longer than " STR(MQTT_MAX_USERNAME_STRLEN) " characters!";
|
||||||
retMsg["code"] = WebApiError::MqttUsernameLength;
|
retMsg["code"] = WebApiError::MqttUsernameLength;
|
||||||
retMsg["param"]["max"] = MQTT_MAX_USERNAME_STRLEN;
|
retMsg["param"]["max"] = MQTT_MAX_USERNAME_STRLEN;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (root["mqtt_password"].as<String>().length() > MQTT_MAX_PASSWORD_STRLEN) {
|
if (root["mqtt_password"].as<String>().length() > MQTT_MAX_PASSWORD_STRLEN) {
|
||||||
retMsg["message"] = "Password must not be longer than " STR(MQTT_MAX_PASSWORD_STRLEN) " characters!";
|
retMsg["message"] = "Password must not be longer than " STR(MQTT_MAX_PASSWORD_STRLEN) " characters!";
|
||||||
retMsg["code"] = WebApiError::MqttPasswordLength;
|
retMsg["code"] = WebApiError::MqttPasswordLength;
|
||||||
retMsg["param"]["max"] = MQTT_MAX_PASSWORD_STRLEN;
|
retMsg["param"]["max"] = MQTT_MAX_PASSWORD_STRLEN;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (root["mqtt_topic"].as<String>().length() > MQTT_MAX_TOPIC_STRLEN) {
|
if (root["mqtt_topic"].as<String>().length() > MQTT_MAX_TOPIC_STRLEN) {
|
||||||
retMsg["message"] = "Topic must not be longer than " STR(MQTT_MAX_TOPIC_STRLEN) " characters!";
|
retMsg["message"] = "Topic must not be longer than " STR(MQTT_MAX_TOPIC_STRLEN) " characters!";
|
||||||
retMsg["code"] = WebApiError::MqttTopicLength;
|
retMsg["code"] = WebApiError::MqttTopicLength;
|
||||||
retMsg["param"]["max"] = MQTT_MAX_TOPIC_STRLEN;
|
retMsg["param"]["max"] = MQTT_MAX_TOPIC_STRLEN;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root["mqtt_topic"].as<String>().indexOf(' ') != -1) {
|
if (root["mqtt_topic"].as<String>().indexOf(' ') != -1) {
|
||||||
retMsg["message"] = "Topic must not contain space characters!";
|
retMsg["message"] = "Topic must not contain space characters!";
|
||||||
retMsg["code"] = WebApiError::MqttTopicCharacter;
|
retMsg["code"] = WebApiError::MqttTopicCharacter;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!root["mqtt_topic"].as<String>().endsWith("/")) {
|
if (!root["mqtt_topic"].as<String>().endsWith("/")) {
|
||||||
retMsg["message"] = "Topic must end with a slash (/)!";
|
retMsg["message"] = "Topic must end with a slash (/)!";
|
||||||
retMsg["code"] = WebApiError::MqttTopicTrailingSlash;
|
retMsg["code"] = WebApiError::MqttTopicTrailingSlash;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root["mqtt_port"].as<uint>() == 0 || root["mqtt_port"].as<uint>() > 65535) {
|
if (root["mqtt_port"].as<uint>() == 0 || root["mqtt_port"].as<uint>() > 65535) {
|
||||||
retMsg["message"] = "Port must be a number between 1 and 65535!";
|
retMsg["message"] = "Port must be a number between 1 and 65535!";
|
||||||
retMsg["code"] = WebApiError::MqttPort;
|
retMsg["code"] = WebApiError::MqttPort;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,8 +197,7 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Certificates must not be longer than " STR(MQTT_MAX_CERT_STRLEN) " characters!";
|
retMsg["message"] = "Certificates must not be longer than " STR(MQTT_MAX_CERT_STRLEN) " characters!";
|
||||||
retMsg["code"] = WebApiError::MqttCertificateLength;
|
retMsg["code"] = WebApiError::MqttCertificateLength;
|
||||||
retMsg["param"]["max"] = MQTT_MAX_CERT_STRLEN;
|
retMsg["param"]["max"] = MQTT_MAX_CERT_STRLEN;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,16 +205,14 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "LWT topic must not be longer than " STR(MQTT_MAX_TOPIC_STRLEN) " characters!";
|
retMsg["message"] = "LWT topic must not be longer than " STR(MQTT_MAX_TOPIC_STRLEN) " characters!";
|
||||||
retMsg["code"] = WebApiError::MqttLwtTopicLength;
|
retMsg["code"] = WebApiError::MqttLwtTopicLength;
|
||||||
retMsg["param"]["max"] = MQTT_MAX_TOPIC_STRLEN;
|
retMsg["param"]["max"] = MQTT_MAX_TOPIC_STRLEN;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root["mqtt_lwt_topic"].as<String>().indexOf(' ') != -1) {
|
if (root["mqtt_lwt_topic"].as<String>().indexOf(' ') != -1) {
|
||||||
retMsg["message"] = "LWT topic must not contain space characters!";
|
retMsg["message"] = "LWT topic must not contain space characters!";
|
||||||
retMsg["code"] = WebApiError::MqttLwtTopicCharacter;
|
retMsg["code"] = WebApiError::MqttLwtTopicCharacter;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,8 +220,7 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "LWT online value must not be longer than " STR(MQTT_MAX_LWTVALUE_STRLEN) " characters!";
|
retMsg["message"] = "LWT online value must not be longer than " STR(MQTT_MAX_LWTVALUE_STRLEN) " characters!";
|
||||||
retMsg["code"] = WebApiError::MqttLwtOnlineLength;
|
retMsg["code"] = WebApiError::MqttLwtOnlineLength;
|
||||||
retMsg["param"]["max"] = MQTT_MAX_LWTVALUE_STRLEN;
|
retMsg["param"]["max"] = MQTT_MAX_LWTVALUE_STRLEN;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,8 +228,7 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "LWT offline value must not be longer than " STR(MQTT_MAX_LWTVALUE_STRLEN) " characters!";
|
retMsg["message"] = "LWT offline value must not be longer than " STR(MQTT_MAX_LWTVALUE_STRLEN) " characters!";
|
||||||
retMsg["code"] = WebApiError::MqttLwtOfflineLength;
|
retMsg["code"] = WebApiError::MqttLwtOfflineLength;
|
||||||
retMsg["param"]["max"] = MQTT_MAX_LWTVALUE_STRLEN;
|
retMsg["param"]["max"] = MQTT_MAX_LWTVALUE_STRLEN;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,8 +236,7 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "LWT QoS must not be greater than " STR(2) "!";
|
retMsg["message"] = "LWT QoS must not be greater than " STR(2) "!";
|
||||||
retMsg["code"] = WebApiError::MqttLwtQos;
|
retMsg["code"] = WebApiError::MqttLwtQos;
|
||||||
retMsg["param"]["max"] = 2;
|
retMsg["param"]["max"] = 2;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,8 +245,7 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["code"] = WebApiError::MqttPublishInterval;
|
retMsg["code"] = WebApiError::MqttPublishInterval;
|
||||||
retMsg["param"]["min"] = 5;
|
retMsg["param"]["min"] = 5;
|
||||||
retMsg["param"]["max"] = 65535;
|
retMsg["param"]["max"] = 65535;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,16 +254,14 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Hass topic must not be longer than " STR(MQTT_MAX_TOPIC_STRLEN) " characters!";
|
retMsg["message"] = "Hass topic must not be longer than " STR(MQTT_MAX_TOPIC_STRLEN) " characters!";
|
||||||
retMsg["code"] = WebApiError::MqttHassTopicLength;
|
retMsg["code"] = WebApiError::MqttHassTopicLength;
|
||||||
retMsg["param"]["max"] = MQTT_MAX_TOPIC_STRLEN;
|
retMsg["param"]["max"] = MQTT_MAX_TOPIC_STRLEN;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root["mqtt_hass_topic"].as<String>().indexOf(' ') != -1) {
|
if (root["mqtt_hass_topic"].as<String>().indexOf(' ') != -1) {
|
||||||
retMsg["message"] = "Hass topic must not contain space characters!";
|
retMsg["message"] = "Hass topic must not contain space characters!";
|
||||||
retMsg["code"] = WebApiError::MqttHassTopicCharacter;
|
retMsg["code"] = WebApiError::MqttHassTopicCharacter;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -339,8 +295,7 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
WebApi.writeConfig(retMsg);
|
WebApi.writeConfig(retMsg);
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
|
|
||||||
MqttSettings.performReconnect();
|
MqttSettings.performReconnect();
|
||||||
MqttHandleHass.forceUpdate();
|
MqttHandleHass.forceUpdate();
|
||||||
|
|||||||
@ -46,8 +46,7 @@ void WebApiNetworkClass::onNetworkStatus(AsyncWebServerRequest* request)
|
|||||||
root["ap_mac"] = WiFi.softAPmacAddress();
|
root["ap_mac"] = WiFi.softAPmacAddress();
|
||||||
root["ap_stationnum"] = WiFi.softAPgetStationNum();
|
root["ap_stationnum"] = WiFi.softAPgetStationNum();
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiNetworkClass::onNetworkAdminGet(AsyncWebServerRequest* request)
|
void WebApiNetworkClass::onNetworkAdminGet(AsyncWebServerRequest* request)
|
||||||
@ -72,8 +71,7 @@ void WebApiNetworkClass::onNetworkAdminGet(AsyncWebServerRequest* request)
|
|||||||
root["aptimeout"] = config.WiFi.ApTimeout;
|
root["aptimeout"] = config.WiFi.ApTimeout;
|
||||||
root["mdnsenabled"] = config.Mdns.Enabled;
|
root["mdnsenabled"] = config.Mdns.Enabled;
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
|
void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
|
||||||
@ -83,37 +81,12 @@ void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
|
JsonDocument root;
|
||||||
|
if (!WebApi.parseRequestData(request, response, root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& retMsg = response->getRoot();
|
auto& retMsg = response->getRoot();
|
||||||
retMsg["type"] = "warning";
|
|
||||||
|
|
||||||
if (!request->hasParam("data", true)) {
|
|
||||||
retMsg["message"] = "No values found!";
|
|
||||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String json = request->getParam("data", true)->value();
|
|
||||||
|
|
||||||
if (json.length() > 1024) {
|
|
||||||
retMsg["message"] = "Data too large!";
|
|
||||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
|
||||||
const DeserializationError error = deserializeJson(root, json);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
retMsg["message"] = "Failed to parse data!";
|
|
||||||
retMsg["code"] = WebApiError::GenericParseError;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(root.containsKey("ssid")
|
if (!(root.containsKey("ssid")
|
||||||
&& root.containsKey("password")
|
&& root.containsKey("password")
|
||||||
@ -127,8 +100,7 @@ void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
|
|||||||
&& root.containsKey("aptimeout"))) {
|
&& root.containsKey("aptimeout"))) {
|
||||||
retMsg["message"] = "Values are missing!";
|
retMsg["message"] = "Values are missing!";
|
||||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,68 +108,59 @@ void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
|
|||||||
if (!ipaddress.fromString(root["ipaddress"].as<String>())) {
|
if (!ipaddress.fromString(root["ipaddress"].as<String>())) {
|
||||||
retMsg["message"] = "IP address is invalid!";
|
retMsg["message"] = "IP address is invalid!";
|
||||||
retMsg["code"] = WebApiError::NetworkIpInvalid;
|
retMsg["code"] = WebApiError::NetworkIpInvalid;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
IPAddress netmask;
|
IPAddress netmask;
|
||||||
if (!netmask.fromString(root["netmask"].as<String>())) {
|
if (!netmask.fromString(root["netmask"].as<String>())) {
|
||||||
retMsg["message"] = "Netmask is invalid!";
|
retMsg["message"] = "Netmask is invalid!";
|
||||||
retMsg["code"] = WebApiError::NetworkNetmaskInvalid;
|
retMsg["code"] = WebApiError::NetworkNetmaskInvalid;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
IPAddress gateway;
|
IPAddress gateway;
|
||||||
if (!gateway.fromString(root["gateway"].as<String>())) {
|
if (!gateway.fromString(root["gateway"].as<String>())) {
|
||||||
retMsg["message"] = "Gateway is invalid!";
|
retMsg["message"] = "Gateway is invalid!";
|
||||||
retMsg["code"] = WebApiError::NetworkGatewayInvalid;
|
retMsg["code"] = WebApiError::NetworkGatewayInvalid;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
IPAddress dns1;
|
IPAddress dns1;
|
||||||
if (!dns1.fromString(root["dns1"].as<String>())) {
|
if (!dns1.fromString(root["dns1"].as<String>())) {
|
||||||
retMsg["message"] = "DNS Server IP 1 is invalid!";
|
retMsg["message"] = "DNS Server IP 1 is invalid!";
|
||||||
retMsg["code"] = WebApiError::NetworkDns1Invalid;
|
retMsg["code"] = WebApiError::NetworkDns1Invalid;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
IPAddress dns2;
|
IPAddress dns2;
|
||||||
if (!dns2.fromString(root["dns2"].as<String>())) {
|
if (!dns2.fromString(root["dns2"].as<String>())) {
|
||||||
retMsg["message"] = "DNS Server IP 2 is invalid!";
|
retMsg["message"] = "DNS Server IP 2 is invalid!";
|
||||||
retMsg["code"] = WebApiError::NetworkDns2Invalid;
|
retMsg["code"] = WebApiError::NetworkDns2Invalid;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root["hostname"].as<String>().length() == 0 || root["hostname"].as<String>().length() > WIFI_MAX_HOSTNAME_STRLEN) {
|
if (root["hostname"].as<String>().length() == 0 || root["hostname"].as<String>().length() > WIFI_MAX_HOSTNAME_STRLEN) {
|
||||||
retMsg["message"] = "Hostname must between 1 and " STR(WIFI_MAX_HOSTNAME_STRLEN) " characters long!";
|
retMsg["message"] = "Hostname must between 1 and " STR(WIFI_MAX_HOSTNAME_STRLEN) " characters long!";
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (NetworkSettings.NetworkMode() == network_mode::WiFi) {
|
if (NetworkSettings.NetworkMode() == network_mode::WiFi) {
|
||||||
if (root["ssid"].as<String>().length() == 0 || root["ssid"].as<String>().length() > WIFI_MAX_SSID_STRLEN) {
|
if (root["ssid"].as<String>().length() == 0 || root["ssid"].as<String>().length() > WIFI_MAX_SSID_STRLEN) {
|
||||||
retMsg["message"] = "SSID must between 1 and " STR(WIFI_MAX_SSID_STRLEN) " characters long!";
|
retMsg["message"] = "SSID must between 1 and " STR(WIFI_MAX_SSID_STRLEN) " characters long!";
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (root["password"].as<String>().length() > WIFI_MAX_PASSWORD_STRLEN - 1) {
|
if (root["password"].as<String>().length() > WIFI_MAX_PASSWORD_STRLEN - 1) {
|
||||||
retMsg["message"] = "Password must not be longer than " STR(WIFI_MAX_PASSWORD_STRLEN) " characters long!";
|
retMsg["message"] = "Password must not be longer than " STR(WIFI_MAX_PASSWORD_STRLEN) " characters long!";
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (root["aptimeout"].as<uint>() > 99999) {
|
if (root["aptimeout"].as<uint>() > 99999) {
|
||||||
retMsg["message"] = "ApTimeout must be a number between 0 and 99999!";
|
retMsg["message"] = "ApTimeout must be a number between 0 and 99999!";
|
||||||
retMsg["code"] = WebApiError::NetworkApTimeoutInvalid;
|
retMsg["code"] = WebApiError::NetworkApTimeoutInvalid;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,8 +198,7 @@ void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
WebApi.writeConfig(retMsg);
|
WebApi.writeConfig(retMsg);
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
|
|
||||||
NetworkSettings.enableAdminMode();
|
NetworkSettings.enableAdminMode();
|
||||||
NetworkSettings.applyConfig();
|
NetworkSettings.applyConfig();
|
||||||
|
|||||||
@ -63,8 +63,7 @@ void WebApiNtpClass::onNtpStatus(AsyncWebServerRequest* request)
|
|||||||
root["sun_isSunsetAvailable"] = SunPosition.isSunsetAvailable();
|
root["sun_isSunsetAvailable"] = SunPosition.isSunsetAvailable();
|
||||||
root["sun_isDayPeriod"] = SunPosition.isDayPeriod();
|
root["sun_isDayPeriod"] = SunPosition.isDayPeriod();
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiNtpClass::onNtpAdminGet(AsyncWebServerRequest* request)
|
void WebApiNtpClass::onNtpAdminGet(AsyncWebServerRequest* request)
|
||||||
@ -84,8 +83,7 @@ void WebApiNtpClass::onNtpAdminGet(AsyncWebServerRequest* request)
|
|||||||
root["latitude"] = config.Ntp.Latitude;
|
root["latitude"] = config.Ntp.Latitude;
|
||||||
root["sunsettype"] = config.Ntp.SunsetType;
|
root["sunsettype"] = config.Ntp.SunsetType;
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
|
void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
|
||||||
@ -95,37 +93,12 @@ void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
|
JsonDocument root;
|
||||||
|
if (!WebApi.parseRequestData(request, response, root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& retMsg = response->getRoot();
|
auto& retMsg = response->getRoot();
|
||||||
retMsg["type"] = "warning";
|
|
||||||
|
|
||||||
if (!request->hasParam("data", true)) {
|
|
||||||
retMsg["message"] = "No values found!";
|
|
||||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String json = request->getParam("data", true)->value();
|
|
||||||
|
|
||||||
if (json.length() > 1024) {
|
|
||||||
retMsg["message"] = "Data too large!";
|
|
||||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
|
||||||
const DeserializationError error = deserializeJson(root, json);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
retMsg["message"] = "Failed to parse data!";
|
|
||||||
retMsg["code"] = WebApiError::GenericParseError;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(root.containsKey("ntp_server")
|
if (!(root.containsKey("ntp_server")
|
||||||
&& root.containsKey("ntp_timezone")
|
&& root.containsKey("ntp_timezone")
|
||||||
@ -134,8 +107,7 @@ void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
|
|||||||
&& root.containsKey("sunsettype"))) {
|
&& root.containsKey("sunsettype"))) {
|
||||||
retMsg["message"] = "Values are missing!";
|
retMsg["message"] = "Values are missing!";
|
||||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,8 +115,7 @@ void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "NTP Server must between 1 and " STR(NTP_MAX_SERVER_STRLEN) " characters long!";
|
retMsg["message"] = "NTP Server must between 1 and " STR(NTP_MAX_SERVER_STRLEN) " characters long!";
|
||||||
retMsg["code"] = WebApiError::NtpServerLength;
|
retMsg["code"] = WebApiError::NtpServerLength;
|
||||||
retMsg["param"]["max"] = NTP_MAX_SERVER_STRLEN;
|
retMsg["param"]["max"] = NTP_MAX_SERVER_STRLEN;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,8 +123,7 @@ void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Timezone must between 1 and " STR(NTP_MAX_TIMEZONE_STRLEN) " characters long!";
|
retMsg["message"] = "Timezone must between 1 and " STR(NTP_MAX_TIMEZONE_STRLEN) " characters long!";
|
||||||
retMsg["code"] = WebApiError::NtpTimezoneLength;
|
retMsg["code"] = WebApiError::NtpTimezoneLength;
|
||||||
retMsg["param"]["max"] = NTP_MAX_TIMEZONE_STRLEN;
|
retMsg["param"]["max"] = NTP_MAX_TIMEZONE_STRLEN;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,8 +131,7 @@ void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Timezone description must between 1 and " STR(NTP_MAX_TIMEZONEDESCR_STRLEN) " characters long!";
|
retMsg["message"] = "Timezone description must between 1 and " STR(NTP_MAX_TIMEZONEDESCR_STRLEN) " characters long!";
|
||||||
retMsg["code"] = WebApiError::NtpTimezoneDescriptionLength;
|
retMsg["code"] = WebApiError::NtpTimezoneDescriptionLength;
|
||||||
retMsg["param"]["max"] = NTP_MAX_TIMEZONEDESCR_STRLEN;
|
retMsg["param"]["max"] = NTP_MAX_TIMEZONEDESCR_STRLEN;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,8 +145,7 @@ void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
WebApi.writeConfig(retMsg);
|
WebApi.writeConfig(retMsg);
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
|
|
||||||
NtpSettings.setServer();
|
NtpSettings.setServer();
|
||||||
NtpSettings.setTimezone();
|
NtpSettings.setTimezone();
|
||||||
@ -208,8 +176,7 @@ void WebApiNtpClass::onNtpTimeGet(AsyncWebServerRequest* request)
|
|||||||
root["minute"] = timeinfo.tm_min;
|
root["minute"] = timeinfo.tm_min;
|
||||||
root["second"] = timeinfo.tm_sec;
|
root["second"] = timeinfo.tm_sec;
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
|
void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
|
||||||
@ -219,37 +186,12 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
|
JsonDocument root;
|
||||||
|
if (!WebApi.parseRequestData(request, response, root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& retMsg = response->getRoot();
|
auto& retMsg = response->getRoot();
|
||||||
retMsg["type"] = "warning";
|
|
||||||
|
|
||||||
if (!request->hasParam("data", true)) {
|
|
||||||
retMsg["message"] = "No values found!";
|
|
||||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String json = request->getParam("data", true)->value();
|
|
||||||
|
|
||||||
if (json.length() > 1024) {
|
|
||||||
retMsg["message"] = "Data too large!";
|
|
||||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
|
||||||
const DeserializationError error = deserializeJson(root, json);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
retMsg["message"] = "Failed to parse data!";
|
|
||||||
retMsg["code"] = WebApiError::GenericParseError;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(root.containsKey("year")
|
if (!(root.containsKey("year")
|
||||||
&& root.containsKey("month")
|
&& root.containsKey("month")
|
||||||
@ -259,8 +201,7 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
|
|||||||
&& root.containsKey("second"))) {
|
&& root.containsKey("second"))) {
|
||||||
retMsg["message"] = "Values are missing!";
|
retMsg["message"] = "Values are missing!";
|
||||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,8 +210,7 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
|
|||||||
retMsg["code"] = WebApiError::NtpYearInvalid;
|
retMsg["code"] = WebApiError::NtpYearInvalid;
|
||||||
retMsg["param"]["min"] = 2022;
|
retMsg["param"]["min"] = 2022;
|
||||||
retMsg["param"]["max"] = 2100;
|
retMsg["param"]["max"] = 2100;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,8 +219,7 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
|
|||||||
retMsg["code"] = WebApiError::NtpMonthInvalid;
|
retMsg["code"] = WebApiError::NtpMonthInvalid;
|
||||||
retMsg["param"]["min"] = 1;
|
retMsg["param"]["min"] = 1;
|
||||||
retMsg["param"]["max"] = 12;
|
retMsg["param"]["max"] = 12;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,8 +228,7 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
|
|||||||
retMsg["code"] = WebApiError::NtpDayInvalid;
|
retMsg["code"] = WebApiError::NtpDayInvalid;
|
||||||
retMsg["param"]["min"] = 1;
|
retMsg["param"]["min"] = 1;
|
||||||
retMsg["param"]["max"] = 31;
|
retMsg["param"]["max"] = 31;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,8 +237,7 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
|
|||||||
retMsg["code"] = WebApiError::NtpHourInvalid;
|
retMsg["code"] = WebApiError::NtpHourInvalid;
|
||||||
retMsg["param"]["min"] = 0;
|
retMsg["param"]["min"] = 0;
|
||||||
retMsg["param"]["max"] = 23;
|
retMsg["param"]["max"] = 23;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,8 +246,7 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
|
|||||||
retMsg["code"] = WebApiError::NtpMinuteInvalid;
|
retMsg["code"] = WebApiError::NtpMinuteInvalid;
|
||||||
retMsg["param"]["min"] = 0;
|
retMsg["param"]["min"] = 0;
|
||||||
retMsg["param"]["max"] = 59;
|
retMsg["param"]["max"] = 59;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,8 +255,7 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
|
|||||||
retMsg["code"] = WebApiError::NtpSecondInvalid;
|
retMsg["code"] = WebApiError::NtpSecondInvalid;
|
||||||
retMsg["param"]["min"] = 0;
|
retMsg["param"]["min"] = 0;
|
||||||
retMsg["param"]["max"] = 59;
|
retMsg["param"]["max"] = 59;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,6 +276,5 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Time updated!";
|
retMsg["message"] = "Time updated!";
|
||||||
retMsg["code"] = WebApiError::NtpTimeUpdated;
|
retMsg["code"] = WebApiError::NtpTimeUpdated;
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,8 +40,7 @@ void WebApiPowerClass::onPowerStatus(AsyncWebServerRequest* request)
|
|||||||
root[inv->serialString()]["power_set_status"] = limitStatus;
|
root[inv->serialString()]["power_set_status"] = limitStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request)
|
void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request)
|
||||||
@ -51,45 +50,19 @@ void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
|
JsonDocument root;
|
||||||
|
if (!WebApi.parseRequestData(request, response, root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& retMsg = response->getRoot();
|
auto& retMsg = response->getRoot();
|
||||||
retMsg["type"] = "warning";
|
|
||||||
|
|
||||||
if (!request->hasParam("data", true)) {
|
|
||||||
retMsg["message"] = "No values found!";
|
|
||||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String json = request->getParam("data", true)->value();
|
|
||||||
|
|
||||||
if (json.length() > 1024) {
|
|
||||||
retMsg["message"] = "Data too large!";
|
|
||||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
|
||||||
const DeserializationError error = deserializeJson(root, json);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
retMsg["message"] = "Failed to parse data!";
|
|
||||||
retMsg["code"] = WebApiError::GenericParseError;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(root.containsKey("serial")
|
if (!(root.containsKey("serial")
|
||||||
&& (root.containsKey("power")
|
&& (root.containsKey("power")
|
||||||
|| root.containsKey("restart")))) {
|
|| root.containsKey("restart")))) {
|
||||||
retMsg["message"] = "Values are missing!";
|
retMsg["message"] = "Values are missing!";
|
||||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,8 +72,7 @@ void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request)
|
|||||||
if (serial == 0) {
|
if (serial == 0) {
|
||||||
retMsg["message"] = "Serial must be a number > 0!";
|
retMsg["message"] = "Serial must be a number > 0!";
|
||||||
retMsg["code"] = WebApiError::PowerSerialZero;
|
retMsg["code"] = WebApiError::PowerSerialZero;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,8 +80,7 @@ void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request)
|
|||||||
if (inv == nullptr) {
|
if (inv == nullptr) {
|
||||||
retMsg["message"] = "Invalid inverter specified!";
|
retMsg["message"] = "Invalid inverter specified!";
|
||||||
retMsg["code"] = WebApiError::PowerInvalidInverter;
|
retMsg["code"] = WebApiError::PowerInvalidInverter;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,6 +97,5 @@ void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Settings saved!";
|
retMsg["message"] = "Settings saved!";
|
||||||
retMsg["code"] = WebApiError::GenericSuccess;
|
retMsg["code"] = WebApiError::GenericSuccess;
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,10 +27,9 @@ void WebApiPowerLimiterClass::init(AsyncWebServer& server, Scheduler& scheduler)
|
|||||||
|
|
||||||
void WebApiPowerLimiterClass::onStatus(AsyncWebServerRequest* request)
|
void WebApiPowerLimiterClass::onStatus(AsyncWebServerRequest* request)
|
||||||
{
|
{
|
||||||
auto const& config = Configuration.get();
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 512);
|
|
||||||
auto& root = response->getRoot();
|
auto& root = response->getRoot();
|
||||||
|
auto const& config = Configuration.get();
|
||||||
|
|
||||||
root["enabled"] = config.PowerLimiter.Enabled;
|
root["enabled"] = config.PowerLimiter.Enabled;
|
||||||
root["verbose_logging"] = config.PowerLimiter.VerboseLogging;
|
root["verbose_logging"] = config.PowerLimiter.VerboseLogging;
|
||||||
@ -57,8 +56,7 @@ void WebApiPowerLimiterClass::onStatus(AsyncWebServerRequest* request)
|
|||||||
root["full_solar_passthrough_start_voltage"] = static_cast<int>(config.PowerLimiter.FullSolarPassThroughStartVoltage * 100 + 0.5) / 100.0;
|
root["full_solar_passthrough_start_voltage"] = static_cast<int>(config.PowerLimiter.FullSolarPassThroughStartVoltage * 100 + 0.5) / 100.0;
|
||||||
root["full_solar_passthrough_stop_voltage"] = static_cast<int>(config.PowerLimiter.FullSolarPassThroughStopVoltage * 100 + 0.5) / 100.0;
|
root["full_solar_passthrough_stop_voltage"] = static_cast<int>(config.PowerLimiter.FullSolarPassThroughStopVoltage * 100 + 0.5) / 100.0;
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiPowerLimiterClass::onMetaData(AsyncWebServerRequest* request)
|
void WebApiPowerLimiterClass::onMetaData(AsyncWebServerRequest* request)
|
||||||
@ -72,14 +70,14 @@ void WebApiPowerLimiterClass::onMetaData(AsyncWebServerRequest* request)
|
|||||||
if (config.Inverter[i].Serial != 0) { ++invAmount; }
|
if (config.Inverter[i].Serial != 0) { ++invAmount; }
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 256 + 256 * invAmount);
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
auto& root = response->getRoot();
|
auto& root = response->getRoot();
|
||||||
|
|
||||||
root["power_meter_enabled"] = config.PowerMeter.Enabled;
|
root["power_meter_enabled"] = config.PowerMeter.Enabled;
|
||||||
root["battery_enabled"] = config.Battery.Enabled;
|
root["battery_enabled"] = config.Battery.Enabled;
|
||||||
root["charge_controller_enabled"] = config.Vedirect.Enabled;
|
root["charge_controller_enabled"] = config.Vedirect.Enabled;
|
||||||
|
|
||||||
JsonObject inverters = root.createNestedObject("inverters");
|
JsonObject inverters = root["inverters"].to<JsonObject>();
|
||||||
for (uint8_t i = 0; i < INV_MAX_COUNT; i++) {
|
for (uint8_t i = 0; i < INV_MAX_COUNT; i++) {
|
||||||
if (config.Inverter[i].Serial == 0) { continue; }
|
if (config.Inverter[i].Serial == 0) { continue; }
|
||||||
|
|
||||||
@ -87,7 +85,7 @@ void WebApiPowerLimiterClass::onMetaData(AsyncWebServerRequest* request)
|
|||||||
// rather than the hex represenation as used when handling the inverter
|
// rather than the hex represenation as used when handling the inverter
|
||||||
// serial elsewhere in the web application, because in this case, the
|
// serial elsewhere in the web application, because in this case, the
|
||||||
// serial is actually not displayed but only used as a value/index.
|
// serial is actually not displayed but only used as a value/index.
|
||||||
JsonObject obj = inverters.createNestedObject(String(config.Inverter[i].Serial));
|
JsonObject obj = inverters[String(config.Inverter[i].Serial)].to<JsonObject>();
|
||||||
obj["pos"] = i;
|
obj["pos"] = i;
|
||||||
obj["name"] = String(config.Inverter[i].Name);
|
obj["name"] = String(config.Inverter[i].Name);
|
||||||
obj["poll_enable"] = config.Inverter[i].Poll_Enable;
|
obj["poll_enable"] = config.Inverter[i].Poll_Enable;
|
||||||
@ -105,8 +103,7 @@ void WebApiPowerLimiterClass::onMetaData(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiPowerLimiterClass::onAdminGet(AsyncWebServerRequest* request)
|
void WebApiPowerLimiterClass::onAdminGet(AsyncWebServerRequest* request)
|
||||||
@ -144,13 +141,12 @@ void WebApiPowerLimiterClass::onAdminPost(AsyncWebServerRequest* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
DeserializationError error = deserializeJson(root, json);
|
DeserializationError error = deserializeJson(root, json);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
retMsg["message"] = "Failed to parse data!";
|
retMsg["message"] = "Failed to parse data!";
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -45,7 +45,7 @@ void WebApiPowerMeterClass::decodeJsonPhaseConfig(JsonObject const& json, PowerM
|
|||||||
|
|
||||||
void WebApiPowerMeterClass::onStatus(AsyncWebServerRequest* request)
|
void WebApiPowerMeterClass::onStatus(AsyncWebServerRequest* request)
|
||||||
{
|
{
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 2048);
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
auto& root = response->getRoot();
|
auto& root = response->getRoot();
|
||||||
const CONFIG_T& config = Configuration.get();
|
const CONFIG_T& config = Configuration.get();
|
||||||
|
|
||||||
@ -60,10 +60,10 @@ void WebApiPowerMeterClass::onStatus(AsyncWebServerRequest* request)
|
|||||||
root["sdmaddress"] = config.PowerMeter.SdmAddress;
|
root["sdmaddress"] = config.PowerMeter.SdmAddress;
|
||||||
root["http_individual_requests"] = config.PowerMeter.HttpIndividualRequests;
|
root["http_individual_requests"] = config.PowerMeter.HttpIndividualRequests;
|
||||||
|
|
||||||
JsonArray httpPhases = root.createNestedArray("http_phases");
|
auto httpPhases = root["http_phases"].to<JsonArray>();
|
||||||
|
|
||||||
for (uint8_t i = 0; i < POWERMETER_MAX_PHASES; i++) {
|
for (uint8_t i = 0; i < POWERMETER_MAX_PHASES; i++) {
|
||||||
JsonObject phaseObject = httpPhases.createNestedObject();
|
auto phaseObject = httpPhases.add<JsonObject>();
|
||||||
|
|
||||||
phaseObject["index"] = i + 1;
|
phaseObject["index"] = i + 1;
|
||||||
phaseObject["enabled"] = config.PowerMeter.Http_Phase[i].Enabled;
|
phaseObject["enabled"] = config.PowerMeter.Http_Phase[i].Enabled;
|
||||||
@ -79,8 +79,7 @@ void WebApiPowerMeterClass::onStatus(AsyncWebServerRequest* request)
|
|||||||
phaseObject["sign_inverted"] = config.PowerMeter.Http_Phase[i].SignInverted;
|
phaseObject["sign_inverted"] = config.PowerMeter.Http_Phase[i].SignInverted;
|
||||||
}
|
}
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiPowerMeterClass::onAdminGet(AsyncWebServerRequest* request)
|
void WebApiPowerMeterClass::onAdminGet(AsyncWebServerRequest* request)
|
||||||
@ -118,7 +117,7 @@ void WebApiPowerMeterClass::onAdminPost(AsyncWebServerRequest* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument root(4096);
|
JsonDocument root;
|
||||||
DeserializationError error = deserializeJson(root, json);
|
DeserializationError error = deserializeJson(root, json);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
@ -201,8 +200,8 @@ void WebApiPowerMeterClass::onAdminPost(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
WebApi.writeConfig(retMsg);
|
WebApi.writeConfig(retMsg);
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
|
|
||||||
// reboot requiered as per https://github.com/helgeerbe/OpenDTU-OnBattery/issues/565#issuecomment-1872552559
|
// reboot requiered as per https://github.com/helgeerbe/OpenDTU-OnBattery/issues/565#issuecomment-1872552559
|
||||||
yield();
|
yield();
|
||||||
@ -237,7 +236,7 @@ void WebApiPowerMeterClass::onTestHttpRequest(AsyncWebServerRequest* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument root(2048);
|
JsonDocument root;
|
||||||
DeserializationError error = deserializeJson(root, json);
|
DeserializationError error = deserializeJson(root, json);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
|
|||||||
@ -31,8 +31,7 @@ void WebApiSecurityClass::onSecurityGet(AsyncWebServerRequest* request)
|
|||||||
root["password"] = config.Security.Password;
|
root["password"] = config.Security.Password;
|
||||||
root["allow_readonly"] = config.Security.AllowReadonly;
|
root["allow_readonly"] = config.Security.AllowReadonly;
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
|
void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
|
||||||
@ -42,44 +41,18 @@ void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
|
JsonDocument root;
|
||||||
|
if (!WebApi.parseRequestData(request, response, root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& retMsg = response->getRoot();
|
auto& retMsg = response->getRoot();
|
||||||
retMsg["type"] = "warning";
|
|
||||||
|
|
||||||
if (!request->hasParam("data", true)) {
|
|
||||||
retMsg["message"] = "No values found!";
|
|
||||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String json = request->getParam("data", true)->value();
|
|
||||||
|
|
||||||
if (json.length() > 1024) {
|
|
||||||
retMsg["message"] = "Data too large!";
|
|
||||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
|
||||||
const DeserializationError error = deserializeJson(root, json);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
retMsg["message"] = "Failed to parse data!";
|
|
||||||
retMsg["code"] = WebApiError::GenericParseError;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!root.containsKey("password")
|
if (!root.containsKey("password")
|
||||||
&& root.containsKey("allow_readonly")) {
|
&& root.containsKey("allow_readonly")) {
|
||||||
retMsg["message"] = "Values are missing!";
|
retMsg["message"] = "Values are missing!";
|
||||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,8 +60,7 @@ void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Password must between 8 and " STR(WIFI_MAX_PASSWORD_STRLEN) " characters long!";
|
retMsg["message"] = "Password must between 8 and " STR(WIFI_MAX_PASSWORD_STRLEN) " characters long!";
|
||||||
retMsg["code"] = WebApiError::SecurityPasswordLength;
|
retMsg["code"] = WebApiError::SecurityPasswordLength;
|
||||||
retMsg["param"]["max"] = WIFI_MAX_PASSWORD_STRLEN;
|
retMsg["param"]["max"] = WIFI_MAX_PASSWORD_STRLEN;
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,8 +70,7 @@ void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
WebApi.writeConfig(retMsg);
|
WebApi.writeConfig(retMsg);
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiSecurityClass::onAuthenticateGet(AsyncWebServerRequest* request)
|
void WebApiSecurityClass::onAuthenticateGet(AsyncWebServerRequest* request)
|
||||||
@ -114,6 +85,5 @@ void WebApiSecurityClass::onAuthenticateGet(AsyncWebServerRequest* request)
|
|||||||
retMsg["message"] = "Authentication successful!";
|
retMsg["message"] = "Authentication successful!";
|
||||||
retMsg["code"] = WebApiError::SecurityAuthSuccess;
|
retMsg["code"] = WebApiError::SecurityAuthSuccess;
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -81,6 +81,5 @@ void WebApiSysstatusClass::onSystemStatus(AsyncWebServerRequest* request)
|
|||||||
root["cmt_configured"] = PinMapping.isValidCmt2300Config();
|
root["cmt_configured"] = PinMapping.isValidCmt2300Config();
|
||||||
root["cmt_connected"] = Hoymiles.getRadioCmt()->isConnected();
|
root["cmt_connected"] = Hoymiles.getRadioCmt()->isConnected();
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,7 +87,7 @@ void WebApiVedirectClass::onVedirectAdminPost(AsyncWebServerRequest* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
DeserializationError error = deserializeJson(root, json);
|
DeserializationError error = deserializeJson(root, json);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
@ -115,8 +115,8 @@ void WebApiVedirectClass::onVedirectAdminPost(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
WebApi.writeConfig(retMsg);
|
WebApi.writeConfig(retMsg);
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
|
|
||||||
VictronMppt.updateSettings();
|
VictronMppt.updateSettings();
|
||||||
|
|
||||||
|
|||||||
@ -59,22 +59,15 @@ void WebApiWsHuaweiLiveClass::sendDataTaskCb()
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
if (Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
|
||||||
JsonVariant var = root;
|
JsonVariant var = root;
|
||||||
generateJsonResponse(var);
|
|
||||||
|
|
||||||
if (Utils::checkJsonOverflow(root, __FUNCTION__, __LINE__)) { return; }
|
generateCommonJsonResponse(var);
|
||||||
|
|
||||||
|
if (Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
String buffer;
|
String buffer;
|
||||||
serializeJson(root, buffer);
|
serializeJson(root, buffer);
|
||||||
|
|
||||||
if (Configuration.get().Security.AllowReadonly) {
|
|
||||||
_ws.setAuthentication("", "");
|
|
||||||
} else {
|
|
||||||
_ws.setAuthentication(AUTH_USERNAME, Configuration.get().Security.Password);
|
|
||||||
}
|
|
||||||
|
|
||||||
_ws.textAll(buffer);
|
_ws.textAll(buffer);
|
||||||
}
|
}
|
||||||
} catch (std::bad_alloc& bad_alloc) {
|
} catch (std::bad_alloc& bad_alloc) {
|
||||||
@ -84,7 +77,7 @@ void WebApiWsHuaweiLiveClass::sendDataTaskCb()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiWsHuaweiLiveClass::generateJsonResponse(JsonVariant& root)
|
void WebApiWsHuaweiLiveClass::generateCommonJsonResponse(JsonVariant& root)
|
||||||
{
|
{
|
||||||
const RectifierParameters_t * rp = HuaweiCan.get();
|
const RectifierParameters_t * rp = HuaweiCan.get();
|
||||||
|
|
||||||
@ -134,13 +127,13 @@ void WebApiWsHuaweiLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 1024U);
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
auto& root = response->getRoot();
|
auto& root = response->getRoot();
|
||||||
|
|
||||||
generateJsonResponse(root);
|
generateCommonJsonResponse(root);
|
||||||
|
|
||||||
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
} catch (std::bad_alloc& bad_alloc) {
|
} catch (std::bad_alloc& bad_alloc) {
|
||||||
MessageOutput.printf("Calling /api/huaweilivedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
|
MessageOutput.printf("Calling /api/huaweilivedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
|
||||||
WebApi.sendTooManyRequests(request);
|
WebApi.sendTooManyRequests(request);
|
||||||
|
|||||||
@ -62,12 +62,12 @@ void WebApiWsBatteryLiveClass::sendDataTaskCb()
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
DynamicJsonDocument root(_responseSize);
|
JsonDocument root;
|
||||||
if (Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
|
||||||
JsonVariant var = root;
|
JsonVariant var = root;
|
||||||
generateJsonResponse(var);
|
|
||||||
|
|
||||||
if (Utils::checkJsonOverflow(root, __FUNCTION__, __LINE__)) { return; }
|
generateCommonJsonResponse(var);
|
||||||
|
|
||||||
|
if (Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
|
|
||||||
// battery provider does not generate a card, e.g., MQTT provider
|
// battery provider does not generate a card, e.g., MQTT provider
|
||||||
if (root.isNull()) { return; }
|
if (root.isNull()) { return; }
|
||||||
@ -90,7 +90,7 @@ void WebApiWsBatteryLiveClass::sendDataTaskCb()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiWsBatteryLiveClass::generateJsonResponse(JsonVariant& root)
|
void WebApiWsBatteryLiveClass::generateCommonJsonResponse(JsonVariant& root)
|
||||||
{
|
{
|
||||||
Battery.getStats()->getLiveViewData(root);
|
Battery.getStats()->getLiveViewData(root);
|
||||||
}
|
}
|
||||||
@ -111,12 +111,11 @@ void WebApiWsBatteryLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, _responseSize);
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
auto& root = response->getRoot();
|
auto& root = response->getRoot();
|
||||||
generateJsonResponse(root);
|
generateCommonJsonResponse(root);
|
||||||
|
|
||||||
response->setLength();
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
request->send(response);
|
|
||||||
} catch (std::bad_alloc& bad_alloc) {
|
} catch (std::bad_alloc& bad_alloc) {
|
||||||
MessageOutput.printf("Calling /api/batterylivedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
|
MessageOutput.printf("Calling /api/batterylivedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
|
||||||
WebApi.sendTooManyRequests(request);
|
WebApi.sendTooManyRequests(request);
|
||||||
|
|||||||
@ -61,11 +61,11 @@ void WebApiWsLiveClass::generateOnBatteryJsonResponse(JsonVariant& root, bool al
|
|||||||
|
|
||||||
auto victronAge = VictronMppt.getDataAgeMillis();
|
auto victronAge = VictronMppt.getDataAgeMillis();
|
||||||
if (all || (victronAge > 0 && (millis() - _lastPublishVictron) > victronAge)) {
|
if (all || (victronAge > 0 && (millis() - _lastPublishVictron) > victronAge)) {
|
||||||
JsonObject vedirectObj = root.createNestedObject("vedirect");
|
auto vedirectObj = root["vedirect"].to<JsonObject>();
|
||||||
vedirectObj["enabled"] = config.Vedirect.Enabled;
|
vedirectObj["enabled"] = config.Vedirect.Enabled;
|
||||||
|
|
||||||
if (config.Vedirect.Enabled) {
|
if (config.Vedirect.Enabled) {
|
||||||
JsonObject totalVeObj = vedirectObj.createNestedObject("total");
|
auto totalVeObj = vedirectObj["total"].to<JsonObject>();
|
||||||
addTotalField(totalVeObj, "Power", VictronMppt.getPanelPowerWatts(), "W", 1);
|
addTotalField(totalVeObj, "Power", VictronMppt.getPanelPowerWatts(), "W", 1);
|
||||||
addTotalField(totalVeObj, "YieldDay", VictronMppt.getYieldDay() * 1000, "Wh", 0);
|
addTotalField(totalVeObj, "YieldDay", VictronMppt.getYieldDay() * 1000, "Wh", 0);
|
||||||
addTotalField(totalVeObj, "YieldTotal", VictronMppt.getYieldTotal(), "kWh", 2);
|
addTotalField(totalVeObj, "YieldTotal", VictronMppt.getYieldTotal(), "kWh", 2);
|
||||||
@ -75,7 +75,7 @@ void WebApiWsLiveClass::generateOnBatteryJsonResponse(JsonVariant& root, bool al
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (all || (HuaweiCan.getLastUpdate() - _lastPublishHuawei) < halfOfAllMillis ) {
|
if (all || (HuaweiCan.getLastUpdate() - _lastPublishHuawei) < halfOfAllMillis ) {
|
||||||
JsonObject huaweiObj = root.createNestedObject("huawei");
|
auto huaweiObj = root["huawei"].to<JsonObject>();
|
||||||
huaweiObj["enabled"] = config.Huawei.Enabled;
|
huaweiObj["enabled"] = config.Huawei.Enabled;
|
||||||
|
|
||||||
if (config.Huawei.Enabled) {
|
if (config.Huawei.Enabled) {
|
||||||
@ -88,7 +88,7 @@ void WebApiWsLiveClass::generateOnBatteryJsonResponse(JsonVariant& root, bool al
|
|||||||
|
|
||||||
auto spStats = Battery.getStats();
|
auto spStats = Battery.getStats();
|
||||||
if (all || spStats->updateAvailable(_lastPublishBattery)) {
|
if (all || spStats->updateAvailable(_lastPublishBattery)) {
|
||||||
JsonObject batteryObj = root.createNestedObject("battery");
|
auto batteryObj = root["battery"].to<JsonObject>();
|
||||||
batteryObj["enabled"] = config.Battery.Enabled;
|
batteryObj["enabled"] = config.Battery.Enabled;
|
||||||
|
|
||||||
if (config.Battery.Enabled) {
|
if (config.Battery.Enabled) {
|
||||||
@ -99,7 +99,7 @@ void WebApiWsLiveClass::generateOnBatteryJsonResponse(JsonVariant& root, bool al
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (all || (PowerMeter.getLastPowerMeterUpdate() - _lastPublishPowerMeter) < halfOfAllMillis) {
|
if (all || (PowerMeter.getLastPowerMeterUpdate() - _lastPublishPowerMeter) < halfOfAllMillis) {
|
||||||
JsonObject powerMeterObj = root.createNestedObject("power_meter");
|
auto powerMeterObj = root["power_meter"].to<JsonObject>();
|
||||||
powerMeterObj["enabled"] = config.PowerMeter.Enabled;
|
powerMeterObj["enabled"] = config.PowerMeter.Enabled;
|
||||||
|
|
||||||
if (config.PowerMeter.Enabled) {
|
if (config.PowerMeter.Enabled) {
|
||||||
@ -112,9 +112,7 @@ void WebApiWsLiveClass::generateOnBatteryJsonResponse(JsonVariant& root, bool al
|
|||||||
|
|
||||||
void WebApiWsLiveClass::sendOnBatteryStats()
|
void WebApiWsLiveClass::sendOnBatteryStats()
|
||||||
{
|
{
|
||||||
DynamicJsonDocument root(1024);
|
JsonDocument root;
|
||||||
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) { return; }
|
|
||||||
|
|
||||||
JsonVariant var = root;
|
JsonVariant var = root;
|
||||||
|
|
||||||
bool all = (millis() - _lastPublishOnBatteryFull) > 10 * 1000;
|
bool all = (millis() - _lastPublishOnBatteryFull) > 10 * 1000;
|
||||||
@ -123,12 +121,12 @@ void WebApiWsLiveClass::sendOnBatteryStats()
|
|||||||
|
|
||||||
if (root.isNull()) { return; }
|
if (root.isNull()) { return; }
|
||||||
|
|
||||||
if (Utils::checkJsonOverflow(root, __FUNCTION__, __LINE__)) { return; }
|
if (Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
|
|
||||||
String buffer;
|
String buffer;
|
||||||
serializeJson(root, buffer);
|
serializeJson(root, buffer);
|
||||||
|
|
||||||
_ws.textAll(buffer);
|
_ws.textAll(buffer);;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiWsLiveClass::sendDataTaskCb()
|
void WebApiWsLiveClass::sendDataTaskCb()
|
||||||
@ -156,19 +154,20 @@ void WebApiWsLiveClass::sendDataTaskCb()
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
DynamicJsonDocument root(4096);
|
JsonDocument root;
|
||||||
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
JsonVariant var = root;
|
JsonVariant var = root;
|
||||||
|
|
||||||
auto invArray = var.createNestedArray("inverters");
|
auto invArray = var["inverters"].to<JsonArray>();
|
||||||
auto invObject = invArray.createNestedObject();
|
auto invObject = invArray.add<JsonObject>();
|
||||||
|
|
||||||
generateCommonJsonResponse(var);
|
generateCommonJsonResponse(var);
|
||||||
generateInverterCommonJsonResponse(invObject, inv);
|
generateInverterCommonJsonResponse(invObject, inv);
|
||||||
generateInverterChannelJsonResponse(invObject, inv);
|
generateInverterChannelJsonResponse(invObject, inv);
|
||||||
|
|
||||||
|
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
String buffer;
|
String buffer;
|
||||||
serializeJson(root, buffer);
|
serializeJson(root, buffer);
|
||||||
|
|
||||||
@ -184,12 +183,12 @@ void WebApiWsLiveClass::sendDataTaskCb()
|
|||||||
|
|
||||||
void WebApiWsLiveClass::generateCommonJsonResponse(JsonVariant& root)
|
void WebApiWsLiveClass::generateCommonJsonResponse(JsonVariant& root)
|
||||||
{
|
{
|
||||||
JsonObject totalObj = root.createNestedObject("total");
|
auto totalObj = root["total"].to<JsonObject>();
|
||||||
addTotalField(totalObj, "Power", Datastore.getTotalAcPowerEnabled(), "W", Datastore.getTotalAcPowerDigits());
|
addTotalField(totalObj, "Power", Datastore.getTotalAcPowerEnabled(), "W", Datastore.getTotalAcPowerDigits());
|
||||||
addTotalField(totalObj, "YieldDay", Datastore.getTotalAcYieldDayEnabled(), "Wh", Datastore.getTotalAcYieldDayDigits());
|
addTotalField(totalObj, "YieldDay", Datastore.getTotalAcYieldDayEnabled(), "Wh", Datastore.getTotalAcYieldDayDigits());
|
||||||
addTotalField(totalObj, "YieldTotal", Datastore.getTotalAcYieldTotalEnabled(), "kWh", Datastore.getTotalAcYieldTotalDigits());
|
addTotalField(totalObj, "YieldTotal", Datastore.getTotalAcYieldTotalEnabled(), "kWh", Datastore.getTotalAcYieldTotalDigits());
|
||||||
|
|
||||||
JsonObject hintObj = root.createNestedObject("hints");
|
JsonObject hintObj = root["hints"].to<JsonObject>();
|
||||||
struct tm timeinfo;
|
struct tm timeinfo;
|
||||||
hintObj["time_sync"] = !getLocalTime(&timeinfo, 5);
|
hintObj["time_sync"] = !getLocalTime(&timeinfo, 5);
|
||||||
hintObj["radio_problem"] = (Hoymiles.getRadioNrf()->isInitialized() && (!Hoymiles.getRadioNrf()->isConnected() || !Hoymiles.getRadioNrf()->isPVariant())) || (Hoymiles.getRadioCmt()->isInitialized() && (!Hoymiles.getRadioCmt()->isConnected()));
|
hintObj["radio_problem"] = (Hoymiles.getRadioNrf()->isInitialized() && (!Hoymiles.getRadioNrf()->isConnected() || !Hoymiles.getRadioNrf()->isPVariant())) || (Hoymiles.getRadioCmt()->isInitialized() && (!Hoymiles.getRadioCmt()->isConnected()));
|
||||||
@ -227,7 +226,7 @@ void WebApiWsLiveClass::generateInverterChannelJsonResponse(JsonObject& root, st
|
|||||||
|
|
||||||
// Loop all channels
|
// Loop all channels
|
||||||
for (auto& t : inv->Statistics()->getChannelTypes()) {
|
for (auto& t : inv->Statistics()->getChannelTypes()) {
|
||||||
JsonObject chanTypeObj = root.createNestedObject(inv->Statistics()->getChannelTypeName(t));
|
auto chanTypeObj = root[inv->Statistics()->getChannelTypeName(t)].to<JsonObject>();
|
||||||
for (auto& c : inv->Statistics()->getChannelsByType(t)) {
|
for (auto& c : inv->Statistics()->getChannelsByType(t)) {
|
||||||
if (t == TYPE_DC) {
|
if (t == TYPE_DC) {
|
||||||
chanTypeObj[String(static_cast<uint8_t>(c))]["name"]["u"] = inv_cfg->channel[c].Name;
|
chanTypeObj[String(static_cast<uint8_t>(c))]["name"]["u"] = inv_cfg->channel[c].Name;
|
||||||
@ -304,21 +303,15 @@ void WebApiWsLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 4096);
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
auto& root = response->getRoot();
|
auto& root = response->getRoot();
|
||||||
|
auto invArray = root["inverters"].to<JsonArray>();
|
||||||
JsonArray invArray = root.createNestedArray("inverters");
|
auto serial = WebApi.parseSerialFromRequest(request);
|
||||||
|
|
||||||
uint64_t serial = 0;
|
|
||||||
if (request->hasParam("inv")) {
|
|
||||||
String s = request->getParam("inv")->value();
|
|
||||||
serial = strtoll(s.c_str(), NULL, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (serial > 0) {
|
if (serial > 0) {
|
||||||
auto inv = Hoymiles.getInverterBySerial(serial);
|
auto inv = Hoymiles.getInverterBySerial(serial);
|
||||||
if (inv != nullptr) {
|
if (inv != nullptr) {
|
||||||
JsonObject invObject = invArray.createNestedObject();
|
JsonObject invObject = invArray.add<JsonObject>();
|
||||||
generateInverterCommonJsonResponse(invObject, inv);
|
generateInverterCommonJsonResponse(invObject, inv);
|
||||||
generateInverterChannelJsonResponse(invObject, inv);
|
generateInverterChannelJsonResponse(invObject, inv);
|
||||||
}
|
}
|
||||||
@ -330,7 +323,7 @@ void WebApiWsLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject invObject = invArray.createNestedObject();
|
JsonObject invObject = invArray.add<JsonObject>();
|
||||||
generateInverterCommonJsonResponse(invObject, inv);
|
generateInverterCommonJsonResponse(invObject, inv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -339,8 +332,9 @@ void WebApiWsLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
generateOnBatteryJsonResponse(root, true);
|
generateOnBatteryJsonResponse(root, true);
|
||||||
|
|
||||||
response->setLength();
|
generateOnBatteryJsonResponse(root, true);
|
||||||
request->send(response);
|
|
||||||
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
|
|
||||||
} catch (const std::bad_alloc& bad_alloc) {
|
} catch (const std::bad_alloc& bad_alloc) {
|
||||||
MessageOutput.printf("Calling /api/livedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
|
MessageOutput.printf("Calling /api/livedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
|
||||||
|
|||||||
@ -86,25 +86,17 @@ void WebApiWsVedirectLiveClass::sendDataTaskCb()
|
|||||||
if (fullUpdate || updateAvailable) {
|
if (fullUpdate || updateAvailable) {
|
||||||
try {
|
try {
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
DynamicJsonDocument root(responseSize());
|
JsonDocument root;
|
||||||
if (Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
|
||||||
JsonVariant var = root;
|
JsonVariant var = root;
|
||||||
generateJsonResponse(var, fullUpdate);
|
|
||||||
|
|
||||||
if (Utils::checkJsonOverflow(root, __FUNCTION__, __LINE__)) { return; }
|
generateCommonJsonResponse(var, fullUpdate);
|
||||||
|
|
||||||
|
if (Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
String buffer;
|
String buffer;
|
||||||
serializeJson(root, buffer);
|
serializeJson(root, buffer);
|
||||||
|
|
||||||
if (Configuration.get().Security.AllowReadonly) {
|
_ws.textAll(buffer);;
|
||||||
_ws.setAuthentication("", "");
|
|
||||||
} else {
|
|
||||||
_ws.setAuthentication(AUTH_USERNAME, Configuration.get().Security.Password);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ws.textAll(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (std::bad_alloc& bad_alloc) {
|
} catch (std::bad_alloc& bad_alloc) {
|
||||||
MessageOutput.printf("Calling /api/vedirectlivedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
|
MessageOutput.printf("Calling /api/vedirectlivedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
|
||||||
} catch (const std::exception& exc) {
|
} catch (const std::exception& exc) {
|
||||||
@ -117,9 +109,9 @@ void WebApiWsVedirectLiveClass::sendDataTaskCb()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiWsVedirectLiveClass::generateJsonResponse(JsonVariant& root, bool fullUpdate)
|
void WebApiWsVedirectLiveClass::generateCommonJsonResponse(JsonVariant& root, bool fullUpdate)
|
||||||
{
|
{
|
||||||
const JsonObject &array = root["vedirect"].createNestedObject("instances");
|
auto array = root["vedirect"]["instances"].to<JsonObject>();
|
||||||
root["vedirect"]["full_update"] = fullUpdate;
|
root["vedirect"]["full_update"] = fullUpdate;
|
||||||
|
|
||||||
for (size_t idx = 0; idx < VictronMppt.controllerAmount(); ++idx) {
|
for (size_t idx = 0; idx < VictronMppt.controllerAmount(); ++idx) {
|
||||||
@ -131,7 +123,7 @@ void WebApiWsVedirectLiveClass::generateJsonResponse(JsonVariant& root, bool ful
|
|||||||
String serial(optMpptData->serialNr_SER);
|
String serial(optMpptData->serialNr_SER);
|
||||||
if (serial.isEmpty()) { continue; } // serial required as index
|
if (serial.isEmpty()) { continue; } // serial required as index
|
||||||
|
|
||||||
const JsonObject &nested = array.createNestedObject(serial);
|
JsonObject nested = array[serial].to<JsonObject>();
|
||||||
nested["data_age_ms"] = VictronMppt.getDataAgeMillis(idx);
|
nested["data_age_ms"] = VictronMppt.getDataAgeMillis(idx);
|
||||||
populateJson(nested, *optMpptData);
|
populateJson(nested, *optMpptData);
|
||||||
}
|
}
|
||||||
@ -149,9 +141,9 @@ void WebApiWsVedirectLiveClass::populateJson(const JsonObject &root, const VeDir
|
|||||||
root["product_id"] = mpptData.getPidAsString();
|
root["product_id"] = mpptData.getPidAsString();
|
||||||
root["firmware_version"] = String(mpptData.firmwareNr_FW);
|
root["firmware_version"] = String(mpptData.firmwareNr_FW);
|
||||||
|
|
||||||
const JsonObject &values = root.createNestedObject("values");
|
const JsonObject values = root["values"].to<JsonObject>();
|
||||||
|
|
||||||
const JsonObject &device = values.createNestedObject("device");
|
const JsonObject device = values["device"].to<JsonObject>();
|
||||||
device["LOAD"] = mpptData.loadOutputState_LOAD ? "ON" : "OFF";
|
device["LOAD"] = mpptData.loadOutputState_LOAD ? "ON" : "OFF";
|
||||||
device["CS"] = mpptData.getCsAsString();
|
device["CS"] = mpptData.getCsAsString();
|
||||||
device["MPPT"] = mpptData.getMpptAsString();
|
device["MPPT"] = mpptData.getMpptAsString();
|
||||||
@ -165,7 +157,7 @@ void WebApiWsVedirectLiveClass::populateJson(const JsonObject &root, const VeDir
|
|||||||
device["MpptTemperature"]["d"] = "1";
|
device["MpptTemperature"]["d"] = "1";
|
||||||
}
|
}
|
||||||
|
|
||||||
const JsonObject &output = values.createNestedObject("output");
|
const JsonObject output = values["output"].to<JsonObject>();
|
||||||
output["P"]["v"] = mpptData.batteryOutputPower_W;
|
output["P"]["v"] = mpptData.batteryOutputPower_W;
|
||||||
output["P"]["u"] = "W";
|
output["P"]["u"] = "W";
|
||||||
output["P"]["d"] = 0;
|
output["P"]["d"] = 0;
|
||||||
@ -179,7 +171,7 @@ void WebApiWsVedirectLiveClass::populateJson(const JsonObject &root, const VeDir
|
|||||||
output["E"]["u"] = "%";
|
output["E"]["u"] = "%";
|
||||||
output["E"]["d"] = 1;
|
output["E"]["d"] = 1;
|
||||||
|
|
||||||
const JsonObject &input = values.createNestedObject("input");
|
const JsonObject input = values["input"].to<JsonObject>();
|
||||||
if (mpptData.NetworkTotalDcInputPowerMilliWatts.first > 0) {
|
if (mpptData.NetworkTotalDcInputPowerMilliWatts.first > 0) {
|
||||||
input["NetworkPower"]["v"] = mpptData.NetworkTotalDcInputPowerMilliWatts.second / 1000.0;
|
input["NetworkPower"]["v"] = mpptData.NetworkTotalDcInputPowerMilliWatts.second / 1000.0;
|
||||||
input["NetworkPower"]["u"] = "W";
|
input["NetworkPower"]["u"] = "W";
|
||||||
@ -233,14 +225,12 @@ void WebApiWsVedirectLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, responseSize());
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
auto& root = response->getRoot();
|
auto& root = response->getRoot();
|
||||||
|
|
||||||
generateJsonResponse(root, true/*fullUpdate*/);
|
generateCommonJsonResponse(root, true/*fullUpdate*/);
|
||||||
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
|
|
||||||
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
} catch (std::bad_alloc& bad_alloc) {
|
} catch (std::bad_alloc& bad_alloc) {
|
||||||
MessageOutput.printf("Calling /api/vedirectlivedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
|
MessageOutput.printf("Calling /api/vedirectlivedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
|
||||||
WebApi.sendTooManyRequests(request);
|
WebApi.sendTooManyRequests(request);
|
||||||
|
|||||||
@ -1,14 +0,0 @@
|
|||||||
/* eslint-env node */
|
|
||||||
require('@rushstack/eslint-patch/modern-module-resolution')
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
'extends': [
|
|
||||||
'plugin:vue/vue3-essential',
|
|
||||||
'eslint:recommended',
|
|
||||||
'@vue/eslint-config-typescript'
|
|
||||||
],
|
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 'latest'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
36
webapp/eslint.config.js
Normal file
36
webapp/eslint.config.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/* eslint-env node */
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
import { FlatCompat } from "@eslint/eslintrc";
|
||||||
|
import js from "@eslint/js";
|
||||||
|
import pluginVue from 'eslint-plugin-vue'
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
const compat = new FlatCompat({
|
||||||
|
baseDirectory: __dirname,
|
||||||
|
recommendedConfig: js.configs.recommended,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default [
|
||||||
|
js.configs.recommended,
|
||||||
|
...pluginVue.configs['flat/essential'],
|
||||||
|
...compat.extends("@vue/eslint-config-typescript/recommended"),
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
"**/*.vue",
|
||||||
|
"**/*.js",
|
||||||
|
"**/*.jsx",
|
||||||
|
"**/*.cjs",
|
||||||
|
"**/*.mjs",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
"**/*.cts",
|
||||||
|
"**/*.mts",
|
||||||
|
],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 'latest'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
]
|
||||||
@ -9,7 +9,7 @@
|
|||||||
"preview": "vite preview --port 4173",
|
"preview": "vite preview --port 4173",
|
||||||
"build-only": "vite build",
|
"build-only": "vite build",
|
||||||
"type-check": "vue-tsc --noEmit",
|
"type-check": "vue-tsc --noEmit",
|
||||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
|
"lint": "eslint ."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
@ -19,31 +19,30 @@
|
|||||||
"sortablejs": "^1.15.2",
|
"sortablejs": "^1.15.2",
|
||||||
"spark-md5": "^3.0.2",
|
"spark-md5": "^3.0.2",
|
||||||
"vue": "^3.4.21",
|
"vue": "^3.4.21",
|
||||||
"vue-i18n": "^9.10.2",
|
"vue-i18n": "^9.12.0",
|
||||||
"vue-router": "^4.3.0"
|
"vue-router": "^4.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@intlify/unplugin-vue-i18n": "^4.0.0",
|
"@intlify/unplugin-vue-i18n": "^4.0.0",
|
||||||
"@rushstack/eslint-patch": "^1.10.1",
|
|
||||||
"@tsconfig/node18": "^18.2.4",
|
"@tsconfig/node18": "^18.2.4",
|
||||||
"@types/bootstrap": "^5.2.10",
|
"@types/bootstrap": "^5.2.10",
|
||||||
"@types/node": "^20.12.2",
|
"@types/node": "^20.12.7",
|
||||||
"@types/pulltorefreshjs": "^0.1.7",
|
"@types/pulltorefreshjs": "^0.1.7",
|
||||||
"@types/sortablejs": "^1.15.8",
|
"@types/sortablejs": "^1.15.8",
|
||||||
"@types/spark-md5": "^3.0.4",
|
"@types/spark-md5": "^3.0.4",
|
||||||
"@vitejs/plugin-vue": "^5.0.4",
|
"@vitejs/plugin-vue": "^5.0.4",
|
||||||
"@vue/eslint-config-typescript": "^13.0.0",
|
"@vue/eslint-config-typescript": "^13.0.0",
|
||||||
"@vue/tsconfig": "^0.5.1",
|
"@vue/tsconfig": "^0.5.1",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^9.0.0",
|
||||||
"eslint-plugin-vue": "^9.24.0",
|
"eslint-plugin-vue": "^9.24.1",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"pulltorefreshjs": "^0.1.22",
|
"pulltorefreshjs": "^0.1.22",
|
||||||
"sass": "^1.72.0",
|
"sass": "^1.75.0",
|
||||||
"terser": "^5.30.0",
|
"terser": "^5.30.3",
|
||||||
"typescript": "^5.4.3",
|
"typescript": "^5.4.5",
|
||||||
"vite": "^5.2.7",
|
"vite": "^5.2.8",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-css-injected-by-js": "^3.5.0",
|
"vite-plugin-css-injected-by-js": "^3.5.0",
|
||||||
"vue-tsc": "^2.0.7"
|
"vue-tsc": "^2.0.13"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,15 +48,14 @@ export default defineComponent({
|
|||||||
showReload: { type: Boolean, required: false, default: false },
|
showReload: { type: Boolean, required: false, default: false },
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
var self = this;
|
|
||||||
console.log("init");
|
console.log("init");
|
||||||
PullToRefresh.init({
|
PullToRefresh.init({
|
||||||
mainElement: 'body', // above which element?
|
mainElement: 'body', // above which element?
|
||||||
instructionsPullToRefresh: this.$t('base.Pull'),
|
instructionsPullToRefresh: this.$t('base.Pull'),
|
||||||
instructionsReleaseToRefresh: this.$t('base.Release'),
|
instructionsReleaseToRefresh: this.$t('base.Release'),
|
||||||
instructionsRefreshing: this.$t('base.Refreshing'),
|
instructionsRefreshing: this.$t('base.Refreshing'),
|
||||||
onRefresh: function() {
|
onRefresh: () => {
|
||||||
self.$emit('reload');
|
this.$emit('reload');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@ -52,7 +52,7 @@ export default defineComponent({
|
|||||||
_countDownTimeout = undefined;
|
_countDownTimeout = undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
var countDown = ref();
|
const countDown = ref();
|
||||||
watch(() => props.modelValue, () => {
|
watch(() => props.modelValue, () => {
|
||||||
countDown.value = parseCountDown(props.modelValue);
|
countDown.value = parseCountDown(props.modelValue);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -87,10 +87,10 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
modelAllowVersionInfo: {
|
modelAllowVersionInfo: {
|
||||||
get(): any {
|
get(): boolean {
|
||||||
return !!this.allowVersionInfo;
|
return !!this.allowVersionInfo;
|
||||||
},
|
},
|
||||||
set(value: any) {
|
set(value: boolean) {
|
||||||
this.$emit('update:allowVersionInfo', value);
|
this.$emit('update:allowVersionInfo', value);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -83,10 +83,12 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
model: {
|
model: {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
get(): any {
|
get(): any {
|
||||||
if (this.type === 'checkbox') return !!this.modelValue;
|
if (this.type === 'checkbox') return !!this.modelValue;
|
||||||
return this.modelValue;
|
return this.modelValue;
|
||||||
},
|
},
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
set(value: any) {
|
set(value: any) {
|
||||||
this.$emit('update:modelValue', value);
|
this.$emit('update:modelValue', value);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -28,9 +28,11 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
model: {
|
model: {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
get(): any {
|
get(): any {
|
||||||
return this.modelValue;
|
return this.modelValue;
|
||||||
},
|
},
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
set(value: any) {
|
set(value: any) {
|
||||||
this.$emit('update:modelValue', value);
|
this.$emit('update:modelValue', value);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -168,8 +168,8 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
isEaster() {
|
isEaster() {
|
||||||
const easter = this.getEasterSunday(this.now.getFullYear());
|
const easter = this.getEasterSunday(this.now.getFullYear());
|
||||||
var easterStart = new Date(easter);
|
const easterStart = new Date(easter);
|
||||||
var easterEnd = new Date(easter);
|
const easterEnd = new Date(easter);
|
||||||
easterStart.setDate(easterStart.getDate() - 2);
|
easterStart.setDate(easterStart.getDate() - 2);
|
||||||
easterEnd.setDate(easterEnd.getDate() + 1);
|
easterEnd.setDate(easterEnd.getDate() + 1);
|
||||||
return this.now >= easterStart && this.now < easterEnd;
|
return this.now >= easterStart && this.now < easterEnd;
|
||||||
@ -192,15 +192,15 @@ export default defineComponent({
|
|||||||
this.$refs.navbarCollapse && (this.$refs.navbarCollapse as HTMLElement).classList.remove("show");
|
this.$refs.navbarCollapse && (this.$refs.navbarCollapse as HTMLElement).classList.remove("show");
|
||||||
},
|
},
|
||||||
getEasterSunday(year: number): Date {
|
getEasterSunday(year: number): Date {
|
||||||
var f = Math.floor;
|
const f = Math.floor;
|
||||||
var G = year % 19;
|
const G = year % 19;
|
||||||
var C = f(year / 100);
|
const C = f(year / 100);
|
||||||
var H = (C - f(C / 4) - f((8 * C + 13) / 25) + 19 * G + 15) % 30;
|
const H = (C - f(C / 4) - f((8 * C + 13) / 25) + 19 * G + 15) % 30;
|
||||||
var I = H - f(H / 28) * (1 - f(29 / (H + 1)) * f((21 - G) / 11));
|
const I = H - f(H / 28) * (1 - f(29 / (H + 1)) * f((21 - G) / 11));
|
||||||
var J = (year + f(year / 4) + I + 2 - C + f(C / 4)) % 7;
|
const J = (year + f(year / 4) + I + 2 - C + f(C / 4)) % 7;
|
||||||
var L = I - J;
|
const L = I - J;
|
||||||
var month = 3 + f((L + 40) / 44);
|
const month = 3 + f((L + 40) / 44);
|
||||||
var day = L + 28 - 31 * f(month / 4);
|
const day = L + 28 - 31 * f(month / 4);
|
||||||
|
|
||||||
return new Date(year, month - 1, day);
|
return new Date(year, month - 1, day);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -84,9 +84,11 @@ export default defineComponent({
|
|||||||
let comCur = 999999;
|
let comCur = 999999;
|
||||||
|
|
||||||
if (this.selectedPinAssignment && category in this.selectedPinAssignment) {
|
if (this.selectedPinAssignment && category in this.selectedPinAssignment) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
comSel = (this.selectedPinAssignment as any)[category][prop];
|
comSel = (this.selectedPinAssignment as any)[category][prop];
|
||||||
}
|
}
|
||||||
if (this.currentPinAssignment && category in this.currentPinAssignment) {
|
if (this.currentPinAssignment && category in this.currentPinAssignment) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
comCur = (this.currentPinAssignment as any)[category][prop];
|
comCur = (this.currentPinAssignment as any)[category][prop];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -41,6 +41,9 @@
|
|||||||
"Release": "Loslassen zum Aktualisieren",
|
"Release": "Loslassen zum Aktualisieren",
|
||||||
"Close": "Schließen"
|
"Close": "Schließen"
|
||||||
},
|
},
|
||||||
|
"Error": {
|
||||||
|
"Oops": "Oops!"
|
||||||
|
},
|
||||||
"localeswitcher": {
|
"localeswitcher": {
|
||||||
"Dark": "Dunkel",
|
"Dark": "Dunkel",
|
||||||
"Light": "Hell",
|
"Light": "Hell",
|
||||||
|
|||||||
@ -41,6 +41,9 @@
|
|||||||
"Release": "Release to refresh",
|
"Release": "Release to refresh",
|
||||||
"Close": "Close"
|
"Close": "Close"
|
||||||
},
|
},
|
||||||
|
"Error": {
|
||||||
|
"Oops": "Oops!"
|
||||||
|
},
|
||||||
"localeswitcher": {
|
"localeswitcher": {
|
||||||
"Dark": "Dark",
|
"Dark": "Dark",
|
||||||
"Light": "Light",
|
"Light": "Light",
|
||||||
|
|||||||
@ -41,6 +41,9 @@
|
|||||||
"Release": "Release to refresh",
|
"Release": "Release to refresh",
|
||||||
"Close": "Fermer"
|
"Close": "Fermer"
|
||||||
},
|
},
|
||||||
|
"Error": {
|
||||||
|
"Oops": "Oops!"
|
||||||
|
},
|
||||||
"localeswitcher": {
|
"localeswitcher": {
|
||||||
"Dark": "Sombre",
|
"Dark": "Sombre",
|
||||||
"Light": "Clair",
|
"Light": "Clair",
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import ConfigAdminView from '@/views/ConfigAdminView.vue';
|
|||||||
import ConsoleInfoView from '@/views/ConsoleInfoView.vue';
|
import ConsoleInfoView from '@/views/ConsoleInfoView.vue';
|
||||||
import DeviceAdminView from '@/views/DeviceAdminView.vue'
|
import DeviceAdminView from '@/views/DeviceAdminView.vue'
|
||||||
import DtuAdminView from '@/views/DtuAdminView.vue';
|
import DtuAdminView from '@/views/DtuAdminView.vue';
|
||||||
|
import ErrorView from '@/views/ErrorView.vue';
|
||||||
import FirmwareUpgradeView from '@/views/FirmwareUpgradeView.vue';
|
import FirmwareUpgradeView from '@/views/FirmwareUpgradeView.vue';
|
||||||
import HomeView from '@/views/HomeView.vue';
|
import HomeView from '@/views/HomeView.vue';
|
||||||
import VedirectAdminView from '@/views/VedirectAdminView.vue'
|
import VedirectAdminView from '@/views/VedirectAdminView.vue'
|
||||||
@ -38,6 +39,11 @@ const router = createRouter({
|
|||||||
name: 'Login',
|
name: 'Login',
|
||||||
component: LoginView
|
component: LoginView
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/error?status=:status&message=:message',
|
||||||
|
name: 'Error',
|
||||||
|
component: ErrorView
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/about',
|
path: '/about',
|
||||||
name: 'About',
|
name: 'About',
|
||||||
|
|||||||
@ -41,7 +41,7 @@ export function isLoggedIn(): boolean {
|
|||||||
return (localStorage.getItem('user') != null);
|
return (localStorage.getItem('user') != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function login(username: String, password: String) {
|
export function login(username: string, password: string) {
|
||||||
const requestOptions = {
|
const requestOptions = {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
@ -74,9 +74,11 @@ export function handleResponse(response: Response, emitter: Emitter<Record<Event
|
|||||||
logout();
|
logout();
|
||||||
emitter.emit("logged-out");
|
emitter.emit("logged-out");
|
||||||
router.push({ path: "/login", query: { returnUrl: router.currentRoute.value.fullPath } });
|
router.push({ path: "/login", query: { returnUrl: router.currentRoute.value.fullPath } });
|
||||||
|
return Promise.reject();
|
||||||
}
|
}
|
||||||
|
|
||||||
const error = { message: (data && data.message) || response.statusText, status: response.status || 0 };
|
const error = { message: (data && data.message) || response.statusText, status: response.status || 0 };
|
||||||
|
router.push({ name: "Error", params: error });
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -188,8 +188,8 @@ export default defineComponent({
|
|||||||
fetch("/api/config/get?file=" + this.backupFileSelect, { headers: authHeader() })
|
fetch("/api/config/get?file=" + this.backupFileSelect, { headers: authHeader() })
|
||||||
.then(res => res.blob())
|
.then(res => res.blob())
|
||||||
.then(blob => {
|
.then(blob => {
|
||||||
var file = window.URL.createObjectURL(blob);
|
const file = window.URL.createObjectURL(blob);
|
||||||
var a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
a.href = file;
|
a.href = file;
|
||||||
a.download = this.backupFileSelect;
|
a.download = this.backupFileSelect;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
|
|||||||
@ -56,7 +56,7 @@ export default defineComponent({
|
|||||||
watch: {
|
watch: {
|
||||||
consoleBuffer() {
|
consoleBuffer() {
|
||||||
if (this.isAutoScroll) {
|
if (this.isAutoScroll) {
|
||||||
let textarea = this.$el.querySelector("#console");
|
const textarea = this.$el.querySelector("#console");
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
textarea.scrollTop = textarea.scrollHeight;
|
textarea.scrollTop = textarea.scrollHeight;
|
||||||
}, 0);
|
}, 0);
|
||||||
@ -121,7 +121,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
this.heartInterval && clearTimeout(this.heartInterval);
|
this.heartInterval && clearTimeout(this.heartInterval);
|
||||||
},
|
},
|
||||||
getOutDate(): String {
|
getOutDate(): string {
|
||||||
const u = new Date();
|
const u = new Date();
|
||||||
return ('0' + u.getHours()).slice(-2) + ':' +
|
return ('0' + u.getHours()).slice(-2) + ':' +
|
||||||
('0' + u.getMinutes()).slice(-2) + ':' +
|
('0' + u.getMinutes()).slice(-2) + ':' +
|
||||||
@ -132,7 +132,7 @@ export default defineComponent({
|
|||||||
this.consoleBuffer = "";
|
this.consoleBuffer = "";
|
||||||
},
|
},
|
||||||
copyConsole() {
|
copyConsole() {
|
||||||
var input = document.createElement('textarea');
|
const input = document.createElement('textarea');
|
||||||
input.innerHTML = this.consoleBuffer;
|
input.innerHTML = this.consoleBuffer;
|
||||||
document.body.appendChild(input);
|
document.body.appendChild(input);
|
||||||
input.select();
|
input.select();
|
||||||
|
|||||||
18
webapp/src/views/ErrorView.vue
Normal file
18
webapp/src/views/ErrorView.vue
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<template>
|
||||||
|
<BasePage :title="$t('Error.Oops')">
|
||||||
|
<div class="alert alert-danger" role="alert">
|
||||||
|
<h2>{{ $route.params.message }}</h2>
|
||||||
|
</div>
|
||||||
|
</BasePage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import BasePage from '@/components/BasePage.vue';
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
BasePage,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@ -191,7 +191,7 @@ export default defineComponent({
|
|||||||
const remoteHostUrl = "/api/system/status";
|
const remoteHostUrl = "/api/system/status";
|
||||||
|
|
||||||
// Use a simple fetch request to check if the remote host is reachable
|
// Use a simple fetch request to check if the remote host is reachable
|
||||||
fetch(remoteHostUrl, { method: 'HEAD' })
|
fetch(remoteHostUrl, { method: 'GET' })
|
||||||
.then(response => {
|
.then(response => {
|
||||||
// Check if the response status is OK (200-299 range)
|
// Check if the response status is OK (200-299 range)
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
|
|||||||
@ -493,17 +493,15 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var self = this;
|
this.socket.onopen = (event) => {
|
||||||
|
|
||||||
this.socket.onopen = function (event) {
|
|
||||||
console.log(event);
|
console.log(event);
|
||||||
console.log("Successfully connected to the echo websocket server...");
|
console.log("Successfully connected to the echo websocket server...");
|
||||||
self.isWebsocketConnected = true;
|
this.isWebsocketConnected = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.socket.onclose = function () {
|
this.socket.onclose = () => {
|
||||||
console.log("Connection to websocket closed...")
|
console.log("Connection to websocket closed...")
|
||||||
self.isWebsocketConnected = false;
|
this.isWebsocketConnected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listen to window events , When the window closes , Take the initiative to disconnect websocket Connect
|
// Listen to window events , When the window closes , Take the initiative to disconnect websocket Connect
|
||||||
|
|||||||
@ -99,7 +99,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
allowVersionInfo(allow: Boolean) {
|
allowVersionInfo(allow: boolean) {
|
||||||
localStorage.setItem("allowVersionInfo", allow ? "1" : "0");
|
localStorage.setItem("allowVersionInfo", allow ? "1" : "0");
|
||||||
if (allow) {
|
if (allow) {
|
||||||
this.getUpdateInfo();
|
this.getUpdateInfo();
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import path from 'path'
|
|||||||
// example 'vite.user.ts': export const proxy_target = '192.168.16.107'
|
// example 'vite.user.ts': export const proxy_target = '192.168.16.107'
|
||||||
let proxy_target;
|
let proxy_target;
|
||||||
try {
|
try {
|
||||||
|
// eslint-disable-next-line
|
||||||
proxy_target = require('./vite.user.ts').proxy_target;
|
proxy_target = require('./vite.user.ts').proxy_target;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
proxy_target = '192.168.20.110';
|
proxy_target = '192.168.20.110';
|
||||||
|
|||||||
371
webapp/yarn.lock
371
webapp/yarn.lock
@ -156,32 +156,32 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.6.2.tgz#1816b5f6948029c5eaacb0703b850ee0cb37d8f8"
|
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.6.2.tgz#1816b5f6948029c5eaacb0703b850ee0cb37d8f8"
|
||||||
integrity sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==
|
integrity sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==
|
||||||
|
|
||||||
"@eslint/eslintrc@^2.1.4":
|
"@eslint/eslintrc@^3.0.2":
|
||||||
version "2.1.4"
|
version "3.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad"
|
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.0.2.tgz#36180f8e85bf34d2fe3ccc2261e8e204a411ab4e"
|
||||||
integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==
|
integrity sha512-wV19ZEGEMAC1eHgrS7UQPqsdEiCIbTKTasEfcXAigzoXICcqZSjBZEHlZwNVvKg6UBCjSlos84XiLqsRJnIcIg==
|
||||||
dependencies:
|
dependencies:
|
||||||
ajv "^6.12.4"
|
ajv "^6.12.4"
|
||||||
debug "^4.3.2"
|
debug "^4.3.2"
|
||||||
espree "^9.6.0"
|
espree "^10.0.1"
|
||||||
globals "^13.19.0"
|
globals "^14.0.0"
|
||||||
ignore "^5.2.0"
|
ignore "^5.2.0"
|
||||||
import-fresh "^3.2.1"
|
import-fresh "^3.2.1"
|
||||||
js-yaml "^4.1.0"
|
js-yaml "^4.1.0"
|
||||||
minimatch "^3.1.2"
|
minimatch "^3.1.2"
|
||||||
strip-json-comments "^3.1.1"
|
strip-json-comments "^3.1.1"
|
||||||
|
|
||||||
"@eslint/js@8.57.0":
|
"@eslint/js@9.0.0":
|
||||||
version "8.57.0"
|
version "9.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f"
|
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.0.0.tgz#1a9e4b4c96d8c7886e0110ed310a0135144a1691"
|
||||||
integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==
|
integrity sha512-RThY/MnKrhubF6+s1JflwUjPEsnCEmYCWwqa/aRISKWNXGZ9epUwft4bUMM35SdKF9xvBrLydAM1RDHd1Z//ZQ==
|
||||||
|
|
||||||
"@humanwhocodes/config-array@^0.11.14":
|
"@humanwhocodes/config-array@^0.12.3":
|
||||||
version "0.11.14"
|
version "0.12.3"
|
||||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b"
|
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.12.3.tgz#a6216d90f81a30bedd1d4b5d799b47241f318072"
|
||||||
integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==
|
integrity sha512-jsNnTBlMWuTpDkeE3on7+dWJi0D6fdDfeANj/w7MpS8ztROCoLvIO2nG0CcFj+E4k8j4QrSTh4Oryi3i2G669g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@humanwhocodes/object-schema" "^2.0.2"
|
"@humanwhocodes/object-schema" "^2.0.3"
|
||||||
debug "^4.3.1"
|
debug "^4.3.1"
|
||||||
minimatch "^3.0.5"
|
minimatch "^3.0.5"
|
||||||
|
|
||||||
@ -190,10 +190,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
|
resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
|
||||||
integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
|
integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
|
||||||
|
|
||||||
"@humanwhocodes/object-schema@^2.0.2":
|
"@humanwhocodes/object-schema@^2.0.3":
|
||||||
version "2.0.2"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917"
|
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3"
|
||||||
integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==
|
integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==
|
||||||
|
|
||||||
"@intlify/bundle-utils@^8.0.0":
|
"@intlify/bundle-utils@^8.0.0":
|
||||||
version "8.0.0"
|
version "8.0.0"
|
||||||
@ -210,20 +210,20 @@
|
|||||||
source-map-js "^1.0.1"
|
source-map-js "^1.0.1"
|
||||||
yaml-eslint-parser "^1.2.2"
|
yaml-eslint-parser "^1.2.2"
|
||||||
|
|
||||||
"@intlify/core-base@9.10.2":
|
"@intlify/core-base@9.12.0":
|
||||||
version "9.10.2"
|
version "9.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/@intlify/core-base/-/core-base-9.10.2.tgz#e7f8857f8011184e4afbdcfae7dbd85c50ba5271"
|
resolved "https://registry.yarnpkg.com/@intlify/core-base/-/core-base-9.12.0.tgz#79f43faa8eb1f3b2bfe569a9fbae9bc50908d311"
|
||||||
integrity sha512-HGStVnKobsJL0DoYIyRCGXBH63DMQqEZxDUGrkNI05FuTcruYUtOAxyL3zoAZu/uDGO6mcUvm3VXBaHG2GdZCg==
|
integrity sha512-6EnWQXHnCh2bMiXT5N/IWwkcYQXjmF8nnEZ3YhTm23h1ZfOylz83D7pJYhcU8CsTiEdgbGiNdqyZPKwrHw03Ng==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@intlify/message-compiler" "9.10.2"
|
"@intlify/message-compiler" "9.12.0"
|
||||||
"@intlify/shared" "9.10.2"
|
"@intlify/shared" "9.12.0"
|
||||||
|
|
||||||
"@intlify/message-compiler@9.10.2":
|
"@intlify/message-compiler@9.12.0":
|
||||||
version "9.10.2"
|
version "9.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/@intlify/message-compiler/-/message-compiler-9.10.2.tgz#c44cbb915bdd0d62780a38595a84006c781f717a"
|
resolved "https://registry.yarnpkg.com/@intlify/message-compiler/-/message-compiler-9.12.0.tgz#5e152344853c29369911bd5e541e061b09218333"
|
||||||
integrity sha512-ntY/kfBwQRtX5Zh6wL8cSATujPzWW2ZQd1QwKyWwAy5fMqJyyixHMeovN4fmEyCqSu+hFfYOE63nU94evsy4YA==
|
integrity sha512-2c6VwhvVJ1nur+2cN2NjdrmrV6vXjvyxYVvtUYMXKsWSUwoNURHGds0xJVJmWxbF8qV9oGepcVV6xl9bvadEIg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@intlify/shared" "9.10.2"
|
"@intlify/shared" "9.12.0"
|
||||||
source-map-js "^1.0.2"
|
source-map-js "^1.0.2"
|
||||||
|
|
||||||
"@intlify/message-compiler@^9.4.0":
|
"@intlify/message-compiler@^9.4.0":
|
||||||
@ -234,10 +234,10 @@
|
|||||||
"@intlify/shared" "9.4.0"
|
"@intlify/shared" "9.4.0"
|
||||||
source-map-js "^1.0.2"
|
source-map-js "^1.0.2"
|
||||||
|
|
||||||
"@intlify/shared@9.10.2":
|
"@intlify/shared@9.12.0":
|
||||||
version "9.10.2"
|
version "9.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-9.10.2.tgz#693300ea033868cbe4086b832170612f002e24a9"
|
resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-9.12.0.tgz#993383b6a98c8e37a1fa184a677eb39635a14a1c"
|
||||||
integrity sha512-ttHCAJkRy7R5W2S9RVnN9KYQYPIpV2+GiS79T4EE37nrPyH6/1SrOh3bmdCRC1T3ocL8qCDx7x2lBJ0xaITU7Q==
|
integrity sha512-uBcH55x5CfZynnerWHQxrXbT6yD6j6T7Nt+R2+dHAOAneoMd6BoGvfEzfYscE94rgmjoDqdr+PdGDBLk5I5EjA==
|
||||||
|
|
||||||
"@intlify/shared@9.4.0", "@intlify/shared@^9.4.0":
|
"@intlify/shared@9.4.0", "@intlify/shared@^9.4.0":
|
||||||
version "9.4.0"
|
version "9.4.0"
|
||||||
@ -412,11 +412,6 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.0.tgz#6abd79db7ff8d01a58865ba20a63cfd23d9e2a10"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.0.tgz#6abd79db7ff8d01a58865ba20a63cfd23d9e2a10"
|
||||||
integrity sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw==
|
integrity sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw==
|
||||||
|
|
||||||
"@rushstack/eslint-patch@^1.10.1":
|
|
||||||
version "1.10.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.1.tgz#7ca168b6937818e9a74b47ac4e2112b2e1a024cf"
|
|
||||||
integrity sha512-S3Kq8e7LqxkA9s7HKLqXGTGck1uwis5vAXan3FnU5yw1Ec5hsSGnq4s/UCaSqABPOnOTg7zASLyst7+ohgWexg==
|
|
||||||
|
|
||||||
"@tsconfig/node18@^18.2.4":
|
"@tsconfig/node18@^18.2.4":
|
||||||
version "18.2.4"
|
version "18.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/@tsconfig/node18/-/node18-18.2.4.tgz#094efbdd70f697d37c09f34067bf41bc4a828ae3"
|
resolved "https://registry.yarnpkg.com/@tsconfig/node18/-/node18-18.2.4.tgz#094efbdd70f697d37c09f34067bf41bc4a828ae3"
|
||||||
@ -444,10 +439,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb"
|
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb"
|
||||||
integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==
|
integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==
|
||||||
|
|
||||||
"@types/node@^20.12.2":
|
"@types/node@^20.12.7":
|
||||||
version "20.12.2"
|
version "20.12.7"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.2.tgz#9facdd11102f38b21b4ebedd9d7999663343d72e"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.7.tgz#04080362fa3dd6c5822061aa3124f5c152cff384"
|
||||||
integrity sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==
|
integrity sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types "~5.26.4"
|
undici-types "~5.26.4"
|
||||||
|
|
||||||
@ -557,36 +552,31 @@
|
|||||||
"@typescript-eslint/types" "7.2.0"
|
"@typescript-eslint/types" "7.2.0"
|
||||||
eslint-visitor-keys "^3.4.1"
|
eslint-visitor-keys "^3.4.1"
|
||||||
|
|
||||||
"@ungap/structured-clone@^1.2.0":
|
|
||||||
version "1.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406"
|
|
||||||
integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==
|
|
||||||
|
|
||||||
"@vitejs/plugin-vue@^5.0.4":
|
"@vitejs/plugin-vue@^5.0.4":
|
||||||
version "5.0.4"
|
version "5.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz#508d6a0f2440f86945835d903fcc0d95d1bb8a37"
|
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz#508d6a0f2440f86945835d903fcc0d95d1bb8a37"
|
||||||
integrity sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==
|
integrity sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==
|
||||||
|
|
||||||
"@volar/language-core@2.1.3", "@volar/language-core@~2.1.3":
|
"@volar/language-core@2.2.0-alpha.8":
|
||||||
version "2.1.3"
|
version "2.2.0-alpha.8"
|
||||||
resolved "https://registry.yarnpkg.com/@volar/language-core/-/language-core-2.1.3.tgz#ac6057ec73c5fcda1fc07677bf0d7be41e6c59b1"
|
resolved "https://registry.yarnpkg.com/@volar/language-core/-/language-core-2.2.0-alpha.8.tgz#74120a27ff2498ad297e86d17be95a9c7e1b46f5"
|
||||||
integrity sha512-F93KYZYqcYltG7NihfnLt/omMZOtrQtsh2+wj+cgx3xolopU+TZvmwlZWOjw3ObZGFj3SKBb4jJn6VSfSch6RA==
|
integrity sha512-Ew1Iw7/RIRNuDLn60fWJdOLApAlfTVPxbPiSLzc434PReC9kleYtaa//Wo2WlN1oiRqneW0pWQQV0CwYqaimLQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@volar/source-map" "2.1.3"
|
"@volar/source-map" "2.2.0-alpha.8"
|
||||||
|
|
||||||
"@volar/source-map@2.1.3":
|
"@volar/source-map@2.2.0-alpha.8":
|
||||||
version "2.1.3"
|
version "2.2.0-alpha.8"
|
||||||
resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-2.1.3.tgz#8f3cb110019c45fa4cd47ad2f5fe5469bd54b9e3"
|
resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-2.2.0-alpha.8.tgz#ca090f828fbef7e09ea06a636c41a06aa2afe153"
|
||||||
integrity sha512-j+R+NG/OlDgdNMttADxNuSM9Z26StT/Bjw0NgSydI05Vihngn9zvaP/xXwfWs5qQrRzbKVFxJebS2ks5m/URuA==
|
integrity sha512-E1ZVmXFJ5DU4fWDcWHzi8OLqqReqIDwhXvIMhVdk6+VipfMVv4SkryXu7/rs4GA/GsebcRyJdaSkKBB3OAkIcA==
|
||||||
dependencies:
|
dependencies:
|
||||||
muggle-string "^0.4.0"
|
muggle-string "^0.4.0"
|
||||||
|
|
||||||
"@volar/typescript@~2.1.3":
|
"@volar/typescript@2.2.0-alpha.8":
|
||||||
version "2.1.3"
|
version "2.2.0-alpha.8"
|
||||||
resolved "https://registry.yarnpkg.com/@volar/typescript/-/typescript-2.1.3.tgz#bfdc901afd44c2d05697967211aa55d53fb8bf69"
|
resolved "https://registry.yarnpkg.com/@volar/typescript/-/typescript-2.2.0-alpha.8.tgz#83a056c52995b4142364be3dda41d955a96f7356"
|
||||||
integrity sha512-ZZqLMih4mvu2eJAW3UCFm84OM/ojYMoA/BU/W1TctT5F2nVzNJmW4jxMWmP3wQzxCbATfTa5gLb1+BSI9NBMBg==
|
integrity sha512-RLbRDI+17CiayHZs9HhSzlH0FhLl/+XK6o2qoiw2o2GGKcyD1aDoY6AcMd44acYncTOrqoTNoY6LuCiRyiJiGg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@volar/language-core" "2.1.3"
|
"@volar/language-core" "2.2.0-alpha.8"
|
||||||
path-browserify "^1.0.1"
|
path-browserify "^1.0.1"
|
||||||
|
|
||||||
"@vue/compiler-core@3.2.47":
|
"@vue/compiler-core@3.2.47":
|
||||||
@ -692,12 +682,12 @@
|
|||||||
"@typescript-eslint/parser" "^7.1.1"
|
"@typescript-eslint/parser" "^7.1.1"
|
||||||
vue-eslint-parser "^9.3.1"
|
vue-eslint-parser "^9.3.1"
|
||||||
|
|
||||||
"@vue/language-core@2.0.7":
|
"@vue/language-core@2.0.13":
|
||||||
version "2.0.7"
|
version "2.0.13"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/language-core/-/language-core-2.0.7.tgz#af12f752a93c4d2498626fca33f5d1ddc8c5ceb9"
|
resolved "https://registry.yarnpkg.com/@vue/language-core/-/language-core-2.0.13.tgz#2d1638b882011187b4b57115425d52b0901acab5"
|
||||||
integrity sha512-Vh1yZX3XmYjn9yYLkjU8DN6L0ceBtEcapqiyclHne8guG84IaTzqtvizZB1Yfxm3h6m7EIvjerLO5fvOZO6IIQ==
|
integrity sha512-oQgM+BM66SU5GKtUMLQSQN0bxHFkFpLSSAiY87wVziPaiNQZuKVDt/3yA7GB9PiQw0y/bTNL0bOc0jM/siYjKg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@volar/language-core" "~2.1.3"
|
"@volar/language-core" "2.2.0-alpha.8"
|
||||||
"@vue/compiler-dom" "^3.4.0"
|
"@vue/compiler-dom" "^3.4.0"
|
||||||
"@vue/shared" "^3.4.0"
|
"@vue/shared" "^3.4.0"
|
||||||
computeds "^0.0.1"
|
computeds "^0.0.1"
|
||||||
@ -768,6 +758,11 @@ acorn-jsx@^5.3.2:
|
|||||||
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
|
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
|
||||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||||
|
|
||||||
|
acorn@^8.11.3:
|
||||||
|
version "8.11.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a"
|
||||||
|
integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==
|
||||||
|
|
||||||
acorn@^8.5.0, acorn@^8.9.0:
|
acorn@^8.5.0, acorn@^8.9.0:
|
||||||
version "8.10.0"
|
version "8.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
|
||||||
@ -1028,13 +1023,6 @@ dir-glob@^3.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
path-type "^4.0.0"
|
path-type "^4.0.0"
|
||||||
|
|
||||||
doctrine@^3.0.0:
|
|
||||||
version "3.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
|
|
||||||
integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
|
|
||||||
dependencies:
|
|
||||||
esutils "^2.0.2"
|
|
||||||
|
|
||||||
entities@^4.5.0:
|
entities@^4.5.0:
|
||||||
version "4.5.0"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
|
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
|
||||||
@ -1136,10 +1124,10 @@ escodegen@^2.1.0:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
source-map "~0.6.1"
|
source-map "~0.6.1"
|
||||||
|
|
||||||
eslint-plugin-vue@^9.24.0:
|
eslint-plugin-vue@^9.24.1:
|
||||||
version "9.24.0"
|
version "9.24.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.24.0.tgz#71209f4652ee767f18c0bf56f25991b7cdc5aa46"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.24.1.tgz#0d90330c939f9dd2f4c759da5a2ad91dc1c8bac4"
|
||||||
integrity sha512-9SkJMvF8NGMT9aQCwFc5rj8Wo1XWSMSHk36i7ZwdI614BU7sIOR28ZjuFPKp8YGymZN12BSEbiSwa7qikp+PBw==
|
integrity sha512-wk3SuwmS1pZdcuJlokGYEi/buDOwD6KltvhIZyOnpJ/378dcQ4zchu9PAMbbLAaydCz1iYc5AozszcOOgZIIOg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@eslint-community/eslint-utils" "^4.4.0"
|
"@eslint-community/eslint-utils" "^4.4.0"
|
||||||
globals "^13.24.0"
|
globals "^13.24.0"
|
||||||
@ -1158,15 +1146,15 @@ eslint-scope@^7.1.1:
|
|||||||
esrecurse "^4.3.0"
|
esrecurse "^4.3.0"
|
||||||
estraverse "^5.2.0"
|
estraverse "^5.2.0"
|
||||||
|
|
||||||
eslint-scope@^7.2.2:
|
eslint-scope@^8.0.1:
|
||||||
version "7.2.2"
|
version "8.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f"
|
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.0.1.tgz#a9601e4b81a0b9171657c343fb13111688963cfc"
|
||||||
integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==
|
integrity sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==
|
||||||
dependencies:
|
dependencies:
|
||||||
esrecurse "^4.3.0"
|
esrecurse "^4.3.0"
|
||||||
estraverse "^5.2.0"
|
estraverse "^5.2.0"
|
||||||
|
|
||||||
eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.4.3:
|
eslint-visitor-keys@^3.0.0:
|
||||||
version "3.4.3"
|
version "3.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
||||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||||
@ -1181,41 +1169,42 @@ eslint-visitor-keys@^3.4.1:
|
|||||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994"
|
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994"
|
||||||
integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==
|
integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==
|
||||||
|
|
||||||
eslint@^8.57.0:
|
eslint-visitor-keys@^4.0.0:
|
||||||
version "8.57.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668"
|
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb"
|
||||||
integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==
|
integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==
|
||||||
|
|
||||||
|
eslint@^9.0.0:
|
||||||
|
version "9.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.0.0.tgz#6270548758e390343f78c8afd030566d86927d40"
|
||||||
|
integrity sha512-IMryZ5SudxzQvuod6rUdIUz29qFItWx281VhtFVc2Psy/ZhlCeD/5DT6lBIJ4H3G+iamGJoTln1v+QSuPw0p7Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@eslint-community/eslint-utils" "^4.2.0"
|
"@eslint-community/eslint-utils" "^4.2.0"
|
||||||
"@eslint-community/regexpp" "^4.6.1"
|
"@eslint-community/regexpp" "^4.6.1"
|
||||||
"@eslint/eslintrc" "^2.1.4"
|
"@eslint/eslintrc" "^3.0.2"
|
||||||
"@eslint/js" "8.57.0"
|
"@eslint/js" "9.0.0"
|
||||||
"@humanwhocodes/config-array" "^0.11.14"
|
"@humanwhocodes/config-array" "^0.12.3"
|
||||||
"@humanwhocodes/module-importer" "^1.0.1"
|
"@humanwhocodes/module-importer" "^1.0.1"
|
||||||
"@nodelib/fs.walk" "^1.2.8"
|
"@nodelib/fs.walk" "^1.2.8"
|
||||||
"@ungap/structured-clone" "^1.2.0"
|
|
||||||
ajv "^6.12.4"
|
ajv "^6.12.4"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
cross-spawn "^7.0.2"
|
cross-spawn "^7.0.2"
|
||||||
debug "^4.3.2"
|
debug "^4.3.2"
|
||||||
doctrine "^3.0.0"
|
|
||||||
escape-string-regexp "^4.0.0"
|
escape-string-regexp "^4.0.0"
|
||||||
eslint-scope "^7.2.2"
|
eslint-scope "^8.0.1"
|
||||||
eslint-visitor-keys "^3.4.3"
|
eslint-visitor-keys "^4.0.0"
|
||||||
espree "^9.6.1"
|
espree "^10.0.1"
|
||||||
esquery "^1.4.2"
|
esquery "^1.4.2"
|
||||||
esutils "^2.0.2"
|
esutils "^2.0.2"
|
||||||
fast-deep-equal "^3.1.3"
|
fast-deep-equal "^3.1.3"
|
||||||
file-entry-cache "^6.0.1"
|
file-entry-cache "^8.0.0"
|
||||||
find-up "^5.0.0"
|
find-up "^5.0.0"
|
||||||
glob-parent "^6.0.2"
|
glob-parent "^6.0.2"
|
||||||
globals "^13.19.0"
|
|
||||||
graphemer "^1.4.0"
|
graphemer "^1.4.0"
|
||||||
ignore "^5.2.0"
|
ignore "^5.2.0"
|
||||||
imurmurhash "^0.1.4"
|
imurmurhash "^0.1.4"
|
||||||
is-glob "^4.0.0"
|
is-glob "^4.0.0"
|
||||||
is-path-inside "^3.0.3"
|
is-path-inside "^3.0.3"
|
||||||
js-yaml "^4.1.0"
|
|
||||||
json-stable-stringify-without-jsonify "^1.0.1"
|
json-stable-stringify-without-jsonify "^1.0.1"
|
||||||
levn "^0.4.1"
|
levn "^0.4.1"
|
||||||
lodash.merge "^4.6.2"
|
lodash.merge "^4.6.2"
|
||||||
@ -1225,7 +1214,16 @@ eslint@^8.57.0:
|
|||||||
strip-ansi "^6.0.1"
|
strip-ansi "^6.0.1"
|
||||||
text-table "^0.2.0"
|
text-table "^0.2.0"
|
||||||
|
|
||||||
espree@^9.0.0, espree@^9.6.1:
|
espree@^10.0.1:
|
||||||
|
version "10.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/espree/-/espree-10.0.1.tgz#600e60404157412751ba4a6f3a2ee1a42433139f"
|
||||||
|
integrity sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==
|
||||||
|
dependencies:
|
||||||
|
acorn "^8.11.3"
|
||||||
|
acorn-jsx "^5.3.2"
|
||||||
|
eslint-visitor-keys "^4.0.0"
|
||||||
|
|
||||||
|
espree@^9.0.0:
|
||||||
version "9.6.1"
|
version "9.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f"
|
resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f"
|
||||||
integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==
|
integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==
|
||||||
@ -1243,15 +1241,6 @@ espree@^9.3.1:
|
|||||||
acorn-jsx "^5.3.2"
|
acorn-jsx "^5.3.2"
|
||||||
eslint-visitor-keys "^3.3.0"
|
eslint-visitor-keys "^3.3.0"
|
||||||
|
|
||||||
espree@^9.6.0:
|
|
||||||
version "9.6.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.0.tgz#80869754b1c6560f32e3b6929194a3fe07c5b82f"
|
|
||||||
integrity sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==
|
|
||||||
dependencies:
|
|
||||||
acorn "^8.9.0"
|
|
||||||
acorn-jsx "^5.3.2"
|
|
||||||
eslint-visitor-keys "^3.4.1"
|
|
||||||
|
|
||||||
esprima@^4.0.1:
|
esprima@^4.0.1:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
|
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
|
||||||
@ -1337,12 +1326,12 @@ fastq@^1.6.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
reusify "^1.0.4"
|
reusify "^1.0.4"
|
||||||
|
|
||||||
file-entry-cache@^6.0.1:
|
file-entry-cache@^8.0.0:
|
||||||
version "6.0.1"
|
version "8.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
|
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f"
|
||||||
integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==
|
integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
flat-cache "^3.0.4"
|
flat-cache "^4.0.0"
|
||||||
|
|
||||||
fill-range@^7.0.1:
|
fill-range@^7.0.1:
|
||||||
version "7.0.1"
|
version "7.0.1"
|
||||||
@ -1359,18 +1348,18 @@ find-up@^5.0.0:
|
|||||||
locate-path "^6.0.0"
|
locate-path "^6.0.0"
|
||||||
path-exists "^4.0.0"
|
path-exists "^4.0.0"
|
||||||
|
|
||||||
flat-cache@^3.0.4:
|
flat-cache@^4.0.0:
|
||||||
version "3.0.4"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
|
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c"
|
||||||
integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==
|
integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==
|
||||||
dependencies:
|
dependencies:
|
||||||
flatted "^3.1.0"
|
flatted "^3.2.9"
|
||||||
rimraf "^3.0.2"
|
keyv "^4.5.4"
|
||||||
|
|
||||||
flatted@^3.1.0:
|
flatted@^3.2.9:
|
||||||
version "3.2.5"
|
version "3.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3"
|
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
|
||||||
integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==
|
integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==
|
||||||
|
|
||||||
fs-extra@^10.0.0:
|
fs-extra@^10.0.0:
|
||||||
version "10.1.0"
|
version "10.1.0"
|
||||||
@ -1381,11 +1370,6 @@ fs-extra@^10.0.0:
|
|||||||
jsonfile "^6.0.1"
|
jsonfile "^6.0.1"
|
||||||
universalify "^2.0.0"
|
universalify "^2.0.0"
|
||||||
|
|
||||||
fs.realpath@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
|
||||||
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
|
||||||
|
|
||||||
fsevents@~2.3.2:
|
fsevents@~2.3.2:
|
||||||
version "2.3.2"
|
version "2.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
||||||
@ -1447,25 +1431,6 @@ glob-parent@^6.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-glob "^4.0.3"
|
is-glob "^4.0.3"
|
||||||
|
|
||||||
glob@^7.1.3:
|
|
||||||
version "7.2.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
|
|
||||||
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
|
|
||||||
dependencies:
|
|
||||||
fs.realpath "^1.0.0"
|
|
||||||
inflight "^1.0.4"
|
|
||||||
inherits "2"
|
|
||||||
minimatch "^3.1.1"
|
|
||||||
once "^1.3.0"
|
|
||||||
path-is-absolute "^1.0.0"
|
|
||||||
|
|
||||||
globals@^13.19.0:
|
|
||||||
version "13.19.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/globals/-/globals-13.19.0.tgz#7a42de8e6ad4f7242fbcca27ea5b23aca367b5c8"
|
|
||||||
integrity sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==
|
|
||||||
dependencies:
|
|
||||||
type-fest "^0.20.2"
|
|
||||||
|
|
||||||
globals@^13.24.0:
|
globals@^13.24.0:
|
||||||
version "13.24.0"
|
version "13.24.0"
|
||||||
resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171"
|
resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171"
|
||||||
@ -1473,6 +1438,11 @@ globals@^13.24.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
type-fest "^0.20.2"
|
type-fest "^0.20.2"
|
||||||
|
|
||||||
|
globals@^14.0.0:
|
||||||
|
version "14.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e"
|
||||||
|
integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==
|
||||||
|
|
||||||
globby@^11.1.0:
|
globby@^11.1.0:
|
||||||
version "11.1.0"
|
version "11.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
|
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
|
||||||
@ -1574,19 +1544,6 @@ imurmurhash@^0.1.4:
|
|||||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||||
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
|
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
|
||||||
|
|
||||||
inflight@^1.0.4:
|
|
||||||
version "1.0.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
|
||||||
integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
|
|
||||||
dependencies:
|
|
||||||
once "^1.3.0"
|
|
||||||
wrappy "1"
|
|
||||||
|
|
||||||
inherits@2:
|
|
||||||
version "2.0.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
|
||||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
|
||||||
|
|
||||||
internal-slot@^1.0.3:
|
internal-slot@^1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c"
|
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c"
|
||||||
@ -1724,6 +1681,11 @@ js-yaml@^4.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
argparse "^2.0.1"
|
argparse "^2.0.1"
|
||||||
|
|
||||||
|
json-buffer@3.0.1:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
|
||||||
|
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
|
||||||
|
|
||||||
json-parse-better-errors@^1.0.1:
|
json-parse-better-errors@^1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
|
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
|
||||||
@ -1768,6 +1730,13 @@ jsonfile@^6.0.1:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
graceful-fs "^4.1.6"
|
graceful-fs "^4.1.6"
|
||||||
|
|
||||||
|
keyv@^4.5.4:
|
||||||
|
version "4.5.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
|
||||||
|
integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==
|
||||||
|
dependencies:
|
||||||
|
json-buffer "3.0.1"
|
||||||
|
|
||||||
levn@^0.4.1:
|
levn@^0.4.1:
|
||||||
version "0.4.1"
|
version "0.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
|
resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
|
||||||
@ -1849,7 +1818,7 @@ minimatch@9.0.3, minimatch@^9.0.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion "^2.0.1"
|
brace-expansion "^2.0.1"
|
||||||
|
|
||||||
minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2:
|
||||||
version "3.1.2"
|
version "3.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||||
@ -1958,13 +1927,6 @@ object.assign@^4.1.4:
|
|||||||
has-symbols "^1.0.3"
|
has-symbols "^1.0.3"
|
||||||
object-keys "^1.1.1"
|
object-keys "^1.1.1"
|
||||||
|
|
||||||
once@^1.3.0:
|
|
||||||
version "1.4.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
|
||||||
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
|
|
||||||
dependencies:
|
|
||||||
wrappy "1"
|
|
||||||
|
|
||||||
optionator@^0.9.3:
|
optionator@^0.9.3:
|
||||||
version "0.9.3"
|
version "0.9.3"
|
||||||
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64"
|
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64"
|
||||||
@ -2016,11 +1978,6 @@ path-exists@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
|
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
|
||||||
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
|
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
|
||||||
|
|
||||||
path-is-absolute@^1.0.0:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
|
||||||
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
|
||||||
|
|
||||||
path-key@^2.0.1:
|
path-key@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
|
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
|
||||||
@ -2181,13 +2138,6 @@ reusify@^1.0.4:
|
|||||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||||
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
||||||
|
|
||||||
rimraf@^3.0.2:
|
|
||||||
version "3.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
|
|
||||||
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
|
|
||||||
dependencies:
|
|
||||||
glob "^7.1.3"
|
|
||||||
|
|
||||||
rollup@^4.13.0:
|
rollup@^4.13.0:
|
||||||
version "4.13.0"
|
version "4.13.0"
|
||||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.13.0.tgz#dd2ae144b4cdc2ea25420477f68d4937a721237a"
|
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.13.0.tgz#dd2ae144b4cdc2ea25420477f68d4937a721237a"
|
||||||
@ -2226,10 +2176,10 @@ safe-regex-test@^1.0.0:
|
|||||||
get-intrinsic "^1.1.3"
|
get-intrinsic "^1.1.3"
|
||||||
is-regex "^1.1.4"
|
is-regex "^1.1.4"
|
||||||
|
|
||||||
sass@^1.72.0:
|
sass@^1.75.0:
|
||||||
version "1.72.0"
|
version "1.75.0"
|
||||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.72.0.tgz#5b9978943fcfb32b25a6a5acb102fc9dabbbf41c"
|
resolved "https://registry.yarnpkg.com/sass/-/sass-1.75.0.tgz#91bbe87fb02dfcc34e052ddd6ab80f60d392be6c"
|
||||||
integrity sha512-Gpczt3WA56Ly0Mn8Sl21Vj94s1axi9hDIzDFn9Ph9x3C3p4nNyvsqJoQyVXKou6cBlfFWEgRW4rT8Tb4i3XnVA==
|
integrity sha512-ShMYi3WkrDWxExyxSZPst4/okE9ts46xZmJDSawJQrnte7M1V9fScVB+uNXOVKRBt0PggHOwoZcn8mYX4trnBw==
|
||||||
dependencies:
|
dependencies:
|
||||||
chokidar ">=3.0.0 <4.0.0"
|
chokidar ">=3.0.0 <4.0.0"
|
||||||
immutable "^4.0.0"
|
immutable "^4.0.0"
|
||||||
@ -2431,10 +2381,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"
|
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||||
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||||
|
|
||||||
terser@^5.30.0:
|
terser@^5.30.3:
|
||||||
version "5.30.0"
|
version "5.30.3"
|
||||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.30.0.tgz#64cb2af71e16ea3d32153f84d990f9be0cdc22bf"
|
resolved "https://registry.yarnpkg.com/terser/-/terser-5.30.3.tgz#f1bb68ded42408c316b548e3ec2526d7dd03f4d2"
|
||||||
integrity sha512-Y/SblUl5kEyEFzhMAQdsxVHh+utAxd4IuRNJzKywY/4uzSogh3G219jqbDDxYu4MXO9CzY3tSEqmZvW6AoEDJw==
|
integrity sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jridgewell/source-map" "^0.3.3"
|
"@jridgewell/source-map" "^0.3.3"
|
||||||
acorn "^8.8.2"
|
acorn "^8.8.2"
|
||||||
@ -2470,10 +2420,10 @@ type-fest@^0.20.2:
|
|||||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
|
||||||
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
|
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
|
||||||
|
|
||||||
typescript@^5.4.3:
|
typescript@^5.4.5:
|
||||||
version "5.4.3"
|
version "5.4.5"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611"
|
||||||
integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==
|
integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==
|
||||||
|
|
||||||
ufo@^1.1.2:
|
ufo@^1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
@ -2544,10 +2494,10 @@ vite-plugin-css-injected-by-js@^3.5.0:
|
|||||||
resolved "https://registry.yarnpkg.com/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-3.5.0.tgz#784c0f42c2b42155eb4c726c6addfa24aba9f4fb"
|
resolved "https://registry.yarnpkg.com/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-3.5.0.tgz#784c0f42c2b42155eb4c726c6addfa24aba9f4fb"
|
||||||
integrity sha512-d0QaHH9kS93J25SwRqJNEfE29PSuQS5jn51y9N9i2Yoq0FRO7rjuTeLvjM5zwklZlRrIn6SUdtOEDKyHokgJZg==
|
integrity sha512-d0QaHH9kS93J25SwRqJNEfE29PSuQS5jn51y9N9i2Yoq0FRO7rjuTeLvjM5zwklZlRrIn6SUdtOEDKyHokgJZg==
|
||||||
|
|
||||||
vite@^5.2.7:
|
vite@^5.2.8:
|
||||||
version "5.2.7"
|
version "5.2.8"
|
||||||
resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.7.tgz#e1b8a985eb54fcb9467d7f7f009d87485016df6e"
|
resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.8.tgz#a99e09939f1a502992381395ce93efa40a2844aa"
|
||||||
integrity sha512-k14PWOKLI6pMaSzAuGtT+Cf0YmIx12z9YGon39onaJNy8DLBfBJrzg9FQEmkAM5lpHBZs9wksWAsyF/HkpEwJA==
|
integrity sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild "^0.20.1"
|
esbuild "^0.20.1"
|
||||||
postcss "^8.4.38"
|
postcss "^8.4.38"
|
||||||
@ -2581,13 +2531,13 @@ vue-eslint-parser@^9.4.2:
|
|||||||
lodash "^4.17.21"
|
lodash "^4.17.21"
|
||||||
semver "^7.3.6"
|
semver "^7.3.6"
|
||||||
|
|
||||||
vue-i18n@^9.10.2:
|
vue-i18n@^9.12.0:
|
||||||
version "9.10.2"
|
version "9.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-9.10.2.tgz#6f4b5d76bce649f1e18bb9b7767b72962b3e30a3"
|
resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-9.12.0.tgz#8d073b3d7b92e822dcc3268946af4ecf14b778b3"
|
||||||
integrity sha512-ECJ8RIFd+3c1d3m1pctQ6ywG5Yj8Efy1oYoAKQ9neRdkLbuKLVeW4gaY5HPkD/9ssf1pOnUrmIFjx2/gkGxmEw==
|
integrity sha512-rUxCKTws8NH3XP98W71GA7btAQdAuO7j6BC5y5s1bTNQYo/CIgZQf+p7d1Zo5bo/3v8TIq9aSUMDjpfgKsC3Uw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@intlify/core-base" "9.10.2"
|
"@intlify/core-base" "9.12.0"
|
||||||
"@intlify/shared" "9.10.2"
|
"@intlify/shared" "9.12.0"
|
||||||
"@vue/devtools-api" "^6.5.0"
|
"@vue/devtools-api" "^6.5.0"
|
||||||
|
|
||||||
vue-router@^4.3.0:
|
vue-router@^4.3.0:
|
||||||
@ -2605,13 +2555,13 @@ vue-template-compiler@^2.7.14:
|
|||||||
de-indent "^1.0.2"
|
de-indent "^1.0.2"
|
||||||
he "^1.2.0"
|
he "^1.2.0"
|
||||||
|
|
||||||
vue-tsc@^2.0.7:
|
vue-tsc@^2.0.13:
|
||||||
version "2.0.7"
|
version "2.0.13"
|
||||||
resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-2.0.7.tgz#3177a2fe720bfa7355d3717929ee8c8d132bc5d0"
|
resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-2.0.13.tgz#6ee557705456442e0f43ec0d1774ebf5ffec54f1"
|
||||||
integrity sha512-LYa0nInkfcDBB7y8jQ9FQ4riJTRNTdh98zK/hzt4gEpBZQmf30dPhP+odzCa+cedGz6B/guvJEd0BavZaRptjg==
|
integrity sha512-a3nL3FvguCWVJUQW/jFrUxdeUtiEkbZoQjidqvMeBK//tuE2w6NWQAbdrEpY2+6nSa4kZoKZp8TZUMtHpjt4mQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@volar/typescript" "~2.1.3"
|
"@volar/typescript" "2.2.0-alpha.8"
|
||||||
"@vue/language-core" "2.0.7"
|
"@vue/language-core" "2.0.13"
|
||||||
semver "^7.5.4"
|
semver "^7.5.4"
|
||||||
|
|
||||||
vue@^3.4.21:
|
vue@^3.4.21:
|
||||||
@ -2660,11 +2610,6 @@ which@^2.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
isexe "^2.0.0"
|
isexe "^2.0.0"
|
||||||
|
|
||||||
wrappy@1:
|
|
||||||
version "1.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
|
||||||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
|
||||||
|
|
||||||
xml-name-validator@^4.0.0:
|
xml-name-validator@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835"
|
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835"
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user