From 037e8f095204274a871c5053d7ceb5ef3b15d5d7 Mon Sep 17 00:00:00 2001 From: Strycher Date: Tue, 14 Jul 2026 00:28:39 -0400 Subject: [PATCH] feat(#176): OFFBAND_CAP_BLOCK detection (supportsOffbandBlock) offbandCapBlock=0x02 + firmwareSupportsOffbandBlock(caps, verCode): requires the explicit bit AND FIRMWARE_VER_CODE>=15 (per firmware as-built PR #247). Connector exposes supportsOffbandBlock; absent -> app-local block only. Mirrors the 0xC1 GPS capability pattern. Epic B #166 / B1 #176. Design: docs/architecture/block-contract-as-built.md. Co-Authored-By: Claude Opus 4.8 --- lib/connector/meshcore_connector.dart | 5 +++++ lib/connector/meshcore_protocol.dart | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/lib/connector/meshcore_connector.dart b/lib/connector/meshcore_connector.dart index 7cfb7be..dd808a5 100644 --- a/lib/connector/meshcore_connector.dart +++ b/lib/connector/meshcore_connector.dart @@ -540,6 +540,11 @@ class MeshCoreConnector extends ChangeNotifier { /// advertised the Offband-fork `offband_caps` byte. Stock MeshCore omits it, /// so 0xC1 is suppressed there rather than pinged blindly. (#144) bool get supportsOffbandGps => firmwareSupportsOffbandGps(_offbandCaps); + + /// Whether the connected radio persists a block list + drops blocked DMs + /// (Offband firmware, capability-gated). Absent → app-local block only. + bool get supportsOffbandBlock => + firmwareSupportsOffbandBlock(_offbandCaps, _firmwareVerCode); Map? get currentCustomVars => _currentCustomVars; int? get batteryMillivolts => _batteryMillivolts; int? get storageUsedKb => _storageUsedKb; diff --git a/lib/connector/meshcore_protocol.dart b/lib/connector/meshcore_protocol.dart index e9e6c83..77a551b 100644 --- a/lib/connector/meshcore_protocol.dart +++ b/lib/connector/meshcore_protocol.dart @@ -274,6 +274,18 @@ Uint8List buildOffbandGpsRequestFrame() => Uint8List.fromList([cmdOffbandGps]); /// defines one, any Offband v14+ radio is assumed to speak `0xC1`. bool firmwareSupportsOffbandGps(int? offbandCaps) => offbandCaps != null; +/// `OFFBAND_CAP_BLOCK` bit (bit 1) in the `offband_caps` byte of the device-info +/// reply: an Offband radio that persists a block list and drops blocked DMs at +/// receive (firmware PR #247, `FIRMWARE_VER_CODE 15`). Unlike the loose GPS +/// presence-gate above, block requires the **explicit bit** set AND +/// `FIRMWARE_VER_CODE >= 15`; absent → app-only mode (no sync, no firmware drop). +const int offbandCapBlock = 0x02; + +bool firmwareSupportsOffbandBlock(int? offbandCaps, int? firmwareVerCode) => + offbandCaps != null && + (offbandCaps & offbandCapBlock) != 0 && + (firmwareVerCode ?? 0) >= 15; + const int statsTypeCore = 0; const int statsTypeRadio = 1; const int statsTypePackets = 2;