Réception de la surveillance de relais

Suite du projet

A la suite de l'article sur la surveillance de relais avec module ESP32-LoRa, je vais détailler ici la gateway. C'est elle qui va traiter les informations reçues, les afficher et les diffuser.

Cahier des charges

Voici, en vrac, les éléments que j'ai inscrit au cahier des charges afin de guider le développement du projet :

  • Affichage en local des informations reçues.
  • Envoie d'une notification via un Bot Télégram sur un salon dédié.

Partie hardware

J'ai ici aussi retenu le choix d'utiliser une platine TTGO comprenant un ESP32 pour la partie logique, un module LoRa pour la partie réception et un écran LCD.

Et le montage final avec la mise en boitier :

Partie software

Encore une fois, je n'ai aucune connaissance en C++, mais en me documentant un peu j'ai quand même décidé de me lancer. Mon code est certainement très améliorable, je je serais ravi d'avoir des retours afin de l'améliorer.

J'ai donc développé l'ensemble du code sur Visual Studio et PlatformIO.

Voici les différentes briques de mon code. Je commence par déclarer les différentes librairies nécessaires ainsi que les variables globales :

#include <Wire.h>
#include <SSD1306Wire.h>
#include <SPI.h>
#include <LoRa.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>
#include <string>
#include "time.h"

SSD1306Wire display(0x3c, SDA, SCL); //Déclaration des pins de l'écran

const long frequency = 430600000;  //430.600MHz
#define SCK     5    // GPIO5  -- SX1278's SCK
#define MISO    19   // GPIO19 -- SX1278's MISnO
#define MOSI    27   // GPIO27 -- SX1278's MOSI
#define SS      18   // GPIO18 -- SX1278's CS
#define RST     14   // GPIO14 -- SX1278's RESET
#define DI0     26   // GPIO26 -- SX1278's IRQ(Interrupt Request)
const char* ssid = "MonSSID";  //Nom du réseau WiFi
const char* password = "MonMdP";  //mot de passe du réseau WiFi
#define BOTtoken "*********************************"  //Id-de votre bot Télégram
#define CHAT_ID "*********" //ID de votre compte ou salon pour recevoir les messages

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

const char* ntpServer = "pool.ntp.org"; //Serveur de temps pour récupérer l'heure
const long  gmtOffset_sec = 0;
const int   daylightOffset_sec = 3600;

Ensuite, je vais créer quelques fonctions que je pourrai appeler dans la suite du code. La première gère l'affichage sur le LCD en prenant en entré les différentes infos reçues :

void Affichage(String DateTimeRX, String message) {
  display.clear();
  display.setFont(ArialMT_Plain_16);
  display.drawString(0, 0, DateTimeRX); //affiche la date et l'heure de réception
  display.setFont(ArialMT_Plain_10);
  display.drawString(0, 15, message + "\n" + "RSSI : " + (String)LoRa.packetRssi());
  display.display();
}

La suivante gère l'acquisition et le formatage de la date et de l'heure :

String GetDateTimeRX(){
  char DateTimeRX[50];
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    return "Erreur get date";
  }
  strftime(DateTimeRX, 50, "%d-%m-%g | %H:%M", &timeinfo);
  return DateTimeRX;
}

Vient ensuite, la fonction d'initialisation (setup). Celle-ci s’exécute une seule fois au démarrage de l'ESP32. Les commentaires sont normalement assez explicites :

void setup() {
  Serial.begin(115200);  //initialisation de la vitesse du port série afin d'afficher des infos de débug

  //Ecran de démarrage
  Serial.println("Démarrage");
  display.init();
  display.clear();
  display.flipScreenVertically();
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.setFont(ArialMT_Plain_16);

  //Module Lora 
  SPI.begin(SCK,MISO,MOSI,SS);
  LoRa.setPins(SS,RST,DI0);
  if (!LoRa.begin(frequency)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }

  //Affichage d'un _écran de démarrage_
  display.clear();
  display.setFont(ArialMT_Plain_10);
  display.drawString(0, 20, "LoRa started");
  display.display();

  //Passage du module LoRa en réception
  LoRa.receive();

  // Connection au réseau WiFi :
  Serial.print("Connecting Wifi: ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // ajout du certificat pour api.telegram.org
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  display.setFont(ArialMT_Plain_10);
  display.drawString(0, 40, "WiFi connected");
  display.display();
  delay(2000);

  // Initialisation et obtention de la date et l'heure actuelle
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  GetDateTimeRX();

  display.clear(); //éffacement de l'écran LCD
  display.setFont(ArialMT_Plain_10);
  display.drawString(0, 20, "Surveillance relais \nAttente RX Lora");  //et affichage du texte
  display.display();
  delay(1000);
}

La fonction loop va être exécutée en boucle, c'est donc ici que va se trouver le "cœur" de la supervision.

void loop() {
  Serial.begin(115200);
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    while (LoRa.available()) {
      String DateTimeRX = GetDateTimeRX(); //On récure l'heure actuelle qui est l'heure de réception de la trame

      String message = LoRa.readString();  //on stocke le message reçu
      Affichage(DateTimeRX, message); //on affiche les info sur l'écran
      Serial.println(DateTimeRX); //et dans la console
      Serial.println(message);
      Serial.println("RSSI : " + (String)LoRa.packetRssi() + "\n"); //avec le niveau de reception
      bot.sendMessage(CHAT_ID, message + "\n\nRSSI : " + (String)LoRa.packetRssi() + "dBm"); //on envoi le tout via télégram
    }
  }
}

Mise en place sur site

à venir après la mise en coffret

Article suivant