Merge pull request #68 from rjwats/clang-format
reformat with .clang-format based on google's spec with some minor ch…
This commit is contained in:
commit
368bfef29b
15
.clang-format
Normal file
15
.clang-format
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: Google
|
||||||
|
ColumnLimit: 120
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: false
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
BreakConstructorInitializers: AfterColon
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
DerivePointerAlignment: false
|
@ -1,8 +1,11 @@
|
|||||||
#include <APSettingsService.h>
|
#include <APSettingsService.h>
|
||||||
|
|
||||||
APSettingsService::APSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager) : AdminSettingsService(server, fs, securityManager, AP_SETTINGS_SERVICE_PATH, AP_SETTINGS_FILE) {}
|
APSettingsService::APSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager) :
|
||||||
|
AdminSettingsService(server, fs, securityManager, AP_SETTINGS_SERVICE_PATH, AP_SETTINGS_FILE) {
|
||||||
|
}
|
||||||
|
|
||||||
APSettingsService::~APSettingsService() {}
|
APSettingsService::~APSettingsService() {
|
||||||
|
}
|
||||||
|
|
||||||
void APSettingsService::begin() {
|
void APSettingsService::begin() {
|
||||||
SettingsService::begin();
|
SettingsService::begin();
|
||||||
@ -12,10 +15,10 @@ void APSettingsService::begin() {
|
|||||||
void APSettingsService::loop() {
|
void APSettingsService::loop() {
|
||||||
unsigned long currentMillis = millis();
|
unsigned long currentMillis = millis();
|
||||||
unsigned long manageElapsed = (unsigned long)(currentMillis - _lastManaged);
|
unsigned long manageElapsed = (unsigned long)(currentMillis - _lastManaged);
|
||||||
if (manageElapsed >= MANAGE_NETWORK_DELAY){
|
if (manageElapsed >= MANAGE_NETWORK_DELAY) {
|
||||||
_lastManaged = currentMillis;
|
_lastManaged = currentMillis;
|
||||||
manageAP();
|
manageAP();
|
||||||
}
|
}
|
||||||
handleDNS();
|
handleDNS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,39 +20,34 @@
|
|||||||
#define AP_SETTINGS_SERVICE_PATH "/rest/apSettings"
|
#define AP_SETTINGS_SERVICE_PATH "/rest/apSettings"
|
||||||
|
|
||||||
class APSettingsService : public AdminSettingsService {
|
class APSettingsService : public AdminSettingsService {
|
||||||
|
public:
|
||||||
|
APSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager);
|
||||||
|
~APSettingsService();
|
||||||
|
|
||||||
public:
|
void begin();
|
||||||
|
void loop();
|
||||||
|
|
||||||
APSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager);
|
protected:
|
||||||
~APSettingsService();
|
void readFromJsonObject(JsonObject& root);
|
||||||
|
void writeToJsonObject(JsonObject& root);
|
||||||
|
void onConfigUpdated();
|
||||||
|
|
||||||
void begin();
|
private:
|
||||||
void loop();
|
// access point settings
|
||||||
|
uint8_t _provisionMode;
|
||||||
|
String _ssid;
|
||||||
|
String _password;
|
||||||
|
|
||||||
protected:
|
// for the mangement delay loop
|
||||||
|
unsigned long _lastManaged;
|
||||||
|
|
||||||
void readFromJsonObject(JsonObject& root);
|
// for the captive portal
|
||||||
void writeToJsonObject(JsonObject& root);
|
DNSServer* _dnsServer;
|
||||||
void onConfigUpdated();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// access point settings
|
|
||||||
uint8_t _provisionMode;
|
|
||||||
String _ssid;
|
|
||||||
String _password;
|
|
||||||
|
|
||||||
// for the mangement delay loop
|
|
||||||
unsigned long _lastManaged;
|
|
||||||
|
|
||||||
// for the captive portal
|
|
||||||
DNSServer *_dnsServer;
|
|
||||||
|
|
||||||
void manageAP();
|
|
||||||
void startAP();
|
|
||||||
void stopAP() ;
|
|
||||||
void handleDNS();
|
|
||||||
|
|
||||||
|
void manageAP();
|
||||||
|
void startAP();
|
||||||
|
void stopAP();
|
||||||
|
void handleDNS();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end APSettingsConfig_h
|
#endif // end APSettingsConfig_h
|
@ -1,17 +1,18 @@
|
|||||||
#include <APStatus.h>
|
#include <APStatus.h>
|
||||||
|
|
||||||
APStatus::APStatus(AsyncWebServer* server, SecurityManager* securityManager) {
|
APStatus::APStatus(AsyncWebServer* server, SecurityManager* securityManager) {
|
||||||
server->on(AP_STATUS_SERVICE_PATH, HTTP_GET,
|
server->on(AP_STATUS_SERVICE_PATH,
|
||||||
securityManager->wrapRequest(std::bind(&APStatus::apStatus, this, std::placeholders::_1), AuthenticationPredicates::IS_AUTHENTICATED)
|
HTTP_GET,
|
||||||
);
|
securityManager->wrapRequest(std::bind(&APStatus::apStatus, this, std::placeholders::_1),
|
||||||
|
AuthenticationPredicates::IS_AUTHENTICATED));
|
||||||
}
|
}
|
||||||
|
|
||||||
void APStatus::apStatus(AsyncWebServerRequest *request) {
|
void APStatus::apStatus(AsyncWebServerRequest* request) {
|
||||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_AP_STATUS_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_AP_STATUS_SIZE);
|
||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
|
|
||||||
WiFiMode_t currentWiFiMode = WiFi.getMode();
|
WiFiMode_t currentWiFiMode = WiFi.getMode();
|
||||||
root["active"] = (currentWiFiMode == WIFI_AP || currentWiFiMode == WIFI_AP_STA);
|
root["active"] = (currentWiFiMode == WIFI_AP || currentWiFiMode == WIFI_AP_STA);
|
||||||
root["ip_address"] = WiFi.softAPIP().toString();
|
root["ip_address"] = WiFi.softAPIP().toString();
|
||||||
root["mac_address"] = WiFi.softAPmacAddress();
|
root["mac_address"] = WiFi.softAPmacAddress();
|
||||||
root["station_num"] = WiFi.softAPgetStationNum();
|
root["station_num"] = WiFi.softAPgetStationNum();
|
||||||
|
@ -2,16 +2,16 @@
|
|||||||
#define APStatus_h
|
#define APStatus_h
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <ESPAsyncTCP.h>
|
#include <ESPAsyncTCP.h>
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
#include <WiFi.h>
|
#include <AsyncTCP.h>
|
||||||
#include <AsyncTCP.h>
|
#include <WiFi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <AsyncJson.h>
|
#include <AsyncJson.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <IPAddress.h>
|
#include <IPAddress.h>
|
||||||
#include <SecurityManager.h>
|
#include <SecurityManager.h>
|
||||||
|
|
||||||
@ -19,15 +19,11 @@
|
|||||||
#define AP_STATUS_SERVICE_PATH "/rest/apStatus"
|
#define AP_STATUS_SERVICE_PATH "/rest/apStatus"
|
||||||
|
|
||||||
class APStatus {
|
class APStatus {
|
||||||
|
public:
|
||||||
|
APStatus(AsyncWebServer* server, SecurityManager* securityManager);
|
||||||
|
|
||||||
public:
|
private:
|
||||||
|
void apStatus(AsyncWebServerRequest* request);
|
||||||
APStatus(AsyncWebServer* server, SecurityManager* securityManager);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void apStatus(AsyncWebServerRequest *request);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end APStatus_h
|
#endif // end APStatus_h
|
||||||
|
@ -4,42 +4,46 @@
|
|||||||
#include <SettingsService.h>
|
#include <SettingsService.h>
|
||||||
|
|
||||||
class AdminSettingsService : public SettingsService {
|
class AdminSettingsService : public SettingsService {
|
||||||
|
public:
|
||||||
public:
|
AdminSettingsService(AsyncWebServer* server,
|
||||||
AdminSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager, char const* servicePath, char const* filePath):
|
FS* fs,
|
||||||
SettingsService(server, fs, servicePath, filePath), _securityManager(securityManager) {}
|
SecurityManager* securityManager,
|
||||||
|
char const* servicePath,
|
||||||
|
char const* filePath) :
|
||||||
|
SettingsService(server, fs, servicePath, filePath),
|
||||||
|
_securityManager(securityManager) {
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// will validate the requests with the security manager
|
// will validate the requests with the security manager
|
||||||
SecurityManager* _securityManager;
|
SecurityManager* _securityManager;
|
||||||
|
|
||||||
void fetchConfig(AsyncWebServerRequest *request) {
|
void fetchConfig(AsyncWebServerRequest* request) {
|
||||||
// verify the request against the predicate
|
// verify the request against the predicate
|
||||||
Authentication authentication = _securityManager->authenticateRequest(request);
|
Authentication authentication = _securityManager->authenticateRequest(request);
|
||||||
if (!getAuthenticationPredicate()(authentication)) {
|
if (!getAuthenticationPredicate()(authentication)) {
|
||||||
request->send(401);
|
request->send(401);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
// delegate to underlying implemetation
|
|
||||||
SettingsService::fetchConfig(request);
|
|
||||||
}
|
}
|
||||||
|
// delegate to underlying implemetation
|
||||||
|
SettingsService::fetchConfig(request);
|
||||||
|
}
|
||||||
|
|
||||||
void updateConfig(AsyncWebServerRequest *request, JsonDocument &jsonDocument) {
|
void updateConfig(AsyncWebServerRequest* request, JsonDocument& jsonDocument) {
|
||||||
// verify the request against the predicate
|
// verify the request against the predicate
|
||||||
Authentication authentication = _securityManager->authenticateRequest(request);
|
Authentication authentication = _securityManager->authenticateRequest(request);
|
||||||
if (!getAuthenticationPredicate()(authentication)) {
|
if (!getAuthenticationPredicate()(authentication)) {
|
||||||
request->send(401);
|
request->send(401);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
// delegate to underlying implemetation
|
|
||||||
SettingsService::updateConfig(request, jsonDocument);
|
|
||||||
}
|
|
||||||
|
|
||||||
// override this to replace the default authentication predicate, IS_ADMIN
|
|
||||||
AuthenticationPredicate getAuthenticationPredicate() {
|
|
||||||
return AuthenticationPredicates::IS_ADMIN;
|
|
||||||
}
|
}
|
||||||
|
// delegate to underlying implemetation
|
||||||
|
SettingsService::updateConfig(request, jsonDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
// override this to replace the default authentication predicate, IS_ADMIN
|
||||||
|
AuthenticationPredicate getAuthenticationPredicate() {
|
||||||
|
return AuthenticationPredicates::IS_ADMIN;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end AdminSettingsService
|
#endif // end AdminSettingsService
|
||||||
|
@ -1,47 +1,48 @@
|
|||||||
#include "ArduinoJsonJWT.h"
|
#include "ArduinoJsonJWT.h"
|
||||||
|
|
||||||
ArduinoJsonJWT::ArduinoJsonJWT(String secret) : _secret(secret) { }
|
ArduinoJsonJWT::ArduinoJsonJWT(String secret) : _secret(secret) {
|
||||||
|
}
|
||||||
|
|
||||||
void ArduinoJsonJWT::setSecret(String secret){
|
void ArduinoJsonJWT::setSecret(String secret) {
|
||||||
_secret = secret;
|
_secret = secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ArduinoJsonJWT::getSecret(){
|
String ArduinoJsonJWT::getSecret() {
|
||||||
return _secret;
|
return _secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ESP32 uses mbedtls, ESP2866 uses bearssl.
|
* ESP32 uses mbedtls, ESP2866 uses bearssl.
|
||||||
*
|
*
|
||||||
* Both come with decent HMAC implmentations supporting sha256, as well as others.
|
* Both come with decent HMAC implmentations supporting sha256, as well as others.
|
||||||
*
|
*
|
||||||
* No need to pull in additional crypto libraries - lets use what we already have.
|
* No need to pull in additional crypto libraries - lets use what we already have.
|
||||||
*/
|
*/
|
||||||
String ArduinoJsonJWT::sign(String &payload) {
|
String ArduinoJsonJWT::sign(String& payload) {
|
||||||
unsigned char hmacResult[32];
|
unsigned char hmacResult[32];
|
||||||
{
|
{
|
||||||
#if defined(ESP_PLATFORM)
|
#if defined(ESP_PLATFORM)
|
||||||
mbedtls_md_context_t ctx;
|
mbedtls_md_context_t ctx;
|
||||||
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
|
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
|
||||||
mbedtls_md_init(&ctx);
|
mbedtls_md_init(&ctx);
|
||||||
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 1);
|
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 1);
|
||||||
mbedtls_md_hmac_starts(&ctx, (unsigned char *) _secret.c_str(), _secret.length());
|
mbedtls_md_hmac_starts(&ctx, (unsigned char*)_secret.c_str(), _secret.length());
|
||||||
mbedtls_md_hmac_update(&ctx, (unsigned char *) payload.c_str(), payload.length());
|
mbedtls_md_hmac_update(&ctx, (unsigned char*)payload.c_str(), payload.length());
|
||||||
mbedtls_md_hmac_finish(&ctx, hmacResult);
|
mbedtls_md_hmac_finish(&ctx, hmacResult);
|
||||||
mbedtls_md_free(&ctx);
|
mbedtls_md_free(&ctx);
|
||||||
#else
|
#else
|
||||||
br_hmac_key_context keyCtx;
|
br_hmac_key_context keyCtx;
|
||||||
br_hmac_key_init(&keyCtx, &br_sha256_vtable, _secret.c_str(), _secret.length());
|
br_hmac_key_init(&keyCtx, &br_sha256_vtable, _secret.c_str(), _secret.length());
|
||||||
br_hmac_context hmacCtx;
|
br_hmac_context hmacCtx;
|
||||||
br_hmac_init(&hmacCtx, &keyCtx, 0);
|
br_hmac_init(&hmacCtx, &keyCtx, 0);
|
||||||
br_hmac_update(&hmacCtx, payload.c_str(), payload.length());
|
br_hmac_update(&hmacCtx, payload.c_str(), payload.length());
|
||||||
br_hmac_out(&hmacCtx, hmacResult);
|
br_hmac_out(&hmacCtx, hmacResult);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return encode((char *) hmacResult, 32);
|
return encode((char*)hmacResult, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
String ArduinoJsonJWT::buildJWT(JsonObject &payload) {
|
String ArduinoJsonJWT::buildJWT(JsonObject& payload) {
|
||||||
// serialize, then encode payload
|
// serialize, then encode payload
|
||||||
String jwt;
|
String jwt;
|
||||||
serializeJson(payload, jwt);
|
serializeJson(payload, jwt);
|
||||||
@ -49,14 +50,14 @@ String ArduinoJsonJWT::buildJWT(JsonObject &payload) {
|
|||||||
|
|
||||||
// add the header to payload
|
// add the header to payload
|
||||||
jwt = JWT_HEADER + '.' + jwt;
|
jwt = JWT_HEADER + '.' + jwt;
|
||||||
|
|
||||||
// add signature
|
// add signature
|
||||||
jwt += '.' + sign(jwt);
|
jwt += '.' + sign(jwt);
|
||||||
|
|
||||||
return jwt;
|
return jwt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArduinoJsonJWT::parseJWT(String jwt, JsonDocument &jsonDocument) {
|
void ArduinoJsonJWT::parseJWT(String jwt, JsonDocument& jsonDocument) {
|
||||||
// clear json document before we begin, jsonDocument wil be null on failure
|
// clear json document before we begin, jsonDocument wil be null on failure
|
||||||
jsonDocument.clear();
|
jsonDocument.clear();
|
||||||
|
|
||||||
@ -74,33 +75,33 @@ void ArduinoJsonJWT::parseJWT(String jwt, JsonDocument &jsonDocument) {
|
|||||||
// check the signature is valid
|
// check the signature is valid
|
||||||
String signature = jwt.substring(signatureDelimiterIndex + 1);
|
String signature = jwt.substring(signatureDelimiterIndex + 1);
|
||||||
jwt = jwt.substring(0, signatureDelimiterIndex);
|
jwt = jwt.substring(0, signatureDelimiterIndex);
|
||||||
if (sign(jwt) != signature){
|
if (sign(jwt) != signature) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode payload
|
// decode payload
|
||||||
jwt = jwt.substring(JWT_HEADER_SIZE + 1);
|
jwt = jwt.substring(JWT_HEADER_SIZE + 1);
|
||||||
jwt = decode(jwt);
|
jwt = decode(jwt);
|
||||||
|
|
||||||
// parse payload, clearing json document after failure
|
// parse payload, clearing json document after failure
|
||||||
DeserializationError error = deserializeJson(jsonDocument, jwt);
|
DeserializationError error = deserializeJson(jsonDocument, jwt);
|
||||||
if (error != DeserializationError::Ok || !jsonDocument.is<JsonObject>()){
|
if (error != DeserializationError::Ok || !jsonDocument.is<JsonObject>()) {
|
||||||
jsonDocument.clear();
|
jsonDocument.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String ArduinoJsonJWT::encode(const char *cstr, int inputLen) {
|
String ArduinoJsonJWT::encode(const char* cstr, int inputLen) {
|
||||||
// prepare encoder
|
// prepare encoder
|
||||||
base64_encodestate _state;
|
base64_encodestate _state;
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
base64_init_encodestate_nonewlines(&_state);
|
base64_init_encodestate_nonewlines(&_state);
|
||||||
size_t encodedLength = base64_encode_expected_len_nonewlines(inputLen) + 1;
|
size_t encodedLength = base64_encode_expected_len_nonewlines(inputLen) + 1;
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
base64_init_encodestate(&_state);
|
base64_init_encodestate(&_state);
|
||||||
size_t encodedLength = base64_encode_expected_len(inputLen) + 1;
|
size_t encodedLength = base64_encode_expected_len(inputLen) + 1;
|
||||||
#endif
|
#endif
|
||||||
// prepare buffer of correct length, returning an empty string on failure
|
// prepare buffer of correct length, returning an empty string on failure
|
||||||
char* buffer = (char*) malloc(encodedLength * sizeof(char));
|
char* buffer = (char*)malloc(encodedLength * sizeof(char));
|
||||||
if (buffer == nullptr) {
|
if (buffer == nullptr) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -113,10 +114,10 @@ String ArduinoJsonJWT::encode(const char *cstr, int inputLen) {
|
|||||||
// convert to arduino string, freeing buffer
|
// convert to arduino string, freeing buffer
|
||||||
String value = String(buffer);
|
String value = String(buffer);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
buffer=nullptr;
|
buffer = nullptr;
|
||||||
|
|
||||||
// remove padding and convert to URL safe form
|
// remove padding and convert to URL safe form
|
||||||
while (value.length() > 0 && value.charAt(value.length() - 1) == '='){
|
while (value.length() > 0 && value.charAt(value.length() - 1) == '=') {
|
||||||
value.remove(value.length() - 1);
|
value.remove(value.length() - 1);
|
||||||
}
|
}
|
||||||
value.replace('+', '-');
|
value.replace('+', '-');
|
||||||
@ -129,7 +130,7 @@ String ArduinoJsonJWT::encode(const char *cstr, int inputLen) {
|
|||||||
String ArduinoJsonJWT::decode(String value) {
|
String ArduinoJsonJWT::decode(String value) {
|
||||||
// convert to standard base64
|
// convert to standard base64
|
||||||
value.replace('-', '+');
|
value.replace('-', '+');
|
||||||
value.replace( '_', '/');
|
value.replace('_', '/');
|
||||||
|
|
||||||
// prepare buffer of correct length
|
// prepare buffer of correct length
|
||||||
char buffer[base64_decode_expected_len(value.length()) + 1];
|
char buffer[base64_decode_expected_len(value.length()) + 1];
|
||||||
@ -139,5 +140,5 @@ String ArduinoJsonJWT::decode(String value) {
|
|||||||
buffer[len] = 0;
|
buffer[len] = 0;
|
||||||
|
|
||||||
// return as string
|
// return as string
|
||||||
return String(buffer);
|
return String(buffer);
|
||||||
}
|
}
|
||||||
|
@ -6,33 +6,31 @@
|
|||||||
#include <libb64/cdecode.h>
|
#include <libb64/cdecode.h>
|
||||||
#include <libb64/cencode.h>
|
#include <libb64/cencode.h>
|
||||||
#if defined(ESP_PLATFORM)
|
#if defined(ESP_PLATFORM)
|
||||||
#include <mbedtls/md.h>
|
#include <mbedtls/md.h>
|
||||||
#else
|
#else
|
||||||
#include <bearssl/bearssl_hmac.h>
|
#include <bearssl/bearssl_hmac.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class ArduinoJsonJWT {
|
class ArduinoJsonJWT {
|
||||||
|
private:
|
||||||
private:
|
|
||||||
String _secret;
|
String _secret;
|
||||||
|
|
||||||
const String JWT_HEADER = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
|
const String JWT_HEADER = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
|
||||||
const int JWT_HEADER_SIZE = JWT_HEADER.length();
|
const int JWT_HEADER_SIZE = JWT_HEADER.length();
|
||||||
|
|
||||||
String sign(String &value);
|
String sign(String& value);
|
||||||
|
|
||||||
static String encode(const char *cstr, int len);
|
static String encode(const char* cstr, int len);
|
||||||
static String decode(String value);
|
static String decode(String value);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ArduinoJsonJWT(String secret);
|
ArduinoJsonJWT(String secret);
|
||||||
|
|
||||||
void setSecret(String secret);
|
void setSecret(String secret);
|
||||||
String getSecret();
|
String getSecret();
|
||||||
|
|
||||||
String buildJWT(JsonObject &payload);
|
String buildJWT(JsonObject& payload);
|
||||||
void parseJWT(String jwt, JsonDocument &jsonDocument);
|
void parseJWT(String jwt, JsonDocument& jsonDocument);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,31 +1,33 @@
|
|||||||
#ifndef _AsyncJsonCallbackResponse_H_
|
#ifndef _AsyncJsonCallbackResponse_H_
|
||||||
#define _AsyncJsonCallbackResponse_H_
|
#define _AsyncJsonCallbackResponse_H_
|
||||||
|
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include <AsyncJson.h>
|
#include <AsyncJson.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Listens for a response being destroyed and calls a callback during said distruction.
|
* 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.
|
* 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!
|
* Avoids having to fork ESPAsyncWebServer with a callback feature, but not nice!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef std::function<void()> AsyncJsonCallback;
|
typedef std::function<void()> AsyncJsonCallback;
|
||||||
|
|
||||||
class AsyncJsonCallbackResponse : public AsyncJsonResponse
|
class AsyncJsonCallbackResponse : public AsyncJsonResponse {
|
||||||
{
|
private:
|
||||||
|
AsyncJsonCallback _callback;
|
||||||
|
|
||||||
private:
|
public:
|
||||||
AsyncJsonCallback _callback;
|
AsyncJsonCallbackResponse(AsyncJsonCallback callback,
|
||||||
|
bool isArray = false,
|
||||||
|
size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) :
|
||||||
|
AsyncJsonResponse(isArray, maxJsonBufferSize),
|
||||||
|
_callback{callback} {
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
~AsyncJsonCallbackResponse() {
|
||||||
AsyncJsonCallbackResponse(AsyncJsonCallback callback, bool isArray = false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE)
|
_callback();
|
||||||
: AsyncJsonResponse(isArray, maxJsonBufferSize), _callback{callback} {}
|
}
|
||||||
~AsyncJsonCallbackResponse()
|
|
||||||
{
|
|
||||||
_callback();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end _AsyncJsonCallbackResponse_H_
|
#endif // end _AsyncJsonCallbackResponse_H_
|
||||||
|
@ -1,120 +1,131 @@
|
|||||||
#ifndef Async_Json_Request_Web_Handler_H_
|
#ifndef Async_Json_Request_Web_Handler_H_
|
||||||
#define Async_Json_Request_Web_Handler_H_
|
#define Async_Json_Request_Web_Handler_H_
|
||||||
|
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
|
||||||
#define ASYNC_JSON_REQUEST_DEFAULT_MAX_SIZE 1024
|
#define ASYNC_JSON_REQUEST_DEFAULT_MAX_SIZE 1024
|
||||||
#define ASYNC_JSON_REQUEST_MIMETYPE "application/json"
|
#define ASYNC_JSON_REQUEST_MIMETYPE "application/json"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handy little utility for dealing with small JSON request body payloads.
|
* Handy little utility for dealing with small JSON request body payloads.
|
||||||
*
|
*
|
||||||
* Need to be careful using this as we are somewhat limited by RAM.
|
* Need to be careful using this as we are somewhat limited by RAM.
|
||||||
*
|
*
|
||||||
* Really only of use where there is a determinate payload size.
|
* Really only of use where there is a determinate payload size.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef std::function<void(AsyncWebServerRequest *request, JsonDocument &jsonDocument)> JsonRequestCallback;
|
typedef std::function<void(AsyncWebServerRequest* request, JsonDocument& jsonDocument)> JsonRequestCallback;
|
||||||
|
|
||||||
class AsyncJsonWebHandler: public AsyncWebHandler {
|
class AsyncJsonWebHandler : public AsyncWebHandler {
|
||||||
|
private:
|
||||||
|
WebRequestMethodComposite _method;
|
||||||
|
JsonRequestCallback _onRequest;
|
||||||
|
size_t _maxContentLength;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
WebRequestMethodComposite _method;
|
String _uri;
|
||||||
JsonRequestCallback _onRequest;
|
|
||||||
size_t _maxContentLength;
|
|
||||||
|
|
||||||
protected:
|
public:
|
||||||
String _uri;
|
AsyncJsonWebHandler() :
|
||||||
|
_method(HTTP_POST | HTTP_PUT | HTTP_PATCH),
|
||||||
public:
|
|
||||||
|
|
||||||
AsyncJsonWebHandler() :
|
|
||||||
_method(HTTP_POST|HTTP_PUT|HTTP_PATCH),
|
|
||||||
_onRequest(nullptr),
|
_onRequest(nullptr),
|
||||||
_maxContentLength(ASYNC_JSON_REQUEST_DEFAULT_MAX_SIZE),
|
_maxContentLength(ASYNC_JSON_REQUEST_DEFAULT_MAX_SIZE),
|
||||||
_uri() {}
|
_uri() {
|
||||||
|
}
|
||||||
|
|
||||||
~AsyncJsonWebHandler() {}
|
~AsyncJsonWebHandler() {
|
||||||
|
}
|
||||||
|
|
||||||
void setUri(const String& uri) { _uri = uri; }
|
void setUri(const String& uri) {
|
||||||
void setMethod(WebRequestMethodComposite method) { _method = method; }
|
_uri = uri;
|
||||||
void setMaxContentLength(size_t maxContentLength) { _maxContentLength = maxContentLength; }
|
}
|
||||||
void onRequest(JsonRequestCallback fn) { _onRequest = fn; }
|
void setMethod(WebRequestMethodComposite method) {
|
||||||
|
_method = method;
|
||||||
|
}
|
||||||
|
void setMaxContentLength(size_t maxContentLength) {
|
||||||
|
_maxContentLength = maxContentLength;
|
||||||
|
}
|
||||||
|
void onRequest(JsonRequestCallback fn) {
|
||||||
|
_onRequest = fn;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool canHandle(AsyncWebServerRequest *request) override final {
|
virtual bool canHandle(AsyncWebServerRequest* request) override final {
|
||||||
if(!_onRequest)
|
if (!_onRequest)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!(_method & request->method()))
|
if (!(_method & request->method()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri+"/")))
|
if (_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri + "/")))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!request->contentType().equalsIgnoreCase(ASYNC_JSON_REQUEST_MIMETYPE))
|
if (!request->contentType().equalsIgnoreCase(ASYNC_JSON_REQUEST_MIMETYPE))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
request->addInterestingHeader("ANY");
|
request->addInterestingHeader("ANY");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void handleRequest(AsyncWebServerRequest *request) override final {
|
virtual void handleRequest(AsyncWebServerRequest* request) override final {
|
||||||
// no request configured
|
// no request configured
|
||||||
if(!_onRequest) {
|
if (!_onRequest) {
|
||||||
Serial.print("No request callback was configured for endpoint: ");
|
Serial.print("No request callback was configured for endpoint: ");
|
||||||
Serial.println(_uri);
|
Serial.println(_uri);
|
||||||
request->send(500);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we have been handed too much data, return a 413 (payload too large)
|
|
||||||
if (request->contentLength() > _maxContentLength) {
|
|
||||||
request->send(413);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse JSON and if possible handle the request
|
|
||||||
if (request->_tempObject) {
|
|
||||||
DynamicJsonDocument jsonDocument(_maxContentLength);
|
|
||||||
DeserializationError error = deserializeJson(jsonDocument, (uint8_t *) request->_tempObject);
|
|
||||||
if (error == DeserializationError::Ok) {
|
|
||||||
_onRequest(request, jsonDocument);
|
|
||||||
}else{
|
|
||||||
request->send(400);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fallthrough, we have a null pointer, return 500.
|
|
||||||
// this can be due to running out of memory or never receiving body data.
|
|
||||||
request->send(500);
|
request->send(500);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final {
|
// we have been handed too much data, return a 413 (payload too large)
|
||||||
if (_onRequest) {
|
if (request->contentLength() > _maxContentLength) {
|
||||||
// don't allocate if data is too large
|
request->send(413);
|
||||||
if (total > _maxContentLength){
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// try to allocate memory on first call
|
// parse JSON and if possible handle the request
|
||||||
// NB: the memory allocated here is freed by ~AsyncWebServerRequest
|
if (request->_tempObject) {
|
||||||
if(index == 0 && !request->_tempObject){
|
DynamicJsonDocument jsonDocument(_maxContentLength);
|
||||||
request->_tempObject = malloc(total);
|
DeserializationError error = deserializeJson(jsonDocument, (uint8_t*)request->_tempObject);
|
||||||
}
|
if (error == DeserializationError::Ok) {
|
||||||
|
_onRequest(request, jsonDocument);
|
||||||
|
} else {
|
||||||
|
request->send(400);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// copy the data into the buffer, if we have a buffer!
|
// fallthrough, we have a null pointer, return 500.
|
||||||
if (request->_tempObject) {
|
// this can be due to running out of memory or never receiving body data.
|
||||||
memcpy((uint8_t *) request->_tempObject+index, data, len);
|
request->send(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void handleBody(AsyncWebServerRequest* request,
|
||||||
|
uint8_t* data,
|
||||||
|
size_t len,
|
||||||
|
size_t index,
|
||||||
|
size_t total) override final {
|
||||||
|
if (_onRequest) {
|
||||||
|
// don't allocate if data is too large
|
||||||
|
if (total > _maxContentLength) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to allocate memory on first call
|
||||||
|
// NB: the memory allocated here is freed by ~AsyncWebServerRequest
|
||||||
|
if (index == 0 && !request->_tempObject) {
|
||||||
|
request->_tempObject = malloc(total);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy the data into the buffer, if we have a buffer!
|
||||||
|
if (request->_tempObject) {
|
||||||
|
memcpy((uint8_t*)request->_tempObject + index, data, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool isRequestHandlerTrivial() override final {
|
virtual bool isRequestHandlerTrivial() override final {
|
||||||
return _onRequest ? false : true;
|
return _onRequest ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end Async_Json_Request_Web_Handler_H_
|
#endif // end Async_Json_Request_Web_Handler_H_
|
||||||
|
@ -1,36 +1,41 @@
|
|||||||
#include <AuthenticationService.h>
|
#include <AuthenticationService.h>
|
||||||
|
|
||||||
AuthenticationService::AuthenticationService(AsyncWebServer* server, SecurityManager* securityManager) : _securityManager(securityManager) {
|
AuthenticationService::AuthenticationService(AsyncWebServer* server, SecurityManager* securityManager) :
|
||||||
server->on(VERIFY_AUTHORIZATION_PATH, HTTP_GET, std::bind(&AuthenticationService::verifyAuthorization, this, std::placeholders::_1));
|
_securityManager(securityManager) {
|
||||||
|
server->on(VERIFY_AUTHORIZATION_PATH,
|
||||||
|
HTTP_GET,
|
||||||
|
std::bind(&AuthenticationService::verifyAuthorization, this, std::placeholders::_1));
|
||||||
_signInHandler.setUri(SIGN_IN_PATH);
|
_signInHandler.setUri(SIGN_IN_PATH);
|
||||||
_signInHandler.setMethod(HTTP_POST);
|
_signInHandler.setMethod(HTTP_POST);
|
||||||
_signInHandler.setMaxContentLength(MAX_AUTHENTICATION_SIZE);
|
_signInHandler.setMaxContentLength(MAX_AUTHENTICATION_SIZE);
|
||||||
_signInHandler.onRequest(std::bind(&AuthenticationService::signIn, this, std::placeholders::_1, std::placeholders::_2));
|
_signInHandler.onRequest(
|
||||||
|
std::bind(&AuthenticationService::signIn, this, std::placeholders::_1, std::placeholders::_2));
|
||||||
server->addHandler(&_signInHandler);
|
server->addHandler(&_signInHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthenticationService::~AuthenticationService() {}
|
AuthenticationService::~AuthenticationService() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifys that the request supplied a valid JWT.
|
* Verifys that the request supplied a valid JWT.
|
||||||
*/
|
*/
|
||||||
void AuthenticationService::verifyAuthorization(AsyncWebServerRequest *request) {
|
void AuthenticationService::verifyAuthorization(AsyncWebServerRequest* request) {
|
||||||
Authentication authentication = _securityManager->authenticateRequest(request);
|
Authentication authentication = _securityManager->authenticateRequest(request);
|
||||||
request->send(authentication.isAuthenticated() ? 200: 401);
|
request->send(authentication.isAuthenticated() ? 200 : 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signs in a user if the username and password match. Provides a JWT to be used in the Authorization header in subsequent requests.
|
* Signs in a user if the username and password match. Provides a JWT to be used in the Authorization header in
|
||||||
|
* subsequent requests.
|
||||||
*/
|
*/
|
||||||
void AuthenticationService::signIn(AsyncWebServerRequest *request, JsonDocument &jsonDocument){
|
void AuthenticationService::signIn(AsyncWebServerRequest* request, JsonDocument& jsonDocument) {
|
||||||
if (jsonDocument.is<JsonObject>()) {
|
if (jsonDocument.is<JsonObject>()) {
|
||||||
String username = jsonDocument["username"];
|
String username = jsonDocument["username"];
|
||||||
String password = jsonDocument["password"];
|
String password = jsonDocument["password"];
|
||||||
Authentication authentication = _securityManager->authenticate(username, password);
|
Authentication authentication = _securityManager->authenticate(username, password);
|
||||||
if (authentication.isAuthenticated()) {
|
if (authentication.isAuthenticated()) {
|
||||||
User* user = authentication.getUser();
|
User* user = authentication.getUser();
|
||||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_AUTHENTICATION_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_AUTHENTICATION_SIZE);
|
||||||
JsonObject jsonObject = response->getRoot();
|
JsonObject jsonObject = response->getRoot();
|
||||||
jsonObject["access_token"] = _securityManager->generateJWT(user);
|
jsonObject["access_token"] = _securityManager->generateJWT(user);
|
||||||
response->setLength();
|
response->setLength();
|
||||||
@ -38,7 +43,6 @@ void AuthenticationService::signIn(AsyncWebServerRequest *request, JsonDocument
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AsyncWebServerResponse *response = request->beginResponse(401);
|
AsyncWebServerResponse* response = request->beginResponse(401);
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,32 +1,28 @@
|
|||||||
#ifndef AuthenticationService_H_
|
#ifndef AuthenticationService_H_
|
||||||
#define AuthenticationService_H_
|
#define AuthenticationService_H_
|
||||||
|
|
||||||
#include <SecurityManager.h>
|
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include <AsyncJsonWebHandler.h>
|
|
||||||
#include <AsyncJson.h>
|
#include <AsyncJson.h>
|
||||||
|
#include <AsyncJsonWebHandler.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
#include <SecurityManager.h>
|
||||||
|
|
||||||
#define VERIFY_AUTHORIZATION_PATH "/rest/verifyAuthorization"
|
#define VERIFY_AUTHORIZATION_PATH "/rest/verifyAuthorization"
|
||||||
#define SIGN_IN_PATH "/rest/signIn"
|
#define SIGN_IN_PATH "/rest/signIn"
|
||||||
|
|
||||||
#define MAX_AUTHENTICATION_SIZE 256
|
#define MAX_AUTHENTICATION_SIZE 256
|
||||||
|
|
||||||
class AuthenticationService {
|
class AuthenticationService {
|
||||||
|
public:
|
||||||
|
AuthenticationService(AsyncWebServer* server, SecurityManager* securityManager);
|
||||||
|
~AuthenticationService();
|
||||||
|
|
||||||
public:
|
private:
|
||||||
|
SecurityManager* _securityManager;
|
||||||
AuthenticationService(AsyncWebServer* server, SecurityManager* securityManager);
|
AsyncJsonWebHandler _signInHandler;
|
||||||
~AuthenticationService();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
SecurityManager* _securityManager;
|
|
||||||
AsyncJsonWebHandler _signInHandler;
|
|
||||||
|
|
||||||
// endpoint functions
|
|
||||||
void signIn(AsyncWebServerRequest *request, JsonDocument &jsonDocument);
|
|
||||||
void verifyAuthorization(AsyncWebServerRequest *request);
|
|
||||||
|
|
||||||
|
// endpoint functions
|
||||||
|
void signIn(AsyncWebServerRequest* request, JsonDocument& jsonDocument);
|
||||||
|
void verifyAuthorization(AsyncWebServerRequest* request);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end SecurityManager_h
|
#endif // end SecurityManager_h
|
@ -1,18 +1,18 @@
|
|||||||
#include <ESP8266React.h>
|
#include <ESP8266React.h>
|
||||||
|
|
||||||
ESP8266React::ESP8266React(AsyncWebServer* server, FS* fs):
|
ESP8266React::ESP8266React(AsyncWebServer* server, FS* fs) :
|
||||||
_securitySettingsService(server, fs),
|
_securitySettingsService(server, fs),
|
||||||
_wifiSettingsService(server, fs, &_securitySettingsService),
|
_wifiSettingsService(server, fs, &_securitySettingsService),
|
||||||
_apSettingsService(server, fs, &_securitySettingsService),
|
_apSettingsService(server, fs, &_securitySettingsService),
|
||||||
_ntpSettingsService(server, fs, &_securitySettingsService),
|
_ntpSettingsService(server, fs, &_securitySettingsService),
|
||||||
_otaSettingsService(server, fs, &_securitySettingsService),
|
_otaSettingsService(server, fs, &_securitySettingsService),
|
||||||
_restartService(server, &_securitySettingsService),
|
_restartService(server, &_securitySettingsService),
|
||||||
_authenticationService(server, &_securitySettingsService),
|
_authenticationService(server, &_securitySettingsService),
|
||||||
_wifiScanner(server, &_securitySettingsService),
|
_wifiScanner(server, &_securitySettingsService),
|
||||||
_wifiStatus(server, &_securitySettingsService),
|
_wifiStatus(server, &_securitySettingsService),
|
||||||
_ntpStatus(server, &_securitySettingsService),
|
_ntpStatus(server, &_securitySettingsService),
|
||||||
_apStatus(server, &_securitySettingsService),
|
_apStatus(server, &_securitySettingsService),
|
||||||
_systemStatus(server, &_securitySettingsService) {
|
_systemStatus(server, &_securitySettingsService) {
|
||||||
// Serve static resources from /www/
|
// Serve static resources from /www/
|
||||||
server->serveStatic("/js/", SPIFFS, "/www/js/");
|
server->serveStatic("/js/", SPIFFS, "/www/js/");
|
||||||
server->serveStatic("/css/", SPIFFS, "/www/css/");
|
server->serveStatic("/css/", SPIFFS, "/www/css/");
|
||||||
@ -22,7 +22,7 @@ ESP8266React::ESP8266React(AsyncWebServer* server, FS* fs):
|
|||||||
|
|
||||||
// Serving all other get requests with "/www/index.htm"
|
// Serving all other get requests with "/www/index.htm"
|
||||||
// OPTIONS get a straight up 200 response
|
// OPTIONS get a straight up 200 response
|
||||||
server->onNotFound([](AsyncWebServerRequest *request) {
|
server->onNotFound([](AsyncWebServerRequest* request) {
|
||||||
if (request->method() == HTTP_GET) {
|
if (request->method() == HTTP_GET) {
|
||||||
request->send(SPIFFS, "/www/index.html");
|
request->send(SPIFFS, "/www/index.html");
|
||||||
} else if (request->method() == HTTP_OPTIONS) {
|
} else if (request->method() == HTTP_OPTIONS) {
|
||||||
@ -32,12 +32,12 @@ ESP8266React::ESP8266React(AsyncWebServer* server, FS* fs):
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Disable CORS if required
|
// Disable CORS if required
|
||||||
#if defined(ENABLE_CORS)
|
#if defined(ENABLE_CORS)
|
||||||
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", CORS_ORIGIN);
|
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", CORS_ORIGIN);
|
||||||
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "Accept, Content-Type, Authorization");
|
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "Accept, Content-Type, Authorization");
|
||||||
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Credentials", "true");
|
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Credentials", "true");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP8266React::begin() {
|
void ESP8266React::begin() {
|
||||||
@ -48,7 +48,7 @@ void ESP8266React::begin() {
|
|||||||
_otaSettingsService.begin();
|
_otaSettingsService.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP8266React::loop() {
|
void ESP8266React::loop() {
|
||||||
_wifiSettingsService.loop();
|
_wifiSettingsService.loop();
|
||||||
_apSettingsService.loop();
|
_apSettingsService.loop();
|
||||||
_ntpSettingsService.loop();
|
_ntpSettingsService.loop();
|
||||||
|
@ -4,59 +4,54 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <ESPAsyncTCP.h>
|
#include <ESPAsyncTCP.h>
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
#include <WiFi.h>
|
#include <AsyncTCP.h>
|
||||||
#include <AsyncTCP.h>
|
#include <SPIFFS.h>
|
||||||
#include <SPIFFS.h>
|
#include <WiFi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <FS.h>
|
|
||||||
#include <SecuritySettingsService.h>
|
|
||||||
#include <WiFiSettingsService.h>
|
|
||||||
#include <APSettingsService.h>
|
#include <APSettingsService.h>
|
||||||
#include <NTPSettingsService.h>
|
|
||||||
#include <OTASettingsService.h>
|
|
||||||
#include <AuthenticationService.h>
|
|
||||||
#include <WiFiScanner.h>
|
|
||||||
#include <WiFiStatus.h>
|
|
||||||
#include <NTPStatus.h>
|
|
||||||
#include <APStatus.h>
|
#include <APStatus.h>
|
||||||
#include <SystemStatus.h>
|
#include <AuthenticationService.h>
|
||||||
|
#include <FS.h>
|
||||||
|
#include <NTPSettingsService.h>
|
||||||
|
#include <NTPStatus.h>
|
||||||
|
#include <OTASettingsService.h>
|
||||||
#include <RestartService.h>
|
#include <RestartService.h>
|
||||||
|
#include <SecuritySettingsService.h>
|
||||||
|
#include <SystemStatus.h>
|
||||||
|
#include <WiFiScanner.h>
|
||||||
|
#include <WiFiSettingsService.h>
|
||||||
|
#include <WiFiStatus.h>
|
||||||
|
|
||||||
class ESP8266React {
|
class ESP8266React {
|
||||||
|
public:
|
||||||
|
ESP8266React(AsyncWebServer* server, FS* fs);
|
||||||
|
|
||||||
public:
|
void begin();
|
||||||
|
void loop();
|
||||||
|
|
||||||
ESP8266React(AsyncWebServer* server, FS* fs);
|
SecurityManager* getSecurityManager() {
|
||||||
|
return &_securitySettingsService;
|
||||||
void begin();
|
}
|
||||||
void loop();
|
|
||||||
|
|
||||||
SecurityManager* getSecurityManager(){
|
|
||||||
return &_securitySettingsService;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
SecuritySettingsService _securitySettingsService;
|
||||||
|
|
||||||
SecuritySettingsService _securitySettingsService;
|
WiFiSettingsService _wifiSettingsService;
|
||||||
|
APSettingsService _apSettingsService;
|
||||||
WiFiSettingsService _wifiSettingsService;
|
NTPSettingsService _ntpSettingsService;
|
||||||
APSettingsService _apSettingsService;
|
OTASettingsService _otaSettingsService;
|
||||||
NTPSettingsService _ntpSettingsService;
|
RestartService _restartService;
|
||||||
OTASettingsService _otaSettingsService;
|
AuthenticationService _authenticationService;
|
||||||
RestartService _restartService;
|
|
||||||
AuthenticationService _authenticationService;
|
|
||||||
|
|
||||||
|
|
||||||
WiFiScanner _wifiScanner;
|
|
||||||
WiFiStatus _wifiStatus;
|
|
||||||
NTPStatus _ntpStatus;
|
|
||||||
APStatus _apStatus;
|
|
||||||
SystemStatus _systemStatus;
|
|
||||||
|
|
||||||
|
WiFiScanner _wifiScanner;
|
||||||
|
WiFiStatus _wifiStatus;
|
||||||
|
NTPStatus _ntpStatus;
|
||||||
|
APStatus _apStatus;
|
||||||
|
SystemStatus _systemStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,22 +1,28 @@
|
|||||||
#include <NTPSettingsService.h>
|
#include <NTPSettingsService.h>
|
||||||
|
|
||||||
NTPSettingsService::NTPSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager) : AdminSettingsService(server, fs, securityManager, NTP_SETTINGS_SERVICE_PATH, NTP_SETTINGS_FILE) {
|
NTPSettingsService::NTPSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager) :
|
||||||
|
AdminSettingsService(server, fs, securityManager, NTP_SETTINGS_SERVICE_PATH, NTP_SETTINGS_FILE) {
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
_onStationModeDisconnectedHandler = WiFi.onStationModeDisconnected(std::bind(&NTPSettingsService::onStationModeDisconnected, this, std::placeholders::_1));
|
_onStationModeDisconnectedHandler = WiFi.onStationModeDisconnected(
|
||||||
_onStationModeGotIPHandler = WiFi.onStationModeGotIP(std::bind(&NTPSettingsService::onStationModeGotIP, this, std::placeholders::_1));
|
std::bind(&NTPSettingsService::onStationModeDisconnected, this, std::placeholders::_1));
|
||||||
|
_onStationModeGotIPHandler =
|
||||||
|
WiFi.onStationModeGotIP(std::bind(&NTPSettingsService::onStationModeGotIP, this, std::placeholders::_1));
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
WiFi.onEvent(std::bind(&NTPSettingsService::onStationModeDisconnected, this, std::placeholders::_1, std::placeholders::_2), WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED);
|
WiFi.onEvent(
|
||||||
WiFi.onEvent(std::bind(&NTPSettingsService::onStationModeGotIP, this, std::placeholders::_1, std::placeholders::_2), WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP);
|
std::bind(&NTPSettingsService::onStationModeDisconnected, this, std::placeholders::_1, std::placeholders::_2),
|
||||||
|
WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED);
|
||||||
|
WiFi.onEvent(std::bind(&NTPSettingsService::onStationModeGotIP, this, std::placeholders::_1, std::placeholders::_2),
|
||||||
|
WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NTP.onNTPSyncEvent ([this](NTPSyncEvent_t ntpEvent) {
|
NTP.onNTPSyncEvent([this](NTPSyncEvent_t ntpEvent) {
|
||||||
_ntpEvent = ntpEvent;
|
_ntpEvent = ntpEvent;
|
||||||
_syncEventTriggered = true;
|
_syncEventTriggered = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
NTPSettingsService::~NTPSettingsService() {}
|
NTPSettingsService::~NTPSettingsService() {
|
||||||
|
}
|
||||||
|
|
||||||
void NTPSettingsService::loop() {
|
void NTPSettingsService::loop() {
|
||||||
// detect when we need to re-configure NTP and do it in the main loop
|
// detect when we need to re-configure NTP and do it in the main loop
|
||||||
@ -41,12 +47,12 @@ void NTPSettingsService::readFromJsonObject(JsonObject& root) {
|
|||||||
|
|
||||||
// validate server is specified, resorting to default
|
// validate server is specified, resorting to default
|
||||||
_server.trim();
|
_server.trim();
|
||||||
if (!_server){
|
if (!_server) {
|
||||||
_server = NTP_SETTINGS_SERVICE_DEFAULT_SERVER;
|
_server = NTP_SETTINGS_SERVICE_DEFAULT_SERVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure interval is in bounds
|
// make sure interval is in bounds
|
||||||
if (_interval < NTP_SETTINGS_MIN_INTERVAL){
|
if (_interval < NTP_SETTINGS_MIN_INTERVAL) {
|
||||||
_interval = NTP_SETTINGS_MIN_INTERVAL;
|
_interval = NTP_SETTINGS_MIN_INTERVAL;
|
||||||
} else if (_interval > NTP_SETTINGS_MAX_INTERVAL) {
|
} else if (_interval > NTP_SETTINGS_MAX_INTERVAL) {
|
||||||
_interval = NTP_SETTINGS_MAX_INTERVAL;
|
_interval = NTP_SETTINGS_MAX_INTERVAL;
|
||||||
@ -98,14 +104,14 @@ void NTPSettingsService::configureNTP() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NTPSettingsService::processSyncEvent(NTPSyncEvent_t ntpEvent) {
|
void NTPSettingsService::processSyncEvent(NTPSyncEvent_t ntpEvent) {
|
||||||
if (ntpEvent) {
|
if (ntpEvent) {
|
||||||
Serial.print ("Time Sync error: ");
|
Serial.print("Time Sync error: ");
|
||||||
if (ntpEvent == noResponse)
|
if (ntpEvent == noResponse)
|
||||||
Serial.println ("NTP server not reachable");
|
Serial.println("NTP server not reachable");
|
||||||
else if (ntpEvent == invalidAddress)
|
else if (ntpEvent == invalidAddress)
|
||||||
Serial.println ("Invalid NTP server address");
|
Serial.println("Invalid NTP server address");
|
||||||
} else {
|
} else {
|
||||||
Serial.print ("Got NTP time: ");
|
Serial.print("Got NTP time: ");
|
||||||
Serial.println (NTP.getTimeDateString (NTP.getLastNTPSync ()));
|
Serial.println(NTP.getTimeDateString(NTP.getLastNTPSync()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
#include <AdminSettingsService.h>
|
#include <AdminSettingsService.h>
|
||||||
|
|
||||||
#include <TimeLib.h>
|
|
||||||
#include <NtpClientLib.h>
|
#include <NtpClientLib.h>
|
||||||
|
#include <TimeLib.h>
|
||||||
|
|
||||||
// default time server
|
// default time server
|
||||||
#define NTP_SETTINGS_SERVICE_DEFAULT_SERVER "pool.ntp.org"
|
#define NTP_SETTINGS_SERVICE_DEFAULT_SERVER "pool.ntp.org"
|
||||||
@ -18,43 +18,38 @@
|
|||||||
#define NTP_SETTINGS_SERVICE_PATH "/rest/ntpSettings"
|
#define NTP_SETTINGS_SERVICE_PATH "/rest/ntpSettings"
|
||||||
|
|
||||||
class NTPSettingsService : public AdminSettingsService {
|
class NTPSettingsService : public AdminSettingsService {
|
||||||
|
public:
|
||||||
|
NTPSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager);
|
||||||
|
~NTPSettingsService();
|
||||||
|
|
||||||
public:
|
void loop();
|
||||||
|
|
||||||
NTPSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager);
|
protected:
|
||||||
~NTPSettingsService();
|
void readFromJsonObject(JsonObject& root);
|
||||||
|
void writeToJsonObject(JsonObject& root);
|
||||||
|
void onConfigUpdated();
|
||||||
|
|
||||||
void loop();
|
private:
|
||||||
|
String _server;
|
||||||
|
int _interval;
|
||||||
|
|
||||||
protected:
|
bool _reconfigureNTP = false;
|
||||||
|
bool _syncEventTriggered = false;
|
||||||
void readFromJsonObject(JsonObject& root);
|
NTPSyncEvent_t _ntpEvent;
|
||||||
void writeToJsonObject(JsonObject& root);
|
|
||||||
void onConfigUpdated();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
String _server;
|
|
||||||
int _interval;
|
|
||||||
|
|
||||||
bool _reconfigureNTP = false;
|
|
||||||
bool _syncEventTriggered = false;
|
|
||||||
NTPSyncEvent_t _ntpEvent;
|
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
WiFiEventHandler _onStationModeDisconnectedHandler;
|
WiFiEventHandler _onStationModeDisconnectedHandler;
|
||||||
WiFiEventHandler _onStationModeGotIPHandler;
|
WiFiEventHandler _onStationModeGotIPHandler;
|
||||||
|
|
||||||
void onStationModeGotIP(const WiFiEventStationModeGotIP& event);
|
void onStationModeGotIP(const WiFiEventStationModeGotIP& event);
|
||||||
void onStationModeDisconnected(const WiFiEventStationModeDisconnected& event);
|
void onStationModeDisconnected(const WiFiEventStationModeDisconnected& event);
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
void onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info);
|
void onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||||
void onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info);
|
void onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void configureNTP();
|
void configureNTP();
|
||||||
void processSyncEvent(NTPSyncEvent_t ntpEvent);
|
void processSyncEvent(NTPSyncEvent_t ntpEvent);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end NTPSettingsService_h
|
#endif // end NTPSettingsService_h
|
||||||
|
@ -1,27 +1,28 @@
|
|||||||
#include <NTPStatus.h>
|
#include <NTPStatus.h>
|
||||||
|
|
||||||
NTPStatus::NTPStatus(AsyncWebServer* server, SecurityManager* securityManager) {
|
NTPStatus::NTPStatus(AsyncWebServer* server, SecurityManager* securityManager) {
|
||||||
server->on(NTP_STATUS_SERVICE_PATH, HTTP_GET,
|
server->on(NTP_STATUS_SERVICE_PATH,
|
||||||
securityManager->wrapRequest(std::bind(&NTPStatus::ntpStatus, this, std::placeholders::_1), AuthenticationPredicates::IS_AUTHENTICATED)
|
HTTP_GET,
|
||||||
);
|
securityManager->wrapRequest(std::bind(&NTPStatus::ntpStatus, this, std::placeholders::_1),
|
||||||
|
AuthenticationPredicates::IS_AUTHENTICATED));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTPStatus::ntpStatus(AsyncWebServerRequest *request) {
|
void NTPStatus::ntpStatus(AsyncWebServerRequest* request) {
|
||||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_NTP_STATUS_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_NTP_STATUS_SIZE);
|
||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
|
|
||||||
// request time now first, this can sometimes force a sync
|
// request time now first, this can sometimes force a sync
|
||||||
time_t timeNow = now();
|
time_t timeNow = now();
|
||||||
timeStatus_t status = timeStatus();
|
timeStatus_t status = timeStatus();
|
||||||
time_t lastSync = NTP.getLastNTPSync();
|
time_t lastSync = NTP.getLastNTPSync();
|
||||||
root["status"] = (int) status;
|
root["status"] = (int)status;
|
||||||
root["last_sync"] = lastSync;
|
root["last_sync"] = lastSync;
|
||||||
root["server"] = NTP.getNtpServerName();
|
root["server"] = NTP.getNtpServerName();
|
||||||
root["interval"] = NTP.getInterval();
|
root["interval"] = NTP.getInterval();
|
||||||
root["uptime"] = NTP.getUptime();
|
root["uptime"] = NTP.getUptime();
|
||||||
|
|
||||||
// only add now to response if we have successfully synced
|
// only add now to response if we have successfully synced
|
||||||
if (status != timeNotSet){
|
if (status != timeNotSet) {
|
||||||
root["now"] = timeNow;
|
root["now"] = timeNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,33 +2,29 @@
|
|||||||
#define NTPStatus_h
|
#define NTPStatus_h
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <ESPAsyncTCP.h>
|
#include <ESPAsyncTCP.h>
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
#include <WiFi.h>
|
#include <AsyncTCP.h>
|
||||||
#include <AsyncTCP.h>
|
#include <WiFi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <AsyncJson.h>
|
#include <AsyncJson.h>
|
||||||
#include <TimeLib.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <NtpClientLib.h>
|
#include <NtpClientLib.h>
|
||||||
#include <SecurityManager.h>
|
#include <SecurityManager.h>
|
||||||
|
#include <TimeLib.h>
|
||||||
|
|
||||||
#define MAX_NTP_STATUS_SIZE 1024
|
#define MAX_NTP_STATUS_SIZE 1024
|
||||||
#define NTP_STATUS_SERVICE_PATH "/rest/ntpStatus"
|
#define NTP_STATUS_SERVICE_PATH "/rest/ntpStatus"
|
||||||
|
|
||||||
class NTPStatus {
|
class NTPStatus {
|
||||||
|
public:
|
||||||
|
NTPStatus(AsyncWebServer* server, SecurityManager* securityManager);
|
||||||
|
|
||||||
public:
|
private:
|
||||||
|
void ntpStatus(AsyncWebServerRequest* request);
|
||||||
NTPStatus(AsyncWebServer* server, SecurityManager* securityManager);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void ntpStatus(AsyncWebServerRequest *request);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end NTPStatus_h
|
#endif // end NTPStatus_h
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
#include <OTASettingsService.h>
|
#include <OTASettingsService.h>
|
||||||
|
|
||||||
OTASettingsService::OTASettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager) : AdminSettingsService(server, fs, securityManager, OTA_SETTINGS_SERVICE_PATH, OTA_SETTINGS_FILE) {
|
OTASettingsService::OTASettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager) :
|
||||||
|
AdminSettingsService(server, fs, securityManager, OTA_SETTINGS_SERVICE_PATH, OTA_SETTINGS_FILE) {
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
_onStationModeGotIPHandler = WiFi.onStationModeGotIP(std::bind(&OTASettingsService::onStationModeGotIP, this, std::placeholders::_1));
|
_onStationModeGotIPHandler =
|
||||||
|
WiFi.onStationModeGotIP(std::bind(&OTASettingsService::onStationModeGotIP, this, std::placeholders::_1));
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
WiFi.onEvent(std::bind(&OTASettingsService::onStationModeGotIP, this, std::placeholders::_1, std::placeholders::_2), WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP);
|
WiFi.onEvent(std::bind(&OTASettingsService::onStationModeGotIP, this, std::placeholders::_1, std::placeholders::_2),
|
||||||
|
WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
OTASettingsService::~OTASettingsService() {}
|
OTASettingsService::~OTASettingsService() {
|
||||||
|
}
|
||||||
|
|
||||||
void OTASettingsService::loop() {
|
void OTASettingsService::loop() {
|
||||||
if (_enabled && _arduinoOTA){
|
if (_enabled && _arduinoOTA) {
|
||||||
_arduinoOTA->handle();
|
_arduinoOTA->handle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -26,7 +30,7 @@ void OTASettingsService::readFromJsonObject(JsonObject& root) {
|
|||||||
_password = root["password"] | DEFAULT_OTA_PASSWORD;
|
_password = root["password"] | DEFAULT_OTA_PASSWORD;
|
||||||
|
|
||||||
// provide defaults
|
// provide defaults
|
||||||
if (_port < 0){
|
if (_port < 0) {
|
||||||
_port = DEFAULT_OTA_PORT;
|
_port = DEFAULT_OTA_PORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -38,7 +42,7 @@ void OTASettingsService::writeToJsonObject(JsonObject& root) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OTASettingsService::configureArduinoOTA() {
|
void OTASettingsService::configureArduinoOTA() {
|
||||||
if (_arduinoOTA){
|
if (_arduinoOTA) {
|
||||||
#if defined(ESP_PLATFORM)
|
#if defined(ESP_PLATFORM)
|
||||||
_arduinoOTA->end();
|
_arduinoOTA->end();
|
||||||
#endif
|
#endif
|
||||||
@ -50,22 +54,23 @@ void OTASettingsService::configureArduinoOTA() {
|
|||||||
_arduinoOTA = new ArduinoOTAClass;
|
_arduinoOTA = new ArduinoOTAClass;
|
||||||
_arduinoOTA->setPort(_port);
|
_arduinoOTA->setPort(_port);
|
||||||
_arduinoOTA->setPassword(_password.c_str());
|
_arduinoOTA->setPassword(_password.c_str());
|
||||||
_arduinoOTA->onStart([]() {
|
_arduinoOTA->onStart([]() { Serial.println("Starting"); });
|
||||||
Serial.println("Starting");
|
_arduinoOTA->onEnd([]() { Serial.println("\nEnd"); });
|
||||||
});
|
|
||||||
_arduinoOTA->onEnd([]() {
|
|
||||||
Serial.println("\nEnd");
|
|
||||||
});
|
|
||||||
_arduinoOTA->onProgress([](unsigned int progress, unsigned int total) {
|
_arduinoOTA->onProgress([](unsigned int progress, unsigned int total) {
|
||||||
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
|
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
|
||||||
});
|
});
|
||||||
_arduinoOTA->onError([](ota_error_t error) {
|
_arduinoOTA->onError([](ota_error_t error) {
|
||||||
Serial.printf("Error[%u]: ", error);
|
Serial.printf("Error[%u]: ", error);
|
||||||
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
|
if (error == OTA_AUTH_ERROR)
|
||||||
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
|
Serial.println("Auth Failed");
|
||||||
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
|
else if (error == OTA_BEGIN_ERROR)
|
||||||
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
|
Serial.println("Begin Failed");
|
||||||
else if (error == OTA_END_ERROR) Serial.println("End Failed");
|
else if (error == OTA_CONNECT_ERROR)
|
||||||
|
Serial.println("Connect Failed");
|
||||||
|
else if (error == OTA_RECEIVE_ERROR)
|
||||||
|
Serial.println("Receive Failed");
|
||||||
|
else if (error == OTA_END_ERROR)
|
||||||
|
Serial.println("End Failed");
|
||||||
});
|
});
|
||||||
_arduinoOTA->begin();
|
_arduinoOTA->begin();
|
||||||
}
|
}
|
||||||
@ -74,9 +79,9 @@ void OTASettingsService::configureArduinoOTA() {
|
|||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
void OTASettingsService::onStationModeGotIP(const WiFiEventStationModeGotIP& event) {
|
void OTASettingsService::onStationModeGotIP(const WiFiEventStationModeGotIP& event) {
|
||||||
configureArduinoOTA();
|
configureArduinoOTA();
|
||||||
}
|
}
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
void OTASettingsService::onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
|
void OTASettingsService::onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||||
configureArduinoOTA();
|
configureArduinoOTA();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -4,13 +4,13 @@
|
|||||||
#include <AdminSettingsService.h>
|
#include <AdminSettingsService.h>
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
#include <ESP8266mDNS.h>
|
#include <ESP8266mDNS.h>
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <WiFiUdp.h>
|
|
||||||
#include <ArduinoOTA.h>
|
#include <ArduinoOTA.h>
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
|
||||||
// Emergency defaults
|
// Emergency defaults
|
||||||
#define DEFAULT_OTA_PORT 8266
|
#define DEFAULT_OTA_PORT 8266
|
||||||
@ -20,36 +20,31 @@
|
|||||||
#define OTA_SETTINGS_SERVICE_PATH "/rest/otaSettings"
|
#define OTA_SETTINGS_SERVICE_PATH "/rest/otaSettings"
|
||||||
|
|
||||||
class OTASettingsService : public AdminSettingsService {
|
class OTASettingsService : public AdminSettingsService {
|
||||||
|
public:
|
||||||
|
OTASettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager);
|
||||||
|
~OTASettingsService();
|
||||||
|
|
||||||
public:
|
void loop();
|
||||||
|
|
||||||
OTASettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager);
|
protected:
|
||||||
~OTASettingsService();
|
void onConfigUpdated();
|
||||||
|
void readFromJsonObject(JsonObject& root);
|
||||||
|
void writeToJsonObject(JsonObject& root);
|
||||||
|
|
||||||
void loop();
|
private:
|
||||||
|
ArduinoOTAClass* _arduinoOTA;
|
||||||
|
bool _enabled;
|
||||||
|
int _port;
|
||||||
|
String _password;
|
||||||
|
|
||||||
protected:
|
void configureArduinoOTA();
|
||||||
|
|
||||||
void onConfigUpdated();
|
|
||||||
void readFromJsonObject(JsonObject& root);
|
|
||||||
void writeToJsonObject(JsonObject& root);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
ArduinoOTAClass *_arduinoOTA;
|
|
||||||
bool _enabled;
|
|
||||||
int _port;
|
|
||||||
String _password;
|
|
||||||
|
|
||||||
void configureArduinoOTA();
|
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
WiFiEventHandler _onStationModeGotIPHandler;
|
WiFiEventHandler _onStationModeGotIPHandler;
|
||||||
void onStationModeGotIP(const WiFiEventStationModeGotIP& event);
|
void onStationModeGotIP(const WiFiEventStationModeGotIP& event);
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
void onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info);
|
void onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end OTASettingsService_h
|
#endif // end OTASettingsService_h
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#include <RestartService.h>
|
#include <RestartService.h>
|
||||||
|
|
||||||
RestartService::RestartService(AsyncWebServer* server, SecurityManager* securityManager) {
|
RestartService::RestartService(AsyncWebServer* server, SecurityManager* securityManager) {
|
||||||
server->on(RESTART_SERVICE_PATH, HTTP_POST, securityManager->wrapRequest(
|
server->on(RESTART_SERVICE_PATH,
|
||||||
std::bind(&RestartService::restart, this, std::placeholders::_1), AuthenticationPredicates::IS_ADMIN
|
HTTP_POST,
|
||||||
));
|
securityManager->wrapRequest(std::bind(&RestartService::restart, this, std::placeholders::_1),
|
||||||
|
AuthenticationPredicates::IS_ADMIN));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RestartService::restart(AsyncWebServerRequest* request) {
|
void RestartService::restart(AsyncWebServerRequest* request) {
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
#define RestartService_h
|
#define RestartService_h
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <ESPAsyncTCP.h>
|
#include <ESPAsyncTCP.h>
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
#include <WiFi.h>
|
#include <AsyncTCP.h>
|
||||||
#include <AsyncTCP.h>
|
#include <WiFi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
@ -15,15 +15,11 @@
|
|||||||
#define RESTART_SERVICE_PATH "/rest/restart"
|
#define RESTART_SERVICE_PATH "/rest/restart"
|
||||||
|
|
||||||
class RestartService {
|
class RestartService {
|
||||||
|
public:
|
||||||
|
RestartService(AsyncWebServer* server, SecurityManager* securityManager);
|
||||||
|
|
||||||
public:
|
private:
|
||||||
|
void restart(AsyncWebServerRequest* request);
|
||||||
RestartService(AsyncWebServer* server, SecurityManager* securityManager);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void restart(AsyncWebServerRequest *request);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end RestartService_h
|
#endif // end RestartService_h
|
@ -1,14 +1,14 @@
|
|||||||
#include <SecurityManager.h>
|
#include <SecurityManager.h>
|
||||||
|
|
||||||
Authentication SecurityManager::authenticateRequest(AsyncWebServerRequest *request) {
|
Authentication SecurityManager::authenticateRequest(AsyncWebServerRequest *request) {
|
||||||
AsyncWebHeader* authorizationHeader = request->getHeader(AUTHORIZATION_HEADER);
|
AsyncWebHeader *authorizationHeader = request->getHeader(AUTHORIZATION_HEADER);
|
||||||
if (authorizationHeader) {
|
if (authorizationHeader) {
|
||||||
String value = authorizationHeader->value();
|
String value = authorizationHeader->value();
|
||||||
if (value.startsWith(AUTHORIZATION_HEADER_PREFIX)){
|
if (value.startsWith(AUTHORIZATION_HEADER_PREFIX)) {
|
||||||
value = value.substring(AUTHORIZATION_HEADER_PREFIX_LEN);
|
value = value.substring(AUTHORIZATION_HEADER_PREFIX_LEN);
|
||||||
return authenticateJWT(value);
|
return authenticateJWT(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Authentication();
|
return Authentication();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ Authentication SecurityManager::authenticateJWT(String jwt) {
|
|||||||
JsonObject parsedPayload = payloadDocument.as<JsonObject>();
|
JsonObject parsedPayload = payloadDocument.as<JsonObject>();
|
||||||
String username = parsedPayload["username"];
|
String username = parsedPayload["username"];
|
||||||
for (User _user : _users) {
|
for (User _user : _users) {
|
||||||
if (_user.getUsername() == username && validatePayload(parsedPayload, &_user)){
|
if (_user.getUsername() == username && validatePayload(parsedPayload, &_user)) {
|
||||||
return Authentication(_user);
|
return Authentication(_user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,7 +29,7 @@ Authentication SecurityManager::authenticateJWT(String jwt) {
|
|||||||
|
|
||||||
Authentication SecurityManager::authenticate(String username, String password) {
|
Authentication SecurityManager::authenticate(String username, String password) {
|
||||||
for (User _user : _users) {
|
for (User _user : _users) {
|
||||||
if (_user.getUsername() == username && _user.getPassword() == password){
|
if (_user.getUsername() == username && _user.getPassword() == password) {
|
||||||
return Authentication(_user);
|
return Authentication(_user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -38,25 +38,26 @@ Authentication SecurityManager::authenticate(String username, String password) {
|
|||||||
|
|
||||||
inline void populateJWTPayload(JsonObject &payload, User *user) {
|
inline void populateJWTPayload(JsonObject &payload, User *user) {
|
||||||
payload["username"] = user->getUsername();
|
payload["username"] = user->getUsername();
|
||||||
payload["admin"] = user -> isAdmin();
|
payload["admin"] = user->isAdmin();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean SecurityManager::validatePayload(JsonObject &parsedPayload, User *user) {
|
boolean SecurityManager::validatePayload(JsonObject &parsedPayload, User *user) {
|
||||||
DynamicJsonDocument _jsonDocument(MAX_JWT_SIZE);
|
DynamicJsonDocument _jsonDocument(MAX_JWT_SIZE);
|
||||||
JsonObject payload = _jsonDocument.to<JsonObject>();
|
JsonObject payload = _jsonDocument.to<JsonObject>();
|
||||||
populateJWTPayload(payload, user);
|
populateJWTPayload(payload, user);
|
||||||
return payload == parsedPayload;
|
return payload == parsedPayload;
|
||||||
}
|
}
|
||||||
|
|
||||||
String SecurityManager::generateJWT(User *user) {
|
String SecurityManager::generateJWT(User *user) {
|
||||||
DynamicJsonDocument _jsonDocument(MAX_JWT_SIZE);
|
DynamicJsonDocument _jsonDocument(MAX_JWT_SIZE);
|
||||||
JsonObject payload = _jsonDocument.to<JsonObject>();
|
JsonObject payload = _jsonDocument.to<JsonObject>();
|
||||||
populateJWTPayload(payload, user);
|
populateJWTPayload(payload, user);
|
||||||
return _jwtHandler.buildJWT(payload);
|
return _jwtHandler.buildJWT(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArRequestHandlerFunction SecurityManager::wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate) {
|
ArRequestHandlerFunction SecurityManager::wrapRequest(ArRequestHandlerFunction onRequest,
|
||||||
return [this, onRequest, predicate](AsyncWebServerRequest *request){
|
AuthenticationPredicate predicate) {
|
||||||
|
return [this, onRequest, predicate](AsyncWebServerRequest *request) {
|
||||||
Authentication authentication = authenticateRequest(request);
|
Authentication authentication = authenticateRequest(request);
|
||||||
if (!predicate(authentication)) {
|
if (!predicate(authentication)) {
|
||||||
request->send(401);
|
request->send(401);
|
||||||
@ -64,5 +65,4 @@ ArRequestHandlerFunction SecurityManager::wrapRequest(ArRequestHandlerFunction o
|
|||||||
}
|
}
|
||||||
onRequest(request);
|
onRequest(request);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#ifndef SecurityManager_h
|
#ifndef SecurityManager_h
|
||||||
#define SecurityManager_h
|
#define SecurityManager_h
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include <ArduinoJsonJWT.h>
|
#include <ArduinoJsonJWT.h>
|
||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
#define DEFAULT_JWT_SECRET "esp8266-react"
|
#define DEFAULT_JWT_SECRET "esp8266-react"
|
||||||
|
|
||||||
@ -14,97 +14,97 @@
|
|||||||
#define MAX_JWT_SIZE 128
|
#define MAX_JWT_SIZE 128
|
||||||
|
|
||||||
class User {
|
class User {
|
||||||
private:
|
private:
|
||||||
String _username;
|
String _username;
|
||||||
String _password;
|
String _password;
|
||||||
bool _admin;
|
bool _admin;
|
||||||
public:
|
|
||||||
User(String username, String password, bool admin): _username(username), _password(password), _admin(admin) {}
|
public:
|
||||||
String getUsername() {
|
User(String username, String password, bool admin) : _username(username), _password(password), _admin(admin) {
|
||||||
return _username;
|
}
|
||||||
}
|
String getUsername() {
|
||||||
String getPassword() {
|
return _username;
|
||||||
return _password;
|
}
|
||||||
}
|
String getPassword() {
|
||||||
bool isAdmin() {
|
return _password;
|
||||||
return _admin;
|
}
|
||||||
}
|
bool isAdmin() {
|
||||||
|
return _admin;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Authentication {
|
class Authentication {
|
||||||
private:
|
private:
|
||||||
User *_user;
|
User* _user;
|
||||||
boolean _authenticated;
|
boolean _authenticated;
|
||||||
public:
|
|
||||||
Authentication(User& user): _user(new User(user)), _authenticated(true) {}
|
public:
|
||||||
Authentication() : _user(nullptr), _authenticated(false) {}
|
Authentication(User& user) : _user(new User(user)), _authenticated(true) {
|
||||||
~Authentication() {
|
}
|
||||||
delete(_user);
|
Authentication() : _user(nullptr), _authenticated(false) {
|
||||||
}
|
}
|
||||||
User* getUser() {
|
~Authentication() {
|
||||||
return _user;
|
delete (_user);
|
||||||
}
|
}
|
||||||
bool isAuthenticated() {
|
User* getUser() {
|
||||||
return _authenticated;
|
return _user;
|
||||||
}
|
}
|
||||||
|
bool isAuthenticated() {
|
||||||
|
return _authenticated;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::function<boolean(Authentication &authentication)> AuthenticationPredicate;
|
typedef std::function<boolean(Authentication& authentication)> AuthenticationPredicate;
|
||||||
|
|
||||||
class AuthenticationPredicates {
|
class AuthenticationPredicates {
|
||||||
public:
|
public:
|
||||||
static bool NONE_REQUIRED(Authentication &authentication) {
|
static bool NONE_REQUIRED(Authentication& authentication) {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
static bool IS_AUTHENTICATED(Authentication &authentication) {
|
static bool IS_AUTHENTICATED(Authentication& authentication) {
|
||||||
return authentication.isAuthenticated();
|
return authentication.isAuthenticated();
|
||||||
};
|
};
|
||||||
static bool IS_ADMIN(Authentication &authentication) {
|
static bool IS_ADMIN(Authentication& authentication) {
|
||||||
return authentication.isAuthenticated() && authentication.getUser()->isAdmin();
|
return authentication.isAuthenticated() && authentication.getUser()->isAdmin();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class SecurityManager {
|
class SecurityManager {
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
* Authenticate, returning the user if found
|
||||||
|
*/
|
||||||
|
Authentication authenticate(String username, String password);
|
||||||
|
|
||||||
public:
|
/*
|
||||||
|
* Check the request header for the Authorization token
|
||||||
|
*/
|
||||||
|
Authentication authenticateRequest(AsyncWebServerRequest* request);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Authenticate, returning the user if found
|
* Generate a JWT for the user provided
|
||||||
*/
|
*/
|
||||||
Authentication authenticate(String username, String password);
|
String generateJWT(User* user);
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Check the request header for the Authorization token
|
* Wrap the provided request to provide validation against an AuthenticationPredicate.
|
||||||
*/
|
*/
|
||||||
Authentication authenticateRequest(AsyncWebServerRequest *request);
|
ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate);
|
||||||
|
|
||||||
/*
|
|
||||||
* Generate a JWT for the user provided
|
|
||||||
*/
|
|
||||||
String generateJWT(User *user);
|
|
||||||
|
|
||||||
/**
|
protected:
|
||||||
* Wrap the provided request to provide validation against an AuthenticationPredicate.
|
ArduinoJsonJWT _jwtHandler = ArduinoJsonJWT(DEFAULT_JWT_SECRET);
|
||||||
*/
|
std::list<User> _users;
|
||||||
ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate);
|
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
|
/*
|
||||||
ArduinoJsonJWT _jwtHandler = ArduinoJsonJWT(DEFAULT_JWT_SECRET);
|
* Lookup the user by JWT
|
||||||
std::list<User> _users;
|
*/
|
||||||
|
Authentication authenticateJWT(String jwt);
|
||||||
private:
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Lookup the user by JWT
|
|
||||||
*/
|
|
||||||
Authentication authenticateJWT(String jwt);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Verify the payload is correct
|
|
||||||
*/
|
|
||||||
boolean validatePayload(JsonObject &parsedPayload, User *user);
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify the payload is correct
|
||||||
|
*/
|
||||||
|
boolean validatePayload(JsonObject& parsedPayload, User* user);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end SecurityManager_h
|
#endif // end SecurityManager_h
|
@ -1,16 +1,20 @@
|
|||||||
#include <SecuritySettingsService.h>
|
#include <SecuritySettingsService.h>
|
||||||
|
|
||||||
SecuritySettingsService::SecuritySettingsService(AsyncWebServer* server, FS* fs) : AdminSettingsService(server, fs, this, SECURITY_SETTINGS_PATH, SECURITY_SETTINGS_FILE), SecurityManager() {}
|
SecuritySettingsService::SecuritySettingsService(AsyncWebServer* server, FS* fs) :
|
||||||
SecuritySettingsService::~SecuritySettingsService() {}
|
AdminSettingsService(server, fs, this, SECURITY_SETTINGS_PATH, SECURITY_SETTINGS_FILE),
|
||||||
|
SecurityManager() {
|
||||||
|
}
|
||||||
|
SecuritySettingsService::~SecuritySettingsService() {
|
||||||
|
}
|
||||||
|
|
||||||
void SecuritySettingsService::readFromJsonObject(JsonObject& root) {
|
void SecuritySettingsService::readFromJsonObject(JsonObject& root) {
|
||||||
// secret
|
// secret
|
||||||
_jwtHandler.setSecret(root["jwt_secret"] | DEFAULT_JWT_SECRET);
|
_jwtHandler.setSecret(root["jwt_secret"] | DEFAULT_JWT_SECRET);
|
||||||
|
|
||||||
// users
|
// users
|
||||||
_users.clear();
|
_users.clear();
|
||||||
if (root["users"].is<JsonArray>()) {
|
if (root["users"].is<JsonArray>()) {
|
||||||
for (JsonVariant user : root["users"].as<JsonArray>()) {
|
for (JsonVariant user : root["users"].as<JsonArray>()) {
|
||||||
_users.push_back(User(user["username"], user["password"], user["admin"]));
|
_users.push_back(User(user["username"], user["password"], user["admin"]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,17 +8,13 @@
|
|||||||
#define SECURITY_SETTINGS_PATH "/rest/securitySettings"
|
#define SECURITY_SETTINGS_PATH "/rest/securitySettings"
|
||||||
|
|
||||||
class SecuritySettingsService : public AdminSettingsService, public SecurityManager {
|
class SecuritySettingsService : public AdminSettingsService, public SecurityManager {
|
||||||
|
public:
|
||||||
|
SecuritySettingsService(AsyncWebServer* server, FS* fs);
|
||||||
|
~SecuritySettingsService();
|
||||||
|
|
||||||
public:
|
protected:
|
||||||
|
void readFromJsonObject(JsonObject& root);
|
||||||
SecuritySettingsService(AsyncWebServer* server, FS* fs);
|
void writeToJsonObject(JsonObject& root);
|
||||||
~SecuritySettingsService();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
void readFromJsonObject(JsonObject& root);
|
|
||||||
void writeToJsonObject(JsonObject& root);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end SecuritySettingsService_h
|
#endif // end SecuritySettingsService_h
|
@ -1,26 +1,24 @@
|
|||||||
#ifndef SettingsPersistence_h
|
#ifndef SettingsPersistence_h
|
||||||
#define SettingsPersistence_h
|
#define SettingsPersistence_h
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <AsyncJson.h>
|
||||||
|
#include <AsyncJsonWebHandler.h>
|
||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include <AsyncJsonWebHandler.h>
|
|
||||||
#include <AsyncJson.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* At the moment, not expecting settings service to have to deal with large JSON
|
* At the moment, not expecting settings service to have to deal with large JSON
|
||||||
* files this could be made configurable fairly simply, it's exposed on
|
* files this could be made configurable fairly simply, it's exposed on
|
||||||
* AsyncJsonWebHandler with a setter.
|
* AsyncJsonWebHandler with a setter.
|
||||||
*/
|
*/
|
||||||
#define MAX_SETTINGS_SIZE 1024
|
#define MAX_SETTINGS_SIZE 1024
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mixin for classes which need to save settings to/from a file on the the file system as JSON.
|
* Mixin for classes which need to save settings to/from a file on the the file system as JSON.
|
||||||
*/
|
*/
|
||||||
class SettingsPersistence {
|
class SettingsPersistence {
|
||||||
|
protected:
|
||||||
protected:
|
|
||||||
|
|
||||||
// will store and retrieve config from the file system
|
// will store and retrieve config from the file system
|
||||||
FS* _fs;
|
FS* _fs;
|
||||||
|
|
||||||
@ -58,11 +56,11 @@ protected:
|
|||||||
if (size <= MAX_SETTINGS_SIZE) {
|
if (size <= MAX_SETTINGS_SIZE) {
|
||||||
DynamicJsonDocument jsonDocument = DynamicJsonDocument(MAX_SETTINGS_SIZE);
|
DynamicJsonDocument jsonDocument = DynamicJsonDocument(MAX_SETTINGS_SIZE);
|
||||||
DeserializationError error = deserializeJson(jsonDocument, configFile);
|
DeserializationError error = deserializeJson(jsonDocument, configFile);
|
||||||
if (error == DeserializationError::Ok && jsonDocument.is<JsonObject>()){
|
if (error == DeserializationError::Ok && jsonDocument.is<JsonObject>()) {
|
||||||
JsonObject root = jsonDocument.as<JsonObject>();
|
JsonObject root = jsonDocument.as<JsonObject>();
|
||||||
readFromJsonObject(root);
|
readFromJsonObject(root);
|
||||||
configFile.close();
|
configFile.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
configFile.close();
|
configFile.close();
|
||||||
@ -73,26 +71,26 @@ protected:
|
|||||||
applyDefaultConfig();
|
applyDefaultConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// serialization routene, from local config to JsonObject
|
||||||
|
virtual void readFromJsonObject(JsonObject& root) {
|
||||||
|
}
|
||||||
|
virtual void writeToJsonObject(JsonObject& root) {
|
||||||
|
}
|
||||||
|
|
||||||
// serialization routene, from local config to JsonObject
|
// We assume the readFromJsonObject supplies sensible defaults if an empty object
|
||||||
virtual void readFromJsonObject(JsonObject& root){}
|
// is supplied, this virtual function allows that to be changed.
|
||||||
virtual void writeToJsonObject(JsonObject& root){}
|
virtual void applyDefaultConfig() {
|
||||||
|
DynamicJsonDocument jsonDocument = DynamicJsonDocument(MAX_SETTINGS_SIZE);
|
||||||
|
JsonObject root = jsonDocument.to<JsonObject>();
|
||||||
|
readFromJsonObject(root);
|
||||||
|
}
|
||||||
|
|
||||||
// We assume the readFromJsonObject supplies sensible defaults if an empty object
|
public:
|
||||||
// is supplied, this virtual function allows that to be changed.
|
SettingsPersistence(FS* fs, char const* filePath) : _fs(fs), _filePath(filePath) {
|
||||||
virtual void applyDefaultConfig(){
|
}
|
||||||
DynamicJsonDocument jsonDocument = DynamicJsonDocument(MAX_SETTINGS_SIZE);
|
|
||||||
JsonObject root = jsonDocument.to<JsonObject>();
|
|
||||||
readFromJsonObject(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
SettingsPersistence(FS* fs, char const* filePath):
|
|
||||||
_fs(fs), _filePath(filePath) {}
|
|
||||||
|
|
||||||
virtual ~SettingsPersistence() {}
|
|
||||||
|
|
||||||
|
virtual ~SettingsPersistence() {
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end SettingsPersistence
|
#endif // end SettingsPersistence
|
||||||
|
@ -5,65 +5,67 @@
|
|||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <ESPAsyncTCP.h>
|
#include <ESPAsyncTCP.h>
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
#include <WiFi.h>
|
|
||||||
#include <AsyncTCP.h>
|
#include <AsyncTCP.h>
|
||||||
|
#include <WiFi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <SecurityManager.h>
|
|
||||||
#include <SettingsPersistence.h>
|
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <AsyncJsonWebHandler.h>
|
|
||||||
#include <AsyncJson.h>
|
#include <AsyncJson.h>
|
||||||
#include <AsyncJsonCallbackResponse.h>
|
#include <AsyncJsonCallbackResponse.h>
|
||||||
|
#include <AsyncJsonWebHandler.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
#include <SecurityManager.h>
|
||||||
|
#include <SettingsPersistence.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Abstraction of a service which stores it's settings as JSON in a file system.
|
* Abstraction of a service which stores it's settings as JSON in a file system.
|
||||||
*/
|
*/
|
||||||
class SettingsService : public SettingsPersistence {
|
class SettingsService : public SettingsPersistence {
|
||||||
|
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));
|
||||||
|
_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);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
virtual ~SettingsService() {
|
||||||
|
}
|
||||||
|
|
||||||
SettingsService(AsyncWebServer* server, FS* fs, char const* servicePath, char const* filePath): SettingsPersistence(fs, filePath), _servicePath(servicePath) {
|
void begin() {
|
||||||
server->on(_servicePath, HTTP_GET, std::bind(&SettingsService::fetchConfig, this, std::placeholders::_1));
|
// read the initial data from the file system
|
||||||
|
readFromFS();
|
||||||
|
}
|
||||||
|
|
||||||
_updateHandler.setUri(servicePath);
|
protected:
|
||||||
_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() {}
|
|
||||||
|
|
||||||
void begin() {
|
|
||||||
// read the initial data from the file system
|
|
||||||
readFromFS();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
char const* _servicePath;
|
char const* _servicePath;
|
||||||
AsyncJsonWebHandler _updateHandler;
|
AsyncJsonWebHandler _updateHandler;
|
||||||
|
|
||||||
virtual void fetchConfig(AsyncWebServerRequest *request) {
|
virtual void fetchConfig(AsyncWebServerRequest* request) {
|
||||||
// handle the request
|
// handle the request
|
||||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_SETTINGS_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_SETTINGS_SIZE);
|
||||||
JsonObject jsonObject = response->getRoot();
|
JsonObject jsonObject = response->getRoot();
|
||||||
writeToJsonObject(jsonObject);
|
writeToJsonObject(jsonObject);
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void updateConfig(AsyncWebServerRequest *request, JsonDocument &jsonDocument) {
|
virtual void updateConfig(AsyncWebServerRequest* request, JsonDocument& jsonDocument) {
|
||||||
// handle the request
|
// handle the request
|
||||||
if (jsonDocument.is<JsonObject>()){
|
if (jsonDocument.is<JsonObject>()) {
|
||||||
JsonObject newConfig = jsonDocument.as<JsonObject>();
|
JsonObject newConfig = jsonDocument.as<JsonObject>();
|
||||||
readFromJsonObject(newConfig);
|
readFromJsonObject(newConfig);
|
||||||
writeToFS();
|
writeToFS();
|
||||||
|
|
||||||
// write settings back with a callback to reconfigure the wifi
|
// write settings back with a callback to reconfigure the wifi
|
||||||
AsyncJsonCallbackResponse * response = new AsyncJsonCallbackResponse([this] () {onConfigUpdated();}, false, MAX_SETTINGS_SIZE);
|
AsyncJsonCallbackResponse* response =
|
||||||
JsonObject jsonObject = response->getRoot();
|
new AsyncJsonCallbackResponse([this]() { onConfigUpdated(); }, false, MAX_SETTINGS_SIZE);
|
||||||
|
JsonObject jsonObject = response->getRoot();
|
||||||
writeToJsonObject(jsonObject);
|
writeToJsonObject(jsonObject);
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
@ -73,8 +75,8 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// implement to perform action when config has been updated
|
// implement to perform action when config has been updated
|
||||||
virtual void onConfigUpdated(){}
|
virtual void onConfigUpdated() {
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end SettingsService
|
#endif // end SettingsService
|
||||||
|
@ -2,54 +2,53 @@
|
|||||||
#define Service_h
|
#define Service_h
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <ESPAsyncTCP.h>
|
#include <ESPAsyncTCP.h>
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
#include <WiFi.h>
|
#include <AsyncTCP.h>
|
||||||
#include <AsyncTCP.h>
|
#include <WiFi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <AsyncJson.h>
|
#include <AsyncJson.h>
|
||||||
#include <AsyncJsonWebHandler.h>
|
|
||||||
#include <AsyncJsonCallbackResponse.h>
|
#include <AsyncJsonCallbackResponse.h>
|
||||||
|
#include <AsyncJsonWebHandler.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* At the moment, not expecting services to have to deal with large JSON
|
* At the moment, not expecting services to have to deal with large JSON
|
||||||
* files this could be made configurable fairly simply, it's exposed on
|
* files this could be made configurable fairly simply, it's exposed on
|
||||||
* AsyncJsonWebHandler with a setter.
|
* AsyncJsonWebHandler with a setter.
|
||||||
*/
|
*/
|
||||||
#define MAX_SETTINGS_SIZE 1024
|
#define MAX_SETTINGS_SIZE 1024
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Abstraction of a service which reads and writes data from an endpoint.
|
* Abstraction of a service which reads and writes data from an endpoint.
|
||||||
*
|
*
|
||||||
* Not currently used, but indended for use by features which do not
|
* Not currently used, but indended for use by features which do not
|
||||||
* require setting persistance.
|
* require setting persistance.
|
||||||
*/
|
*/
|
||||||
class SimpleService {
|
class SimpleService {
|
||||||
|
private:
|
||||||
private:
|
|
||||||
|
|
||||||
AsyncJsonWebHandler _updateHandler;
|
AsyncJsonWebHandler _updateHandler;
|
||||||
|
|
||||||
void fetchConfig(AsyncWebServerRequest *request) {
|
void fetchConfig(AsyncWebServerRequest* request) {
|
||||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_SETTINGS_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_SETTINGS_SIZE);
|
||||||
JsonObject jsonObject = response->getRoot();
|
JsonObject jsonObject = response->getRoot();
|
||||||
writeToJsonObject(jsonObject);
|
writeToJsonObject(jsonObject);
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateConfig(AsyncWebServerRequest *request, JsonDocument &jsonDocument) {
|
void updateConfig(AsyncWebServerRequest* request, JsonDocument& jsonDocument) {
|
||||||
if (jsonDocument.is<JsonObject>()) {
|
if (jsonDocument.is<JsonObject>()) {
|
||||||
JsonObject newConfig = jsonDocument.as<JsonObject>();
|
JsonObject newConfig = jsonDocument.as<JsonObject>();
|
||||||
readFromJsonObject(newConfig);
|
readFromJsonObject(newConfig);
|
||||||
|
|
||||||
// write settings back with a callback to reconfigure the wifi
|
// write settings back with a callback to reconfigure the wifi
|
||||||
AsyncJsonCallbackResponse * response = new AsyncJsonCallbackResponse([this] () {onConfigUpdated();}, false, MAX_SETTINGS_SIZE);
|
AsyncJsonCallbackResponse* response =
|
||||||
JsonObject jsonObject = response->getRoot();
|
new AsyncJsonCallbackResponse([this]() { onConfigUpdated(); }, false, MAX_SETTINGS_SIZE);
|
||||||
|
JsonObject jsonObject = response->getRoot();
|
||||||
writeToJsonObject(jsonObject);
|
writeToJsonObject(jsonObject);
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
@ -58,29 +57,31 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// reads the local config from the
|
||||||
|
virtual void readFromJsonObject(JsonObject& root) {
|
||||||
|
}
|
||||||
|
virtual void writeToJsonObject(JsonObject& root) {
|
||||||
|
}
|
||||||
|
|
||||||
// reads the local config from the
|
// implement to perform action when config has been updated
|
||||||
virtual void readFromJsonObject(JsonObject& root) {}
|
virtual void onConfigUpdated() {
|
||||||
virtual void writeToJsonObject(JsonObject& root) {}
|
}
|
||||||
|
|
||||||
// implement to perform action when config has been updated
|
public:
|
||||||
virtual void onConfigUpdated() {}
|
SimpleService(AsyncWebServer* server, char const* servicePath) {
|
||||||
|
server->on(servicePath, HTTP_GET, std::bind(&SimpleService::fetchConfig, this, std::placeholders::_1));
|
||||||
|
|
||||||
public:
|
_updateHandler.setUri(servicePath);
|
||||||
|
_updateHandler.setMethod(HTTP_POST);
|
||||||
SimpleService(AsyncWebServer* server, char const* servicePath) {
|
_updateHandler.setMaxContentLength(MAX_SETTINGS_SIZE);
|
||||||
server->on(servicePath, HTTP_GET, std::bind(&SimpleService::fetchConfig, this, std::placeholders::_1));
|
_updateHandler.onRequest(
|
||||||
|
std::bind(&SimpleService::updateConfig, this, std::placeholders::_1, std::placeholders::_2));
|
||||||
_updateHandler.setUri(servicePath);
|
server->addHandler(&_updateHandler);
|
||||||
_updateHandler.setMethod(HTTP_POST);
|
}
|
||||||
_updateHandler.setMaxContentLength(MAX_SETTINGS_SIZE);
|
|
||||||
_updateHandler.onRequest(std::bind(&SimpleService::updateConfig, this, std::placeholders::_1, std::placeholders::_2));
|
|
||||||
server->addHandler(&_updateHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~SimpleService() {}
|
|
||||||
|
|
||||||
|
virtual ~SimpleService() {
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end SimpleService
|
#endif // end SimpleService
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
#include <SystemStatus.h>
|
#include <SystemStatus.h>
|
||||||
|
|
||||||
SystemStatus::SystemStatus(AsyncWebServer* server, SecurityManager* securityManager) {
|
SystemStatus::SystemStatus(AsyncWebServer* server, SecurityManager* securityManager) {
|
||||||
server->on(SYSTEM_STATUS_SERVICE_PATH, HTTP_GET,
|
server->on(SYSTEM_STATUS_SERVICE_PATH,
|
||||||
securityManager->wrapRequest(std::bind(&SystemStatus::systemStatus, this, std::placeholders::_1), AuthenticationPredicates::IS_AUTHENTICATED)
|
HTTP_GET,
|
||||||
);
|
securityManager->wrapRequest(std::bind(&SystemStatus::systemStatus, this, std::placeholders::_1),
|
||||||
|
AuthenticationPredicates::IS_AUTHENTICATED));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStatus::systemStatus(AsyncWebServerRequest *request) {
|
void SystemStatus::systemStatus(AsyncWebServerRequest* request) {
|
||||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_ESP_STATUS_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_ESP_STATUS_SIZE);
|
||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
root["esp_platform"] = "esp8266";
|
root["esp_platform"] = "esp8266";
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
root["esp_platform"] = "esp32";
|
root["esp_platform"] = "esp32";
|
||||||
#endif
|
#endif
|
||||||
root["cpu_freq_mhz"] = ESP.getCpuFreqMHz();
|
root["cpu_freq_mhz"] = ESP.getCpuFreqMHz();
|
||||||
root["free_heap"] = ESP.getFreeHeap();
|
root["free_heap"] = ESP.getFreeHeap();
|
||||||
root["sketch_size"] = ESP.getSketchSize();
|
root["sketch_size"] = ESP.getSketchSize();
|
||||||
root["free_sketch_space"] = ESP.getFreeSketchSpace();
|
root["free_sketch_space"] = ESP.getFreeSketchSpace();
|
||||||
|
@ -2,31 +2,27 @@
|
|||||||
#define SystemStatus_h
|
#define SystemStatus_h
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <ESPAsyncTCP.h>
|
#include <ESPAsyncTCP.h>
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
#include <WiFi.h>
|
#include <AsyncTCP.h>
|
||||||
#include <AsyncTCP.h>
|
#include <WiFi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <AsyncJson.h>
|
#include <AsyncJson.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <SecurityManager.h>
|
#include <SecurityManager.h>
|
||||||
|
|
||||||
#define MAX_ESP_STATUS_SIZE 1024
|
#define MAX_ESP_STATUS_SIZE 1024
|
||||||
#define SYSTEM_STATUS_SERVICE_PATH "/rest/systemStatus"
|
#define SYSTEM_STATUS_SERVICE_PATH "/rest/systemStatus"
|
||||||
|
|
||||||
class SystemStatus {
|
class SystemStatus {
|
||||||
|
public:
|
||||||
|
SystemStatus(AsyncWebServer* server, SecurityManager* securityManager);
|
||||||
|
|
||||||
public:
|
private:
|
||||||
|
void systemStatus(AsyncWebServerRequest* request);
|
||||||
SystemStatus(AsyncWebServer* server, SecurityManager* securityManager);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void systemStatus(AsyncWebServerRequest *request);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end SystemStatus_h
|
#endif // end SystemStatus_h
|
@ -1,29 +1,31 @@
|
|||||||
#include <WiFiScanner.h>
|
#include <WiFiScanner.h>
|
||||||
|
|
||||||
WiFiScanner::WiFiScanner(AsyncWebServer *server, SecurityManager* securityManager) {
|
WiFiScanner::WiFiScanner(AsyncWebServer* server, SecurityManager* securityManager) {
|
||||||
server->on(SCAN_NETWORKS_SERVICE_PATH, HTTP_GET,
|
server->on(SCAN_NETWORKS_SERVICE_PATH,
|
||||||
securityManager->wrapRequest(std::bind(&WiFiScanner::scanNetworks, this, std::placeholders::_1), AuthenticationPredicates::IS_ADMIN)
|
HTTP_GET,
|
||||||
);
|
securityManager->wrapRequest(std::bind(&WiFiScanner::scanNetworks, this, std::placeholders::_1),
|
||||||
server->on(LIST_NETWORKS_SERVICE_PATH, HTTP_GET,
|
AuthenticationPredicates::IS_ADMIN));
|
||||||
securityManager->wrapRequest(std::bind(&WiFiScanner::listNetworks, this, std::placeholders::_1), AuthenticationPredicates::IS_ADMIN)
|
server->on(LIST_NETWORKS_SERVICE_PATH,
|
||||||
);
|
HTTP_GET,
|
||||||
|
securityManager->wrapRequest(std::bind(&WiFiScanner::listNetworks, this, std::placeholders::_1),
|
||||||
|
AuthenticationPredicates::IS_ADMIN));
|
||||||
};
|
};
|
||||||
|
|
||||||
void WiFiScanner::scanNetworks(AsyncWebServerRequest *request) {
|
void WiFiScanner::scanNetworks(AsyncWebServerRequest* request) {
|
||||||
if (WiFi.scanComplete() != -1){
|
if (WiFi.scanComplete() != -1) {
|
||||||
WiFi.scanDelete();
|
WiFi.scanDelete();
|
||||||
WiFi.scanNetworks(true);
|
WiFi.scanNetworks(true);
|
||||||
}
|
}
|
||||||
request->send(202);
|
request->send(202);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiFiScanner::listNetworks(AsyncWebServerRequest *request) {
|
void WiFiScanner::listNetworks(AsyncWebServerRequest* request) {
|
||||||
int numNetworks = WiFi.scanComplete();
|
int numNetworks = WiFi.scanComplete();
|
||||||
if (numNetworks > -1){
|
if (numNetworks > -1) {
|
||||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_WIFI_SCANNER_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_WIFI_SCANNER_SIZE);
|
||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
JsonArray networks = root.createNestedArray("networks");
|
JsonArray networks = root.createNestedArray("networks");
|
||||||
for (int i=0; i<numNetworks ; i++){
|
for (int i = 0; i < numNetworks; i++) {
|
||||||
JsonObject network = networks.createNestedObject();
|
JsonObject network = networks.createNestedObject();
|
||||||
network["rssi"] = WiFi.RSSI(i);
|
network["rssi"] = WiFi.RSSI(i);
|
||||||
network["ssid"] = WiFi.SSID(i);
|
network["ssid"] = WiFi.SSID(i);
|
||||||
@ -32,14 +34,14 @@ void WiFiScanner::listNetworks(AsyncWebServerRequest *request) {
|
|||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
network["encryption_type"] = convertEncryptionType(WiFi.encryptionType(i));
|
network["encryption_type"] = convertEncryptionType(WiFi.encryptionType(i));
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
network["encryption_type"] = (uint8_t) WiFi.encryptionType(i);
|
network["encryption_type"] = (uint8_t)WiFi.encryptionType(i);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
} else if (numNetworks == -1){
|
} else if (numNetworks == -1) {
|
||||||
request->send(202);
|
request->send(202);
|
||||||
}else{
|
} else {
|
||||||
scanNetworks(request);
|
scanNetworks(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -47,11 +49,11 @@ void WiFiScanner::listNetworks(AsyncWebServerRequest *request) {
|
|||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
/*
|
/*
|
||||||
* Convert encryption type to standard used by ESP32 rather than the translated form which the esp8266 libaries expose.
|
* Convert encryption type to standard used by ESP32 rather than the translated form which the esp8266 libaries expose.
|
||||||
*
|
*
|
||||||
* This allows us to use a single set of mappings in the UI.
|
* This allows us to use a single set of mappings in the UI.
|
||||||
*/
|
*/
|
||||||
uint8_t WiFiScanner::convertEncryptionType(uint8_t encryptionType){
|
uint8_t WiFiScanner::convertEncryptionType(uint8_t encryptionType) {
|
||||||
switch (encryptionType){
|
switch (encryptionType) {
|
||||||
case ENC_TYPE_NONE:
|
case ENC_TYPE_NONE:
|
||||||
return AUTH_OPEN;
|
return AUTH_OPEN;
|
||||||
case ENC_TYPE_WEP:
|
case ENC_TYPE_WEP:
|
||||||
|
@ -2,18 +2,18 @@
|
|||||||
#define WiFiScanner_h
|
#define WiFiScanner_h
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <ESPAsyncTCP.h>
|
#include <ESPAsyncTCP.h>
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
#include <WiFi.h>
|
#include <AsyncTCP.h>
|
||||||
#include <AsyncTCP.h>
|
#include <WiFi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <AsyncJson.h>
|
#include <AsyncJson.h>
|
||||||
#include <TimeLib.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <SecurityManager.h>
|
#include <SecurityManager.h>
|
||||||
|
#include <TimeLib.h>
|
||||||
|
|
||||||
#define SCAN_NETWORKS_SERVICE_PATH "/rest/scanNetworks"
|
#define SCAN_NETWORKS_SERVICE_PATH "/rest/scanNetworks"
|
||||||
#define LIST_NETWORKS_SERVICE_PATH "/rest/listNetworks"
|
#define LIST_NETWORKS_SERVICE_PATH "/rest/listNetworks"
|
||||||
@ -21,20 +21,16 @@
|
|||||||
#define MAX_WIFI_SCANNER_SIZE 1024
|
#define MAX_WIFI_SCANNER_SIZE 1024
|
||||||
|
|
||||||
class WiFiScanner {
|
class WiFiScanner {
|
||||||
|
public:
|
||||||
|
WiFiScanner(AsyncWebServer* server, SecurityManager* securityManager);
|
||||||
|
|
||||||
public:
|
private:
|
||||||
|
void scanNetworks(AsyncWebServerRequest* request);
|
||||||
WiFiScanner(AsyncWebServer *server, SecurityManager* securityManager);
|
void listNetworks(AsyncWebServerRequest* request);
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void scanNetworks(AsyncWebServerRequest *request);
|
|
||||||
void listNetworks(AsyncWebServerRequest *request);
|
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
uint8_t convertEncryptionType(uint8_t encryptionType);
|
uint8_t convertEncryptionType(uint8_t encryptionType);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end WiFiScanner_h
|
#endif // end WiFiScanner_h
|
||||||
|
@ -1,73 +1,78 @@
|
|||||||
#include <WiFiSettingsService.h>
|
#include <WiFiSettingsService.h>
|
||||||
|
|
||||||
WiFiSettingsService::WiFiSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager) : AdminSettingsService(server, fs, securityManager, WIFI_SETTINGS_SERVICE_PATH, WIFI_SETTINGS_FILE) {
|
WiFiSettingsService::WiFiSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager) :
|
||||||
|
AdminSettingsService(server, fs, securityManager, WIFI_SETTINGS_SERVICE_PATH, WIFI_SETTINGS_FILE) {
|
||||||
// We want the device to come up in opmode=0 (WIFI_OFF), when erasing the flash this is not the default.
|
// We want the device to come up in opmode=0 (WIFI_OFF), when erasing the flash this is not the default.
|
||||||
// If needed, we save opmode=0 before disabling persistence so the device boots with WiFi disabled in the future.
|
// If needed, we save opmode=0 before disabling persistence so the device boots with WiFi disabled in the future.
|
||||||
if (WiFi.getMode() != WIFI_OFF) {
|
if (WiFi.getMode() != WIFI_OFF) {
|
||||||
WiFi.mode(WIFI_OFF);
|
WiFi.mode(WIFI_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable WiFi config persistance and auto reconnect
|
// Disable WiFi config persistance and auto reconnect
|
||||||
WiFi.persistent(false);
|
WiFi.persistent(false);
|
||||||
WiFi.setAutoReconnect(false);
|
WiFi.setAutoReconnect(false);
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
_onStationModeDisconnectedHandler = WiFi.onStationModeDisconnected(std::bind(&WiFiSettingsService::onStationModeDisconnected, this, std::placeholders::_1));
|
_onStationModeDisconnectedHandler = WiFi.onStationModeDisconnected(
|
||||||
|
std::bind(&WiFiSettingsService::onStationModeDisconnected, this, std::placeholders::_1));
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
// Init the wifi driver on ESP32
|
// Init the wifi driver on ESP32
|
||||||
WiFi.mode(WIFI_MODE_MAX);
|
WiFi.mode(WIFI_MODE_MAX);
|
||||||
WiFi.mode(WIFI_MODE_NULL);
|
WiFi.mode(WIFI_MODE_NULL);
|
||||||
WiFi.onEvent(std::bind(&WiFiSettingsService::onStationModeDisconnected, this, std::placeholders::_1, std::placeholders::_2), WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED);
|
WiFi.onEvent(
|
||||||
|
std::bind(&WiFiSettingsService::onStationModeDisconnected, this, std::placeholders::_1, std::placeholders::_2),
|
||||||
|
WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
WiFiSettingsService::~WiFiSettingsService() {}
|
WiFiSettingsService::~WiFiSettingsService() {
|
||||||
|
}
|
||||||
|
|
||||||
void WiFiSettingsService::begin() {
|
void WiFiSettingsService::begin() {
|
||||||
SettingsService::begin();
|
SettingsService::begin();
|
||||||
reconfigureWiFiConnection();
|
reconfigureWiFiConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiFiSettingsService::readFromJsonObject(JsonObject& root){
|
void WiFiSettingsService::readFromJsonObject(JsonObject& root) {
|
||||||
_ssid = root["ssid"] | "";
|
_ssid = root["ssid"] | "";
|
||||||
_password = root["password"] | "";
|
_password = root["password"] | "";
|
||||||
_hostname = root["hostname"] | "";
|
_hostname = root["hostname"] | "";
|
||||||
_staticIPConfig = root["static_ip_config"] | false;
|
_staticIPConfig = root["static_ip_config"] | false;
|
||||||
|
|
||||||
// extended settings
|
// extended settings
|
||||||
readIP(root, "local_ip", _localIP);
|
readIP(root, "local_ip", _localIP);
|
||||||
readIP(root, "gateway_ip", _gatewayIP);
|
readIP(root, "gateway_ip", _gatewayIP);
|
||||||
readIP(root, "subnet_mask", _subnetMask);
|
readIP(root, "subnet_mask", _subnetMask);
|
||||||
readIP(root, "dns_ip_1", _dnsIP1);
|
readIP(root, "dns_ip_1", _dnsIP1);
|
||||||
readIP(root, "dns_ip_2", _dnsIP2);
|
readIP(root, "dns_ip_2", _dnsIP2);
|
||||||
|
|
||||||
// Swap around the dns servers if 2 is populated but 1 is not
|
// Swap around the dns servers if 2 is populated but 1 is not
|
||||||
if (_dnsIP1 == INADDR_NONE && _dnsIP2 != INADDR_NONE){
|
if (_dnsIP1 == INADDR_NONE && _dnsIP2 != INADDR_NONE) {
|
||||||
_dnsIP1 = _dnsIP2;
|
_dnsIP1 = _dnsIP2;
|
||||||
_dnsIP2 = INADDR_NONE;
|
_dnsIP2 = INADDR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turning off static ip config if we don't meet the minimum requirements
|
// Turning off static ip config if we don't meet the minimum requirements
|
||||||
// of ipAddress, gateway and subnet. This may change to static ip only
|
// of ipAddress, gateway and subnet. This may change to static ip only
|
||||||
// as sensible defaults can be assumed for gateway and subnet
|
// as sensible defaults can be assumed for gateway and subnet
|
||||||
if (_staticIPConfig && (_localIP == INADDR_NONE || _gatewayIP == INADDR_NONE || _subnetMask == INADDR_NONE)){
|
if (_staticIPConfig && (_localIP == INADDR_NONE || _gatewayIP == INADDR_NONE || _subnetMask == INADDR_NONE)) {
|
||||||
_staticIPConfig = false;
|
_staticIPConfig = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiFiSettingsService::writeToJsonObject(JsonObject& root){
|
void WiFiSettingsService::writeToJsonObject(JsonObject& root) {
|
||||||
// connection settings
|
// connection settings
|
||||||
root["ssid"] = _ssid;
|
root["ssid"] = _ssid;
|
||||||
root["password"] = _password;
|
root["password"] = _password;
|
||||||
root["hostname"] = _hostname;
|
root["hostname"] = _hostname;
|
||||||
root["static_ip_config"] = _staticIPConfig;
|
root["static_ip_config"] = _staticIPConfig;
|
||||||
|
|
||||||
// extended settings
|
// extended settings
|
||||||
writeIP(root, "local_ip", _localIP);
|
writeIP(root, "local_ip", _localIP);
|
||||||
writeIP(root, "gateway_ip", _gatewayIP);
|
writeIP(root, "gateway_ip", _gatewayIP);
|
||||||
writeIP(root, "subnet_mask", _subnetMask);
|
writeIP(root, "subnet_mask", _subnetMask);
|
||||||
writeIP(root, "dns_ip_1", _dnsIP1);
|
writeIP(root, "dns_ip_1", _dnsIP1);
|
||||||
writeIP(root, "dns_ip_2", _dnsIP2);
|
writeIP(root, "dns_ip_2", _dnsIP2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiFiSettingsService::onConfigUpdated() {
|
void WiFiSettingsService::onConfigUpdated() {
|
||||||
@ -75,21 +80,21 @@ void WiFiSettingsService::onConfigUpdated() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WiFiSettingsService::reconfigureWiFiConnection() {
|
void WiFiSettingsService::reconfigureWiFiConnection() {
|
||||||
// disconnect and de-configure wifi
|
// disconnect and de-configure wifi
|
||||||
WiFi.disconnect(true);
|
WiFi.disconnect(true);
|
||||||
|
|
||||||
// reset last connection attempt to force loop to reconnect immediately
|
// reset last connection attempt to force loop to reconnect immediately
|
||||||
_lastConnectionAttempt = 0;
|
_lastConnectionAttempt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiFiSettingsService::readIP(JsonObject& root, String key, IPAddress& _ip){
|
void WiFiSettingsService::readIP(JsonObject& root, String key, IPAddress& _ip) {
|
||||||
if (!root[key].is<String>() || !_ip.fromString(root[key].as<String>())){
|
if (!root[key].is<String>() || !_ip.fromString(root[key].as<String>())) {
|
||||||
_ip = INADDR_NONE;
|
_ip = INADDR_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiFiSettingsService::writeIP(JsonObject& root, String key, IPAddress& _ip){
|
void WiFiSettingsService::writeIP(JsonObject& root, String key, IPAddress& _ip) {
|
||||||
if (_ip != INADDR_NONE){
|
if (_ip != INADDR_NONE) {
|
||||||
root[key] = _ip.toString();
|
root[key] = _ip.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -98,7 +103,7 @@ void WiFiSettingsService::loop() {
|
|||||||
unsigned long currentMillis = millis();
|
unsigned long currentMillis = millis();
|
||||||
if (!_lastConnectionAttempt || (unsigned long)(currentMillis - _lastConnectionAttempt) >= WIFI_RECONNECTION_DELAY) {
|
if (!_lastConnectionAttempt || (unsigned long)(currentMillis - _lastConnectionAttempt) >= WIFI_RECONNECTION_DELAY) {
|
||||||
_lastConnectionAttempt = currentMillis;
|
_lastConnectionAttempt = currentMillis;
|
||||||
manageSTA();
|
manageSTA();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,13 +114,13 @@ void WiFiSettingsService::manageSTA() {
|
|||||||
}
|
}
|
||||||
// Connect or reconnect as required
|
// Connect or reconnect as required
|
||||||
if ((WiFi.getMode() & WIFI_STA) == 0) {
|
if ((WiFi.getMode() & WIFI_STA) == 0) {
|
||||||
Serial.println("Connecting to WiFi.");
|
Serial.println("Connecting to WiFi.");
|
||||||
if (_staticIPConfig) {
|
if (_staticIPConfig) {
|
||||||
// configure for static IP
|
// configure for static IP
|
||||||
WiFi.config(_localIP, _gatewayIP, _subnetMask, _dnsIP1, _dnsIP2);
|
WiFi.config(_localIP, _gatewayIP, _subnetMask, _dnsIP1, _dnsIP2);
|
||||||
} else {
|
} else {
|
||||||
// configure for DHCP
|
// configure for DHCP
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
WiFi.config(INADDR_ANY, INADDR_ANY, INADDR_ANY);
|
WiFi.config(INADDR_ANY, INADDR_ANY, INADDR_ANY);
|
||||||
WiFi.hostname(_hostname);
|
WiFi.hostname(_hostname);
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
@ -137,4 +142,3 @@ void WiFiSettingsService::onStationModeDisconnected(WiFiEvent_t event, WiFiEvent
|
|||||||
WiFi.disconnect(true);
|
WiFi.disconnect(true);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -9,50 +9,46 @@
|
|||||||
#define WIFI_RECONNECTION_DELAY 1000 * 60
|
#define WIFI_RECONNECTION_DELAY 1000 * 60
|
||||||
|
|
||||||
class WiFiSettingsService : public AdminSettingsService {
|
class WiFiSettingsService : public AdminSettingsService {
|
||||||
|
public:
|
||||||
|
WiFiSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager);
|
||||||
|
~WiFiSettingsService();
|
||||||
|
|
||||||
public:
|
void begin();
|
||||||
|
void loop();
|
||||||
|
|
||||||
WiFiSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager);
|
protected:
|
||||||
~WiFiSettingsService();
|
void readFromJsonObject(JsonObject& root);
|
||||||
|
void writeToJsonObject(JsonObject& root);
|
||||||
|
void onConfigUpdated();
|
||||||
|
|
||||||
void begin();
|
private:
|
||||||
void loop();
|
// connection settings
|
||||||
|
String _ssid;
|
||||||
|
String _password;
|
||||||
|
String _hostname;
|
||||||
|
bool _staticIPConfig;
|
||||||
|
|
||||||
protected:
|
// for the mangement delay loop
|
||||||
|
unsigned long _lastConnectionAttempt;
|
||||||
|
|
||||||
void readFromJsonObject(JsonObject& root);
|
// optional configuration for static IP address
|
||||||
void writeToJsonObject(JsonObject& root);
|
IPAddress _localIP;
|
||||||
void onConfigUpdated();
|
IPAddress _gatewayIP;
|
||||||
|
IPAddress _subnetMask;
|
||||||
private:
|
IPAddress _dnsIP1;
|
||||||
// connection settings
|
IPAddress _dnsIP2;
|
||||||
String _ssid;
|
|
||||||
String _password;
|
|
||||||
String _hostname;
|
|
||||||
bool _staticIPConfig;
|
|
||||||
|
|
||||||
// for the mangement delay loop
|
|
||||||
unsigned long _lastConnectionAttempt;
|
|
||||||
|
|
||||||
// optional configuration for static IP address
|
|
||||||
IPAddress _localIP;
|
|
||||||
IPAddress _gatewayIP;
|
|
||||||
IPAddress _subnetMask;
|
|
||||||
IPAddress _dnsIP1;
|
|
||||||
IPAddress _dnsIP2;
|
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
WiFiEventHandler _onStationModeDisconnectedHandler;
|
WiFiEventHandler _onStationModeDisconnectedHandler;
|
||||||
void onStationModeDisconnected(const WiFiEventStationModeDisconnected& event);
|
void onStationModeDisconnected(const WiFiEventStationModeDisconnected& event);
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
void onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info);
|
void onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void readIP(JsonObject& root, String key, IPAddress& _ip);
|
|
||||||
void writeIP(JsonObject& root, String key, IPAddress& _ip);
|
|
||||||
void reconfigureWiFiConnection();
|
|
||||||
void manageSTA();
|
|
||||||
|
|
||||||
|
void readIP(JsonObject& root, String key, IPAddress& _ip);
|
||||||
|
void writeIP(JsonObject& root, String key, IPAddress& _ip);
|
||||||
|
void reconfigureWiFiConnection();
|
||||||
|
void manageSTA();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end WiFiSettingsService_h
|
#endif // end WiFiSettingsService_h
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
#include <WiFiStatus.h>
|
#include <WiFiStatus.h>
|
||||||
|
|
||||||
WiFiStatus::WiFiStatus(AsyncWebServer* server, SecurityManager* securityManager) {
|
WiFiStatus::WiFiStatus(AsyncWebServer* server, SecurityManager* securityManager) {
|
||||||
server->on(WIFI_STATUS_SERVICE_PATH, HTTP_GET,
|
server->on(WIFI_STATUS_SERVICE_PATH,
|
||||||
securityManager->wrapRequest(std::bind(&WiFiStatus::wifiStatus, this, std::placeholders::_1), AuthenticationPredicates::IS_AUTHENTICATED)
|
HTTP_GET,
|
||||||
);
|
securityManager->wrapRequest(std::bind(&WiFiStatus::wifiStatus, this, std::placeholders::_1),
|
||||||
|
AuthenticationPredicates::IS_AUTHENTICATED));
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
_onStationModeConnectedHandler = WiFi.onStationModeConnected(onStationModeConnected);
|
_onStationModeConnectedHandler = WiFi.onStationModeConnected(onStationModeConnected);
|
||||||
_onStationModeDisconnectedHandler = WiFi.onStationModeDisconnected(onStationModeDisconnected);
|
_onStationModeDisconnectedHandler = WiFi.onStationModeDisconnected(onStationModeDisconnected);
|
||||||
_onStationModeGotIPHandler = WiFi.onStationModeGotIP(onStationModeGotIP);
|
_onStationModeGotIPHandler = WiFi.onStationModeGotIP(onStationModeGotIP);
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
WiFi.onEvent(onStationModeConnected, WiFiEvent_t::SYSTEM_EVENT_STA_CONNECTED);
|
WiFi.onEvent(onStationModeConnected, WiFiEvent_t::SYSTEM_EVENT_STA_CONNECTED);
|
||||||
WiFi.onEvent(onStationModeDisconnected, WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED);
|
WiFi.onEvent(onStationModeDisconnected, WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED);
|
||||||
WiFi.onEvent(onStationModeGotIP, WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP);
|
WiFi.onEvent(onStationModeGotIP, WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,12 +51,12 @@ void WiFiStatus::onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void WiFiStatus::wifiStatus(AsyncWebServerRequest *request) {
|
void WiFiStatus::wifiStatus(AsyncWebServerRequest* request) {
|
||||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_WIFI_STATUS_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_WIFI_STATUS_SIZE);
|
||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
wl_status_t status = WiFi.status();
|
wl_status_t status = WiFi.status();
|
||||||
root["status"] = (uint8_t) status;
|
root["status"] = (uint8_t)status;
|
||||||
if (status == WL_CONNECTED){
|
if (status == WL_CONNECTED) {
|
||||||
root["local_ip"] = WiFi.localIP().toString();
|
root["local_ip"] = WiFi.localIP().toString();
|
||||||
root["mac_address"] = WiFi.macAddress();
|
root["mac_address"] = WiFi.macAddress();
|
||||||
root["rssi"] = WiFi.RSSI();
|
root["rssi"] = WiFi.RSSI();
|
||||||
@ -66,10 +67,10 @@ void WiFiStatus::wifiStatus(AsyncWebServerRequest *request) {
|
|||||||
root["gateway_ip"] = WiFi.gatewayIP().toString();
|
root["gateway_ip"] = WiFi.gatewayIP().toString();
|
||||||
IPAddress dnsIP1 = WiFi.dnsIP(0);
|
IPAddress dnsIP1 = WiFi.dnsIP(0);
|
||||||
IPAddress dnsIP2 = WiFi.dnsIP(1);
|
IPAddress dnsIP2 = WiFi.dnsIP(1);
|
||||||
if (dnsIP1 != INADDR_NONE){
|
if (dnsIP1 != INADDR_NONE) {
|
||||||
root["dns_ip_1"] = dnsIP1.toString();
|
root["dns_ip_1"] = dnsIP1.toString();
|
||||||
}
|
}
|
||||||
if (dnsIP2 != INADDR_NONE){
|
if (dnsIP2 != INADDR_NONE) {
|
||||||
root["dns_ip_2"] = dnsIP2.toString();
|
root["dns_ip_2"] = dnsIP2.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,16 +2,16 @@
|
|||||||
#define WiFiStatus_h
|
#define WiFiStatus_h
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <ESPAsyncTCP.h>
|
#include <ESPAsyncTCP.h>
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
#include <WiFi.h>
|
#include <AsyncTCP.h>
|
||||||
#include <AsyncTCP.h>
|
#include <WiFi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <AsyncJson.h>
|
#include <AsyncJson.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <IPAddress.h>
|
#include <IPAddress.h>
|
||||||
#include <SecurityManager.h>
|
#include <SecurityManager.h>
|
||||||
|
|
||||||
@ -19,31 +19,27 @@
|
|||||||
#define WIFI_STATUS_SERVICE_PATH "/rest/wifiStatus"
|
#define WIFI_STATUS_SERVICE_PATH "/rest/wifiStatus"
|
||||||
|
|
||||||
class WiFiStatus {
|
class WiFiStatus {
|
||||||
|
public:
|
||||||
|
WiFiStatus(AsyncWebServer* server, SecurityManager* securityManager);
|
||||||
|
|
||||||
public:
|
private:
|
||||||
|
|
||||||
WiFiStatus(AsyncWebServer* server, SecurityManager* securityManager);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
// handler refrences for logging important WiFi events over serial
|
// handler refrences for logging important WiFi events over serial
|
||||||
WiFiEventHandler _onStationModeConnectedHandler;
|
WiFiEventHandler _onStationModeConnectedHandler;
|
||||||
WiFiEventHandler _onStationModeDisconnectedHandler;
|
WiFiEventHandler _onStationModeDisconnectedHandler;
|
||||||
WiFiEventHandler _onStationModeGotIPHandler;
|
WiFiEventHandler _onStationModeGotIPHandler;
|
||||||
// static functions for logging WiFi events to the UART
|
// static functions for logging WiFi events to the UART
|
||||||
static void onStationModeConnected(const WiFiEventStationModeConnected& event);
|
static void onStationModeConnected(const WiFiEventStationModeConnected& event);
|
||||||
static void onStationModeDisconnected(const WiFiEventStationModeDisconnected& event);
|
static void onStationModeDisconnected(const WiFiEventStationModeDisconnected& event);
|
||||||
static void onStationModeGotIP(const WiFiEventStationModeGotIP& event);
|
static void onStationModeGotIP(const WiFiEventStationModeGotIP& event);
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
// static functions for logging WiFi events to the UART
|
// static functions for logging WiFi events to the UART
|
||||||
static void onStationModeConnected(WiFiEvent_t event, WiFiEventInfo_t info);
|
static void onStationModeConnected(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||||
static void onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info);
|
static void onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||||
static void onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info);
|
static void onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void wifiStatus(AsyncWebServerRequest *request);
|
void wifiStatus(AsyncWebServerRequest* request);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // end WiFiStatus_h
|
#endif // end WiFiStatus_h
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
#include <DemoProject.h>
|
#include <DemoProject.h>
|
||||||
|
|
||||||
DemoProject::DemoProject(AsyncWebServer* server, FS* fs, SecurityManager* securityManager) : AdminSettingsService(server, fs, securityManager, DEMO_SETTINGS_PATH, DEMO_SETTINGS_FILE) {
|
DemoProject::DemoProject(AsyncWebServer* server, FS* fs, SecurityManager* securityManager) :
|
||||||
pinMode(BLINK_LED, OUTPUT);
|
AdminSettingsService(server, fs, securityManager, DEMO_SETTINGS_PATH, DEMO_SETTINGS_FILE) {
|
||||||
|
pinMode(BLINK_LED, OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
DemoProject::~DemoProject() {}
|
DemoProject::~DemoProject() {
|
||||||
|
}
|
||||||
|
|
||||||
void DemoProject::loop() {
|
void DemoProject::loop() {
|
||||||
unsigned delay = MAX_DELAY / 255 * (255 - _blinkSpeed);
|
unsigned delay = MAX_DELAY / 255 * (255 - _blinkSpeed);
|
||||||
@ -23,4 +25,3 @@ void DemoProject::writeToJsonObject(JsonObject& root) {
|
|||||||
// connection settings
|
// connection settings
|
||||||
root["blink_speed"] = _blinkSpeed;
|
root["blink_speed"] = _blinkSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,24 +11,19 @@
|
|||||||
#define DEMO_SETTINGS_PATH "/rest/demoSettings"
|
#define DEMO_SETTINGS_PATH "/rest/demoSettings"
|
||||||
|
|
||||||
class DemoProject : public AdminSettingsService {
|
class DemoProject : public AdminSettingsService {
|
||||||
|
public:
|
||||||
|
DemoProject(AsyncWebServer* server, FS* fs, SecurityManager* securityManager);
|
||||||
|
~DemoProject();
|
||||||
|
|
||||||
public:
|
void loop();
|
||||||
|
|
||||||
DemoProject(AsyncWebServer* server, FS* fs, SecurityManager* securityManager);
|
private:
|
||||||
~DemoProject();
|
unsigned long _lastBlink = 0;
|
||||||
|
uint8_t _blinkSpeed = 255;
|
||||||
void loop();
|
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
|
void readFromJsonObject(JsonObject& root);
|
||||||
unsigned long _lastBlink = 0;
|
void writeToJsonObject(JsonObject& root);
|
||||||
uint8_t _blinkSpeed = 255;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
void readFromJsonObject(JsonObject& root);
|
|
||||||
void writeToJsonObject(JsonObject& root);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include <ESP8266React.h>
|
|
||||||
#include <DemoProject.h>
|
#include <DemoProject.h>
|
||||||
|
#include <ESP8266React.h>
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
|
|
||||||
#define SERIAL_BAUD_RATE 115200
|
#define SERIAL_BAUD_RATE 115200
|
||||||
|
Loading…
Reference in New Issue
Block a user