mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
Arduino v7
This commit is contained in:
@@ -10,7 +10,7 @@ APStatus::APStatus(AsyncWebServer * server, SecurityManager * securityManager, A
|
||||
}
|
||||
|
||||
void APStatus::apStatus(AsyncWebServerRequest * request) {
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_AP_STATUS_SIZE);
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
root["status"] = _apSettingsService->getAPNetworkStatus();
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <SecurityManager.h>
|
||||
#include <APSettingsService.h>
|
||||
|
||||
#define MAX_AP_STATUS_SIZE 1024
|
||||
// #define MAX_AP_STATUS_SIZE 1024
|
||||
#define AP_STATUS_SERVICE_PATH "/rest/apStatus"
|
||||
|
||||
class APStatus {
|
||||
|
||||
@@ -32,7 +32,7 @@ void AuthenticationService::signIn(AsyncWebServerRequest * request, JsonVariant
|
||||
Authentication authentication = _securityManager->authenticate(username, password);
|
||||
if (authentication.authenticated) {
|
||||
User * user = authentication.user;
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_AUTHENTICATION_SIZE);
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false);
|
||||
JsonObject jsonObject = response->getRoot();
|
||||
jsonObject["access_token"] = _securityManager->generateJWT(user);
|
||||
response->setLength();
|
||||
|
||||
@@ -7,18 +7,12 @@
|
||||
template <class T>
|
||||
class FSPersistence {
|
||||
public:
|
||||
FSPersistence(JsonStateReader<T> stateReader,
|
||||
JsonStateUpdater<T> stateUpdater,
|
||||
StatefulService<T> * statefulService,
|
||||
FS * fs,
|
||||
const char * filePath,
|
||||
size_t bufferSize = FS_BUFFER_SIZE)
|
||||
FSPersistence(JsonStateReader<T> stateReader, JsonStateUpdater<T> stateUpdater, StatefulService<T> * statefulService, FS * fs, const char * filePath)
|
||||
: _stateReader(stateReader)
|
||||
, _stateUpdater(stateUpdater)
|
||||
, _statefulService(statefulService)
|
||||
, _fs(fs)
|
||||
, _filePath(filePath)
|
||||
, _bufferSize(bufferSize)
|
||||
, _updateHandlerId(0) {
|
||||
enableUpdateHandler();
|
||||
}
|
||||
@@ -27,8 +21,8 @@ class FSPersistence {
|
||||
File settingsFile = _fs->open(_filePath, "r");
|
||||
|
||||
if (settingsFile) {
|
||||
DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize);
|
||||
DeserializationError error = deserializeJson(jsonDocument, settingsFile);
|
||||
JsonDocument jsonDocument;
|
||||
DeserializationError error = deserializeJson(jsonDocument, settingsFile);
|
||||
if (error == DeserializationError::Ok && jsonDocument.is<JsonObject>()) {
|
||||
JsonObject jsonObject = jsonDocument.as<JsonObject>();
|
||||
_statefulService->updateWithoutPropagation(jsonObject, _stateUpdater);
|
||||
@@ -46,8 +40,8 @@ class FSPersistence {
|
||||
|
||||
bool writeToFS() {
|
||||
// create and populate a new json object
|
||||
DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize);
|
||||
JsonObject jsonObject = jsonDocument.to<JsonObject>();
|
||||
JsonDocument jsonDocument;
|
||||
JsonObject jsonObject = jsonDocument.to<JsonObject>();
|
||||
_statefulService->read(jsonObject, _stateReader);
|
||||
|
||||
// make directories if required, for new IDF4.2 & LittleFS
|
||||
@@ -96,15 +90,14 @@ class FSPersistence {
|
||||
StatefulService<T> * _statefulService;
|
||||
FS * _fs;
|
||||
const char * _filePath;
|
||||
size_t _bufferSize;
|
||||
update_handler_id_t _updateHandlerId;
|
||||
|
||||
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);
|
||||
JsonObject jsonObject = jsonDocument.as<JsonObject>();
|
||||
JsonDocument jsonDocument;
|
||||
JsonObject jsonObject = jsonDocument.as<JsonObject>();
|
||||
_statefulService->updateWithoutPropagation(jsonObject, _stateUpdater);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@ FeaturesService::FeaturesService(AsyncWebServer * server) {
|
||||
}
|
||||
|
||||
void FeaturesService::features(AsyncWebServerRequest * request) {
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_FEATURES_SIZE);
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
root["version"] = EMSESP_APP_VERSION;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <AsyncJson.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
|
||||
#define MAX_FEATURES_SIZE 256
|
||||
// #define MAX_FEATURES_SIZE 256
|
||||
#define FEATURES_SERVICE_PATH "/rest/features"
|
||||
|
||||
class FeaturesService {
|
||||
|
||||
@@ -20,32 +20,24 @@ class HttpGetEndpoint {
|
||||
AsyncWebServer * server,
|
||||
const String & servicePath,
|
||||
SecurityManager * securityManager,
|
||||
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
|
||||
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN)
|
||||
: _stateReader(stateReader)
|
||||
, _statefulService(statefulService)
|
||||
, _bufferSize(bufferSize) {
|
||||
, _statefulService(statefulService) {
|
||||
server->on(servicePath.c_str(), HTTP_GET, securityManager->wrapRequest(std::bind(&HttpGetEndpoint::fetchSettings, this, _1), authenticationPredicate));
|
||||
}
|
||||
|
||||
HttpGetEndpoint(JsonStateReader<T> stateReader,
|
||||
StatefulService<T> * statefulService,
|
||||
AsyncWebServer * server,
|
||||
const String & servicePath,
|
||||
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||
HttpGetEndpoint(JsonStateReader<T> stateReader, StatefulService<T> * statefulService, AsyncWebServer * server, const String & servicePath)
|
||||
: _stateReader(stateReader)
|
||||
, _statefulService(statefulService)
|
||||
, _bufferSize(bufferSize) {
|
||||
, _statefulService(statefulService) {
|
||||
server->on(servicePath.c_str(), HTTP_GET, std::bind(&HttpGetEndpoint::fetchSettings, this, _1));
|
||||
}
|
||||
|
||||
protected:
|
||||
JsonStateReader<T> _stateReader;
|
||||
StatefulService<T> * _statefulService;
|
||||
size_t _bufferSize;
|
||||
|
||||
void fetchSettings(AsyncWebServerRequest * request) {
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, _bufferSize);
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false);
|
||||
JsonObject jsonObject = response->getRoot().to<JsonObject>();
|
||||
_statefulService->read(jsonObject, _stateReader);
|
||||
|
||||
@@ -63,13 +55,11 @@ class HttpPostEndpoint {
|
||||
AsyncWebServer * server,
|
||||
const String & servicePath,
|
||||
SecurityManager * securityManager,
|
||||
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
|
||||
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN)
|
||||
: _stateReader(stateReader)
|
||||
, _stateUpdater(stateUpdater)
|
||||
, _statefulService(statefulService)
|
||||
, _updateHandler(servicePath, securityManager->wrapCallback(std::bind(&HttpPostEndpoint::updateSettings, this, _1, _2), authenticationPredicate), bufferSize)
|
||||
, _bufferSize(bufferSize) {
|
||||
, _updateHandler(servicePath, securityManager->wrapCallback(std::bind(&HttpPostEndpoint::updateSettings, this, _1, _2), authenticationPredicate)) {
|
||||
_updateHandler.setMethod(HTTP_POST);
|
||||
server->addHandler(&_updateHandler);
|
||||
}
|
||||
@@ -78,13 +68,11 @@ class HttpPostEndpoint {
|
||||
JsonStateUpdater<T> stateUpdater,
|
||||
StatefulService<T> * statefulService,
|
||||
AsyncWebServer * server,
|
||||
const String & servicePath,
|
||||
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||
const String & servicePath)
|
||||
: _stateReader(stateReader)
|
||||
, _stateUpdater(stateUpdater)
|
||||
, _statefulService(statefulService)
|
||||
, _updateHandler(servicePath, std::bind(&HttpPostEndpoint::updateSettings, this, _1, _2), bufferSize)
|
||||
, _bufferSize(bufferSize) {
|
||||
, _updateHandler(servicePath, std::bind(&HttpPostEndpoint::updateSettings, this, _1, _2)) {
|
||||
_updateHandler.setMethod(HTTP_POST);
|
||||
server->addHandler(&_updateHandler);
|
||||
}
|
||||
@@ -94,7 +82,6 @@ class HttpPostEndpoint {
|
||||
JsonStateUpdater<T> _stateUpdater;
|
||||
StatefulService<T> * _statefulService;
|
||||
AsyncCallbackJsonWebHandler _updateHandler;
|
||||
size_t _bufferSize;
|
||||
|
||||
void updateSettings(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
if (!json.is<JsonObject>()) {
|
||||
@@ -109,7 +96,7 @@ class HttpPostEndpoint {
|
||||
} else if ((outcome == StateUpdateResult::CHANGED) || (outcome == StateUpdateResult::CHANGED_RESTART)) {
|
||||
request->onDisconnect([this]() { _statefulService->callUpdateHandlers(HTTP_ENDPOINT_ORIGIN_ID); });
|
||||
}
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, _bufferSize);
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false);
|
||||
jsonObject = response->getRoot().to<JsonObject>();
|
||||
_statefulService->read(jsonObject, _stateReader);
|
||||
if (outcome == StateUpdateResult::CHANGED_RESTART) {
|
||||
@@ -129,20 +116,18 @@ class HttpEndpoint : public HttpGetEndpoint<T>, public HttpPostEndpoint<T> {
|
||||
AsyncWebServer * server,
|
||||
const String & servicePath,
|
||||
SecurityManager * securityManager,
|
||||
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
|
||||
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||
: HttpGetEndpoint<T>(stateReader, statefulService, server, servicePath, securityManager, authenticationPredicate, bufferSize)
|
||||
, HttpPostEndpoint<T>(stateReader, stateUpdater, statefulService, server, servicePath, securityManager, authenticationPredicate, bufferSize) {
|
||||
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN)
|
||||
: HttpGetEndpoint<T>(stateReader, statefulService, server, servicePath, securityManager, authenticationPredicate)
|
||||
, HttpPostEndpoint<T>(stateReader, stateUpdater, statefulService, server, servicePath, securityManager, authenticationPredicate) {
|
||||
}
|
||||
|
||||
HttpEndpoint(JsonStateReader<T> stateReader,
|
||||
JsonStateUpdater<T> stateUpdater,
|
||||
StatefulService<T> * statefulService,
|
||||
AsyncWebServer * server,
|
||||
const String & servicePath,
|
||||
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||
: HttpGetEndpoint<T>(stateReader, statefulService, server, servicePath, bufferSize)
|
||||
, HttpPostEndpoint<T>(stateReader, stateUpdater, statefulService, server, servicePath, bufferSize) {
|
||||
const String & servicePath)
|
||||
: HttpGetEndpoint<T>(stateReader, statefulService, server, servicePath)
|
||||
, HttpPostEndpoint<T>(stateReader, stateUpdater, statefulService, server, servicePath) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ MqttStatus::MqttStatus(AsyncWebServer * server, MqttSettingsService * mqttSettin
|
||||
}
|
||||
|
||||
void MqttStatus::mqttStatus(AsyncWebServerRequest * request) {
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_MQTT_STATUS_SIZE);
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
root["enabled"] = _mqttSettingsService->isEnabled();
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <SecurityManager.h>
|
||||
|
||||
#define MAX_MQTT_STATUS_SIZE 1024
|
||||
// #define MAX_MQTT_STATUS_SIZE 1024
|
||||
#define MQTT_STATUS_SERVICE_PATH "/rest/mqttStatus"
|
||||
|
||||
class MqttStatus {
|
||||
|
||||
@@ -29,7 +29,7 @@ String toLocalTimeString(tm * time) {
|
||||
}
|
||||
|
||||
void NTPStatus::ntpStatus(AsyncWebServerRequest * request) {
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_NTP_STATUS_SIZE);
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
// grab the current instant in unix seconds
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <SecurityManager.h>
|
||||
#include <uuid/common.h>
|
||||
|
||||
#define MAX_NTP_STATUS_SIZE 1024
|
||||
// #define MAX_NTP_STATUS_SIZE 1024
|
||||
#define NTP_STATUS_SERVICE_PATH "/rest/ntpStatus"
|
||||
|
||||
class NTPStatus {
|
||||
|
||||
@@ -11,7 +11,7 @@ NetworkStatus::NetworkStatus(AsyncWebServer * server, SecurityManager * security
|
||||
}
|
||||
|
||||
void NetworkStatus::networkStatus(AsyncWebServerRequest * request) {
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_NETWORK_STATUS_SIZE);
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
bool ethernet_connected = emsesp::EMSESP::system_.ethernet_connected();
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#define AUTHORIZATION_HEADER_PREFIX "Bearer "
|
||||
#define AUTHORIZATION_HEADER_PREFIX_LEN 7
|
||||
|
||||
#define MAX_JWT_SIZE 128
|
||||
// #define MAX_JWT_SIZE 128
|
||||
|
||||
class User {
|
||||
public:
|
||||
|
||||
@@ -40,7 +40,7 @@ void SecuritySettingsService::configureJWTHandler() {
|
||||
}
|
||||
|
||||
Authentication SecuritySettingsService::authenticateJWT(String & jwt) {
|
||||
DynamicJsonDocument payloadDocument(MAX_JWT_SIZE);
|
||||
JsonDocument payloadDocument;
|
||||
_jwtHandler.parseJWT(jwt, payloadDocument);
|
||||
if (payloadDocument.is<JsonObject>()) {
|
||||
JsonObject parsedPayload = payloadDocument.as<JsonObject>();
|
||||
@@ -69,15 +69,15 @@ inline void populateJWTPayload(JsonObject & payload, User * user) {
|
||||
}
|
||||
|
||||
boolean SecuritySettingsService::validatePayload(JsonObject & parsedPayload, User * user) {
|
||||
DynamicJsonDocument jsonDocument(MAX_JWT_SIZE);
|
||||
JsonObject payload = jsonDocument.to<JsonObject>();
|
||||
JsonDocument jsonDocument;
|
||||
JsonObject payload = jsonDocument.to<JsonObject>();
|
||||
populateJWTPayload(payload, user);
|
||||
return payload == parsedPayload;
|
||||
}
|
||||
|
||||
String SecuritySettingsService::generateJWT(User * user) {
|
||||
DynamicJsonDocument jsonDocument(MAX_JWT_SIZE);
|
||||
JsonObject payload = jsonDocument.to<JsonObject>();
|
||||
JsonDocument jsonDocument;
|
||||
JsonObject payload = jsonDocument.to<JsonObject>();
|
||||
populateJWTPayload(payload, user);
|
||||
return _jwtHandler.buildJWT(payload);
|
||||
}
|
||||
@@ -115,7 +115,7 @@ void SecuritySettingsService::generateToken(AsyncWebServerRequest * request) {
|
||||
AsyncWebParameter * usernameParam = request->getParam("username");
|
||||
for (User _user : _state.users) {
|
||||
if (_user.username == usernameParam->value()) {
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, GENERATE_TOKEN_SIZE);
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
root["token"] = generateJWT(&_user);
|
||||
response->setLength();
|
||||
|
||||
@@ -40,9 +40,9 @@ class SecuritySettings {
|
||||
root["jwt_secret"] = settings.jwtSecret;
|
||||
|
||||
// users
|
||||
JsonArray users = root.createNestedArray("users");
|
||||
JsonArray users = root["users"].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;
|
||||
|
||||
@@ -9,14 +9,6 @@
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
|
||||
#ifndef DEFAULT_BUFFER_SIZE
|
||||
#define DEFAULT_BUFFER_SIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef FS_BUFFER_SIZE
|
||||
#define FS_BUFFER_SIZE 8192
|
||||
#endif
|
||||
|
||||
enum class StateUpdateResult {
|
||||
CHANGED = 0, // The update changed the state and propagation should take place if required
|
||||
CHANGED_RESTART, // a restart of the device is needed
|
||||
|
||||
@@ -14,7 +14,7 @@ SystemStatus::SystemStatus(AsyncWebServer * server, SecurityManager * securityMa
|
||||
void SystemStatus::systemStatus(AsyncWebServerRequest * request) {
|
||||
emsesp::EMSESP::system_.refreshHeapMem(); // refresh free heap and max alloc heap
|
||||
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_ESP_STATUS_SIZE);
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
root["emsesp_version"] = EMSESP_APP_VERSION;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <SecurityManager.h>
|
||||
|
||||
#define MAX_ESP_STATUS_SIZE 1024
|
||||
// #define MAX_ESP_STATUS_SIZE 1024
|
||||
#define SYSTEM_STATUS_SERVICE_PATH "/rest/systemStatus"
|
||||
|
||||
class SystemStatus {
|
||||
|
||||
@@ -52,7 +52,7 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
|
||||
|
||||
if (is_firmware) {
|
||||
// Check firmware header, 0xE9 magic offset 0 indicates esp bin, chip offset 12: esp32:0, S2:2, C3:5
|
||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||
if (len > 12 && (data[0] != 0xE9 || data[12] != 0)) {
|
||||
handleError(request, 503); // service unavailable
|
||||
return;
|
||||
@@ -81,7 +81,7 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
|
||||
}
|
||||
request->onDisconnect(UploadFileService::handleEarlyDisconnect); // success, let's make sure we end the update if the client hangs up
|
||||
} else {
|
||||
handleError(request, 507); // failed to begin, send an error response Insufficient Storage
|
||||
handleError(request, 507); // failed to begin, send an error response Insufficient Storage
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -133,7 +133,7 @@ void UploadFileService::uploadComplete(AsyncWebServerRequest * request) {
|
||||
}
|
||||
|
||||
if (strlen(md5) == 32) {
|
||||
auto * response = new AsyncJsonResponse(false, 256);
|
||||
auto * response = new AsyncJsonResponse(false);
|
||||
JsonObject root = response->getRoot();
|
||||
root["md5"] = md5;
|
||||
response->setLength();
|
||||
|
||||
@@ -1,216 +0,0 @@
|
||||
#ifndef WebSocketTxRx_h
|
||||
#define WebSocketTxRx_h
|
||||
|
||||
#include <StatefulService.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <SecurityManager.h>
|
||||
|
||||
#define WEB_SOCKET_CLIENT_ID_MSG_SIZE 128
|
||||
|
||||
#define WEB_SOCKET_ORIGIN "websocket"
|
||||
#define WEB_SOCKET_ORIGIN_CLIENT_ID_PREFIX "websocket:"
|
||||
|
||||
using namespace std::placeholders; // for `_1` etc
|
||||
|
||||
template <class T>
|
||||
class WebSocketConnector {
|
||||
protected:
|
||||
StatefulService<T> * _statefulService;
|
||||
AsyncWebServer * _server;
|
||||
AsyncWebSocket _webSocket;
|
||||
size_t _bufferSize;
|
||||
|
||||
WebSocketConnector(StatefulService<T> * statefulService,
|
||||
AsyncWebServer * server,
|
||||
const char * webSocketPath,
|
||||
SecurityManager * securityManager,
|
||||
AuthenticationPredicate authenticationPredicate,
|
||||
size_t bufferSize)
|
||||
: _statefulService(statefulService)
|
||||
, _server(server)
|
||||
, _webSocket(webSocketPath)
|
||||
, _bufferSize(bufferSize) {
|
||||
_webSocket.setFilter(securityManager->filterRequest(authenticationPredicate));
|
||||
_webSocket.onEvent(std::bind(&WebSocketConnector::onWSEvent, this, _1, _2, _3, _4, _5, _6));
|
||||
_server->addHandler(&_webSocket);
|
||||
_server->on(webSocketPath, HTTP_GET, std::bind(&WebSocketConnector::forbidden, this, _1));
|
||||
}
|
||||
|
||||
WebSocketConnector(StatefulService<T> * statefulService, AsyncWebServer * server, const char * webSocketPath, size_t bufferSize)
|
||||
: _statefulService(statefulService)
|
||||
, _server(server)
|
||||
, _webSocket(webSocketPath)
|
||||
, _bufferSize(bufferSize) {
|
||||
_webSocket.onEvent(std::bind(&WebSocketConnector::onWSEvent, this, _1, _2, _3, _4, _5, _6));
|
||||
_server->addHandler(&_webSocket);
|
||||
}
|
||||
|
||||
virtual void onWSEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t * data, size_t len) = 0;
|
||||
|
||||
String clientId(AsyncWebSocketClient * client) {
|
||||
return WEB_SOCKET_ORIGIN_CLIENT_ID_PREFIX + String(client->id());
|
||||
}
|
||||
|
||||
private:
|
||||
void forbidden(AsyncWebServerRequest * request) {
|
||||
request->send(403);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class WebSocketTx : virtual public WebSocketConnector<T> {
|
||||
public:
|
||||
WebSocketTx(JsonStateReader<T> stateReader,
|
||||
StatefulService<T> * statefulService,
|
||||
AsyncWebServer * server,
|
||||
const char * webSocketPath,
|
||||
SecurityManager * securityManager,
|
||||
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
|
||||
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||
: WebSocketConnector<T>(statefulService, server, webSocketPath, securityManager, authenticationPredicate, bufferSize)
|
||||
, _stateReader(stateReader) {
|
||||
WebSocketConnector<T>::_statefulService->addUpdateHandler([&](const String & originId) { transmitData(nullptr, originId); }, false);
|
||||
}
|
||||
|
||||
WebSocketTx(JsonStateReader<T> stateReader,
|
||||
StatefulService<T> * statefulService,
|
||||
AsyncWebServer * server,
|
||||
const char * webSocketPath,
|
||||
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||
: WebSocketConnector<T>(statefulService, server, webSocketPath, bufferSize)
|
||||
, _stateReader(stateReader) {
|
||||
WebSocketConnector<T>::_statefulService->addUpdateHandler([&](const String & originId) { transmitData(nullptr, originId); }, false);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void onWSEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t * data, size_t len) {
|
||||
if (type == WS_EVT_CONNECT) {
|
||||
// when a client connects, we transmit it's id and the current payload
|
||||
transmitId(client);
|
||||
transmitData(client, WEB_SOCKET_ORIGIN);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
JsonStateReader<T> _stateReader;
|
||||
|
||||
void transmitId(AsyncWebSocketClient * client) {
|
||||
DynamicJsonDocument jsonDocument = DynamicJsonDocument(WEB_SOCKET_CLIENT_ID_MSG_SIZE);
|
||||
JsonObject root = jsonDocument.to<JsonObject>();
|
||||
root["type"] = "id";
|
||||
root["id"] = WebSocketConnector<T>::clientId(client);
|
||||
size_t len = measureJson(jsonDocument);
|
||||
AsyncWebSocketMessageBuffer * buffer = WebSocketConnector<T>::_webSocket.makeBuffer(len);
|
||||
if (buffer) {
|
||||
serializeJson(jsonDocument, (char *)buffer->get(), len + 1);
|
||||
client->text(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 sufficent for all use-cases.
|
||||
*/
|
||||
void transmitData(AsyncWebSocketClient * client, const String & originId) {
|
||||
DynamicJsonDocument jsonDocument = DynamicJsonDocument(WebSocketConnector<T>::_bufferSize);
|
||||
JsonObject root = jsonDocument.to<JsonObject>();
|
||||
root["type"] = "payload";
|
||||
root["origin_id"] = originId;
|
||||
JsonObject payload = root.createNestedObject("payload");
|
||||
WebSocketConnector<T>::_statefulService->read(payload, _stateReader);
|
||||
|
||||
size_t len = measureJson(jsonDocument);
|
||||
AsyncWebSocketMessageBuffer * buffer = WebSocketConnector<T>::_webSocket.makeBuffer(len);
|
||||
if (buffer) {
|
||||
serializeJson(jsonDocument, (char *)buffer->get(), len + 1);
|
||||
if (client) {
|
||||
client->text(buffer);
|
||||
} else {
|
||||
WebSocketConnector<T>::_webSocket.textAll(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class WebSocketRx : virtual public WebSocketConnector<T> {
|
||||
public:
|
||||
WebSocketRx(JsonStateUpdater<T> stateUpdater,
|
||||
StatefulService<T> * statefulService,
|
||||
AsyncWebServer * server,
|
||||
const char * webSocketPath,
|
||||
SecurityManager * securityManager,
|
||||
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
|
||||
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||
: WebSocketConnector<T>(statefulService, server, webSocketPath, securityManager, authenticationPredicate, bufferSize)
|
||||
, _stateUpdater(stateUpdater) {
|
||||
}
|
||||
|
||||
WebSocketRx(JsonStateUpdater<T> stateUpdater,
|
||||
StatefulService<T> * statefulService,
|
||||
AsyncWebServer * server,
|
||||
const char * webSocketPath,
|
||||
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||
: WebSocketConnector<T>(statefulService, server, webSocketPath, bufferSize)
|
||||
, _stateUpdater(stateUpdater) {
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void onWSEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t * data, size_t len) {
|
||||
if (type == WS_EVT_DATA) {
|
||||
AwsFrameInfo * info = (AwsFrameInfo *)arg;
|
||||
if (info->final && info->index == 0 && info->len == len) {
|
||||
if (info->opcode == WS_TEXT) {
|
||||
DynamicJsonDocument jsonDocument = DynamicJsonDocument(WebSocketConnector<T>::_bufferSize);
|
||||
DeserializationError error = deserializeJson(jsonDocument, (char *)data);
|
||||
if (!error && jsonDocument.is<JsonObject>()) {
|
||||
JsonObject jsonObject = jsonDocument.as<JsonObject>();
|
||||
WebSocketConnector<T>::_statefulService->update(jsonObject, _stateUpdater, WebSocketConnector<T>::clientId(client));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
JsonStateUpdater<T> _stateUpdater;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class WebSocketTxRx : public WebSocketTx<T>, public WebSocketRx<T> {
|
||||
public:
|
||||
WebSocketTxRx(JsonStateReader<T> stateReader,
|
||||
JsonStateUpdater<T> stateUpdater,
|
||||
StatefulService<T> * statefulService,
|
||||
AsyncWebServer * server,
|
||||
const char * webSocketPath,
|
||||
SecurityManager * securityManager,
|
||||
AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
|
||||
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||
: WebSocketConnector<T>(statefulService, server, webSocketPath, securityManager, authenticationPredicate, bufferSize)
|
||||
, WebSocketTx<T>(stateReader, statefulService, server, webSocketPath, securityManager, authenticationPredicate, bufferSize)
|
||||
, WebSocketRx<T>(stateUpdater, statefulService, server, webSocketPath, securityManager, authenticationPredicate, bufferSize) {
|
||||
}
|
||||
|
||||
WebSocketTxRx(JsonStateReader<T> stateReader,
|
||||
JsonStateUpdater<T> stateUpdater,
|
||||
StatefulService<T> * statefulService,
|
||||
AsyncWebServer * server,
|
||||
const char * webSocketPath,
|
||||
size_t bufferSize = DEFAULT_BUFFER_SIZE)
|
||||
: WebSocketConnector<T>(statefulService, server, webSocketPath, bufferSize)
|
||||
, WebSocketTx<T>(stateReader, statefulService, server, webSocketPath, bufferSize)
|
||||
, WebSocketRx<T>(stateUpdater, statefulService, server, webSocketPath, bufferSize) {
|
||||
}
|
||||
|
||||
protected:
|
||||
void onWSEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t * data, size_t len) {
|
||||
WebSocketRx<T>::onWSEvent(server, client, type, arg, data, len);
|
||||
WebSocketTx<T>::onWSEvent(server, client, type, arg, data, len);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -23,11 +23,11 @@ void WiFiScanner::scanNetworks(AsyncWebServerRequest * request) {
|
||||
void WiFiScanner::listNetworks(AsyncWebServerRequest * request) {
|
||||
int numNetworks = WiFi.scanComplete();
|
||||
if (numNetworks > -1) {
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_WIFI_SCANNER_SIZE);
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse(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);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#define SCAN_NETWORKS_SERVICE_PATH "/rest/scanNetworks"
|
||||
#define LIST_NETWORKS_SERVICE_PATH "/rest/listNetworks"
|
||||
|
||||
#define MAX_WIFI_SCANNER_SIZE 1024
|
||||
// #define MAX_WIFI_SCANNER_SIZE 1024
|
||||
|
||||
class WiFiScanner {
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user