Come realizzare un bot Telegram e gestirlo con ESP32
Introduzione
Telegram ha incentrato la sua filosofia aziendale sull’open source, cioè la libertà di circolazione del software.
Nel 2015 è stato annunciata la pubblicazione di una nuova API per la gestione dei bot con il microcontrollore ESP32.
Con un semplice software di messaggistica è possibile pilotare e ricevere telemetrie sullo stato di alcune periferiche connesse da remoto, con l’invio di un messaggio di configurazione, o di richiesta di stato.
Con l’introduzione di questa API è stata notevolmente semplificata la gestione di sistemi IOT.
In questo articolo realizzeremo un semplice bot, e analizzeremo il codice per gestire le richieste inviate tramite Telegram.
Cos’è Telegram
Per i pochi che non conoscessero Telegram, faccio una breve introduzione.
Telegram è un’applicazione di messaggistica molto popolare poiché è stata tra le prime ad introdurre funzionalità avanzate sulla privacy e implementato algoritmi di cifratura che rendono le conversazioni indecifrabili.
L’app è multipiattaforme, ci sono versioni disponibili per iOS, Android, Windows, Mac e Linux ed è possibile accedere a Telegram anche tramite un browser web.
Inoltre ha introdotto la possibilità di realizzare un gruppo di chat di grandi dimensioni.
È completamente indipendente e non ha legami con altri social media come Facebook, WhatsApp ecc. oltre ad essere open source come già accennato in precedenza.
Cos’è un bot Telegram
I bot sono delle applicazioni sviluppate da terze parti e che poi sono eseguite all’interno dell’ambiente Telegram.
Proprio per questo motivo è definita un’applicazione open source, poiché ognuno può sviluppare il suo codice per sfruttare le infrastrutture messa a disposizione dall’applicazione Telegram.
Gli utenti possono interagire con i bot inviando loro messaggi, comandi e richieste a linea di comando. I bot sono controllati utilizzando delle richieste HTTPS all’API Bot di Telegram.
In questo progetto realizzerai un semplice bot dove invierai dei comandi predefiniti al server di Telegram, che li memorizzerà in un’area di memoria dedicata al tuo bot.
La scheda ESP32, si connetterà al server di Telegram e leggerà i comandi inviati in precedenza per poi eseguire una decodifica per identificare il comando che deve eseguire.
Creazione di un bot su Telegram
Ovviamente, prima di iniziare il progetto, bisogna scaricare e installare Telegram.
Dopo aver installato Telegram, esegui sulla barra di ricerca il bot “botfather”.
Questo bot è stato creato da Telegram e ci permette di creare altri bot.
Clicca sua “riavvia” e digita “/start”, seleziona “/newbot” dall’elenco dei comandi proposti dal bot, come in figura:
Inserisci il nome del bot e l’username, se la procedura è andata a buon fine Telegram t’invierà un messaggio con il token, un codice alfanumerico univoco, da usare nello Sketch dell’ESP32 che può essere paragonata alla password della nostra mail, per evitare che altri utenti possano accedere al nostro bot.
Conservate il token , poiché senza di esso non sarà possibile accedere al bot.
Nella barra di ricerca, possiamo ricercare il bot che abbiamo appena creato, digitando il nome che abbiamo scelto nella fase di creazione.
La procedura per poter usare il bot non è ancora terminata, abbiamo bisogno della “chatid” del bot, che pouò essere paragonato al tuo indirizzo mail, nella fase lettura dei comandi, per poterli leggere, dobbiamo fornire sia il token che la “chatid”, per potersi autenticare per evitare accessi indesiderati.
La procedura d’identificazione della chatid è molto semplice, basta connettersi al seguente link:
https://api.telegram.org/botXXXXXX/getUpdates
Sostituire alle “X” il token del bot.
Se avete fatto tutto correttamente nella pagina del link si dovrebbe visualizzare il seguente messaggio:
{"update_id":8393,"message":{"message_id":3,"from":{"id":7474,"first_name":"AAA"},"chat":{"id":<group_ID>,"title":""},"date":25497,"new_chat_participant":{"id":71,"first_name":"NAME","username":"YOUR_BOT_NAME"}}}
Cercate l’identificativo “chat id” e il numero che segue è il vostro codice del bot.
Se invece il messaggio visualizzato dovesse essere come il seguente:
{"ok":true,"result":[]}
Dovete aprire il vostro bot e poi effettuare una nuova connessione.
Come in quasi tutti i progetti che ho pubblicato su questo blog, usiamo l’ID di Arduino, ma è necessario installare le librerie per poter usare l’API di Telegram, per inviare e ricevere i dati dal server.
Per questo progetto usiamo le librerie Universal Telegram Bot Librar, scritta da Brian Lough che fornisce una semplice interfaccia per l’API di Telegram.
Codice
In questa applicazione imposterai lo stato di un pin del microcontrollore ESP32 e leggerai la temperatura del sensore DHT22 e lo stato del pin, tutto gestito tramite dei messaggi di richiesta inviati tramite Telegram.
/* Genanro Vitiello Per maggiori approfondimenti cllegati al sito www.quattrodispositivi.it PAbbiamo usato la libreiria di Brian Lough Universal Telegram Bot Library: https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot */ #i#include <WiFi.h> #include <WiFiClientSecure.h> #include <UniversalTelegramBot.h>//libreiria bot scritta da Brian Lough: https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot #include <ArduinoJson.h> //************************************************** // sensore di temperatura #include "DHT.h" #define DHTPIN 25 //il pin d'ingresso del microcontrollore dove e' connesso il sensore // togliere il commento solo al tipo di sensore usato //#define DHTTYPE DHT11 // DHT 11 #define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 //#define DHTTYPE DHT21 // DHT 21 (AM2301) DHT dht(DHTPIN, DHTTYPE); // indichiamo il pin dov e è connesso il sensore e la tipologia //************************************************** // Indica le credenziali del tuo WIFI const char* ssid = "SSID"; const char* password = "Password"; // Inizializzazione bot #define BOTtoken "XXXXXXXXXXXXXXXXXX" // inserisci il tuo toke, che hai ricevuto da Botfather //Inseriamo la chat id cbcla procedura è stata indicata nel post #define CHAT_ID "XXXXXX" WiFiClientSecure client; UniversalTelegramBot bot(BOTtoken, client); // E' ritardo con il quale la nostra applicazione interroga il server di Telegram int botRequestDelay = 1000; unsigned long lastTimeBotRan; const int ledPin = 13; bool ledState = LOW; float h, t; String ts, hs; // Stampiamo sul terminale della seriale indicazioni sul messaggio ricevuto void handleNewMessages(int numNewMessages) { Serial.println("Gestione del messaggio"); Serial.println(String(numNewMessages)); for (int i=0; i<numNewMessages; i++) { // verifichiamo che la chat id sia corretta String chat_id = String(bot.messages[i].chat_id); if (chat_id != CHAT_ID){ bot.sendMessage(chat_id, "Utente non autorizzato", ""); continue; } // Stampiamo sul bot l'elenco dei comandi String text = bot.messages[i].text; Serial.println(text); String from_name = bot.messages[i].from_name; if (text == "/start") { String welcome = "Welcome, " + from_name + ".\n"; welcome += "Use the following commands to control your outputs.\n\n"; welcome += "/led_on to turn GPIO ON \n"; welcome += "/led_off to turn GPIO OFF \n"; welcome += "/state to request current GPIO state \n"; welcome += "/temperatura temperatura \n"; welcome += "/umidita umidita' \n"; bot.sendMessage(chat_id, welcome, ""); } if (text == "/led_on") { bot.sendMessage(chat_id, "lo stato del LED è ON", ""); ledState = HIGH; digitalWrite(ledPin, ledState); } if (text == "/led_off") { bot.sendMessage(chat_id, "lo stato del LED è OFF", ""); ledState = LOW; digitalWrite(ledPin, ledState); } if (text == "/temperatura") { ts = String(t); bot.sendMessage(chat_id, ts, ""); } if (text == "/umidita") { hs = String(h); bot.sendMessage(chat_id, hs, ""); } if (text == "/state") { if (digitalRead(ledPin)){ bot.sendMessage(chat_id, "il LED è acceso", ""); } else{ bot.sendMessage(chat_id, "Il LED è spento", ""); } } } } void setup() { Serial.begin(115200); pinMode(ledPin, OUTPUT); digitalWrite(ledPin, ledState); // Connessione al WIFI WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // aggiungiamo il certificato root per api.telegram.org while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("connessione al WI-FI.."); } // Stampiamo sul terminale della seriale l'IP locale dell'ESP32 Serial.println(WiFi.localIP()); } void loop() { if (millis() > lastTimeBotRan + botRequestDelay) { int numNewMessages = bot.getUpdates(bot.last_message_received + 1); h = dht.readHumidity(); // Leggiamo la temperatura in gradi centigradi t = dht.readTemperature(); Serial.print("Umidita': "); Serial.print(h); Serial.print("% Temperatura: "); Serial.print(t); Serial.println(""); while(numNewMessages) { Serial.println("got response"); handleNewMessages(numNewMessages); numNewMessages = bot.getUpdates(bot.last_message_received + 1); } lastTimeBotRan = millis(); } }
#i#include <WiFi.h> #include <WiFiClientSecure.h> #include <UniversalTelegramBot.h>//libreiria bot scritta da Brian Lough: https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot #include <ArduinoJson.h>
Inseriamo tutte le librerie da usare in seguito, compresa quella per la gestione dell’API di Telegram, se non aveste la libreria ArduinoJson.h, dovete scaricarla dall’ID di Arduino, con la classica procedura.
#include "DHT.h" #define DHTPIN 25 //il pin d'ingresso del microcontrollore dove e' connesso il sensore // togliere il commento solo al tipo di sensore usato //#define DHTTYPE DHT11 // DHT 11 #define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 //#define DHTTYPE DHT21 // DHT 21 (AM2301) DHT dht(DHTPIN, DHTTYPE); // indichiamo il pin dov e è connesso il sensore e la tipologia
In questa parte di codice inseriamo le librerie e la gestione del sensore di
temperatura selezionato.
Mi raccomando, eliminate il commento dal sensore che userete nella vostra applicazione, e commentate tutti gli altri.
// Indica le credenziali del tuo WIFI const char* ssid = "SSID"; const char* password = "Password";
Devi aggiungere le credenziali per l’accesso al tuo WI-FI.
// Inizializzazione bot #define BOTtoken "XXXXXXXXXXXXXXXXXX" // inserisci il tuo toke, che hai ricevuto da Botfather //Inseriamo la chat id cbcla procedura è stata indicata nel post #define CHAT_ID "XXXXXX"
Devi inserire le credenziali del tuo bot, che hai ricavato dalla procedura indicata nel paragrafo precedente.
void handleNewMessages(int numNewMessages) { Serial.println("Gestione del messaggio"); Serial.println(String(numNewMessages)); for (int i=0; i<numNewMessages; i++) { // verifichiamo che la chat id sia corretta String chat_id = String(bot.messages[i].chat_id); if (chat_id != CHAT_ID){ bot.sendMessage(chat_id, "Utente non autorizzato", ""); continue; } // Stampiamo sul bot l'elenco dei comandi String text = bot.messages[i].text; Serial.println(text); String from_name = bot.messages[i].from_name; if (text == "/start") { String welcome = "Welcome, " + from_name + ".\n"; welcome += "Use the following commands to control your outputs.\n\n"; welcome += "/led_on to turn GPIO ON \n"; welcome += "/led_off to turn GPIO OFF \n"; welcome += "/state to request current GPIO state \n"; welcome += "/temperatura temperatura \n"; welcome += "/umidita umidita' \n"; bot.sendMessage(chat_id, welcome, ""); } if (text == "/led_on") { bot.sendMessage(chat_id, "lo stato del LED è ON", ""); ledState = HIGH; digitalWrite(ledPin, ledState); } if (text == "/led_off") { bot.sendMessage(chat_id, "lo stato del LED è OFF", ""); ledState = LOW; digitalWrite(ledPin, ledState); } if (text == "/temperatura") { ts = String(t); bot.sendMessage(chat_id, ts, ""); } if (text == "/umidita") { hs = String(h); bot.sendMessage(chat_id, hs, ""); } if (text == "/state") { if (digitalRead(ledPin)){ bot.sendMessage(chat_id, "il LED è acceso", ""); } else{ bot.sendMessage(chat_id, "Il LED è spento", ""); } } } }
Con questo codice verranno gestiti i messaggi con il bot.
void loop() { if (millis() > lastTimeBotRan + botRequestDelay) { int numNewMessages = bot.getUpdates(bot.last_message_received + 1); h = dht.readHumidity(); // Leggiamo la temperatura in gradi centigradi t = dht.readTemperature(); Serial.print("Umidita': "); Serial.print(h); Serial.print("% Temperatura: "); Serial.print(t); Serial.println(""); while(numNewMessages) { Serial.println("got response"); handleNewMessages(numNewMessages); numNewMessages = bot.getUpdates(bot.last_message_received + 1); } lastTimeBotRan = millis(); } }
Ogni secondo si interroga il server di Telegram, per verificare se ci sono nuovi messaggi.
Conclusioni
Con questa applicazione potrai divertirti e realizzare un sistema domotico, di controllo dispositivi da remoto con innumerevoli applicazioni pratiche.
Spero che questo articolo ti sarà d’aiuto per le tue applicazioni future e abbia stimolato la tua fantasia.
Per qualsiasi dubbio non esitare a scrivermi nel form di seguito e se vuoi ricevere aggiornamenti su nuovi articoli pubblicati su questo blog, iscriviti alla newsletter, trovi il link sull’header del sito.
provo ad inviare l’url direttamente da arduino, ma senza le librerie non funziona. ci sarebbe un modo?
esempio
STRGMYSQL =”https://api.telegram.org/botMYTOKEN/sendmessage?chat_id=MYCHAT&text=test”
ClientMYSQL.print(String(“GET “) + STRGMYSQL + ” HTTP/1.0\r\n” + “Host: api.telegram.org\r\n” + “User-Agent: ESP32\r\n” + “Connection: close\r\n\r\n”);
ciao
il programma funziona benissimo, ma per pochi minuti. sai se è già capitato?
grazie per l’attenzione.
saluti
peppino
Ciao Giuseppe, ho riprovato il sistema e funziona correttamente anche dopo diverse ore. Non so che dirti, potrebbe essere la tua rete di casa, fai un tentativo con l’hotspot del tu telefono.