feat(mqtt): implement deferred OTA update scheduling in MyMesh

Add functionality to schedule deferred OTA updates in the MyMesh class.
This includes a new member variable to track the update time and a method
to initiate the update process, allowing for a smoother OTA experience
by managing timing and state transitions effectively.
This commit is contained in:
agessaman
2026-07-21 10:27:35 -07:00
parent 333e7869cf
commit 76f44d7d80
2 changed files with 27 additions and 0 deletions
+17
View File
@@ -1374,6 +1374,23 @@ void MyMesh::loop() {
MESH_DEBUG_PRINTLN("Radio params restored");
}
#if defined(WITH_MQTT_BRIDGE) && defined(OTA_MANIFEST_BASE)
if (_ota_update_at && millisHasNowPassed(_ota_update_at)) { // deferred `ota update`
_ota_update_at = 0; // clear timer
// The "Beginning update..." reply has now gone out. Free the bridge for heap
// headroom, then flash: otaFromManifest reboots into the new image on success
// (so this never returns); on any abort (already up to date, partition change,
// download error) it returns and we resume the bridge.
Serial.println("OTA: starting update");
setBridgeState(false);
char ota_reply[160];
if (!_cli.getBoard()->otaFromManifest(getFirmwareVer(), false, ota_reply)) {
Serial.print("OTA: aborted, resuming bridge - "); Serial.println(ota_reply);
setBridgeState(true);
}
}
#endif
// is pending dirty contacts write needed?
if (dirty_contacts_expiry && millisHasNowPassed(dirty_contacts_expiry)) {
acl.save(_fs, MyMesh::saveFilter);
+10
View File
@@ -125,6 +125,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
RegionEntry* recv_pkt_region;
TransportKey default_scope;
unsigned long set_radio_at, revert_radio_at;
unsigned long _ota_update_at = 0; // deferred `ota update` fire time (0 = none scheduled)
float pending_freq;
float pending_bw;
uint8_t pending_sf;
@@ -352,6 +353,15 @@ public:
#endif
}
// Schedule the pull-OTA flash to run from loop() in ~2.5 s, leaving time for the
// "Beginning update..." CLI reply (CLI_REPLY_DELAY_MILLIS = 600 ms) to transmit
// before the flash blocks the loop and reboots.
bool beginDeferredOtaUpdate() override {
_ota_update_at = millis() + 2500;
if (_ota_update_at == 0) _ota_update_at = 1; // 0 means "none"
return true;
}
int getQueueSize() override {
return bridge ? bridge->getQueueSize() : 0;
}