Questa è la quarta parte della serie PiGarden. Nella parte 3 abbiamo montato l’hardware; adesso gli diamo un cervello. Installiamo lo script che comanda i relè, il pannello web per usarlo dal browser e il «traduttore» che lo fa parlare con Home Assistant. Non serve essere programmatori: si copiano dei comandi e ti spiego cosa fanno. L’indice della serie è in fondo.
Tre programmi, tre compiti
Il cuore di tutto è piGarden, un progetto open source di lejubila.net: uno script che apre e chiude le elettrovalvole pilotando i GPIO del Raspberry, controlla il sensore pioggia e tiene le schedulazioni. Da solo basterebbe per irrigare. Intorno a lui ne uso altri due, e per ricordarli mi aiuta un paragone con un cantiere:
- piGarden è il capo cantiere: è l’unico che sa davvero come si apre una valvola.
- piGardenWeb è il telecomando con lo schermo: un pannello web (un’applicazione Laravel) per comandare le zone dal browser.
- mqttconnector è l’interprete: traduce i messaggi MQTT che arrivano da Home Assistant in ordini che il capo cantiere capisce.
Il mio Raspberry è un Pi 3 Model B+ con Raspberry Pi OS 10 (Buster), PHP 7.3 e nginx. La versione dello script è la 0.6, quella di piGardenWeb la 0.6.2.

Guarda il disegno. Al centro c’è piGarden, che ascolta su una porta TCP interna (la 8084): è come un citofono, ma installato dentro casa, che solo il Raspberry stesso può raggiungere. Chi vuole dare un ordine ci «bussa»: lo fa il pannello web, lo fa mqttconnector. Il cron, la sveglia di Linux, si occupa invece dei compiti ricorrenti.
Le parole difficili, tradotte
| Parola | Cosa vuol dire |
|---|---|
| Script Bash | un file di testo con dei comandi che il computer esegue uno dopo l’altro, come una ricetta |
| cron | la sveglia di Linux: esegue un comando a orari o intervalli fissi |
| Porta TCP | un «citofono» numerato su un computer: un programma ci ascolta, un altro ci bussa per parlargli |
| MQTT | un sistema di messaggi nato per la domotica: chi vuole dire qualcosa appende un biglietto su una bacheca, chi è interessato lo legge |
| Broker | la bacheca di MQTT: riceve i biglietti e li consegna a chi si è iscritto |
| Topic | l’etichetta di un biglietto, per esempio pigarden/command: serve a decidere chi legge cosa |
| systemd | il gestore dei servizi di Linux: avvia un programma all’accensione e lo rilancia se si ferma |
Ti preoccupi troppo di ciò che era e di ciò che sarà. C’è un detto: ieri è storia, domani è un mistero, ma oggi è un dono… per questo si chiama presente.
Maestro OogwayPreparare le dipendenze
piGarden usa alcuni strumenti di base, jq per leggere i dati in formato JSON e WiringPi, la libreria che permette di comandare i GPIO con il comando gpio:
sudo apt-get update
sudo apt-get install -y git curl gzip grep sed ucspi-tcp jq
WiringPi si compila dai sorgenti:
git clone https://github.com/WiringPi/WiringPi.git
cd WiringPi
./build
gpio -v
L’ultimo comando deve stampare la versione di WiringPi: se lo fa, il Raspberry sa parlare con i suoi pin. Il programma finisce in /usr/local/bin/gpio, percorso che ritroveremo nella configurazione.
Installare piGarden
cd
git clone https://github.com/lejubila/piGarden.git
sudo cp ~/piGarden/conf/piGarden.conf.example /etc/piGarden.conf
sudo nano /etc/piGarden.conf
Tutta la configurazione sta in /etc/piGarden.conf. È un file lungo, ma le voci che contano sono poche: le vediamo una alla volta.
Tipo di valvola e logica del relè
GPIO="/usr/local/bin/gpio"
EV_MONOSTABLE=1
RELE_GPIO_CLOSE=0
RELE_GPIO_OPEN=1
EV_MONOSTABLE=1 dice a piGarden che le valvole sono monostabili: restano aperte finché il relè le alimenta e si chiudono da sole quando smette. È il caso delle Hunter PGV che ho scelto. RELE_GPIO_OPEN e RELE_GPIO_CLOSE indicano quale livello del GPIO fa scattare il relè: dipende dalla scheda che usi, e nella parte 3 c’è il mio caso.
Con valvole monostabili l’alimentazione deve essere in 24 V corrente alternata. Un alimentatore in corrente continua mi ha bruciato i solenoidi: ne parlo nella parte 3.
Le zone e i pin
Ogni zona è un’elettrovalvola con un nome (alias) e un pin GPIO. Sono quelli della tabella della parte 3:
EV_TOTAL=5
EV1_ALIAS="1"
EV1_GPIO=17
EV2_ALIAS="2"
EV2_GPIO=27
EV3_ALIAS="3"
EV3_GPIO=12
EV4_ALIAS="4"
EV4_GPIO=18
EV5_ALIAS="5"
EV5_GPIO=23
Ho usato alias numerici, così i comandi restano brevi (open 3) e coincidono con le zone che vedrai in Home Assistant.
Sensore pioggia e porta interna
RAIN_GPIO=25
RAIN_GPIO_STATE=1
NOT_IRRIGATE_IF_RAIN_SENSOR=86400
TCPSERVER_IP="127.0.0.1"
TCPSERVER_PORT="8084"
NOT_IRRIGATE_IF_RAIN_SENSOR=86400 impedisce di avviare le zone per 24 ore (86.400 secondi) dopo una pioggia rilevata. Il server TCP resta in ascolto solo su localhost: è la «porta del citofono» a cui si collegano piGardenWeb e mqttconnector, e non ha motivo di essere raggiungibile dalla rete.
Due trappole sul sensore pioggia. Se non hai il sensore, lascia RAIN_GPIO vuoto: un pin scollegato viene letto come pioggia permanente e tutte le zone si rifiutano di partire. E se sostituisci il sensore, controlla RAIN_GPIO_STATE: due sensori diversi possono avere polarità opposte, e con quella sbagliata ogni zona risponde «ha appena piovuto».
Le voci MQTT
Ultimo blocco: piGarden può pubblicare da solo lo stato dell’impianto su una bacheca MQTT. È così che Home Assistant scopre se una zona è aperta o chiusa.
MQTT_ENABLE=1
MQTT_HOST="<IP-DEL-BROKER>"
MQTT_PORT=1883
MQTT_USER="<UTENTE-MQTT>"
MQTT_PWD="<PASSWORD-MQTT>"
MQTT_TOPIC="pigarden/result"
MQTT_CLIENT_ID=piGarden
Con queste voci piGarden scrive lo stato delle zone sul topic pigarden/result a ogni evento: un’apertura, una chiusura, un controllo della pioggia.
Se MQTT_HOST punta a un indirizzo sbagliato, piGarden non protesta: i messaggi finiscono nel vuoto. Nel mio caso puntava al Raspberry stesso, dove non gira nessun broker. Il sintomo era subdolo: Home Assistant vedeva lo stato solo dopo i comandi partiti da lui, e le chiusure decise dal Raspberry restavano invisibili. Se una zona resta «accesa» in dashboard dopo essersi chiusa, controlla questa riga per prima.
Avvio automatico con il cron
piGarden va inizializzato a ogni accensione e ha bisogno di qualche controllo periodico. Nel crontab dell’utente pi (si apre con crontab -e):
@reboot /home/pi/piGarden/piGarden.sh init
@reboot /home/pi/piGarden/piGarden.sh start_socket_server force
* * * * * /home/pi/piGarden/piGarden.sh check_rain_sensor 2> /tmp/check_rain_sensor.err
*/3 * * * * /home/pi/piGarden/piGarden.sh check_rain_online 2> /tmp/check_rain_online.err
*/5 * * * * /home/pi/piGarden/piGarden.sh close_all_for_rain 2> /tmp/close_all_for_rain.err 1> /dev/null
Le prime due righe (@reboot) si eseguono a ogni riavvio: preparano i GPIO e accendono il «citofono» interno. Le altre tre sono i controlli periodici: leggono il sensore pioggia ogni minuto, interrogano il servizio meteo online ogni tre minuti e chiudono tutte le zone se sta piovendo.
Provare le zone da riga di comando
Prima di aggiungere altro, verifica che lo script comandi davvero i relè. Con l’acqua chiusa a monte, la prima volta:
cd ~/piGarden
./piGarden.sh init
./piGarden.sh open 1
./piGarden.sh ev_status_all
./piGarden.sh close 1
Al comando open 1 devi sentire il «clic» del relè della zona 1; ev_status_all mostra lo stato di tutte le zone e close 1 le richiude. Lo stesso stato si legge in formato JSON con json_status.
Irrigare a tempo: open_in
Per irrigare un tempo preciso serve un comando diverso da open. Si chiama open_in:
./piGarden.sh open_in 0 10 1
Si legge così: «tra 0 minuti apri la zona 1 e chiudila dopo 10». Il primo numero è l’attesa prima dell’apertura (0 vuol dire subito), il secondo è la durata, il terzo è la zona. In coda si può aggiungere force per ignorare il controllo pioggia.
Il comando open accetta solo il numero della zona e, volendo, la parola force: se ci scrivi dietro una durata, viene ignorata. La valvola si apre e resta aperta finché non arriva un close. È una trappola in cui sono caduto io: per irrigare a tempo usa sempre open_in.
Una cosa da sapere: la chiusura la fa una riga di cron che gira ogni minuto, quindi la zona resta aperta tra M e M+1 minuti. In una prova con un timer di 1 minuto la valvola è rimasta aperta 1 minuto e 23 secondi. Per irrigare va benissimo; conta solo se cronometri.
Il pannello web: piGardenWeb
piGardenWeb è il telecomando con lo schermo. È un’applicazione Laravel che si appoggia alla porta interna di piGarden: sul mio Raspberry vive in /home/pi/piGardenWeb, servita da nginx con PHP 7.3, e la dashboard si apre da http://<IP-DEL-RASPBERRY>/admin/dashboard. Da lì si aprono e chiudono le zone e si vedono stato e log.

