Release v0.4.0: complete rewrite #1

Merged
admar merged 13 commits from Plus-Claire into main 2024-09-24 21:54:12 +02:00
8 changed files with 221 additions and 183 deletions
Showing only changes of commit 388bd0a84c - Show all commits

View file

@ -1,29 +0,0 @@
#ifndef __WIFIHANDLER_HPP__
#define __WIFIHANDLER_HPP__
#include <WiFiManager-esp32.h> // https://github.com/admarschoonen/WiFiManager
#define TICKER_RATE_CONNECTING 0.6
#define TICKER_RATE_CONFIG 0.2
#define TICKER_RATE_ERASE 0.05
#ifndef LED_BUILTIN
#define LED_BUILTIN 2
#endif
#ifndef BUTTON_BUILTIN
#define BUTTON_BUILTIN 0
#endif
#define CONNECT_BUTTON BUTTON_BUILTIN
void wifiManagerCb(WiFiManager::Status status);
void set_blink_rate(float interval);
void connect();
void resetSettings();
String getMac(bool insertColons);
#endif // __WIFIHANDLER_HPP__

View file

@ -1,21 +0,0 @@
#ifndef __BACKEND_HPP__
#define __BACKEND_HPP__
#include <Arduino.h>
#include <ArduinoJson.h>
#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__

View file

@ -0,0 +1,38 @@
#ifndef __BACKEND_HPP__
#define __BACKEND_HPP__
#include <Arduino.h>
#include <ArduinoJson.h>
#include "../include/root_ca.hpp"
#include "../include/wifi_handler.hpp"
class BackendCommunication {
public:
// Constructor
BackendCommunication(WifiHandler& p_wifi_handler);
public:
// Public methods
bool parseJsonConfig(String& payload);
bool getConfig();
bool getWeatherData();
private:
// Private methods
String urlencode(String str);
public:
// Public member objects
JsonDocument m_config;
bool m_is_config_valid;
JsonDocument m_weather_data;
private:
// Private member objects
WifiHandler& m_wifi_handler;
};
#endif // __BACKEND_HPP__

33
include/wifi_handler.hpp Normal file
View file

@ -0,0 +1,33 @@
#ifndef __WIFIHANDLER_HPP__
#define __WIFIHANDLER_HPP__
#include <WiFiManager-esp32.h> // https://github.com/admarschoonen/WiFiManager
class WifiHandler {
public:
// Constructor
WifiHandler(uint8_t p_led_pin);
public:
// Public static methods
static void setBlinkRate(float p_interval);
static void wifiManagerCb(WiFiManager::Status p_status);
public:
// Public methods
void connect();
void resetSettings();
String getMac(bool insertColons);
public:
// Public static objects
constexpr static float BLINK_RATE_CONNECTING = 0.6f;
constexpr static float BLINK_RATE_CONFIG = 0.2f;
constexpr static float BLINK_RATE_ERASE = 0.05f;
private:
// Private objects
WiFiManager m_wifiManager;
};
#endif // __WIFIHANDLER_HPP__

View file

