fbpx
13 de agosto de 2022

Do bit Ao Byte

Embarcados, Linux e programação

Controle remoto com bot Telegram

controle remoto com bot Telegram

Já há algum tempo não escrevo, devido à recente mudança de endereço. De positivo, agora tenho um cômodo, o qual venho transformando em um estúdio para a gravação de vídeos para os canais DobitaobyteBrasil e Da20Resolve. Mas esse artigo de hoje tem duas finalidades; a primeira é que recebi a grata visita do Nascimento Júnior, do canal Arduino Brasil, que hospedou-se aqui. Logo, não poderíamos perder a oportunidade de fazermos algo juntos – no caso, esse controle remoto com bot Telegram, que nesse primeiro momento servirá para acionar remotamente a sirene em casa, quando algum evento suspeito ocorrer. É uma longa história, mas vou resumir esse propósito.

Sistema de segurança

Quem acompanha Dobitaobyte no Instagram, têm visto algumas postagens sem muito detalhamento, mas estou instalando um sistema de segurança em casa. Algumas câmeras, sensores de gás, presença, sirene. Haverá mensagens enviadas automaticamente pelo Telegram para eventos como reconhecimento de armas de fogo (já mostrado nesse artigo e também nesse vídeo), cerca virtual e outros. Em alguns casos o alarme será disparado automaticamente, até chamada para a polícia é considerada, mas em casos de menor acurácia pode ser necessário interação humana para definir a ação – e nesse caso sim, disparar o alarme manualmente, utilizando um bot telegram. O mais importante é não perder eventos verdadeiros, mas também deve-se ajustar o sistema o máximo possível, para reduzir falso-positivos (considere que “falso” nesse composto é um advérbio para “falsamente”, portanto, invariável).

Hardware utilizado

Para esse projeto, optamos por algo que tivesse tudo integrado e que realmente fosse confiável. Estamos utilizando o PLC da VDC, que é um hardware estupendo e de qualidade descomunal. Já escrevi sobre esse PLC feito para a indústria 4.0. Veja os recursos e apaixone-se! E se quiser adquiri-lo, a revenda é feita pela AFEletronica. Visite o site.

Como esse PLC possui 6 relés, outros recursos podem ser implementados além da sirene.

Programa de controle remoto com bot Telegram

Vale lembrar que a primeira vez que escrevi sobre bot telegram foi em 2019 (se não me engano). Depois disso escrevi sobre o bot telegram com Raspberry, que é muito mais simples. Dessa vez tem alguma diferença em relação à implementação porque houve alguma modificação na biblioteca que me obrigou a desabilitar o SSL. Mas convenhamos que não é lá tão fundamental encriptar essa troca de mensagens com o bot. Vou postar o código básico para 1 relé do PLC e explico os conceitos importantes envolvidos em seguida.

#include <Arduino.h>
#include <UniversalTelegramBot.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
#include <WiFi.h>
#include <Wire.h>
#include <math.h>

#define pcf1 0x20
#define pcf2 0x27

char ssid[]     = "SuhankoFamily";  
char password[] = "fsjmr112";

// Initialize Telegram BOT
#define BOTtoken "0123456789:sASAsaSAsSsASAsSaSA"  // your Bot Token (Get from Botfather)

int Bot_mtbs = 1000; //mean time between scan messages
long Bot_lasttime;   //last time messages' scan has been done

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

void turnOn(uint8_t val, uint8_t addr);
void turnOff(uint8_t val, uint8_t addr);
void readValue(uint8_t addr);

void setup(){
    Wire.begin();
    client.setInsecure();
    Serial.begin(9600);
    Serial.println("Hermes, o mensageiro");
    

    Serial.print("Connecting Wifi: ");
    Serial.println(ssid);

    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(500);
  }
}

void loop(){
    delay(1000);

    if (millis() > Bot_lasttime + Bot_mtbs)  {
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);

    while(numNewMessages) {
      Serial.println("got response");
      for (int i=0; i<numNewMessages; i++) {
        bot.sendMessage(bot.messages[i].chat_id, bot.messages[i].text, "");
        Serial.print("Recebido: ");
        Serial.println(bot.messages[i].text);
        if (strcmp("sirene on",bot.messages[i].text.c_str()) == 0){
            turnOn(0, 0x27);
            Serial.println("Ligando...");
            delay(200);
            turnOff(0,0x27);
        }
        else if (strcmp("sirene off",bot.messages[i].text.c_str()) == 0){
            turnOn(0, 0x27);
            Serial.println("Ligando...");
            delay(200);
            turnOff(0,0x27);
        }
        //else / else if...
      }
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }

    Bot_lasttime = millis();
    }
}
  
