MiniMQTT Loop
You should always use a loop when writing CircuitPython code which uses the MiniMQTT module. The loop method checks incoming and processes outgoing MQTT messages along with keeping the network connection between your board and the MQTT broker alive.
loop
Calling loop
creates a non-blocking network loop. You can create new code below the call to loop
, and it'll be executed. This type of loop should be run frequently to avoid disconnecting from the MQTT server. The loop
method also does not handle network hardware (WiFi) or MQTT broker disconnection. You'll need to handle that yourself.
Here's an example of using a non-blocking loop.
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries # SPDX-License-Identifier: MIT import os import time import board import busio from digitalio import DigitalInOut import neopixel import adafruit_connection_manager from adafruit_esp32spi import adafruit_esp32spi import adafruit_minimqtt.adafruit_minimqtt as MQTT # Add settings.toml to your filesystem CIRCUITPY_WIFI_SSID and CIRCUITPY_WIFI_PASSWORD keys # with your WiFi credentials. Add your Adafruit IO username and key as well. # DO NOT share that file or commit it into Git or other source control. aio_username = os.getenv("aio_username") aio_key = os.getenv("aio_key") # If you are using a board with pre-defined ESP32 Pins: esp32_cs = DigitalInOut(board.ESP_CS) esp32_ready = DigitalInOut(board.ESP_BUSY) esp32_reset = DigitalInOut(board.ESP_RESET) # If you have an externally connected ESP32: # esp32_cs = DigitalInOut(board.D9) # esp32_ready = DigitalInOut(board.D10) # esp32_reset = DigitalInOut(board.D5) spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) """Use below for Most Boards""" status_light = neopixel.NeoPixel( board.NEOPIXEL, 1, brightness=0.2 ) # Uncomment for Most Boards """Uncomment below for ItsyBitsy M4""" # status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) # Uncomment below for an externally defined RGB LED # import adafruit_rgbled # from adafruit_esp32spi import PWMOut # RED_LED = PWMOut.PWMOut(esp, 26) # GREEN_LED = PWMOut.PWMOut(esp, 27) # BLUE_LED = PWMOut.PWMOut(esp, 25) # status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) ### Adafruit IO Setup ### # Setup a feed named `testfeed` for publishing. default_topic = aio_username + "/feeds/testfeed" ### Code ### # Define callback methods which are called when events occur # pylint: disable=unused-argument, redefined-outer-name def connected(client, userdata, flags, rc): # This function will be called when the client is connected # successfully to the broker. print(f"Connected to MQTT broker! Listening for topic changes on {default_topic}") # Subscribe to all changes on the default_topic feed. client.subscribe(default_topic) def disconnected(client, userdata, rc): # This method is called when the client is disconnected print("Disconnected from MQTT Broker!") def message(client, topic, message): """Method callled when a client's subscribed feed has a new value. :param str topic: The topic of the feed with a new value. :param str message: The new value """ print(f"New message on topic {topic}: {message}") # Connect to WiFi print("Connecting to WiFi...") esp.connect_AP(os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD")) print("Connected!") pool = adafruit_connection_manager.get_radio_socketpool(esp) ssl_context = adafruit_connection_manager.get_radio_ssl_context(esp) # Set up a MiniMQTT Client mqtt_client = MQTT.MQTT( broker="io.adafruit.com", username=aio_username, password=aio_key, socket_pool=pool, ssl_context=ssl_context, ) # Setup the callback methods above mqtt_client.on_connect = connected mqtt_client.on_disconnect = disconnected mqtt_client.on_message = message # Connect the client to the MQTT broker. mqtt_client.connect() photocell_val = 0 while True: # Poll the message queue mqtt_client.loop() # Send a new message print(f"Sending photocell value: {photocell_val}") mqtt_client.publish(default_topic, photocell_val) photocell_val += 1 time.sleep(3)
Here's an example of using a loop with a network interface. In this example, we use the loop to reset the network interface (wifi.reset
) and reconnect the socket to the MQTT broker (mqtt_client.reconnect
)
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries # SPDX-License-Identifier: MIT import os import time import board import busio from digitalio import DigitalInOut import neopixel import adafruit_connection_manager from adafruit_esp32spi import adafruit_esp32spi import adafruit_minimqtt.adafruit_minimqtt as MQTT # Add settings.toml to your filesystem CIRCUITPY_WIFI_SSID and CIRCUITPY_WIFI_PASSWORD keys # with your WiFi credentials. Add your Adafruit IO username and key as well. # DO NOT share that file or commit it into Git or other source control. aio_username = os.getenv("aio_username") aio_key = os.getenv("aio_key") # If you are using a board with pre-defined ESP32 Pins: esp32_cs = DigitalInOut(board.ESP_CS) esp32_ready = DigitalInOut(board.ESP_BUSY) esp32_reset = DigitalInOut(board.ESP_RESET) # If you have an externally connected ESP32: # esp32_cs = DigitalInOut(board.D9) # esp32_ready = DigitalInOut(board.D10) # esp32_reset = DigitalInOut(board.D5) spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) """Use below for Most Boards""" status_light = neopixel.NeoPixel( board.NEOPIXEL, 1, brightness=0.2 ) # Uncomment for Most Boards """Uncomment below for ItsyBitsy M4""" # status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) # Uncomment below for an externally defined RGB LED # import adafruit_rgbled # from adafruit_esp32spi import PWMOut # RED_LED = PWMOut.PWMOut(esp, 26) # GREEN_LED = PWMOut.PWMOut(esp, 27) # BLUE_LED = PWMOut.PWMOut(esp, 25) # status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) ### Adafruit IO Setup ### # Setup a feed named `testfeed` for publishing. default_topic = aio_username + "/feeds/testfeed" ### Code ### # Define callback methods which are called when events occur # pylint: disable=unused-argument, redefined-outer-name def connected(client, userdata, flags, rc): # This function will be called when the client is connected # successfully to the broker. print("Connected to MQTT broker! Listening for topic changes on %s" % default_topic) # Subscribe to all changes on the default_topic feed. client.subscribe(default_topic) def disconnected(client, userdata, rc): # This method is called when the client is disconnected print("Disconnected from MQTT Broker!") def message(client, topic, message): """Method callled when a client's subscribed feed has a new value. :param str topic: The topic of the feed with a new value. :param str message: The new value """ print("New message on topic {0}: {1}".format(topic, message)) # Connect to WiFi print("Connecting to WiFi...") esp.connect_AP(os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD")) print("Connected!") pool = adafruit_connection_manager.get_radio_socketpool(esp) ssl_context = adafruit_connection_manager.get_radio_ssl_context(esp) # Set up a MiniMQTT Client mqtt_client = MQTT.MQTT( broker="io.adafruit.com", username=aio_username, password=aio_key, socket_pool=pool, ssl_context=ssl_context, ) # Setup the callback methods above mqtt_client.on_connect = connected mqtt_client.on_disconnect = disconnected mqtt_client.on_message = message # Connect the client to the MQTT broker. print("Connecting to MQTT broker...") mqtt_client.connect() # Start a blocking message loop... # NOTE: NO code below this loop will execute # NOTE: Network reconnection is handled within this loop while True: try: mqtt_client.loop() except (ValueError, RuntimeError) as e: print("Failed to get data, retrying\n", e) esp.reset() time.sleep(1) esp.connect_AP( os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD") ) mqtt_client.reconnect() continue time.sleep(1)
MiniMQTT Client Identifier
By default, MiniMQTT will generate a unique, randomly generated client identifier based off the CircuitPython device's microcontroller's UUID and a random number. The broker will see a client named something like cpy-3123
If you'd like to set a custom client_id
(what the broker sees the CircuitPython device as), you can provide a string. Do make sure the client_id
's you create are unique, or your broker will disconnect them.
client = MQTT.MQTT( broker="io.adafruit.com", username=aio_username, password=aio_key, client_id='brentspyportal' )
MiniMQTT Logging
MiniMQTT uses the CircuitPython logger module for printing different types of errors, depending on the priority the logger was set to.
To attach a logger to a MiniMQTT client, simply:
client = MQTT.MQTT( broker="io.adafruit.com", username=aio_username, password=aio_key, log=True )
Then, you will need to add another line setting the logger's level. While the logger is initialized to the INFO level by default, you may want to see more information about your current MQTT session.
To set the logger to a higher priority logging level, like DEBUG, add the following line after the MQTT client has been initialized:
client.set_logger_level(DEBUG)
MiniMQTT Last Will and Testament
MiniMQTT supports setting publishing a message to a specific topic when your MQTT client disconnects.
- For more information about MQTT's Last Will - check this guide.
To use the last will - specify the topic
you'd like to publish to and provide it with a message
to publish when the client disconnects.
client.will_set('device/status/','Goodbye!')
This method must be called before the connect method. The last will and testament also must be allowed by your MQTT Broker - Adafruit IO does not support this feature.