La montre ne diffuse pas parce qu'elle est déjà connectée : la chercher ailleurs

4020 advertisements vus — HomePod, Furbo, des sans-nom — et aucune Polar. Le
scan marchait donc parfaitement depuis le correctif précédent. C'est la montre
qui ne s'annonce pas.

Et c'est normal : un appareil BLE connecté cesse d'émettre. La Vantage est liée
à l'iPhone par l'app Flow, donc invisible au scan par conception. Tous les
correctifs de scan qui ont précédé ne pouvaient rien y changer — on cherchait
dans le seul endroit où elle ne pouvait pas être.

`search()` prévoit exactement ce cas, mais seulement si on lui passe des UUID :
`manager.retrieveConnectedPeripherals(withServices: uuids!)` rend les
périphériques DÉJÀ connectés exposant le service, et leur fabrique une session.
Je passais `nil`, donc cette branche n'était jamais empruntée.

Au passage, déduplication des sessions : AllowDuplicates est armé côté SDK, d'où
les 4020 pour une poignée d'appareils réels — sans quoi on ouvrirait quarante
fois la même session.

Ce que la journée aura montré : chaque message d'erreur qui affirmait une cause
unique a fait perdre du temps, et chaque message qui RAPPORTAIT ce qu'il avait vu
a fait avancer. La liste des appareils vus valait tous les raisonnements.

84 tests au vert.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sylvain Bettinelli
2026-08-31 13:40:12 +00:00
parent 60dd22eaeb
commit 3cc7d935ad
2 changed files with 45 additions and 1 deletions

View File

@@ -304,7 +304,12 @@ final class PolarPsFtpWriter {
// L'état, lui, est acquis avant d'arriver ici : `blePowered()` a été
// sondé jusqu'à devenir vrai.
do {
// `AllowDuplicates` est armé côté SDK : le même appareil revient à
// chaque advertisement (4020 émissions pour une poignée d'appareils
// réels). On déduplique avant de compter et d'ouvrir quoi que ce soit.
var dejaVues = Set<String>()
let toutes = try await sessionsVues(listener, fenetre: timeout)
.filter { dejaVues.insert(Self.etiquette($0)).inserted }
vues = toutes.count
noms = toutes.map { Self.etiquette($0) }
@@ -372,7 +377,22 @@ final class PolarPsFtpWriter {
rendu = true
suite.resume(returning: vues)
}
listener.search(nil, identifiers: nil, fetchKnownDevices: true)
// PASSER L'UUID DU SERVICE c'est ce qui trouve une montre DÉJÀ
// CONNECTÉE.
//
// Mesuré le 2026-08-31 : 4020 advertisements vus (HomePod, Furbo),
// aucune Polar. Normal **un appareil BLE connecté cesse
// d'émettre**. La Vantage est liée à l'iPhone par l'app Flow : elle
// est donc invisible au scan, par conception, et l'attendre était
// sans espoir.
//
// Avec un `uuids` non nil, `search()` emprunte une autre branche :
// `manager.retrieveConnectedPeripherals(withServices: uuids!)`, qui
// rend les périphériques déjà connectés au système exposant ce
// service, et leur fabrique une session. Passer `nil` ce que
// faisait ce code n'exécutait jamais cette branche.
listener.search([BlePsFtpClient.PSFTP_SERVICE],
identifiers: nil, fetchKnownDevices: true)
.sink(receiveCompletion: { [weak self] fin in
// Distinguer « le publisher a terminé » de « il n'a
// jamais rien dit » : dans le second cas, `flatMap`