void turnOn(uint8_t val, uint8_t addr){
    Wire.beginTransmission(addr);
    //Wire.write(0b00000001);
    Wire.write(255&~(1<<val));
    Wire.endTransmission();
    Serial.print("Value: ");
    Serial.println(val,BIN);
}

void turnOff(uint8_t val, uint8_t addr){
    Wire.beginTransmission(addr);
    //Wire.write(0b00000001);
    Wire.write(255|(1<<val));
    Wire.endTransmission();
    Serial.print("Value: ");
    Serial.println(val,BIN);
}

void readValue(uint8_t addr){
    Wire.requestFrom(addr,1); // 1 Byte
    if (Wire.available()){
        uint8_t data = Wire.read();
        Serial.print("Value: ");
        Serial.println(data,BIN);
    }
}

As bibliotecas estão disponíveis no repositório de bibliotecas do Arduino, não há nada de especial que precise ser feito. Instale a biblioteca ArduinoJSON e a biblioteca UniversalTelegramBot.

A biblioteca math foi incluída para a utilização do pow(), mas se desejar, escreva sua própria função exponencial. Não vou aplicar nesse artigo, mas no próximo artigo relacionado veremos sua aplicação. Agora a intenção é mostrar o código mais claro e sucinto possível.

Antes da função setup() temos alguns protótipos de função:

void turnOn(uint8_t val, uint8_t addr);
void turnOff(uint8_t val, uint8_t addr);
void readValue(uint8_t addr);

Se estiver utilizando o VS Code, será necessário criar os protótipos das funções, se for declarar seus respectivos códigos após a função loop. Se implementar as funções precedendo a função setup(), não será necessário declarar os protótipos, exceto a função A faça uma chamada da função B e vice-versa. Em suma, não dói declarar os protótipos de função; faça-o.

PCF8574 no PLC

Esse PLC possui 2 PCF8574, sendo que um deles está dedicado a entradas, enquanto o outro utiliza apenas 6 bits, dedicados aos mini-relés. Já escrevi um monte de artigos sobre PCF8574 e bitwise e sempre que posso, referencio o artigo “Dominando PCF8574 com Arduino“, que é um artigo para qualquer plataforma no final das contas.

Optei por enviar uma mensagem explícita, literal, de modo a ter que usar uma função comparadora de string, já que trata-se de uma interação humana. De outro modo, poderíamos definir a posição de 0 à 5, sem precisar fazer cálculo dos bits para saber que valor “empurrar” para o PCF8574.

Se quiser fazer um teste com pow em seu computador, tendo o g++ instalado, basta escrever um arquivo chamado teste.cpp com esse conteúdo:

#include <iostream>
#include <math.h>

using namespace std;

int main(){
    for (int i=0; i<6;i++){
        cout << pow(2,i) << endl;
    }
    return 0;
}

E para compilar:

g++ -o teste.exe teste.cpp #no Linux dispense a extensão

Parece estranho o código acima? Bem, isso é C++, a linguagem usada no Arduino. A questão é o Arduino tem um framework próprio e abstrai um monte de coisas.

As funções turnOn e tunOff Escrevem 1 byte para o barramento I2C, no endereço do PCF8574 responsável pelos relés (0x27). Para identificar os endereços dos dispositivos I2C, use o scanner descrito no artigo “Dominando PCF8574 com Arduino“.

Para finalizar, o print no final das funções supracitadas recebe um parâmetro extra, que é o BIN. Podemos definir o formato da saída para que seja decimal, hexadecimal, binário etc. No caso, mostrando em binário fica visualmente simples para depuração, mas sequer precisamos de prints, uma vez que a comunicação UART não fará parte dessa integração.

Erro de SSL com ESP32

A classe WiFiClientSecure aplica a camada SSL à comunicação, mas essa biblioteca tem um comportamento diferente em ESP8266 e ESP32. No ESP8266 é usado fingerprint e no ESP32 sei-lá-o-quê. O fato é que ao subir o firmware, iniciar-se-á um erro contínuo de SSL após a conexão WiFi e o único contorno que achei foi desabilitar o SSL, usando o método client.setInsecure().

Como criar um bot telegram?

É muito fácil. Use a lupa do Telegram para pesquisar por @botFather. Acesse-o e então digite /newbot. Será solicitado um nome, então crie esse nome. Pronto, seu bot estará criado e seu token será exibido. Copie-o para seu programa, substituindo:

#define BOTtoken "0123456789:tokenDoTelegram"

Pelo token real.

Vídeo do controle remoto com bot Telegram

Esse vídeo estará disponível em ambos os canais, DobitaobyteBrasil e também ArduinoBrasil. O estúdio ainda não tinha nem mesa no dia do vídeo, mas não quisemos perder a oportunidade de gravar. Mas garanto que será uma experiência agradável, contando com a edição do vídeo!

Entrem nos canais e inscrevam-se!