MQTT & Raspberry Pi Managing Networked Sensors while Dealing with Jargon and (if all goes well) a net-connected cowbell Stewart Russell — @scruss 2017-12-14
“Back in the old days …” Coal Clough Wind Farm - Photo by James Bird, 2009 - CC-BY-ND
MQTT Stands for MQ Telemetry Transport Only faintly related to IBM’s MQ message queue product Allows sensors to talk over TCP/IP As standard as we’re likely to see: ISO/IEC 20922:2016 OASIS standard, 2015 Widely (but quietly) used Extraordinarily jargon-heavy
MQTT Basic Jargon https://micropython-iot-hackathon.readthedocs.io/
MQTT Topic Hierarchy Topics have levels: home/basement/temperature home/basement/humidity home/kitchen/temperature … Wildcard + matches one level: home/+/temperature → home/basement/temperature → home/kitchen/temperature Wildcard # matches all levels: home/#
MQTT: “they thought of that” Quality of Service: each message can be sent At most once: typical for most IoT sensors At least once: may be sent multiple times — important alarms Exactly once: receipt is verified — valuable transactions Last Will A client can register a “will” with the broker should it exit unexpectedly The broker publishes the will as a message for other clients to act upon
Installing a broker Eclipse Mosquitto™ — https://mosquitto.org/ doesn’t seem to require any configuration small and quite well-behaved default port 1883 Raspbian installation: sudo apt install mosquitto mosquitto-clients
MQTT “Hello, World!” On the broker host: mosquitto_sub --topic 'hello/#' On another (or same host): mosquitto_pub [ --host broker_host ] --topic 'hello/world' --message "Hello, World!" Displayed on the broker host: Hello, World!
ESP8266 Wireless sensor board 80 – 160 MHz 32-bit core Multiple digital I/O ports One (slightly weedy) 0 – 1 V ADC Can be very cheap: < $5 / unit Sold under many names: NodeMCU, Huzzah, ESP8266 Thing, WiPy (v1.0) Can be programmed in Lua, Arduino, MicroPython, … By Sparkfun Electronics - https://c1.staticflickr.com/1/494/19681470919_9a9bcd5692_z.jpg, CC BY 2.0, https://commons.wikimedia.org/w/index.php?curid=57331438
MicroPython Real Python 3 — only smaller! Runs on many µc boards from ARM Cortex-M0 up Small memory footprint: can run in under 64 KB RAM Actively targets ESP8266 Many libraries for supporting different sensors/protocols Downside: can’t exactly be called fast … https://micropython.org/
Installing MicroPython Download binary image from https://micropython.org/ Install over USB serial using esptool.py: sudo pip install esptool Provides MicroPython REPL over USB serial at 115200 bps (Optionally) provides MicroPython REPL over WebSockets terminal to browser (configuration required)
ampy, a serial helper Install via pip install adafruit-ampy Uploads and downloads program and data files Manages file folders on your ESP8266 Runs MicroPython scripts with output to the terminal Examples: ampy -p /dev/ttyUSB2 get boot.py > boot.py ampy -p /dev/ttyUSB2 put main-esp8266-MQTT-DHT22-pin4.py /main.py
MicroPython User Interface Typically through two scripts: boot.py — board and network setup main.py — user program
boot.py def do_connect(): import network sta_if = network.WLAN(network.STA_IF) ap_if = network.WLAN(network.AP_IF) if ap_if.active(): ap_if.active(False) print("AP turned off ...") if not sta_if.isconnected(): print('connecting to network...') sta_if.active(True) sta_if.connect('SSID', 'PASSWORD') while not sta_if.isconnected(): pass print('network config:', sta_if.ifconfig()) print("Starting network ...") do_connect()
Sensor Setup DHT22: Cheap temperature (°C) and relative humidity sensor (%) Simple one-wire digital protocol Results to 1 decimal place Max 1 reading / 2 s Can be cranky and decides not to give you a reading sometimes (in MicroPython, at least)
main.py: 1 of 2 import machine import dht import time from umqtt.simple import MQTTClient broker_ip = '192.168.2.109' # broker address client_id = 'wemos024155' print('broker: ', broker_ip) print('client_id: ', client_id) client = MQTTClient(client_id, broker_ip) d = dht.DHT22(machine.Pin(4))
main.py: 2 of 2 while True: time.sleep(5) retry = 0 # retry reading if DHT22 stubborn while retry < 3: try: d.measure() break except: retry = retry + 1 if retry < 3: print(("%6.1f deg C / %6.1f %% RH") % (d.temperature(), d.humidity())) client.connect() client.publish(client_id + '/temperature', str(d.temperature())) client.publish(client_id + '/humidity', str(d.humidity())) client.disconnect()
Local Results! Starting network ... connecting to network... network config: ('192.168.2.72', '255.255.255.0', '192.168.2.1', '192.168.2.1') broker: 192.168.2.109 client_id: wemos024155 20.1 deg C / 30.7 % RH 20.2 deg C / 31.2 % RH 20.1 deg C / 31.3 % RH …
Network Results! $ mosquitto_sub -h 192.168.2.109 -v --topic 'wemos024155/+' wemos024155/temperature 20.6 wemos024155/humidity 30.4 wemos024155/humidity 30.3 wemos024155/humidity 30.3 …
Overnight Results From mqtt-spy https://kamilfb.github.io/mqtt-spy/
Consuming and Creating In Python, Eclipse Paho MQTT Python client library: sudo pip install paho-mqtt This next demo was created using paho-mqtt for Python 3 GPIO Zero https://gpiozero.readthedocs.io MicroPython
🐮🔔
But seriously … BlueLine PowerCost Monitor Clips to Smart Meter and gives power readings every 30 s Given away free by the power authority Talks over 433 MHz RF Doesn’t connect to your network ☹ → just as well we reverse-engineered the protocol! ☺ → stable Arduino implementation over serial Almost the perfect application for a small MQTT device