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.
Voici, en vrac, les éléments que j'ai inscrit au cahier des charges afin de guider le développement du projet :
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 :
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
}
}
}
à venir après la mise en coffret