Nuova sezione libri disponibile!

Un bot telegram che invia messaggi al verificarsi di eventi sui GPIO del Raspberry Pi

Ludovico Russo

lettura in 6 minuti

Il primo post di quest'anno è stato inspirato da una domanda di un utente su un precedente articolo, che mi chiedeva questo:

"ho implementato il bot senza problemi, mando un comando e mi restituisce quando mi serve, vorrei nel frattempo, monitorare un GPIO, il quale se cambia stato, manda un messaggio al bot senza che io abbia fatto esplicita richiesta con un comando, è possibile farlo ? grazie mille"

Dato che l'idea è molto interessante e permette di lavorare su progetti molto utili, ad esempio un allarme fatto in casa, ho deciso di scrivere un post per spiegare come fare!

Iniziamo quindi, al solito, ad tirare su l'ambinete di sviluppo ed iniziare a lavorare.

Componenti necessari

Il progetto si basa su Raspberry Pi, quindi sarà necessario avere a disposizione in casa questo computerino. Nel mio caso, ho usato un Raspberry Pi Model 3B+ con relativi componenti necessari e su cui ho installato Raspbian Lite, che come sapete è la mia Distro preferita per Rpi. Ovviamente dovrebbe andare bene qualsiasi Distro e qualsiasi versione del Raspberry.

Vi servirà anche un modo per inviare comandi al GPIO di ingresso che invierà il segnale. Nel mio caso, ho usato un semplice bottone connesso al PIN come descritto più sotto.

Setup Ambiante di Sviluppo

Assicuriamoci, una volta entrati nel Raspberry pi, di avere installato python3 (che dovrebbe essere installato di default in Raspbian).

A questo punto, dobbiamo installare virtualenv con il comando

python3 -m venv env

E siamo finalmente pronti a lanciare il nostro ambiente virtuale ed installare le dipendenze:

  1. telepot per creare il nostro bot,
  2. RPi.GPIO per interagire con i GPIO del Raspberry PI.
$ mkdir bot-telegram && cd bot-telegram
$ python3 -m venv env && source ./env/bin/activate
(env)$ pip install telepot RPI.GPIO

Notate che, a differenza di quello fatto nei miei precedenti tutorial, questa volta ho installato l'ambiente virtuale con il comando python3 -m venv env, e che stiamo usando Python 3 invece che Python 2.

Creiamo il BOT

Creiamo un file chiamato bot.py (o come preferite) e apriamolo con un qualsiasi editor di testo (io uso vim, ma voi potete usare quello che volete).

Come punto di partenza, prendiamo il codice che trovate nel mio precedente tutorial. Ho dovuto solo modificare la linea print 'Listening ...' con print('Listening ...') in quanto questa volta usiamo Python3 invece che Python2.

import telepot

def on_chat_message(msg):
    content_type, chat_type, chat_id = telepot.glance(msg)
    if content_type == 'text':
        bot.sendMessage(chat_id, 'ciao, sono un bot molto stupido!')

TOKEN = '*** inserisci il tuo token qui  ***'

bot = telepot.Bot(TOKEN)
bot.message_loop(on_chat_message)

print('Listening ...')

import time
while 1:
    time.sleep(10)

Come sapete, questo bot è un semplicissimo bot che risponde a qualsiasi messaggio con un semplice 'ciao, sono un bot molto stupido!'. Se volete più informazioni su come scrivere questo codice o sapere esattamente cosa fa vi consiglio di rileggere il mio primo articolo su Telegram e Python. Non credo sia necessario ripetermi qui.

Altro consiglio, dato che questo bot è super testato, prima di andare avanti lanciatelo e provate almeno una volta che funziona. Saprete, in futuro, che se qualcosa non funziona è colpa di quello che avete aggiunto dopo :D

Callback e GPIO

Se avete letto questi articoli, vi ricorderete che quando parlo della funzione on_chat_message vi metto in guardia sul fatto che questa funzione non viene mai chiamata direttamente dal nostro codice, ma è la libreria telepot che si occupa di invocarla quando qualcuno scrive un messaggio al bot. In gergo, questo tipo di funzioni vengono chiamate callback, e vengono usate ogni volta che creiamo un programma che deve gestire eventi che vengono generati esternamente al programma stesso.

Le funzioni di callback, oltre ad essere definite, devono anche essere registrate all'evento che devono gestire. Ogni libreria o tool che usiamo ha un modo proprio di gestire le registrazioni, ad esempio, in telepot la registrazione avviene con la riga bot.message_loop(on_chat_message), in cui essenzialmente diciamo al nostro bot:

Hey bot! Ogni volta che qualcuno ti scrive un messaggio, chiama gentilmente la funzione on_chat_message. Si occuperà lei di generare la risposta.

Perchè ho fatto questa lunga premessa? Il motivo è semplice, anche il cambio dello stato di un GPIO (in ingresso) del Raspberry Pi è un evento esterno al programma, quindi deve essere gestito in un modo simile :)

Ed infatti, la libreria RPi.GPIO mette a disposizione un modo per registrare una funzione di callback quando lo stato di un GPIO cambia. Questa funzione è la seguente:

GPIO.add_event_detect(PIN, EVENT, callback=cfunc)

e che prende i seguenti parametri:

  1. PIN è il numero del GPIO che vogliamo "ascoltare".
  2. EVENT è il tipo di evento a cui vogliamo rispondere. Ci sono 3 tipi di eventi:
    • GPIO.RISING: risponde all'evento cambio stato da LOW a HIGH.
    • GPIO.FALLING: risponde all'evento cambio stato da HIGH a LOW.
    • GPIO.BOTH: risponde indistintamente ad entrambi gli eventi.
  3. callback, il nome della funzione di Callback che dobbiamo chiamare al verificarsi dell'evento.

