« errorcode 104 » n'était pas un refus : mkdir sur un dossier déjà là

Sylvain a rapporté un errorcode 104 en testant l'envoi. Le code vient du
protocole PFTP de Polar, et pftp_error.proto du SDK officiel le nomme :
104 = DIRECTORY_EXISTS. Ce n'est donc pas un refus de la montre — la session BLE
s'était parfaitement ouverte, le transport fonctionnait, et c'est notre séquence
de mkdir qui n'était pas idempotente.

L'hypothèse fautive était écrite noir sur blanc dans parseSteps : « aucun des
deux n'existe d'avance pour une date neuve ». Vrai d'une date neuve, faux dès le
second envoi vers la même date — exactement ce que Sylvain venait de faire après
avoir réussi un premier envoi.

Un mkdir qui bute sur 104 est désormais considéré comme satisfait, à la manière
d'un mkdir -p : le dossier est là, c'est tout ce qu'on lui demandait. Strictement
limité à la création de dossier — un put de fichier n'est jamais avalé, 105
FILE_EXISTS signifierait que l'objectif est déjà écrit et l'appelant doit le
savoir.

Le renvoi n'est pas passé sous silence pour autant : ecrire() rend un drapeau
dossierPreexistant, le plugin le résout en alreadyExisted, et l'UI de coach
affiche « Un objectif existait déjà à cette date. Redémarrer la montre pour que
le nouveau s'affiche. » C'est la contrepartie de l'index en cache constaté le
31/08 — sans cet avertissement, l'envoi annoncerait un succès que la montre ne
montrerait pas.

Les codes PFTP sont définis dans PolarPftpStep.swift, donc couverts par les
tests Linux : 87 tests verts, dont 3 nouveaux qui vérifient que 104 est
satisfaisant pour un mkdir et que 103, 105, 106 et 108 restent des échecs.

⚠️ CoachPolarBLE.swift n'est pas compilable ici — Capacitor et le SDK Polar
n'existent pas sur Linux. La modification du plugin est à vérifier au prochain
build Xcode ; la logique des codes, elle, est testée.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sylvain Bettinelli
2026-09-01 08:25:26 +00:00
parent 474afce348
commit 7d68605e83
3 changed files with 96 additions and 6 deletions

View File

@@ -25,6 +25,38 @@
import Foundation
/// Codes d'erreur du protocole PFTP, tels que Polar les publie.
///
/// Source : `pftp_error.proto` du SDK officiel 100 `UNIDENTIFIED_HOST_ERROR`,
/// 101 `INVALID_COMMAND`, 102 `INVALID_PARAMETER`, 103 `NO_SUCH_FILE_OR_DIRECTORY`,
/// **104 `DIRECTORY_EXISTS`**, 105 `FILE_EXISTS`, 106 `OPERATION_NOT_PERMITTED`,
/// 107 `NO_SUCH_USER`, 108 `TIMEOUT`.
/// https://github.com/polarofficial/polar-ble-sdk/blob/master/sources/Android/android-communications/library/src/sdk/proto/pftp_error.proto
///
/// Le SDK iOS les remonte tels quels par
/// `BlePsFtpException.responseError(errorCode: Int)`.
public enum PftpCode {
/// Le dossier visé par un `mkdir` existe déjà.
///
/// **Ce n'est pas un échec d'envoi.** Rencontré le 01/09/2026 sur un
/// second envoi vers la même date : la session BLE s'était bien ouverte, et
/// c'est notre séquence de `mkdir` qui n'était pas idempotente. Le message
/// « errorcode 104 » donnait donc à croire à un refus de la montre alors
/// que le transport fonctionnait.
public static let directoryExists = 104
/// Codes sur lesquels un `mkdir` peut être considéré comme satisfait : le
/// dossier est là, c'est tout ce qu'on lui demandait. L'équivalent de
/// `mkdir -p`.
///
/// Strictement limité à la création de dossier. Un `put` de fichier ne
/// doit JAMAIS être avalé de la sorte 105 `FILE_EXISTS` signifierait que
/// l'objectif est déjà écrit, ce que l'appelant doit savoir.
public static func mkdirEstSatisfait(par code: Int) -> Bool {
code == directoryExists
}
}
/// Un PUT PFTP : un chemin, un contenu. Un contenu vide crée un dossier.
public struct PftpStep: Equatable {
public let path: String