Public Access
Add a web UI to the clock firmware
- Web UI on port 80: live view of the display, choose the page (clock or a bitmap), bitmaps (list, show, live, edit, delete), draw / image upload with conversion in the browser, live mode, settings, Home Assistant - Live view from a shadow buffer in the BROSE9323 driver (shownPixel) - Settings in NVS with the original behaviour as defaults: schedule times, quarter hours, yawning Pikachu, No WiFi screen, flip time, status LED, Home Assistant broker (restart on change) - Bitmaps on LittleFS; new 320 KB partition, ota slots now 1.31 MB - DisplayController: pages, live mode, settings; app.cpp holds the objects - README for the recovery app; docs for the web UI - Tests: settings, time parsing, bitmap format and names, schedule with settings, pages and live mode (95 total) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c9e0800e36
commit
2b1ac12ed7
34 files changed
+1989
-117
No files matched your search
@@ -0,0 +1,122 @@
|
||||
#include "app.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "display/bitmap_store.h"
|
||||
#include "system/settings_store.h"
|
||||
|
||||
NanoLink nano(Serial2, NANO_RX_PIN, NANO_TX_PIN, RELAY_PIN, NANO_RESET_PIN);
|
||||
BROSE9323 display(DISPLAY_WIDTH, DISPLAY_HEIGHT, PANEL_WIDTH);
|
||||
FlipdotFrames frames(display);
|
||||
StatusScreen status(display, nano);
|
||||
DisplayController controller(nano, frames);
|
||||
|
||||
static Settings settings;
|
||||
static bool restart_pending = false;
|
||||
static uint32_t restart_at = 0;
|
||||
|
||||
// Load the page bitmap into the frames; falls back to the clock when it is gone
|
||||
static void applyPage()
|
||||
{
|
||||
if (strcmp(settings.page, PAGE_CLOCK) != 0)
|
||||
{
|
||||
uint8_t bitmap[BITMAP_BYTES];
|
||||
if (loadBitmap(settings.page, bitmap))
|
||||
{
|
||||
frames.setPageBitmap(bitmap);
|
||||
controller.setPage(Page::Bitmap);
|
||||
return;
|
||||
}
|
||||
Serial.printf("Page bitmap \"%s\" not found, showing the clock\n", settings.page);
|
||||
}
|
||||
controller.setPage(Page::Clock);
|
||||
}
|
||||
|
||||
static void apply()
|
||||
{
|
||||
controller.setSettings(settings.schedule, settings.clock);
|
||||
status.setFlipTime(settings.flip_time);
|
||||
applyPage();
|
||||
}
|
||||
|
||||
const Settings &appSettings()
|
||||
{
|
||||
return settings;
|
||||
}
|
||||
|
||||
void appLoadSettings()
|
||||
{
|
||||
loadSettings(settings);
|
||||
apply();
|
||||
}
|
||||
|
||||
static bool sameHomeAssistant(const HomeAssistantSettings &a, const HomeAssistantSettings &b)
|
||||
{
|
||||
return a.enabled == b.enabled && a.port == b.port && strcmp(a.host, b.host) == 0 &&
|
||||
strcmp(a.user, b.user) == 0 && strcmp(a.password, b.password) == 0;
|
||||
}
|
||||
|
||||
const char *appSaveSettings(const Settings &new_settings, bool &restart_needed)
|
||||
{
|
||||
const char *error = validateSettings(new_settings);
|
||||
if (error)
|
||||
return error;
|
||||
if (strcmp(new_settings.page, PAGE_CLOCK) != 0 && !bitmapExists(new_settings.page))
|
||||
return "Bitmap not found";
|
||||
|
||||
restart_needed = !sameHomeAssistant(settings.home_assistant, new_settings.home_assistant);
|
||||
bool flip_time_changed = settings.flip_time != new_settings.flip_time;
|
||||
settings = new_settings;
|
||||
saveSettings(settings);
|
||||
apply();
|
||||
if (flip_time_changed && nano.isOn())
|
||||
display.setTiming(settings.flip_time);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *appSelectPage(const char *name)
|
||||
{
|
||||
if (strcmp(name, PAGE_CLOCK) != 0 && !bitmapExists(name))
|
||||
return "Bitmap not found";
|
||||
strncpy(settings.page, name, sizeof(settings.page) - 1);
|
||||
settings.page[sizeof(settings.page) - 1] = '\0';
|
||||
saveSettings(settings);
|
||||
applyPage();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void appBitmapChanged(const char *name)
|
||||
{
|
||||
if (strcmp(settings.page, name) == 0)
|
||||
{
|
||||
applyPage();
|
||||
controller.pageChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void appShowLive(const uint8_t *bitmap)
|
||||
{
|
||||
frames.setLiveBitmap(bitmap);
|
||||
controller.showLive(millis());
|
||||
}
|
||||
|
||||
void appStopLive()
|
||||
{
|
||||
controller.stopLive();
|
||||
}
|
||||
|
||||
void appRestartLater(uint32_t delay_ms)
|
||||
{
|
||||
restart_pending = true;
|
||||
restart_at = millis() + delay_ms;
|
||||
}
|
||||
|
||||
void appLoop()
|
||||
{
|
||||
if (restart_pending && (int32_t)(millis() - restart_at) >= 0)
|
||||
{
|
||||
Serial.println("Restarting for the new settings");
|
||||
ESP.restart();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user