Capito questo, il resto è facile. Per prima cosa, dobbiamo creare una funzione che invia un messaggio tramite il nostro bot. La cosa è molto facile, infatti basta implementare questo:

def bot_cb(pin):
    print('il pin {} ha cambiato stato'.format(pin))
    bot.sendMessage(admin_id, 'il pin {} ha cambiato stato'.format(pin))

ed attaccare questa funzione al nostro PIN di input nel seguiente modo:

INPIN = 2

GPIO.setmode(GPIO.BCM)
GPIO.setup(INPIN, GPIO.IN)

GPIO.add_event_detect(INPIN, GPIO.BOTH, bot_cb)

Notate che, a differenza del caso normale in cui il bot risponde ad una chat, in questo caso il bot deve conoscere a priori l'id chat a cui mandare il messaggio. Ci sono vari modi per farlo, ma il più semplice è embeddare nel codice il proprio chat id. Basta quindi definire la variabile admin_id = 00000000 (con il proprio chat id) e poi usarla per inviare il messaggio.

Per scoprire il proprio chat id ci sono vari modi, il più immediato è quello di usare uno dei bot disponibili su telegram, come @chatid_echo_bot, che vi risponderà con il vostro chat id a qualsiasi messaggio gli invierete.

Programma Completo

Il programma finale, quindi, è il seguente:

import telepot
import RPi.GPIO as GPIO

admin_id = 0000000 # Inserisci il chat id di chi deve ricevere il messagio
INPIN = 2
TOKEN = '*** INSERISCI IL TUO TOKEN ***'

GPIO.setmode(GPIO.BCM)
GPIO.setup(INPIN, GPIO.IN)

def on_chat_message(msg):
    content_type, chat_type, chat_id = telepot.glance(msg)
    if content_type == 'text':
        bot.sendMessage(chat_id, 'ciao, sono un bot molto stupido!')

bot = telepot.Bot(TOKEN)
bot.message_loop(on_chat_message)

def bot_cb(pin):
    print('il pin {} ha cambiato stato'.format(pin))
    bot.sendMessage(admin_id, 'il pin {} ha cambiato stato'.format(pin))

GPIO.add_event_detect(INPIN, GPIO.BOTH, bot_cb)

print('Listening ...')

import time
while 1:
    time.sleep(10)

Test con un bottone

Per testare il tutto, ho creato un semplicissimo circuito con un pulsante sul Raspberry, collegato al GPIO 2 secondo il seguente schema:

Schema Collegamenti

Il bot funziona bene, ci sono alcuni problemi che non ho voluto risolvere perchè questo test è (appunto), un semplice test di funzionamento e non un vero e proprio caso d'uso.

In particolare, a causa dei rimbalzi meccanici delle perti interne del bottone, capita che la funzione di callback venga chiamata più volte quando il bottone cambia stato. Questo è normale ed anche facilmente risolvibile, ma non ho voluto complicare il codice per un esempio di questo tipo.

Che ne pensate?

Avete in mente applicazioni e casi d'uso dove è richiesto che un raspberry invii messaggi a qualcuno quando lo stato di un pin (od un sensore in generale) cambia? Io si, e la mia idea consiste anche nel dover fare un po' di analisi di immagini. Quindi aspettatevi a breve un nuovo tutorial!!!!

Ti è piaciuto questo post?

Registrati alla newsletter per rimanere sempre aggiornato!

Ci tengo alla tua privacy. Leggi di più sulla mia Privacy Policy.

Ti potrebbe anche interessare

Installiamo ROS su Raspberry Pi
Un breve tutorial su come utilizzare ROS sul Raspberry Pi
Un IDE web Arduino sviluppato in Python e Flask
Un mio progetto dell'estate del 2015 che permette di programmare Arduino da un'interfaccia Web esposta da un Raspberry Pi
Utilizziamo Atom come editor di testo remoto su Raspberry Pi
Come usare Atom come editor di testo remoto per Raspberry Pi
Accendere led con Arduino e Telegram
Un bot telegram in grado di controllare Arduino realizzato da 3 ragazzi del Liceo Stampacchia
Implementiamo un bot Telegram con Python
Una semplice guida per iniziare a muovere i primi passi nello sviluppo di chatbot Telegram con Python
Implementiamo un bot Telegram con Python - I Comandi
Vediamo come gestire i comandi del nostro bot in Telegram
Sviluppiamo un bot Telegram che legge i codici a barre degli alimenti
Implementiamo un bot Telegram in grado di leggere ed analizzare le immagini per la lettura ed interpretazione dei codici a barre
I chatbot possono Parlare? Sviluppiamo un bot telegram che manda messaggi vocali
Usiamo le API di sintesi vocale di google per creare un bot in grado di mandare messaggi vocali
Buildare e usare container Docker per Raspberry Pi
In questa guida vediamo come buildare ed utilizzare Docker su Raspberry Pi (ed in generale sistemi Linux Embedded) per velocizzare la produzione di applicazioni Linux Embedded
Robot Open Source - Docker e Raspberry
È disponibile il video "Docker e Raspberry".
Setup Wifi super semplice per Raspbian Lite
Vi propongo un trucchetto per gestire in modo semplicissimo il WiFi su Raspbian (Lite).
Abilitare l'accesso SSH del raspberry pi senza usare un monitor
Un piccolo trucco per gestire al meglio lo sviluppo su Raspberry Pi, specialmente se non si ha a disposizione un monitor.
Passive income con Raspberry Pi e earnapp
Come guadagnare un po' di soldi senza muovere un dito usando un raspberry pi e una connessione ad internet