docs(miotiq): move ping trigger to 0x02 for backward compatibility
Deployed firmwares hardcode command=0x01 (legacy from when the byte was named `version`); treating 0x01 as ping would have flagged every existing frame as a diagnostic. Keep 0x00/0x01 as normal-data and use 0x02 as the explicit ping trigger. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -32,20 +32,21 @@ Le **type de capteur** est passé en query string. Modèles supportés :
|
|||||||
|------------------|--------|--------------------------------------------------------------------------------------------------|
|
|------------------|--------|--------------------------------------------------------------------------------------------------|
|
||||||
| `device_id` | string | Identifiant unique, **représentation hexadécimale** de 16 caractères (8 octets ASCII). Convertir hex → ASCII pour obtenir le numéro de série imprimé sur le boîtier. Ex. `"4430353234313938"` → `"D0524198"`. |
|
| `device_id` | string | Identifiant unique, **représentation hexadécimale** de 16 caractères (8 octets ASCII). Convertir hex → ASCII pour obtenir le numéro de série imprimé sur le boîtier. Ex. `"4430353234313938"` → `"D0524198"`. |
|
||||||
| `signal_quality` | int | Qualité du signal réseau (dB, souvent RSSI négatif). |
|
| `signal_quality` | int | Qualité du signal réseau (dB, souvent RSSI négatif). |
|
||||||
| `command` | int | Type de trame. `0x00` = données mesure (les autres champs sont valides). `0x01` = ping test (trame émise volontairement par le firmware pour vérifier le lien capteur → Miotiq → backend ; le backend ne doit pas archiver les mesures associées). Voir [Commande / type de trame](#commande--type-de-trame). |
|
| `command` | int | Type de trame. `0x00` / `0x01` = données mesure (les autres champs sont valides ; `0x01` est conservé pour la rétrocompatibilité avec les firmwares qui hardcodaient l'ancien champ `version`). `0x02` = ping test (trame émise volontairement par le firmware pour vérifier le lien capteur → Miotiq → backend ; le backend ne doit pas archiver les mesures associées). Voir [Commande / type de trame](#commande--type-de-trame). |
|
||||||
|
|
||||||
## Commande / type de trame
|
## Commande / type de trame
|
||||||
|
|
||||||
Le champ `command` (1 octet, offset 9 du payload binaire) discrimine la nature de la trame.
|
Le champ `command` (1 octet, offset 9 du payload binaire) discrimine la nature de la trame.
|
||||||
|
|
||||||
| Valeur | Sens | Action backend attendue |
|
| Valeur | Sens | Action backend attendue |
|
||||||
|---------|--------------|---------------------------------------------------------------------------------------------------------------|
|
|---------|------------------|---------------------------------------------------------------------------------------------------------------|
|
||||||
| `0x00` | données | Trame de mesure normale. Décoder et persister les champs métier comme d'habitude. |
|
| `0x00` | données | Trame de mesure normale. Décoder et persister les champs métier comme d'habitude. |
|
||||||
| `0x01` | ping test | Trame de diagnostic émise par le firmware pour vérifier le chemin capteur → Miotiq → backend. Logger la réception (timestamp, `device_id`, `signal_quality`) puis **ne pas archiver** les autres champs comme mesures réelles — leur contenu n'est pas garanti significatif. |
|
| `0x01` | données (legacy) | Identique à `0x00`. Émis par les firmwares antérieurs au renommage `version` → `command` qui hardcodaient cet octet à `0x01` ; conservé comme alias de mesure normale pour ne pas casser le parc déployé. |
|
||||||
|
| `0x02` | ping test | Trame de diagnostic émise par le firmware pour vérifier le chemin capteur → Miotiq → backend. Logger la réception (timestamp, `device_id`, `signal_quality`) puis **ne pas archiver** les autres champs comme mesures réelles — leur contenu n'est pas garanti significatif. |
|
||||||
|
|
||||||
Toute autre valeur doit être traitée comme une trame de données (`0x00`) en attendant qu'elle soit officiellement allouée — éviter de rejeter la trame sur la seule base d'un `command` inconnu pour rester forward-compatible.
|
Toute autre valeur doit être traitée comme une trame de données (`0x00`) en attendant qu'elle soit officiellement allouée — éviter de rejeter la trame sur la seule base d'un `command` inconnu pour rester forward-compatible.
|
||||||
|
|
||||||
**Note historique** : ce champ s'appelait `version` avant 2026-04-27 et était hardcodé `0x01` côté firmware. Le versioning du protocole est exclusivement porté par `version_major/minor/patch` (voir [Version firmware](#version-firmware)).
|
**Note historique** : ce champ s'appelait `version` avant 2026-04-27 et était hardcodé `0x01` côté firmware. C'est cette valeur héritée qui force `0x01` à rester une trame de données et pousse le ping sur `0x02`. Le versioning du protocole est exclusivement porté par `version_major/minor/patch` (voir [Version firmware](#version-firmware)).
|
||||||
|
|
||||||
## Polluants (codes ISO LCSQA)
|
## Polluants (codes ISO LCSQA)
|
||||||
|
|
||||||
@@ -240,7 +241,7 @@ Enum extensible — de nouvelles valeurs peuvent être ajoutées (7, 8, …) san
|
|||||||
- Ignorer `error_flags`, `npm_status`, `device_status` si `== 255` — c'est un firmware ancien, l'absence de diagnostic n'est pas une alarme.
|
- Ignorer `error_flags`, `npm_status`, `device_status` si `== 255` — c'est un firmware ancien, l'absence de diagnostic n'est pas une alarme.
|
||||||
- Les `_unit` sont purement informatifs / de debug. La valeur métier est toujours le champ sans suffixe.
|
- Les `_unit` sont purement informatifs / de debug. La valeur métier est toujours le champ sans suffixe.
|
||||||
- `device_id` est **hex** dans le JSON ; convertir en ASCII (`bytes.fromhex(v).decode('ascii')`) pour afficher le numéro de série lisible.
|
- `device_id` est **hex** dans le JSON ; convertir en ASCII (`bytes.fromhex(v).decode('ascii')`) pour afficher le numéro de série lisible.
|
||||||
- Lire `command` **avant** de persister la trame : si `command == 0x01` (ping test), logger la réception (timestamp, `device_id`, `signal_quality`) sans archiver les mesures. Une trame `command` absent ou `0x00` est une trame de données normale.
|
- Lire `command` **avant** de persister la trame : si `command == 0x02` (ping test), logger la réception (timestamp, `device_id`, `signal_quality`) sans archiver les mesures. Une trame `command` absent, `0x00` ou `0x01` est une trame de données normale (`0x01` = legacy, voir [Commande / type de trame](#commande--type-de-trame)).
|
||||||
|
|
||||||
## Historique
|
## Historique
|
||||||
|
|
||||||
@@ -249,3 +250,4 @@ Enum extensible — de nouvelles valeurs peuvent être ajoutées (7, 8, …) san
|
|||||||
| 2026-04-23 | v1 | Version initiale inventée (schéma imbriqué avec `token`/`ts`/`measurements`) — remplacée. |
|
| 2026-04-23 | v1 | Version initiale inventée (schéma imbriqué avec `token`/`ts`/`measurements`) — remplacée. |
|
||||||
| 2026-04-23 | v2 | **Format officiel AirCarto 2026** : schéma plat, bitfields détaillés, compat firmware ancien. |
|
| 2026-04-23 | v2 | **Format officiel AirCarto 2026** : schéma plat, bitfields détaillés, compat firmware ancien. |
|
||||||
| 2026-04-27 | v3 | Champ `version` (offset 9 du binaire, hardcodé `0x01` côté firmware) renommé `command` et réaffecté à un type de trame : `0x00` = données, `0x01` = ping test. Ajout de la section « Commande / type de trame ». Versioning protocole reste sur `version_major/minor/patch`. |
|
| 2026-04-27 | v3 | Champ `version` (offset 9 du binaire, hardcodé `0x01` côté firmware) renommé `command` et réaffecté à un type de trame : `0x00` = données, `0x01` = ping test. Ajout de la section « Commande / type de trame ». Versioning protocole reste sur `version_major/minor/patch`. |
|
||||||
|
| 2026-04-27 | v4 | Rétrocompatibilité : ping test déplacé de `0x01` vers `0x02`. Les firmwares déployés émettent déjà `0x01` (héritage de l'ancien champ `version`) ; les compter comme pings aurait masqué toutes leurs mesures. `0x00` et `0x01` sont désormais tous deux des trames de données normales, `0x02` est le déclencheur explicite du ping. |
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ Layout octet par octet :
|
|||||||
|--------|--------|-------------------|---------|--------|------------------------------------------|
|
|--------|--------|-------------------|---------|--------|------------------------------------------|
|
||||||
| 0 | 8 | `device_id` | | | Hex 16 chars, converti en ASCII côté client (ex. `"D0524198"`) |
|
| 0 | 8 | `device_id` | | | Hex 16 chars, converti en ASCII côté client (ex. `"D0524198"`) |
|
||||||
| 8 | 1 | `signal_quality` | dB | | Signal cellulaire |
|
| 8 | 1 | `signal_quality` | dB | | Signal cellulaire |
|
||||||
| 9 | 1 | `command` | | | Type de trame — `0x00` = données mesure, `0x01` = ping test (déclenché par le firmware pour vérifier le lien capteur → Miotiq → backend). Voir [`json-payload.md`](json-payload.md#commande--type-de-trame). |
|
| 9 | 1 | `command` | | | Type de trame — `0x00` / `0x01` = données mesure, `0x02` = ping test (déclenché par le firmware pour vérifier le lien capteur → Miotiq → backend). `0x01` est conservé comme synonyme de mesure normale par rétrocompatibilité (firmwares existants hardcodés `0x01` quand l'octet portait encore le nom `version`). Voir [`json-payload.md`](json-payload.md#commande--type-de-trame). |
|
||||||
| 10 | 2 | `ISO_68` | µg/m³ | /10 | PM1 |
|
| 10 | 2 | `ISO_68` | µg/m³ | /10 | PM1 |
|
||||||
| 12 | 2 | `ISO_39` | µg/m³ | /10 | PM2.5 |
|
| 12 | 2 | `ISO_39` | µg/m³ | /10 | PM2.5 |
|
||||||
| 14 | 2 | `ISO_24` | µg/m³ | /10 | PM10 |
|
| 14 | 2 | `ISO_24` | µg/m³ | /10 | PM10 |
|
||||||
@@ -220,3 +220,4 @@ Valeurs manquantes codées `-1` (sentinelle legacy). À **ne pas reproduire** po
|
|||||||
| 2026-04-23 | v5 | Extension prévue du descripteur NebuleAir Pro 4G avec `latitude`, `longitude`, `misc` dans le bloc `reserved` — proposition d'encodage dans la section À faire. |
|
| 2026-04-23 | v5 | Extension prévue du descripteur NebuleAir Pro 4G avec `latitude`, `longitude`, `misc` dans le bloc `reserved` — proposition d'encodage dans la section À faire. |
|
||||||
| 2026-04-24 | v6 | Intégration effective de `latitude` (4B), `longitude` (4B), `misc` (1B) dans le descripteur NebuleAir Pro 4G. Encodage offset unsigned (`raw = (deg + 90|180) * 1e6`, équation `x/1000000-90|180`) pour contourner l'absence de signed sur `hex2dec` Miotiq. « No fix » géré par le bit `GPS_NO_FIX` de `device_status`. Reste 2B `reserved`. |
|
| 2026-04-24 | v6 | Intégration effective de `latitude` (4B), `longitude` (4B), `misc` (1B) dans le descripteur NebuleAir Pro 4G. Encodage offset unsigned (`raw = (deg + 90|180) * 1e6`, équation `x/1000000-90|180`) pour contourner l'absence de signed sur `hex2dec` Miotiq. « No fix » géré par le bit `GPS_NO_FIX` de `device_status`. Reste 2B `reserved`. |
|
||||||
| 2026-04-27 | v7 | Octet 9 renommé `version` → `command`. Ce champ était hardcodé `0x01` côté firmware (jamais une vraie version de protocole). Réaffecté à un type de trame : `0x00` = données mesure, `0x01` = ping test. Permet au firmware de déclencher une trame de bout en bout (capteur → Miotiq → backend) sans envoyer de mesures réelles. Versioning protocole assuré par `version_major/minor/patch` (offsets 69-71). |
|
| 2026-04-27 | v7 | Octet 9 renommé `version` → `command`. Ce champ était hardcodé `0x01` côté firmware (jamais une vraie version de protocole). Réaffecté à un type de trame : `0x00` = données mesure, `0x01` = ping test. Permet au firmware de déclencher une trame de bout en bout (capteur → Miotiq → backend) sans envoyer de mesures réelles. Versioning protocole assuré par `version_major/minor/patch` (offsets 69-71). |
|
||||||
|
| 2026-04-27 | v8 | Rétrocompatibilité : ping test déplacé de `0x01` vers `0x02`. Les firmwares déployés émettent déjà `0x01` (héritage du champ `version` hardcodé) ; les traiter comme ping aurait fait passer toutes leurs trames pour des diagnostics. `0x00` et `0x01` restent donc des trames de mesure normales, `0x02` devient le déclencheur explicite du ping. |
|
||||||
|
|||||||
Reference in New Issue
Block a user