Domotique — Networking
Le réseau domotique leukOS relie les devices physiques, les cartes de contrôle, la box locale et les interfaces utilisateur. Chaque protocole intervient à une couche précise afin de ne jamais exposer directement le matériel au smartphone ou à Internet.

Communication entre les interfaces, la box, les contrôleurs et les circuits. Cliquer pour ouvrir le schéma en pleine résolution.
Vue d'ensemble des communications
Le smartphone ne commande normalement jamais un relais ou une vanne directement. Il appelle le hub local, qui valide l'action et la transmet au contrôleur concerné. Le retour d'état remonte ensuite par le chemin inverse.
Rôle et état des protocoles
| Protocole | Usage | État dans leukOS |
|---|---|---|
| UART | Heartbeat, mesures et commandes entre le daemon et un MCU local | Implémenté par le Device Bridge |
| TCP/IP | Transport commun à HTTP, MQTT, WebSocket et gRPC | Implémenté |
| HTTP/REST | États, commandes et onboarding | Implémenté |
| WebSocket | Mise à jour temps réel de la Web IHM | Implémenté |
| MQTT | États, présence, commandes et discovery | Implémenté en réseau local |
| Ethernet / PoE | Réseau filaire stable et alimentation possible | Architecture cible supportée |
| Wi-Fi | Accès smartphone et contrôleurs IP sans câble | Supporté par l'OS et la topologie |
| Bluetooth / BLE | Provisioning de proximité | Scénario prévu, pas encore intégré au daemon |
| mDNS / DNS-SD | Découverte automatique sur le LAN | Service externe possible ; intégration native à ajouter |
| X.509 / mTLS | Identité et chiffrement mutuels | Vérification X.509 implémentée ; MQTT mTLS à finaliser |
UART — liaison directe avec une carte
UART est utilisé lorsqu'un microcontrôleur est raccordé physiquement à la box, par
exemple sur /dev/ttyUSB0 ou /dev/ttyACM0. Le Device Bridge ouvre le port en mode non
bloquant, applique le débit configuré et sonde périodiquement la carte.
{
"device_bridge": {
"enabled": true,
"probe_interval_s": 15,
"plugins": [
{
"name": "arduino_atmega2560",
"enabled": true,
"transport": "serial",
"port": "/dev/ttyUSB0",
"baud": 115200,
"heartbeat_cmd": "PING\n",
"heartbeat_ack": "PONG"
}
]
}
}
Le cycle réel vérifie le port, configure termios, envoie PING, attend PONG pendant
300 ms, puis met à jour connected, last_seen_ts et last_error. Une réponse telle que
temperature=21.4 humidity=48 peut également être convertie en métriques.
Extrait simplifié de l'ouverture série :
int fd = open(plugin.port.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
termios tty{};
tcgetattr(fd, &tty);
cfmakeraw(&tty);
cfsetispeed(&tty, B115200);
cfsetospeed(&tty, B115200);
tty.c_cflag |= CLOCAL | CREAD;
tcsetattr(fd, TCSANOW, &tty);
UART convient aux cartes proches de la box. Il évite une dépendance réseau, mais sa portée et le nombre de périphériques restent limités par le câblage et les ports disponibles.
TCP/IP — transport commun du réseau local
TCP assure une livraison ordonnée et fiable entre la box, les contrôleurs Ethernet/Wi-Fi et les interfaces. Il transporte notamment :
- l'API HTTP locale du daemon sur le port
8080; - l'API et la Web IHM du hub Go sur le port
8123; - MQTT via Mosquitto sur le port
1883; - les WebSockets de mise à jour temps réel ;
- gRPC sur le port
9080lorsqu'il est activé.
TCP ne définit pas le sens métier d'un message : HTTP, MQTT, WebSocket ou gRPC fournissent la structure applicative au-dessus de la connexion.
MQTT — bus de messages local
MQTT découple les producteurs et les consommateurs. Un contrôleur publie son état sans connaître les interfaces qui l'afficheront ; le hub publie une commande sans ouvrir une liaison spécifique vers chaque circuit.
| Topic | Sens | Contenu |
|---|---|---|
openautomation/<node_id>/status | node → broker | online ou LWT offline retenu |
openautomation/<node_id>/state | node → broker | État JSON publié environ toutes les 2 secondes |
openautomation/<node_id>/cmd/relay/<id> | broker → node | on, off ou toggle |
openautomation/<node_id>/cmd/valve/<id> | broker → node | open, close ou open:600 |
# Observer la présence et les états du node
mosquitto_sub -h 127.0.0.1 -t 'openautomation/node-0001/#' -v
# Allumer un relais
mosquitto_pub -h 127.0.0.1 \
-t 'openautomation/node-0001/cmd/relay/relay1' \
-m 'on'
# Ouvrir une vanne pendant dix minutes
mosquitto_pub -h 127.0.0.1 \
-t 'openautomation/node-0001/cmd/valve/garden' \
-m 'open:600'
Le Last Will and Testament annonce automatiquement offline si un client disparaît
brutalement. Sur un réseau partagé, le listener anonyme doit être remplacé par des comptes,
des ACL et TLS.
Communication entre le smartphone et le circuit
Ce chemin évite d'exposer les protocoles des PCB au navigateur. Le hub applique l'authentification et les règles métier, puis l'interface affiche le retour réel du circuit plutôt que la seule intention de l'utilisateur.
Le frontend Vue utilise l'API REST pour son chargement initial, puis maintient un WebSocket
sur /api/websocket. Il reçoit ainsi les événements state_changed sans interroger le hub
en permanence.
Plug and Play sécurisé
Le plug-and-play automatise l'arrivée d'un contrôleur sans confondre découverte et confiance.
:::info État actuel de l'implémentation Le daemon implémente la réception d'une découverte, la vérification X.509, l'allowlist, le registre SQLite et l'activation manuelle. La découverte mDNS/DNS-SD doit aujourd'hui être réalisée par un service externe. Le transport MQTT avec mTLS et la génération d'ACL dynamiques restent à finaliser. :::
Configuration sécurisée
{
"secure_network": {
"enabled": true,
"require_activation": true,
"require_crl": false,
"discovery_ttl_s": 300,
"ca_cert_path": "/etc/leukos/pki/ca.crt",
"crl_path": "/etc/leukos/pki/crl.pem",
"mqtt_topic_prefix": "home",
"allowed_device_ids": [
"HOME-CTRL-000001",
"HOME-CTRL-000002"
]
}
}
Le service de découverte externe construit un document similaire :
{
"device_id": "HOME-CTRL-000001",
"ip": "192.168.20.41",
"device_type": "room-controller",
"firmware": "1.4.2",
"service": "_homecontroller._tcp.local",
"cert_pem": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n"
}
Puis il appelle l'API locale :
# Soumettre le contrôleur à la vérification
curl -X POST http://127.0.0.1:8080/secure/discover \
-H 'Content-Type: application/json' \
--data-binary @discovery.json
# Lister les devices vérifiés en attente
curl http://127.0.0.1:8080/secure/pending
# Affecter le contrôleur à la pièce « salon »
curl -X POST \
http://127.0.0.1:8080/secure/activate/HOME-CTRL-000001/salon
# Contrôler le registre complet
curl http://127.0.0.1:8080/secure/devices
La vérification C++ refuse le device si le certificat est absent, si son Common Name
ne correspond pas au device_id, si la chaîne n'est pas signée par la CA locale, si la
CRL l'interdit ou si l'identifiant n'appartient pas à l'allowlist.
Scénarios de mise en réseau
1. Réseau domotique local isolé
La box et les contrôleurs sont reliés à un switch ou à un point d'accès dédié, sans route
vers Internet. La box peut exécuter dnsmasq pour fournir DHCP et DNS.
Smartphone ─ Wi-Fi local ─ Box leukOS ─ Switch ─ Contrôleurs
├─ DHCP/DNS
├─ Hub Go
└─ MQTT
Ce scénario maximise l'autonomie. Le smartphone doit simplement rejoindre ce Wi-Fi pour accéder à la Web IHM.
2. Cohabitation avec le routeur Internet
La box et les contrôleurs rejoignent le LAN du routeur Internet existant. Le smartphone reste sur son Wi-Fi habituel et atteint la box par son adresse locale ou son nom DNS.
Internet
│
Routeur Internet / Wi-Fi / DHCP
├── Smartphone
├── Box leukOS
└── Contrôleurs Wi-Fi ou switch Ethernet
Dans ce mode :
- le routeur domestique reste le seul serveur DHCP du segment ;
- une réservation DHCP est recommandée pour la box ;
- MQTT et l'API du daemon restent limités au LAN ;
- aucune redirection Internet ne doit exposer
1883,8080ou8123; - l'accès distant passe par un VPN ou un reverse proxy authentifié en TLS.
3. Box leukOS comme point d'accès Wi-Fi
La box crée son propre SSID domotique et distribue les adresses IP. Son interface Ethernet peut rester reliée au routeur Internet comme lien amont, avec routage/NAT facultatif.
Routeur Internet ─ Ethernet ─ Box leukOS )) Wi-Fi domotique
├── Smartphone
└── Contrôleurs Wi-Fi
Même si Internet tombe, le SSID local, le hub, MQTT et les automatismes continuent de fonctionner.
4. VLAN IoT séparé
Les contrôleurs sont placés dans un VLAN IoT. Le smartphone reste sur le LAN utilisateur et le pare-feu n'autorise que l'accès à la Web IHM de la box.
LAN utilisateurs ── HTTPS/WebSocket ── Box leukOS
│
MQTT / management
│
VLAN IoT
Le VLAN IoT ne doit pas initier librement des connexions vers les postes utilisateurs. Les règles autorisent seulement DHCP, DNS, NTP, MQTT vers le broker et les opérations de maintenance nécessaires. mDNS ne traverse pas naturellement les VLAN ; un réflecteur ne doit être ajouté que si la découverte l'exige.
5. Bluetooth/BLE pour la première association
BLE peut simplifier la mise en service d'un contrôleur Wi-Fi qui ne connaît pas encore le SSID :
- le device démarre en mode provisioning BLE ;
- le smartphone détecte son identifiant de proximité ;
- l'application transmet le SSID et un secret Wi-Fi de façon chiffrée ;
- le device rejoint le LAN puis lance l'onboarding X.509 ;
- BLE est désactivé ou réservé à la maintenance.
:::warning Fonctionnalité cible
Ce provisioning BLE décrit le scénario recommandé mais n'est pas encore implémenté dans
le Device Bridge C++ actuel, dont le transport actif est serial. BLE ne doit pas devenir
un canal permanent de commande à la place de MQTT et de l'identité X.509.
:::
Règles de cohabitation réseau
- Un seul DHCP par segment pour éviter des adresses et routes incohérentes.
- Une IP stable pour la box, de préférence par réservation DHCP.
- Pas d'exposition Internet directe des ports techniques.
- Séparation des identités : le secret Wi-Fi ne remplace ni le certificat du device ni l'autorisation applicative.
- ACL par zone : un contrôleur de salon ne publie et ne souscrit qu'aux topics qui lui sont nécessaires.
- Fonctionnement hors ligne : DNS local, MQTT, API, Web IHM et automatismes ne doivent pas dépendre d'un service cloud.
Diagnostic rapide
# Interfaces, adresses et route par défaut
ip address
ip route
# Ports attendus
ss -lntp | grep -E ':(1883|8080|8123|9080)\b'
# Daemon, hub et flux MQTT
curl http://127.0.0.1:8080/status
curl http://127.0.0.1:8123/api/
mosquitto_sub -h 127.0.0.1 -t '#' -v
# Ports UART présents
ls -l /dev/ttyUSB* /dev/ttyACM* 2>/dev/null