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:
		
							
								
								
									
										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,9 +15,9 @@ 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: | ||||||
|  |   AdminSettingsService(AsyncWebServer* server, | ||||||
|  |                        FS* fs, | ||||||
|  |                        SecurityManager* securityManager, | ||||||
|  |                        char const* servicePath, | ||||||
|  |                        char const* filePath) : | ||||||
|  |       SettingsService(server, fs, servicePath, filePath), | ||||||
|  |       _securityManager(securityManager) { | ||||||
|  |   } | ||||||
|  |  | ||||||
|   public:   |  protected: | ||||||
|     AdminSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager, char const* servicePath, char const* filePath): |   // will validate the requests with the security manager | ||||||
|       SettingsService(server, fs, servicePath, filePath), _securityManager(securityManager) {} |   SecurityManager* _securityManager; | ||||||
|  |  | ||||||
|   protected: |   void fetchConfig(AsyncWebServerRequest* request) { | ||||||
|     // will validate the requests with the security manager |     // verify the request against the predicate | ||||||
|     SecurityManager* _securityManager; |     Authentication authentication = _securityManager->authenticateRequest(request); | ||||||
|  |     if (!getAuthenticationPredicate()(authentication)) { | ||||||
|     void fetchConfig(AsyncWebServerRequest *request) { |       request->send(401); | ||||||
|       // verify the request against the predicate |       return; | ||||||
|       Authentication authentication = _securityManager->authenticateRequest(request); |  | ||||||
|       if (!getAuthenticationPredicate()(authentication)) { |  | ||||||
|         request->send(401); |  | ||||||
|         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,12 +1,13 @@ | |||||||
| #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; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -17,31 +18,31 @@ String ArduinoJsonJWT::getSecret(){ | |||||||
|  * |  * | ||||||
|  * 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); | ||||||
| @@ -51,12 +52,12 @@ String ArduinoJsonJWT::buildJWT(JsonObject &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,7 +75,7 @@ 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; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -84,12 +85,12 @@ void ArduinoJsonJWT::parseJWT(String jwt, JsonDocument &jsonDocument) { | |||||||
|  |  | ||||||
|   // 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) | ||||||
| @@ -100,7 +101,7 @@ String ArduinoJsonJWT::encode(const char *cstr, int inputLen) { | |||||||
|   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]; | ||||||
|   | |||||||
| @@ -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() { | ||||||
|   | |||||||
| @@ -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(); |  private: | ||||||
|     void loop(); |   SecuritySettingsService _securitySettingsService; | ||||||
|  |  | ||||||
|     SecurityManager* getSecurityManager(){ |   WiFiSettingsService _wifiSettingsService; | ||||||
|         return &_securitySettingsService; |   APSettingsService _apSettingsService; | ||||||
|     } |   NTPSettingsService _ntpSettingsService; | ||||||
|  |   OTASettingsService _otaSettingsService; | ||||||
|   private: |   RestartService _restartService; | ||||||
|  |   AuthenticationService _authenticationService; | ||||||
|     SecuritySettingsService _securitySettingsService; |  | ||||||
|  |  | ||||||
|     WiFiSettingsService _wifiSettingsService; |  | ||||||
|     APSettingsService _apSettingsService; |  | ||||||
|     NTPSettingsService _ntpSettingsService; |  | ||||||
|     OTASettingsService _otaSettingsService; |  | ||||||
|     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(); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -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,10 +1,10 @@ | |||||||
| #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); | ||||||
|     } |     } | ||||||
| @@ -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,7 +38,7 @@ 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) { | ||||||
| @@ -55,8 +55,9 @@ String SecurityManager::generateJWT(User *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); | ||||||
| @@ -65,4 +66,3 @@ 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); | ||||||
|  |  | ||||||
|     /* |  protected: | ||||||
|     * Generate a JWT for the user provided |   ArduinoJsonJWT _jwtHandler = ArduinoJsonJWT(DEFAULT_JWT_SECRET); | ||||||
|     */ |   std::list<User> _users; | ||||||
|     String generateJWT(User *user); |  | ||||||
|  |  | ||||||
|     /** |  private: | ||||||
|      * Wrap the provided request to provide validation against an AuthenticationPredicate. |   /* | ||||||
|      */ |    * Lookup the user by JWT | ||||||
|     ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate);  |    */ | ||||||
|  |   Authentication authenticateJWT(String jwt); | ||||||
|   protected: |  | ||||||
|  |  | ||||||
|     ArduinoJsonJWT _jwtHandler = ArduinoJsonJWT(DEFAULT_JWT_SECRET); |  | ||||||
|     std::list<User> _users; |  | ||||||
|  |  | ||||||
|   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,7 +1,11 @@ | |||||||
| #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 | ||||||
| @@ -10,7 +14,7 @@ void SecuritySettingsService::readFromJsonObject(JsonObject& root) { | |||||||
|   // 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,7 +56,7 @@ 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(); | ||||||
| @@ -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,64 +5,66 @@ | |||||||
| #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 = | ||||||
|  |           new AsyncJsonCallbackResponse([this]() { onConfigUpdated(); }, false, MAX_SETTINGS_SIZE); | ||||||
|       JsonObject jsonObject = response->getRoot(); |       JsonObject jsonObject = response->getRoot(); | ||||||
|       writeToJsonObject(jsonObject); |       writeToJsonObject(jsonObject); | ||||||
|       response->setLength(); |       response->setLength(); | ||||||
| @@ -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,53 +2,52 @@ | |||||||
| #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 = | ||||||
|  |           new AsyncJsonCallbackResponse([this]() { onConfigUpdated(); }, false, MAX_SETTINGS_SIZE); | ||||||
|       JsonObject jsonObject = response->getRoot(); |       JsonObject jsonObject = response->getRoot(); | ||||||
|       writeToJsonObject(jsonObject); |       writeToJsonObject(jsonObject); | ||||||
|       response->setLength(); |       response->setLength(); | ||||||
| @@ -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,13 +1,14 @@ | |||||||
| #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"; | ||||||
|   | |||||||
| @@ -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); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -50,8 +52,8 @@ void WiFiScanner::listNetworks(AsyncWebServerRequest *request) { | |||||||
|  * |  * | ||||||
|  * 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,6 +1,7 @@ | |||||||
| #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) { | ||||||
| @@ -12,62 +13,66 @@ WiFiSettingsService::WiFiSettingsService(AsyncWebServer* server, FS* fs, Securit | |||||||
|   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(); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -112,7 +117,7 @@ void WiFiSettingsService::manageSTA() { | |||||||
|     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) | ||||||
| @@ -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 readIP(JsonObject& root, String key, IPAddress& _ip); | ||||||
|     void writeIP(JsonObject& root, String key, IPAddress& _ip); |   void writeIP(JsonObject& root, String key, IPAddress& _ip); | ||||||
|     void reconfigureWiFiConnection(); |   void reconfigureWiFiConnection(); | ||||||
|     void manageSTA(); |   void manageSTA(); | ||||||
|  |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif // end WiFiSettingsService_h | #endif  // end WiFiSettingsService_h | ||||||
|   | |||||||
| @@ -1,9 +1,10 @@ | |||||||
| #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); | ||||||
| @@ -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) : | ||||||
|  |     AdminSettingsService(server, fs, securityManager, DEMO_SETTINGS_PATH, DEMO_SETTINGS_FILE) { | ||||||
|   pinMode(BLINK_LED, OUTPUT); |   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: |  | ||||||
|  |  | ||||||
|     unsigned long _lastBlink = 0; |  | ||||||
|     uint8_t _blinkSpeed = 255; |  | ||||||
|  |  | ||||||
|   protected: |  | ||||||
|  |  | ||||||
|     void readFromJsonObject(JsonObject& root); |  | ||||||
|     void writeToJsonObject(JsonObject& root); |  | ||||||
|  |  | ||||||
|  |  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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user