in Tutorial

Tutorial – Utilizzare MQTT con Python (Parte 2): Callback e Loop

Nell’articolo precedente è stata introdotta la classe Client del modulo paho.mqtt.client, assieme alle sue modalità di connessione, sottoscrizione e pubblicazione verso un broker MQTT.
Due aspetti fondamentali dell’implementazione Python di questo Client MQTT sono rappresentati dalle possibilità di utilizzo delle funzioni di callback e dai loop

Cosa si intende per callback? Le callback sono delle funzioni che vengono passate come parametro di ingresso ad altre funzioni, per essere utilizzate al loro interno. Ciò permette di potere aggiungere dei comportamenti nuovi associati alla funzione di partenza, non presenti nell’originale implementazione. Un esempio molto semplice di come implementare un meccanismo di questo genere in Python potrebbe essere il seguente:

def func(callback):
    callback()
def new_func():
    print("callback!")
func(new_func)


La maniera in cui la classe Client è progettata ricorda una piattaforma ad eventi: ad ogni evento che si verifica, viene associata una funzione particolare che lo cattura, lo processa. Le funzioni di callback sono utilizzate, in questo contesto, per potere personalizzare le operazioni di cattura degli eventi con delle istruzioni non native alla classe. A differenza dell’esempio presentato poco fa, però, la classe Client ha definito dentro di sé una serie di callback predefinite che possiamo liberamente modificare a seconda dei nostri scopi.


Ad ogni tipo di evento corrisponde una callback: modificarne le istruzioni permetterà di ottenere un comportamento ben preciso associato alla cattura di quello specifico evento. Gli eventi previsti sono in totale 7, con le loro rispettive callback, riportati nella tabella sottostante.

Evento Callback
   
Connessione on_connect()
Disconnessione on_disconnect()
Sottoscrizione on_subscribe()
Annullamento sottoscrizione on_unsubscribe()
Pubblicazione messaggio on_publish()
Ricezione messaggio on_message()
Disponibilità log on_log()

L’altro aspetto cruciale della classe Client è l’utilizzo dei loop per la gestione del traffico dati. Quando viene chiamata una funzione di loop, il Client inizia a processare eventi di rete ad intervalli regolari; questi eventi includono l’inoltro di messaggi pubblicati, la sottoscrizione ad un topic, la ricezione di messaggi in arrivo, ecc.; queste funzioni costituiscono lo scheletro su cui si fonda il funzionamento della classe Client.
I due tipi di loop da prendere in considerazione sono:

  • loop_forever(), che blocca il thread in cui viene eseguito;
  • loop_start()/loop_stop(), che inizializza un thread dedicato per la gestione del traffico di messaggi MQTT.

Un esempio di codice che sfrutta questi concetti è fornito qui di seguito, come semplice implementazione di un client che ci avvisa con delle stampe a video ogni qual volta si effettua la connessione al broker (attivo sulla stessa macchina su cui eseguiamo questo codice) o si riceve un messaggio sul topic test, stampandone il contenuto:

from paho.mqtt.client import Client

client = Client(client_id = "Subscriber_test")

def on_connect(client, userdata, flags, rc):
    print("Connesso con successo")

def on_message(client, userdata, message):
    print( message.payload.decode() )

client.on_connect = on_connect
client.on_message = on_message

client.connect("localhost")
client.subscribe("test")
client.loop_forever()

N.B. 

message.payload

è un oggetto di tipo bytes,

decode()

lo rende una stringa.

Da questo estratto si nota come le funzioni di callback vengono definite come nuove funzioni che vanno poi a sovrascrivere le versioni native dell’oggetto client, tramite le operazioni di assegnamento nelle righe 10 e 11. I parametri in ingresso alle funzioni rappresentano dati del client che possono tornare utili, in questo caso si è utilizzata la variabile message, che contiene un attributo payload che rappresenta il contenuto del messaggio MQTT ricevuto.

Il prossimo semplice programma utilizza i concetti del primo articolo per effettuare la pubblicazione di messaggi da terminale verso il topic test:

from paho.mqtt.client import Client

client = Client("Publisher_test")

def on_publish(client, userdata, mid):
    print("Messaggio pubblicato")

client.on_publish = on_publish

client.connect("localhost")
client.loop_start()

messaggio = input("Inserisci il testo da inviare al topic test")
client.publish(topic = "test", payload = messaggio)

client.loop_stop()
client.disconnect()

A questo punto basterà avviare il broker (negli articoli precedenti si è scelto di utilizzare Mosquitto, più informazioni in questo articolo) ed eseguire i due programmi per osservare il corretto scambio dei messaggi tra i due client.

Scrivi un commento

Commento

  1. Davvero un’ottima guida!!!… Mi servirebbe un consiglio su come poter associare a due variabili i messaggi pubblicati su due Topic.