+
{/* ── Status bar ────────────────────────────────────────────────────── */}
@@ -419,6 +491,135 @@ export default function ControlTab({ device, attr, canEdit, isOnline, sendMqttCo
+ {/* ── Firmware ────────────────────────────────────────────────────── */}
+
}
+ >
+
+
+ {/* Current status summary */}
+
+
+ {firmwareStatus && (
+ <>
+
+ {firmwareStatus.validation_state || '—'}
+
+
+ Boot count: {Number.isFinite(firmwareStatus.boot_count) ? firmwareStatus.boot_count : '—'}
+
+ >
+ )}
+
+
+
+
+ {/* Commit / rollback */}
+
+
+
+
+
+
+
+ {/* OTA channel + update */}
+
+
+
+ handleChangeChannel(e.target.value)}
+ disabled={disabled}
+ >
+ {OTA_CHANNELS.map(c => (
+
+ ))}
+
+
+
+
+
+
+ {/* Custom OTA URL */}
+
+
+
+ setCustomUrl(e.target.value)}
+ placeholder="http://example.com/firmware.bin"
+ disabled={disabled}
+ />
+
+
+
+
+
+
+
+
{/* ── Confirm dialogs ───────────────────────────────────────────────── */}
@@ -452,6 +653,39 @@ export default function ControlTab({ device, attr, canEdit, isOnline, sendMqttCo
sendMqttCommand={sendMqttCommand}
/>
+