Merge pull request #59 from rjwats/ft_remove_arduinojson6_workaround

Remove custom work-around for missing ArduinoJson6 support
This commit is contained in:
rjwats 2019-11-30 13:33:33 +00:00 committed by GitHub
commit 243e1b35be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 87 additions and 215 deletions

View File

@ -7,7 +7,7 @@ APStatus::APStatus(AsyncWebServer* server, SecurityManager* securityManager) {
}
void APStatus::apStatus(AsyncWebServerRequest *request) {
AsyncJsonResponse * response = new AsyncJsonResponse(MAX_AP_STATUS_SIZE);
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_AP_STATUS_SIZE);
JsonObject root = response->getRoot();
WiFiMode_t currentWiFiMode = WiFi.getMode();

View File

@ -11,7 +11,7 @@
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include <AsyncArduinoJson6.h>
#include <AsyncJson.h>
#include <IPAddress.h>
#include <SecurityManager.h>

View File

@ -1,167 +0,0 @@
/**
* A copy of AsyncJson.h from ESPAsyncWebServer, updated for ArduinoJson6.
*/
#ifndef ASYNC_ARDUINO_JSON_6_H
#define ASYNC_ARDUINO_JSON_6_H
#include <ArduinoJson.h>
#include <WebResponseImpl.h>
#include <ESPAsyncWebServer.h>
constexpr const char* JSON_MIMETYPE = "application/json";
class ChunkPrint : public Print {
private:
uint8_t* _destination;
size_t _to_skip;
size_t _to_write;
size_t _pos;
public:
ChunkPrint(uint8_t* destination, size_t from, size_t len)
: _destination(destination), _to_skip(from), _to_write(len), _pos{0} {}
virtual ~ChunkPrint(){}
size_t write(uint8_t c){
if (_to_skip > 0) {
_to_skip--;
return 1;
} else if (_to_write > 0) {
_to_write--;
_destination[_pos++] = c;
return 1;
}
return 0;
}
size_t write(const uint8_t *buffer, size_t size) {
size_t written = 0;
while (written < size && write(buffer[written])) {
written++;
}
return written;
}
};
class AsyncJsonResponse: public AsyncAbstractResponse {
private:
DynamicJsonDocument _jsonDocument;
bool _isValid;
JsonObject _root;
public:
AsyncJsonResponse(int maxSize): _jsonDocument(maxSize), _isValid{false} {
_code = 200;
_contentType = JSON_MIMETYPE;
_root = _jsonDocument.to<JsonObject>();
}
~AsyncJsonResponse() {}
JsonObject getRoot() {
return _root;
}
bool _sourceValid() const {
return _isValid;
}
size_t setLength() {
_contentLength = measureJson(_jsonDocument);
if (_contentLength) { _isValid = true; }
return _contentLength;
}
size_t getSize() {
return _jsonDocument.size();
}
size_t _fillBuffer(uint8_t *data, size_t len){
ChunkPrint dest(data, _sentLength, len);
serializeJson(_jsonDocument, dest);
return len;
}
};
typedef std::function<void(AsyncWebServerRequest *request, JsonVariant json)> ArJsonRequestHandlerFunction;
class AsyncCallbackJsonWebHandler: public AsyncWebHandler {
private:
protected:
const String _uri;
WebRequestMethodComposite _method;
ArJsonRequestHandlerFunction _onRequest;
size_t _contentLength;
size_t _maxContentLength;
public:
AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest) : _uri(uri), _method(HTTP_POST|HTTP_PUT|HTTP_PATCH), _onRequest(onRequest), _maxContentLength(16384) {}
void setMethod(WebRequestMethodComposite method){ _method = method; }
void setMaxContentLength(int maxContentLength){ _maxContentLength = maxContentLength; }
void onRequest(ArJsonRequestHandlerFunction fn){ _onRequest = fn; }
virtual bool canHandle(AsyncWebServerRequest *request) override final{
if(!_onRequest)
return false;
if(!(_method & request->method()))
return false;
if(_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri+"/")))
return false;
if (!request->contentType().equalsIgnoreCase(JSON_MIMETYPE))
return false;
request->addInterestingHeader("ANY");
return true;
}
virtual void handleRequest(AsyncWebServerRequest *request) override final {
if(_onRequest) {
if (request->_tempObject != nullptr) {
DynamicJsonDocument _jsonDocument(_maxContentLength);
DeserializationError err = deserializeJson(_jsonDocument, (uint8_t*)(request->_tempObject));
if (err == DeserializationError::Ok) {
_onRequest(request, _jsonDocument.as<JsonVariant>());
return;
}
}
request->send(_contentLength > _maxContentLength ? 413 : 400);
} else {
request->send(500);
}
}
virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final {
}
virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final {
if (_onRequest) {
_contentLength = total;
if (total > 0 && request->_tempObject == nullptr && total < _maxContentLength) {
request->_tempObject = malloc(total);
}
if (request->_tempObject != nullptr) {
memcpy((uint8_t*)(request->_tempObject) + index, data, len);
}
}
}
virtual bool isRequestHandlerTrivial() override final {return _onRequest ? false : true;}
};
/*
* Listens for a response being destroyed and calls a callback during said distruction.
*
* Used so we can take action after the response has been rendered to the client.
*
* Avoids having to fork ESPAsyncWebServer with a callback feature - still not a nice use of a destructor!
*/
typedef std::function<void()> AsyncJsonCallback;
class AsyncJsonCallbackResponse: public AsyncJsonResponse {
private:
AsyncJsonCallback _callback;
public:
AsyncJsonCallbackResponse(AsyncJsonCallback callback, int maxSize) : AsyncJsonResponse(maxSize), _callback{callback} {}
~AsyncJsonCallbackResponse() {
_callback();
}
};
#endif

