Recents in Beach


Receba o meu conteúdo GRATUITAMENTE


Automação com Telegram e ESP32



Hoje vamos criar um bot no ESP8266/ESP32 para servir de contato no Telegram. Assim, podemos modificar/verificar o estado de um relé e verificar a temperatura e umidade de acordo com mensagens que enviamos para ele. Ou seja, é como se este contato fosse uma pessoa real que estivesse executando os seus comandos, estes enviados pelo programa de troca de mensagens.




Montagem





Atualizar o core do ESP8266

Em caso de problemas com o ESP8266, na IDE do Arduino vá em:
 Ferramentas->Placa->Gerenciar de Placas...
Atualize o ESP8266 (no caso utilizamos a versão 2.4.2)




Biblioteca ArduinoJson

Na IDE do Arduino vá em Sketch->Incluir Biblioteca->Gerenciar Bibliotecas...
Instale ArduinoJson (no caso utilizamos a versão 5.13.2)




Biblioteca UniversalTelegramBot

Na IDE do Arduino vá em Sketch->Incluir Biblioteca->Gerenciar Bibliotecas...
Instale UniversalTelegramBot




Biblioteca SimpleDHT

Na IDE do Arduino vá em Sketch->Incluir Biblioteca->Gerenciar Bibliotecas...
Instale SimpleDHT




Criando um Bot no Telegram

Abra o Telegram e pesquise por botfather. Selecione o com a marca azul


Nesta tela clique em COMEÇAR


O BotFather te mostrará algumas opções


Digite /newbot


Digite o nome que queira para seu bot


Digite o nome de usuário para seu bot. Deve terminar com bot (Exemplo: TesteFKBot).
Guarde o token gerado para substituir no código fonte .ino



TelegramBot.ino

Declarações e variáveis


#if defined(ESP8266)
#include <ESP8266WiFi.h>        
#else
#include <WiFi.h>
#endif
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <SimpleDHT.h>

//Pino onde está o Relê
#define RELAY_PIN 5
//Pino onde está o DHT22
#define DHT_PIN 4

//Intervalo entre as checagens de novas mensagens
#define INTERVAL 1000

//Token do seu bot. Troque pela que o BotFather te mostrar
#define BOT_TOKEN "000000000:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

//Troque pelo ssid e senha da sua rede WiFi
#define SSID "SSID"
#define PASSWORD "12345678"


Comandos e definições

//Comandos aceitos
const String LIGHT_ON = "ligar a luz";
const String LIGHT_OFF = "desligar a luz";
const String CLIMATE = "clima";
const String STATS = "status";
const String START = "/start";

//Objeto que realiza a leitura da temperatura e umidade
SimpleDHT22 dht;

//Estado do relê
int relayStatus = HIGH;

//Cliente para conexões seguras
WiFiClientSecure client;
//Objeto com os métodos para comunicarmos pelo Telegram
UniversalTelegramBot bot(BOT_TOKEN, client);
//Tempo em que foi feita a última checagem
uint32_t lastCheckTime = 0;

//Quantidade de usuários que podem interagir com o bot
#define SENDER_ID_COUNT 2
//Ids dos usuários que podem interagir com o bot. 
//É possível verificar seu id pelo monitor serial ao enviar uma mensagem para o bot
String validSenderIds[SENDER_ID_COUNT] = {"012345678", "123456789"};


Setup

void setup()
{
  Serial.begin(115200);

  //Inicializa o WiFi e se conecta à rede
  setupWiFi();

  //Coloca o pino do relê como saída e enviamos o estado atual
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, relayStatus);
}


SetupWiFi

void setupWiFi()
{
  Serial.print("Connecting to SSID: ");
  Serial.println(SSID);

  //Inicia em modo station e se conecta à rede WiFi
  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID, PASSWORD);

  //Enquanto não estiver conectado à rede
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(500);
  }

  //Se chegou aqui está conectado
  Serial.println();
  Serial.println("Connected");
}


Loop

void loop()
{
  //Tempo agora desde o boot
  uint32_t now = millis();

  //Se o tempo passado desde a última checagem for maior que o intervalo determinado
  if (now - lastCheckTime > INTERVAL) 
  {
    //Coloca o tempo de útlima checagem como agora e checa por mensagens
    lastCheckTime = now;
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    handleNewMessages(numNewMessages);
  }
}


