Skip to content

Releases: Xptrucks/tinyrail-releases

TinyRail v0.14.0-beta.12

Pre-release

Choose a tag to compare

La mise à jour par BLE ne se dispute plus la mémoire, et se libère seule

Deux défauts trouvés en diagnostiquant des mises à jour qui n'aboutissaient
pas. Tous deux touchent l'opération la plus critique du produit : une carte à
moitié écrite est le pire état possible.

⚠️ LE LIEN DISTANT S'EFFACE DEVANT UNE MISE À JOUR. Rien ne le suspendait, et
la session TLS du client MQTT fragmentait le heap : le plus gros bloc allouable
était tombé de 25 600 à 7 680 octets pendant qu'il tournait. Perdre le lien
distant deux minutes n'est rien à côté d'une mise à jour qui manque de mémoire.
Le client est DÉTRUIT, pas seulement arrêté, pour rendre la mémoire.
Mesuré après correction : 65 300 octets libres, plus gros bloc 55 296.

⚠️ UN TRANSFERT INTERROMPU SE LIBÈRE SEUL. Il ne se libérait qu'à la
DÉCONNEXION du client. Une application qui renonce sans se déconnecter — retour
arrière, passage en arrière-plan, plantage — laissait la carte occupée jusqu'au
redémarrage, et refusait toute nouvelle tentative. Au-delà d'une minute sans
paquet, le transfert est abandonné.

⚠️ Ce que ces corrections NE changent pas, parce que c'était déjà juste : une
image n'est activée qu'APRÈS vérification de son empreinte, un transfert
interrompu ne laisse rien d'actif, et le bootloader revient à l'ancienne image
si la nouvelle démarre mal (CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE). Une mise à
jour qui échoue laisse une carte qui fonctionne.

Vérifié de bout en bout : 1,53 Mio envoyés par BLE, empreinte vérifiée, bascule
de partition, redémarrage sur la nouvelle image.

35 vérifications natives sur le délai d'abandon, dont le débordement de
millis() à 49,7 jours et le cas inverse : un transfert qui reçoit régulièrement
ne doit jamais être coupé.

TinyRail v0.14.0-beta.11

Pre-release

Choose a tag to compare

Le compte du broker se déduit du nom de la carte

Plus rien à saisir, plus rien à stocker, plus rien à re-synchroniser :

motdepasse = SHA256(nom + "albatros" + "xptrucks")

La carte le calcule, l'application aussi. Le compte ne peut donc plus manquer
ni diverger, et l'accès distant s'ouvre sans qu'on ait rien à configurer.

⚠️ CE QUE CETTE PROTECTION VAUT, ET CE QU'ELLE NE VAUT PAS. Les deux sels
vivent dans cette image, qui se télécharge sans authentification et qu'un
strings suffit à lire ; le nom d'une carte est diffusé en clair dans son
annonce BLE. Le mot de passe est donc reconstituable.

C'est un choix assumé, et il tient parce que le mot de passe n'est pas ce qui
protège l'installation : tout ce qui transite est chiffré de bout en bout avec
la clé d'appairage, que le broker n'a jamais et qui ne sort jamais de la carte.
Un tiers qui recalculerait ce mot de passe ne pourrait ni lire les trames, ni
en fabriquer que la carte accepte. Il pourrait occuper le compte et usurper le
sujet status : un dérangement, pas une prise de contrôle.

⚠️ Un compte posé par OP_SET_MQTT reste prioritaire, pour viser un broker tiers
dont les comptes ne suivent pas cette règle.

Vérifié de bout en bout sur une carte réelle : compte effacé, carte redémarrée,
connexion acceptée par le broker avec le mot de passe calculé, trames
déchiffrées lues sur le flux.

⚠️ Rappel pour qui efface un compte : CLEAR_MQTT n'écrit pas la NVS lui-même,
un interval s'en charge. Couper le courant aussitôt après laisse le compte en
place.

TinyRail v0.14.0-beta.10

Pre-release

Choose a tag to compare

Armer l'accès distant depuis l'app, et suivre un déménagement du broker

