Upgrades ArduinoJson from version 6 to 7

This commit is contained in:
Rune Harlyk
2024-05-07 10:36:16 +02:00
committed by Rune Harlyk
parent 2b4d196e7c
commit a150caad9d
39 changed files with 241 additions and 561 deletions
+1 -1
View File
@@ -33,7 +33,7 @@ void APStatus::begin()
esp_err_t APStatus::apStatus(PsychicRequest *request)
{
PsychicJsonResponse response = PsychicJsonResponse(request, false, MAX_AP_STATUS_SIZE);
PsychicJsonResponse response = PsychicJsonResponse(request, false);
JsonObject root = response.getRoot();
root["status"] = _apSettingsService->getAPNetworkStatus();
-1
View File
@@ -23,7 +23,6 @@
#include <SecurityManager.h>
#include <APSettingsService.h>
#define MAX_AP_STATUS_SIZE 1024
#define AP_STATUS_SERVICE_PATH "/api/apStatus"
class APStatus
+3 -3
View File
@@ -43,7 +43,7 @@ class AnalyticsService
updateAnalytics();
}
};
StaticJsonDocument<MAX_ESP_ANALYTICS_SIZE> doc;
JsonDocument doc;
char message[MAX_ESP_ANALYTICS_SIZE];
private:
@@ -65,10 +65,10 @@ class AnalyticsService
doc["cpu1_usage"] = _taskManager->getCpuUsage(1);
doc["cpu_usage"] = _taskManager->getCpuUsage();
// Add _taskManager->getTaskNames() as a JSON array
JsonArray tasks = doc.createNestedArray("tasks");
JsonArray tasks = doc["tasks"].as<JsonArray>();
for (auto const &task : _taskManager->getTasks())
{
JsonObject nested = tasks.createNestedObject();
JsonObject nested = tasks.add<JsonObject>();
nested["name"] = task.name;
nested["stackSize"] = task.stackSize;
nested["priority"] = task.priority;
@@ -27,13 +27,13 @@ void AuthenticationService::begin()
_server->on(SIGN_IN_PATH, HTTP_POST, [this](PsychicRequest *request, JsonVariant &json)
{
if (json.is<JsonObject>()) {
String username = json["username"];
String password = json["password"];
String username = json["username"];
String password = json["password"];
Authentication authentication = _securityManager->authenticate(username, password);
if (authentication.authenticated) {
PsychicJsonResponse response = PsychicJsonResponse(request, false, 256);
JsonObject root = response.getRoot();
root["access_token"] = _securityManager->generateJWT(authentication.user);
PsychicJsonResponse response = PsychicJsonResponse(request, false);
JsonObject root = response.getRoot();
root["access_token"] = _securityManager->generateJWT(authentication.user);
return response.send();
}
}
@@ -22,8 +22,6 @@
#define VERIFY_AUTHORIZATION_PATH "/api/verifyAuthorization"
#define SIGN_IN_PATH "/api/signIn"
#define MAX_AUTHENTICATION_SIZE 256
#if FT_ENABLED(FT_SECURITY)
class AuthenticationService
+1 -1
View File
@@ -24,7 +24,7 @@ void BatteryService::begin()
void BatteryService::batteryEvent()
{
StaticJsonDocument<32> doc;
JsonDocument doc;
char message[32];
doc["soc"] = _lastSOC;
doc["charging"] = _isCharging;
@@ -17,7 +17,7 @@ extern const uint8_t rootca_crt_bundle_start[] asm("_binary_src_certs_x509_crt_b
static EventSocket *_socket = nullptr;
static int previousProgress = 0;
StaticJsonDocument<128> doc;
JsonDocument doc;
void update_started()
{
+1 -1
View File
@@ -59,7 +59,7 @@ ESP32SvelteKit::ESP32SvelteKit(PsychicHttpServer *server, unsigned int numberEnd
void ESP32SvelteKit::begin() {
ESP_LOGV("ESP32SvelteKit", "Loading settings from files system");
ESP_LOGI("Running Firmware Version: %s\n", APP_VERSION);
ESP_LOGI("Running Firmware Version: %s", APP_VERSION);
ESPFS.begin(true);
_wifiSettingsService.initWiFi();
+2 -5
View File
@@ -27,12 +27,10 @@ public:
EventEndpoint(JsonStateReader<T> stateReader,
JsonStateUpdater<T> stateUpdater,
StatefulService<T> *statefulService,
EventSocket *socket, const char *event,
size_t bufferSize = DEFAULT_BUFFER_SIZE) : _stateReader(stateReader),
EventSocket *socket, const char *event) : _stateReader(stateReader),
_stateUpdater(stateUpdater),
_statefulService(statefulService),
_socket(socket),
_bufferSize(bufferSize),
_event(event)
{
_statefulService->addUpdateHandler([&](const String &originId)
@@ -53,7 +51,6 @@ private:
StatefulService<T> *_statefulService;
EventSocket *_socket;
const char *_event;
size_t _bufferSize;
void updateState(JsonObject &root, int originId)
{
@@ -62,7 +59,7 @@ private:
void syncState(const String &originId, bool sync = false)
{
DynamicJsonDocument jsonDocument{_bufferSize};
JsonDocument jsonDocument;
JsonObject root = jsonDocument.to<JsonObject>();
String output;
_statefulService->read(root, _stateReader);
+2 -32
View File
@@ -6,8 +6,7 @@ EventSocket::EventSocket(PsychicHttpServer *server,
SecurityManager *securityManager,
AuthenticationPredicate authenticationPredicate) : _server(server),
_securityManager(securityManager),
_authenticationPredicate(authenticationPredicate),
_bufferSize(1024)
_authenticationPredicate(authenticationPredicate)
{
}
@@ -19,11 +18,6 @@ void EventSocket::begin()
_socket.onFrame(std::bind(&EventSocket::onFrame, this, std::placeholders::_1, std::placeholders::_2));
_server->on(EVENT_SERVICE_PATH, &_socket);
registerEvent("errorToast");
registerEvent("warningToast");
registerEvent("infoToast");
registerEvent("successToast");
ESP_LOGV("EventSocket", "Registered event socket endpoint: %s", EVENT_SERVICE_PATH);
}
@@ -64,7 +58,7 @@ esp_err_t EventSocket::onFrame(PsychicWebSocketRequest *request, httpd_ws_frame
ESP_LOGV("EventSocket", "ws[%s][%u] request: %s", request->client()->remoteIP().toString().c_str(),
request->client()->socket(), (char *)frame->payload);
DynamicJsonDocument doc = DynamicJsonDocument(_bufferSize);
JsonDocument doc;
DeserializationError error = deserializeJson(doc, (char *)frame->payload, frame->len);
if (!error && doc.is<JsonObject>())
@@ -159,30 +153,6 @@ void EventSocket::emit(const char *event, const char *payload, const char *origi
xSemaphoreGive(clientSubscriptionsMutex);
}
void EventSocket::pushNotification(String message, pushEvent event)
{
String eventType;
switch (event)
{
case (PUSHERROR):
eventType = "errorToast";
break;
case (PUSHWARNING):
eventType = "warningToast";
break;
case (PUSHINFO):
eventType = "infoToast";
break;
case (PUSHSUCCESS):
eventType = "successToast";
break;
default:
ESP_LOGW("EventSocket", "Client tried invalid push notification: %s", event);
return;
}
emit(eventType.c_str(), message.c_str());
}
void EventSocket::handleEventCallbacks(String event, JsonObject &jsonObject, int originId)
{
for (auto &callback : event_callbacks[event])
-11
View File
@@ -13,14 +13,6 @@
typedef std::function<void(JsonObject &root, int originId)> EventCallback;
typedef std::function<void(const String &originId, bool sync)> SubscribeCallback;
enum pushEvent
{
PUSHERROR,
PUSHWARNING,
PUSHINFO,
PUSHSUCCESS
};
class EventSocket
{
public:
@@ -41,8 +33,6 @@ public:
void emit(const char *event, const char *payload, const char *originId, bool onlyToSameOrigin = false);
// if onlyToSameOrigin == true, the message will be sent to the originId only, otherwise it will be broadcasted to all clients except the originId
void pushNotification(String message, pushEvent event);
private:
PsychicHttpServer *_server;
PsychicWebSocketHandler _socket;
@@ -58,7 +48,6 @@ private:
bool isEventValid(String event);
size_t _bufferSize;
void onWSOpen(PsychicWebSocketClient *client);
void onWSClose(PsychicWebSocketClient *client);
esp_err_t onFrame(PsychicWebSocketRequest *request, httpd_ws_frame *frame);
+45 -56
View File
@@ -15,58 +15,55 @@
* the terms of the LGPL v3 license. See the LICENSE file for details.
**/
#include <StatefulService.h>
#include <FS.h>
#include <StatefulService.h>
template <class T>
class FSPersistence
{
public:
class FSPersistence {
public:
FSPersistence(JsonStateReader<T> stateReader,
JsonStateUpdater<T> stateUpdater,
StatefulService<T> *statefulService,
FS *fs,
const char *filePath,
size_t bufferSize = DEFAULT_BUFFER_SIZE) : _stateReader(stateReader),
_stateUpdater(stateUpdater),
_statefulService(statefulService),
_fs(fs),
_filePath(filePath),
_bufferSize(bufferSize),
_updateHandlerId(0)
{
StatefulService<T> *statefulService, FS *fs,
const char *filePath)
: _stateReader(stateReader),
_stateUpdater(stateUpdater),
_statefulService(statefulService),
_fs(fs),
_filePath(filePath),
_updateHandlerId(0) {
enableUpdateHandler();
}
void readFromFS()
{
void readFromFS() {
File settingsFile = _fs->open(_filePath, "r");
if (settingsFile)
{
DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize);
DeserializationError error = deserializeJson(jsonDocument, settingsFile);
if (error == DeserializationError::Ok && jsonDocument.is<JsonObject>())
{
if (settingsFile) {
JsonDocument jsonDocument;
DeserializationError error =
deserializeJson(jsonDocument, settingsFile);
if (error == DeserializationError::Ok &&
jsonDocument.is<JsonObject>()) {
JsonObject jsonObject = jsonDocument.as<JsonObject>();
_statefulService->updateWithoutPropagation(jsonObject, _stateUpdater);
_statefulService->updateWithoutPropagation(jsonObject,
_stateUpdater);
settingsFile.close();
return;
}
settingsFile.close();
}
// If we reach here we have not been successful in loading the config and hard-coded defaults are now applied.
// The settings are then written back to the file system so the defaults persist between resets. This last step is
// required as in some cases defaults contain randomly generated values which would otherwise be modified on reset.
// If we reach here we have not been successful in loading the config
// and hard-coded defaults are now applied. The settings are then
// written back to the file system so the defaults persist between
// resets. This last step is required as in some cases defaults contain
// randomly generated values which would otherwise be modified on reset.
applyDefaults();
writeToFS();
}
bool writeToFS()
{
bool writeToFS() {
// create and populate a new json object
DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize);
JsonDocument jsonDocument;
JsonObject jsonObject = jsonDocument.to<JsonObject>();
_statefulService->read(jsonObject, _stateReader);
@@ -77,8 +74,7 @@ public:
File settingsFile = _fs->open(_filePath, "w");
// failed to open file, return false
if (!settingsFile)
{
if (!settingsFile) {
return false;
}
@@ -88,25 +84,21 @@ public:
return true;
}
void disableUpdateHandler()
{
if (_updateHandlerId)
{
void disableUpdateHandler() {
if (_updateHandlerId) {
_statefulService->removeUpdateHandler(_updateHandlerId);
_updateHandlerId = 0;
}
}
void enableUpdateHandler()
{
if (!_updateHandlerId)
{
_updateHandlerId = _statefulService->addUpdateHandler([&](const String &originId)
{ writeToFS(); });
void enableUpdateHandler() {
if (!_updateHandlerId) {
_updateHandlerId = _statefulService->addUpdateHandler(
[&](const String &originId) { writeToFS(); });
}
}
private:
private:
JsonStateReader<T> _stateReader;
JsonStateUpdater<T> _stateUpdater;
StatefulService<T> *_statefulService;
@@ -115,31 +107,28 @@ private:
size_t _bufferSize;
update_handler_id_t _updateHandlerId;
// We assume we have a _filePath with format "/directory1/directory2/filename"
// We create a directory for each missing parent
void mkdirs()
{
// We assume we have a _filePath with format
// "/directory1/directory2/filename" We create a directory for each missing
// parent
void mkdirs() {
String path(_filePath);
int index = 0;
while ((index = path.indexOf('/', index + 1)) != -1)
{
while ((index = path.indexOf('/', index + 1)) != -1) {
String segment = path.substring(0, index);
if (!_fs->exists(segment))
{
if (!_fs->exists(segment)) {
_fs->mkdir(segment);
}
}
}
protected:
protected:
// We assume the updater supplies sensible defaults if an empty object
// is supplied, this virtual function allows that to be changed.
virtual void applyDefaults()
{
DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize);
virtual void applyDefaults() {
JsonDocument jsonDocument;
JsonObject jsonObject = jsonDocument.as<JsonObject>();
_statefulService->updateWithoutPropagation(jsonObject, _stateUpdater);
}
};
#endif // end FSPersistence
#endif // end FSPersistence
@@ -14,8 +14,6 @@
#include <FactoryResetService.h>
using namespace std::placeholders;
FactoryResetService::FactoryResetService(PsychicHttpServer *server,
FS *fs,
SecurityManager *securityManager) : _server(server),
@@ -28,7 +26,7 @@ void FactoryResetService::begin()
{
_server->on(FACTORY_RESET_SERVICE_PATH,
HTTP_POST,
_securityManager->wrapRequest(std::bind(&FactoryResetService::handleRequest, this, _1), AuthenticationPredicates::IS_ADMIN));
_securityManager->wrapRequest(std::bind(&FactoryResetService::handleRequest, this, std::placeholders::_1), AuthenticationPredicates::IS_ADMIN));
ESP_LOGV("FactoryResetService", "Registered POST endpoint: %s", FACTORY_RESET_SERVICE_PATH);
}
@@ -22,7 +22,7 @@ void FeaturesService::begin()
{
_server->on(FEATURES_SERVICE_PATH, HTTP_GET, [&](PsychicRequest *request)
{
PsychicJsonResponse response = PsychicJsonResponse(request, false, MAX_FEATURES_SIZE);
PsychicJsonResponse response = PsychicJsonResponse(request, false);
JsonObject root = response.getRoot();
#if FT_ENABLED(FT_SECURITY)
@@ -22,7 +22,6 @@
#include <PsychicHttp.h>
#include <vector>
#define MAX_FEATURES_SIZE 256
#define FEATURES_SERVICE_PATH "/api/features"
typedef struct
+51 -60
View File
@@ -1,22 +1,18 @@
#ifndef HttpEndpoint_h
#define HttpEndpoint_h
#include <functional>
#include <PsychicHttp.h>
#include <SecurityManager.h>
#include <StatefulService.h>
#include <functional>
#define HTTP_ENDPOINT_ORIGIN_ID "http"
#define HTTPS_ENDPOINT_ORIGIN_ID "https"
using namespace std::placeholders; // for `_1` etc
template <class T>
class HttpEndpoint
{
protected:
class HttpEndpoint {
protected:
JsonStateReader<T> _stateReader;
JsonStateUpdater<T> _stateUpdater;
StatefulService<T> *_statefulService;
@@ -26,42 +22,38 @@ protected:
PsychicHttpServer *_server;
const char *_servicePath;
public:
public:
HttpEndpoint(JsonStateReader<T> stateReader,
JsonStateUpdater<T> stateUpdater,
StatefulService<T> *statefulService,
PsychicHttpServer *server,
const char *servicePath,
SecurityManager *securityManager,
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
size_t bufferSize = DEFAULT_BUFFER_SIZE)
: _stateReader(stateReader), _stateUpdater(stateUpdater), _statefulService(statefulService), _server(server), _servicePath(servicePath), _securityManager(securityManager), _authenticationPredicate(authenticationPredicate), _bufferSize(bufferSize)
{
}
StatefulService<T> *statefulService, PsychicHttpServer *server,
const char *servicePath, SecurityManager *securityManager,
AuthenticationPredicate authenticationPredicate =
AuthenticationPredicates::IS_ADMIN)
: _stateReader(stateReader),
_stateUpdater(stateUpdater),
_statefulService(statefulService),
_server(server),
_servicePath(servicePath),
_securityManager(securityManager),
_authenticationPredicate(authenticationPredicate) {}
// register the web server on() endpoints
void begin()
{
void begin() {
// OPTIONS (for CORS preflight)
#ifdef ENABLE_CORS
_server->on(_servicePath,
HTTP_OPTIONS,
_securityManager->wrapRequest(
[this](PsychicRequest *request)
{
return request->reply(200);
},
AuthenticationPredicates::IS_AUTHENTICATED));
_server->on(
_servicePath, HTTP_OPTIONS,
_securityManager->wrapRequest(
[this](PsychicRequest *request) { return request->reply(200); },
AuthenticationPredicates::IS_AUTHENTICATED));
#endif
// GET
_server->on(_servicePath,
HTTP_GET,
_server->on(_servicePath, HTTP_GET,
_securityManager->wrapRequest(
[this](PsychicRequest *request)
{
PsychicJsonResponse response = PsychicJsonResponse(request, false, _bufferSize);
[this](PsychicRequest *request) {
PsychicJsonResponse response =
PsychicJsonResponse(request, false);
JsonObject jsonObject = response.getRoot();
_statefulService->read(jsonObject, _stateReader);
return response.send();
@@ -70,37 +62,36 @@ public:
ESP_LOGV("HttpEndpoint", "Registered GET endpoint: %s", _servicePath);
// POST
_server->on(_servicePath,
HTTP_POST,
_securityManager->wrapCallback(
[this](PsychicRequest *request, JsonVariant &json)
{
if (!json.is<JsonObject>())
{
return request->reply(400);
}
_server->on(
_servicePath, HTTP_POST,
_securityManager->wrapCallback(
[this](PsychicRequest *request, JsonVariant &json) {
if (!json.is<JsonObject>()) {
return request->reply(400);
}
JsonObject jsonObject = json.as<JsonObject>();
StateUpdateResult outcome = _statefulService->updateWithoutPropagation(jsonObject, _stateUpdater);
JsonObject jsonObject = json.as<JsonObject>();
StateUpdateResult outcome =
_statefulService->updateWithoutPropagation(
jsonObject, _stateUpdater);
if (outcome == StateUpdateResult::ERROR)
{
return request->reply(400);
}
else if ((outcome == StateUpdateResult::CHANGED))
{
// persist the changes to the FS
_statefulService->callUpdateHandlers(HTTP_ENDPOINT_ORIGIN_ID);
}
if (outcome == StateUpdateResult::ERROR) {
return request->reply(400);
} else if ((outcome == StateUpdateResult::CHANGED)) {
// persist the changes to the FS
_statefulService->callUpdateHandlers(
HTTP_ENDPOINT_ORIGIN_ID);
}
PsychicJsonResponse response = PsychicJsonResponse(request, false, _bufferSize);
jsonObject = response.getRoot();
PsychicJsonResponse response =
PsychicJsonResponse(request, false);
jsonObject = response.getRoot();
_statefulService->read(jsonObject, _stateReader);
_statefulService->read(jsonObject, _stateReader);
return response.send();
},
_authenticationPredicate));
return response.send();
},
_authenticationPredicate));
ESP_LOGV("HttpEndpoint", "Registered POST endpoint: %s", _servicePath);
}
+42 -69
View File
@@ -15,61 +15,50 @@
* the terms of the LGPL v3 license. See the LICENSE file for details.
**/
#include <StatefulService.h>
#include <PsychicMqttClient.h>
#include <StatefulService.h>
#define MQTT_ORIGIN_ID "mqtt"
template <class T>
class MqttEndpoint
{
public:
class MqttEndpoint {
public:
MqttEndpoint(JsonStateReader<T> stateReader,
JsonStateUpdater<T> stateUpdater,
StatefulService<T> *statefulService,
PsychicMqttClient *mqttClient,
const String &pubTopic = "",
const String &subTopic = "",
bool retain = false,
size_t bufferSize = DEFAULT_BUFFER_SIZE) : _stateReader(stateReader),
_stateUpdater(stateUpdater),
_statefulService(statefulService),
_mqttClient(mqttClient),
_pubTopic(pubTopic),
_subTopic(subTopic),
_retain(retain),
_bufferSize(bufferSize)
PsychicMqttClient *mqttClient, const String &pubTopic = "",
const String &subTopic = "", bool retain = false)
: _stateReader(stateReader),
_stateUpdater(stateUpdater),
_statefulService(statefulService),
_mqttClient(mqttClient),
_pubTopic(pubTopic),
_subTopic(subTopic),
_retain(retain),
_bufferSize(bufferSize)
{
_statefulService->addUpdateHandler([&](const String &originId)
{ publish(); },
false);
_statefulService->addUpdateHandler(
[&](const String &originId) { publish(); }, false);
_mqttClient->onConnect(std::bind(&MqttEndpoint::onConnect, this));
_mqttClient->onMessage(std::bind(&MqttEndpoint::onMqttMessage,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5));
_mqttClient->onMessage(
std::bind(&MqttEndpoint::onMqttMessage, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3,
std::placeholders::_4, std::placeholders::_5));
}
public:
void configureTopics(const String &pubTopic, const String &subTopic)
{
public:
void configureTopics(const String &pubTopic, const String &subTopic) {
setSubTopic(subTopic);
setPubTopic(pubTopic);
}
void setSubTopic(const String &subTopic)
{
if (!_subTopic.equals(subTopic))
{
void setSubTopic(const String &subTopic) {
if (!_subTopic.equals(subTopic)) {
// unsubscribe from the existing topic if one was set
if (_subTopic.length() > 0)
{
if (_subTopic.length() > 0) {
_mqttClient->unsubscribe(_subTopic.c_str());
}
// set the new topic and re-configure the subscription
@@ -78,24 +67,20 @@ public:
}
}
void setPubTopic(const String &pubTopic)
{
void setPubTopic(const String &pubTopic) {
_pubTopic = pubTopic;
publish();
}
void setRetain(const bool retain)
{
void setRetain(const bool retain) {
_retain = retain;
publish();
}
void publish()
{
if (_pubTopic.length() > 0 && _mqttClient->connected())
{
void publish() {
if (_pubTopic.length() > 0 && _mqttClient->connected()) {
// serialize to json doc
DynamicJsonDocument json(_bufferSize);
JsonDocument json;
JsonObject jsonObject = json.to<JsonObject>();
_statefulService->read(jsonObject, _stateReader);
@@ -104,60 +89,48 @@ public:
serializeJson(json, payload);
// publish the payload
_mqttClient->publish(_pubTopic.c_str(), 0, _retain, payload.c_str());
_mqttClient->publish(_pubTopic.c_str(), 0, _retain,
payload.c_str());
}
}
PsychicMqttClient *getMqttClient()
{
return _mqttClient;
}
PsychicMqttClient *getMqttClient() { return _mqttClient; }
protected:
protected:
StatefulService<T> *_statefulService;
PsychicMqttClient *_mqttClient;
int _bufferSize;
JsonStateUpdater<T> _stateUpdater;
JsonStateReader<T> _stateReader;
String _subTopic;
String _pubTopic;
bool _retain;
void onMqttMessage(char *topic,
char *payload,
int retain,
int qos,
bool dup)
{
void onMqttMessage(char *topic, char *payload, int retain, int qos,
bool dup) {
// we only care about the topic we are watching in this class
if (strcmp(_subTopic.c_str(), topic))
{
if (strcmp(_subTopic.c_str(), topic)) {
return;
}
// deserialize from string
DynamicJsonDocument json(_bufferSize);
JsonDocument json;
DeserializationError error = deserializeJson(json, payload);
if (!error && json.is<JsonObject>())
{
if (!error && json.is<JsonObject>()) {
JsonObject jsonObject = json.as<JsonObject>();
_statefulService->update(jsonObject, _stateUpdater, MQTT_ORIGIN_ID);
}
}
void onConnect()
{
void onConnect() {
subscribe();
publish();
}
void subscribe()
{
if (_subTopic.length() > 0)
{
void subscribe() {
if (_subTopic.length() > 0) {
_mqttClient->subscribe(_subTopic.c_str(), 2);
}
}
};
#endif // end MqttEndpoint
#endif // end MqttEndpoint
+2 -3
View File
@@ -95,7 +95,7 @@ public:
if (_pubTopic.length() > 0 && _mqttClient->connected())
{
// serialize to json doc
DynamicJsonDocument json(_bufferSize);
JsonDocument json;
JsonObject jsonObject = json.to<JsonObject>();
_statefulService->read(jsonObject, _stateReader);
@@ -116,7 +116,6 @@ public:
protected:
StatefulService<T> *_statefulService;
PsychicMqttClient *_mqttClient;
int _bufferSize;
JsonStateUpdater<T> _stateUpdater;
JsonStateReader<T> _stateReader;
String _subTopic;
@@ -136,7 +135,7 @@ protected:
}
// deserialize from string
DynamicJsonDocument json(_bufferSize);
JsonDocument json;
DeserializationError error = deserializeJson(json, payload);
if (!error && json.is<JsonObject>())
{
+1 -1
View File
@@ -34,7 +34,7 @@ void MqttStatus::begin()
esp_err_t MqttStatus::mqttStatus(PsychicRequest *request)
{
PsychicJsonResponse response = PsychicJsonResponse(request, false, MAX_MQTT_STATUS_SIZE);
PsychicJsonResponse response = PsychicJsonResponse(request, false);
JsonObject root = response.getRoot();
root["enabled"] = _mqttSettingsService->isEnabled();
-1
View File
@@ -22,7 +22,6 @@
#include <PsychicHttp.h>
#include <SecurityManager.h>
#define MAX_MQTT_STATUS_SIZE 1024
#define MQTT_STATUS_SERVICE_PATH "/api/mqttStatus"
class MqttStatus
@@ -41,7 +41,6 @@
#define NTP_SETTINGS_FILE "/config/ntpSettings.json"
#define NTP_SETTINGS_SERVICE_PATH "/api/ntpSettings"
#define MAX_TIME_SIZE 256
#define TIME_PATH "/api/time"
class NTPSettings
+1 -1
View File
@@ -53,7 +53,7 @@ String toLocalTimeString(tm *time)
esp_err_t NTPStatus::ntpStatus(PsychicRequest *request)
{
PsychicJsonResponse response = PsychicJsonResponse(request, false, MAX_NTP_STATUS_SIZE);
PsychicJsonResponse response = PsychicJsonResponse(request, false);
JsonObject root = response.getRoot();
// grab the current instant in unix seconds
-1
View File
@@ -23,7 +23,6 @@
#include <PsychicHttp.h>
#include <SecurityManager.h>
#define MAX_NTP_STATUS_SIZE 1024
#define NTP_STATUS_SERVICE_PATH "/api/ntpStatus"
class NTPStatus
@@ -69,7 +69,7 @@ void SecuritySettingsService::configureJWTHandler()
Authentication SecuritySettingsService::authenticateJWT(String &jwt)
{
DynamicJsonDocument payloadDocument(MAX_JWT_SIZE);
JsonDocument payloadDocument;
_jwtHandler.parseJWT(jwt, payloadDocument);
if (payloadDocument.is<JsonObject>())
{
@@ -106,7 +106,7 @@ inline void populateJWTPayload(JsonObject &payload, User *user)
boolean SecuritySettingsService::validatePayload(JsonObject &parsedPayload, User *user)
{
DynamicJsonDocument jsonDocument(MAX_JWT_SIZE);
JsonDocument jsonDocument;
JsonObject payload = jsonDocument.to<JsonObject>();
populateJWTPayload(payload, user);
return payload == parsedPayload;
@@ -114,7 +114,7 @@ boolean SecuritySettingsService::validatePayload(JsonObject &parsedPayload, User
String SecuritySettingsService::generateJWT(User *user)
{
DynamicJsonDocument jsonDocument(MAX_JWT_SIZE);
JsonDocument jsonDocument;
JsonObject payload = jsonDocument.to<JsonObject>();
populateJWTPayload(payload, user);
return _jwtHandler.buildJWT(payload);
@@ -179,7 +179,7 @@ esp_err_t SecuritySettingsService::generateToken(PsychicRequest *request)
{
if (_user.username == usernameParam)
{
PsychicJsonResponse response = PsychicJsonResponse(request, false, GENERATE_TOKEN_SIZE);
PsychicJsonResponse response = PsychicJsonResponse(request, false);
JsonObject root = response.getRoot();
root["token"] = generateJWT(&_user);
return response.send();
@@ -44,7 +44,6 @@
#define SECURITY_SETTINGS_FILE "/config/securitySettings.json"
#define SECURITY_SETTINGS_PATH "/api/securitySettings"
#define GENERATE_TOKEN_SIZE 512
#define GENERATE_TOKEN_PATH "/api/generateToken"
#if FT_ENABLED(FT_SECURITY)
@@ -61,10 +60,10 @@ public:
root["jwt_secret"] = settings.jwtSecret;
// users
JsonArray users = root.createNestedArray("users");
JsonArray users = root.to<JsonArray>();
for (User user : settings.users)
{
JsonObject userRoot = users.createNestedObject();
JsonObject userRoot = users.add<JsonObject>();
userRoot["username"] = user.username;
userRoot["password"] = user.password;
userRoot["admin"] = user.admin;
@@ -23,10 +23,6 @@
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
#ifndef DEFAULT_BUFFER_SIZE
#define DEFAULT_BUFFER_SIZE 1024
#endif
enum class StateUpdateResult
{
CHANGED = 0, // The update changed the state and propagation should take place if required
+1 -1
View File
@@ -111,7 +111,7 @@ void SystemStatus::begin()
esp_err_t SystemStatus::systemStatus(PsychicRequest *request)
{
PsychicJsonResponse response = PsychicJsonResponse(request, false, MAX_ESP_STATUS_SIZE);
PsychicJsonResponse response = PsychicJsonResponse(request, false);
JsonObject root = response.getRoot();
root["esp_platform"] = ESP_PLATFORM;
-1
View File
@@ -22,7 +22,6 @@
#include <SecurityManager.h>
#include <ESPFS.h>
#define MAX_ESP_STATUS_SIZE 1024
#define SYSTEM_STATUS_SERVICE_PATH "/api/systemStatus"
class SystemStatus
@@ -16,7 +16,7 @@
#include <esp_ota_ops.h>
#include <esp_app_format.h>
using namespace std::placeholders; // for `_1` etc
using namespace std::placeholders;
static char md5[33] = "\0";
@@ -152,7 +152,7 @@ esp_err_t UploadFirmwareService::uploadComplete(PsychicRequest *request)
{
if (strlen(md5) == 32)
{
PsychicJsonResponse response = PsychicJsonResponse(request, false, 256);
PsychicJsonResponse response = PsychicJsonResponse(request, false);
JsonObject root = response.getRoot();
root["md5"] = md5;
return response.send();
+60 -68
View File
@@ -4,9 +4,9 @@
/**
* ESP32 SvelteKit
*
* A simple, secure and extensible framework for IoT projects for ESP32 platforms
* with responsive Sveltekit front-end built with TailwindCSS and DaisyUI.
* https://github.com/theelims/ESP32-sveltekit
* A simple, secure and extensible framework for IoT projects for ESP32
*platforms with responsive Sveltekit front-end built with TailwindCSS and
*DaisyUI. https://github.com/theelims/ESP32-sveltekit
*
* Copyright (C) 2018 - 2023 rjwats
* Copyright (C) 2023 theelims
@@ -15,9 +15,9 @@
* the terms of the LGPL v3 license. See the LICENSE file for details.
**/
#include <StatefulService.h>
#include <PsychicHttp.h>
#include <SecurityManager.h>
#include <StatefulService.h>
#define WEB_SOCKET_CLIENT_ID_MSG_SIZE 128
@@ -25,90 +25,86 @@
#define WEB_SOCKET_ORIGIN_CLIENT_ID_PREFIX "wsserver:"
template <class T>
class WebSocketServer
{
public:
class WebSocketServer {
public:
WebSocketServer(JsonStateReader<T> stateReader,
JsonStateUpdater<T> stateUpdater,
StatefulService<T> *statefulService,
PsychicHttpServer *server,
const char *webSocketPath,
PsychicHttpServer *server, const char *webSocketPath,
SecurityManager *securityManager,
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
size_t bufferSize = DEFAULT_BUFFER_SIZE) : _stateReader(stateReader),
_stateUpdater(stateUpdater),
_statefulService(statefulService),
_server(server),
_bufferSize(bufferSize),
_webSocketPath(webSocketPath),
_authenticationPredicate(authenticationPredicate),
_securityManager(securityManager)
{
AuthenticationPredicate authenticationPredicate =
AuthenticationPredicates::IS_ADMIN)
: _stateReader(stateReader),
_stateUpdater(stateUpdater),
_statefulService(statefulService),
_server(server),
_webSocketPath(webSocketPath),
_authenticationPredicate(authenticationPredicate),
_securityManager(securityManager) {
_statefulService->addUpdateHandler(
[&](const String &originId)
{ transmitData(nullptr, originId); },
[&](const String &originId) { transmitData(nullptr, originId); },
false);
}
void begin()
{
_webSocket.setFilter(_securityManager->filterRequest(_authenticationPredicate));
_webSocket.onOpen(std::bind(&WebSocketServer::onWSOpen,
this,
std::placeholders::_1));
_webSocket.onClose(std::bind(&WebSocketServer::onWSClose,
this,
void begin() {
_webSocket.setFilter(
_securityManager->filterRequest(_authenticationPredicate));
_webSocket.onOpen(
std::bind(&WebSocketServer::onWSOpen, this, std::placeholders::_1));
_webSocket.onClose(std::bind(&WebSocketServer::onWSClose, this,
std::placeholders::_1));
_webSocket.onFrame(std::bind(&WebSocketServer::onWSFrame,
this,
_webSocket.onFrame(std::bind(&WebSocketServer::onWSFrame, this,
std::placeholders::_1,
std::placeholders::_2));
_server->on(_webSocketPath.c_str(), &_webSocket);
ESP_LOGV("WebSocketServer", "Registered WebSocket handler: %s", _webSocketPath.c_str());
ESP_LOGV("WebSocketServer", "Registered WebSocket handler: %s",
_webSocketPath.c_str());
}
void onWSOpen(PsychicWebSocketClient *client)
{
void onWSOpen(PsychicWebSocketClient *client) {
// when a client connects, we transmit it's id and the current payload
transmitId(client);
transmitData(client, WEB_SOCKET_ORIGIN);
ESP_LOGI("WebSocketServer", "ws[%s][%u] connect", client->remoteIP().toString().c_str(), client->socket());
ESP_LOGI("WebSocketServer", "ws[%s][%u] connect",
client->remoteIP().toString().c_str(), client->socket());
}
void onWSClose(PsychicWebSocketClient *client)
{
ESP_LOGI("WebSocketServer", "ws[%s][%u] disconnect", client->remoteIP().toString().c_str(), client->socket());
void onWSClose(PsychicWebSocketClient *client) {
ESP_LOGI("WebSocketServer", "ws[%s][%u] disconnect",
client->remoteIP().toString().c_str(), client->socket());
}
esp_err_t onWSFrame(PsychicWebSocketRequest *request, httpd_ws_frame *frame)
{
ESP_LOGV("WebSocketServer", "ws[%s][%u] opcode[%d]", request->client()->remoteIP().toString().c_str(), request->client()->socket(), frame->type);
esp_err_t onWSFrame(PsychicWebSocketRequest *request,
httpd_ws_frame *frame) {
ESP_LOGV("WebSocketServer", "ws[%s][%u] opcode[%d]",
request->client()->remoteIP().toString().c_str(),
request->client()->socket(), frame->type);
if (frame->type == HTTPD_WS_TYPE_TEXT)
{
ESP_LOGV("WebSocketServer", "ws[%s][%u] request: %s", request->client()->remoteIP().toString().c_str(), request->client()->socket(), (char *)frame->payload);
if (frame->type == HTTPD_WS_TYPE_TEXT) {
ESP_LOGV("WebSocketServer", "ws[%s][%u] request: %s",
request->client()->remoteIP().toString().c_str(),
request->client()->socket(), (char *)frame->payload);
DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize);
DeserializationError error = deserializeJson(jsonDocument, (char *)frame->payload, frame->len);
JsonDocument jsonDocument;
DeserializationError error = deserializeJson(
jsonDocument, (char *)frame->payload, frame->len);
if (!error && jsonDocument.is<JsonObject>())
{
if (!error && jsonDocument.is<JsonObject>()) {
JsonObject jsonObject = jsonDocument.as<JsonObject>();
_statefulService->update(jsonObject, _stateUpdater, clientId(request->client()));
_statefulService->update(jsonObject, _stateUpdater,
clientId(request->client()));
return ESP_OK;
}
}
return ESP_OK;
}
String clientId(PsychicWebSocketClient *client)
{
String clientId(PsychicWebSocketClient *client) {
return WEB_SOCKET_ORIGIN_CLIENT_ID_PREFIX + String(client->socket());
}
private:
private:
JsonStateReader<T> _stateReader;
JsonStateUpdater<T> _stateUpdater;
StatefulService<T> *_statefulService;
@@ -119,9 +115,8 @@ private:
String _webSocketPath;
size_t _bufferSize;
void transmitId(PsychicWebSocketClient *client)
{
DynamicJsonDocument jsonDocument = DynamicJsonDocument(WEB_SOCKET_CLIENT_ID_MSG_SIZE);
void transmitId(PsychicWebSocketClient *client) {
JsonDocument jsonDocument;
JsonObject root = jsonDocument.to<JsonObject>();
root["type"] = "id";
root["id"] = clientId(client);
@@ -133,15 +128,15 @@ private:
}
/**
* Broadcasts the payload to the destination, if provided. Otherwise broadcasts to all clients except the origin, if
* specified.
* Broadcasts the payload to the destination, if provided. Otherwise
* broadcasts to all clients except the origin, if specified.
*
* Original implementation sent clients their own IDs so they could ignore updates they initiated. This approach
* simplifies the client and the server implementation but may not be sufficient for all use-cases.
* Original implementation sent clients their own IDs so they could ignore
* updates they initiated. This approach simplifies the client and the
* server implementation but may not be sufficient for all use-cases.
*/
void transmitData(PsychicWebSocketClient *client, const String &originId)
{
DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize);
void transmitData(PsychicWebSocketClient *client, const String &originId) {
JsonDocument jsonDocument;
JsonObject root = jsonDocument.to<JsonObject>();
String buffer;
@@ -149,12 +144,9 @@ private:
// serialize the json to a string
serializeJson(jsonDocument, buffer);
if (client)
{
if (client) {
client->sendMessage(buffer.c_str());
}
else
{
} else {
_webSocket.sendAll(buffer.c_str());
}
}
+3 -3
View File
@@ -52,12 +52,12 @@ esp_err_t WiFiScanner::listNetworks(PsychicRequest *request)
int numNetworks = WiFi.scanComplete();
if (numNetworks > -1)
{
PsychicJsonResponse response = PsychicJsonResponse(request, false, MAX_WIFI_SCANNER_SIZE);
PsychicJsonResponse response = PsychicJsonResponse(request, false);
JsonObject root = response.getRoot();
JsonArray networks = root.createNestedArray("networks");
JsonArray networks = root["networks"].to<JsonArray>();
for (int i = 0; i < numNetworks; i++)
{
JsonObject network = networks.createNestedObject();
JsonObject network = networks.add<JsonObject>();
network["rssi"] = WiFi.RSSI(i);
network["ssid"] = WiFi.SSID(i);
network["bssid"] = WiFi.BSSIDstr(i);
-2
View File
@@ -24,8 +24,6 @@
#define SCAN_NETWORKS_SERVICE_PATH "/api/scanNetworks"
#define LIST_NETWORKS_SERVICE_PATH "/api/listNetworks"
#define MAX_WIFI_SCANNER_SIZE 1024
class WiFiScanner
{
public:
@@ -18,9 +18,8 @@ WiFiSettingsService::WiFiSettingsService(PsychicHttpServer *server, FS *fs, Secu
EventSocket *socket)
: _server(server), _securityManager(securityManager),
_httpEndpoint(WiFiSettings::read, WiFiSettings::update, this, server, WIFI_SETTINGS_SERVICE_PATH, securityManager,
AuthenticationPredicates::IS_ADMIN, WIFI_SETTINGS_BUFFER_SIZE),
_eventEndpoint(WiFiSettings::read, WiFiSettings::update, this, socket, EVENT_WIFI_SETTINGS,
WIFI_SETTINGS_BUFFER_SIZE),
AuthenticationPredicates::IS_ADMIN),
_eventEndpoint(WiFiSettings::read, WiFiSettings::update, this, socket, EVENT_WIFI_SETTINGS),
_fsPersistence(WiFiSettings::read, WiFiSettings::update, this, fs, WIFI_SETTINGS_FILE), _lastConnectionAttempt(0),
_socket(socket)
{
@@ -50,8 +50,6 @@
#define WIFI_RECONNECTION_DELAY 1000 * 30
#define RSSI_EVENT_DELAY 500
#define WIFI_SETTINGS_BUFFER_SIZE 2048
#define EVENT_RSSI "rssi"
#define EVENT_WIFI_SETTINGS "WiFiSettings"
@@ -83,13 +81,13 @@ public:
root["priority_RSSI"] = settings.priorityBySignalStrength;
// create JSON array from root
JsonArray wifiNetworks = root.createNestedArray("wifi_networks");
JsonArray wifiNetworks = root["wifi_networks"].to<JsonArray>();
// iterate over the wifiSettings
for (auto &wifi : settings.wifiSettings)
{
// create JSON object for each wifi network
JsonObject wifiNetwork = wifiNetworks.createNestedObject();
JsonObject wifiNetwork = wifiNetworks.add<JsonObject>();
// add the ssid and password to the JSON object
wifiNetwork["ssid"] = wifi.ssid;
+1 -1
View File
@@ -63,7 +63,7 @@ void WiFiStatus::onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info)
esp_err_t WiFiStatus::wifiStatus(PsychicRequest *request)
{
PsychicJsonResponse response = PsychicJsonResponse(request, false, MAX_WIFI_STATUS_SIZE);
PsychicJsonResponse response = PsychicJsonResponse(request, false);
JsonObject root = response.getRoot();
wl_status_t status = WiFi.status();
root["status"] = (uint8_t)status;
-1
View File
@@ -22,7 +22,6 @@
#include <IPUtils.h>
#include <SecurityManager.h>
#define MAX_WIFI_STATUS_SIZE 1024
#define WIFI_STATUS_SERVICE_PATH "/api/wifiStatus"
class WiFiStatus