Add initialisation checks

This commit is contained in:
Fred Boniface 2024-11-25 22:18:43 +00:00
parent 5734c82748
commit ac11576550
6 changed files with 205 additions and 40 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
config.json

View File

@ -612,3 +612,39 @@ const unsigned char esphub_lrg [] PROGMEM = {
0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00
}; };
const unsigned char sun [] PROGMEM = {
// 'sun, 64x64px
0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff,
0xff, 0xef, 0xff, 0xf8, 0x1f, 0xff, 0xf7, 0xff, 0xff, 0x87, 0xff, 0xfc, 0x3f, 0xff, 0xe1, 0xff,
0xff, 0x83, 0xff, 0xfe, 0x7f, 0xff, 0xc1, 0xff, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0x80, 0xff,
0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xc0, 0x7f, 0xff, 0xff, 0xfe, 0x03, 0xff,
0xff, 0xe0, 0x3f, 0xff, 0xff, 0xfc, 0x07, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xfc, 0x0f, 0xff,
0xff, 0xf8, 0x7f, 0xf0, 0x0f, 0xfe, 0x1f, 0xff, 0xff, 0xfc, 0xff, 0x80, 0x01, 0xff, 0x3f, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xff,
0xff, 0xff, 0xf8, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x03, 0xc0, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xe0, 0x1f, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x3f, 0xfc, 0x03, 0xff, 0xff,
0xff, 0xff, 0xc0, 0x7f, 0xfe, 0x03, 0xff, 0xff, 0xff, 0xff, 0x80, 0xff, 0xff, 0x01, 0xff, 0xff,
0xff, 0xff, 0x81, 0xff, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xc1, 0xff, 0xff,
0xff, 0xff, 0x03, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0x7f, 0x03, 0xff, 0xff, 0xc0, 0xfe, 0x03,
0x00, 0x3f, 0x07, 0xff, 0xff, 0xe0, 0xfc, 0x00, 0x00, 0x1f, 0x07, 0xff, 0xff, 0xe0, 0xf8, 0x00,
0x00, 0x1f, 0x07, 0xff, 0xff, 0xe0, 0xf8, 0x00, 0x00, 0x3f, 0x07, 0xff, 0xff, 0xe0, 0xfc, 0x00,
0xc0, 0x7f, 0x03, 0xff, 0xff, 0xc0, 0xfe, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0xc0, 0xff, 0xff,
0xff, 0xff, 0x83, 0xff, 0xff, 0xc1, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0xff, 0x81, 0xff, 0xff,
0xff, 0xff, 0x80, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x7f, 0xfe, 0x03, 0xff, 0xff,
0xff, 0xff, 0xe0, 0x3f, 0xfc, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1f, 0xf8, 0x07, 0xff, 0xff,
0xff, 0xff, 0xf0, 0x03, 0xc0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x1f, 0xff, 0xff,
0xff, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff,
0xff, 0xfc, 0xff, 0x80, 0x01, 0xff, 0x3f, 0xff, 0xff, 0xf8, 0x7f, 0xf0, 0x0f, 0xfe, 0x1f, 0xff,
0xff, 0xf0, 0x3f, 0xff, 0xff, 0xfc, 0x0f, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xfc, 0x07, 0xff,
0xff, 0xc0, 0x7f, 0xff, 0xff, 0xfe, 0x03, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff,
0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0xff, 0x83, 0xff, 0xfe, 0x7f, 0xff, 0xc1, 0xff,
0xff, 0x87, 0xff, 0xfc, 0x3f, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff
};

View File

@ -4,5 +4,6 @@
#include <Arduino.h> #include <Arduino.h>
extern const unsigned char esphub_lrg [] PROGMEM; extern const unsigned char esphub_lrg [] PROGMEM;
extern const unsigned char sun [] PROGMEM;
#endif #endif

View File

