Release v0.4.0: complete rewrite #1
7 changed files with 180 additions and 14 deletions
|
@ -24,4 +24,6 @@ void set_blink_rate(float interval);
|
||||||
void connect();
|
void connect();
|
||||||
void resetSettings();
|
void resetSettings();
|
||||||
|
|
||||||
|
String getMac(bool insertColons);
|
||||||
|
|
||||||
#endif // __WIFIHANDLER_HPP__
|
#endif // __WIFIHANDLER_HPP__
|
21
include/backend.hpp
Normal file
21
include/backend.hpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#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__
|
6
include/root_ca.hpp
Normal file
6
include/root_ca.hpp
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef __ROOT_CA_H__
|
||||||
|
#define __ROOT_CA_H__
|
||||||
|
|
||||||
|
extern const char* root_ca;
|
||||||
|
|
||||||
|
#endif // __ROOT_CA_H__
|
|
@ -52,14 +52,14 @@ void connect() {
|
||||||
// if it does not connect it starts an access point
|
// if it does not connect it starts an access point
|
||||||
// and goes into a blocking loop awaiting configuration
|
// and goes into a blocking loop awaiting configuration
|
||||||
if (!wifiManager.autoConnect()) {
|
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
|
// reset and try again, or maybe put it to deep sleep
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
delay(1000);
|
delay(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if you get here you have connected to the WiFi
|
// 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());
|
Serial.println(WiFi.localIP());
|
||||||
|
|
||||||
// keep LED on
|
// keep LED on
|
||||||
|
@ -69,7 +69,7 @@ void connect() {
|
||||||
void resetSettings() {
|
void resetSettings() {
|
||||||
WiFiManager::Status status = {.wifi_status = 0U, .mode = WiFiManager::Mode::ERASING};
|
WiFiManager::Status status = {.wifi_status = 0U, .mode = WiFiManager::Mode::ERASING};
|
||||||
|
|
||||||
Serial.println("resetting wifi settings...");
|
Serial.println(String(millis()) + " Resetting wifi settings...");
|
||||||
|
|
||||||
wifiManagerCb(status);
|
wifiManagerCb(status);
|
||||||
wifiManager.resetSettings();
|
wifiManager.resetSettings();
|
||||||
|
@ -79,3 +79,8 @@ void resetSettings() {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getMac(bool insertColons) {
|
||||||
|
String mac = wifiManager.getMacAsString(insertColons);
|
||||||
|
return mac;
|
||||||
|
}
|
131
src/backend.cpp
Normal file
131
src/backend.cpp
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
#include <HTTPClient.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
18
src/main.cpp
18
src/main.cpp
|
@ -1,7 +1,7 @@
|
||||||
#include <dESPatch.h>
|
#include <dESPatch.h>
|
||||||
|
|
||||||
#include "../include/WifiHandler.hpp"
|
#include "../include/WifiHandler.hpp"
|
||||||
#include "../include/root_ca.h"
|
#include "../include/backend.hpp"
|
||||||
|
|
||||||
DESPatch dESPatch;
|
DESPatch dESPatch;
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ void setup() {
|
||||||
|
|
||||||
if (CONNECT_BUTTON >= 0) {
|
if (CONNECT_BUTTON >= 0) {
|
||||||
// Give user 3 second chance to press button and reset settings
|
// 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);
|
delay(3000);
|
||||||
if (not digitalRead(CONNECT_BUTTON)) {
|
if (not digitalRead(CONNECT_BUTTON)) {
|
||||||
resetSettings();
|
resetSettings();
|
||||||
|
@ -31,12 +31,18 @@ void setup() {
|
||||||
|
|
||||||
int x = dESPatch.configure(url, true, false, interval, false, root_ca);
|
int x = dESPatch.configure(url, true, false, interval, false, root_ca);
|
||||||
|
|
||||||
Serial.print("dESPatch.configure() returned with code ");
|
Serial.println(String(millis()) + " dESPatch.configure() returned with code " + String(x));
|
||||||
Serial.println(x);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop(void) {
|
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<const char*>(config["address"])));
|
||||||
|
// getWeatherData();
|
||||||
|
}
|
||||||
dESPatch.checkForUpdate(true);
|
dESPatch.checkForUpdate(true);
|
||||||
delay(5000);
|
delay(2000);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
#ifndef __ROOT_CA_H__
|
|
||||||
#define __ROOT_CA_H__
|
|
||||||
|
|
||||||
const char* root_ca =
|
const char* root_ca =
|
||||||
"-----BEGIN CERTIFICATE-----\n"
|
"-----BEGIN CERTIFICATE-----\n"
|
||||||
"MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n"
|
"MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n"
|
||||||
|
@ -33,5 +30,3 @@ const char* root_ca =
|
||||||
"mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n"
|
"mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n"
|
||||||
"emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n"
|
"emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n"
|
||||||
"-----END CERTIFICATE-----\n";
|
"-----END CERTIFICATE-----\n";
|
||||||
|
|
||||||
#endif // __ROOT_CA_H__
|
|
Loading…
Reference in a new issue