View File

@ -0,0 +1,31 @@
#ifndef _AsyncJsonCallbackResponse_H_
#define _AsyncJsonCallbackResponse_H_
#include <ESPAsyncWebServer.h>
#include <AsyncJson.h>
/*
* Listens for a response being destroyed and calls a callback during said distruction.
* used so we can take action after the response has been rendered to the client.
*
* Avoids having to fork ESPAsyncWebServer with a callback feature, but not nice!
*/
typedef std::function<void()> AsyncJsonCallback;
class AsyncJsonCallbackResponse : public AsyncJsonResponse
{
private:
AsyncJsonCallback _callback;
public:
AsyncJsonCallbackResponse(AsyncJsonCallback callback, bool isArray = false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE)
: AsyncJsonResponse(isArray, maxJsonBufferSize), _callback{callback} {}
~AsyncJsonCallbackResponse()
{
_callback();
}
};
#endif // end _AsyncJsonCallbackResponse_H_

View File

@ -30,7 +30,7 @@ void AuthenticationService::signIn(AsyncWebServerRequest *request, JsonDocument
Authentication authentication = _securityManager->authenticate(username, password);
if (authentication.isAuthenticated()) {
User* user = authentication.getUser();
AsyncJsonResponse * response = new AsyncJsonResponse(MAX_AUTHENTICATION_SIZE);
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_AUTHENTICATION_SIZE);
JsonObject jsonObject = response->getRoot();
jsonObject["access_token"] = _securityManager->generateJWT(user);
response->setLength();

View File

@ -4,7 +4,7 @@
#include <SecurityManager.h>
#include <ESPAsyncWebServer.h>
#include <AsyncJsonWebHandler.h>
#include <AsyncArduinoJson6.h>
#include <AsyncJson.h>
#define VERIFY_AUTHORIZATION_PATH "/rest/verifyAuthorization"
#define SIGN_IN_PATH "/rest/signIn"

View File

@ -7,7 +7,7 @@ NTPStatus::NTPStatus(AsyncWebServer* server, SecurityManager* securityManager) {
}
void NTPStatus::ntpStatus(AsyncWebServerRequest *request) {
AsyncJsonResponse * response = new AsyncJsonResponse(MAX_NTP_STATUS_SIZE);
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_NTP_STATUS_SIZE);
JsonObject root = response->getRoot();
// request time now first, this can sometimes force a sync

View File

@ -11,7 +11,7 @@
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include <AsyncArduinoJson6.h>
#include <AsyncJson.h>
#include <TimeLib.h>
#include <NtpClientLib.h>
#include <SecurityManager.h>

View File

@ -5,7 +5,7 @@
#include <FS.h>
#include <ArduinoJson.h>
#include <AsyncJsonWebHandler.h>
#include <AsyncArduinoJson6.h>
#include <AsyncJson.h>
/**
* At the moment, not expecting settings service to have to deal with large JSON

View File

@ -2,11 +2,11 @@
#define SettingsService_h
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#elif defined(ESP_PLATFORM)
#include <WiFi.h>
#include <AsyncTCP.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#endif
#include <SecurityManager.h>
@ -14,66 +14,73 @@
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include <AsyncJsonWebHandler.h>
#include <AsyncArduinoJson6.h>
#include <AsyncJson.h>
#include <AsyncJsonCallbackResponse.h>
/*
* Abstraction of a service which stores it's settings as JSON in a file system.
*/
class SettingsService : public SettingsPersistence {
class SettingsService : public SettingsPersistence
{
public:
public:
SettingsService(AsyncWebServer *server, FS *fs, char const *servicePath, char const *filePath) : SettingsPersistence(fs, filePath), _servicePath(servicePath)
{
server->on(_servicePath, HTTP_GET, std::bind(&SettingsService::fetchConfig, this, std::placeholders::_1));
SettingsService(AsyncWebServer* server, FS* fs, char const* servicePath, char const* filePath): SettingsPersistence(fs, filePath), _servicePath(servicePath) {
server->on(_servicePath, HTTP_GET, std::bind(&SettingsService::fetchConfig, this, std::placeholders::_1));
_updateHandler.setUri(servicePath);
_updateHandler.setMethod(HTTP_POST);
_updateHandler.setMaxContentLength(MAX_SETTINGS_SIZE);
_updateHandler.onRequest(std::bind(&SettingsService::updateConfig, this, std::placeholders::_1, std::placeholders::_2));
server->addHandler(&_updateHandler);
}
_updateHandler.setUri(servicePath);
_updateHandler.setMethod(HTTP_POST);
_updateHandler.setMaxContentLength(MAX_SETTINGS_SIZE);
_updateHandler.onRequest(std::bind(&SettingsService::updateConfig, this, std::placeholders::_1, std::placeholders::_2));
server->addHandler(&_updateHandler);
}
virtual ~SettingsService() {}
virtual ~SettingsService() {}
void begin() {
// read the initial data from the file system
readFromFS();
}
void begin()
{
// read the initial data from the file system
readFromFS();
}
protected:
char const* _servicePath;
char const *_servicePath;
AsyncJsonWebHandler _updateHandler;
virtual void fetchConfig(AsyncWebServerRequest *request) {
virtual void fetchConfig(AsyncWebServerRequest *request)
{
// handle the request
AsyncJsonResponse * response = new AsyncJsonResponse(MAX_SETTINGS_SIZE);
AsyncJsonResponse *response = new AsyncJsonResponse(false, MAX_SETTINGS_SIZE);
JsonObject jsonObject = response->getRoot();
writeToJsonObject(jsonObject);
response->setLength();
request->send(response);
}
virtual void updateConfig(AsyncWebServerRequest *request, JsonDocument &jsonDocument) {
virtual void updateConfig(AsyncWebServerRequest *request, JsonDocument &jsonDocument)
{
// handle the request
if (jsonDocument.is<JsonObject>()){
if (jsonDocument.is<JsonObject>())
{
JsonObject newConfig = jsonDocument.as<JsonObject>();
readFromJsonObject(newConfig);
writeToFS();
// write settings back with a callback to reconfigure the wifi
AsyncJsonCallbackResponse * response = new AsyncJsonCallbackResponse([this] () {onConfigUpdated();}, MAX_SETTINGS_SIZE);
AsyncJsonCallbackResponse *response = new AsyncJsonCallbackResponse([this]() { onConfigUpdated(); }, false, MAX_SETTINGS_SIZE);
JsonObject jsonObject = response->getRoot();
writeToJsonObject(jsonObject);
response->setLength();
request->send(response);
} else {
}
else
{
request->send(400);
}
}
// implement to perform action when config has been updated
virtual void onConfigUpdated(){}
virtual void onConfigUpdated() {}
};
#endif // end SettingsService

View File

@ -11,8 +11,9 @@
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include <AsyncArduinoJson6.h>
#include <AsyncJson.h>
#include <AsyncJsonWebHandler.h>
#include <AsyncJsonCallbackResponse.h>
/**
* At the moment, not expecting services to have to deal with large JSON
@ -34,7 +35,7 @@ private:
AsyncJsonWebHandler _updateHandler;
void fetchConfig(AsyncWebServerRequest *request) {
AsyncJsonResponse * response = new AsyncJsonResponse(MAX_SETTINGS_SIZE);
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_SETTINGS_SIZE);
JsonObject jsonObject = response->getRoot();
writeToJsonObject(jsonObject);
response->setLength();
@ -47,7 +48,7 @@ private:
readFromJsonObject(newConfig);
// write settings back with a callback to reconfigure the wifi
AsyncJsonCallbackResponse * response = new AsyncJsonCallbackResponse([this] () {onConfigUpdated();}, MAX_SETTINGS_SIZE);
AsyncJsonCallbackResponse * response = new AsyncJsonCallbackResponse([this] () {onConfigUpdated();}, false, MAX_SETTINGS_SIZE);
JsonObject jsonObject = response->getRoot();
writeToJsonObject(jsonObject);
response->setLength();

View File

@ -7,7 +7,7 @@ SystemStatus::SystemStatus(AsyncWebServer* server, SecurityManager* securityMana
}
void SystemStatus::systemStatus(AsyncWebServerRequest *request) {
AsyncJsonResponse * response = new AsyncJsonResponse(MAX_ESP_STATUS_SIZE);
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_ESP_STATUS_SIZE);
JsonObject root = response->getRoot();
#if defined(ESP8266)
root["esp_platform"] = "esp8266";

View File

@ -11,7 +11,7 @@
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include <AsyncArduinoJson6.h>
#include <AsyncJson.h>
#include <SecurityManager.h>
#define MAX_ESP_STATUS_SIZE 1024

View File

@ -20,7 +20,7 @@ void WiFiScanner::scanNetworks(AsyncWebServerRequest *request) {
void WiFiScanner::listNetworks(AsyncWebServerRequest *request) {
int numNetworks = WiFi.scanComplete();
if (numNetworks > -1){
AsyncJsonResponse * response = new AsyncJsonResponse(MAX_WIFI_SCANNER_SIZE);
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_WIFI_SCANNER_SIZE);
JsonObject root = response->getRoot();
JsonArray networks = root.createNestedArray("networks");
for (int i=0; i<numNetworks ; i++){

View File

@ -11,7 +11,7 @@
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include <AsyncArduinoJson6.h>
#include <AsyncJson.h>
#include <TimeLib.h>
#include <SecurityManager.h>

View File

@ -51,7 +51,7 @@ void WiFiStatus::onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
#endif
void WiFiStatus::wifiStatus(AsyncWebServerRequest *request) {
AsyncJsonResponse * response = new AsyncJsonResponse(MAX_WIFI_STATUS_SIZE);
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_WIFI_STATUS_SIZE);
JsonObject root = response->getRoot();
wl_status_t status = WiFi.status();
root["status"] = (uint8_t) status;

View File

@ -11,7 +11,7 @@
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include <AsyncArduinoJson6.h>
#include <AsyncJson.h>
#include <IPAddress.h>
#include <SecurityManager.h>