Soluções voltadas a segurança de sistemas são parte da realidade de muitas pessoas atualmente, afinal, quem nunca se deparou com um leitor biométrico, câmeras de vigilância, etc. Componentes como RC522, são aplicados a construção de Interfaces de acesso, monitorando informações referentes a usuários ou objetos através da leitura de cartões, etiquetas ou chaveiros, com a capacidade de emitir sinais  de radiofrequência. Este tipo de tecnologia poderá ser encontrada tanto em catracas de transportes públicos, debitando valores digitalmente, quanto em soluções domótica, servindo como chave de acesso a determinados cômodos, desbloqueio de alarmes, e até mesmo para o acionamento de outros componentes eletrônicos. Neste post, iremos explorar o funcionamento deste tipo de tecnologia controlado por placas ESP32, descobrindo inicialmente como ler e armazenar informações em um determinado dispositivo, finalizando com uma transmissão de informações via Telegram, explorando o desenvolvimento de um sistema de monitoramento mobile.

Circuito Elétrico

          Para concluir as atividades desse post, tenha em mãos os seguintes componentes:

 

          Você pode compra-los clicando nos links acima ou visitando nosso site: www.curtocircuito.com.br.

          O funcionamento do leitor RFID será baseado no chip MF-RC522 da empresa NXP,  que opera com uma frequência de 13,56 MHz , classificada como ultra-alta frequência (UHF), possibilitando a leitura e o armazenamento de informações em cartões do padrão Mifare. A comunicação entre o leitor e o microcontrolador será obtida através da interface SPI, correspondendo aos pinos MISO (GPIO19), MOSI (GPIO23), CLK (GPIO18) e SCO (GPIO5) do ESP32. A ordem de conexão será apresentada na imagem abaixo:


A leitura do receptor RFID será dada através da comunicação SPI do ESP32.


          O leitor deverá se restringir a 3,3V, o pino RQ deverá permanecer desconectado, e RST será declarado na programação, portanto, poderá ser conectado a qualquer outro pino, no caso do exemplo acima, optamos por conecta-lo ao pino VP (GPIO36). No desenvolvimento com aplicativos como o Telegram será necessário conectar-se a internet, exigindo a aplicação de uma alimentação externa ao circuito elétrico. Como forma mais simplificada e segura, optamos por inserir uma fonte para protoboar, juntamente a um conversor AC/DC 9V, mas esta parte do circuito será opcional.

          Em alguns dos exercícios a seguir iremos utilizar um LED RGB, portanto, encaixe o LED no Protoboard, conectando os resistores de 1KΩ entre os pinos menores do LED e as portas digitais D15, D2 e D4 do ESP32, e alimente o pino maior de acordo com o tipo, se for anodo conectar ao positivo, e catodo ao negativo.


O LED RGB será utilizado para testar o funcionamento de algumas funções.


Leitura de ID

 

          Os objetos utilizados para a comunicação RFID serão conhecidos como Transponders, que são dispositivos de comunicação com o objetivo de transmitir, receber ou ampliar sinais de radiofrequência. Esse tipo de componente poderá ser classificado como passivo ou ativo, sendo que os ativos possuem uma fonte de alimentação própria, enquanto os passivos utilizam a energia do sinal do leitor para emitir respostas, e normalmente possuem algumas informações pré-definidas, no caso do chaveiro ou o cartão presente no Kit RFID, serão encontrados valores de ID e algumas informações referentes ao fabricante.  O ID represeenta um número de identificação exclusivo atribuido a cada transpoder, e descobri-lo será de grande importância em projetos futuros, afinal, com o registro de um determinado componente torna-se possível distingui-lo dos demais, atribuindo funções e comandos específicos. Antes de mais nada, instale as bibliotecas MFRC522.h e SPI.h, e transfira a programação a seguir ao ESP32.

/* Projeto Curto Circuito - ESP32 & RFID: Leitura de ID */
/* ---- Bibliotecas ---- */
#include <SPI.h>  /* https://github.com/PaulStoffregen/SPI */
#include <MFRC522.h> /*https://github.com/miguelbalboa/rfid */

/*---- Declara a Pinagem RST e SDA ---- */
#define SDA 5 /* Conectado ao pino D5 do ESP32 */
#define RST 36 /* Conectado ao pino VP do ESP32 */

/* ---- LED ---- */
int LED = 2;             /* LED presente no próprio ESP32 */

MFRC522 mfrc522(SDA, RST);/* Cria uma instância MFRC522. */

void setup()
{

  Serial.begin(9600);  /* Inicia a comunicação serial com o PC */
  SPI.begin();             /* Inicia SPI */
  mfrc522.PCD_Init();  /* Inicia MFRC522 */
  Serial.println("Encoste o cartao ou chaveiro no leitor");
  Serial.println();
  pinMode(LED, OUTPUT);

}

void loop()
{


  if ( ! mfrc522.PICC_IsNewCardPresent())
  { /* Procura por novos cartões */
    return;
  }

  if ( ! mfrc522.PICC_ReadCardSerial())
  { /* Reenicia a leitura */
    return;
  }
  Serial.print("ID do objeto:"); /* Mostra o valor de ID */
  String conteudo = "";
  byte letra;
  /* Rotina para despejar a matriz de bytes com os valores hexadecimais para Serial. */
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
    Serial.print(mfrc522.uid.uidByte[i], HEX);
    conteudo.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
    conteudo.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  digitalWrite (LED, HIGH);
  conteudo.toUpperCase(); /* Converte a String em Letras maiúsculas */
  delay(100);
  digitalWrite (LED, LOW);

}

          Após transferir a programação, abra o monitor serial e encoste o chaveiro ou cartão próximo ao leitor RFID, em seguida, observe que o valor impresso será similar ao exibido na imagem abaixo.


Ao abrir o monitor serial será possível visualizar a leitura do número de identificação individual de cada TAG.


          A leitura e armazenamento de informações será constituído por valores em Hexadecimal, que se trata de um sistema numérico composto por uma combinação de caracteres de 0-9 e A-F. No exemplo de leitura apresentado acima, o valor de identificação exclusiva do objeto é : E7 4F 7D 89.

          A biblioteca MFRC522.h será inserida com a finalidade de simplicar o uso do Leitor RFID, atuando em conjunto com o SPI.h, que, como o próprio nome sugere, irá inserir o protocolo de comunicação SPI. A função MFRC522 mfrc522(SDA, RST) cria um objeto com o nome mfrc522, que irá se comunicar com base nos pinos delarados em SDA e RST, e mfrc522.PCD_Init() inicia o funcionamento do Leitor.

          Os comandos mfrc522.PICC_IsNewCardPresent() e mfrc522.PICC_ReadCardSerial() irão construir um loop de leitura contínuo, buscando sempre por uma nova TAG, enquanto a rotina  for (byte i = 0; i < mfrc522.uid.size; i++) será responsável por imprimir os valores Hexadecimais no Monitor Serial. 

 

Leitura e Armazenamento de Informações

 

          O desafio princiapal para quem utiliza tecnologias RFID, será o armazenamento personalizado de informações em transpoders, registrando dados importantes como nomes, saldos e números de indentificação. O registro de anotações pessoais irá exigir um cartão ou chaveiro programável, afinal, nem todos os modelos terão este tipo de opção, na verdade, é até muito comum encontrar alguns que servirão apenas para a leitura.  No caso do kit RFID fornecido por nós, ambos os componentes permitirão o registro de informações, com uma memória de 1KB EEPROM (768 bytes livre), e até 100.000 ciclos de durabilidade de escrita.

          Na programação a serguir iremos desenvolver um teste simples através do monitor serial do Arduino IDE, gravando duas variáveis com um nome e RG fictícios no cartão RFID, e em seguida realizando uma leitura das informações armazenadas no mesmo. O circuito elétrico será similar ao utilizado nos exemplos anteriores.

