Python

На плате Графит-S3 предустановлен интерпретатор CircuitPython, который позволяет писать программы на упрощённом python.

Для работы с MQTT используем библиотеку adafruit_minimqtt. Всё, что нам нужно сделать для её установки — это скопировать файл adafruit_minimqtt.mpy в папку lib на накопителе CIRCUITPY.

Более подробно о работе с библиотеками CircuitPython мы писали в одном из ранних наших уроков: Библиотеки для CircuitPython

Программа

Для составления программы используем среду разработки Mu.

Пусть, тестовая программа будет каждые пять секунд отправлять MQTT брокеру значение обычного счётчика. Начнём с подключения всех необходимых библиотек. Помним, что в python это делается с помощью команды import.

Кроме adafruit_minimqtt нам будут нужны еще три библиотеки:

  • time — предоставляет функцию sleep для организации паузы;
  • wifi — нужен для работы с wifi;
  • socketpool — нужен для работы с сетью, в принципе.

Итак, минимальная программа для отправки сообщений.

import time
import wifi
import socketpool

import adafruit_minimqtt.adafruit_minimqtt as MQTT

ssid = 'X-COM-CITADEL' # имя точки доступа WiFi
password = 'id7dq8d-' # пароль к точке доступа WiFi
mqtt_username = 'user_3ad51bab' # имя пользователя MQTT
mqtt_password = '************' # пароль пользователя MQTT
broker = 'mqtt.robotclass.ru' # адрес MQTT брокера

sensor_feed = 'user_3ad51bab/data'

print(f"Подключаемся к {ssid}...")
wifi.radio.connect(ssid, password)
print("успешно")

pool = socketpool.SocketPool(wifi.radio)

mqtt_client = MQTT.MQTT(
    broker=broker,
    username=mqtt_username,
    password=mqtt_password,
    client_id='user_3ad51bab_env',
    socket_pool=pool
)

print(f"Подключаемся к MQTT брокеру {broker}...")
mqtt_client.connect()
print("успешно")

val = 0
while True:
    print(f"Отправляем значение: {val}...")
    mqtt_client.publish(sensor_feed, val)
    print("успешно")
    val += 1
    time.sleep(5)

Загружаем программу на Графит-S3 и смотрим панель управления на смартфоне. Число в блоке data должно увеличиваться на единицу каждые 5 секунд.

А в мониторе последовательного порта среды Mu появится такой вывод:

Подключаемся к X-COM-CITADEL...
успешно
Подключаемся к MQTT брокеру mqtt.robotclass.ru...
успешно
Отправляем значение: 0...
успешно
Отправляем значение: 1...
успешно
Отправляем значение: 2...

Такой вывод означает, что сообщения были успешно отправлены брокеру MQTT.

Приём сообщений

Теперь изменим программу так, чтобы наше устройство смогло ещё и получать сообщения от MQTT брокера.

Пусть при нажатии кнопки в панели управления на плате Графит-S3 включается или выключается штатный светодиод.

Для начала напишем обработчики событий MQTT: подключение, отключение, получение сообщения. Эти функции-обработчики будут вызывать каждый раз, когда происходит соответствующее событие.

def connected(client, userdata, flags, rc):
    # эта функция будет вызвана, когда клиент успешно подключится к брокеру
    print(f"успешно подключен к брокеру")
    # подписываемся на сообщения с указанной темой 
    client.subscribe(switch_feed)

def disconnected(client, userdata, rc):
    # эта функция будет вызвана, когда клиент отключится от брокера
    print("успешно отключен от брокера")

def message(client, topic, message):
    # эта функция будет вызвана, когда клиент получит новое сообщение
    print(f"пришло сообщение с темой {topic}: {message}")

Затем укажем их в настройках объекта mqtt_client.

mqtt_client.on_connect = connected
mqtt_client.on_disconnect = disconnected
mqtt_client.on_message = message

В суперцикл программы добавим вызов обработчика событий:

while True:
    mqtt_client.loop(timeout=1)

Чтобы не пропустить события избавимся от явной паузы в суперцикле: time.sleep(5). Организуем отправку сообщений с помощью таймаута.

Итак, полный код программы:

import time
import board
from digitalio import DigitalInOut, Direction

import wifi
import socketpool

import adafruit_minimqtt.adafruit_minimqtt as MQTT

ssid = 'X-COM-CITADEL' # имя точки доступа WiFi
password = 'id7dq8d-' # пароль к точке доступа WiFi
mqtt_username = 'user_3ad51bab' # имя пользователя MQTT
mqtt_password = '************' # пароль пользователя MQTT
broker = 'mqtt.robotclass.ru' # адрес MQTT брокера

sensor_feed = 'user_3ad51bab/data'
switch_feed = 'user_3ad51bab/switch'

sensor_timeout = 5
sensor_next = 0

def connected(client, userdata, flags, rc):
    # эта функция будет вызвана, когда клиент успешно подключится к брокеру
    print(f"успешно подключен к брокеру")
    # подписываемся на сообщения с указанной темой 
    client.subscribe(switch_feed)

def disconnected(client, userdata, rc):
    # эта функция будет вызвана, когда клиент отключится от брокера
    print("успешно отключен от брокера")

def message(client, topic, message):
    # эта функция будет вызвана, когда клиент получит новое сообщение
    print(f"пришло сообщение с темой {topic}: {message}")
    led.value = message=="1" and 1 or 0

# настраиваем светодиод
led = DigitalInOut(board.LED)
led.direction = Direction.OUTPUT

print(f"Подключаемся к {ssid}...")
wifi.radio.connect(ssid, password)
print("успешно")

pool = socketpool.SocketPool(wifi.radio)

mqtt_client = MQTT.MQTT(
    broker=broker,
    username=mqtt_username,
    password=mqtt_password,
    client_id='user_3ad51bab_env',
    socket_pool=pool
)

mqtt_client.on_connect = connected
mqtt_client.on_disconnect = disconnected
mqtt_client.on_message = message

print(f"Подключаемся к MQTT брокеру {broker}...")
mqtt_client.connect()

val = 0
while True:
    mqtt_client.loop(timeout=1)
    
    t = time.monotonic()
    if( t > sensor_next ):
        sensor_next = t + sensor_timeout
        print(f"Отправляем значение: {val}...")
        mqtt_client.publish(sensor_feed, val)
        print(f"успешно")
        val += 1

Загружаем программу на Графит-S3 и открываем консоль интерпретатора.

Теперь при нажатии на кнопку на панели управления сработает функция-обработчик message и штатный светодиод зажжётся, а в консоли появится соответствующий текст:

Подключаемся к X-COM-CITADEL...
успешно
Подключаемся к MQTT брокеру mqtt.robotclass.ru...
успешно подключен к брокеру
Отправляем значение: 0...
успешно
Отправляем значение: 1...
успешно
Отправляем значение: 2...
успешно
пришло сообщение с темой user_3ad51bab/switch: 1
Отправляем значение: 3...
успешно
Примечание. Панель управления MQTT Dash при нажатии кнопки отправляет строку «1» или «0». Именно поэтому для изменения состояния светодиода мы делаем так:
led.value = message==»1″ and 1 or 0

Изменено: