Menu


Stacks Image 9724
Tuto spécial maker, nous allons réaliser une sonde température avec un microcontrôleur ESP 8266 nodeMCU et une sonde AM2302. Cette sonde se connectera au réseau Wifi. Elle sera interrogeable par un mini-serveur web ou par une requête SNMP. Cette dernière nous permettra de configurer notre serveur de supervision préféré Centreon. Ce tutoriel s'enrichira au fur et à mesure de mes travaux sur ce sujet.

1 Préparation d'Arduino IDE pour l'ESP 8266

Nous devons préparer le logiciel Arduino IDE pour programmer notre ESP 8266. Tout d'abord, installons la bibliothèque pour l'ESP. Sélectionnez Fichier -> Préférences :
Stacks Image 37220
Saisissez la ligne suivante :
http://arduino.esp8266.com/stable/package_esp8266com_index.json
Ensuite, sélectionnez Outils -> Type de Carte… -> Gestionnaire de carte. Dans le filtre de recherche, saisissez esp
Stacks Image 37368
Cliquez sur Installer. Ensuite, il faut installer la librairie pour la sonde de température. Dans le filtre de recherche, saisissez dht.
Stacks Image 37371
Installer les librairies DHT sensor Library et DHT sensor library for ESPx. Les librairies sont installées, vérifiez la connectivité de votre ESP. Assurez-vous d'avoir le bon câble pour envoyer et recevoir les données. De nombreux câbles d'alimentation de portables, par exemple, n'ont pas les liaisons de données. Lorsque vous branchez l'ESP, vous devriez avoir une nouvelle connexion USB dans le menu Outils -> Port comme la copie d'écran ci-contre.
Stacks Image 37374
Avec une machine sous Linux, nous aurons la connexion /dev/ttyUSB0. Nous finirons par la bibliothèque SNMP, il faut télécharger le fichier ZIP sur le GitHub https://github.com/0neblock/Arduino_SNMP. Il en existe bien d'autres, regardez le chapitre Mes sources. Une fois le fichier téléchargé, sélectionnez le menu Croquis -> Inclure une bibliothèque -> Ajouter la bibliothèque ZIP... Sélectionnez le fichier téléchargé Arduino_SNMP-master.zip et validez pour l'inclure pour vos projets.

1.1 Modification pour Linux

Si vous avez la chance de travailler sous Linux, il faut modifier le fichier Arduino_SNMP.h. En effet, Linux comme tout système Unix like est sensible à la casse des caractères. Il faut modifier la ligne suivante :
#include <UDP.h>
par
#include <Udp.h>
Stacks Image 37381

2 Montage de la sonde de température

La sonde AM2302 est très facile à installer. Aucune résistance est requise, il se branche directement sur l'ESP. La sonde fonctionne en 5 Volts, nous utiliserons pour l'instant l'alimentation du connecteur USB de l'ESP. Le fil de données sera connecté au port D4.
Stacks Image 37390
Stacks Image 37393

3 Programmation de l'ESP

3.1 Fonctionnement de la sonde de température

Premier programme très simple permettant de vérifier le fonctionnement de la sonde de température avec le moniteur série.
#include "DHT.h"

#define DHTPIN 2 // Digital pin connected to the DHT sensor

#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321

// Initialize DHT sensor.
DHT dht(DHTPIN, DHTTYPE);

float Temperature;
float Humidity;

void setup() {
  Serial.begin(115200);
  delay (100);
  
  pinMode(DHTPIN, INPUT);
  dht.begin();    
   
}

void loop() {
  server.handleClient();
  // Wait a few seconds between measurements.
  delay(2000);
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F(" C "));
  Serial.print(f);
  Serial.print(F(" F  Heat index: "));
  Serial.print(hic);
  Serial.print(F(" C "));
  Serial.print(hif);
  Serial.println(F(" F"));
}

void handle_OnConnect() {
  Temperature = dht.readTemperature(); // Gets the values of the temperature
  Humidity = dht.readHumidity(); // Gets the values of the humidity 
  server.send(200, "text/html", SendHTML(Temperature,Humidity)); 
}
Stacks Image 37437
Attention lors des chargements de code, j'ai remarqué que la sonde de température ne fonctionnait qu'après un redémarrage électrique du montage.

3.2 Création d'un mini-serveur Web

Avec ce code, nous allons ajouter un mini-serveur Web qui nous affichera l'hygrométrie et la température de la sonde AM2302.
#include "DHT.h"
#include 
#include 

#define DHTPIN 2 // Digital pin connected to the DHT sensor
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321

// Initialize DHT sensor.
DHT dht(DHTPIN, DHTTYPE);

/*Put your SSID & Password*/
const char* ssid = "ssid wifi";  // Enter SSID here
const char* password = "mdp wifi";  //Enter Password here

ESP8266WebServer server(80);