Les deux autorisations, publier son état et accepter les commandes, n'existaient
que comme entités Home Assistant : elles n'étaient donc pilotables que depuis
lui. Or le produit a retiré le serveur web, l'AP et le portail captif au nom
d'un usage « BLE + app », et n'exige pas Home Assistant. Une carte sans HA ne
pouvait pas armer son propre accès distant.

OP_GET_REMOTE 0x76 → [accès, commandes, connecté]
OP_SET_REMOTE 0x77 ← [accès, commandes]

⚠️ La lecture rend TROIS champs : les deux autorisations sont une intention,
connecté est l'état réel du lien. Armé ne veut pas dire joint.

⚠️ Aucun des deux n'est ouvert au MQTT : qui tiendrait le lien distant pourrait
sinon s'accorder lui-même le droit de commander, que l'utilisateur a refusé.

⚠️ Une connexion TCP établie survit à un changement de destination. Le jour où
le broker déménage, ou qu'une redirection de port change, la carte continue de
parler à l'ancien : elle est connectée, mais plus au bon endroit, et rien ne le
détecte puisque l'ancien répond. Constaté en vraie grandeur le 2026-09-04.

La session est donc rouverte toutes les six heures, avec un décalage propre à
chaque carte pour qu'un parc entier ne se reconnecte pas à la même seconde.

⚠️ Le déclenchement réel des six heures n'a pas été observé sur carte : attendre
six heures n'est pas un protocole d'essai. La logique est éprouvée hors carte,
débordement de millis() à 49,7 jours compris.

Le protocole MQTT n'existait qu'en un seul exemplaire, le firmware lui-même :
rien ne pouvait dire si ce que la carte publie est seulement lisible.
tools/mqtt/tinyrail_mqtt.py s'abonne, déchiffre avec la clé d'appairage et
affiche en continu. Il réutilise le décodeur du client BLE plutôt que d'en
écrire un second, qui dériverait.

wifi_ssid() est retiré dans ESPHome 2026.9.0 : migré vers wifi_ssid_to(),
qui épargne en outre une allocation sur un chemin de boucle. Et deux réglages
qui empêchent la carte de redémarrer toutes les quinze minutes sont désormais
contrôlés avant publication.

TinyRail v0.14.0-beta.9

Pre-release

Choose a tag to compare

@chpeps chpeps released this 03 Sep 21:42

Accès distant MQTT, chiffré de bout en bout

La carte publie son état sur mqtt.tinyrail.xptrucks.fr:8883 en TLS et se pilote à distance. Le contenu est chiffré avec la clé d'appairage : le broker achemine, il ne peut ni lire ni commander. Le protocole décalque le GATT, une caractéristique par topic.

Le Wi-Fi et le compte du broker se posent par BLE (OP_SET_WIFI, OP_SET_MQTT). Rien n'est compilé dans l'image : un secret y serait lisible d'un strings.

Deux interrupteurs séparés : publier son état, et accepter les commandes.

⚠️ Ce qui disparaît, et qu'il faut savoir avant de flasher

Plus de serveur web, plus de point d'accès de secours, plus de portail captif, plus d'Improv BLE. L'usage du produit est BLE plus application.

Conséquence directe : une carte sans Wi-Fi ne se configure plus que par BLE, ou par le câble USB (improv_serial, conservé). Il n'y a plus de réseau « TinyRail V2 Setup » sur lequel se rabattre, ni de page à 192.168.4.1.

Home Assistant découvre toujours la carte, par mDNS.

Ce retrait est ce qui a rendu le MQTT possible : le creux de mémoire libre passe de 236 octets à 27 432, et le plus gros bloc allouable de 8 192 à 26 624, ce qu'un handshake TLS exige.

L'annonce BLE retrouve du même coup son UUID de service, qu'Improv confisquait.

Garde-fous

  • Une option Bluetooth qui change met les cartes en service en boucle de redémarrage, sans remède à distance. La carte migre seule, et la publication est refusée si la configuration a bougé.
  • Cinq paniques d'affilée effacent la NVS, pour sortir d'une boucle sans intervention.
  • reboot_timeout: 0s sur l'API et sur le Wi-Fi, désormais contrôlé : sans lui, une carte pilotée seulement en BLE redémarrerait toutes les quinze minutes en coupant ses huit sorties.
  • Un garde-fou de débit par sujet, qui diffère au lieu de jeter.

