Files
coach-ios/docs
Sylvain Bettinelli 1389edb1f7 Cause racine : le CBCentralManager du SDK est lazy, et search() ne le réveille jamais
L'instrumentation a tranché : le publisher de search() n'émettait RIEN — ni
valeur, ni complétion, ni erreur. Ce n'était donc pas « aucun appareil », c'était
« on n'a jamais cherché ».

CBDeviceListenerImpl.manager est une `lazy var` : le CBCentralManager n'existe
qu'au premier accès. Or search() commence par
`monitorBleState().filter { $0 == .poweredOn }`, et monitorBleState() se contente
de rendre bleStateSubject — il ne touche jamais manager. Les seuls accès du
chemin de recherche (retrieveConnectedPeripherals, retrievePeripherals) sont à
l'intérieur du flatMap, donc APRÈS le filtre qui bloque. Le manager n'était
jamais créé, centralManagerDidUpdateState jamais appelé, le sujet jamais
alimenté : le filtre attendait un état que rien ne pouvait produire.

`blePowered()` — `return manager.state == .poweredOn` — est le seul accès public
exécuté immédiatement. On l'appelle donc pour instancier le manager, et on le
fait APRÈS s'être abonné : si bleStateSubject est un PassthroughSubject, un état
émis avant l'abonnement serait perdu et on retomberait sur le même silence. Cet
ordre est écrit dans le code, c'est exactement ce qu'une relecture inverserait.

Trois mesures ont conduit ici, aucune supposition : l'absence de ligne Bluetooth
dans les réglages de l'app, puis 43 appareils en scan nu contre 0 par le SDK,
puis le publisher muet. Chacune a éliminé une famille de causes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 13:11:20 +00:00
..