float Temperature;
float Humidity;


void setup() {
  Serial.begin(115200);
  delay (100);
  
  pinMode(DHTPIN, INPUT);
  dht.begin();

  Serial.println("Connecting to ");
  Serial.println(ssid);

  //connect to your local wi-fi network
  WiFi.begin(ssid, password);

  //check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected..!");
  Serial.print("Got IP: ");  Serial.println(WiFi.localIP());

  server.on("/", handle_OnConnect);
  server.onNotFound(handle_NotFound);

  server.begin();
  Serial.println("HTTP server started");
    
   
}

void loop() {
  
  server.handleClient();

  // Wait a few seconds between measurements.
  delay(2000);
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F(" C "));
  Serial.print(f);
  Serial.print(F(" F  Heat index: "));
  Serial.print(hic);
  Serial.print(F(" C "));
  Serial.print(hif);
  Serial.println(F(" F"));
}

void handle_OnConnect() {
  Temperature = dht.readTemperature(); // Gets the values of the temperature
  Humidity = dht.readHumidity(); // Gets the values of the humidity 
  server.send(200, "text/html", SendHTML(Temperature,Humidity)); 
}

void handle_NotFound(){
  server.send(404, "text/plain", "Not found");
}

String SendHTML(float Temperaturestat,float Humiditystat){
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr +="<title>ESP8266 Weather Report</title>\n";
  ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";
  ptr +="p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n";
  ptr +="</style>\n";
  ptr +="</head>\n";
  ptr +="<body>\n";
  ptr +="<div id=\"webpage\">\n";
  ptr +="<h1>ESP8266 NodeMCU Weather Report</h1>\n";
  
  ptr +="<p>Température: ";
  ptr +=Temperaturestat;
  ptr +=" ºC</p>";
  ptr +="<p>Hygrométrie: ";
  ptr +=Humiditystat;
  ptr +=" %</p>";
  
  ptr +="</div>\n";
  ptr +="</body>\n";
  ptr +="</html>\n";
  return ptr;
}
L'affichage de la sonde via un navigateur
Stacks Image 37442

3.3 Utilisation du SNMP

Troisième modification du code, l'ajout de la fonctionnalité SNMP, très basique. Il y a seulement trois OID pour l'hygrométrie, la température en degré Celsius et Fahrenheit.
#include "DHT.h"
#include 
#include 
#include 
#include 

#define DHTPIN 2 // Digital pin connected to the DHT sensor

#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321

// Initialize DHT sensor.
DHT dht(DHTPIN, DHTTYPE);

/*Put your SSID & Password*/
const char* ssid = "Livebox-FA0A";  // Enter SSID here
const char* password = "DuGeerbq2yNGLHFNGs";  //Enter Password here

ESP8266WebServer server(80);

WiFiUDP udp;
SNMPAgent snmp = SNMPAgent("public");  // Starts an SMMPAgent instance with the community string 'public'

int TempSNMPC = 0;
int TempSNMPF = 0;
int TempHumidity = 0;
int settableNumber = 0;

float Temperature;
float Humidity;


void setup() {
  Serial.begin(115200);
  delay (100);

  pinMode(DHTPIN, INPUT);
  dht.begin();

  Serial.println("Connecting to ");
  Serial.println(ssid);

  //connect to your local wi-fi network
  WiFi.begin(ssid, password);

  //check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected..!");
  Serial.print("Got IP: ");  Serial.println(WiFi.localIP());

  server.on("/", handle_OnConnect);
  server.onNotFound(handle_NotFound);

  server.begin();
  Serial.println("HTTP server started");

      // give snmp a pointer to the UDP object
    snmp.setUDP(&udp);
    snmp.begin();
    
    // add 'callback' for an OID - Temperature Celsius
    snmp.addIntegerHandler(".1.3.6.1.3.2106.5.1.0", &TempSNMPC);

   // add 'callback' for an OID - Temperature Farenheit
    snmp.addIntegerHandler(".1.3.6.1.3.2106.5.1.1", &TempSNMPF);
 
    // add 'callback' for an OID - Humidity
    snmp.addIntegerHandler(".1.3.6.1.3.2106.5.1.2", &TempHumidity);

    
    // you can accept SET commands with a pointer to an integer (or string)
    snmp.addIntegerHandler(".1.3.6.1.3.2106.5.1.3", &settableNumber, true);
    
   
}

void loop() {
      snmp.loop(); // must be called as often as possible
    if(snmp.setOccurred){
        Serial.printf("Number has been set to value: %i", settableNumber);
        snmp.resetSetOccurred();
    }
  
  server.handleClient();

  // Wait a few seconds between measurements.
  delay(2000);
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);
  TempSNMPC = int(t * 100) ;
  TempSNMPF = int(f * 100) ;
  TempHumidity = int(h * 100) ;

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F(" C "));
  Serial.print(f);
  Serial.print(F(" F  Heat index: "));
  Serial.print(hic);
  Serial.print(F(" C "));
  Serial.print(hif);
  Serial.println(F(" F"));
}