handleNewMessages

void handleNewMessages(int numNewMessages)
{
  for (int i=0; i<numNewMessages; i++) //para cada mensagem nova
  {
    String chatId = String(bot.messages[i].chat_id); //id do chat 
    String senderId = String(bot.messages[i].from_id); //id do contato
    
    Serial.println("senderId: " + senderId); //mostra no monitor serial o id de quem mandou a mensagem

    boolean validSender = validateSender(senderId); //verifica se é o id de um remetente da lista de remetentes válidos

    if(!validSender) //se não for um remetente válido
    {
      bot.sendMessage(chatId, "Desculpe mas você não tem permissão", "HTML"); //envia mensagem que não possui permissão e retorna sem fazer mais nada
      continue; //continua para a próxima iteração do for (vai para próxima mensgem, não executa o código abaixo)
    }
    
    String text = bot.messages[i].text; //texto que chegou

    if (text.equalsIgnoreCase(START))
    {
      handleStart(chatId, bot.messages[i].from_name); //mostra as opções
    }
    else if (text.equalsIgnoreCase(LIGHT_ON))
    {
      handleLightOn(chatId); //liga o relê
    }
    else if(text.equalsIgnoreCase(LIGHT_OFF))
    {
     handleLightOff(chatId); //desliga o relê
    }
    else if(text.equalsIgnoreCase(CLIMATE))
    {
      handleClimate(chatId); //envia mensagem com a temperatura e umidade
    }
    else if (text.equalsIgnoreCase(STATS))
    {
      handleStatus(chatId); //envia mensagem com o estado do relê, temperatura e umidade
    }
    else
    {
      handleNotFound(chatId); //mostra mensagem que a opção não é válida e mostra as opções
    }
  }//for
}


validateSender

boolean validateSender(String senderId)
{
  //Para cada id de usuário que pode interagir com este bot
  for(int i=0; i<SENDER_ID_COUNT; i++)
  {
    //Se o id do remetente faz parte do array retornamos que é válido
    if(senderId == validSenderIds[i])
    {
      return true;
    }
  }

  //Se chegou aqui significa que verificou todos os ids e não encontrou no array
  return false;
}


handleStart

void handleStart(String chatId, String fromName)
{
  //Mostra Olá e o nome do contato seguido das mensagens válidas
  String message = "<b>Olá " + fromName + ".</b>\n";
  message += getCommands();
  bot.sendMessage(chatId, message, "HTML");
}


getCommands

String getCommands()
{
  //String com a lista de mensagens que são válidas e explicação sobre o que faz
  String message = "Os comandos disponíveis são:\n\n";
  message += "<b>" + LIGHT_ON + "</b>: Para ligar a luz\n";
  message += "<b>" + LIGHT_OFF + "</b>: Para desligar a luz\n";
  message += "<b>" + CLIMATE + "</b>: Para verificar o clima\n";
  message += "<b>" + STATS + "</b>: Para verificar o estado da luz e a temperatura";
  return message;
}


handleLightOn

void handleLightOn(String chatId)
{
  //Liga o relê e envia mensagem confirmando a operação
  relayStatus = LOW; //A lógica do nosso relê é invertida
  digitalWrite(RELAY_PIN, relayStatus);  
  bot.sendMessage(chatId, "A luz está <b>acesa</b>", "HTML");
}


handleLightOff

void handleLightOff(String chatId)
{
  //Desliga o relê e envia mensagem confirmando a operação 
  relayStatus = HIGH; //A lógica do nosso relê é invertida
  digitalWrite(RELAY_PIN, relayStatus);  
  bot.sendMessage(chatId, "A luz está <b>apagada</b>", "HTML");
}


handleClimate

void handleClimate(String chatId)
{
  //Envia mensagem com o valor da temperatura e da umidade
  bot.sendMessage(chatId, getClimateMessage(), "");
}


getClimateMessage

