Skip to content

Instantly share code, notes, and snippets.

@ccooper21
Created October 16, 2017 00:17
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ccooper21/cf956344c0a1428a0c1a9aa71edd4205 to your computer and use it in GitHub Desktop.
Save ccooper21/cf956344c0a1428a0c1a9aa71edd4205 to your computer and use it in GitHub Desktop.
Example MicroPython MQTT over WebSocket script
# This example script requires the MicroPython changes in the following branches:
#
# https://github.com/ccooper21/micropython/tree/websocket-client-support
# https://github.com/ccooper21/micropython-lib/tree/umqtt.simple-websocket-support
import usocket as socket
import utime as time
from websocket import websocket
from umqtt.simple import MQTTClient
# Create a TCP socket and connect it to the MQTT broker
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
addr = socket.getaddrinfo(b'broker.mqttdashboard.com', 8000)[0][-1]
s.connect(addr)
# Negotiate the WebSocket protocol upgrade via HTTP. This is most easily
# done by simulating an HTTP request with the necessary headers. There is no
# need to bust out a full HTTP implementation.
#
# TODO: Generate the value for the "Sec-WebSocket-Key" header dynamically.
s.write(b'''\
GET /mqtt HTTP/1.1\r
Host: broker.mqttdashboard.com:8000\r
Connection: Upgrade\r
Upgrade: websocket\r
Sec-WebSocket-Key: aSk+xCH/A9ZbxvqjxF8itg==\r
Sec-WebSocket-Version: 13\r
\r
''')
# TODO: Validate the response to the websocket upgrade request. This can be
# done by checking the HTTP response code and validating the
# "Sec-WebSocket-Accept" header.
l = s.readline()
while l:
if l == b'\r\n':
break
l = s.readline()
# Now that the WebSocket protocol upgrade negotiation is complete, create a
# WebSocket from the TCP socket connected to the MQTT broker.
ws = websocket(s)
# Create an MQTT client
#
# TODO: Generate the client ID dynamically.
keepalive = 60
client = MQTTClient('clientId-g47Izb6dPK', sock=ws, keepalive=keepalive)
def on_message_received(topic, message):
print('Message received: topic=%s, message=%s' % (topic, message))
client.set_callback(on_message_received)
# Publish messages to and receive messages from the MQTT broker forever
connected = False
topic = b'testtopic/1'
while True:
if not connected:
print('Connecting...')
client.connect()
connected = True
last_publish = 0
last_ping = time.ticks_ms()
print('Connected')
print('Subscribing to topic %s...' % (topic,))
client.subscribe(topic)
print('Subscribed')
else:
# Periodically ping the broker consistently with the "keepalive"
# argument used when connecting. If this isn't done, the broker will
# disconnect when the client has been idle for 1.5x the keepalive
# time.
if time.ticks_ms() - last_ping >= keepalive * 1000:
client.ping()
last_ping = time.ticks_ms()
# Every 5 minutes publish a message for fun.
if time.ticks_ms() - last_publish >= 5 * 60 * 1000:
print('Publishing a message to topic %s...' % (topic,))
client.publish(topic, 'Coming from MicroPython via a websocket @%d' % (time.ticks_ms(),))
last_publish = time.ticks_ms()
print('Published')
# Receive the next message if one is available, and handle the case that
# the broker has disconnected.
try:
client.check_msg()
except OSError as e:
if str(e) == '-1':
ws.close()
connected = False
print('Connection closed')
continue
# Sleep a little to not needlessly burn processor cycles.
#time.sleep(0.5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment