Public Access
OTA steps 3-5: Update Service, Probation and Rollback, Update from SD
- EcdsaVerifier (mbedTLS, embedded public key) and EspOtaSink (writes the inactive app slot, esp_ota_end validates the image, then sets the boot partition) - UpdateService: listens on TCP 3232 (and mDNS roro9stack-<id>) while Wi-Fi is Connected; streams into UpdateParser; replies OK/ERR to the sender; remembers the pending version so a Rollback is reported after the reboot - Probation (host-tested): confirm after the first frame + 30 s + Wi-Fi (if configured); roll back if configured Wi-Fi never connects in 3 min - Main loop: full-screen progress while receiving; restart once installed, waiting up to 60 s for Text Entry to end - Settings > Firmware: version, Probation status, push address and name, and the .ota files in /updates on the SD card to install - StorageService.runJob() runs work on the storage task (SD installs) - wifi status prints IP and running version; RORO_TEST_CRASH test hook Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
+42
-5
@@ -19,6 +19,7 @@
|
||||
#include "services/clock_service.h"
|
||||
#include "services/power_service.h"
|
||||
#include "services/storage_service.h"
|
||||
#include "services/update_service.h"
|
||||
#include "services/wifi_service.h"
|
||||
#include "settings.h"
|
||||
#include "storage_paths.h"
|
||||
@@ -43,6 +44,7 @@ static ClockService* clockService;
|
||||
static SavedNetworks* savedNetworks;
|
||||
static WifiService* wifi;
|
||||
static IrcService* irc;
|
||||
static UpdateService* update;
|
||||
static Notifier* notifier;
|
||||
static LauncherApp launcher;
|
||||
static AppManager* apps;
|
||||
@@ -104,6 +106,7 @@ void setup() {
|
||||
savedNetworks = new SavedNetworks(nvs);
|
||||
savedNetworks->load();
|
||||
wifi = new WifiService(settings, *savedNetworks, *clockService);
|
||||
update = new UpdateService(nvs, *wifi, *savedNetworks, *storageService, bus, settings);
|
||||
irc = new IrcService(nvs, "roro_" + identity::defaultShortName(), *wifi, *storageService, *clockService, bus);
|
||||
notifier = new Notifier(bus, settings);
|
||||
notifier->onShow = [](uint32_t now, uint32_t until) { power->onNotification(now, until); };
|
||||
@@ -113,13 +116,14 @@ void setup() {
|
||||
services.add(*storageService);
|
||||
services.add(*wifi);
|
||||
services.add(*irc);
|
||||
services.add(*update);
|
||||
|
||||
apps = new AppManager(launcher);
|
||||
launcher.setManager(*apps);
|
||||
apps->registerApp({"irc", "IRC", false, new IrcApp(*irc, *clockService, bus)});
|
||||
apps->registerApp({"wifi-tools", "Wi-Fi Tools", false, new WifiToolsApp(*wifi, *storageService, *clockService)});
|
||||
apps->registerApp({"settings", "Settings", false,
|
||||
new SettingsApp({settings, bus, *apps, *battery, *storageService, *clockService, *wifi, *savedNetworks})});
|
||||
new SettingsApp({settings, bus, *apps, *battery, *storageService, *clockService, *wifi, *savedNetworks, *update})});
|
||||
apps->registerApp({"demo", "Widget demo", true, new DemoApp(bus)});
|
||||
apps->registerApp({"setup", "Setup", true, new SetupApp(settings, *apps)});
|
||||
|
||||
@@ -222,9 +226,10 @@ static void serialCommands() {
|
||||
});
|
||||
}
|
||||
if (line == "wifi status")
|
||||
Serial.printf("wifi: state %d ssid '%s' rssi %d clock %s heap %u min %u\n", (int)wifi->state(),
|
||||
wifi->ssid().c_str(), wifi->rssi(), clockService->displayTime().c_str(), ESP.getFreeHeap(),
|
||||
ESP.getMinFreeHeap());
|
||||
Serial.printf("wifi: state %d ssid '%s' rssi %d ip %s clock %s heap %u min %u | fw %s%s\n",
|
||||
(int)wifi->state(), wifi->ssid().c_str(), wifi->rssi(), wifi->ip().c_str(),
|
||||
clockService->displayTime().c_str(), ESP.getFreeHeap(), ESP.getMinFreeHeap(), versionString(),
|
||||
update->onProbation() ? " (on probation)" : "");
|
||||
if (line == "sound off") settings.setBool(Setting::Sound, false);
|
||||
if (line == "sound on") settings.setBool(Setting::Sound, true);
|
||||
if (line == "short") {
|
||||
@@ -240,6 +245,10 @@ static void serialCommands() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
#ifdef RORO_TEST_CRASH
|
||||
// Test builds only (never in a release): crash during Probation to exercise Rollback.
|
||||
if (millis() > 5000) abort();
|
||||
#endif
|
||||
static StatusInfo lastStatus;
|
||||
static uint32_t lastLog = 0;
|
||||
uint32_t now = millis();
|
||||
@@ -265,12 +274,40 @@ void loop() {
|
||||
Serial.printf("status: heap %u min %u\n", ESP.getFreeHeap(), ESP.getMinFreeHeap());
|
||||
}
|
||||
|
||||
// Firmware Update: its progress takes over the screen, then the device restarts when it's safe.
|
||||
static int shownPercent = -1;
|
||||
static uint32_t installedAt = 0;
|
||||
static bool redrawAfterUpdate = false;
|
||||
switch (update->phase()) {
|
||||
case UpdateService::Phase::Receiving:
|
||||
if (update->percent() != shownPercent) {
|
||||
shownPercent = update->percent();
|
||||
screen.renderUpdate("Firmware update", "Receiving " + update->incomingVersion(), shownPercent);
|
||||
}
|
||||
redrawAfterUpdate = true;
|
||||
return;
|
||||
case UpdateService::Phase::Installed:
|
||||
if (!installedAt) installedAt = now;
|
||||
// Don't pull the rug out from under someone typing, for up to a minute.
|
||||
if (!apps->foreground().textEntryActive() || now - installedAt >= 60000) {
|
||||
screen.renderUpdate("Restarting", "into " + update->incomingVersion(), -1);
|
||||
delay(800);
|
||||
ESP.restart();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
shownPercent = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (power->screen() == ScreenState::Off) return;
|
||||
StatusInfo status = currentStatus();
|
||||
const Toast* toast = notifier->toasts().current(now);
|
||||
bool toastChanged = notifier->toasts().takeChanged();
|
||||
if (apps->takeRedraw() || toastChanged || status != lastStatus) {
|
||||
if (apps->takeRedraw() || toastChanged || status != lastStatus || redrawAfterUpdate) {
|
||||
lastStatus = status;
|
||||
redrawAfterUpdate = false;
|
||||
screen.render(*apps, status, toast);
|
||||
update->firstFrameDrawn();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user