L’installazione segue la solita strada delle applicazioni Laravel: si scarica il progetto, si installano le dipendenze con Composer e si punta nginx alla cartella pubblica. Il procedimento completo è descritto bene nella guida di lejubila.net e non lo ripeto.
Il pannello non è indispensabile. Nel mio impianto il comando quotidiano passa da Home Assistant, e il pannello resta per le prove e la diagnostica: è comodo per controllare una zona senza uscire dal browser.
mqttconnector: il ponte verso Home Assistant
mqttconnector è l’interprete. Si iscrive a un topic MQTT, gira i comandi alla porta interna di piGarden e pubblica la risposta. Home Assistant non deve sapere nulla di piGarden: appende un biglietto sulla bacheca, e il resto è compito del ponte.
La versione upstream è scritta per Python 2.7, ormai fuori supporto: sul mio Raspberry gira una versione riscritta in Python 3, con la libreria paho-mqtt 1.6.1 (l’ultima compatibile con il Python 3.7 di Buster). L’originale è rimasto come copia di riserva accanto al nuovo file.
La configurazione
Il file principale è /etc/mqttconnector.ini. Qui ci sono la sezione del broker e quella di piGarden (le credenziali vanno nelle voci user e password, che qui ometto):
[mqtt]
broker_address=<IP-DEL-BROKER>
port=1883
client_id=mqttconnector
path_connector=/home/pi/mqttconnector/
subtopic_command=command
subtopic_result=result
[pigarden]
enabled=1
host=127.0.0.1
port=8084
exec_command=exec_cmd2sck.sh
topic=pigarden
result_enable=1
topic_result_qos=0
topic_result_retain=1
Il broker è il Mosquitto di Home Assistant, con un utente dedicato a piGarden. Con topic=pigarden i comandi arrivano su pigarden/command e le risposte escono su pigarden/result.
Il servizio systemd
Perché il ponte parta da solo e si rialzi se cade, lo affido a systemd:
[Unit]
Description=mqttconnector
After=network-online.target
StartLimitIntervalSec=0
[Service]
Type=simple
User=pi
ExecStart=/usr/bin/python3 /home/pi/mqttconnector/mqttconnector.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now mqttconnector
Restart=always con StartLimitIntervalSec=0 fa ripartire il servizio sempre, senza mai fermarsi dopo troppi tentativi. A questo aggiungo una cintura di sicurezza nel crontab, che ogni minuto controlla e riavvia se serve:
* * * * * systemctl is-active --quiet mqttconnector || sudo systemctl restart mqttconnector
Per permettere all’utente pi quel sudo senza password, in /etc/sudoers.d/ ho autorizzato solo quel comando esatto:
pi ALL=(ALL) NOPASSWD: /bin/systemctl restart mqttconnector
I comandi disponibili
Questi sono i «biglietti» che il ponte sa leggere:
| Messaggio | Effetto |
|---|---|
open N | apre la zona N |
open N force | apre la zona N ignorando il controllo pioggia |
open_in 0 M N | apre la zona N subito e la chiude dopo M minuti |
close N | chiude la zona N |
close_all | chiude tutte le zone |
close_all disable_scheduling | chiude tutto e disabilita le schedulazioni |
reboot | riavvia il Raspberry |
Verificare la catena completa
Da un computer con i client Mosquitto, metti un ascolto sul topic dei risultati e manda un comando:
mosquitto_sub -h <IP-DEL-BROKER> -u <UTENTE-MQTT> -P <PASSWORD-MQTT> -t 'pigarden/#' -v
mosquitto_pub -h <IP-DEL-BROKER> -u <UTENTE-MQTT> -P <PASSWORD-MQTT> -t pigarden/command -m 'open 1'
mosquitto_pub -h <IP-DEL-BROKER> -u <UTENTE-MQTT> -P <PASSWORD-MQTT> -t pigarden/command -m 'close 1'
Il primo comando resta in ascolto e stampa ogni biglietto che passa; gli altri due sono un «apri» e un «chiudi» sulla zona 1. Se il relè scatta e sul topic pigarden/result compare la risposta, la catena Home Assistant → MQTT → mqttconnector → piGarden → relè funziona.
Nel prossimo articolo costruiamo la parte di Home Assistant: switch, timer, script e schedulazioni.
Indice della serie PiGarden
- Parte 1 — Progettare l’impianto
- Parte 2 — Componenti e materiali: elettrovalvole, tubi, raccordi, sensore pioggia
- Parte 3 — La centralina: Raspberry Pi, relè e alimentazione
- Parte 4 — Il software: piGarden, piGardenWeb e mqttconnector ← sei qui
- Parte 5 — Integrazione con Home Assistant: switch, timer, script e schedulazioni
Riferimenti: lejubila.net/pigarden per il software open source · github.com/lejubila/piGarden