⚠️ Ce qui n'a jamais tourné en conditions réelles

Le filet des cinq paniques, la migration Bluetooth sur un parc, huit clients simultanés. C'est pourquoi cette version reste une bêta.

TinyRail v0.14.0-beta.8

Pre-release

Choose a tag to compare

Bêta 8 : la chaîne de publication sous l'organisation Xptrucks

⚠️ AUCUN CHANGEMENT DE CODE EMBARQUÉ. Le firmware est celui de la bêta 7, à
l'octet près pour ce qui tourne sur la carte. Ne cherchez pas ce qui a changé
dans le comportement : rien.

Cette version n'a qu'une raison d'être : éprouver la chaîne de publication
après le passage des dépôts sous l'organisation Xptrucks.

· Le dépôt de publication est maintenant Xptrucks/tinyrail-releases.
· Le miroir GitHub Pages est xptrucks.github.io/tinyrail-releases.
⚠️ L'ancienne adresse chpeps.github.io est MORTE (404), pas redirigée.
· Le jeton de publication vient d'une GitHub App de l'organisation, plus d'un
jeton personnel : celui-ci avait cessé de fonctionner à l'instant du
transfert, l'organisation refusant les jetons de plus de 366 jours.

Les adresses du produit ne changent pas : ota. et flash.tinyrail.xptrucks.fr
servent les mêmes fichiers, aux mêmes URL. Une carte en service ne voit
strictement aucune différence.

TinyRail v0.14.0-beta.7

Pre-release

Choose a tag to compare

@chpeps chpeps released this 31 Aug 15:13

Aucun changement de comportement : cette bêta éprouve la chaîne de publication

⚠️ Le firmware est fonctionnellement identique à la 0.14.0-beta.6. Aucun
fichier embarqué n'a bougé entre les deux : ni packages/, ni components/,
ni la configuration, ni le protocole. Si une carte est déjà en bêta 6, cette
mise à jour ne changera rien à ce qu'elle fait. Il n'y a aucune raison de la
flasher pour autre chose que participer à cet essai.

Ce qu'elle publie, en revanche, est nouveau :

  • compat-beta.json, qui déclare ce que ce firmware exige autour de lui :
    version de protocole, révisions de carte, version minimale de l'app. La
    question « quelle app va avec quel firmware sur quelle carte » se posait
    depuis la Rev 0.2 sans qu'aucun fichier n'y réponde.
  • protocol-beta.json et son empreinte, qui permettent à l'app de savoir
    que sa copie du protocole a pris du retard. Jusqu'ici, son propre contrôle
    comparait cette copie à une empreinte écrite en dur : il attrapait une copie
    retouchée sur place, jamais une source qui avait avancé.

Et surtout, c'est la première publication qui passe par les cinq étages :
contrôler, construire, attester, publier, vérifier après coup. Le dernier
interroge les adresses publiques et confronte le binaire téléchargé au md5 du
manifest. Une release ne peut plus se déclarer réussie sans que les adresses
servent effectivement la version publiée.

⚠️ Le canal stable reste sur la 0.13.0 et n'est pas touché : cette bêta
n'écrit que manifest-beta.json et firmware-beta.bin.

TinyRail v0.14.0-beta.6

Pre-release

Choose a tag to compare

@chpeps chpeps released this 31 Aug 10:27

Changer une sortie ne fait plus sursauter les autres

Commuter une sortie faisait sursauter brièvement toutes les autres — visible à
l'œil, et gênant pour ce qui est alimenté.

Deux observations ont fait le diagnostic, et la première a tué la piste la plus
évidente : le sursaut se voyait même quand la sortie commutée n'avait aucune
charge
. Aucun courant appelé, donc rien à voir avec l'appel de courant au
démarrage — et le remède qu'on aurait naturellement appliqué, un démarrage en
douceur, n'aurait rien réglé.

