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.