Skip to content

Commit c936376

Browse files
authored
OTA Updates based on tags created via git (#159)
* OTA Updates based on tags created via git * Fixes from code review
1 parent 8510b52 commit c936376

18 files changed

Lines changed: 1054 additions & 17 deletions

Docs/Commands.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ These are commands used to configure the system settings and can only be sent fr
1818
| `F9` — SD Card Log File Size | `F9` | Get current log file size in bytes. Returns `v=<bytes>` where bytes is the size of the active log file. Returns `v=0` if no file is open. No params. |
1919
| `F10` — RTC Diagnostic | `F10` | Perform DS1302 RTC diagnostics. Returns status message with RTC health (availability, running state, write protection, time validity). Returns error message if RTC fails any check. No params. |
2020
| `F11` — Uptime | F11 | Returns system uptime as "days HH:MM:SS" (e.g. 2d 03:12:45). No params. |
21+
| `F12` — OTA Check / Apply | `F12` or `F12:apply=1` | Trigger an OTA firmware check against the latest GitHub release. Without params (or `apply=0`) checks only and returns current status. With `apply=1` downloads and applies the update if one is available (or queues apply if a check is already in progress). Response params: `v=<current>` current firmware version, `av=<available>` available version tag (empty if none found yet), `s=<state>` OTA state string. **SFB only** — requires `OTA_AUTO_UPDATE`, ESP32 and WiFi in client mode. |
22+
| `F13` — OTA Status | `F13` | Query current OTA state without triggering a check. Response params: `v=<current>` current firmware version, `av=<available>` available version tag, `s=<state>` OTA state string (`idle`, `checking`, `available`, `downloading`, `rebooting`, `failed`, `uptodate`), `auto=<0\|1>` whether auto-apply is enabled. **SFB only** — requires `OTA_AUTO_UPDATE`, ESP32 and WiFi in client mode. |
2123

2224
**Heartbeat Behavior:**
2325
- Sent every 1 second (1000ms) from both devices
@@ -30,7 +32,17 @@ These are commands used to configure the system settings and can only be sent fr
3032
### Wifi System Commands (SFB)
3133
Only F0 is supported via wifi.
3234
Route: /api/system/{command}
33-
Example: Return free memory = /api/system/F2
35+
Example: Return free memory = /api/system/F2
36+
37+
### OTA Behavior (F12 / F13)
38+
- Automatic periodic check runs every 24 hours (first check fires 24 h after boot to allow WiFi to fully connect).
39+
- F12 without params (or `apply=0`) triggers an immediate check and broadcasts the result — it does **not** apply the update automatically.
40+
- F12 with `apply=1` downloads and applies immediately if an update is available; if a check is still in progress the apply is queued.
41+
- Auto-apply on each periodic check is **off by default**; enable it by setting bit `OtaFlagAutoApply (0x01)` in `SystemHeader::reserved[0]`.
42+
- State transitions broadcast an `F12` command automatically as they occur (e.g. `checking``available``downloading``rebooting`).
43+
- Debug and error messages are broadcast via the debug channel with source `OTA` at each key milestone: API query, tag found/not found, checksum fetch, binary size, download progress (25 / 50 / 75%), hash verification, and reboot.
44+
- F13 is read-only — it never triggers any OTA activity.
45+
- OTA is only active when `OTA_AUTO_UPDATE` is defined, the board is an ESP32, `WIFI_SUPPORT` is defined, and WiFi is in connected client mode.
3446

3547

3648
------

SmartFuseBox/BoardConfig.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,13 @@
8383
#if defined(ARDUINO_UNO_R4) && defined(WIFI_SUPPORT) && defined(BLUETOOTH_SUPPORT)
8484
#error "WIFI_SUPPORT and BLUETOOTH_SUPPORT cannot both be active on Arduino Uno R4. Disable one in Local.h."
8585
#endif
86+
87+
// ─── OTA Auto-Update Guard ───────────────────────────────────────────────────
88+
// OTA requires ESP32 (Update library) and an active WiFi client connection.
89+
// Silently strip the define on unsupported boards instead of erroring, so that
90+
// the same Local.h can be used across board types without manual edits.
91+
#if defined(OTA_AUTO_UPDATE)
92+
#if !defined(ESP32) || !defined(WIFI_SUPPORT)
93+
#undef OTA_AUTO_UPDATE
94+
#endif
95+
#endif

SmartFuseBox/Config.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ constexpr uint8_t ConfigMaxSensorPins = 4;
4444

4545
constexpr uint32_t SystemHeaderMagic = 0x53464201; // 'SFB\x01'
4646

47+
// Flags stored in SystemHeader::reserved[0]
48+
constexpr uint8_t OtaFlagAutoApply = 0x01; // bit0: automatically download and apply updates
49+
4750
struct SystemHeader {
4851
uint32_t magic; // offset 0 — must equal SystemHeaderMagic
4952
uint32_t bootCount; // offset 4
@@ -52,7 +55,7 @@ struct SystemHeader {
5255
uint8_t crashCounter; // offset 11
5356
uint8_t lastResetReason; // offset 12
5457
uint8_t safeModeFlagsf; // offset 13
55-
uint8_t reserved[16]; // offset 14
58+
uint8_t reserved[16]; // offset 14 — reserved[0] = OTA flags (see OtaFlagAutoApply)
5659
uint16_t checksum; // offset 30 — always last
5760
} __attribute__((packed)); // = 32 bytes
5861

SmartFuseBox/Dht11SensorHandler.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ class Dht11SensorHandler : public BaseSensor, public BroadcastLoggerSupport
119119
_warningManager(warningManager), _sensorPin(sensorPin), _dht11Sensor(sensorPin), _humidityOffset(humidityOffset),
120120
_temperatureOffset(temperatureOffset), _humidity(0.0f), _celsius(0.0f)
121121
{
122+
_dht11Sensor.setDelay(0);
122123
#if defined(MQTT_SUPPORT)
123124
snprintf(_slugTemp, sizeof(_slugTemp), "%s_temperature", _safeSlug);
124125
snprintf(_slugHumidity, sizeof(_slugHumidity), "%s_humidity", _safeSlug);
@@ -144,8 +145,8 @@ class Dht11SensorHandler : public BaseSensor, public BroadcastLoggerSupport
144145
dtostrf(_temperatureOffset, 1, 1, celsiusOffset);
145146
dtostrf(_humidityOffset, 1, 1, humidityOffset);
146147

147-
int written = snprintf(buffer, size, "\"name\":\"%s\",\"SensorPin\":%u,\"temperature\":%s,\"humidity\":%s,\"humOffset\":%s,\"tempOffset\":%s",
148-
_name, _sensorPin, celsius, humidity, humidityOffset, celsiusOffset);
148+
int written = snprintf(buffer, size, "\"name\":\"%s\",\"SensorPin\":%u,\"temperature\":%s,\"tempOffset\":%s,\"humidity\":%s,\"humOffset\":%s",
149+
_name, _sensorPin, celsius, celsiusOffset, humidity, humidityOffset);
149150

150151
if (written < 0 || (size_t)written >= size)
151152
{

SmartFuseBox/FirmwareVersion.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* SmartFuseBox
3+
* Copyright (C) 2025 Simon Carter (s1cart3r@gmail.com)
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
#pragma once
19+
#include <Arduino.h>
20+
21+
// Firmware version constants.
22+
// On release builds these values are overwritten by the CI workflow from the
23+
// git tag (v<major>.<minor>.<patch>.<build>) — do not edit the four lines below.
24+
// For local/development builds these fallback values are used instead.
25+
constexpr uint8_t FirmwareMajor = 0;
26+
constexpr uint8_t FirmwareMinor = 9;
27+
constexpr uint8_t FirmwarePatch = 0;
28+
constexpr uint8_t FirmwareBuild = 3;

SmartFuseBox/Local.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@
6868
// MQTT home-assistant discovery (requires WIFI_SUPPORT — enforced in BoardConfig.h)
6969
#define MQTT_SUPPORT
7070

71+
// OTA auto-update via GitHub releases (requires ESP32 + WIFI_SUPPORT — enforced in BoardConfig.h).
72+
// When enabled, the device checks for a new release every 24 hours and broadcasts the result.
73+
// Auto-applying the update is OFF by default; use the F12:apply=1 command or set the
74+
// OtaFlagAutoApply bit in SystemHeader::reserved[0] to enable automatic installs.
75+
#define OTA_AUTO_UPDATE
76+
7177
// Bluetooth BLE (mutually exclusive with WIFI_SUPPORT on Arduino Uno R4)
7278
#define BLUETOOTH_SUPPORT_
7379

0 commit comments

Comments
 (0)