Files
roro9stack/src/services/update_service.h
T
twislaandClaude Opus 5.5 4e439410cd Stop IRC by hand; remove mDNS
IrcService::disconnect() stops the session from any state: QUIT if
connected, then no more retries. /quit goes through it (before, it only
stopped a connected session; while waiting for Wi-Fi or retrying it did
nothing), and so does the new `irc stop` command. Stopped by hand,
opening the IRC App no longer reconnects; typing a line does.

mDNS is gone: it never crossed the dev box's routed network, and it
cost about 7.5 KB of RAM. Pushes go to the IP shown in Settings ->
Firmware, which drops its Name row. OTA Q54 records the change.

On the device, Debug Build: 105.6 KB free with Wi-Fi (was 98); with IRC
on TLS 54 KB free (was 46); after `irc stop`, back to 99 KB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
2026-10-04 23:17:48 +02:00

68 lines
2.4 KiB
C++

#pragma once
#include <freertos/FreeRTOS.h>
#include <string>
#include "event_bus.h"
#include "key_value_store.h"
#include "service.h"
#include "services/storage_service.h"
#include "services/wifi_service.h"
namespace roro {
// Firmware Updates (see CONTEXT.md and docs/milestones/OTA.md): listens for signed Update Files on
// TCP 3232 while Wi-Fi is Connected, installs them from the SD card on request, keeps new firmware
// on Probation until it proves healthy, and reports a Rollback after the reboot.
class UpdateService : public Service {
public:
enum class Phase { Idle, Receiving, Installed, Failed };
static constexpr uint16_t kPort = 3232;
// Call first in setup(): rolls back new firmware that already died once on Probation.
static void bootGuard(KeyValueStore& store);
UpdateService(KeyValueStore& store, WifiService& wifi, SavedNetworks& saved, StorageService& storage,
EventBus& bus, const Settings& settings);
const char* name() const override { return "update"; }
uint32_t tickIntervalMs() const override { return 1000; }
void start() override;
void tick(uint32_t nowMs) override;
// For the progress screen and the Firmware page.
Phase phase() const { return phase_; }
int percent() const { return percent_; }
std::string incomingVersion() const;
bool onProbation() const { return probation_; }
// Installs an Update File from the SD card (runs on the storage task).
void installFromSd(const std::string& path);
// The main loop calls this once it has drawn a frame (part of Probation).
void firstFrameDrawn() { firstFrame_ = true; }
// True when an installed update is waiting to reboot; the main loop reboots when it's safe.
bool rebootPending() const { return phase_ == Phase::Installed; }
private:
static void taskEntry(void* self);
void listen();
void install(class UpdateSource& source, const char* via);
void notify(const std::string& text, NotificationLevel level);
KeyValueStore& store_;
WifiService& wifi_;
SavedNetworks& saved_;
StorageService& storage_;
EventBus& bus_;
const Settings& settings_;
TaskHandle_t task_ = nullptr;
volatile Phase phase_ = Phase::Idle;
volatile int percent_ = 0;
std::string incoming_;
bool probation_ = false;
volatile bool firstFrame_ = false;
};
} // namespace roro