Are you familiar with SNMP (Simple Network Management Protocol)? It’s used to control services and equipment on the Internet, as well as for device management in IP networks. I decided to use it in a project similar to one that I had already developed: Automatic Humidifier Control using ESP32 / 8266.
Using an ESP32 and an ESP8266, this one is connected to a humidifier unit through a relay. These ESPs communicate through the ESP-NOW protocol.
You can check the temperature and humidity of an environment, such as a CPD (for example), by monitoring the network with SNMP.
The ESP32 will read humidity, temperature, and display on an Oled display. Based on the humidity, this same microcontroller will therefore (via the ESP-NOW protocol), send a signal to an ESP8266 for on or off the relay. We will check temperature and humidity through the SNMP protocol, and then we will change maximum and minimum relay trigger humidity while also using the SNMP protocol.
Simple Network Management
Protocol (SNMP) is a protocol used in network management systems to monitor various devices.
For more information: https://www.gta.ufrj.br/grad/10_1/snmp/snmp.htm
In this project, we have two source codes. The first is ESP32, and the second is ESP8266. The second is connected to the solid state relay.
Let's include the libraries and set the pins. We start the 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 <SPIFS.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;
We continue to define parameters:
//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;
In the Setup, we initialize the serial monitor and call the function to save the strings. I checked the possibility of loading the file. Here, I also initialize the WiFi, SNMP protocol, Display, ESP-NOW, and 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
In the Loop, I call functions for sensor reading, SNMP checking, display, humidity check, and intervals.
void loop() {
readSensor(); verifySNMP(); showOnDisplay(); verifyHumidity(); delay(INTERVAL); }
SetupWiFi
First, we will disconnect to clear settings and then boot the network.
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
Here, we initialize SNMP and use PEN 12345 for testing purposes only. For a real application, the correct way would be to register the application at https://pen.iana.org/pen/PenApplication.page to avoid conflicts.
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
Here, we initialize the display and configure the source.
void setupDisplay(){
display.init(); //inicializa o display display.flipScreenVertically(); display.setFont(ArialMT_Plain_10); //configura a fonte }
SetupESPNow
We verified that the startup was successful.
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
We added the Slave here. If you want to know more details of ESP-NOW, I recommend this video: ESP32 with ESP-NOW Protocol.
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
We send the current status of the relay to the Slave.
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
This function must always be called during the main loop.
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
We check if the humidity is out of range and inform ESP8266 if the relay should be on or off.
//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
This function is responsible for reading the humidity and temperature.
//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
We work here with the display of data on the 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
In this step, we open the file to save the settings.
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
Here, we open the file for reading.
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(); }
We have included two important libraries here: ESP-NOW and ESP8266WiFi.
extern "C" {
#include } #include <ESP8266WiFi.h> #define RELAY_PIN D1
Setup
We put the pin of the relay as the output, and with a low signal. Then reset the WiFi settings and put them in AP mode. We copy the address that appears, and we put it in the slaveMacAddress of the 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
We initialize ESP-NOW and record the function that will be executed when new data arrives.
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
This function collects ESP-NOW messages and performs the action of turning the humidifier on or off.
//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
In this code, we have nothing to do in the loop since information is received by receiveCallback automatically when new data arrives.
//Nada para fazer no loop já que as informações
//são recebidas pelo receiveCallback //automaticamente quando novos dados chegam void loop() { }
Go to https://sourceforge.net/projects/net-snmp/files/net-snmp/ and install Net SNMP.
Type in the cmd or terminal:
snmpget -v 1 -c public 192.168.0.134 1.3.6.1.4.1.12345.0 to check the value of the humidity
snmpget -v 1 -c public 192.168.0.134 1.3.6.1.4.1.12345.1 to check the temperature value
snmpget -v 1 -c public 192.168.0.134 1.3.6.1.4.1.12345.2 to check the maximum humidity
snmpget -v 1 -c public 192.168.0.134 1.3.6.1.4.1.12345.3 to check the minimum humidity
snmpwalk -v 1 -c public 192.168.0.134 1.3.6.1.4.1.12345 to check all from 12345
snmpset -v 1 -c public 192.168.0.134 1.3.6.1.4.1.12345.2 i 75 to change the maximum humidity value
to 75 (or replace 75 with any value greater than the minimum humidity)
snmpset -v 1 -c public 192.168.0.134 1.3.6.1.4.1.12345.3 i 45 to change the minimum humidity value
to 45 (or replace 45 with any value less than the maximum humidity)
Go to http://www.dart.com/snmp-free-manager.aspx and download power snmp. Install and run the
Program. Left-click SNMP Agents and click Add Agent...
Go to http://www.dart.com/snmp-free-manager.aspx and download power snmp. Install and run the
Program. Right-click SNMP Agents and click Add Agent...
Click Add Agent
Enter the ip and leave the port as 161. Click OK in this window, and do the same for the next one.
You should see the IP in the list on the left side of the program. Right-click and choose Add Watch...
In variable IID enter 1.3.6.1.4.1.12345.0. In update interval, enter the time of each check. In the example, we set to check every 1 second. Click Add.
The humidity value should appear. Now repeat the process for the 1.3.6.1.4.1.12345.1, 1.3.6.1.4.1.12345.2 and 1.3.6.1.4.1.12345.3 variables.