Skip to content

Commit e68b762

Browse files
authored
Arduinojson6 (#8)
* Remove redundant AuthSettingsService. Will re-implement properly soon using JWT. * Support ArduinoJson >= 6.0.0 * Fix ArduinoJson version to 6.x.x
1 parent 51c5e51 commit e68b762

17 files changed

+226
-186
lines changed

platformio.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ build_flags=
2323
lib_deps =
2424
https://github.com/PaulStoffregen/Time
2525
https://github.com/gmag11/NtpClient
26-
ArduinoJson@>=5.0.0,<6.0.0
26+
ArduinoJson@>=6.0.0,<7.0.0
2727
https://github.com/me-no-dev/ESPAsyncWebServer
2828
https://github.com/me-no-dev/AsyncTCP

src/APStatus.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ APStatus::APStatus(AsyncWebServer *server) : _server(server) {
55
}
66

77
void APStatus::apStatus(AsyncWebServerRequest *request) {
8-
AsyncJsonResponse * response = new AsyncJsonResponse();
9-
JsonObject& root = response->getRoot();
8+
AsyncJsonResponse * response = new AsyncJsonResponse(MAX_AP_STATUS_SIZE);
9+
JsonObject root = response->getRoot();
1010

1111
WiFiMode_t currentWiFiMode = WiFi.getMode();
1212
root["active"] = (currentWiFiMode == WIFI_AP || currentWiFiMode == WIFI_AP_STA);

src/APStatus.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111

1212
#include <ESPAsyncWebServer.h>
1313
#include <ArduinoJson.h>
14-
#include <AsyncJson.h>
14+
#include <AsyncArduinoJson6.h>
1515
#include <IPAddress.h>
1616

17+
#define MAX_AP_STATUS_SIZE 1024
1718
#define AP_STATUS_SERVICE_PATH "/rest/apStatus"
1819

1920
class APStatus {

src/AsyncArduinoJson6.h

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
2+
/**
3+
* A copy of AsyncJson.h from ESPAsyncWebServer, updated for ArduinoJson6.
4+
*/
5+
6+
#ifndef ASYNC_ARDUINO_JSON_6_H
7+
#define ASYNC_ARDUINO_JSON_6_H
8+
9+
#include <ArduinoJson.h>
10+
#include <WebResponseImpl.h>
11+
#include <ESPAsyncWebServer.h>
12+
13+
constexpr const char* JSON_MIMETYPE = "application/json";
14+
15+
class ChunkPrint : public Print {
16+
private:
17+
uint8_t* _destination;
18+
size_t _to_skip;
19+
size_t _to_write;
20+
size_t _pos;
21+
public:
22+
ChunkPrint(uint8_t* destination, size_t from, size_t len)
23+
: _destination(destination), _to_skip(from), _to_write(len), _pos{0} {}
24+
virtual ~ChunkPrint(){}
25+
size_t write(uint8_t c){
26+
if (_to_skip > 0) {
27+
_to_skip--;
28+
return 1;
29+
} else if (_to_write > 0) {
30+
_to_write--;
31+
_destination[_pos++] = c;
32+
return 1;
33+
}
34+
return 0;
35+
}
36+
size_t write(const uint8_t *buffer, size_t size) {
37+
size_t written = 0;
38+
while (written < size && write(buffer[written])) {
39+
written++;
40+
}
41+
return written;
42+
}
43+
};
44+
45+
class AsyncJsonResponse: public AsyncAbstractResponse {
46+
private:
47+
DynamicJsonDocument _jsonDocument;
48+
bool _isValid;
49+
JsonObject _root;
50+
51+
public:
52+
AsyncJsonResponse(int maxSize): _jsonDocument(maxSize), _isValid{false} {
53+
_code = 200;
54+
_contentType = JSON_MIMETYPE;
55+
_root = _jsonDocument.to<JsonObject>();
56+
}
57+
~AsyncJsonResponse() {}
58+
JsonObject getRoot() {
59+
return _root;
60+
}
61+
bool _sourceValid() const {
62+
return _isValid;
63+
}
64+
size_t setLength() {
65+
_contentLength = measureJson(_jsonDocument);
66+
if (_contentLength) { _isValid = true; }
67+
return _contentLength;
68+
}
69+
size_t getSize() {
70+
return _jsonDocument.size();
71+
}
72+
size_t _fillBuffer(uint8_t *data, size_t len){
73+
ChunkPrint dest(data, _sentLength, len);
74+
serializeJson(_jsonDocument, dest);
75+
return len;
76+
}
77+
};
78+
79+
typedef std::function<void(AsyncWebServerRequest *request, JsonVariant json)> ArJsonRequestHandlerFunction;
80+
81+
class AsyncCallbackJsonWebHandler: public AsyncWebHandler {
82+
private:
83+
protected:
84+
const String _uri;
85+
WebRequestMethodComposite _method;
86+
ArJsonRequestHandlerFunction _onRequest;
87+
size_t _contentLength;
88+
size_t _maxContentLength;
89+
public:
90+
AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest) : _uri(uri), _method(HTTP_POST|HTTP_PUT|HTTP_PATCH), _onRequest(onRequest), _maxContentLength(16384) {}
91+
void setMethod(WebRequestMethodComposite method){ _method = method; }
92+
void setMaxContentLength(int maxContentLength){ _maxContentLength = maxContentLength; }
93+
void onRequest(ArJsonRequestHandlerFunction fn){ _onRequest = fn; }
94+
virtual bool canHandle(AsyncWebServerRequest *request) override final{
95+
if(!_onRequest)
96+
return false;
97+
98+
if(!(_method & request->method()))
99+
return false;
100+
101+
if(_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri+"/")))
102+
return false;
103+
104+
if (!request->contentType().equalsIgnoreCase(JSON_MIMETYPE))
105+
return false;
106+
107+
request->addInterestingHeader("ANY");
108+
return true;
109+
}
110+
virtual void handleRequest(AsyncWebServerRequest *request) override final {
111+
if(_onRequest) {
112+
if (request->_tempObject != NULL) {
113+
DynamicJsonDocument _jsonDocument(_maxContentLength);
114+
DeserializationError err = deserializeJson(_jsonDocument, (uint8_t*)(request->_tempObject));
115+
if (err == DeserializationError::Ok) {
116+
_onRequest(request, _jsonDocument.as<JsonVariant>());
117+
return;
118+
}
119+
}
120+
request->send(_contentLength > _maxContentLength ? 413 : 400);
121+
} else {
122+
request->send(500);
123+
}
124+
}
125+
virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final {
126+
}
127+
virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final {
128+
if (_onRequest) {
129+
_contentLength = total;
130+
if (total > 0 && request->_tempObject == NULL && total < _maxContentLength) {
131+
request->_tempObject = malloc(total);
132+
}
133+
if (request->_tempObject != NULL) {
134+
memcpy((uint8_t*)(request->_tempObject) + index, data, len);
135+
}
136+
}
137+
}
138+
virtual bool isRequestHandlerTrivial() override final {return _onRequest ? false : true;}
139+
};
140+
141+
142+
/*
143+
* Listens for a response being destroyed and calls a callback during said distruction.
144+
*
145+
* Used so we can take action after the response has been rendered to the client.
146+
*
147+
* Avoids having to fork ESPAsyncWebServer with a callback feature - still not a nice use of a destructor!
148+
*/
149+
150+
typedef std::function<void()> AsyncJsonCallback;
151+
152+
class AsyncJsonCallbackResponse: public AsyncJsonResponse {
153+
154+
private:
155+
156+
AsyncJsonCallback _callback;
157+
158+
public:
159+
160+
AsyncJsonCallbackResponse(AsyncJsonCallback callback, int maxSize) : AsyncJsonResponse(maxSize), _callback{callback} {}
161+
~AsyncJsonCallbackResponse() {
162+
_callback();
163+
}
164+
165+
};
166+
167+
#endif