String getClimateMessage()
{
  //Faz a leitura da temperatura e da umidade
  float temperature, humidity;
  int status = dht.read2(DHT_PIN, &temperature, &humidity, NULL);

  //Se foi bem sucedido
  if (status == SimpleDHTErrSuccess)
  {
    //Retorna uma string com os valores
    String message = "";
    message += "A temperatura é de " + String(temperature)+ " °C e ";
    message += "a umidade é de " + String(humidity) + "%";
    return message;
  }
  
  //Se não foi bem sucedido retorna um mensagem de erro
  return "Erro ao ler temperatura e umidade";
}


handleStatus

void handleStatus(String chatId)
{
  String message = "";

  //Verifica se o relê está ligado ou desligado e gera a mensagem de acordo
  if(relayStatus == LOW) //A lógica do nosso relê é invertida
  {
    message += "A luz está acesa\n";
  }
  else
  {
    message += "A luz está apagada\n";
  }

  //Adiciona à mensagem o valor da temperatura e umidade
  message += getClimateMessage();

  //Envia a mensagem para o contato
  bot.sendMessage(chatId, message, "");
}


handleNotFound

void handleNotFound(String chatId)
{
  //Envia mensagem dizendo que o comando não foi encontrado e mostra opções de comando válidos
  String message = "Comando não encontrado\n";
  message += getCommands();
  bot.sendMessage(chatId, message, "HTML");
}


Interagindo com o Bot no Telegram

Vá até o BotFather e clique no link para conversar com o bot


Clique em COMEÇAR


Envie os comandos e verifique as mensagens que o bot retorna







Faça o download dos arquivos






Postar um comentário

17 Comentários

  1. Ola Fernando, muito bom este artigo, só uma dúvida, para usar com um ESP32 eu utilizo a mesma biblioteca?

    ResponderExcluir
    Respostas
    1. Gostaria de saber também, estou tentando mas da Erro ao Compilar... ESP-WROOM-32

      Excluir
    2. Eu estava tendo o mesmo problema, incluí a biblioteca ArduinoJson.h (que ele até ensina como instalar na IDE), mas mesmo assim continuava a dar o erro, percebi que a versão está diferente da que ele usou, coloquei na mesma versão e o problema foi resolvido.

      Excluir
  2. Gostaria de desenvolver um sistema que informasse em tempo real a temperatura de um liquido que fica dentro de um tanque de um caminhão. Será que tem como?

    ResponderExcluir
  3. boa tarde no meu aparece que não tenho permissão

    ResponderExcluir
    Respostas
    1. Só fazer esse procedimento aqui amigo e depois colar no seu codigo
      //É possível verificar seu id pelo monitor serial ao enviar uma mensagem para o bot
      String validSenderIds[SENDER_ID_COUNT] = {"12345678", "12345678"};

      Excluir
  4. Boa tarde. Qual a comunidade para discutir sobre o artigo ?

    ResponderExcluir
  5. Ótimo artigo ser usado não a barreira

    ResponderExcluir
  6. e Para o ESP32:, estou tentando mas da Erro ao Compilar... ESP-WROOM-32

    (Erro compilando para a Placa DOIT ESP32 DEVKIT V1)

    ResponderExcluir
  7. Ótima Aula, por favor me fala dos os componentes usados nesse exemplo.

    ResponderExcluir
  8. Valeu pelo conteúdo... parabéns...

    ResponderExcluir
  9. Muito interessante. Funcionou muito bem. Só não foi mostrado no video como achar o sender id para incluir na string de permissões. Descobri o id pela serial. Não vi como achar pelo proprio Telegram.

    ResponderExcluir
  10. oi fernando bom projeto..so que esse telegram não que funcionar comigo não..kkk..deu tudo certo a compilação e o envio para o esp 8266 mcu lolin so que monitor serial dar conectado mando o comando que voce deixou o mesmo (ligar a luz) so quem nem manda o comando de retorno com o Led fica aceso apaga nem acende .. dar para voce me dizer qual o problema..e ja testei com outros exemplos de outras pessoas nem conectado dar esse pelo menos deu conectado so que mando os comandos e não obedece...

    ResponderExcluir
  11. Olá, pessoal!
    Alguém sabe se é possível implementar esse projeto usando GPRS com um SIM808 ao invés de wifi? O projeto se encaixa com o que preciso, mas no meu caso a mobilidade é essencial.
    Valeu, pessoal!

    ResponderExcluir
  12. Olá Fernando. O código não esta rodando, poderia verificar por favor?

    ResponderExcluir