MQTT API
Qui viene descritto come connettere dispositivi di qualsiasi tipo, in grado di comunicare con il protocollo MQTT.

Requisiti

Affinché possiate integrare i vostri dispositivi è necessario aver configurato come scheda Master una delle nostre schede o un nostro dispositivo Gateway.

MQTT

MQTT è l’acronimo di Message Queuing Telemetry Transport e indica un protocollo di trasmissione dati TCP/IP basato su un modello di pubblicazione e sottoscrizione che opera attraverso un apposito Message Broker.
La scheda Master del Sistema (o il Gateway che forniamo in impianti privi di schede) fa le veci del Broker, quindi il dispositivo è ad essa che si deve connettere.

Connessione al Broker

Dall'applicazione tecnico potete ottenere l'indirizzo IP della scheda Master, quindi per la connessione al Broker è sufficiente definire:
  • Porta: 1883
  • Indirizzo Server: IP scheda Master
Consigliamo di impostare un indirizzo IP statico per la scheda Master, per evitare che questo cambi in seguito a riavvii della scheda o del router.

Publish

I topic per la pubblicazione degli stati non devono avere un formato particolare, ma è importante che siano univoci per ciascun input e output che desiderate integrare; è invece importante che il messaggio contenga soltanto il valore.
Quindi se vogliamo integrare un sensore di temperatura, il topic potrebbe essere test/temperatura e il messaggio il valore numerico che vogliamo comunicare.
Non ci sono vincoli sull'origine del valore numerico, potrebbe ad esempio trattarsi di un valore di temperatura ottenuto tramite internet sfruttando qualche API Meteo, o in seguito alla digitazione di un valore da tastiera.
Di seguito il formato del valore da inviare a seconda del tipo di elemento:
  • Sensore: invio del valore numerico con . come separatore decimale (es. 23.4).
  • Input: inviare 0 nel caso di input verificato, 1 se verificato.
  • Output Digitale (relè): 0 se disattivo, 1 se attivo.
  • Output Analogico: valore tra 1 (o valore minimo di dimmerazione) e 255 (o valore massimo di dimmerazione) se attivo, mentre se è disattivo va inviato 0 e separato dai : il valore dell'output prima di essere disattivato (es. 0:130).
  • Variabile Virtuale: numero intero o decimale (con il . come separatore decimale).

Subscribe

Nel caso si voglia integrare un output va definito anche il topic per la ricezione delle richieste. Anche in questo caso non ci sono vincoli, se non la definizione di topic univoci per ciascun output.
Il topic per la ricezione delle richieste potrebbe essere ad esempio out_1/comando, e a seconda del tipo di richiesta il messaggio sarà:
  • on: per l'attivazione dell'output
  • off: per la disattivazione
  • Valore tra 0 e 255: se l'uscita è analogica viene inviato un valore numerico (0 corrisponde alla minima intensità, 255 alla massima)
Anche in questo caso non è obbligatorio che il comando sia inviato ad un output reale, o comunque connesso fisicamente al dispositivo che volete integrare, ma tale valore potrebbe essere allegato ad una richiesta HTTP o ad un messaggio via bus seriale.

Esempi

Il codice sottostante (in Python) è stato testato su un Raspberry Pi, e permette di integrare un sensore DHT, per l'invio di temperatura e umidità:
import Adafruit_DHT
import time
import uuid
import paho.mqtt.client as mqtt
disconnected = False
last_message_sent = time.time()
class SuperClient(mqtt.Client):
def loop(self, timeout=1.0, max_packets=1):
time.sleep(0.001)
return super(SuperClient, self).loop()
class DHTSensor(object):
def __init__(self, pin):
self.pin = pin
self.temperature = 0.0
self.humidity = 0.0
self.old_temperature = 0.0
self.old_humidity = 0.0
self.last_update = 0
def check(self) -> bool:
return self.old_humidity != self.humidity or self.old_temperature != self.temperature
def upate(self) -> bool:
if time.time() - self.last_update > 5:
self.old_humidity = self.humidity
self.old_temperature = self.temperature
humidity, temperature = Adafruit_DHT.read(sensor=Adafruit_DHT.DHT22, pin=self.pin)
if None not in [humidity, temperature]:
self.humidity = round(float(humidity), 1)
self.temperature = round(float(temperature), 1)
self.last_update = time.time()
return self.check()
return False
# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
global disconnected
disconnected = False
# The callback for when the client receives a CONNACK response from the server.
def on_disconnect(client, userdata, rc):
global disconnected
disconnected = True
def set_client(host):
try:
global mqtt_client
client_id = "rasp-" + str(uuid.uuid4())
mqtt_client = SuperClient(client_id=client_id, clean_session=True)
# Set callbacks methods
mqtt_client.on_connect = on_connect
mqtt_client.on_disconnect = on_disconnect
mqtt_client._host = host
mqtt_client._port = 1883
mqtt_client._keepalive = 60
#mqtt_client.max_queued_messages_set(queue_size=1)
# Start connection
mqtt_client.loop_start()
mqtt_client.reconnect()
except:
pass
def update_via_mqtt(sensor: DHTSensor):
global mqtt_client
try:
mqtt_client.publish(topic=f"rasp/dht/humidity/{sensor.pin}", payload=f"{sensor.humidity}", qos=0, retain=True)
mqtt_client.publish(topic=f"rasp/dht/temperature/{sensor.pin}", payload=f"{sensor.temperature}", qos=0, retain=True)
except:
pass
set_client(host="x.x.x.x")
sensors = [DHTSensor(pin=19), DHTSensor(pin=26)]
# Set client loop
while True:
for sensor in sensors:
if sensor.upate():
update_via_mqtt(sensor=sensor)
if time.time() - last_message_sent > 10:
for sensor in sensors:
update_via_mqtt(sensor=sensor)
last_message_sent = time.time()
time.sleep(0.1)