src/AsyncJsonCallbackResponse.h

Lines changed: 0 additions & 31 deletions
This file was deleted.

src/AsyncJsonRequestWebHandler.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* Really only of use where there is a determinate payload size.
1515
*/
1616

17-
typedef std::function<void(AsyncWebServerRequest *request, JsonVariant &json)> JsonRequestCallback;
17+
typedef std::function<void(AsyncWebServerRequest *request, JsonDocument &jsonDocument)> JsonRequestCallback;
1818

1919
class AsyncJsonRequestWebHandler: public AsyncWebHandler {
2020

@@ -72,10 +72,10 @@ class AsyncJsonRequestWebHandler: public AsyncWebHandler {
7272

7373
// parse JSON and if possible handle the request
7474
if (request->_tempObject) {
75-
DynamicJsonBuffer jsonBuffer;
76-
JsonVariant json = jsonBuffer.parse((uint8_t *) request->_tempObject);
77-
if (json.success()) {
78-
_onRequest(request, json);
75+
DynamicJsonDocument jsonDocument(_maxContentLength);
76+
DeserializationError error = deserializeJson(jsonDocument, (uint8_t *) request->_tempObject);
77+
if (error == DeserializationError::Ok) {
78+
_onRequest(request, jsonDocument);
7979
}else{
8080
request->send(400);
8181
}

src/AuthSettingsService.cpp

Lines changed: 0 additions & 47 deletions
This file was deleted.

src/AuthSettingsService.h

Lines changed: 0 additions & 56 deletions
This file was deleted.

src/NTPStatus.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ NTPStatus::NTPStatus(AsyncWebServer *server) : _server(server) {
55
}
66

77
void NTPStatus::ntpStatus(AsyncWebServerRequest *request) {
8-
AsyncJsonResponse * response = new AsyncJsonResponse();
9-
JsonObject& root = response->getRoot();
8+
AsyncJsonResponse * response = new AsyncJsonResponse(MAX_NTP_STATUS_SIZE);
9+
JsonObject root = response->getRoot();
1010

1111
// request time now first, this can sometimes force a sync
1212
time_t timeNow = now();

src/NTPStatus.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111

1212
#include <ESPAsyncWebServer.h>
1313
#include <ArduinoJson.h>
14-
#include <AsyncJson.h>
14+
#include <AsyncArduinoJson6.h>
1515
#include <TimeLib.h>
1616
#include <NtpClientLib.h>
1717

18+
#define MAX_NTP_STATUS_SIZE 1024
1819
#define NTP_STATUS_SERVICE_PATH "/rest/ntpStatus"
1920

2021
class NTPStatus {

0 commit comments

Comments
 (0)