
Quando ho deciso di integrare un pulsante per tapparelle Tuya nella mia rete domestica – una rete tutta basata su MQTT, senza Home Assistant né altri colossi – ero convinto che avrei semplicemente trovato un gateway già pronto su GitHub. Dopotutto, ogni cosa ha già la sua libreria, no?
Spoiler: non questa volta.
Il pellegrinaggio fra i repository abbandonati
La prima ora l’ho passata aprendo e chiudendo repository:
- Tuya-MQTT di Elias Kotlyar sembrava la scelta giusta, finché non ho visto che l’ultimo commit risaliva al 2021 e che il supporto ai dispositivi era limitato a lampadine e ventilatori.
- tinytuya-api-server – dello stesso autore di TinyTuya – si fermava al discovery via UDP: niente invio comandi, adatto a trovare IP e nulla più.
- localtuya, il celebre componente di Home Assistant, funzionava benissimo… a patto di installare Home Assistant. Non volevo caricare un’intera piattaforma su un server che in LAN fa solo Mosquitto e qualche script.
- Altri fork sparsi (“tuya-mqtt-python” e simili) compilavano, ma cadevano su dipendenze non mantenute o su README pieni di TODO.
A mezzanotte ho realizzato che stavo spendendo più tempo a patchare progetti moribondi che non ci avrei messo a scriverne uno mio da capo. Ho aperto il terminale, importato TinyTuya e ho iniziato così:
import tinytuya, json
dev = tinytuya.Device(ID, IP, KEY)
dev.set_version("3.3")
print(json.dumps(dev.status(), indent=2))
Il device rispondeva. Non c’era più motivo di procrastinare.
Il primo script: funziona, ma spamma
Il mio “gateway 0.1” era un while True
che interpellava status()
ogni dieci secondi e pubblicava il JSON su Mosquitto:
while True:
state = json.dumps(dev.status()["dps"])
mqtt.publish("tuya/device/status", state)
time.sleep(10)
Sì, funzionava – e intasava il broker con pacchetti identici. La soluzione è venuta subito: cache dell’ultimo stato e ripubblicazione soltanto se qualcosa cambia o se passano sessanta secondi.
Dai numeri indecifrabili a un topic leggibile
Vedere tuya/bf26d7fbfbfdb40eadqm3f/set
non mi entusiasmava. Ho scritto una piccola slugify
che normalizza il nome del dispositivo (“Pulsante Per Tapparella (Wi-Fi BLE)”) in pulsante_per_tapparella_wi_fi_ble
. Così i topic sono diventati:
tuya/pulsante_per_tapparella_wi_fi_ble/status
tuya/pulsante_per_tapparella_wi_fi_ble/set
Più umani, zero collisioni.
Il primo vero step: ricevere i comandi
Pubblicare era facile, ma volevo anche ascoltare …/set
e inoltrare subito il comando al dispositivo. TinyTuya mette a disposizione set_dps_multiple
, ma molte guide indicano ancora set_multiple
. Il mio script doveva funzionare con entrambe le versioni della libreria. Ho scelto un semplice “se c’è, usalo; altrimenti manda i DPS uno per uno”:
if hasattr(dev, "set_dps_multiple"):
dev.set_dps_multiple(dps_map, nowait=False)
else:
for dps, value in dps_map.items():
dev.set_value(dps, value, nowait=False)
I messaggi di log si sono trasformati in qualcosa del genere:
[RAW] tuya/pulsante_per_tapparella_wi_fi_ble/set -> {"1":"open"}
[CMD] pulsante_per_tapparella_wi_fi_ble <- {1: 'open'}
[ACK] pulsante_per_tapparella_wi_fi_ble -> {'Err': 0}
Se vedevo Err: 0
sapevo che la tapparella si stava muovendo.
Quote, timeout e thread – tutte le piccole grane
- Quote Gate: su Windows CMD, chi pubblicava
mosquitto_pub -m '{"1":"open"}'
mandava in realtà i singoli apici nel payload, rendendo il JSON invalido. Ho risolto sbucciando eventuali virgolette esterne prima di farejson.loads()
. - Socket bloccati: un dispositivo offline mi congelava il loop. Ho ridotto il timeout con
set_socketTimeout(2)
e ho spostato il polling in un thread per ogni device; se uno dorme, gli altri continuano. - Spam risolto: cache + force-refresh di sessanta secondi tengono il traffico pulito.
Metterlo in produzione: l’unit file systemd
A quel punto mancava solo l’autostart. Sul mio Ubuntu Server la ricetta è stata:
[Service]
User=utente
WorkingDirectory=/home/utente/tuya-mqtt-bridge
ExecStart=/home/utente/tuya-mqtt-bridge/venv/bin/python bridge.py
Restart=on-failure
Con systemctl enable --now tuya-bridge
il gioco è fatto: il gateway parte al boot, riavvia se crasha, logga tutto in journalctl -u tuya-bridge
.
Perché alla fine “costruirlo” ha battuto “cercarlo”
- Peso leggero: due dipendenze, meno di 30 MB di RAM.
- Controllo completo: se domani cambio broker, basta una riga.
- Zero cloud: il dispositivo continua a funzionare anche senza Internet.
- Esperienza didattica: posso mostrare il codice agli studenti, spiegare threading, caching, logging e MQTT in un unico esempio compatto.
- Soddisfazione: vedere la tapparella obbedire a
mosquitto_pub -m '{"1":"open"}'
alle tre del mattino non ha prezzo.

TL;DR – Ho passato più tempo a patchare repo abbandonati che a scrivere 250 righe di Python. Se hai bisogno di un gateway “strano”, forse il vero shortcut è aprire l’editor e cominciare a digitarlo tu. La REPO: https://github.com/il-prof-f-a/tuya_mqtt_simple_bridge