La cause était dans le composant pca9685 d'ESPHome, et ce sont deux défauts
qui se cumulent :

  • il réécrit les seize canaux dès qu'un seul change. À 400 kHz, huit canaux
    prennent ~1,5 ms, soit plus d'une période PWM entière à 1 kHz : chaque canal
    se fait recharger ses comparateurs à un instant arbitraire de son cycle. Ce
    n'est pas la valeur écrite qui pose problème — les autres canaux reçoivent
    des valeurs identiques — c'est l'acte de recharger, qui peut faire manquer
    la transition du cycle en cours ;
  • son mode par défaut met la sortie à jour à chaque octet acquitté, donc
    quatre fois par canal, dont trois sur des registres à moitié écrits.

Commuter une sortie écrit désormais quatre octets au lieu de trente-deux, et
les canaux qui n'ont pas bougé ne sont plus touchés du tout.

Coût : 16 octets de RAM, et 182 octets de flash rendus.

Rien d'autre ne change : ni le protocole, ni les réglages, ni le comportement
des sorties.

Sur la carte, et c'est le seul juge qui vaille : un glitch d'un cycle PWM
dure une milliseconde, hors de portée de tout ce qui se mesure ici — la carte
échantillonne à 500 ms. Le sursaut a disparu à l'œil.

Le composant est copié localement, ce qui est un piège à retardement : une
montée d'ESPHome pourrait l'écraser sans un mot. tools/check-pca9685.py
surveille les deux moitiés du risque — les correctifs toujours là, et le reste
qui n'a pas divergé de l'amont.

Le défaut de surintensité est rémanent : il reste levé après la coupure et
ne s'efface qu'au rallumage de la sortie. Un client ne doit pas le traiter comme
une impulsion. ⚠️ Cette partie-là n'a toujours pas disjoncté pour de vrai :
l'éprouver demande une charge d'au moins 1 A et tests/test_overcurrent.py.

TinyRail v0.14.0-beta.5

Pre-release

Choose a tag to compare

@chpeps chpeps released this 31 Aug 08:54

Le défaut de surintensité reste levé jusqu'au rallumage

Une sortie disjonctait et la lecture des défauts restait vide, partout à la
fois : bande de métriques, tuile « Défauts », encadré du van, journal
d'alertes. Une sortie coupée, et rien qui dise pourquoi.

Le drapeau s'effaçait dès que le courant retombait sous le seuil — or couper
la sortie fait tomber son courant. Il vivait un tour de boucle, 500 ms. Et
comme la boucle de surintensité et celle qui notifie les trames sont deux
interval de 500 ms non en phase, FAULTS pouvait être évaluée après que le
drapeau soit retombé, et ne jamais le montrer.

⚠️ Le bit de surintensité est désormais rémanent. Il reste levé après la
coupure et ne s'efface qu'au rallumage de la sortie : rallumer EST
l'acquittement, il n'y a pas d'opcode pour ça. Un client ne doit plus le
traiter comme une impulsion. Ce n'est pas un passe-droit : si la surcharge
dure, le délai repart et la sortie recoupe.

Le compteur de disjonctions de l'historique embarqué — un octet par canal et
par bucket, réservé depuis le début et incrémenté nulle part — compte enfin.
Sur les fronts, jamais sur l'état, et il sature à 255.

Un banc natif, tests/native/, qui tourne sans carte ni charge : 86
vérifications, dont le débordement de millis() à 49,7 jours. Éprouvé contre
l'ancienne règle, il rend 23 échecs. La règle elle-même vit maintenant dans
packages/overcurrent.h, sans un seul id() — c'est ce qui la rend
éprouvable, et la boucle passe de huit copies déroulées à une boucle.

tests/test_overcurrent.py couvre l'autre moitié, sur carte, et exige une
charge réelle déclarée par --load-channel / --load-amps.

Cette bêta n'a tourné sur AUCUNE carte. Elle compile (flash 91,7 %) et passe
les tests natifs, rien de plus. La disjonction réelle reste à éprouver au banc.

TinyRail v0.14.0-beta.4

Pre-release

Choose a tag to compare

@chpeps chpeps released this 26 Aug 12:24

TinyRail v0.14.0-beta.3

Pre-release

Choose a tag to compare

@chpeps chpeps released this 24 Aug 20:26