/* Projeto Curto Circuito – ESP32 & RFID: Leitura e Armazenamento */

/* ------ Bibliotecas -------- */
#include <SPI.h>
#include <MFRC522.h> 
/*-------- SPI configuração do pinos do Leitor----------- */
#define SDA 5 /* Conectado ao pino D5 do ESP32 */
#define RST 36 /* Conectado ao pino VP do ESP32 */
MFRC522 mfrc522(SDA, RST);
/*-------- LED RGB----------- */
int RED = 15;
int BLUE = 2;
int GREEN = 4;

void setup()
{
  Serial.begin(115200);
  pinMode(RED, OUTPUT);      /* RED D15 do ESP32 */
  pinMode(GREEN, OUTPUT);    /* GREEN D4 do ESP32 */
  pinMode(BLUE, OUTPUT);     /* BLUE D2 do ESP32 */
  SPI.begin();               /* Inicia o protocolo SPI */
  mfrc522.PCD_Init();        /* Inicia o Leitor */
  Serial.println("Aproxime o cartão/chaveiro e Digite: 1 - Leitura ou 2 - Armazenamento");

}
void loop()
{
  digitalWrite(RED, LOW);   /* Desliga LED Red */
  digitalWrite(GREEN, LOW); /* Desliga LED Green */
  digitalWrite(BLUE, HIGH); /* Liga LED Blue */

  /* Armazena os caracteres escritos no Monitor Serial */
  char choice = Serial.read();

  if (choice == '1')
  { /* Se receber 1 */
    Serial.println("Opção 1: Leitura de informações");
    leitor(); /* Função Leitor */

  }

  else if (choice == '2')
  { /* Se receber 2 */
    Serial.println("Opção 2: Armazenamento de informações");
    escritor(); /* Função Gravador */
  }


}
void leitor()
{
  digitalWrite(BLUE, LOW);   /* Desliga LED Blue*/
  digitalWrite(GREEN, HIGH); /* Liga LED Green*/

  /* Prepara chave de segurança no formato FFFFFFFFFFFFh */
  MFRC522::MIFARE_Key key;
  for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

  /* Procura por novos cartões*/
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }
  /* Reenicia a leitura */
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }

  /*Variável para controlar os blocos de memórias */
  byte block;
  /*Variável para acessar as linhas */
  byte len;
  /*Verifica o status de leitura */
  MFRC522::StatusCode status;
  /* Quando encontrar alguma informação escreve no monitor serial */
  Serial.println(F("----Informações Encontradas----"));
  mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid));

  /*---Variável 1: Nome --- */

  byte buffer1[18];
  /* Direciona a leitura ao bloco 4 */
  block = 4;
  len = 18;
  Serial.print(F("Nome: "));
  /* Coleta as informações armazenadas no bloco 4 */
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(mfrc522.uid));
  status = mfrc522.MIFARE_Read(block, buffer1, &len);

  /* Escreve as informações no monitor serial */
  for (uint8_t i = 0; i < 16; i++)
  {
    if (buffer1[i] != 32)
    {
      Serial.write(buffer1[i]);
    }
  }
  Serial.print(" ");

  /*---Variável 2: RG --- */

  byte buffer2[18];
  /* Direciona a leitura ao bloco 1 */
  block = 1;
  /* Coleta as informações armazenadas no bloco 1 */
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 1, &key, &(mfrc522.uid)); /* line 834 */
  status = mfrc522.MIFARE_Read(block, buffer2, &len);

  Serial.print(F("RG: "));
  /* Escreve as informações no monitor serial */
  for (uint8_t i = 0; i < 16; i++) {
    Serial.write(buffer2[i] );
  }
  Serial.println(F("\n----Fim----\n"));

  delay(1000);
  /* Se tiver finalizado a leitura */
  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
  setup();  /* Retorna ao void Setup */
}

