En este artículo, te diré cómo escribir un bot de Telegram que se integre con el mundo real a través de un
microcontrolador (Arduino).
Todo se recuerda mejor en la práctica. Entonces, explicaré todo a través de un proyecto práctico desde mi experiencia. El código del proyecto está publicado en mi GitHub
Hice un proyecto para controlar la cola de la sala de juegos de nuestra oficina mediante Telegram basado en Arduino. Se instaló el Arduino con servomotor para bloquear y desbloquear la puerta. La gente podía tomar una cola y verificar cuántas personas estaban en la cola a través del bot de Telegram.
En este proyecto se ha utilizado NodeMCU pero la misma lógica funciona para Arduino con ESP32/ESP8266.
Telegram es un mensajero con aplicaciones móviles (iPhone y Android) y aplicaciones de escritorio (Mac, Windows y Linux). En Telegram, tenemos la oportunidad de crear un bot. Lo controlaremos con nuestro microcontrolador procesando los mensajes de los usuarios.
Para crear un Telegram Bot, debemos solicitarlo al bot de Telegram "botfather". Todo lo que necesita es encontrar el bot mediante la búsqueda u obtenerlo mediante el enlace:
Envía el comando /start para iniciar el bot. Envíe el comando /newbot para crear un nuevo bot. Se nos pedirá que ingresemos el nombre y el nombre de usuario del nuevo bot. Después de la creación exitosa del bot, el padre del bot nos enviará un token. Este será necesario para recibir todos los mensajes enviados al bot y enviar mensajes del bot a los usuarios.
Usaremos un servomotor para bloquear y desbloquear la puerta y un LED para indicar si la puerta está bloqueada.
Los servomotores tienen 3 pines: naranja, rojo y marrón: rojo - 5 V, marrón - GND, naranja - 14. LED conectado al pin 2.
En primer lugar, debemos importar todas las bibliotecas necesarias:
#ifdef ESP32 #include <WiFi.h> #else #include <ESP8266WiFi.h> #endif #include <WiFiClientSecure.h> #include <UniversalTelegramBot.h> #include <ArduinoJson.h> #include <Servo.h> Servo myservo;
Escriba las credenciales de wi-fi a las que se conectará el microcontrolador:
const char* ssid = ""; //wifi name const char* password = ""; //wifi password
Escriba el token de nuestro bot, que recibimos después de su creación:
// Initialize Telegram BOT #define BOTtoken "XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" // your Bot Token (Get from Botfather)
Defina las salidas y otras variables requeridas:
// Checks for new messages every 0.1 second. int botRequestDelay = 100; unsigned long lastTimeBotRan; int servo_pin = 14;//servo pin int servo_locked_value = 180; int servo_unlocked_value = 30; const int ledPin = 2; String queue[10] ={};//array of queue int queue_array_len = 0;//len of queue bool room_is_free = true;//initially the room is free bool door_is_locked = true;// the door is locked
Cree un nuevo cliente wi-fi y un bot con el token y el cliente:
WiFiClientSecure client; UniversalTelegramBot bot(BOTtoken, client);
En la sección de configuración, inicializaremos el led y el servo, comenzaremos en serie y nos conectaremos a wi-fi:
void setup() { Serial.begin(115200); #ifdef ESP8266 configTime(0, 0, "pool.ntp.org"); // get UTC time via NTP client.setTrustAnchors(&cert); // Add root certificate for api.telegram.org #endif pinMode(ledPin, OUTPUT); digitalWrite(ledPin, HIGH); // Connect to Wi-Fi WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); #ifdef ESP32 client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org #endif while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi.."); } // Print ESP32 Local IP Address Serial.println(WiFi.localIP()); //Servo - close: myservo.attach(servo_pin); myservo.write(180); }
En la sección de bucle haremos tres cosas principales:
void loop() { if (millis() > lastTimeBotRan + botRequestDelay) { 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); } lastTimeBotRan = millis(); //check if the room free if(room_is_free ==true && queue[0]!=""){ room_is_free = false; //invite to the room: Serial.println("Invinting to the room: "+queue[0]); bot.sendMessage(queue[0], "The room is free! \n Please come and send /unlock_the_door_from_outside to unlock the door.", ""); } //Indicating and opening/closing the door: digitalWrite(ledPin, door_is_locked);//ledState if(door_is_locked){ myservo.write(servo_locked_value);//locked }else{ myservo.write(servo_unlocked_value);//unlocked } } }
Así es como manejaremos los mensajes nuevos y responderemos a /mensaje de inicio:
void handleNewMessages(int numNewMessages) { Serial.println("handleNewMessages"); Serial.println(String(numNewMessages)); for (int i=0; i<numNewMessages; i++) { // Chat id of the requester String chat_id = String(bot.messages[i].chat_id); // Print the received message String text = bot.messages[i].text; Serial.print("From: ");Serial.println(chat_id); Serial.print("Message: ");Serial.println(text); String from_name = bot.messages[i].from_name; if (text == "/start") { String welcome = "Welcome, " + from_name + ".\n"; welcome += "By this bot you can stand in line to the Gaming room.\n"; welcome += "Please see my /options.\n\n"; bot.sendMessage(chat_id, welcome, ""); } } }
Así es como respondemos al mensaje /options y enviamos botones para facilitar las interacciones:
if (text == "/options") { String keyboardJson = "[[\"/Stand_in_line\"],[\"/cancel\", \"/status\"]]"; bot.sendMessageWithReplyKeyboard(chat_id, "Here is my options:", "", keyboardJson, true); }
Cuando recibimos el mensaje /Stand_in_line, debemos verificar si la persona ya está en la cola y, si no, agregar a la persona a la cola e informarle:
if (text == "/Stand_in_line") { //check if person already in the queue: if(if_chat_id_not_in_queue(chat_id)){ //add person to the queue queue[queue_array_len] = chat_id;//array of queue queue_array_len++; bot.sendMessage(chat_id, "You joined the queue.", ""); }else{ bot.sendMessage(chat_id, "You are already in the queue.", ""); } //printing the queue print_queue(); }
**
**
Cuando recibimos un mensaje de cancelación, debemos eliminar a la persona de la cola verificando si está allí. Además, si la persona ya estaba invitada a la sala, volveremos a configurar el estado de la sala como libre.
if (text == "/cancel") { //check if person already in the queue: if(if_chat_id_not_in_queue(chat_id)){ bot.sendMessage(chat_id, "You were not in the queue.", ""); }else{ //checking if the person first one to set room to free again. if (queue[0]=chat_id){ room_is_free = true; } //remove person from the queue for(int i = 0; i < queue_array_len; i++){ if(queue[i]=chat_id){ queue[i] = ""; //move items after the deleted one: for(int j = i;j < queue_array_len; j++){ queue[j] = queue[j+1]; } } } queue_array_len--; bot.sendMessage(chat_id, "You are no longer in the queue.", ""); //printing the queue print_queue(); } }
Cuando recibamos un mensaje de estado, enviaremos cuántas personas hay en la cola y, si hay una persona, también enviaremos la posición de la persona en la cola:
if (text == "/status") { //printing the queue print_queue(); int current_person_id_in_queue = -1; for(int i = 0; i < queue_array_len; i++){ if(queue[i]==chat_id){ current_person_id_in_queue = i+1; } } String message = "The queue consist of " + String(queue_array_len ) + " person(s).\n"; if(current_person_id_in_queue != -1){ message +="You are #"+String(current_person_id_in_queue)+ " in line.\n"; } bot.sendMessage(chat_id, message, ""); }
Cuando llegue la cola de personas, enviaremos un mensaje de invitación:
Cuando recibimos el mensaje /unlock_the_door_from_outside, debemos verificar si la persona es la primera en la cola y, de ser así, desbloquear la puerta y enviar la respuesta:
if (text == "/unlock_the_door_from_outside") { //checking if this first person in queue: if(chat_id == queue[0]){ door_is_locked = false; myservo.write(servo_unlocked_value);//unlocked bot.sendMessage(chat_id, "The door is unlocked! \nCome in and lock the door by sending /lock_the_door_from_inside.", ""); }else{ bot.sendMessage(chat_id, "Something went wrong. \nPlease try to check your status in queue by /status command.", ""); } }
En los siguientes comandos /lock_the_door_from_inside y /unlock_the_door_from_inside como antes, debemos verificar si la persona es la primera en la cola. Hacemos esto para asegurarnos de que la puerta esté bloqueada o desbloqueada por la persona adecuada.
Para el mensaje /lock_the_door_from_inside, solo necesitamos bloquear la puerta:
if (text == "/lock_the_door_from_inside") { //checking if this first person in queue: if(chat_id == queue[0]){ door_is_locked = true; myservo.write(servo_locked_value);//locked bot.sendMessage(chat_id, "The door is locked! \nTo unlock the door send /unlock_the_door_from_inside.", ""); }else{ bot.sendMessage(chat_id, "Something went wrong. \nPlease try to check your status in queue by /status command.", ""); } }
Cuando recibamos el mensaje /unlock_the_door_from_inside, desbloquearemos la puerta durante tres segundos y la volveremos a bloquear. Además, eliminaremos a la persona de la cola y volveremos a configurar el estado de la habitación como libre. Esto requiere invitar a la siguiente persona de la cola:
if (text == "/unlock_the_door_from_inside") { //checking if this first person in queue: if(chat_id == queue[0]){ door_is_locked = false; myservo.write(servo_unlocked_value);//unlocked bot.sendMessage(chat_id, "The door is unlocked! We will lock it in 3 sec", ""); delay(3000); door_is_locked = true; room_is_free = true; myservo.write(servo_locked_value);//locked //remove the person from the queue for(int i = 0; i < queue_array_len; i++){ if(queue[i]=chat_id){ queue[i] = ""; //move items after the deleted one: for(int j = i;j < queue_array_len; j++){ queue[j] = queue[j+1]; } } } queue_array_len--; bot.sendMessage(chat_id, "The door is locked. Bye!", ""); }else{ bot.sendMessage(chat_id, "Something went wrong. \nPlease try to check your status in queue by /status command.", ""); } }
Aquí están nuestras funciones auxiliares. Estas dos partes del código se usan muchas veces. Entonces, decidí separarlos por conveniencia del código:
//check if person already in the queue: bool if_chat_id_not_in_queue(String chat_id){ for(int i = 0; i < queue_array_len; i++){ if(chat_id == queue[i]){ return false; } } return true; } //printing the queue void print_queue(){ Serial.print("In queue - ");Serial.println(queue_array_len); for(int i = 0; i < queue_array_len; i++){ Serial.println(queue[i]); } }
A través de este tutorial, ha aprendido a interactuar con su microcontrolador con Telegram Bot.
El microcontrolador puede procesar los mensajes enviados al bot y devolverlos.
Este proyecto es un ejemplo y un escaparate para ti. Las posibilidades están limitadas por su imaginación. Aquí hay algunas ideas para usted: haga un detector de movimiento que envíe un mensaje cuando se detecte movimiento; conecte un módulo de cámara y envíe la imagen a pedido; controle la tira de LED u obtenga cualquier indicación del sensor. Además, se podría hacer
Lo mejor de los proyectos integrados de bots de Telegram es que se pueden controlar desde cualquier parte del mundo. Esto le da a sus proyectos la oportunidad de alcanzar un nuevo nivel.