@ -0,0 +1,44 @@
#include "config_loader.h"
#include <LittleFS.h>
#include <ArduinoJson.h>
Config loadConfig() {
Config config;
if (!LittleFS.begin()) {
return config;
}
File configFile = LittleFS.open("/config.json", "r");
if (!configFile) {
return config;
}
StaticJsonDocument<1024> doc;
DeserializationError error = deserializeJson(doc, configFile);
if (error) {
configFile.close();
return config;
}
configFile.close();
config.ssid = doc["ssid"] | "";
config.wifiPass = doc["wifiPass"] | "";
config.latitude = doc["latitude"] | 0.0;
config.longitude = doc["longitude"] | 0.0;
config.haKey = doc["haKey"] | "";
config.homeEntity = doc["homeEntity"] | "";
config.haUrl = doc["haUrl"] | "";
config.calUser = doc["calUser"] | "";
config.calKey = doc["calKey"] | "";
config.ncUrl = doc["ncUrl"] | "";
JsonArray calUrls = doc["calUrls"];
for (JsonVariant url : calUrls) {
config.calUrls.push_back(url.as<String>());
}
return config;
}

View File

@ -0,0 +1,24 @@
#ifndef CONFIG_LOADER_H
#define CONFIG_LOADER_H
#include <Arduino.h>
#include <vector>
// Config structure
struct Config {
String ssid;
String wifiPass;
float latitude = 0.0;
float longitude = 0.0;
String haKey;
String homeEntity;
String haUrl;
String calUser;
String calKey;
std::vector<String> calUrls;
String ncUrl;
};
Config loadConfig();
#endif

View File

