diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0cffcb3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +config.json \ No newline at end of file diff --git a/NewDisplayDriver/esphub/bitmap.cpp b/NewDisplayDriver/esphub/bitmap.cpp index 85622d5..bbee0f2 100644 --- a/NewDisplayDriver/esphub/bitmap.cpp +++ b/NewDisplayDriver/esphub/bitmap.cpp @@ -611,4 +611,40 @@ const unsigned char esphub_lrg [] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 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 +}; + +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 }; \ No newline at end of file diff --git a/NewDisplayDriver/esphub/bitmap.h b/NewDisplayDriver/esphub/bitmap.h index c295b03..2ce074a 100644 --- a/NewDisplayDriver/esphub/bitmap.h +++ b/NewDisplayDriver/esphub/bitmap.h @@ -4,5 +4,6 @@ #include extern const unsigned char esphub_lrg [] PROGMEM; +extern const unsigned char sun [] PROGMEM; #endif \ No newline at end of file diff --git a/NewDisplayDriver/esphub/config_loader.cpp b/NewDisplayDriver/esphub/config_loader.cpp new file mode 100644 index 0000000..c07f7f7 --- /dev/null +++ b/NewDisplayDriver/esphub/config_loader.cpp @@ -0,0 +1,44 @@ +#include "config_loader.h" + +#include +#include + +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()); + } + + return config; +} \ No newline at end of file diff --git a/NewDisplayDriver/esphub/config_loader.h b/NewDisplayDriver/esphub/config_loader.h new file mode 100644 index 0000000..4e1836c --- /dev/null +++ b/NewDisplayDriver/esphub/config_loader.h @@ -0,0 +1,24 @@ +#ifndef CONFIG_LOADER_H +#define CONFIG_LOADER_H + +#include +#include + +// 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 calUrls; + String ncUrl; +}; + +Config loadConfig(); + +#endif \ No newline at end of file diff --git a/NewDisplayDriver/esphub/esphub.ino b/NewDisplayDriver/esphub/esphub.ino index c1fe09c..8a6f8e9 100644 --- a/NewDisplayDriver/esphub/esphub.ino +++ b/NewDisplayDriver/esphub/esphub.ino @@ -12,13 +12,9 @@ // somehow there should be an easier way to do this #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 IS_GxEPD(c, x) (c##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) #if defined(ESP32) @@ -32,27 +28,29 @@ #endif GxEPD2_DISPLAY_CLASS display(GxEPD2_DRIVER_CLASS(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); #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) SPIClass hspi(HSPI); #endif -// +// #include "bitmap.h" +#include "config_loader.h" + +// +#include + +// +#include +#include +#include + +// Globals +Config conf; void setup() { Serial.begin(115200); - delay(5000); + delay(1000); Serial.println(); Serial.println("setup"); // *** special handling for Waveshare ESP32 Driver board *** // @@ -65,38 +63,47 @@ void setup() // **************************************************************** // display.init(115200); // first update should be full refresh - bootDisplay(); delay(1000); - // partial refresh mode can be used to full screen, - // effective if display panel hasFastPartialUpdate -/* helloFullScreenPartialMode(); - delay(1000); - helloArduino(); - delay(1000); - helloEpaper(); - delay(1000); - showFont("FreeMonoBold9pt7b", &FreeMonoBold9pt7b); - delay(1000); - drawBitmaps(); - if (display.epd2.hasPartialUpdate) - { - showPartialUpdate(); - delay(1000); + bootLogo(); + // Do Selftest and Initiation here... Check for WiFi, check NTP Update, check connectivity. + int text_y = 155; + int line_height = 20; + bootMsg("v0.0.1-alpha", text_y); + text_y += line_height; + bootMsg("https://git.fjla.uk/fred.boniface/esphub", text_y); + text_y += line_height; + conf = loadConfig(); + if (connect_WiFi(conf.ssid.c_str(), conf.wifiPass.c_str())) { + bootMsg("WiFi Connection: OK", text_y); + } else { + bootMsg("WiFi Connection: FAIL", text_y); } - display.powerOff(); - deepSleepTest(); */ - - bootDisplay(); - Serial.println("setup done"); + text_y += line_height; + if (update_time()) { + bootMsg("Network Time Update: OK", text_y); + } else { + 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(); } void loop() { + // Run loop here } -void bootDisplay() { - int img_x = (800 - 648) / 2; +// Places the boot logo in position at the top of the screen +void bootLogo() { + constexpr int img_x = (800 - 648) / 2; display.setFullWindow(); display.firstPage(); do @@ -106,4 +113,56 @@ void bootDisplay() { } while (display.nextPage()); delay(2000); -} \ No newline at end of file +} + +// 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; + } +}