From e0cb9536af6fc97b29f8be17bb4402b6ed11b6ea Mon Sep 17 00:00:00 2001 From: uvtqt Date: Fri, 13 Nov 2026 09:28:09 +0100 Subject: [PATCH 1/3] Name the 50.43 firmware data lock instead of advising a charger cycle A WHOOP 5.0 / MG band on firmware 50.43.x answers commands but sends no history or live data until a WHOOP-signed membership token is on it (#673). The stuck-strap and empty-sync flags trip for it, and the status told the user to charge or re-pair, neither of which can help. With the firmware from the gen5 HELLO kept on DeviceState, bandStatusFor names the lock instead. The firmware also goes into support report bundles. --- lib/ble/band_status_l10n.dart | 7 ++++++ lib/ble/ble_engine.dart | 2 ++ lib/ble/ble_state.dart | 32 ++++++++++++++++++++++++ lib/data/models.dart | 4 +++ lib/l10n/app_de.arb | 5 +++- lib/l10n/app_en.arb | 14 ++++++++++- lib/l10n/app_es.arb | 5 +++- lib/l10n/app_fr.arb | 5 +++- lib/l10n/app_hi.arb | 5 +++- lib/l10n/app_ru.arb | 5 +++- lib/l10n/app_th.arb | 5 +++- lib/l10n/app_zh.arb | 5 +++- lib/support/issue_report.dart | 1 + test/ble_state_test.dart | 46 +++++++++++++++++++++++++++++++++++ 14 files changed, 133 insertions(+), 8 deletions(-) diff --git a/lib/ble/band_status_l10n.dart b/lib/ble/band_status_l10n.dart index 5267a476b..b77af69c4 100644 --- a/lib/ble/band_status_l10n.dart +++ b/lib/ble/band_status_l10n.dart @@ -70,6 +70,13 @@ BandStatus localizedBandStatus(BuildContext c, BandStatus s) { l?.bandStatusClockLostReason ?? s.reason, fix: l?.bandStatusClockLostFix ?? s.fix, ); + case BandCondition.firmwareLocked: + return BandStatus( + s.condition, + l?.bandStatusFirmwareLockedTitle ?? s.title, + l?.bandStatusFirmwareLockedReason ?? s.reason, + fix: l?.bandStatusFirmwareLockedFix ?? s.fix, + ); case BandCondition.connected: return BandStatus( s.condition, diff --git a/lib/ble/ble_engine.dart b/lib/ble/ble_engine.dart index 21109483f..81f81fc58 100644 --- a/lib/ble/ble_engine.dart +++ b/lib/ble/ble_engine.dart @@ -2817,6 +2817,7 @@ class BleEngine { strapNeedsReboot: state.strapNeedsReboot, syncClockLost: state.syncClockLost, bondRefusals: state.bondRefusals, + bandFirmware: state.firmware, ); /// Read past pre-init/resetting states without an unbounded startup await. @@ -6176,6 +6177,7 @@ class BleEngine { if (h.batteryPct != null) state.batteryPct = h.batteryPct!.toDouble(); state.charging = h.charging; state.wristOn = h.wristOn; + state.firmware = h.firmwareVersion; onState(state); unawaited(LocalDb.noteBandFirmware(h.firmwareVersion)); _log('[HELLO gen5] serial=${h.serial} fw=${h.firmwareVersion} ' diff --git a/lib/ble/ble_state.dart b/lib/ble/ble_state.dart index 6641f3284..addc5385d 100644 --- a/lib/ble/ble_state.dart +++ b/lib/ble/ble_state.dart @@ -223,6 +223,10 @@ enum BandCondition { /// Syncs complete carrying no sensor data — the band's clock has lost sync. clockLost, + /// The band is on a firmware that withholds all data until a WHOOP-signed + /// membership token is on it (edge#673), and no data is arriving. + firmwareLocked, + connected, connecting, scanning, @@ -271,6 +275,16 @@ class BandStatus { bool isLinkAuthRefusal(int? code) => code == 5 || code == 8 || code == 15 || code == 137; +/// True for WHOOP 5.0 / MG firmware 50.43.x, which keeps answering commands +/// but sends no history or live data until a WHOOP-signed membership token is +/// on the band (edge#673, captured on 50.43.1.0; reported on 50.43.2.0). +/// [firmware] is `Gen5HelloInfo.firmwareVersion` (`major.minor.build.x`). +// ponytail: a version prefix, not a probe for the token itself. A later +// firmware with the same lock needs adding here; one that lifts it on 50.43 +// still only shows this while the data flags below are tripped. +bool isDataLockedFirmware(String? firmware) => + firmware != null && firmware.startsWith('50.43.'); + /// Fold the phone-level blocker and the band's own diagnostic flags into one /// state. Pure; [connection] is `DeviceState.connection`. /// @@ -287,6 +301,7 @@ BandStatus bandStatusFor({ bool strapNeedsReboot = false, bool syncClockLost = false, int bondRefusals = 0, + String? bandFirmware, }) { const repairFix = 'Forget the band in the phone’s Bluetooth settings, ' 'then pair it again here'; @@ -355,6 +370,23 @@ BandStatus bandStatusFor({ fix: 'Reconnect the band; if it repeats tomorrow, pair it again', ); } + // The same two "no data is arriving" flags, explained by the firmware + // instead: a charger cycle or a re-pair cannot help a band that withholds + // its data by design, and both flags clear once records bank again. + if ((strapNeedsReboot || syncClockLost) && + isDataLockedFirmware(bandFirmware)) { + return const BandStatus( + BandCondition.firmwareLocked, + 'The band’s firmware is holding back its data', + 'This band runs WHOOP firmware 50.43, which connects and answers the ' + 'app but sends no recordings or live heart rate until a ' + 'WHOOP-signed membership token is on it. OpenStrap cannot issue ' + 'that token. Everything already saved here is safe, and the band ' + 'keeps recording.', + fix: 'Re-pairing or charging will not help. This clears by itself once ' + 'the band sends data again', + ); + } if (strapNeedsReboot) { return const BandStatus( BandCondition.strapUnresponsive, diff --git a/lib/data/models.dart b/lib/data/models.dart index 35b772a14..99dbd79a2 100644 --- a/lib/data/models.dart +++ b/lib/data/models.dart @@ -419,6 +419,9 @@ class DeviceState { /// EmptySyncTracker tripped: ≥3 consecutive console-only offloads — the strap's /// RTC has likely lost sync. bool syncClockLost = false; + /// Firmware the gen5 HELLO reported on this connection (`50.43.2.0`), null + /// until one has. Read by `bandStatusFor` to name a firmware data lock. + String? firmware; /// StuckStrapDetector tripped: frontier frozen while the strap is ahead — a /// defensive reboot/clock-reset was attempted. bool strapNeedsReboot = false; @@ -475,6 +478,7 @@ class DeviceState { bondRefusals = 0; autoReconnectPaused = false; syncClockLost = false; + firmware = null; strapNeedsReboot = false; syncChunkQuarantined = false; dataRangeOldest = null; diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 233bed5aa..ff29c7f3f 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -3545,5 +3545,8 @@ "stepCalDoneHousehold": "Gespeichert. Dein Smartphone hat {count} der {band} Schritte gezählt, die das Band erkannt hat. Bewegung im Haushalt wird jetzt auf {gain} skaliert.", "whoopFirmwareWarningTitle": "WHOOP-Nutzer: Verbinde dich nicht wieder mit der WHOOP-App", "whoopFirmwareWarningAction": "Wenn du OpenStrap oder eine andere Open-Source-App nutzt oder später zu einer wechseln möchtest, verbinde dein Band nicht wieder mit der offiziellen WHOOP-App. Sie kann Firmware-Updates automatisch installieren. Deinstalliere oder deaktiviere die WHOOP-App, damit sie dein Band nicht aktualisiert.", - "whoopFirmwareWarningDetails": "Berichte zur WHOOP 5.0 / MG Firmware 50.43.1.0 und 50.43.2.0 beschreiben einen blockierten Datenzugriff. Bluetooth kann sich weiterhin verbinden. OpenStrap kann das von WHOOP signierte Mitgliedschafts-Token nicht ausstellen, das betroffene Bänder entsperrt. Wir arbeiten an einer Lösung, aber es gibt noch keine Abhilfe." + "whoopFirmwareWarningDetails": "Berichte zur WHOOP 5.0 / MG Firmware 50.43.1.0 und 50.43.2.0 beschreiben einen blockierten Datenzugriff. Bluetooth kann sich weiterhin verbinden. OpenStrap kann das von WHOOP signierte Mitgliedschafts-Token nicht ausstellen, das betroffene Bänder entsperrt. Wir arbeiten an einer Lösung, aber es gibt noch keine Abhilfe.", + "bandStatusFirmwareLockedTitle": "Die Firmware des Bands hält seine Daten zurück", + "bandStatusFirmwareLockedReason": "Dieses Band läuft mit WHOOP-Firmware 50.43. Sie verbindet sich und antwortet der App, sendet aber keine Aufzeichnungen und keine Live-Herzfrequenz, solange kein von WHOOP signiertes Mitgliedschafts-Token auf dem Band ist. OpenStrap kann dieses Token nicht ausstellen. Alles, was hier schon gespeichert ist, bleibt erhalten, und das Band zeichnet weiter auf.", + "bandStatusFirmwareLockedFix": "Neu koppeln oder Laden hilft nicht. Das verschwindet von selbst, sobald das Band wieder Daten sendet" } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index ec5231ef9..fb409c16e 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -16398,5 +16398,17 @@ "strengthDelete": "Delete", "@strengthDelete": {"description": "Strength set editor copy."}, "strengthSaveFailed": "Failed to save changes", - "@strengthSaveFailed": {"description": "Strength set editor copy."} + "@strengthSaveFailed": {"description": "Strength set editor copy."}, + "bandStatusFirmwareLockedTitle": "The band’s firmware is holding back its data", + "@bandStatusFirmwareLockedTitle": { + "description": "BandStatus card title: band firmware 50.43 withholds all data until a WHOOP membership token is on it" + }, + "bandStatusFirmwareLockedReason": "This band runs WHOOP firmware 50.43, which connects and answers the app but sends no recordings or live heart rate until a WHOOP-signed membership token is on it. OpenStrap cannot issue that token. Everything already saved here is safe, and the band keeps recording.", + "@bandStatusFirmwareLockedReason": { + "description": "BandStatus card body: band firmware 50.43 withholds all data until a WHOOP membership token is on it" + }, + "bandStatusFirmwareLockedFix": "Re-pairing or charging will not help. This clears by itself once the band sends data again", + "@bandStatusFirmwareLockedFix": { + "description": "BandStatus fix action: band firmware 50.43 withholds all data until a WHOOP membership token is on it" + } } diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index a236842ec..cf3287237 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -3245,5 +3245,8 @@ "stepCalDoneHousehold": "Guardado. Tu teléfono contó {count} de los {band} pasos que vio la banda. El movimiento en casa ahora se escala a {gain}.", "whoopFirmwareWarningTitle": "Usuarios de WHOOP: no vuelvas a conectarte a la app de WHOOP", "whoopFirmwareWarningAction": "Si usas OpenStrap u otra app de código abierto, o piensas cambiarte a una más adelante, no vuelvas a conectar tu banda a la app oficial de WHOOP. Puede instalar actualizaciones de firmware automáticamente. Desinstala o desactiva la app de WHOOP para evitar que actualice tu banda.", - "whoopFirmwareWarningDetails": "Hay informes de que el firmware 50.43.1.0 y 50.43.2.0 de WHOOP 5.0 / MG bloquea el acceso a los datos. Es posible que el Bluetooth siga conectándose. OpenStrap no puede emitir el token de membresía firmado por WHOOP que se necesita para desbloquear las bandas afectadas. Estamos trabajando en una solución, pero todavía no hay ningún arreglo disponible." + "whoopFirmwareWarningDetails": "Hay informes de que el firmware 50.43.1.0 y 50.43.2.0 de WHOOP 5.0 / MG bloquea el acceso a los datos. Es posible que el Bluetooth siga conectándose. OpenStrap no puede emitir el token de membresía firmado por WHOOP que se necesita para desbloquear las bandas afectadas. Estamos trabajando en una solución, pero todavía no hay ningún arreglo disponible.", + "bandStatusFirmwareLockedTitle": "El firmware de la banda está reteniendo sus datos", + "bandStatusFirmwareLockedReason": "Esta banda usa el firmware 50.43 de WHOOP, que se conecta y responde a la app, pero no envía registros ni frecuencia cardíaca en vivo hasta que haya en ella un token de membresía firmado por WHOOP. OpenStrap no puede emitir ese token. Todo lo que ya está guardado aquí está a salvo, y la banda sigue registrando.", + "bandStatusFirmwareLockedFix": "Volver a emparejarla o cargarla no servirá. Esto desaparece solo cuando la banda vuelva a enviar datos" } diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 2875f5709..d3aa988fe 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -2895,5 +2895,8 @@ "pairBandNotSensor": "Cet appareil est un {label}, c’est-à-dire un bracelet, pas un simple capteur. Rien n’a été enregistré.", "whoopFirmwareWarningTitle": "Utilisateurs WHOOP : ne vous reconnectez pas à l’application WHOOP", "whoopFirmwareWarningAction": "Si vous utilisez OpenStrap ou une autre application open source, ou si vous comptez y passer plus tard, ne reconnectez pas votre bracelet à l’application WHOOP officielle. Elle peut installer des mises à jour du firmware automatiquement. Désinstallez ou désactivez l’application WHOOP pour l’empêcher de mettre à jour votre bracelet.", - "whoopFirmwareWarningDetails": "Des signalements concernant les firmwares 50.43.1.0 et 50.43.2.0 des WHOOP 5.0 / MG décrivent un accès aux données bloqué. Le Bluetooth peut encore se connecter. OpenStrap ne peut pas émettre le jeton d’abonnement signé par WHOOP nécessaire pour déverrouiller les bracelets concernés. Nous travaillons sur une solution, mais aucun correctif n’est encore disponible." + "whoopFirmwareWarningDetails": "Des signalements concernant les firmwares 50.43.1.0 et 50.43.2.0 des WHOOP 5.0 / MG décrivent un accès aux données bloqué. Le Bluetooth peut encore se connecter. OpenStrap ne peut pas émettre le jeton d’abonnement signé par WHOOP nécessaire pour déverrouiller les bracelets concernés. Nous travaillons sur une solution, mais aucun correctif n’est encore disponible.", + "bandStatusFirmwareLockedTitle": "Le firmware du bracelet retient ses données", + "bandStatusFirmwareLockedReason": "Ce bracelet utilise le firmware WHOOP 50.43, qui se connecte et répond à l’application mais n’envoie ni enregistrements ni fréquence cardiaque en direct tant qu’un jeton d’abonnement signé par WHOOP n’est pas présent sur le bracelet. OpenStrap ne peut pas émettre ce jeton. Tout ce qui est déjà enregistré ici est en sécurité, et le bracelet continue d’enregistrer.", + "bandStatusFirmwareLockedFix": "Le jumeler à nouveau ou le recharger n’y changera rien. Ce message disparaît de lui-même dès que le bracelet renvoie des données" } diff --git a/lib/l10n/app_hi.arb b/lib/l10n/app_hi.arb index b9fea6734..11350b7f0 100644 --- a/lib/l10n/app_hi.arb +++ b/lib/l10n/app_hi.arb @@ -2895,5 +2895,8 @@ "pairBandNotSensor": "यह डिवाइस {label} है, यानी एक बैंड, साधारण सेंसर नहीं। कुछ भी सहेजा नहीं गया।", "whoopFirmwareWarningTitle": "WHOOP उपयोगकर्ता: WHOOP ऐप से दोबारा कनेक्ट न करें", "whoopFirmwareWarningAction": "अगर आप OpenStrap या कोई दूसरा ओपन-सोर्स ऐप इस्तेमाल करते हैं, या बाद में किसी पर जाने की सोच रहे हैं, तो अपना बैंड आधिकारिक WHOOP ऐप से दोबारा कनेक्ट न करें। वह फ़र्मवेयर अपडेट अपने-आप इंस्टॉल कर सकता है। WHOOP ऐप को अनइंस्टॉल या अक्षम कर दें, ताकि वह आपके बैंड को अपडेट न कर सके।", - "whoopFirmwareWarningDetails": "WHOOP 5.0 / MG के फ़र्मवेयर 50.43.1.0 और 50.43.2.0 के बारे में रिपोर्टें बताती हैं कि डेटा तक पहुँच रोक दी जाती है। ब्लूटूथ फिर भी कनेक्ट हो सकता है। प्रभावित बैंड को अनलॉक करने के लिए WHOOP द्वारा साइन किया गया मेंबरशिप टोकन चाहिए, जिसे OpenStrap जारी नहीं कर सकता। हम समाधान पर काम कर रहे हैं, लेकिन अभी कोई उपाय उपलब्ध नहीं है।" + "whoopFirmwareWarningDetails": "WHOOP 5.0 / MG के फ़र्मवेयर 50.43.1.0 और 50.43.2.0 के बारे में रिपोर्टें बताती हैं कि डेटा तक पहुँच रोक दी जाती है। ब्लूटूथ फिर भी कनेक्ट हो सकता है। प्रभावित बैंड को अनलॉक करने के लिए WHOOP द्वारा साइन किया गया मेंबरशिप टोकन चाहिए, जिसे OpenStrap जारी नहीं कर सकता। हम समाधान पर काम कर रहे हैं, लेकिन अभी कोई उपाय उपलब्ध नहीं है।", + "bandStatusFirmwareLockedTitle": "बैंड का फ़र्मवेयर उसका डेटा रोक रहा है", + "bandStatusFirmwareLockedReason": "यह बैंड WHOOP फ़र्मवेयर 50.43 पर चल रहा है, जो कनेक्ट होता है और ऐप को जवाब देता है, लेकिन जब तक बैंड पर WHOOP द्वारा साइन किया गया सदस्यता टोकन न हो, तब तक कोई रिकॉर्डिंग या लाइव हृदय गति नहीं भेजता। OpenStrap वह टोकन जारी नहीं कर सकता। यहाँ पहले से सहेजा गया सब कुछ सुरक्षित है, और बैंड रिकॉर्ड करता रहता है।", + "bandStatusFirmwareLockedFix": "दोबारा पेयर करने या चार्ज करने से मदद नहीं मिलेगी। बैंड के फिर से डेटा भेजते ही यह अपने-आप हट जाएगा" } diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index f25901a16..759860c05 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -7943,5 +7943,8 @@ "type": "String" } } - } + }, + "bandStatusFirmwareLockedTitle": "Прошивка браслета удерживает его данные", + "bandStatusFirmwareLockedReason": "На этом браслете прошивка WHOOP 50.43: он подключается и отвечает приложению, но не передаёт ни записи, ни пульс в реальном времени, пока на нём нет подписанного WHOOP токена подписки. OpenStrap не может выпустить такой токен. Всё, что уже сохранено здесь, в безопасности, а браслет продолжает запись.", + "bandStatusFirmwareLockedFix": "Повторное сопряжение или зарядка не помогут. Сообщение исчезнет само, как только браслет снова начнёт передавать данные" } diff --git a/lib/l10n/app_th.arb b/lib/l10n/app_th.arb index 19e7265dd..7858f3ed5 100644 --- a/lib/l10n/app_th.arb +++ b/lib/l10n/app_th.arb @@ -16365,5 +16365,8 @@ "type": "String" } } - } + }, + "bandStatusFirmwareLockedTitle": "เฟิร์มแวร์ของสายรัดกำลังกักข้อมูลไว้", + "bandStatusFirmwareLockedReason": "สายรัดนี้ใช้เฟิร์มแวร์ WHOOP 50.43 ซึ่งเชื่อมต่อและตอบสนองแอปได้ แต่จะไม่ส่งข้อมูลที่บันทึกไว้หรืออัตราการเต้นของหัวใจแบบสด จนกว่าจะมีโทเค็นสมาชิกที่ WHOOP ลงนามอยู่บนสายรัด OpenStrap ไม่สามารถออกโทเค็นนั้นได้ ข้อมูลทั้งหมดที่บันทึกไว้ที่นี่แล้วยังปลอดภัย และสายรัดยังคงบันทึกต่อไป", + "bandStatusFirmwareLockedFix": "การจับคู่ใหม่หรือการชาร์จจะไม่ช่วย ข้อความนี้จะหายไปเองเมื่อสายรัดส่งข้อมูลอีกครั้ง" } diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 111dc74e2..d1343f319 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -2895,5 +2895,8 @@ "pairBandNotSensor": "这台设备是 {label},是手环,不是普通传感器。没有保存任何内容。", "whoopFirmwareWarningTitle": "WHOOP 用户:请勿重新连接 WHOOP 应用", "whoopFirmwareWarningAction": "如果你在使用 OpenStrap 或其他开源应用,或打算以后改用,请不要再把手环连接到 WHOOP 官方应用。它可能会自动安装固件更新。请卸载或停用 WHOOP 应用,以免它更新你的手环。", - "whoopFirmwareWarningDetails": "有报告称,WHOOP 5.0 / MG 固件 50.43.1.0 和 50.43.2.0 会阻止访问数据。蓝牙可能仍能连接。解锁受影响的手环需要由 WHOOP 签名的会员令牌,OpenStrap 无法签发。我们正在寻找解决办法,但目前还没有可用的修复。" + "whoopFirmwareWarningDetails": "有报告称,WHOOP 5.0 / MG 固件 50.43.1.0 和 50.43.2.0 会阻止访问数据。蓝牙可能仍能连接。解锁受影响的手环需要由 WHOOP 签名的会员令牌,OpenStrap 无法签发。我们正在寻找解决办法,但目前还没有可用的修复。", + "bandStatusFirmwareLockedTitle": "手环固件正在扣留它的数据", + "bandStatusFirmwareLockedReason": "这个手环运行的是 WHOOP 固件 50.43:它能连接并响应应用,但在手环上没有 WHOOP 签名的会员令牌之前,不会发送任何记录或实时心率。OpenStrap 无法签发这个令牌。已保存在这里的所有数据都是安全的,手环也会继续记录。", + "bandStatusFirmwareLockedFix": "重新配对或充电都无济于事。手环重新发送数据后,此提示会自动消失" } diff --git a/lib/support/issue_report.dart b/lib/support/issue_report.dart index 219a64931..d998ff6ec 100644 --- a/lib/support/issue_report.dart +++ b/lib/support/issue_report.dart @@ -317,6 +317,7 @@ Future<({File zip, Map meta})> collectReport( 'syncClockLost': d.syncClockLost, 'strapNeedsReboot': d.strapNeedsReboot, 'syncChunkQuarantined': d.syncChunkQuarantined, + 'bandFirmware': d.firmware, 'initError': app.initError, 'importRollupError': app.importRollupError, 'lastBackupError': app.lastBackupError, diff --git a/test/ble_state_test.dart b/test/ble_state_test.dart index e45ea0500..ecf04ed6e 100644 --- a/test/ble_state_test.dart +++ b/test/ble_state_test.dart @@ -638,6 +638,10 @@ void main() { bandStatusFor(connection: 'connected', syncChunkQuarantined: true), bandStatusFor(connection: 'connected', strapNeedsReboot: true), bandStatusFor(connection: 'connected', syncClockLost: true), + bandStatusFor( + connection: 'connected', + strapNeedsReboot: true, + bandFirmware: '50.43.2.0'), ]; for (final s in faults) { expect(s.isFault, isTrue, reason: '${s.condition}'); @@ -712,6 +716,48 @@ void main() { ); }); + test('a 50.43 band that sends nothing is named by its firmware (#673)', () { + for (final flags in [ + (stuck: true, clock: false), + (stuck: false, clock: true), + ]) { + final s = bandStatusFor( + connection: 'connected', + strapNeedsReboot: flags.stuck, + syncClockLost: flags.clock, + bandFirmware: '50.43.2.0', + ); + expect(s.condition, BandCondition.firmwareLocked, reason: '$flags'); + expect(s.isFault, isTrue); + expect(s.reason, contains('50.43')); + // Charging or re-pairing is the advice for the other two flags; for a + // locked band it is the wrong instruction. + expect(s.fix, startsWith('Re-pairing or charging will not help')); + } + }); + + test('firmware alone is not a fault, and other firmware keeps its advice', + () { + // A token-unlocked 50.43 band that is syncing shows as connected. + expect( + bandStatusFor(connection: 'connected', bandFirmware: '50.43.1.0') + .condition, + BandCondition.connected, + ); + expect( + bandStatusFor( + connection: 'connected', + strapNeedsReboot: true, + bandFirmware: '50.38.1.0', + ).condition, + BandCondition.strapUnresponsive, + ); + expect(isDataLockedFirmware(null), isFalse); + expect(isDataLockedFirmware('50.43.1.0'), isTrue); + expect(isDataLockedFirmware('50.430.0.0'), isFalse); + expect(isDataLockedFirmware('5.43.0.0'), isFalse); + }); + test('the ordinary link states are not faults', () { for (final c in ['connected', 'connecting', 'scanning', 'disconnected']) { expect(bandStatusFor(connection: c).isFault, isFalse, reason: c); From 2e19ff3d406dc1e582fe1c161629fe9a923097a1 Mon Sep 17 00:00:00 2001 From: uvtqt Date: Fri, 13 Nov 2026 15:22:04 +0100 Subject: [PATCH 2/3] Firmware lock: hedge the cause, clear stale firmware on other HELLOs The no-data flags cannot tell a 50.43 token lock from a real strap or clock fault, so the status now says the firmware is "probably" the cause and only rules out re-pairing/charging if it is (all 8 locales). A non-revision-1 HELLO now clears DeviceState.firmware instead of leaving an earlier HELLO's version to drive the lock status. The rev-3 reader stays diagnostics-only. Co-Authored-By: Claude Opus 5.5 --- lib/ble/ble_engine.dart | 5 +++++ lib/ble/ble_state.dart | 22 +++++++++++++--------- lib/l10n/app_de.arb | 6 +++--- lib/l10n/app_en.arb | 6 +++--- lib/l10n/app_es.arb | 6 +++--- lib/l10n/app_fr.arb | 6 +++--- lib/l10n/app_hi.arb | 6 +++--- lib/l10n/app_ru.arb | 6 +++--- lib/l10n/app_th.arb | 6 +++--- lib/l10n/app_zh.arb | 6 +++--- test/ble_state_test.dart | 3 ++- 11 files changed, 44 insertions(+), 34 deletions(-) diff --git a/lib/ble/ble_engine.dart b/lib/ble/ble_engine.dart index e6e88cd23..b9ea39787 100644 --- a/lib/ble/ble_engine.dart +++ b/lib/ble/ble_engine.dart @@ -6313,6 +6313,11 @@ class BleEngine { // battery figure as if they were read, which is the same imputation // the quarantine above exists to stop. The revision and the body // length are the two things true at any layout. + // + // Firmware is CLEARED, not kept: a version from an earlier HELLO must + // not survive to drive the 50.43 lock status for this one. The rev-3 + // reader below stays diagnostics-only. + state.firmware = null; _log('[HELLO gen5] revision ${h.helloRevision} is not the revision-1 ' 'layout these offsets read (body ${h.rawHex.length ~/ 2}B) — ' 'serial, battery, charge and wrist state are NOT published or ' diff --git a/lib/ble/ble_state.dart b/lib/ble/ble_state.dart index 7c88b0c4e..de525ee60 100644 --- a/lib/ble/ble_state.dart +++ b/lib/ble/ble_state.dart @@ -372,19 +372,23 @@ BandStatus bandStatusFor({ } // The same two "no data is arriving" flags, explained by the firmware // instead: a charger cycle or a re-pair cannot help a band that withholds - // its data by design, and both flags clear once records bank again. + // its data by design, and both flags clear once records bank again. The + // flags cannot tell the lock from a real strap or clock fault, so the text + // says "probably", never "is". It sits BELOW the quarantine check on + // purpose: a quarantined batch is data that DID arrive, which a locked band + // does not send, so that diagnosis is the more specific one. if ((strapNeedsReboot || syncClockLost) && isDataLockedFirmware(bandFirmware)) { return const BandStatus( BandCondition.firmwareLocked, - 'The band’s firmware is holding back its data', - 'This band runs WHOOP firmware 50.43, which connects and answers the ' - 'app but sends no recordings or live heart rate until a ' - 'WHOOP-signed membership token is on it. OpenStrap cannot issue ' - 'that token. Everything already saved here is safe, and the band ' - 'keeps recording.', - fix: 'Re-pairing or charging will not help. This clears by itself once ' - 'the band sends data again', + 'The band’s firmware is probably holding back its data', + 'This band runs WHOOP firmware 50.43, which can connect and answer the ' + 'app but send no recordings or live heart rate until a ' + 'WHOOP-signed membership token is on it. That is the most likely ' + 'reason no data is arriving. OpenStrap cannot issue that token. ' + 'Everything already saved here is safe.', + fix: 'If it is the firmware, re-pairing or charging will not help. This ' + 'clears by itself once the band sends data again', ); } if (strapNeedsReboot) { diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 9c3fcee3b..e680cd485 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -3583,7 +3583,7 @@ "whoopFirmwareWarningTitle": "WHOOP-Nutzer: Verbinde dich nicht wieder mit der WHOOP-App", "whoopFirmwareWarningAction": "Wenn du OpenStrap oder eine andere Open-Source-App nutzt oder später zu einer wechseln möchtest, verbinde dein Band nicht wieder mit der offiziellen WHOOP-App. Sie kann Firmware-Updates automatisch installieren. Deinstalliere oder deaktiviere die WHOOP-App, damit sie dein Band nicht aktualisiert.", "whoopFirmwareWarningDetails": "Berichte zur WHOOP 5.0 / MG Firmware 50.43.1.0 und 50.43.2.0 beschreiben einen blockierten Datenzugriff. Bluetooth kann sich weiterhin verbinden. OpenStrap kann das von WHOOP signierte Mitgliedschafts-Token nicht ausstellen, das betroffene Bänder entsperrt. Wir arbeiten an einer Lösung, aber es gibt noch keine Abhilfe.", - "bandStatusFirmwareLockedTitle": "Die Firmware des Bands hält seine Daten zurück", - "bandStatusFirmwareLockedReason": "Dieses Band läuft mit WHOOP-Firmware 50.43. Sie verbindet sich und antwortet der App, sendet aber keine Aufzeichnungen und keine Live-Herzfrequenz, solange kein von WHOOP signiertes Mitgliedschafts-Token auf dem Band ist. OpenStrap kann dieses Token nicht ausstellen. Alles, was hier schon gespeichert ist, bleibt erhalten, und das Band zeichnet weiter auf.", - "bandStatusFirmwareLockedFix": "Neu koppeln oder Laden hilft nicht. Das verschwindet von selbst, sobald das Band wieder Daten sendet" + "bandStatusFirmwareLockedTitle": "Die Firmware des Bands hält wahrscheinlich seine Daten zurück", + "bandStatusFirmwareLockedReason": "Dieses Band läuft mit WHOOP-Firmware 50.43. Sie kann sich verbinden und der App antworten, aber keine Aufzeichnungen und keine Live-Herzfrequenz senden, solange kein von WHOOP signiertes Mitgliedschafts-Token auf dem Band ist. Das ist der wahrscheinlichste Grund, warum keine Daten ankommen. OpenStrap kann dieses Token nicht ausstellen. Alles, was hier schon gespeichert ist, bleibt erhalten.", + "bandStatusFirmwareLockedFix": "Liegt es an der Firmware, hilft neu koppeln oder Laden nicht. Das verschwindet von selbst, sobald das Band wieder Daten sendet" } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 278f726ef..20e214743 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -16575,15 +16575,15 @@ "@strengthDelete": {"description": "Strength set editor copy."}, "strengthSaveFailed": "Failed to save changes", "@strengthSaveFailed": {"description": "Strength set editor copy."}, - "bandStatusFirmwareLockedTitle": "The band’s firmware is holding back its data", + "bandStatusFirmwareLockedTitle": "The band’s firmware is probably holding back its data", "@bandStatusFirmwareLockedTitle": { "description": "BandStatus card title: band firmware 50.43 withholds all data until a WHOOP membership token is on it" }, - "bandStatusFirmwareLockedReason": "This band runs WHOOP firmware 50.43, which connects and answers the app but sends no recordings or live heart rate until a WHOOP-signed membership token is on it. OpenStrap cannot issue that token. Everything already saved here is safe, and the band keeps recording.", + "bandStatusFirmwareLockedReason": "This band runs WHOOP firmware 50.43, which can connect and answer the app but send no recordings or live heart rate until a WHOOP-signed membership token is on it. That is the most likely reason no data is arriving. OpenStrap cannot issue that token. Everything already saved here is safe.", "@bandStatusFirmwareLockedReason": { "description": "BandStatus card body: band firmware 50.43 withholds all data until a WHOOP membership token is on it" }, - "bandStatusFirmwareLockedFix": "Re-pairing or charging will not help. This clears by itself once the band sends data again", + "bandStatusFirmwareLockedFix": "If it is the firmware, re-pairing or charging will not help. This clears by itself once the band sends data again", "@bandStatusFirmwareLockedFix": { "description": "BandStatus fix action: band firmware 50.43 withholds all data until a WHOOP membership token is on it" }, diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 2115cfe33..16c752f5a 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -3283,7 +3283,7 @@ "whoopFirmwareWarningTitle": "Usuarios de WHOOP: no vuelvas a conectarte a la app de WHOOP", "whoopFirmwareWarningAction": "Si usas OpenStrap u otra app de código abierto, o piensas cambiarte a una más adelante, no vuelvas a conectar tu banda a la app oficial de WHOOP. Puede instalar actualizaciones de firmware automáticamente. Desinstala o desactiva la app de WHOOP para evitar que actualice tu banda.", "whoopFirmwareWarningDetails": "Hay informes de que el firmware 50.43.1.0 y 50.43.2.0 de WHOOP 5.0 / MG bloquea el acceso a los datos. Es posible que el Bluetooth siga conectándose. OpenStrap no puede emitir el token de membresía firmado por WHOOP que se necesita para desbloquear las bandas afectadas. Estamos trabajando en una solución, pero todavía no hay ningún arreglo disponible.", - "bandStatusFirmwareLockedTitle": "El firmware de la banda está reteniendo sus datos", - "bandStatusFirmwareLockedReason": "Esta banda usa el firmware 50.43 de WHOOP, que se conecta y responde a la app, pero no envía registros ni frecuencia cardíaca en vivo hasta que haya en ella un token de membresía firmado por WHOOP. OpenStrap no puede emitir ese token. Todo lo que ya está guardado aquí está a salvo, y la banda sigue registrando.", - "bandStatusFirmwareLockedFix": "Volver a emparejarla o cargarla no servirá. Esto desaparece solo cuando la banda vuelva a enviar datos" + "bandStatusFirmwareLockedTitle": "Probablemente el firmware de la banda está reteniendo sus datos", + "bandStatusFirmwareLockedReason": "Esta banda usa el firmware 50.43 de WHOOP, que puede conectarse y responder a la app sin enviar registros ni frecuencia cardíaca en vivo hasta que haya en ella un token de membresía firmado por WHOOP. Es la razón más probable de que no lleguen datos. OpenStrap no puede emitir ese token. Todo lo que ya está guardado aquí está a salvo.", + "bandStatusFirmwareLockedFix": "Si es el firmware, volver a emparejarla o cargarla no servirá. Esto desaparece solo cuando la banda vuelva a enviar datos" } diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 409056c36..0e567b746 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -3283,7 +3283,7 @@ "whoopFirmwareWarningTitle": "Utilisateurs WHOOP : ne vous reconnectez pas à l’application WHOOP", "whoopFirmwareWarningAction": "Si vous utilisez OpenStrap ou une autre application open source, ou si vous comptez y passer plus tard, ne reconnectez pas votre bracelet à l’application WHOOP officielle. Elle peut installer des mises à jour du firmware automatiquement. Désinstallez ou désactivez l’application WHOOP pour l’empêcher de mettre à jour votre bracelet.", "whoopFirmwareWarningDetails": "Des signalements concernant les firmwares 50.43.1.0 et 50.43.2.0 des WHOOP 5.0 / MG décrivent un accès aux données bloqué. Le Bluetooth peut encore se connecter. OpenStrap ne peut pas émettre le jeton d’abonnement signé par WHOOP nécessaire pour déverrouiller les bracelets concernés. Nous travaillons sur une solution, mais aucun correctif n’est encore disponible.", - "bandStatusFirmwareLockedTitle": "Le firmware du bracelet retient ses données", - "bandStatusFirmwareLockedReason": "Ce bracelet utilise le firmware WHOOP 50.43, qui se connecte et répond à l’application mais n’envoie ni enregistrements ni fréquence cardiaque en direct tant qu’un jeton d’abonnement signé par WHOOP n’est pas présent sur le bracelet. OpenStrap ne peut pas émettre ce jeton. Tout ce qui est déjà enregistré ici est en sécurité, et le bracelet continue d’enregistrer.", - "bandStatusFirmwareLockedFix": "Le jumeler à nouveau ou le recharger n’y changera rien. Ce message disparaît de lui-même dès que le bracelet renvoie des données" + "bandStatusFirmwareLockedTitle": "Le firmware du bracelet retient probablement ses données", + "bandStatusFirmwareLockedReason": "Ce bracelet utilise le firmware WHOOP 50.43, qui peut se connecter et répondre à l’application sans envoyer ni enregistrements ni fréquence cardiaque en direct tant qu’un jeton d’abonnement signé par WHOOP n’est pas présent sur le bracelet. C’est la raison la plus probable pour laquelle aucune donnée n’arrive. OpenStrap ne peut pas émettre ce jeton. Tout ce qui est déjà enregistré ici est en sécurité.", + "bandStatusFirmwareLockedFix": "Si c’est le firmware, le jumeler à nouveau ou le recharger n’y changera rien. Ce message disparaît de lui-même dès que le bracelet renvoie des données" } diff --git a/lib/l10n/app_hi.arb b/lib/l10n/app_hi.arb index c791cafff..e93313e38 100644 --- a/lib/l10n/app_hi.arb +++ b/lib/l10n/app_hi.arb @@ -2933,9 +2933,9 @@ "whoopFirmwareWarningTitle": "WHOOP उपयोगकर्ता: WHOOP ऐप से दोबारा कनेक्ट न करें", "whoopFirmwareWarningAction": "अगर आप OpenStrap या कोई दूसरा ओपन-सोर्स ऐप इस्तेमाल करते हैं, या बाद में किसी पर जाने की सोच रहे हैं, तो अपना बैंड आधिकारिक WHOOP ऐप से दोबारा कनेक्ट न करें। वह फ़र्मवेयर अपडेट अपने-आप इंस्टॉल कर सकता है। WHOOP ऐप को अनइंस्टॉल या अक्षम कर दें, ताकि वह आपके बैंड को अपडेट न कर सके।", "whoopFirmwareWarningDetails": "WHOOP 5.0 / MG के फ़र्मवेयर 50.43.1.0 और 50.43.2.0 के बारे में रिपोर्टें बताती हैं कि डेटा तक पहुँच रोक दी जाती है। ब्लूटूथ फिर भी कनेक्ट हो सकता है। प्रभावित बैंड को अनलॉक करने के लिए WHOOP द्वारा साइन किया गया मेंबरशिप टोकन चाहिए, जिसे OpenStrap जारी नहीं कर सकता। हम समाधान पर काम कर रहे हैं, लेकिन अभी कोई उपाय उपलब्ध नहीं है।", - "bandStatusFirmwareLockedTitle": "बैंड का फ़र्मवेयर उसका डेटा रोक रहा है", - "bandStatusFirmwareLockedReason": "यह बैंड WHOOP फ़र्मवेयर 50.43 पर चल रहा है, जो कनेक्ट होता है और ऐप को जवाब देता है, लेकिन जब तक बैंड पर WHOOP द्वारा साइन किया गया सदस्यता टोकन न हो, तब तक कोई रिकॉर्डिंग या लाइव हृदय गति नहीं भेजता। OpenStrap वह टोकन जारी नहीं कर सकता। यहाँ पहले से सहेजा गया सब कुछ सुरक्षित है, और बैंड रिकॉर्ड करता रहता है।", - "bandStatusFirmwareLockedFix": "दोबारा पेयर करने या चार्ज करने से मदद नहीं मिलेगी। बैंड के फिर से डेटा भेजते ही यह अपने-आप हट जाएगा", + "bandStatusFirmwareLockedTitle": "बैंड का फ़र्मवेयर शायद उसका डेटा रोक रहा है", + "bandStatusFirmwareLockedReason": "यह बैंड WHOOP फ़र्मवेयर 50.43 पर चल रहा है, जो कनेक्ट होकर ऐप को जवाब दे सकता है, लेकिन जब तक बैंड पर WHOOP द्वारा साइन किया गया सदस्यता टोकन न हो, तब तक कोई रिकॉर्डिंग या लाइव हृदय गति नहीं भेजता। डेटा न आने का सबसे संभावित कारण यही है। OpenStrap वह टोकन जारी नहीं कर सकता। यहाँ पहले से सहेजा गया सब कुछ सुरक्षित है।", + "bandStatusFirmwareLockedFix": "अगर वजह फ़र्मवेयर है, तो दोबारा पेयर करने या चार्ज करने से मदद नहीं मिलेगी। बैंड के फिर से डेटा भेजते ही यह अपने-आप हट जाएगा", "alarmNextLabel": "अगला", "alarmScheduleGroup": "साप्ताहिक शेड्यूल", "alarmWakeTimeRowTitle": "जागने का समय", diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index b6ad54ff0..fb7aa2680 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -8031,7 +8031,7 @@ } } }, - "bandStatusFirmwareLockedTitle": "Прошивка браслета удерживает его данные", - "bandStatusFirmwareLockedReason": "На этом браслете прошивка WHOOP 50.43: он подключается и отвечает приложению, но не передаёт ни записи, ни пульс в реальном времени, пока на нём нет подписанного WHOOP токена подписки. OpenStrap не может выпустить такой токен. Всё, что уже сохранено здесь, в безопасности, а браслет продолжает запись.", - "bandStatusFirmwareLockedFix": "Повторное сопряжение или зарядка не помогут. Сообщение исчезнет само, как только браслет снова начнёт передавать данные" + "bandStatusFirmwareLockedTitle": "Прошивка браслета, вероятно, удерживает его данные", + "bandStatusFirmwareLockedReason": "На этом браслете прошивка WHOOP 50.43: он может подключаться и отвечать приложению, но не передавать ни записи, ни пульс в реальном времени, пока на нём нет подписанного WHOOP токена подписки. Скорее всего, данные не приходят именно поэтому. OpenStrap не может выпустить такой токен. Всё, что уже сохранено здесь, в безопасности.", + "bandStatusFirmwareLockedFix": "Если дело в прошивке, повторное сопряжение или зарядка не помогут. Сообщение исчезнет само, как только браслет снова начнёт передавать данные" } diff --git a/lib/l10n/app_th.arb b/lib/l10n/app_th.arb index aa757fd97..8ca1e25df 100644 --- a/lib/l10n/app_th.arb +++ b/lib/l10n/app_th.arb @@ -16403,7 +16403,7 @@ } } }, - "bandStatusFirmwareLockedTitle": "เฟิร์มแวร์ของสายรัดกำลังกักข้อมูลไว้", - "bandStatusFirmwareLockedReason": "สายรัดนี้ใช้เฟิร์มแวร์ WHOOP 50.43 ซึ่งเชื่อมต่อและตอบสนองแอปได้ แต่จะไม่ส่งข้อมูลที่บันทึกไว้หรืออัตราการเต้นของหัวใจแบบสด จนกว่าจะมีโทเค็นสมาชิกที่ WHOOP ลงนามอยู่บนสายรัด OpenStrap ไม่สามารถออกโทเค็นนั้นได้ ข้อมูลทั้งหมดที่บันทึกไว้ที่นี่แล้วยังปลอดภัย และสายรัดยังคงบันทึกต่อไป", - "bandStatusFirmwareLockedFix": "การจับคู่ใหม่หรือการชาร์จจะไม่ช่วย ข้อความนี้จะหายไปเองเมื่อสายรัดส่งข้อมูลอีกครั้ง" + "bandStatusFirmwareLockedTitle": "เฟิร์มแวร์ของสายรัดน่าจะกำลังกักข้อมูลไว้", + "bandStatusFirmwareLockedReason": "สายรัดนี้ใช้เฟิร์มแวร์ WHOOP 50.43 ซึ่งอาจเชื่อมต่อและตอบสนองแอปได้ แต่ไม่ส่งข้อมูลที่บันทึกไว้หรืออัตราการเต้นของหัวใจแบบสด จนกว่าจะมีโทเค็นสมาชิกที่ WHOOP ลงนามอยู่บนสายรัด นี่เป็นสาเหตุที่น่าจะเป็นที่สุดที่ไม่มีข้อมูลเข้ามา OpenStrap ไม่สามารถออกโทเค็นนั้นได้ ข้อมูลทั้งหมดที่บันทึกไว้ที่นี่แล้วยังปลอดภัย", + "bandStatusFirmwareLockedFix": "หากเป็นที่เฟิร์มแวร์ การจับคู่ใหม่หรือการชาร์จจะไม่ช่วย ข้อความนี้จะหายไปเองเมื่อสายรัดส่งข้อมูลอีกครั้ง" } diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 7925ecf93..aaea726ff 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -2933,9 +2933,9 @@ "whoopFirmwareWarningTitle": "WHOOP 用户:请勿重新连接 WHOOP 应用", "whoopFirmwareWarningAction": "如果你在使用 OpenStrap 或其他开源应用,或打算以后改用,请不要再把手环连接到 WHOOP 官方应用。它可能会自动安装固件更新。请卸载或停用 WHOOP 应用,以免它更新你的手环。", "whoopFirmwareWarningDetails": "有报告称,WHOOP 5.0 / MG 固件 50.43.1.0 和 50.43.2.0 会阻止访问数据。蓝牙可能仍能连接。解锁受影响的手环需要由 WHOOP 签名的会员令牌,OpenStrap 无法签发。我们正在寻找解决办法,但目前还没有可用的修复。", - "bandStatusFirmwareLockedTitle": "手环固件正在扣留它的数据", - "bandStatusFirmwareLockedReason": "这个手环运行的是 WHOOP 固件 50.43:它能连接并响应应用,但在手环上没有 WHOOP 签名的会员令牌之前,不会发送任何记录或实时心率。OpenStrap 无法签发这个令牌。已保存在这里的所有数据都是安全的,手环也会继续记录。", - "bandStatusFirmwareLockedFix": "重新配对或充电都无济于事。手环重新发送数据后,此提示会自动消失", + "bandStatusFirmwareLockedTitle": "手环固件可能正在扣留它的数据", + "bandStatusFirmwareLockedReason": "这个手环运行的是 WHOOP 固件 50.43:它可以连接并响应应用,但在手环上没有 WHOOP 签名的会员令牌之前,可能不会发送任何记录或实时心率。这是收不到数据最可能的原因。OpenStrap 无法签发这个令牌。已保存在这里的所有数据都是安全的。", + "bandStatusFirmwareLockedFix": "如果是固件的原因,重新配对或充电都无济于事。手环重新发送数据后,此提示会自动消失", "alarmNextLabel": "下一次", "alarmScheduleGroup": "每周计划", "alarmWakeTimeRowTitle": "起床时间", diff --git a/test/ble_state_test.dart b/test/ble_state_test.dart index ecf04ed6e..a7125b183 100644 --- a/test/ble_state_test.dart +++ b/test/ble_state_test.dart @@ -732,7 +732,8 @@ void main() { expect(s.reason, contains('50.43')); // Charging or re-pairing is the advice for the other two flags; for a // locked band it is the wrong instruction. - expect(s.fix, startsWith('Re-pairing or charging will not help')); + expect(s.fix, contains('re-pairing or charging will not help')); + expect(s.title, contains('probably')); } }); From 0fdaf36151a2f7ac172dd814898e1534e76be177 Mon Sep 17 00:00:00 2001 From: abdulsaheel Date: Fri, 13 Nov 2026 21:22:20 +0530 Subject: [PATCH 3/3] firmware lock card: charging or re-pairing is still worth a try, since the flags can't tell the lock from a real fault --- lib/ble/ble_state.dart | 7 ++++--- lib/l10n/app_de.arb | 2 +- lib/l10n/app_en.arb | 2 +- lib/l10n/app_es.arb | 2 +- lib/l10n/app_fr.arb | 2 +- lib/l10n/app_hi.arb | 2 +- lib/l10n/app_ru.arb | 2 +- lib/l10n/app_th.arb | 2 +- lib/l10n/app_zh.arb | 2 +- test/ble_state_test.dart | 9 ++++++--- 10 files changed, 18 insertions(+), 14 deletions(-) diff --git a/lib/ble/ble_state.dart b/lib/ble/ble_state.dart index de525ee60..0da2ab2b0 100644 --- a/lib/ble/ble_state.dart +++ b/lib/ble/ble_state.dart @@ -277,7 +277,7 @@ bool isLinkAuthRefusal(int? code) => /// True for WHOOP 5.0 / MG firmware 50.43.x, which keeps answering commands /// but sends no history or live data until a WHOOP-signed membership token is -/// on the band (edge#673, captured on 50.43.1.0; reported on 50.43.2.0). +/// on the band (edge#673; reported on 50.43.1.0 and 50.43.2.0). /// [firmware] is `Gen5HelloInfo.firmwareVersion` (`major.minor.build.x`). // ponytail: a version prefix, not a probe for the token itself. A later // firmware with the same lock needs adding here; one that lifts it on 50.43 @@ -387,8 +387,9 @@ BandStatus bandStatusFor({ 'WHOOP-signed membership token is on it. That is the most likely ' 'reason no data is arriving. OpenStrap cannot issue that token. ' 'Everything already saved here is safe.', - fix: 'If it is the firmware, re-pairing or charging will not help. This ' - 'clears by itself once the band sends data again', + fix: 'If it is the firmware, nothing in the app changes it, and this ' + 'clears once the band sends data again. If nothing arrives, ' + 'charging the band or re-pairing is still worth a try', ); } if (strapNeedsReboot) { diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index f265de486..a7a8d58a6 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -3688,5 +3688,5 @@ "whoopFirmwareWarningDetails": "Berichte zur WHOOP 5.0 / MG Firmware 50.43.1.0 und 50.43.2.0 beschreiben einen blockierten Datenzugriff. Bluetooth kann sich weiterhin verbinden. OpenStrap kann das von WHOOP signierte Mitgliedschafts-Token nicht ausstellen, das betroffene Bänder entsperrt. Wir arbeiten an einer Lösung, aber es gibt noch keine Abhilfe.", "bandStatusFirmwareLockedTitle": "Die Firmware des Bands hält wahrscheinlich seine Daten zurück", "bandStatusFirmwareLockedReason": "Dieses Band läuft mit WHOOP-Firmware 50.43. Sie kann sich verbinden und der App antworten, aber keine Aufzeichnungen und keine Live-Herzfrequenz senden, solange kein von WHOOP signiertes Mitgliedschafts-Token auf dem Band ist. Das ist der wahrscheinlichste Grund, warum keine Daten ankommen. OpenStrap kann dieses Token nicht ausstellen. Alles, was hier schon gespeichert ist, bleibt erhalten.", - "bandStatusFirmwareLockedFix": "Liegt es an der Firmware, hilft neu koppeln oder Laden nicht. Das verschwindet von selbst, sobald das Band wieder Daten sendet" + "bandStatusFirmwareLockedFix": "Liegt es an der Firmware, lässt sich das in der App nicht ändern, und der Hinweis verschwindet, sobald das Band wieder Daten sendet. Kommen keine Daten an, lohnt sich trotzdem ein Versuch mit Laden oder neu koppeln" } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 9cb6594c9..608cf3f33 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -16811,7 +16811,7 @@ "@bandStatusFirmwareLockedReason": { "description": "BandStatus card body: band firmware 50.43 withholds all data until a WHOOP membership token is on it" }, - "bandStatusFirmwareLockedFix": "If it is the firmware, re-pairing or charging will not help. This clears by itself once the band sends data again", + "bandStatusFirmwareLockedFix": "If it is the firmware, nothing in the app changes it, and this clears once the band sends data again. If nothing arrives, charging the band or re-pairing is still worth a try", "@bandStatusFirmwareLockedFix": { "description": "BandStatus fix action: band firmware 50.43 withholds all data until a WHOOP membership token is on it" }, diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index d08eb51b6..794442bd4 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -3388,5 +3388,5 @@ "whoopFirmwareWarningDetails": "Hay informes de que el firmware 50.43.1.0 y 50.43.2.0 de WHOOP 5.0 / MG bloquea el acceso a los datos. Es posible que el Bluetooth siga conectándose. OpenStrap no puede emitir el token de membresía firmado por WHOOP que se necesita para desbloquear las bandas afectadas. Estamos trabajando en una solución, pero todavía no hay ningún arreglo disponible.", "bandStatusFirmwareLockedTitle": "Probablemente el firmware de la banda está reteniendo sus datos", "bandStatusFirmwareLockedReason": "Esta banda usa el firmware 50.43 de WHOOP, que puede conectarse y responder a la app sin enviar registros ni frecuencia cardíaca en vivo hasta que haya en ella un token de membresía firmado por WHOOP. Es la razón más probable de que no lleguen datos. OpenStrap no puede emitir ese token. Todo lo que ya está guardado aquí está a salvo.", - "bandStatusFirmwareLockedFix": "Si es el firmware, volver a emparejarla o cargarla no servirá. Esto desaparece solo cuando la banda vuelva a enviar datos" + "bandStatusFirmwareLockedFix": "Si es el firmware, la app no puede cambiarlo y el aviso desaparece cuando la banda vuelva a enviar datos. Si no llega nada, vale la pena probar a cargarla o volver a emparejarla" } diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index a75349761..33f1944da 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -3388,5 +3388,5 @@ "whoopFirmwareWarningDetails": "Des signalements concernant les firmwares 50.43.1.0 et 50.43.2.0 des WHOOP 5.0 / MG décrivent un accès aux données bloqué. Le Bluetooth peut encore se connecter. OpenStrap ne peut pas émettre le jeton d’abonnement signé par WHOOP nécessaire pour déverrouiller les bracelets concernés. Nous travaillons sur une solution, mais aucun correctif n’est encore disponible.", "bandStatusFirmwareLockedTitle": "Le firmware du bracelet retient probablement ses données", "bandStatusFirmwareLockedReason": "Ce bracelet utilise le firmware WHOOP 50.43, qui peut se connecter et répondre à l’application sans envoyer ni enregistrements ni fréquence cardiaque en direct tant qu’un jeton d’abonnement signé par WHOOP n’est pas présent sur le bracelet. C’est la raison la plus probable pour laquelle aucune donnée n’arrive. OpenStrap ne peut pas émettre ce jeton. Tout ce qui est déjà enregistré ici est en sécurité.", - "bandStatusFirmwareLockedFix": "Si c’est le firmware, le jumeler à nouveau ou le recharger n’y changera rien. Ce message disparaît de lui-même dès que le bracelet renvoie des données" + "bandStatusFirmwareLockedFix": "Si c’est le firmware, l’application n’y peut rien et ce message disparaît dès que le bracelet renvoie des données. Si rien n’arrive, essayez quand même de le recharger ou de le jumeler à nouveau" } diff --git a/lib/l10n/app_hi.arb b/lib/l10n/app_hi.arb index 40e786d84..5891b933a 100644 --- a/lib/l10n/app_hi.arb +++ b/lib/l10n/app_hi.arb @@ -3039,7 +3039,7 @@ "whoopFirmwareWarningDetails": "WHOOP 5.0 / MG के फ़र्मवेयर 50.43.1.0 और 50.43.2.0 के बारे में रिपोर्टें बताती हैं कि डेटा तक पहुँच रोक दी जाती है। ब्लूटूथ फिर भी कनेक्ट हो सकता है। प्रभावित बैंड को अनलॉक करने के लिए WHOOP द्वारा साइन किया गया मेंबरशिप टोकन चाहिए, जिसे OpenStrap जारी नहीं कर सकता। हम समाधान पर काम कर रहे हैं, लेकिन अभी कोई उपाय उपलब्ध नहीं है।", "bandStatusFirmwareLockedTitle": "बैंड का फ़र्मवेयर शायद उसका डेटा रोक रहा है", "bandStatusFirmwareLockedReason": "यह बैंड WHOOP फ़र्मवेयर 50.43 पर चल रहा है, जो कनेक्ट होकर ऐप को जवाब दे सकता है, लेकिन जब तक बैंड पर WHOOP द्वारा साइन किया गया सदस्यता टोकन न हो, तब तक कोई रिकॉर्डिंग या लाइव हृदय गति नहीं भेजता। डेटा न आने का सबसे संभावित कारण यही है। OpenStrap वह टोकन जारी नहीं कर सकता। यहाँ पहले से सहेजा गया सब कुछ सुरक्षित है।", - "bandStatusFirmwareLockedFix": "अगर वजह फ़र्मवेयर है, तो दोबारा पेयर करने या चार्ज करने से मदद नहीं मिलेगी। बैंड के फिर से डेटा भेजते ही यह अपने-आप हट जाएगा", + "bandStatusFirmwareLockedFix": "अगर वजह फ़र्मवेयर है, तो ऐप इसे बदल नहीं सकता और बैंड के फिर से डेटा भेजते ही यह संदेश हट जाएगा। अगर कुछ नहीं आता, तो बैंड को चार्ज करना या दोबारा पेयर करना फिर भी आज़माने लायक है", "alarmNextLabel": "अगला", "alarmScheduleGroup": "साप्ताहिक शेड्यूल", "alarmWakeTimeRowTitle": "जागने का समय", diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index be69c1bdf..016fc54e6 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -8103,7 +8103,7 @@ }, "bandStatusFirmwareLockedTitle": "Прошивка браслета, вероятно, удерживает его данные", "bandStatusFirmwareLockedReason": "На этом браслете прошивка WHOOP 50.43: он может подключаться и отвечать приложению, но не передавать ни записи, ни пульс в реальном времени, пока на нём нет подписанного WHOOP токена подписки. Скорее всего, данные не приходят именно поэтому. OpenStrap не может выпустить такой токен. Всё, что уже сохранено здесь, в безопасности.", - "bandStatusFirmwareLockedFix": "Если дело в прошивке, повторное сопряжение или зарядка не помогут. Сообщение исчезнет само, как только браслет снова начнёт передавать данные", + "bandStatusFirmwareLockedFix": "Если дело в прошивке, приложение изменить это не может, и сообщение исчезнет, как только браслет снова начнёт передавать данные. Если ничего не приходит, всё равно стоит зарядить браслет или заново выполнить сопряжение", "pairResetWhoop5Step1": "Снимите браслет с руки и подождите, пока погаснут зелёные огоньки.", "pairResetWhoop5Step2": "Держите браслет за боковые стороны и сильно постукивайте двумя пальцами по верхней части, пока не будет мигать только синий. Если горят синий и белый вместе, продолжайте стучать, пока не останется только синий.", "pairResetWhoop5Step3": "Если приложение WHOOP установлено на этом телефоне, принудительно закройте его.", diff --git a/lib/l10n/app_th.arb b/lib/l10n/app_th.arb index a99494e1f..cc8891c0d 100644 --- a/lib/l10n/app_th.arb +++ b/lib/l10n/app_th.arb @@ -16489,7 +16489,7 @@ }, "bandStatusFirmwareLockedTitle": "เฟิร์มแวร์ของสายรัดน่าจะกำลังกักข้อมูลไว้", "bandStatusFirmwareLockedReason": "สายรัดนี้ใช้เฟิร์มแวร์ WHOOP 50.43 ซึ่งอาจเชื่อมต่อและตอบสนองแอปได้ แต่ไม่ส่งข้อมูลที่บันทึกไว้หรืออัตราการเต้นของหัวใจแบบสด จนกว่าจะมีโทเค็นสมาชิกที่ WHOOP ลงนามอยู่บนสายรัด นี่เป็นสาเหตุที่น่าจะเป็นที่สุดที่ไม่มีข้อมูลเข้ามา OpenStrap ไม่สามารถออกโทเค็นนั้นได้ ข้อมูลทั้งหมดที่บันทึกไว้ที่นี่แล้วยังปลอดภัย", - "bandStatusFirmwareLockedFix": "หากเป็นที่เฟิร์มแวร์ การจับคู่ใหม่หรือการชาร์จจะไม่ช่วย ข้อความนี้จะหายไปเองเมื่อสายรัดส่งข้อมูลอีกครั้ง", + "bandStatusFirmwareLockedFix": "หากเป็นที่เฟิร์มแวร์ แอปแก้ไขเรื่องนี้ไม่ได้ และข้อความนี้จะหายไปเองเมื่อสายรัดส่งข้อมูลอีกครั้ง หากยังไม่มีข้อมูลเข้ามา การชาร์จหรือจับคู่ใหม่ก็ยังคุ้มค่าที่จะลอง", "pairResetWhoop5Step1": "ถอดสายรัดออกจากข้อมือ แล้วรอจนไฟสีเขียวดับ", "@pairResetWhoop5Step1": { "description": "Reset help for WHOOP 5.0 / MG, step 1." diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 9096afe7e..b1976de88 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -3039,7 +3039,7 @@ "whoopFirmwareWarningDetails": "有报告称,WHOOP 5.0 / MG 固件 50.43.1.0 和 50.43.2.0 会阻止访问数据。蓝牙可能仍能连接。解锁受影响的手环需要由 WHOOP 签名的会员令牌,OpenStrap 无法签发。我们正在寻找解决办法,但目前还没有可用的修复。", "bandStatusFirmwareLockedTitle": "手环固件可能正在扣留它的数据", "bandStatusFirmwareLockedReason": "这个手环运行的是 WHOOP 固件 50.43:它可以连接并响应应用,但在手环上没有 WHOOP 签名的会员令牌之前,可能不会发送任何记录或实时心率。这是收不到数据最可能的原因。OpenStrap 无法签发这个令牌。已保存在这里的所有数据都是安全的。", - "bandStatusFirmwareLockedFix": "如果是固件的原因,重新配对或充电都无济于事。手环重新发送数据后,此提示会自动消失", + "bandStatusFirmwareLockedFix": "如果是固件的原因,应用无法更改,手环重新发送数据后此提示会自动消失。如果仍然没有数据,充电或重新配对仍然值得一试", "alarmNextLabel": "下一次", "alarmScheduleGroup": "每周计划", "alarmWakeTimeRowTitle": "起床时间", diff --git a/test/ble_state_test.dart b/test/ble_state_test.dart index a7125b183..cfc099847 100644 --- a/test/ble_state_test.dart +++ b/test/ble_state_test.dart @@ -730,9 +730,12 @@ void main() { expect(s.condition, BandCondition.firmwareLocked, reason: '$flags'); expect(s.isFault, isTrue); expect(s.reason, contains('50.43')); - // Charging or re-pairing is the advice for the other two flags; for a - // locked band it is the wrong instruction. - expect(s.fix, contains('re-pairing or charging will not help')); + // The flags cannot tell the lock from a real strap or clock fault, so + // the text must not tell the user that charging or re-pairing is + // pointless; it only says the app cannot change a firmware lock. + expect(s.fix, contains('nothing in the app changes it')); + expect(s.fix, contains('worth a try')); + expect(s.fix, isNot(contains('will not help'))); expect(s.title, contains('probably')); } });