Comando control Esp32 a traves de Telegram con JavaScript
Presentación
El presente proyecto consiste en realizar un programa en python que permita enviar ordenes a una placa Esp-32 a traves de un bot de Telegram.
Para el desarrollo de este proyecto se ha utilizado un bot de telegram y la libreria Telethon
Para simplificar la programacion el proyecto consiste en encender y apagar dos leds, pero a partir de este modelo se pueden realizar operaciones mucho mas complejas
El siguiente video muestra el proyecto en funcionamiento:
Materiales
Placa Esp32 D1 R32
Leds
A ello se debe agregar los cables pertinentes y la fuente de alimentacion adecuada.
Esquema de conexion
Las conexiones de placa Esp32 donde correrá el programa que recibirá los mandos a traves de Telegram y encenderá o apagará los leds según se indique se harán de acuerdo al siguiente esquema
Programación Esp32
El programa de la Esp32 es el administrador del bot de Telegram y cuenta con dos archivos: esp32telegram.ino y credencial.h, ambos archivos deben estar en una carpeta llamada esp32telegram y con el IDE de arduino se pueden instalar en la placa Esp32
En el archivo credencial.h se deberan completar los datos del nombre y clave de acceso de la red wifi a la que se conectará la placa Esp-32 el Token BOT de Telegram que se obtener de Botfather y el ID de chat que se obtiene con @myidbot
Sobre la creación y manejo de Bot de Telegram si bien existen infinidad de paginas y tutoriales yo uso la siguiente página Cómo crear un chatbot en Telegram
Programa de control de luces
El programa de control de luces correrá en la pc y esta desarrollado en python 3, la versión que presento es el archivo paneluz.py que debe ser arrancado de una consola de Terminal abierta en el directorio que este el archivo con la instruccion python3 paneluz.py tal como se ve en el video.
Código
esp32telegram.ino
/*******************************************************************
Un bot de Telegram para Esp32
*******************************************************************/
// ----------------------------
// Librerias
// ----------------------------
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>
#include "credencial.h"
#define FLASH_LED_PIN 4
#define LED_VERDE 25
#define LED_ROJO 26
const unsigned long tiempo_escaneo = 1000; // tiempo medio entre mensajes escaneados
unsigned long ultimo_escaneo; // última vez que se realizó el escaneo de mensajes
WiFiClientSecure cliente;
UniversalTelegramBot bot(BOT_TOKEN, cliente);
bool estado_flash = LOW;
bool estado_verde = LOW;
bool estado_rojo = LOW;
void manejo_mensajes(int num_mensaje)
{
Serial.println("Nuevo mensaje");
Serial.println(String(num_mensaje));
for (int i = 0; i < num_mensaje; i++)
{
String chat_id = String(bot.messages[i].chat_id);
if (chat_id != id_autorizado){
bot.sendMessage(chat_id, "Usuario no autorizado", "");
continue;
}
String text = bot.messages[i].text;
String nombre = bot.messages[i].from_name;
if (nombre == "")
nombre = "Invitado";
if (text == "/flash")
{
estado_flash = !estado_flash;
digitalWrite(FLASH_LED_PIN, estado_flash);
Serial.println("Nuevo mensaje - encender/apagar Flash");
if (estado_flash == LOW){
bot.sendMessage(chat_id, "Apago Flash1", "");
}else{
bot.sendMessage(chat_id, "Encendio Flash1", "");
}
}
if (text == "/verde")
{
estado_verde = !estado_verde;
digitalWrite(LED_VERDE, estado_verde);
Serial.println("Nuevo mensaje - encender/apagar Verde");
if (estado_verde == LOW){
bot.sendMessage(chat_id, "Apago Verde", "");
}else{
bot.sendMessage(chat_id, "Encendio Verde", "");
}
}
if (text == "/rojo")
{
estado_rojo = !estado_rojo;
digitalWrite(LED_ROJO, estado_rojo);
Serial.println("Nuevo mensaje - encender/apagar Rojo");
if (estado_rojo == LOW){
bot.sendMessage(chat_id, "Apago Rojo", "");
}else{
bot.sendMessage(chat_id, "Encendio Rojo", "");
}
}
if (text == "/prueba")
{
Serial.println("Recibi nuevo mensaje - prueba");
bot.sendMessage(chat_id, "Recibi mensaje prueba1", "");
}
if (text == "/start")
{
String mensaj_bienvenida = "Bienvenido al bot de Telegram1.\n\n";
mensaj_bienvenida += "/prueba : mensaje de prueba\n";
mensaj_bienvenida += "/flash : encender/apagar flash LED\n";
bot.sendMessage(chat_id, mensaj_bienvenida, "");
}
}
}
void setup()
{
Serial.begin(115200);
Serial.println();
pinMode(FLASH_LED_PIN, OUTPUT);
pinMode(LED_ROJO, OUTPUT);
pinMode(LED_VERDE, OUTPUT);
digitalWrite(FLASH_LED_PIN, estado_flash); //por defecto a bajo
digitalWrite(LED_ROJO, estado_rojo); //por defecto a bajo
digitalWrite(LED_VERDE, estado_verde); //por defecto a bajo
// intenta conectarte a la red wifi:
Serial.print("Conexión a red Wi-Fi ");
Serial.print(red);
WiFi.begin(red, clave);
cliente.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Agregar certificado raíz para api.telegram.org
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(500);
}
Serial.print("\nWi-Fi conectado. dirección IP: ");
Serial.println(WiFi.localIP());
Serial.print("Tiempo de recuperación: ");
configTime(0, 0, "pool.ntp.org"); // obtener la hora UTC a través de NTP
time_t now = time(nullptr);
while (now < 24 * 3600)
{
Serial.print(".");
delay(100);
now = time(nullptr);
}
Serial.println(now);
// Haz que el bot espere un nuevo mensaje hasta 60 segundos
bot.longPoll = 60;
delay(5000);
bot.sendMessage(id_autorizado, "Bot dos iniciado", "");
}
void loop()
{
if (millis() - ultimo_escaneo > tiempo_escaneo)
{
int num_mensaje = bot.getUpdates(bot.last_message_received + 1);
while (num_mensaje)
{
Serial.println("obtuve respuesta");
manejo_mensajes(num_mensaje);
num_mensaje = bot.getUpdates(bot.last_message_received + 1);
}
ultimo_escaneo = millis();
}
}
credencial.h
//Credenciales de red
const char* red = "xxxxxxxxxxx";
const char* clave = "xxxxxxxxxxx";
// Token BOT de Telegram (Obtener de Botfather)
#define BOT_TOKEN "0000000000:AAAAAAAAAAAA-BBBBBBBBBBBBBBBBBBBBBB"
// Usa @myidbot para averiguar el ID de chat
String id_autorizado = "1111111111";
paneluz.py
# importamos las librerías requeridas
from telethon.sync import TelegramClient
from telethon import TelegramClient
from telethon.errors import SessionPasswordNeededError
import tkinter as tk
from tkinter import messagebox
# App_ID, Api_Hash obtenidos desde web de Telegram de autorización de aplicación
appID = '00000000'
appAPIHash = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
# Token del Bot de Telegram al que llegará el mensaje
tokenBot = '0000000000:AAAAAAAAAAAA-BBBBBBBBBBBBBBBBBBBBBB'
# Número de telefóno móvil (incluyendo código de país)
numeroTelefono = '+555555555555'
# Nombre de usuario en Telegram al que se enviará el mensaje
nombreUsuarioTelegram = '@usuario'
valor_rojo = "Apagado"
valor_verde = "Apagado"
def inicio():
receptorChat = clienteTelegram.get_input_entity(nombreUsuarioTelegram)
async def main():
await clienteTelegram.send_message(receptorChat, "Se conecto programa de control")
print("Se conecto programa de control")
clienteTelegram.loop.run_until_complete(main())
def roja():
global valor_rojo
if valor_rojo == "Apagado":
valor_rojo = "Encendido"
eti_roja.configure(text=valor_rojo)
else:
valor_rojo = "Apagado"
eti_roja.configure(text=valor_rojo)
receptorChat = clienteTelegram.get_input_entity(nombreUsuarioTelegram)
async def main():
await clienteTelegram.send_message(receptorChat, "/rojo")
print("Enviado comando led rojo")
clienteTelegram.loop.run_until_complete(main())
def verde():
global valor_verde
if valor_verde == "Apagado":
valor_verde = "Encendido"
eti_verde.configure(text=valor_verde)
else:
valor_verde = "Apagado"
eti_verde.configure(text=valor_verde)
receptorChat = clienteTelegram.get_input_entity(nombreUsuarioTelegram)
async def main():
await clienteTelegram.send_message(receptorChat, "/verde")
print("Enviado comando led verde")
clienteTelegram.loop.run_until_complete(main())
def cerrar():
receptorChat = clienteTelegram.get_input_entity(nombreUsuarioTelegram)
async def main():
await clienteTelegram.send_message(receptorChat, "Se desconecta programa de control")
print("Se desconecto programa de control")
clienteTelegram.loop.run_until_complete(main())
def desconectar():
close = messagebox.askyesno(
message="¿Está seguro de que quiere cerrar la aplicación?",
title="Confirmar cierre"
)
if close:
cerrar()
# Desconectamos la sesión de Telegram abierta
print("Desconectando sesión de Telegram...")
clienteTelegram.disconnect()
print("Desconectado y fin del programa")
ventana.destroy()
print("Conectando con Telegram...")
# Creamos sesión de Telegram
clienteTelegram = TelegramClient('sesión', appID, appAPIHash)
print("Iniciando sesión en Telegram...")
# Iniciamos una sesión de Telegram
clienteTelegram.connect()
# Si se ejecuta por primera vez, Telegram generará un código de inicio de sesión
# en el chat de Telegram "Telegram", si es así, la aplicación
# pedirá este código de inicio de sesión
print("Comprobando autorización...")
if not clienteTelegram.is_user_authorized():
clienteTelegram.send_code_request(numeroTelefono)
# Pedimos el código de inicio de sesión que haya enviado Telegram al usuario
try:
clienteTelegram.sign_in(numeroTelefono, input('Introduzca el Código de inicio de sesión: '))
except SessionPasswordNeededError:
clienteTelegram.sign_in(numeroTelefono, input('Introduzca la contraseña: '))
inicio()
ventana = tk.Tk()
ventana.title("Control de Luces")
ventana.geometry("400x200+300+200")
boton_rojo = tk.Button(ventana, text="Luz Roja", foreground="#FDFEFE", background="#FF0000", command=roja)
boton_rojo.place(x=80, y=40)
eti_roja = tk.Label(ventana, text=valor_rojo)
eti_roja.place(x=90, y=80)
boton_verde = tk.Button(ventana, text="Luz Verde", foreground="#FDFEFE", background="#27AE60", command=verde)
boton_verde.place(x=240, y=40)
eti_verde = tk.Label(ventana, text=valor_verde)
eti_verde.place(x=250, y=80)
boton_cerrar = tk.Button(ventana, text="Cerrar Aplicacion", foreground="#FDFEFE",background="#85C1E9", command=desconectar)
boton_cerrar.place(x=120, y=140)
ventana.mainloop()