@ -1,86 +0,0 @@
#include <Ticker.h>
#include <WiFiManager-esp32.h> // https://github.com/admarschoonen/WiFiManager
#include "../include/WifiHandler.hpp"
WiFiManager wifiManager;
Ticker ticker;
static void tick(void) {
int state = 0;
if (LED_BUILTIN >= 0) {
state = digitalRead(LED_BUILTIN);
digitalWrite(LED_BUILTIN, !state);
}
}
void set_blink_rate(float interval) {
if (ticker.active()) {
ticker.detach();
}
if (interval > 0.0f) {
ticker.attach(interval, tick);
}
}
void wifiManagerCb(WiFiManager::Status status) {
if (status.mode == WiFiManager::Mode::CONNECTING) {
set_blink_rate(TICKER_RATE_CONNECTING);
} else if (status.mode == WiFiManager::Mode::SCANNING) {
set_blink_rate(TICKER_RATE_CONNECTING);
} else if (status.mode == WiFiManager::Mode::PORTAL) {
set_blink_rate(TICKER_RATE_CONFIG);
} else if (status.mode == WiFiManager::Mode::ERASING) {
set_blink_rate(TICKER_RATE_ERASE);
} else if (status.mode == WiFiManager::Mode::CONNECTED) {
set_blink_rate(0.0f);
digitalWrite(LED_BUILTIN, HIGH);
} else if (status.mode == WiFiManager::Mode::DISCONNECTED) {
set_blink_rate(0.0f);
digitalWrite(LED_BUILTIN, LOW);
}
}
void connect() {
Serial.begin(115200);
wifiManager.configure("Claire", wifiManagerCb);
// fetches ssid and pass and tries to connect
// if it does not connect it starts an access point
// and goes into a blocking loop awaiting configuration
if (!wifiManager.autoConnect()) {
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(String(millis()) + " Connected with address: ");
Serial.println(WiFi.localIP());
// keep LED on
digitalWrite(LED_BUILTIN, HIGH);
}
void resetSettings() {
WiFiManager::Status status = {.wifi_status = 0U, .mode = WiFiManager::Mode::ERASING};
Serial.println(String(millis()) + " Resetting wifi settings...");
wifiManagerCb(status);
wifiManager.resetSettings();
delay(1000);
status.mode = WiFiManager::Mode::DISCONNECTED;
wifiManagerCb(status);
return;
}
String getMac(bool insertColons) {
String mac = wifiManager.getMacAsString(insertColons);
return mac;
}

View file

@ -1,9 +1,8 @@
#include <HTTPClient.h> #include <HTTPClient.h>
#include "../include/WifiHandler.hpp" #include "../include/backend_communication.hpp"
#include "../include/backend.hpp" #include "../include/wifi_handler.hpp"
JsonDocument config;
bool isConfigValid = false; bool isConfigValid = false;
String configTimestamp = ""; String configTimestamp = "";
@ -11,19 +10,22 @@ static HTTPClient http;
JsonDocument weatherData; JsonDocument weatherData;
bool parseJsonConfig(String& payload) { BackendCommunication::BackendCommunication(WifiHandler& p_wifi_handler) : m_wifi_handler(p_wifi_handler) { return; }
bool BackendCommunication::parseJsonConfig(String& payload) {
bool isSuccess = false; bool isSuccess = false;
config.clear(); m_config.clear();
DeserializationError error = deserializeJson(config, payload); DeserializationError error = deserializeJson(m_config, payload);
if (error) { if (error) {
Serial.print(String(millis()) + " DeserializeJson() failed: " + String(error.f_str())); Serial.print(String(millis()) + " DeserializeJson() failed: " + String(error.f_str()));
} else { } else {
if (config["config version"] != "0.0.1") { if (m_config["config version"] != "0.0.1") {
Serial.println(String(millis()) + " Unsupported config version"); Serial.println(String(millis()) + " Unsupported config version");
} else { } else {
m_is_config_valid = true;
isSuccess = true; isSuccess = true;
} }
} }
@ -31,9 +33,10 @@ bool parseJsonConfig(String& payload) {
return isSuccess; return isSuccess;
} }
bool getConfig() { bool BackendCommunication::getConfig() {
String mac = getMac(false); String mac = m_wifi_handler.getMac(false);
String url = "https://target.luon.net/~admar/Claire/" + mac + "/config.json"; String url = "https://target.luon.net/~admar/Claire/" + urlencode(mac) + "/config.json";
String payload = ""; String payload = "";
bool isSuccess = false; bool isSuccess = false;
@ -68,8 +71,30 @@ bool getConfig() {
return isSuccess; return isSuccess;
} }
// From https://circuits4you.com/2019/03/21/esp8266-url-encode-decode-example/ bool BackendCommunication::getWeatherData() {
String urlencode(String str) { String url = "https://sinoptik.luon.net/forecast?address=" + urlencode(m_config["address"]) +
"&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;
}
String BackendCommunication::urlencode(String str) {
// From https://circuits4you.com/2019/03/21/esp8266-url-encode-decode-example/
String encodedString = ""; String encodedString = "";
char c; char c;
char code0; char code0;
@ -102,30 +127,3 @@ String urlencode(String str) {
return encodedString; 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;
}

View file

@ -1,15 +1,29 @@
#include <dESPatch.h> #include <dESPatch.h>
#include "../include/WifiHandler.hpp" #include "../include/backend_communication.hpp"
#include "../include/backend.hpp" #include "../include/wifi_handler.hpp"
#ifndef LED_BUILTIN
#define LED_BUILTIN 2
#endif
#ifndef BUTTON_BUILTIN
#define BUTTON_BUILTIN 0
#endif
#define CONNECT_BUTTON BUTTON_BUILTIN
DESPatch dESPatch; DESPatch dESPatch;
WifiHandler wifi_handler(LED_BUILTIN);
BackendCommunication backend_communication(wifi_handler);
void setup() { void setup() {
Serial.begin(115200); Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT); pinMode(LED_BUILTIN, OUTPUT);
set_blink_rate(TICKER_RATE_CONNECTING);
wifi_handler.setBlinkRate(WifiHandler::BLINK_RATE_CONNECTING);
pinMode(CONNECT_BUTTON, INPUT); pinMode(CONNECT_BUTTON, INPUT);
@ -18,11 +32,11 @@ void setup() {
Serial.println(String(millis()) + " 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); delay(3000);
if (not digitalRead(CONNECT_BUTTON)) { if (not digitalRead(CONNECT_BUTTON)) {
resetSettings(); wifi_handler.resetSettings();
} }
} }
connect(); wifi_handler.connect();
const char url[] = const char url[] =
"https://apikey:cqprlgiafadnidsgeqozcpldkaeqimqw@despatch.luon.net/" "https://apikey:cqprlgiafadnidsgeqozcpldkaeqimqw@despatch.luon.net/"
@ -35,12 +49,13 @@ void setup() {
} }
void loop(void) { void loop(void) {
isConfigValid = getConfig(); backend_communication.getConfig();
if (not isConfigValid) { if (not backend_communication.m_is_config_valid) {
Serial.println(String(millis()) + " Invalid config"); Serial.println(String(millis()) + " Invalid config");
} else { } else {
Serial.println(String(millis()) + " Address: " + String(static_cast<const char*>(config["address"]))); Serial.println(String(millis()) +
" Address: " + String(static_cast<const char*>(backend_communication.m_config["address"])));
// getWeatherData(); // getWeatherData();
} }
dESPatch.checkForUpdate(true); dESPatch.checkForUpdate(true);

90
src/wifi_handler.cpp Normal file
View file

@ -0,0 +1,90 @@
#include <Ticker.h>
#include "../include/wifi_handler.hpp"
static uint8_t g_led_pin;
static Ticker g_ticker;
WifiHandler::WifiHandler(uint8_t p_led_pin) {
g_led_pin = p_led_pin;
return;
}
static void tick() {
int state = 0;
if (g_led_pin >= 0) {
state = digitalRead(g_led_pin);
digitalWrite(g_led_pin, !state);
}
}
void WifiHandler::setBlinkRate(float p_interval) {
if (g_ticker.active()) {
g_ticker.detach();
}
if (p_interval > 0.0f) {
g_ticker.attach(p_interval, tick);
}
}
void WifiHandler::wifiManagerCb(WiFiManager::Status p_status) {
if (p_status.mode == WiFiManager::Mode::CONNECTING) {
WifiHandler::setBlinkRate(WifiHandler::BLINK_RATE_CONNECTING);
} else if (p_status.mode == WiFiManager::Mode::SCANNING) {
WifiHandler::setBlinkRate(WifiHandler::BLINK_RATE_CONNECTING);
} else if (p_status.mode == WiFiManager::Mode::PORTAL) {
WifiHandler::setBlinkRate(WifiHandler::BLINK_RATE_CONFIG);
} else if (p_status.mode == WiFiManager::Mode::ERASING) {
WifiHandler::setBlinkRate(WifiHandler::BLINK_RATE_ERASE);
} else if (p_status.mode == WiFiManager::Mode::CONNECTED) {
WifiHandler::setBlinkRate(0.0f);
digitalWrite(g_led_pin, HIGH);
} else if (p_status.mode == WiFiManager::Mode::DISCONNECTED) {
WifiHandler::setBlinkRate(0.0f);
digitalWrite(g_led_pin, LOW);
}
}
void WifiHandler::connect() {
Serial.begin(115200);
m_wifiManager.configure("Claire", WifiHandler::wifiManagerCb);
// fetches ssid and pass and tries to connect
// if it does not connect it starts an access point
// and goes into a blocking loop awaiting configuration
if (!m_wifiManager.autoConnect()) {
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(String(millis()) + " Connected with address: ");
Serial.println(WiFi.localIP());
// keep LED on
digitalWrite(g_led_pin, HIGH);
}
void WifiHandler::resetSettings() {
WiFiManager::Status status = {.wifi_status = 0U, .mode = WiFiManager::Mode::ERASING};
Serial.println(String(millis()) + " Resetting wifi settings...");
wifiManagerCb(status);
m_wifiManager.resetSettings();
delay(1000);
status.mode = WiFiManager::Mode::DISCONNECTED;
wifiManagerCb(status);
return;
}
String WifiHandler::getMac(bool p_insertColons) {
String mac = m_wifiManager.getMacAsString(p_insertColons);
return mac;
}