void escritor()
{
  digitalWrite(BLUE, LOW); /* Desliga LED Blue */
  digitalWrite(RED, HIGH); /*Liga LED Red */
  /* Prepara chave de segurança no formato FFFFFFFFFFFFh */
  MFRC522::MIFARE_Key key;
  for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

  /* Procura por novos cartões*/
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  } 
  /* Reenicia a leitura */
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }
  Serial.print(F("ID:"));    /* Indica o valor de ID (UID) */
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
    Serial.print(mfrc522.uid.uidByte[i], HEX);
  }
  Serial.print(F(" Tipo: "));   /* Tipo */
  MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
  Serial.println(mfrc522.PICC_GetTypeName(piccType));

  byte buffer[34];
  byte block;
  MFRC522::StatusCode status;
  byte len;
  /* Aguarda até 20 segundo pelas informações */
  Serial.setTimeout(20000L) ;
  /* Variável 1: RG, finalize o Valor desejado com */
  Serial.println(F("Escreva o RG, finalizando com #"));
  len = Serial.readBytesUntil('#', (char *) buffer, 30) ; /* Le o nome para a serial */
  for (byte i = len; i < 30; i++) buffer[i] = ' ';

  /* Direciona as informações ao bloco 1 */
  block = 1;
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));

  /* Escreve no bloco 1 */ 
  status = mfrc522.MIFARE_Write(block, buffer, 16);
  Serial.println(F("Valores armazenados no bloco 1"));


  /* Variável 2: Nome, finalize o nome desejado com #; */
  Serial.println(F("Escreva o nome, finalizando com #"));
  len = Serial.readBytesUntil('#', (char *) buffer, 20) ;
  for (byte i = len; i < 20; i++) buffer[i] = ' ';

  /* Direciona as informações ao bloco 4 */
  block = 4;
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));

  /* Escreve no bloco 4 */
  status = mfrc522.MIFARE_Write(block, buffer, 16);
  Serial.println(F("Valores armazenados no bloco 4"));
  Serial.println(F(" "));

  Serial.println(F("Informações Armazenadas com Sucesso."));


  Serial.println(" ");
  /* Ao finalizar */
  mfrc522.PICC_HaltA(); 
  mfrc522.PCD_StopCrypto1(); 
  setup();/* Retorna ao void Setup */
}

          Como foi dito anteriormente, os dispositivos Mifare presente no kit são EEPROM 1KB, e, segundo o datasheet do fabricante, a memória será organizada em 16 setores (de 0 á 15), e 4 blocos (de 0 á 3) composto por 16 Bytes cada. O bloco 0 do setor 0 será protegido contra gravações, pois este contem informações referentes ao fabricante, assim como o número de série exclusivo do componente (UID).    


O esquema apresentado a seguir encontra-se a disposição no datasheet do próprio fabricante, exemplificando a distribuição dos blocos de memória dos dispositivos Mifare.


          Para simplificar a programação construimos a variável byte block , cuja função será direcionar a leitura e o armazenamento de informação a alguns blocos de memória específicos. Abra o monitor serial, aproxime o cartão ou chaveiro no leitor RFID, e envie o caractere 1.


Encoste o dispositivo, e envie no monitor serial a função desejada, sendo 1 para ler, e 2 para armazenar.


          Ao enviar o valor "1", será iniciada a leitura dos dados armazenados no dispositivo, direcionando-a diretamente aos blocos de memória 1 e 4. No caso da imagem a seguir, o cartão utilizado não contém quaisquer informações armazenadas nos blocos específicos, exibindo apenas o número de série (UID) e as variáveis "nome" e "RG" vazias.


