ENFR

Projet personnel · TypeScript, React, Web Bluetooth · Hardware, rétro-ingénierie

La doc avait tort. Le trafic, non.

  • TypeScript
  • React
  • Vite
  • Web Bluetooth API
  • Vitest
  • ~58xplus rapide, une fois testé sur le vrai matériel
  • 4/4valeurs du protocole issues de la doc, toutes fausses

Le problème, en une phrase

Je devais imprimer une étiquette avec le prénom de mon fils pour l’école, mon téléphone n’était pas avec moi, et il n’y avait pas de moyen simple d’imprimer depuis un ordinateur à la place.

Contexte

L’app de l’imprimante ne marche que sur téléphone. J’ai cherché une app prête à l’emploi pour ordinateur. Aucune n’existait. J’ai trouvé quelques projets open source sur GitHub qui essayaient de résoudre le même problème, mais aucun ne me satisfaisait : difficiles à installer, ou peu fiables. J’ai donc décidé de construire le mien : une petite app web qui se connecte à l’imprimante en Bluetooth, directement depuis le navigateur. Aucune app à installer, sur n’importe quel ordinateur.

Ce n’était pas seulement pour cette étiquette-là. Mon téléphone ne sera pas toujours avec moi la prochaine fois que j’aurai besoin d’imprimer quelque chose. Construire un outil qui marche depuis n’importe quel appareil voulait dire ne plus jamais retomber dans le même problème.

L’imprimante parle en Bluetooth Low Energy. Le navigateur peut lui parler directement, avec l’API Web Bluetooth. Pas besoin de serveur, pas de store d’applications, juste une page à ouvrir. Cette partie du plan était simple. Ce qui ne l’était pas : faire en sorte que l’imprimante comprenne vraiment ce que je lui envoyais.

Trouver la vraie cause

Je suis parti de documentations publiques sur cette famille d’imprimantes. Elles donnaient l’identifiant du service Bluetooth, et des valeurs typiques pour la qualité, la vitesse et l’énergie de chauffe. J’ai construit l’app autour de ces chiffres.

Rien ne fonctionnait sur ma vraie imprimante. Mauvais identifiant de service. Mauvaise valeur de qualité. Mauvaise valeur de vitesse. Mauvaise valeur d’énergie, même pas proche de la plage documentée. Aucune erreur nulle part. L’imprimante ne faisait juste rien.

Une comparaison côte à côte : à gauche, les valeurs copiées depuis une documentation tierce ; à droite, les vraies valeurs lues dans le trafic Bluetooth réel de l’imprimante via Wireshark, avec quatre différences marquées

J’ai donc arrêté de deviner. J’ai activé l’enregistrement du trafic Bluetooth sur mon téléphone, imprimé quelque chose avec la vraie app de l’imprimante, récupéré le journal, et lu les vrais octets dans Wireshark. Cela m’a donné les vraies valeurs, plus une commande absente de toutes les documentations que j’ai trouvées, envoyée avant tout le reste. La leçon : une documentation est une bonne première hypothèse, pas la vérité. Quand on peut vérifier le comportement réel, il faut le vérifier.

La décision, et celle que j’ai écartée

Une fois que l’imprimante acceptait mes commandes, un second problème est apparu : envoyer les données trop vite peut bloquer ce type d’imprimante. C’est exactement ce qui rend les projets open source similaires peu fiables. Il n’existe aucune réponse officielle et écrite sur la vitesse sûre.

La solution « intelligente » semblait évidente : attendre une notification de l’imprimante après chaque écriture, plutôt que de deviner un délai fixe. Pas d’attente arbitraire, l’imprimante indique elle-même quand elle est prête. Je l’ai construite ainsi en premier, sous le nom NotifyAck.

Je ne lui ai pas fait confiance sans preuve. J’ai donc aussi construit la version simple, FixedDelay : attendre un temps fixe après chaque écriture. Puis j’ai testé les deux sur la vraie imprimante, avec le même job d’impression de 20 lignes, et mesuré.

FixedDelay a fini en environ 1 seconde, impression propre, aucun blocage. NotifyAck a mis environ 58 secondes pour le même job. Pas un simple ralentissement : cette imprimante précise n’envoie jamais de notification sur la caractéristique d’écriture, donc chaque écriture retombait sur son délai d’attente maximal. La solution « intelligente » n’était pas intelligente sur ce matériel. Elle ne fonctionnait tout simplement jamais.

FixedDelay est la valeur par défaut maintenant. NotifyAck est resté dans le code, pas supprimé, au cas où une autre imprimante ou un autre firmware la supporterait vraiment un jour.

Résultats

  • Environ 58 fois plus rapide, en comparant les deux stratégies d’envoi sur le même job d’impression réel, mesuré sur le vrai matériel, pas estimé.
  • 4 valeurs sur 4 issues de documentations tierces se sont révélées fausses pour cette imprimante précise, trouvées uniquement en lisant son trafic Bluetooth réel.
  • Une Progressive Web App fonctionnelle : on l’installe, on se connecte en Bluetooth, on imprime une image, sans app compagnon nécessaire, sur n’importe quel appareil.

Ce que je ferais différemment

Je ferais moins confiance à la documentation écrite, et plus tôt. J’ai passé du temps réel à construire à partir de valeurs trouvées dans des documentations, avant de les vérifier sur la vraie imprimante. La capture du trafic Bluetooth est ce qui a vraiment fonctionné, à chaque fois, du premier coup. La prochaine fois, je capturerais le trafic réel en premier, et je traiterais toute documentation comme une piste à vérifier, pas comme une base sur laquelle construire.