Conhece o SNMP (Simple Network
Management Protocol), em portuguĂȘs: Protocolo Simples de GerĂȘncia de Rede?
Utilizado para controlar serviços e equipamentos na internet, bem como para
gerenciamento de dispositivos em redes IP, resolvi utilizĂĄ-lo em um projeto
semelhante a um que eu jĂĄ tinha desenvolvido: Controle AutomĂĄtico de Umidificador usando ESP32/8266.
Utilizando um ESP32 e um
ESP8266, este segundo ligado a um aparelho umidificador através de um relé,
estes ESPs se comunicam atravĂ©s do protocolo ESP-NOW. Ă possĂvel checar a
temperatura e umidade de um ambiente, como um CPD, por exemplo, monitorando a
rede com o SNMP.
O ESP32 vai ler umidade,
temperatura e mostrar em um display Oled. Baseado na umidade, este mesmo
microcontrolador vai, portanto, através do protocolo ESP-NOW, enviar sinal para
um ESP8266 ligar ou desligar o relĂȘ. Verificaremos temperatura e umidade
atravĂ©s do protocolo SNMP e alteraremos umidade mĂĄxima e mĂnima de acionamento
do relĂȘ tambĂ©m utilizando o protocolo SNMP.
ESP32 Pinout
Montagem
Na montagem, como vocĂȘ pode
ver na imagem, utilizamos também um DHT22.
Arquitetura SNMP
No protocolo SNMP, temos
agentes que trocam mensagens de comando e de resposta.
Demonstração
SNMP
O SNMP (Simple Network
Management Protocol) Ă© um protocolo usado em sistemas de gerenciamento de redes
para que se possa monitorar diversos dispositivos.
Mais informaçÔes: https://www.gta.ufrj.br/grad/10_1/snmp/snmp.htm
Biblioteca SimpleDHT
Na IDE do Arduino vĂĄ em
Sketch->Incluir Biblioteca->Gerenciar Bibliotecas...
Instale SimpleDHT
Biblioteca SSD1306
Na IDE do Arduino vĂĄ em
Sketch->Incluir Biblioteca->Gerenciar Bibliotecas...
Procure por SSD1306 e instale
ESP8266 and ESP32 Oled Driver for SSD1306 display
Biblioteca ArduinoSNMP
VĂĄ em
https://github.com/fusionps/Arduino_SNMP faça o download do arquivo ZIP
descompacte e copie para a pasta
C:\Users\<SEU_USUARIO>\Documents\Arduino\libraries
CĂłdigo Fonte
Neste projeto temos dois
cĂłdigos fonte, sendo o primeiro do ESP32 e o segundo, do ESP8266, que fica
ligado no relé de estado sólido.
ESP32_EspNow_Master.ino
Vamos incluir as bibliotecas e
definir os pinos. Iniciamos o SMMPAgent.
#include <esp_now.h> #include <WiFi.h> #include <SimpleDHT.h> #include <WiFiUdp.h> #include <Arduino_SNMP.h> #include <SSD1306.h> #include <FS.h> #include <SPIFFS.h> #define DHTPIN 4 #define INTERVAL 100 #define ESPNOW_CHANNEL 1 #define CONFIG_PATH "/conf.bin" #define SSID "SSID" #define PASSWORD "12345678" #define IP "192.168.0.134" WiFiUDP udp; SNMPAgent snmp = SNMPAgent("public"); //Inicia o SMMPAgent //ReferĂȘncias para o SNMP char* strHumidity; char* strTemperature; //Valores caso nada esteja salvo no arquivo de configuração int maxHumidity = 65; int minHumidity = 55;
Seguimos definindo parĂąmetros:
//parametros: address,SDA,SCL SSD1306 display(0x3c, 21, 22); //construtor do objeto que controlaremos o display uint8_t slaveMacAddress[] = {0x1A,0xFE,0x34,0xA5,0x90,0x69}; // uint8_t slaveMacAddress[] = {0x18,0xFE,0x34,0xA5,0x90,0x69}; esp_now_peer_info_t slave; //Objeto que realiza a leitura da umidade SimpleDHT22 dht; //VariĂĄvel para guardarmos o valor da umidade float humidity = 0; //VariĂĄvel para guardarmos o valor da temperatura float temperature = 0;
No Setup, inicializamos o monitor serial e chamo a função para guardar as strings. Verifico a possibilidade de carregar o arquivo. Ainda inicializo aqui o WiFi, protocolo SNMP, Display, ESP-NOW e o Slave.
void setup() { Serial.begin(115200); strHumidity = (char*)malloc(6); strTemperature = (char*)malloc(6); memset(strHumidity, 0, 6); memset(strTemperature, 0, 6); if(SPIFFS.begin(true)) { loadConfig(); } else { //Se nĂŁo conseguiu inicializar Serial.println("SPIFFS Mount Failed"); } setupWiFi(); setupSNMP(); setupDisplay(); setupESPNow(); setupSlave(); }
Loop
No Loop, chamo as funçÔes para
leitura do sensor, verificação de SNMP, exibição no display, verificação de
umidade e intervalo.
void loop() { readSensor(); verifySNMP(); showOnDisplay(); verifyHumidity(); delay(INTERVAL); }
SetupWiFi
Antes de tudo, vamos desconectar
para limpar configuraçÔes e depois inicializar a rede.
void setupWiFi() { WiFi.disconnect(); WiFi.mode(WIFI_STA); WiFi.begin(SSID, PASSWORD); Serial.println(""); // Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Connected to "); Serial.println(SSID); //Configura o IP IPAddress ipAddress; ipAddress.fromString(IP); WiFi.config(ipAddress, WiFi.gatewayIP(), WiFi.subnetMask()); Serial.print("IP address: "); Serial.println(WiFi.localIP()); }
SetupSNMP
Aqui inicializamos o SNMP e utilizamos
o PEN 12345 apenas para testes. Para uma aplicação de verdade o correto seria registrar
a aplicação em https://pen.iana.org/pen/PenApplication.page para não haver
conflitos.
void setupSNMP() { //Inicializa o snmp snmp.setUDP(&udp); snmp.begin(); //Adiciona o OID para umidade (apenas leitura) snmp.addStringHandler(".1.3.6.1.4.1.12345.0", &strHumidity, false); //Adiciona o OID para temperatura (apenas leitura) snmp.addStringHandler(".1.3.6.1.4.1.12345.1", &strTemperature, false); //Adiciona o OID para umidade mĂĄxima (leitura e escrita) snmp.addIntegerHandler(".1.3.6.1.4.1.12345.2", &maxHumidity, true); //Adiciona o OID para umidade mĂnima (leitura e escrita) snmp.addIntegerHandler(".1.3.6.1.4.1.12345.3", &minHumidity, true); }
SetupDisplay
Aqui inicializamos o display e
configuramos a fonte.
void setupDisplay(){ display.init(); //inicializa o display display.flipScreenVertically(); display.setFont(ArialMT_Plain_10); //configura a fonte }
SetupESPNow
Verificamos se a inicialização
foi bem sucedida.
void setupESPNow() { //Se a inicialização foi bem sucedida if (esp_now_init() == ESP_OK) { Serial.println("ESPNow Init Success"); } //Se houve erro na inicialização else { Serial.println("ESPNow Init Failed"); ESP.restart(); } }
SetupSlave
Adicionamos aqui o Slave. Caso
vocĂȘ queira saber mais detalhes de ESP-NOW, recomendo este vĂdeo: ESP32 com Protocolo ESP-NOW.
void setupSlave(){ slave.channel = ESPNOW_CHANNEL; //0 para não usar criptografia ou 1 para usar slave.encrypt = 0; //Copia o endereço do array para a estrutura do slave memcpy(slave.peer_addr, slaveMacAddress, 6); //Adiciona o slave esp_now_add_peer(&slave); }
SendRelayStatus
Enviamos para o Slave o status
atual do relé.
void sendRelayStatus(int relayStatus){ //Envia para o slave o status atual do relĂȘ esp_err_t result = esp_now_send(slaveMacAddress, (uint8_t*)&relayStatus, 1); }
VerifySNMP
Essa função deve ser sempre
chamada durante o loop principal.
void verifySNMP() { //Deve ser sempre chamado durante o loop principal snmp.loop(); //Se aconteceu alteração de um dos valores if(snmp.setOccurred) { //Salva as os valores saveConfig(); //Reseta a flag de alteração snmp.resetSetOccurred(); } }
VerifyHumidity
Verificamos se a umidade estĂĄ
fora dos limites e informamos ao ESP8266 se o relé deve ficar ligado ou
desligado.
//Verifica se a umidade estĂĄ fora dos limites e informa ao ESP8266 //se o relĂȘ deve ficar ligado ou desligado void verifyHumidity(){ if(humidity > maxHumidity) { sendRelayStatus(LOW); } else if(humidity < minHumidity) { sendRelayStatus(HIGH); } }
ReadSensor
Essa função é responsåvel por
realizar a leitura da umidade e temperatura.
//Função responsåvel por realizar a leitura //da umidade e temperatura void readSensor(){ float h, t; int status = dht.read2(DHTPIN, &t, &h, NULL); if (status == SimpleDHTErrSuccess) { humidity = h; temperature = t; //Transforma os dados em string String strH = String(humidity); strH.toCharArray(strHumidity, strH.length()); String strT = String(temperature); strT.toCharArray(strTemperature, strT.length()); } }
ShowOnDisplay
Trabalhamos aqui com a
exibição dos dados no display.
//Mostra a umidade no display void showOnDisplay(){ //apaga o conteĂșdo do display display.clear(); display.setTextAlignment(TEXT_ALIGN_LEFT); display.setFont(ArialMT_Plain_16); display.drawString(0, 0, "Humidity: "); display.drawString(70, 0, String(humidity)); display.drawString(0, 30, "Temperat: "); display.drawString(75, 30, String(temperature)); display.display(); //mostra o conteĂșdo na tela }
SaveConfig
Nesta etapa, abrimos o arquivo
para salvar as configuraçÔes.
void saveConfig() { Serial.println("saveConfig"); //Abre o arquivo para escrita File file = SPIFFS.open(CONFIG_PATH, FILE_WRITE); //Se nĂŁo conseguiu abrir/criar o arquivo if(!file) { Serial.println("Failed to open file for writing"); return; } file.seek(0); file.write((uint8_t*)&maxHumidity, sizeof(maxHumidity)); file.write((uint8_t*)&minHumidity, sizeof(minHumidity)); //Fecha o arquivo file.close(); }
LoadConfig
Aqui abrimos o arquivo para
leitura.
void loadConfig() { Serial.println("loadConfig"); File file = SPIFFS.open(CONFIG_PATH, FILE_READ); //Se arquivo nĂŁo existe if(!file) { //Na primeira vez o arquivo ainda nĂŁo foi criado Serial.println("Failed to open file for reading"); return; } file.read((uint8_t*)&maxHumidity, sizeof(maxHumidity)); file.read((uint8_t*)&minHumidity, sizeof(minHumidity)); //Fecha o arquivo file.close(); }
ESP8266_EspNow_Slave.ino – setup
IncluĂmos duas bibliotecas
importantes aqui: do ESP-NOW e do ESP8266WiFi.
extern "C" { #include <espnow.h> } #include <ESP8266WiFi.h> #define RELAY_PIN D1
Setup
Colocamos o pino do relé como
saĂda e com sinal baixo. Resetamos, entĂŁo, as configuraçÔes da WiFi e colocamos
em modo AP. Copiamos o endereço que aparece e colocamos no slaveMacAddress do
Master.
void setup() { Serial.begin(115200); //Coloca o pino do relĂȘ como saĂda e coloca com sinal baixo pinMode(RELAY_PIN, OUTPUT); digitalWrite(RELAY_PIN, HIGH); //Reseta as configuraçÔes da WiFi WiFi.disconnect(); //Coloca em modo AP WiFi.mode(WIFI_AP); setupESPNow(); //Copiar o endereço que aparece aqui e colocar //no slaveMacAddress do Master Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress()); }
SetupESPNow
Inicializamos o ESP-NOW e registramos
a função que serå executada quando novos dados chegarem.
void setupESPNow(){ //Inicializa o ESPNOW if (esp_now_init()!=0) { Serial.println("EspNow init failed"); ESP.restart(); } //0=IDLE, 1=MASTER, 2=SLAVE and 3=MASTER+SLAVE esp_now_set_self_role(ESP_NOW_ROLE_SLAVE); //Registra a função que serå executada quando novos //dados chegarem esp_now_register_recv_cb(receiveCallback); }
ReceiveCallback
Esta função coleta as
mensagens do ESP-NOW e executa a ação de ligar ou de desligar o umidificador.
//Função que serå executada quando chegarem novos dados void receiveCallback(uint8_t *mac, uint8_t *data, uint8_t len) { int relayStatus = data[0]; Serial.println("Received " + String(relayStatus)); digitalWrite(RELAY_PIN, !relayStatus); }
Loop
Neste cĂłdigo nĂŁo temos nada
para fazer no loop jå que as informaçÔes são recebidas pelo receiveCallback automaticamente
quando novos dados chegam.
//Nada para fazer no loop jå que as informaçÔes //são recebidas pelo receiveCallback //automaticamente quando novos dados chegam void loop() { }
NET SNMP
VĂĄ para https://sourceforge.net/projects/net-snmp/files/net-snmp/ e instale o Net SNMP.
Digite no cmd ou terminal:
snmpget -v 1 -c public 192.168.0.134 1.3.6.1.4.1.12345.0 para verificar o valor da umidade
snmpget -v 1 -c public 192.168.0.134 1.3.6.1.4.1.12345.1 para verificar o valor da temperature
snmpget -v 1 -c public 192.168.0.134 1.3.6.1.4.1.12345.2 para verificar a umidade mĂĄxima
snmpget -v 1 -c public 192.168.0.134 1.3.6.1.4.1.12345.3 para verificar a umidade minima
snmpwalk -v 1 -c public 192.168.0.134 1.3.6.1.4.1.12345 para verificar todos a partir do 12345
snmpset -v 1 -c public 192.168.0.134 1.3.6.1.4.1.12345.2 i 75 para alterar o valor da umidade mĂĄxima
para 75 (ou substitua 75 por qualquer outro valor maior que a umidade mĂnima)
snmpset -v 1 -c public 192.168.0.134 1.3.6.1.4.1.12345.3 i 45 para alterar o valor da umidade mĂnima
para 45 (ou substitua 45 por qualquer outro valor menor que a umidade mĂĄxima)
POWER SNMP
VĂĄ para http://www.dart.com/snmp-free-manager.aspx e baixe o power snmp. Instale e execute o
Programa. Clique com o botĂŁo esquerdo do mouse em SNMP Agents e clique em Add Agent…
VĂĄ para http://www.dart.com/snmp-free-manager.aspx e baixe o power snmp. Instale e execute o
Programa. Clique com o botĂŁo direito do mouse em SNMP Agents e clique em Add Agent…
Clique em Add Agent
Digite o ip e deixe a porta como 161. Clique em OK nesta janela e na prĂłxima
DeverĂĄ aprecer o IP na lista do lado esquerdo do programa. Clique com o botĂŁo direito do mouse e escolha Add Watch...
Em variable IID digite 1.3.6.1.4.1.12345.0. Em update interval coloque o tempo de cada verificação. No exemplo eixamos para verificar de 1 em 1 segundo. Clique em Add.
O valor da umidade deverĂĄ aparecer. Agora repita o processo para as variĂĄveis 1.3.6.1.4.1.12345.1, 1.3.6.1.4.1.12345.2 e 1.3.6.1.4.1.12345.3.
Faça o download dos arquivos:
4 ComentĂĄrios
Sugestão: Usando framework ESP-IDF poderia ser melhor para gerenciamento de memoria dinùmica e prioridades entre outros serviços para alem do SMNP.
ResponderExcluirEste exemplo Ă© para versao SNMP V1, certo ?
ResponderExcluirHello, can I replace SNMP for a connection to an online database? Like Firebase?
ResponderExcluirBoa tarde!
ResponderExcluirEu estou tentado monitorar uma porta digital por snmp, se ela esta 0 ou 1 mais nĂŁo estou conseguindo, poderia me ajudar?
Estou usado um nodemcu e o zabbix para receber os dados.