A primeira leitura de um cartão virgem costuma conter apenas as informações gravadas pelo próprio fabricante, contendo informações técnicas e o ID do objeto.


          Envie o número "2" para habilitar o modo de armazenamento do programa. A função MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak), será responsável por coletar as informações referente ao fabricante, Serial.println(mfrc522.PICC_GetTypeName(piccType)) irá imprimir tal valor no monitor serial, enquanto a rotina  for (byte i = 0; i < mfrc522.uid.size; i++) será responsável por indicar o ID exclusivo do dispositivo em Hexadecimais. 

          O comando status = mfrc522.PCD_Authenticate (MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid)) irá direcionar as informações a seus devidos blocos, enquanto status = mfrc522.MIFARE_Write(block, buffer, 16) terá o papel de grava-los. Antes de enviar os valores desejados, finalize-os com "#" como mostra o exemplo a seguir.   


Finalize a informação que deseja salvar com o símbolo "#".


          Após preencher as variáveis, realize outra leitura para verificar se os valores escritos foram salvos corretamente. 


Ao realizar uma segunda leitura, observe que as informações pessoais inseridas anteriormente, estarão armazenadas nas variáveis "nome" e "RG"


          Serial.setTimeout(20000L), descrita na programação, terá a função de limitar a espera das informações a serem armazenadas, aguardando apenas 20 segundos. Se desejar apagar alguma informação, por exemplo, basta aguardar o tempo limite, deixando de preencher as variáveis RG, NOME ou ambas. 

 

Controle de Acesso via Telegram

          A aplicação mais comum a este tipo de componente, será localizada em sistemas de segurança, controlando o horário de transição em portarias e empresas por meio do registro de cartões/Tags RFID. Com base nisso, iremos explorar o desenvolvimento de um sistema de monitoramento de acesso, visualizando o horário de entrada e saída de um determinado indivíduo através do Telegram, que trata-se de um aplicativo para troca de mensagens instantâneas baseado na nuvem.


O Telegram disponibiliza servos robôs, que poderão auxilia-lo no controle de sistemas através do envio de comandos via chat.


          Diferente te outras ferramentas como Whatsapp, Mensseger, o Telegram facilita a construção de sistemas como Internet of Things, possibilitando um controle para componentes através da troca de mensagens entre plataformas mobile como smartphones ou tablets, e microcontroladores como ESP32, NodeMCU, etc. E, de forma simples, esse aplicativo disponibiliza a seus usuários uma inteligência artificial (IA) capaz de auxilia-lo na construção de seu próprio robô virtual (Bot), que, no caso do projeto proposto, servirá no controle de acesso, visualizando o horário de entrada/saída de cada usuário registrado. Para criar seu próprio chatBot, abra a tela inicial do aplciativo e pesquise por : @BotFather. 


Como referência ao clássico filme "O poderoso chefão", os usuários deverão pedir permissão ao "Father" para conseguir construir um chatbot particular.


          O comando irá direciona-lo a um chat particular com o "Father", o robô virtual do Telegram, que apresentará diversas ferramentas e funções exclusivas. Clique em "Iniciar", inicie a conversa com o comando "/newbot", solicitando a construção de um novo chatBot. Como resposta, o Father irá lhe solicitar um nome para o novo Bot,  e um usuário finalizado com a palavra "bot", este será utilizado como forma de localiza-lo na barra de pesquisa, que, no caso da imagem a seguir, seria : @Curtocircuitobot. 


Os chatbots particulares serão compostos por uma IA programável, que irá auxiliar no desenvolvimento de projetos automatizados.


          Na confirmação da construção do novo auxiliar virtual, será enviado um Token de acesso, uma chave de API composta por diversas letras e números, com a função de estabelecer conexão entre seu chat particular no Telegram e o ESP32.


Para construir uma comunicação entre o chatbot e ESP32, será necessário inserir um token API, que atuará como uma autenticação na comunicação entre o Hardware e o Software.


          Procure por seu novo chatBot na barra de pesquisa, por exemplo: @Curtocircuitobot.