@ -12,13 +12,9 @@
// somehow there should be an easier way to do this // somehow there should be an easier way to do this
#define GxEPD2_BW_IS_GxEPD2_BW true #define GxEPD2_BW_IS_GxEPD2_BW true
//#define GxEPD2_3C_IS_GxEPD2_3C true
//#define GxEPD2_7C_IS_GxEPD2_7C true
#define GxEPD2_1248_IS_GxEPD2_1248 true #define GxEPD2_1248_IS_GxEPD2_1248 true
#define IS_GxEPD(c, x) (c##x) #define IS_GxEPD(c, x) (c##x)
#define IS_GxEPD2_BW(x) IS_GxEPD(GxEPD2_BW_IS_, x) #define IS_GxEPD2_BW(x) IS_GxEPD(GxEPD2_BW_IS_, x)
//#define IS_GxEPD2_3C(x) IS_GxEPD(GxEPD2_3C_IS_, x)
//#define IS_GxEPD2_7C(x) IS_GxEPD(GxEPD2_7C_IS_, x)
#define IS_GxEPD2_1248(x) IS_GxEPD(GxEPD2_1248_IS_, x) #define IS_GxEPD2_1248(x) IS_GxEPD(GxEPD2_1248_IS_, x)
#if defined(ESP32) #if defined(ESP32)
@ -32,27 +28,29 @@
#endif #endif
GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
#endif #endif
/*
// comment out unused bitmaps to reduce code space used
#include "bitmaps/Bitmaps200x200.h" // 1.54" b/w
#include "bitmaps/Bitmaps104x212.h" // 2.13" b/w flexible GDEW0213I5F
#include "bitmaps/Bitmaps128x250.h" // 2.13" b/w
#include "bitmaps/Bitmaps128x296.h" // 2.9" b/w
#include "bitmaps/Bitmaps176x264.h" // 2.7" b/w
#include "bitmaps/Bitmaps400x300.h" // 4.2" b/w
#include "bitmaps/Bitmaps640x384.h" // 7.5" b/w
*/
#if defined(ESP32) && defined(USE_HSPI_FOR_EPD) #if defined(ESP32) && defined(USE_HSPI_FOR_EPD)
SPIClass hspi(HSPI); SPIClass hspi(HSPI);
#endif #endif
// <My Includes> // <Local Includes>
#include "bitmap.h" #include "bitmap.h"
#include "config_loader.h"
// <Fonts>
#include <Fonts/FreeMono9pt7b.h>
// <Connectivity>
#include <WiFi.h>
#include <time.h>
#include <HTTPClient.h>
// Globals
Config conf;
void setup() void setup()
{ {
Serial.begin(115200); Serial.begin(115200);
delay(5000); delay(1000);
Serial.println(); Serial.println();
Serial.println("setup"); Serial.println("setup");
// *** special handling for Waveshare ESP32 Driver board *** // // *** special handling for Waveshare ESP32 Driver board *** //
@ -65,38 +63,47 @@ void setup()
// **************************************************************** // // **************************************************************** //
display.init(115200); display.init(115200);
// first update should be full refresh // first update should be full refresh
bootDisplay();
delay(1000); delay(1000);
// partial refresh mode can be used to full screen, bootLogo();
// effective if display panel hasFastPartialUpdate // Do Selftest and Initiation here... Check for WiFi, check NTP Update, check connectivity.
/* helloFullScreenPartialMode(); int text_y = 155;
delay(1000); int line_height = 20;
helloArduino(); bootMsg("v0.0.1-alpha", text_y);
delay(1000); text_y += line_height;
helloEpaper(); bootMsg("https://git.fjla.uk/fred.boniface/esphub", text_y);
delay(1000); text_y += line_height;
showFont("FreeMonoBold9pt7b", &FreeMonoBold9pt7b); conf = loadConfig();
delay(1000); if (connect_WiFi(conf.ssid.c_str(), conf.wifiPass.c_str())) {
drawBitmaps(); bootMsg("WiFi Connection: OK", text_y);
if (display.epd2.hasPartialUpdate) } else {
{ bootMsg("WiFi Connection: FAIL", text_y);
showPartialUpdate();
delay(1000);
} }
display.powerOff(); text_y += line_height;
deepSleepTest(); */ if (update_time()) {
bootMsg("Network Time Update: OK", text_y);
bootDisplay(); } else {
Serial.println("setup done"); bootMsg("Network Time Update: FAIL", text_y);
}
text_y += line_height;
if (checkUrlPing(conf.haUrl)) { // FAILS FOR SOME REASON -- DEBUG ME
bootMsg("Home Assistant URL Reachable: OK", text_y);
// Check home entity is reachable here.
} else {
bootMsg("Home Assistant URL Reachable: FAIL", text_y);
}
text_y += line_height;
// Check Nextcloud reachable here
display.hibernate(); display.hibernate();
} }
void loop() void loop()
{ {
// Run loop here
} }
void bootDisplay() { // Places the boot logo in position at the top of the screen
int img_x = (800 - 648) / 2; void bootLogo() {
constexpr int img_x = (800 - 648) / 2;
display.setFullWindow(); display.setFullWindow();
display.firstPage(); display.firstPage();
do do
@ -107,3 +114,55 @@ void bootDisplay() {
while (display.nextPage()); while (display.nextPage());
delay(2000); delay(2000);
} }
// Prints a one-line message to the screen, aligned with the boot logo at `y_pos`
void bootMsg(const char* msg, const uint16_t y_pos) {
constexpr uint16_t x_pos = 76; // Manually calculated based on values in bootLogo();
// Define the partial window area
display.setPartialWindow(0, 0, display.width(), display.height());
display.setFont(&FreeMono9pt7b); // Set font
display.setTextColor(GxEPD_BLACK); // Set color
display.setCursor(x_pos, y_pos); // Set the cursor for printing
display.print(msg); // Print the message
display.nextPage(); // Only needed for e-ink paginated updates
}
bool connect_WiFi(String ssid, String pass) {
WiFi.begin(ssid, pass);
int retries = 10;
while (WiFi.status() != WL_CONNECTED && retries > 0) {
delay(1000);
retries --;
}
if (WiFi.status() != WL_CONNECTED) {
return false;
}
return true;
}
bool update_time() {
configTime(0, 0, "time.fjla.net", "pool.ntp.org");
struct tm timeinfo;
if (!getLocalTime(&timeinfo, 20000)) {
Serial.println("Failed to obtain time");
return false;
}
return true;
}
bool checkUrlPing(const String& url) {
HTTPClient http;
WiFiClient client;
http.begin(client, url);
int httpCode = http.GET();
if (httpCode == HTTP_CODE_OK) {
http.end();
return true;
} else {
http.end();
return false;
}
}