void handle_OnConnect() {
  Temperature = dht.readTemperature(); // Gets the values of the temperature
  Humidity = dht.readHumidity(); // Gets the values of the humidity 
  server.send(200, "text/html", SendHTML(Temperature,Humidity)); 
}

void handle_NotFound(){
  server.send(404, "text/plain", "Not found");
}

String SendHTML(float Temperaturestat,float Humiditystat){
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr +="<title>ESP8266 Weather Report</title>\n";
  ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";
  ptr +="p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n";
  ptr +="</style>\n";
  ptr +="</head>\n";
  ptr +="<body>\n";
  ptr +="<div id=\"webpage\">\n";
  ptr +="<h1>ESP8266 NodeMCU Weather Report</h1>\n";
  
  ptr +="<p>Température: ";
  ptr +=Temperaturestat;
  ptr +=" ºC</p>";
  ptr +="<p>Hygrométrie: ";
  ptr +=Humiditystat;
  ptr +=" %</p>";
  
  ptr +="</div>\n";
  ptr +="</body>\n";
  ptr +="</html>\n";
  return ptr;
}
Nous pouvons récupérer les informations SNMP comme ceci :
température en Celsius
[root@centreon2004pp ~]# snmpwalk -c public -v1 192.168.1.16 .1.3.6.1.3.2106.5.1.0
SNMPv2-SMI::experimental.2106.5.1.0 = INTEGER: 2360

température en Fahrenheit
[root@centreon2004pp ~]# snmpwalk -c public -v1 192.168.1.16 .1.3.6.1.3.2106.5.1.1
SNMPv2-SMI::experimental.2106.5.1.1 = INTEGER: 7448

hygrométrie
[root@centreon2004pp ~]# snmpwalk -c public -v1 192.168.1.16 .1.3.6.1.3.2106.5.1.2
SNMPv2-SMI::experimental.2106.5.1.2 = INTEGER: 6270
Comme vous le constatez les valeurs sont des integer, il faudra diviser par 100 pour avoir les bonnes valeurs. Heureusement, le plugin Centreon a prévu ce cas.

4 Intégration dans Centreon

Nous utiliserons la version open-source sans plugin-pack. Pour plus d'explication de la sonde Centreon, voir l'article lm-sensors.

4.1 Création de la commande

La commande utilisera le plugin centreon_generic_snmp.pl
Stacks Image 37298
La commande est la suivante
$CENTREONPLUGINS$/centreon_generic_snmp.pl  --plugin=apps::protocols::snmp::plugin --mode=numeric-value --hostname=$HOSTADDRESS$ --snmp-community='$_HOSTSNMPCOMMUNITY$' --snmp-version=$_HOSTSNMPVERSION$ --oid='$_SERVICEOID$' --format-custom='$_SERVICEFORMATCUSTOM$' --format='$_SERVICEFORMAT$' --perfdata-name='$_SERVICEPRFDATANAME$' --warning=$_SERVICEWARNING$ --critical=$_SERVICECRITICAL$ $_SERVICEOPTIONS$

4.2 Création du template de service

La création du template de service stpl-sonde-esp8266-temp-hygro ne présente aucune difficulté.
Stacks Image 37303
Nous rajouterons dans la macro OPTIONS, cette chaîne de caractères permettant de récupérer les valeurs hygrométriques et de température en degré celsius.
--config-json='[ { "oid": "1.3.6.1.3.2106.5.1.0","perfdata_name": "temp", "format": "temperature sonde : %s","format_custom": "/ 100","warning": "30","critical": "35"},{ "oid": "1.3.6.1.3.2106.5.1.2", "perfdata_name": "hygro","format": "hygrometrie sonde : %s","format_custom": "/ 100","warning": "65","critical": "70"} ]'

4.3 Création du Template d'hôte

Création du template d'hôte htpl-sonde_esp8266, nous associerons le template de service stpl-sonde-esp8266-temp-hygro
Stacks Image 37414
La relation
Stacks Image 37419

4.4 Création du service

Nous avons besoin de l'adresse IP de notre sonde ESP 8266. Appliquons le modèle précédent htpl-sonde_esp8266. Les services seront automatiquement créés.
Stacks Image 37308
Appliquez la configuration.

4.5 Vérification de la supervision.

Voici le résultat de la vérification par les sondes Centreon au bout de quelques minutes.
Stacks Image 37424
Et le graphe correspondant à la sonde de température.
Stacks Image 37313

5 Mes sources

Cet article n'est terminé, il va s'enrichir au fur et à mesure de mes travaux. bonne lecture.
comments powered by Disqus