Para localizar o bot recém criado, escreva "@" juntamente ao nome do chat.


          Na programação a seguir, iremos utilizar o protocolo de comunicação NTP, abordado em outras postagens, como meio de indicar o horário preciso do acesso no leitor RFID. A transmissão da hora correta, assim como a troca de mensagens via Telegram irá exigir que o ESP32 esteja  conectado a uma rede Wi-Fi, portanto, antes de transferir o programa substitua os valores de "ssid" e "password" por um usuário e senha de uma rede conhecida, adicione o valor de token fornecido pelo "Father" na variável BOTtoken, e adicione as bibliocas UniversalTelegramBot e NTPClient.

/* Projeto Curto Circuito – ESP32 & RFID: Controle via Telegram */

/* ------ Bibliotecas -------- */
#include <WiFi.h>
#include <NTPClient.h> /* https://github.com/arduino-libraries/NTPClient */
#include <SPI.h>
#include <MFRC522.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h> /* https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot */

/* -------- SPI configuração do pinos do Leitor----------- */
#define SDA 5 /* Conectado ao pino D5 do ESP32 */
#define RST 36 /* Conectado ao pino VP do ESP32 */
MFRC522 mfrc522(SDA, RST);

/*-------- Configurações de relógio on-line----------- */
WiFiUDP udp;
NTPClient ntp(udp, "a.st1.ntp.br", -3 * 3600, 60000); /*Cria um objeto "NTP" com as configurações.utilizada no Brasil */
String hora;            /* Variável que armazena */


/* -------- Configurações de Wi-Fi----------- */
const char* ssid = "NOME_DA_REDE;
const char* password =  "SENHA";

/* -------- Token de acesso Telegram----------- */
#define BOTtoken " Token:Insira a sequência completa de números e letras" /* Token do telegram */

/* -------- LED----------- */
#define BLUE 2
#define RED 15

/*------- Variáveis lógicas ---------- */
int i = 0;
String sit ;
unsigned long temp;


/* ------- Registro de Usuários ---------- */
String cartao = "E7 4F 7D 89";     /*  Insira um valor ID conhecido */
String chaveiro = "00 0E B8 73"; /*Insira um valor de ID conhecido */
int id = 0;
int id2 = 0;


WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);


void setupWifi()
{ /* BConectando ao Wi-Fi */
  Serial.begin(115200);      /* Transmissão em 115200 */
  delay(2000);               /* Aguarda 2 segundos. */
  ntp.begin();               /* Inicia o protocolo NTP */

  /* Indica o Wi-Fi ao qual se conectou */
  Serial.print("Conectando ao Wifi: ");
  Serial.println(ssid);

  /* Tenta se Conectar aos valores armazenados em ssid e password */
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED)
  { /* Enquanto estiver desconectado */
    Serial.print(".");
    delay(500);
  }
  ntp.forceUpdate();          /* Atualização do horário */
  Serial.println("");
  Serial.println("Wi-Fi conectado");
  Serial.print("Endereço de IP: ");
  Serial.println(WiFi.localIP());
}

void setup()
{
  Serial.begin(115200);      /* Transmissão em 115200 */
  SPI.begin();               /* Inicia o protocolo SPI */
  mfrc522.PCD_Init();        /* Inicia o Leitor */
  pinMode(RED, OUTPUT);      /* LED Vermelho */
  pinMode(BLUE, OUTPUT);     /* LED Verde */
  setupWifi();
}

void loop()
{
  if (millis() > 1500)
  { /* Cria um intervalo de tempo entre as leituras */
    rfid();
  }

  /* Armazena o horário atual. */
  hora = ntp.getFormattedTime();
}

