« Fermer l'app Polar Flow » était un conseil faux, et mesuré tel dès le 31/08
Sylvain enchaîne un troisième envoi et reçoit « le canal est probablement occupé » — notre propre message, déclenché par watchNotFound avec des montres muettes : le service PsFTP est là, il ne répond pas. La chronologie de ses trois envois explique tout. Le premier réussit, montre fraîchement réinitialisée donc pas encore liée à Flow. Le deuxième renvoie 104 DIRECTORY_EXISTS, ce qui prouve que le canal était ENCORE libre. Le troisième échoue : Flow a repris la main entre-temps. Le canal n'est donc pas ouvert ou fermé en général — il y a une fenêtre, qui se referme dès que Flow se reconnecte. Le message conseillait de fermer complètement l'app Polar Flow. C'était faux, et la mesure du 31/08 le disait déjà : la montre affichait « connexion impossible » pendant que les réglages iOS la disaient toujours connectée à Flow. iOS maintient le lien d'un accessoire appairé, app fermée ou non. Le message nomme maintenant le geste qui libère réellement le canal — redémarrer la montre — précise que fermer l'app n'y change rien, et rappelle que le câble est le chemin fiable. Corrigé au passage le message des appareils sans PsFTP, qui présentait encore la question comme « l'inconnue restante » alors qu'elle a été tranchée le 31/08 : la montre expose bien PsFTP quand elle est connectée. Un test interdit désormais de la rouvrir dans l'UI. 88 tests Linux verts, dont deux nouveaux qui verrouillent l'absence du conseil inutile et la présence du geste utile. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -383,3 +383,33 @@ documentée et devra être mesurée.
|
|||||||
**câble**.
|
**câble**.
|
||||||
|
|
||||||
[ancs]: https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification/Specification/Specification.html
|
[ancs]: https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification/Specification/Specification.html
|
||||||
|
|
||||||
|
### La séquence du 01/09, et ce qu'elle apprend sur la fenêtre
|
||||||
|
|
||||||
|
Trois envois consécutifs, trois résultats différents — c'est la chronologie qui
|
||||||
|
explique tout :
|
||||||
|
|
||||||
|
| # | résultat | lecture |
|
||||||
|
|---|---|---|
|
||||||
|
| 1 | **réussi** | montre fraîchement réinitialisée, **pas encore liée à Flow** : canal libre |
|
||||||
|
| 2 | **errorcode 104** `DIRECTORY_EXISTS` | canal **toujours** libre, la session s'ouvre — seul le `mkdir` bute sur un dossier déjà créé au 1ᵉʳ envoi |
|
||||||
|
| 3 | **« canal probablement occupé »** | Flow a repris la main entre-temps |
|
||||||
|
|
||||||
|
⇒ Le canal n'est pas ouvert ou fermé « en général » : il y a une **fenêtre**,
|
||||||
|
qui commence quand la montre n'est liée à personne et se referme dès que Flow
|
||||||
|
se reconnecte. C'est cohérent avec le 31/08 et avec l'USB, où il faut fermer
|
||||||
|
Flow.
|
||||||
|
|
||||||
|
⚠️ **Le message d'erreur du plugin conseillait « fermer complètement l'app Polar
|
||||||
|
Flow ». C'est faux, et ça l'était déjà le 31/08** : la montre affichait
|
||||||
|
« connexion impossible » pendant que les réglages iOS la disaient **toujours
|
||||||
|
connectée** à Flow. iOS maintient le lien d'un accessoire appairé, app fermée ou
|
||||||
|
non. Message corrigé le 01/09 — il nomme désormais le geste qui libère
|
||||||
|
réellement le canal (redémarrer la montre) et rappelle que le câble est le
|
||||||
|
chemin fiable.
|
||||||
|
|
||||||
|
**Hypothèse ouverte, non vérifiée** : redémarrer la montre puis écrire *dans la
|
||||||
|
foulée*, avant que Flow ne se reconnecte, pourrait suffire. Ça expliquerait les
|
||||||
|
envois 1 et 2. Ce n'est pas une méthode tant que ça n'a pas été reproduit
|
||||||
|
plusieurs fois — et ⛔ chaque essai a un coût matériel avéré (l'USB désactivé le
|
||||||
|
31/08). **Écrire la séance par câble AVANT tout essai.**
|
||||||
|
|||||||
@@ -210,17 +210,37 @@ public enum PolarPftpError: Error, CustomStringConvertible, Equatable {
|
|||||||
+ "la montre allumée et à portée."
|
+ "la montre allumée et à portée."
|
||||||
|
|
||||||
case .watchNotFound(let seconds, let vues, _, let muettes) where muettes > 0:
|
case .watchNotFound(let seconds, let vues, _, let muettes) where muettes > 0:
|
||||||
// Le service est là mais ne répond pas : signature d'un canal déjà pris.
|
// Le service est là mais ne répond pas : canal déjà pris.
|
||||||
|
//
|
||||||
|
// ⚠️ Ce message conseillait « fermer l'app Polar Flow ». C'était
|
||||||
|
// faux, et mesuré comme tel le 31/08/2026 : la montre affichait
|
||||||
|
// « connexion impossible » pendant que les réglages iOS la
|
||||||
|
// disaient TOUJOURS connectée à Flow. iOS maintient le lien d'un
|
||||||
|
// accessoire appairé, app fermée ou non — fermer l'app ne rend pas
|
||||||
|
// le canal.
|
||||||
|
//
|
||||||
|
// Ce qui l'a rendu, le 01/09 : une montre fraîchement
|
||||||
|
// réinitialisée, donc pas encore liée à Flow. Redémarrer la montre
|
||||||
|
// libère aussi son canal, mais Flow le reprend.
|
||||||
return "\(vues) appareil(s) vu(s), \(muettes) portant PsFTP mais sans "
|
return "\(vues) appareil(s) vu(s), \(muettes) portant PsFTP mais sans "
|
||||||
+ "réponse en \(Int(seconds)) s. Le canal est probablement déjà "
|
+ "réponse en \(Int(seconds)) s. Le canal PsFTP de la Vantage "
|
||||||
+ "occupé : fermer complètement l'app Polar Flow (elle synchronise "
|
+ "n'accepte qu'une session, et Polar Flow la détient tant que "
|
||||||
+ "en arrière-plan), puis réessayer."
|
+ "la montre lui est appairée — fermer l'app n'y change rien, "
|
||||||
|
+ "iOS maintient le lien. Redémarrer la montre (appui long sur "
|
||||||
|
+ "OK) libère le canal ; il faut écrire dans la foulée, avant "
|
||||||
|
+ "que Flow ne le reprenne. Chemin fiable : le câble."
|
||||||
|
|
||||||
case .watchNotFound(let seconds, let vues, _, _):
|
case .watchNotFound(let seconds, let vues, _, _):
|
||||||
// Des appareils, mais aucun ne porte le service.
|
// Des appareils, mais aucun ne porte le service.
|
||||||
|
// ⚠️ Ce message parlait d'« inconnue restante ». Elle a été levée le
|
||||||
|
// 31/08/2026 : la montre EST atteignable et expose bien PsFTP
|
||||||
|
// (« 12 appareils vus, 1 portant PsFTP ») — quand elle est
|
||||||
|
// connectée. N'en voir aucun est donc autre chose : montre éteinte,
|
||||||
|
// hors de portée, ou pas encore connectée à l'iPhone.
|
||||||
return "\(vues) appareil(s) Bluetooth vu(s) en \(Int(seconds)) s, aucun "
|
return "\(vues) appareil(s) Bluetooth vu(s) en \(Int(seconds)) s, aucun "
|
||||||
+ "n'expose PsFTP. La Vantage n'annonce peut-être pas ce service "
|
+ "n'expose PsFTP. La Vantage expose bien ce service quand elle "
|
||||||
+ "tant qu'elle est appairée à Flow — c'est l'inconnue restante."
|
+ "est connectée (vérifié le 31/08) : la chercher plutôt du côté "
|
||||||
|
+ "de la montre — allumée, à portée, et reliée à l'iPhone."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,13 +138,31 @@ final class PolarPftpErrorTests: XCTestCase {
|
|||||||
func testUneMontreMuettePointeVersFlow() {
|
func testUneMontreMuettePointeVersFlow() {
|
||||||
let e = PolarPftpError.watchNotFound(30, vues: 3, sansPsFtp: 2, muettes: 1)
|
let e = PolarPftpError.watchNotFound(30, vues: 3, sansPsFtp: 2, muettes: 1)
|
||||||
XCTAssertTrue(e.description.contains("Polar Flow"))
|
XCTAssertTrue(e.description.contains("Polar Flow"))
|
||||||
XCTAssertTrue(e.description.contains("occupé"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testDesAppareilsSansPsFtpNommentLInconnueRestante() {
|
/// ⚠️ Le message conseillait « fermer complètement l'app Polar Flow ».
|
||||||
|
/// Mesuré faux le 31/08/2026 : la montre affichait « connexion impossible »
|
||||||
|
/// pendant que les réglages iOS la disaient toujours connectée à Flow. iOS
|
||||||
|
/// maintient le lien d'un accessoire appairé, app fermée ou non.
|
||||||
|
func testLeMessageNeConseillePlusDeFermerLApp() {
|
||||||
|
let e = PolarPftpError.watchNotFound(30, vues: 3, sansPsFtp: 2, muettes: 1)
|
||||||
|
XCTAssertTrue(e.description.contains("fermer l'app n'y change rien"),
|
||||||
|
"le geste inutile doit être explicitement écarté")
|
||||||
|
XCTAssertTrue(e.description.contains("Redémarrer la montre"),
|
||||||
|
"le geste qui libère réellement le canal doit être donné")
|
||||||
|
XCTAssertTrue(e.description.contains("câble"),
|
||||||
|
"le chemin fiable doit être rappelé")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// L'« inconnue restante » a été levée le 31/08 : la montre expose bien
|
||||||
|
/// PsFTP quand elle est connectée. Le message ne doit plus la présenter
|
||||||
|
/// comme une question ouverte.
|
||||||
|
func testDesAppareilsSansPsFtpNePresententPlusUneInconnue() {
|
||||||
let e = PolarPftpError.watchNotFound(30, vues: 4, sansPsFtp: 4, muettes: 0)
|
let e = PolarPftpError.watchNotFound(30, vues: 4, sansPsFtp: 4, muettes: 0)
|
||||||
XCTAssertTrue(e.description.contains("n'expose PsFTP"))
|
XCTAssertTrue(e.description.contains("n'expose PsFTP"))
|
||||||
XCTAssertTrue(e.description.contains("4 appareil"))
|
XCTAssertTrue(e.description.contains("4 appareil"))
|
||||||
|
XCTAssertFalse(e.description.contains("inconnue"),
|
||||||
|
"la question a été tranchée, ne pas la rouvrir dans l'UI")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testLesTroisMessagesSontDistincts() {
|
func testLesTroisMessagesSontDistincts() {
|
||||||
|
|||||||
Reference in New Issue
Block a user