🛠 Client MQTT : télémétrie IoT légère sur la Pico W
Objectifs
MQTT est LE protocole des objets connectés : léger (en-tête de 2 octets), pub/sub, adapté aux liens radio instables. L'exemple officiel MQTT client figure dans pico_w/wifi/ du dépôt pico-examples (C SDK) ; en MicroPython, tu peux parler MQTT sans dépendance en construisant les paquets à la main sur une socket TCP — excellent pour comprendre le protocole. Tu implémenteras CONNECT + PUBLISH QoS 0, le pattern de toute télémétrie de capteurs.
Matériel
- 1 × Raspberry Pi Pico W + firmware MicroPython
_picow - Un broker MQTT joignable sur le LAN (Mosquitto sur un NAS/Raspberry Pi 5, ou broker public de test — attention aux données envoyées)
- Console série 115200 bauds ; port TCP 1883 ouvert sur le broker
Code complet
# mqtt_pub.py — MQTT 3.1.1 minimal (CONNECT + PUBLISH QoS 0) sur socket
import machine, network, socket, time, struct
wlan = network.WLAN; wlan.active(True)
if not wlan.isconnected:
wlan.connect('my_ssid', 'my_password')
while not wlan.isconnected:
machine.idle
def remaining_length(n): # encodage varint MQTT
out = b''
while True:
b = n % 128; n //= 128
if n: b |= 0x80
out += bytes([b])
if not n: return out
def connect(sock, client_id):
proto = b'\x00\x04MQTT\x04\x02\x00\x3c' # level 4, clean session,
cid = struct.pack('>H', len(client_id)) + client_id.encode # keepalive 60s
body = proto + cid
sock.send(b'\x10' + remaining_length(len(body)) + body)
return sock.recv(4) # CONNACK 0x20 0x02 0x00 = accepté
def publish(sock, topic, payload):
t = struct.pack('>H', len(topic)) + topic.encode
p = payload.encode if isinstance(payload, str) else payload
body = t + p
sock.send(b'\x30' + remaining_length(len(body)) + body) # QoS 0
s = socket.socket
s.connect(('192.168.1.10', 1883)) # IP de ton broker
print('CONNACK:', connect(s, 'picow-01'))
while True:
publish(s, 'maison/picow/temperature', '21.5')
time.sleep(10)
# En C SDK : exemple officiel pico_w/wifi/mqtt (lwIP). En MicroPython, la
# lib umqtt.simple existe aussi dans micropython-lib.
# >
# n'a pas été vérifiée (hors base documentaire) — le code ci-dessus s'en passe.
Vérification attendue
CONNACK: b'\\x20\\x02\\x00' (code retour 0 = accepté), puis sur le broker : mosquitto_sub -t 'maison/picow/#' affiche un message toutes les 10 s. Coupures Wi-Fi : la socket casse — relance la connexion dans un try/except autour de la boucle pour un vrai comportement terrain.
Erreurs fréquentes
- Mauvais encodage de la longueur restante : les champs « remaining length » sont des varints 7 bits — un paquet mal formaté fait éjecter le client par le broker sans message d'erreur.
- Rester connecté sans
ping: le keepalive annoncé (60 s ici) oblige le client à envoyer PINGREQ (0xC0) sinon le broker le déconnecte — ajoute un ping périodique pour les longues sessions. - Conflit d'
client_id: deux clients avec le même identifiant s'expulsent mutuellement en boucle — unique par carte. - QoS 1/2 attendus : cet exemple ne fait que QoS 0 (fire and forget) ; le PUBACK de QoS 1 n'est pas traité.
- Broker sur le WAN sans TLS : MQTT 1883 en clair sur Internet = identifiants lisibles ; reste sur le LAN ou ajoute un tunnel.
- En C SDK lwIP threadbackground : oublier le verrou d'arch autour des appels socket — voir le tuto SDK.
Autres tutoriels pour cette carte
- Faire clignoter la LED embarquée (elle est derrière la puce Wi-Fi !)
- Se connecter à un réseau Wi-Fi (station, WPA2/WPA3)
- Bouton et potentiomètre sans marcher sur le sans-fil (GPIO libres & ADC)
- Servir une page web depuis la Pico W (socket TCP + HTTP)
- Client HTTP : consommer une API depuis la Pico W
- Heure exacte via NTP : l'horloge temps réel des projets connectés
Exemples de code pour cette carte
clignotante.pyPythonbouton-interruption.pyPythonpwm-servo.pyPythonlecture-adc.pyPythonneopixel.pyPythonoled-i2c.pyPython