Aller au contenu

Écoute Forge IoT : forge iot:listen

Statut : commande de développement / pédagogie.
Elle écoute le broker MQTT configuré et insère chaque mesure reçue dans la table iot_events.
Ce n'est pas un service de production (pas de daemon, pas de retry, pas de batch).

Objectif

Relier les briques Forge IoT en un flux local réellement utilisable :

Mosquitto
forge iot:listen
MqttSubscriber
IotEventRepository.insert()
iot_events

Jusqu'ici, forge iot:simulate publiait des mesures, mais Forge n'avait pas de commande simple pour écouter et stocker.
C'est ce que comble forge iot:listen.

Usage

forge iot:listen

Aucune option pour ce premier ticket.
Aide via :

forge iot:listen --help

La commande reste active jusqu'à Ctrl+C, puis s'arrête proprement.

Sortie exemple

Forge IoT listen

[INFO] Broker MQTT : localhost:1883
[INFO] Topic       : forge/+/+/telemetry
[INFO] Stockage    : table iot_events via IotEventRepository
[INFO] En écoute. Ctrl+C pour arrêter.

[OK] atelier/esp32-001 temperature=22.4 °C
[OK] atelier/esp32-001 humidity=55 %
^C
[INFO] Arrêt demandé.
[OK] Écoute MQTT arrêtée proprement.

Résumé :
  mesures reçues       : 2
  mesures stockées     : 2
  erreurs de contrat   : 0
  erreurs de stockage  : 0

Chaque ligne [OK] correspond à une mesure validée par le contrat MQTT et insérée dans iot_events.

Arrêt propre

Sur Ctrl+C, la commande affiche [INFO] Arrêt demandé. puis, une fois la connexion fermée, [OK] Écoute MQTT arrêtée proprement..
La déconnexion du broker (disconnect) est toujours effectuée, même si l'écoute s'est interrompue sur une erreur.

Résumé de session

À l'arrêt, un petit résumé récapitule la session, utile en classe et pour le debug :

Résumé :
  mesures reçues       : 3
  mesures stockées     : 3
  erreurs de contrat   : 0
  erreurs de stockage  : 0
  • mesures reçues : messages conformes au contrat MQTT ;
  • mesures stockées : insertions réussies dans iot_events ;
  • erreurs de contrat : messages MQTT ignorés (payload ou topic invalide) ;
  • erreurs de stockage : échecs d'insertion en base.

Message MQTT invalide

Un message qui ne respecte pas le contrat (topic mal formé, champ manquant, type incorrect…) est ignoré sans arrêter l'écoute :

[WARN] Message MQTT ignoré - PAYLOAD_FIELD_MISSING

Le code affiché (TOPIC_PATTERN, PAYLOAD_PARSE, PAYLOAD_FIELD_MISSING, PAYLOAD_FIELD_TYPE, PAYLOAD_VALUE_FORMAT) vient de la taxonomie du contrat MQTT.
Le compteur erreurs de contrat est incrémenté.
Contrairement à une erreur base, un message invalide ne fait pas tomber la commande : on continue d'écouter.

Parcours complet

forge iot:listen est le maillon central d'un flux qui réutilise toutes les commandes IoT déjà disponibles :

forge iot:doctor          # package, config, migration, API HTTP
forge iot:init            # copier la migration vers mvc/migrations/
forge migration:apply     # créer la table iot_events
forge iot:doctor --db     # confirmer que la table est lisible
forge iot:doctor --mqtt   # confirmer que le broker répond
forge iot:listen          # écouter et stocker (laisser tourner)

Dans un second terminal, publie des mesures :

forge iot:simulate --count 3 --interval 1

Les mesures apparaissent dans le terminal forge iot:listen ([OK] …), puis sont lisibles via l'API HTTP :

curl http://localhost:8000/api/iot/events

Gestion des erreurs

Configuration invalide

[ERREUR] Configuration IoT invalide : FORGE_IOT_MQTT_HOST ne peut pas être vide

Exit code 1.
Voir Configuration Forge IoT.

Broker inaccessible

[ERREUR] Connexion MQTT impossible : [Errno 111] Connection refused

Exit code 1.
Le broker n'est pas démarré ou l'hôte/port est faux ; diagnostique avec forge iot:doctor --mqtt.
Pour installer et lancer un broker local, voir Mosquitto local.

Erreurs base

La commande s'arrête au premier échec base (exit code 1), volontairement simple et pédagogique, et distingue trois cas, message sobre (jamais de stacktrace) :

Table iot_events absente :

[ERREUR] Table iot_events absente.
Conseil : lance forge iot:init puis forge migration:apply.

Crée la table (forge iot:init puis forge migration:apply) puis relance forge iot:listen.

Connexion base impossible (MariaDB arrêté, mauvais identifiants, base inconnue…) :

[ERREUR] Connexion base impossible.
Conseil : vérifie forge db:init et forge iot:doctor --db.

Autre erreur SQL (cas générique) :

[ERREUR] Stockage IoT impossible.

Connexion TLS

forge iot:listen bénéficie du TLS via le MqttSubscriber : si FORGE_IOT_MQTT_TLS_ENABLED=true, le subscriber appelle client.tls_set(...) avant de se connecter (ca_certs = FORGE_IOT_MQTT_TLS_CA_FILE si fourni, sinon les certificats système).
Pense à configurer aussi le port TLS du broker (généralement 8883) :

export FORGE_IOT_MQTT_HOST="mqtt.example.net"
export FORGE_IOT_MQTT_PORT="8883"
export FORGE_IOT_MQTT_TLS_ENABLED="true"
export FORGE_IOT_MQTT_TLS_CA_FILE="/etc/ssl/certs/mosquitto-ca.crt"

forge iot:listen

Sans TLS (défaut), la connexion reste en clair, adapté au Mosquitto local.
Détails : Configuration : TLS MQTT.

Limites

forge iot:listen est conçue pour le développement et la pédagogie, pas pour la production.
Sont hors périmètre :

  • pas de daemon systemd ni de mode service ;
  • pas de file d'attente, de retry/backoff, ni de batch insert ;
  • pas de stockage multi-thread ;
  • pas d'authentification avancée (mTLS, ACL côté broker) ;
  • ne lance pas le simulateur (voir forge iot:simulate) ;
  • ne modifie ni l'API HTTP ni le contrat MQTT.

Pour un déploiement réel, on brancherait MqttSubscriber dans un processus supervisé de l'application, ce qui dépasse ce ticket.