void rfid()
{
  /* ---------- Armazenando informações ------- */
  String chat_id = String(bot.messages[i].chat_id);/* Armazena o ID */
  String text = bot.messages[i].text; /*Armazena o texto */
  int NewMessages = bot.getUpdates(bot.last_message_received + 1); /* Atualiza as mensagens */

  if ( ! mfrc522.PICC_IsNewCardPresent())
  { /* Procura por novos cartões */
    return;
  }

  if ( ! mfrc522.PICC_ReadCardSerial())
  { /* Reenicia a leitura */
    return;
  }

  MFRC522::MIFARE_Key key;
  MFRC522::StatusCode status;
  for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

  /*---------- Leitura do ID ------- */
  Serial.print("ID do objeto:"); /* Mostra o valor de ID */
  String conteudo = "";

  /* Rotina para despejar a matriz de bytes com os valores hexadecimais na Serial. */
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
    Serial.print(mfrc522.uid.uidByte[i], HEX);
    conteudo.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
    conteudo.concat(String(mfrc522.uid.uidByte[i], HEX));
  }

  Serial.println();
  conteudo.toUpperCase(); /* Converte a String em Letras maiúsculas */



  /*---------- Leitura do Nome ------- */
  String conteudo2 = "";
  /* Variável para controlar os blocos de memórias */
  byte block;
  /* Variável para acessar as linhas */
  byte len;
  byte buffer2[18];
  /* Direciona a leitura ao bloco 1 */
  block = 4;
  len = 18;
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(mfrc522.uid));
  status = mfrc522.MIFARE_Read(block, buffer2, &len);
  for (uint8_t i = 0; i < 16; i++) {
    if (buffer2[i] != 32)
    {
      Serial.write(buffer2[i]);

      conteudo2.concat(char(buffer2[i]));

    }
  }
  Serial.println();
  conteudo2.toUpperCase(); /* Converte a String em Letras maiúscula s */

  /* ---------- Leitura do RG ------- */

  String conteudo3 = "";
  byte buffer1[18];
  /* Direciona a leitura ao bloco 1 */
  block = 1;

  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 1, &key, &(mfrc522.uid));
  status = mfrc522.MIFARE_Read(block, buffer1, &len);
  for (uint8_t i = 0; i < 16; i++) {
    if (buffer1[i] != 32)
    {
      Serial.write(buffer1[i]);

      conteudo3.concat(char(buffer1[i]));

    }
  }

  Serial.println();
  conteudo3.toUpperCase(); /* Converte a String em Letras maiúsculas */
  if (conteudo.substring(1) == cartao || conteudo.substring(1) == chaveiro)
  {
    digitalWrite(RED, 1);
    if (conteudo.substring(1) == cartao)
    {
      id = !id;
      if (id == 1)
      {
        sit = "Entrada";

      }
      else
      {
        sit = "Saída";
      }
    }
    if (conteudo.substring(1) == chaveiro)
    {
      id2 = !id2;
      if (id2 == 1)
      {
        sit = "Entrada";

      }
      else
      {
        sit = "Saída";
      }
    }
  }
  else
  {
    Serial.println("Cartão desconhecido");
    digitalWrite(BLUE, 1);
  }

  /*---------- Transmitindo ao Telegram------- */

  Serial.println("Cartão on"); /* Cartão ON */
  /* Envia ao Telegram o horário, nome e status Entrando */
  String msg = "\nSituação: " + sit;
  msg += "\n Nome: " + conteudo2;
  msg += "\n Horário:" + hora; /* Horário */
  msg += "\n ID:" + conteudo;
  msg += "\n RG:" + conteudo3;
  bot.sendMessage(chat_id, msg, "");
  delay(10);
  digitalWrite(RED, 0);
  digitalWrite(BLUE, 0);
  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
  loop();
}

          Todas as informações armazenadas na String msg serão enviadas ao Telegram através do comando bot.sendMessage(chat_id, msg, ""), porém, antes de visualizar qualquer mensagem, será necessário iniciar a comunicação entre o ESP32 e o aplicativo, portanto, abra seu chatbot exclusivo e envie o comando "/start", em seguida, aproxime um cartão ou chaveiro cujo valor esteja registrado nas variáveis String cartao e String chaveiro, o LED D2 irá acender indicando a leitura de um dispositivo conhecido, enquanto D15 será voltado a leituras de Tags desconhecidas.


