Se sei un appassionato di elettronica e automazione, sicuramente conosci il microcontrollore ESP8266, che permette di realizzare progetti interessanti e funzionali grazie alla sua connessione Wi-Fi. E se ti dicessi che puoi anche utilizzarlo per creare un bot Telegram? In questo articolo vedremo come realizzare un bot Telegram per ESP8266 con cui potremo interagire ricevendo e inviando comandi.
Prima di iniziare, assicurati di avere un Wemos D1 Mini oppure un NodeMCU nella loro versione con ESP8266
In qualità di affiliato Amazon io ricevo un guadagno dagli acquisti idonei. A voi non costerà nulla di più ma avrete modo di supportare così il mio lavoro per altri progetti. Grazie.
E’ necessario un account Telegram e una chat privata o un gruppo su cui il bot potrà interagire
Passiamo alla parte pratica.
Creazione del bot Telegram
Per creare un bot Telegram, devi innanzitutto registrarlo sul sito ufficiale di Telegram e ottenere il token.
Per fare questo, segui questi semplici passaggi:
- Apri Telegram e cerca il bot “@BotFather”.
- Invia il comando “/newbot” e segui le istruzioni per creare il tuo bot.
- Una volta creato il bot, il BotFather ti fornirà un token. Ricordati di conservarlo, ti servirà per la configurazione del bot sul tuo ESP8266.
Ricapitolando avremo:

Configurazione dell’ESP8266
Per configurare l’ESP8266, ti servirà un ambiente di sviluppo come il framework Arduino IDE. Se non l’hai già installato, puoi scaricarlo gratuitamente dal sito ufficiale. Inoltre, per utilizzare il modulo Wi-Fi dell’ESP8266, dovrai installare la libreria ESP8266WiFi. Puoi seguire l’articolo che avevo scritto qui https://www.lutritech.it/come-programmare-esp8266-con-lide-di-arduino/
- Apri l’IDE di Arduino e crea un nuovo sketch.
- Includi la libreria ESP8266WiFi digitando “#include <ESP8266WiFi.h>”.
- Inserisci le credenziali della tua rete Wi-Fi utilizzando la funzione “WiFi.begin()”.
- Verifica che la connessione Wi-Fi sia attiva utilizzando la funzione “WiFi.status()”.
Programmazione del bot Telegram
Per programmare il bot Telegram, dovrai utilizzare la libreria UniversalTelegramBot.h.
Puoi scaricare la libreria gratuitamente dal repository ufficiale di GitHub
https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot
Vi consiglio questa libreria perché l’ho provata per più progetti ed essendo ottimizzata per la piattaforma ESP8266/ESP32 si evitano i riavvi indesiderati per il crash del sistema.
- Apri il tuo sketch e includi la libreria UniversalTelegramBot.h digitando #include <UniversalTelegramBot.h>
- Crea un’istanza della classe “UniversalTelegramBot” e inserisci il token del bot che hai ottenuto dal BotFather.
- Utilizza la funzione “bot.sendMessage()” per inviare un messaggio alla chat del bot.
Qui sotto il codice completo:
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h> // https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot
// Wifi network station credentials
#define WIFI_SSID "YOUR_SSID"
#define WIFI_PASSWORD "YOUR_PASSWORD"
// Telegram BOT Token (Get from Botfather)
#define BOT_TOKEN "XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
const unsigned long BOT_MTBS = 1000; // mean time between scan messages
X509List cert(TELEGRAM_CERTIFICATE_ROOT);
WiFiClientSecure secured_client;
UniversalTelegramBot bot(BOT_TOKEN, secured_client);
unsigned long bot_lasttime; // last time messages' scan has been done
const int ledPin = LED_BUILTIN;
int ledStatus = 0;
void handleNewMessages(int numNewMessages)
{
Serial.print("handleNewMessages ");
Serial.println(numNewMessages);
for (int i = 0; i < numNewMessages; i++)
{
String chat_id = bot.messages[i].chat_id;
String text = bot.messages[i].text;
String from_name = bot.messages[i].from_name;
if (from_name == "")
from_name = "Guest";
if (text == "/ledon")
{
digitalWrite(ledPin, LOW); // turn the LED on (HIGH is the voltage level)
ledStatus = 1;
bot.sendMessage(chat_id, "Led is ON", "");
}
if (text == "/ledoff")
{
ledStatus = 0;
digitalWrite(ledPin, HIGH); // turn the LED off (LOW is the voltage level)
bot.sendMessage(chat_id, "Led is OFF", "");
}
if (text == "/status")
{
if (ledStatus)
{
bot.sendMessage(chat_id, "Led is ON", "");
}
else
{
bot.sendMessage(chat_id, "Led is OFF", "");
}
}
if (text == "/start")
{
String welcome = "Welcome to Universal Arduino Telegram Bot library, " + from_name + ".\n";
welcome += "This is Flash Led Bot example.\n\n";
welcome += "/ledon : to switch the Led ON\n";
welcome += "/ledoff : to switch the Led OFF\n";
welcome += "/status : Returns current status of LED\n";
bot.sendMessage(chat_id, welcome, "Markdown");
}
}
}
void setup()
{
Serial.begin(115200);
Serial.println();
pinMode(ledPin, OUTPUT); // initialize digital ledPin as an output.
delay(10);
digitalWrite(ledPin, HIGH); // initialize pin as off (active LOW)
// attempt to connect to Wifi network:
configTime(0, 0, "pool.ntp.org"); // get UTC time via NTP
secured_client.setTrustAnchors(&cert); // Add root certificate for api.telegram.org
Serial.print("Connecting to Wifi SSID ");
Serial.print(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(500);
}
Serial.print("\nWiFi connected. IP address: ");
Serial.println(WiFi.localIP());
// Check NTP/Time, usually it is instantaneous and you can delete the code below.
Serial.print("Retrieving time: ");
time_t now = time(nullptr);
while (now < 24 * 3600)
{
Serial.print(".");
delay(100);
now = time(nullptr);
}
Serial.println(now);
}
void loop()
{
if (millis() - bot_lasttime > BOT_MTBS)
{
int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
while (numNewMessages)
{
Serial.println("got response");
handleNewMessages(numNewMessages);
numNewMessages = bot.getUpdates(bot.last_message_received + 1);
}
bot_lasttime = millis();
}
}
Spostiamoci su Telegram e avviamo il nostro bot:

Cliccando su /ledon il led sulla nostra scheda Wemos D1 mini si illuminerà


In modo analogo cliccando su /ledoff il led integrato del Wemos D1 mini si spegnerà


Questo è un esempio semplice di come si può utilizzare il Bot Telegram con ESP8266. Nell’articolo https://www.lutritech.it/blynk-energia-gratuita/ avevamo realizzato la stessa cosa, ma con un lavoro ben più articolato. Per cose semplici, come inviare comandi e ricevere notifiche, trovo che utilizzare questo metodo sia nettamente molto più veloce e alla portata di tutti.
Rilevatore di fumi smart con Telegram
Ho deciso di riadattare lo sketch del rilevatore di fumi smart utilizzando il Bot di Telegram senza utilizzare Blynk Legacy. Qui sotto trovate la nuova versione.
//https://www.lutritech.it/
//https://www.youtube.com/@lutritech
//
//ponticellando D4 con GND si entra in modalità configurazione wifi
//ponticellando D4 con GND per più di 5 secondi si cancellano le configurazioni delle rete wifi salvate
#include <MQ2.h>
#include <ESP8266WiFi.h>
#include <time.h>
#include <Timezone.h> // https://github.com/JChristensen/Timezone
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h> //https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot
#include <ArduinoJson.h> //https://github.com/bblanchon/ArduinoJson
#define TRIGGER_PIN D4
#define BOT_TOKEN "XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" //t.me/ProvaEsp8266bot.
#define CHAT_ID "XXXXXXXX"
int pin = A0;
int soglia = 200; //ppm
float lpg, co, smoke;
String welcome;
MQ2 mq2(pin);
// wifimanager can run in a blocking mode or a non blocking mode
// Be sure to know how to process loops with no delay() if using non blocking
bool wm_nonblocking = false; // change to true to use non blocking
WiFiManager wm; // global wm instance
WiFiManagerParameter custom_field; // global param ( for non blocking w params )
const unsigned long BOT_MTBS = 1000; // mean time between scan messages
unsigned long bot_lasttime; // last time messages' scan has been done
X509List cert(TELEGRAM_CERTIFICATE_ROOT);
WiFiClientSecure secured_client;
UniversalTelegramBot bot(BOT_TOKEN, secured_client);
void handleNewMessages(int numNewMessages)
{
Serial.print("handleNewMessages ");
Serial.println(numNewMessages);
for (int i = 0; i < numNewMessages; i++)
{
String chat_id = bot.messages[i].chat_id;
String text = bot.messages[i].text;
String from_name = bot.messages[i].from_name;
if (from_name == "")
from_name = "Guest";
if (text == "/statoAria")
{
bot.sendMessage(CHAT_ID, "ppm Fumo: " + String(smoke) + "\nppm CO:" + String(co) + "\nppm lpg:" + String(lpg));
}
if (text == "/start")
{
bot.sendMessage(CHAT_ID, welcome);
}
}
}
void setup() {
WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP
Serial.begin(115200);
Serial.setDebugOutput(true);
delay(3000);
Serial.println("\n Starting");
pinMode(TRIGGER_PIN, INPUT);
if (wm_nonblocking) wm.setConfigPortalBlocking(false);
// add a custom input field
int customFieldLength = 40;
// test custom html(radio)
const char* custom_radio_str = "<br/><label for='customfieldid'>Custom Field Label</label><input type='radio' name='customfieldid' value='1' checked> One<br><input type='radio' name='customfieldid' value='2'> Two<br><input type='radio' name='customfieldid' value='3'> Three";
new (&custom_field) WiFiManagerParameter(custom_radio_str); // custom html input
wm.addParameter(&custom_field);
wm.setSaveParamsCallback(saveParamCallback);
// custom menu via array or vector
std::vector<const char *> menu = {"wifi", "info", "param", "sep", "restart", "exit"};
wm.setMenu(menu);
// set dark theme
wm.setClass("invert");
wm.setConfigPortalTimeout(30); // auto close configportal after n seconds
bool res;
res = wm.autoConnect("AutoConnectAP"); // anonymous ap
if (!res) {
Serial.println("Failed to connect or hit timeout");
// ESP.restart();
}
else {
//if you get here you have connected to the WiFi
Serial.println("connected...yeey :)");
}
// calibra il sensore
mq2.begin();
// attempt to connect to Wifi network:
configTime(0, 0, "pool.ntp.org"); // get UTC time via NTP
secured_client.setTrustAnchors(&cert); // Add root certificate for api.telegram.org
welcome = "Benvenuto nel Bot LutriTech per il monitoraggio dell'aria ";
welcome += "/statoAria: ti invio subito i dati rilevati dal sensore \n";
bot.sendMessage(CHAT_ID, welcome);
}
void checkButton() {
// check for button press
if ( digitalRead(TRIGGER_PIN) == LOW ) {
// poor mans debounce/press-hold, code not ideal for production
delay(50);
if ( digitalRead(TRIGGER_PIN) == LOW ) {
Serial.println("Button Pressed");
// still holding button for 5000 ms, reset settings, code not ideaa for production
delay(5000); // reset delay hold
if ( digitalRead(TRIGGER_PIN) == LOW ) {
Serial.println("Button Held");
Serial.println("Erasing Config, restarting");
wm.resetSettings();
ESP.restart();
}
// start portal w delay
Serial.println("Starting config portal");
wm.setConfigPortalTimeout(120);
if (!wm.startConfigPortal("OnDemandAP", "password")) {
Serial.println("failed to connect or hit timeout");
delay(3000);
// ESP.restart();
} else {
//if you get here you have connected to the WiFi
Serial.println("connected :-)");
}
}
}
}
String getParam(String name) {
//read parameter from server, for customhmtl input
String value;
if (wm.server->hasArg(name)) {
value = wm.server->arg(name);
}
return value;
}
void saveParamCallback() {
Serial.println("[CALLBACK] saveParamCallback fired");
Serial.println("PARAM customfieldid = " + getParam("customfieldid"));
}
void loop() {
if (wm_nonblocking) wm.process(); // avoid delays() in loop when non-blocking and other long running code
checkButton();
/*
read the values from the sensor, it returns
an array which contains 3 values.
0 : LPG in ppm
1 : CO in ppm
2 : SMOKE in ppm
*/
float* values = mq2.read(true); //set it false if you don't want to print the values to the Serial
lpg = mq2.readLPG();
co = mq2.readCO();
smoke = mq2.readSmoke();
if (lpg > soglia or co > soglia or smoke > soglia )
{
bot.sendMessage(CHAT_ID, "Superata Soglia Attenzione Fumi: " + String(smoke));
Serial.println("superata soglia" + String(smoke));
}
if (millis() - bot_lasttime > BOT_MTBS)
{
int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
while (numNewMessages)
{
Serial.println("got response");
handleNewMessages(numNewMessages);
numNewMessages = bot.getUpdates(bot.last_message_received + 1);
}
bot_lasttime = millis();
}
}
Eseguiamo il nostro bot da Telegram:

Premendo /statoAria possiamo avere i dati in diretta relativi alla qualità dell’aria.
Per provare il rilevatore avviciniamoci con una bacchetta di incenso al nostro sensore:
qualche istante dopo riceveremo questo messaggio su Telegram:

Ricapitolando, abbiamo visto come creare e utilizzare un Bot Telegram con ESP8266, in modo da poter ricevere notifiche e inviare comandi senza particolari piattaforme e server privati in cloud. Tramite un’applicazione di messaggistica molto utilizzata possiamo gestire i nostri progetti domotici. Ho realizzato il rilevatore di fumi wifi che ci avviserà tramite un messaggio su Telegram dell’eventuale pericolo.