From a0dc2e257ad12cc096668e5083aa73cdfadfb95a Mon Sep 17 00:00:00 2001 From: admar Date: Sat, 17 Aug 2024 22:46:10 +0200 Subject: [PATCH] Get config from server --- include/WifiHandler.hpp | 2 + include/backend.hpp | 21 +++++ include/root_ca.hpp | 6 ++ src/WifiHandler.cpp | 11 ++- src/backend.cpp | 131 +++++++++++++++++++++++++++ src/main.cpp | 18 ++-- include/root_ca.h => src/root_ca.cpp | 5 - 7 files changed, 180 insertions(+), 14 deletions(-) create mode 100644 include/backend.hpp create mode 100644 include/root_ca.hpp create mode 100644 src/backend.cpp rename include/root_ca.h => src/root_ca.cpp (96%) diff --git a/include/WifiHandler.hpp b/include/WifiHandler.hpp index 01f5edd..506bf17 100644 --- a/include/WifiHandler.hpp +++ b/include/WifiHandler.hpp @@ -24,4 +24,6 @@ void set_blink_rate(float interval); void connect(); void resetSettings(); +String getMac(bool insertColons); + #endif // __WIFIHANDLER_HPP__ \ No newline at end of file diff --git a/include/backend.hpp b/include/backend.hpp new file mode 100644 index 0000000..e31ee4d --- /dev/null +++ b/include/backend.hpp @@ -0,0 +1,21 @@ +#ifndef __BACKEND_HPP__ +#define __BACKEND_HPP__ + +#include +#include + +#include "../include/root_ca.hpp" + +extern JsonDocument config; +extern bool isConfigValid; + +extern JsonDocument weatherData; + +bool parseJsonConfig(String& payload); +bool getConfig(); + +String urlencode(String str); + +bool getWeatherData(); + +#endif // __BACKEND_HPP__ \ No newline at end of file diff --git a/include/root_ca.hpp b/include/root_ca.hpp new file mode 100644 index 0000000..a24e7e5 --- /dev/null +++ b/include/root_ca.hpp @@ -0,0 +1,6 @@ +#ifndef __ROOT_CA_H__ +#define __ROOT_CA_H__ + +extern const char* root_ca; + +#endif // __ROOT_CA_H__ \ No newline at end of file diff --git a/src/WifiHandler.cpp b/src/WifiHandler.cpp index c0c1b5c..03abd61 100644 --- a/src/WifiHandler.cpp +++ b/src/WifiHandler.cpp @@ -52,14 +52,14 @@ void connect() { // if it does not connect it starts an access point // and goes into a blocking loop awaiting configuration if (!wifiManager.autoConnect()) { - Serial.println("failed to connect and hit timeout"); + Serial.println(String(millis()) + " Failed to connect and hit timeout"); // reset and try again, or maybe put it to deep sleep ESP.restart(); delay(1000); } // if you get here you have connected to the WiFi - Serial.print("connected with address: "); + Serial.print(String(millis()) + " Connected with address: "); Serial.println(WiFi.localIP()); // keep LED on @@ -69,7 +69,7 @@ void connect() { void resetSettings() { WiFiManager::Status status = {.wifi_status = 0U, .mode = WiFiManager::Mode::ERASING}; - Serial.println("resetting wifi settings..."); + Serial.println(String(millis()) + " Resetting wifi settings..."); wifiManagerCb(status); wifiManager.resetSettings(); @@ -79,3 +79,8 @@ void resetSettings() { return; } + +String getMac(bool insertColons) { + String mac = wifiManager.getMacAsString(insertColons); + return mac; +} \ No newline at end of file diff --git a/src/backend.cpp b/src/backend.cpp new file mode 100644 index 0000000..d969cc4 --- /dev/null +++ b/src/backend.cpp @@ -0,0 +1,131 @@ +#include + +#include "../include/WifiHandler.hpp" +#include "../include/backend.hpp" + +JsonDocument config; +bool isConfigValid = false; +String configTimestamp = ""; + +static HTTPClient http; + +JsonDocument weatherData; + +bool parseJsonConfig(String& payload) { + bool isSuccess = false; + + config.clear(); + + DeserializationError error = deserializeJson(config, payload); + + if (error) { + Serial.print(String(millis()) + " DeserializeJson() failed: " + String(error.f_str())); + } else { + if (config["config version"] != "0.0.1") { + Serial.println(String(millis()) + " Unsupported config version"); + } else { + isSuccess = true; + } + } + + return isSuccess; +} + +bool getConfig() { + String mac = getMac(false); + String url = "https://target.luon.net/~admar/Claire/" + mac + "/config.json"; + String payload = ""; + bool isSuccess = false; + + http.begin(url, root_ca); + if (isConfigValid) { + http.addHeader("If-Modified-Since", configTimestamp); + } + + const char* headerKeys[] = {"Last-Modified"}; + const size_t headerKeysCount = sizeof(headerKeys) / sizeof(headerKeys[0]); + http.collectHeaders(headerKeys, headerKeysCount); + + int httpCode = http.GET(); + + if (httpCode == 200) { + // Content is in payload + payload = http.getString(); + isSuccess = parseJsonConfig(payload); + + if (isSuccess) { + configTimestamp = http.header("Last-Modified"); + Serial.println(String(millis()) + " ConfigTimestamp: " + configTimestamp); + } + } else if (httpCode == 304) { + // Content did not change + isSuccess = true; + } else { + Serial.println(String(millis()) + " Got http code " + httpCode); + } + http.end(); + + return isSuccess; +} + +// From https://circuits4you.com/2019/03/21/esp8266-url-encode-decode-example/ +String urlencode(String str) { + String encodedString = ""; + char c; + char code0; + char code1; + char code2; + for (int i = 0; i < str.length(); i++) { + c = str.charAt(i); + if (c == ' ') { + encodedString += '+'; + } else if (isalnum(c)) { + encodedString += c; + } else { + code1 = (c & 0xf) + '0'; + if ((c & 0xf) > 9) { + code1 = (c & 0xf) - 10 + 'A'; + } + c = (c >> 4) & 0xf; + code0 = c + '0'; + if (c > 9) { + code0 = c - 10 + 'A'; + } + code2 = '\0'; + encodedString += '%'; + encodedString += code0; + encodedString += code1; + // encodedString+=code2; + } + yield(); + } + + return encodedString; +} + +bool getWeatherData() { + String encodedAddress = urlencode(config["address"]); + String url = + "https://sinoptik.luon.net/" + "forecast?address=" + + encodedAddress + + "&metrics=precipitation&metrics=UVI&metrics=AQI&metrics=" + "pollen&metrics=PAQI"; + + String payload = ""; + bool isSuccess = false; + + http.begin(url, root_ca); + + int httpCode = http.GET(); + + if (httpCode > 0) { + payload = http.getString(); + // isSuccess = parseJsonConfig(payload); + } else { + Serial.println(String(millis()) + " Got http code " + httpCode); + } + http.end(); + + return isSuccess; +} diff --git a/src/main.cpp b/src/main.cpp index c29cd5c..605071f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,7 @@ #include #include "../include/WifiHandler.hpp" -#include "../include/root_ca.h" +#include "../include/backend.hpp" DESPatch dESPatch; @@ -15,7 +15,7 @@ void setup() { if (CONNECT_BUTTON >= 0) { // Give user 3 second chance to press button and reset settings - Serial.println("Waiting 3 seconds to check if user presses the button"); + Serial.println(String(millis()) + " Waiting 3 seconds to check if user presses the button"); delay(3000); if (not digitalRead(CONNECT_BUTTON)) { resetSettings(); @@ -31,12 +31,18 @@ void setup() { int x = dESPatch.configure(url, true, false, interval, false, root_ca); - Serial.print("dESPatch.configure() returned with code "); - Serial.println(x); + Serial.println(String(millis()) + " dESPatch.configure() returned with code " + String(x)); } void loop(void) { - Serial.println("hello :-)"); + isConfigValid = getConfig(); + + if (not isConfigValid) { + Serial.println(String(millis()) + " Invalid config"); + } else { + Serial.println(String(millis()) + " Address: " + String(static_cast(config["address"]))); + // getWeatherData(); + } dESPatch.checkForUpdate(true); - delay(5000); + delay(2000); } diff --git a/include/root_ca.h b/src/root_ca.cpp similarity index 96% rename from include/root_ca.h rename to src/root_ca.cpp index 96c6030..c981279 100644 --- a/include/root_ca.h +++ b/src/root_ca.cpp @@ -1,6 +1,3 @@ -#ifndef __ROOT_CA_H__ -#define __ROOT_CA_H__ - const char* root_ca = "-----BEGIN CERTIFICATE-----\n" "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n" @@ -33,5 +30,3 @@ const char* root_ca = "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n" "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n" "-----END CERTIFICATE-----\n"; - -#endif // __ROOT_CA_H__ \ No newline at end of file