Após iniciar uma conversa com o chatbot através do comando "/start", encoste um dispositivo e visualize se as informações foram enviadas corretamente ao Telegram.


          A hora correta será coletada através do protocolo NTP, que tem como função coletar um determinado horário com base em servidores na internet. A configuração de um padrão regional irá depender das informações adicionadas na variável NTPClient, que será utilizada como ponte na comunicação entre um servidor externo e o ESP32, ajustando o relógio de acordo com o valor fornecido.

NTPClient ntp(udp, "a.st1.ntp.br", -3 * 3600, 60000);

NTPClient: Função que configura o fuso horário

ntp: Armazena os valores configurados;

udp:Estabelece uma comunicação entre o ESP32 e um cliente externo, no caso desse exemplo, o NTP.

a.st1.ntp.br: Endereço on-line utilizado na coleta da hora correta no servidor.

-3 : Fuso brasileiro segundo o Meridiano de Greenwich.

3600 : Multiplica pelo fuso formatando a leitura em segundos. 

60000: Intervalo entre cada atualização (1 minuto)

 

          As funções ntp.forceUpdate() e  ntp.begin() serão responsáveis por manter a leitura do horário ativa e atualizada, enquanto o ntp.getFormattedTime() ajusta o formato do horário em hora/minuto/segundo (00:00:00). Para conhecer os servidores brasileiros disponíveis, ou ajustar a leitura para o horário de verão, acesse o site oficial da NTP.  

          Ao abrir o monitor serial serão exibidas duas informações iniciais, o nome da rede ao qual o ESP32 tentará conectar-se através do comando Serial.println(ssid), e ao conectar irá imprimir o endereço de IP através de Serial.println(WiFi.localIP()). Após estabelecer conexão, será exibido o valor de ID de qualquer transponders que se aproxime do leitor RFID, com um intervalo de 1,5 segundos entre cada leitura, determinado na função if (millis() > 1500).


Utilize o monitor serial para visualizar o status de conexão do ESP32 na rede de internet.


          A função conteudo.substring(1 será a responsável por registrar o acesso de transpoders conhecidos, de acordo com os valores de ID registrados em String cartao e String chaveiro, para ajustar a um valor de Tag  específico de sua preferência, basta substituir o valor registrado entre aspas nas variáveis String cartao = "E7 4F 7D 89"String chaveiro = "00 0E B8 73". Quaisquer outros dispositivos que não possuam o valor declarado na programação, serão exibidos  no monitor serial como "desconhecido", exibindo as informações dos blocos de memória 1 e 4.

   Cartões desconhecidos não serão capaz de enviar informações ao telegram.


          O comando id = !id, será responsável por avaliar o status de acesso de usuários conhecidos, invertendo o valor armazenado a cada acesso autorizado, sendo eles 1 na condição de entrada, e 0 na saída. Nas funções status = mfrc522.PCD_Authenticate (MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(mfrc522.uid)) e status = mfrc522.MIFARE_Read(block, buffer2, &len), os valores armazenados em block, buffer e len, serão utilizados para direcionar a leitura a determinados setores de memória do transpoder, imprimindo as informações coletadas através de Serial.write(buffer2[i]), no monitor serial, e conteudo2.concat(char(buffer2[i])), no Telegram.

O telegram irá atuar como um breve banco de dados para a leitura das informações presente nas Tags RFID.

 


Considerações Finais

          Tecnologias RFID  são aplicadas a sistemas de segurança desde os anos 60, servindo como um importante aliado em metodologias de identificação automática, através da transmissão de dados por sinais de radiofrequência. O registro de informações em etiquetas, cartãos, entre outros dispositivos, simplifica a identificação de pessoas ou objetos, agilizando processos de controle e segurança. Integrar esse tipo de tecnologia a plataformas como o Telegram irá simplificar a construção de muitos projetos, visto que o aplicativo em questão, por exemplo, possui um sistema de comunicação integrado a nuvem, possibilitando utiliza-lo como um banco de dados, e realizar a troca mensagens entre o softwarer e o ESP32 de forma praticamente instantânea.