Table of Contents

5. MQTT komunikace

Cíle cvičení

  1. Obousměrná UART komunikace s aplikací na PC
  2. Komunikace s MQTT brokerem

Komunikace po UART

Pro komunikaci po UART použijeme třídu UnbufferedSerial, která umožňuje vyvolat při příchodu dat na sériový port Thunderboardu přerušení. V ISR pak provedeme potřebnou akci, např. změnu stavu LED diod.

#include <mbed.h>
 
UnbufferedSerial serial_port(USBTX, USBRX, 115200);
DigitalOut R_LED(LED0); // LED0 = PD8 ~ RED, LED1 = PD9 ~ GREEN
DigitalOut G_LED(LED1);
 
void serial_isr()
{
    char c;
    if (serial_port.read(&c, 1))
    {                             // Read the data to clear the receive interrupt.
        serial_port.write(&c, 1); // Echo the input back to the terminal.
        if (c == 'r')
            R_LED = !R_LED;
        if (c == 'g')
            G_LED = !G_LED;
    }
}
 
int main()
{
    serial_port.attach(serial_isr, SerialBase::RxIrq);
    while(1) {}
}

POkud je po sériové lince poslán znak r, změní se stav červené LED, znak g změní stav zelené LED. Abyste nemuseli případně kód kompilovat, můžete využít již hotový binární soubor unbuffered.zip, který rozbalte a nahrajte do Thunderboardu připojeném jako disk.

MQTT komunikace

Aby bylo možné komunikovat, je třeba mít přístup na MQTT server, tzv. broker. Je buď možné využít veřejně dostupný (např. HiveMQ, vytvořit si vlastní instanci v cloudu (např. Heroku, Google) nebo si vytvořit vlastní, klidně na svém počítači. Patrně nejznámějším volně dostupným MQTT brokerem je Mosquitto. Pro naše účely využijeme volně přístupný broker na adrese https://mqtt.eclipseprojects.io/.

MQTT protokol

Na Internetu lze najít řadu článků o tom, jak MQTT funguje (v češtině např. tento). My se pro naše účely spokojíme s následujícím

MQTT client - subscriber

Pro vytvoření odběratele zpráv použijeme knihovnu paho-mqtt. Následující kód přečte dvě zprávy ze všech zpráv (topic # reprezentuje všechny zprávy), které v okamžiku připojení brokerem procházejí.

import paho.mqtt.subscribe as subscribe
 
topics = ['#']
 
m = subscribe.simple(topics, hostname="mqtt.eclipseprojects.io", retained=False, msg_count=2)
for a in m:
    print(a.topic)
    print(a.payload)

Pochopitelně nepotřebujeme přijímat všechny zprávy, ale pouze zprávy, které přijímat chceme. Následující kód se přihlásí k odběru topicu nsi/test a může přijímat zprávy, které do něj někdo pošle. Použijeme také asychronní zpracování dat pomocí callback funkce print_msg(), která se zavolá v okamžiku, kdy se v topicu objeví zpráva:

import paho.mqtt.subscribe as subscribe
 
def print_msg(client, userdata, message):
    print("%s : %s" % (message.topic, message.payload))
 
subscribe.callback(print_msg, "nsi/test", hostname="mqtt.eclipseprojects.io")

MQTT - publisher

Aby se v topicu objevila zpráva, je třeba ji tam publikovat.

import paho.mqtt.publish as publish
 
publish.single("nsi/test", "nazdar!", hostname="mqtt.eclipseprojects.io")

Data lze publikovat asychronně, jako v předchozím příkladu (nebo např. stisknutím tlačítka na embedded zařízení), nebo synchronně s využitím časovače. Můžeme použít např. časovač z knihovny Qt:

from PyQt6.QtCore import * 
from PyQt6.QtGui import * 
from PyQt6.QtWidgets import *
import paho.mqtt.publish as publish
 
def message():
    publish.single("nsi/test", "nazdar!", hostname="mqtt.eclipseprojects.io")
 
def hello():
    print("hello")
 
if __name__ == '__main__':
    app = QApplication([])
 
    timer = QTimer()
    timer.timeout.connect(message)
    timer.start(1000)
 
    dlg = QDialog()
 
    layout = QVBoxLayout()
    button = QPushButton("hello")
    button.clicked.connect(hello)
    layout.addWidget(button)
    dlg.setLayout(layout)
 
    dlg.show()
    app.exec()