ESP32 Lora : use interruption process or not ?

Hello.
I have developped a project using ESP32 boards sending and receiving LORA frames.
Right now, I' using the "standard" library with Lora.h, where the check to "see" if a trame is received or not is in the loop procedure. Like that
void loop() { onReceive(LoRa.parsePacket());

I have seen that with another libray (loraLib) it is possible to code the check as an interruption.

My question is : >>> Is there any interest in configuring the check through the interruption process ? (instead of checking in the loop()) ?

See below the LoRaLib/examples/ReceiveInterrupt//ReceiveInterrupt.ino

ReceiveInterrupt.ino

/*
   LoRaLib Receive with Interrupts Example

   This example listens for LoRa transmissions and tries to
   receive them. Once a packet is received, an interrupt is
   triggered. To successfully receive data, the following
   settings have to be the same on both transmitter
   and receiver:
    - carrier frequency
    - bandwidth
    - spreading factor
    - coding rate
    - sync word
    - preamble length

   For more detailed information, see the LoRaLib Wiki
   https://github.com/jgromes/LoRaLib/wiki

   For full API reference, see the GitHub Pages
   https://jgromes.github.io/LoRaLib/
*/

// include the library
#include <LoRaLib.h>

// create instance of LoRa class using SX1278 module
// this pinout corresponds to RadioShield
// https://github.com/jgromes/RadioShield
// NSS pin:   10 (4 on ESP32/ESP8266 boards)
// DIO0 pin:  2
// DIO1 pin:  3
// IMPORTANT: because this example uses external interrupts,
//            DIO0 MUST be connected to Arduino pin 2 or 3.
//            DIO1 MAY be connected to any free pin
//            or left floating.
SX1278 lora = new LoRa;

void setup() {
  Serial.begin(9600);

  // initialize SX1278 with default settings
  Serial.print(F("Initializing ... "));
  // carrier frequency:           434.0 MHz
  // bandwidth:                   125.0 kHz
  // spreading factor:            9
  // coding rate:                 7
  // sync word:                   0x12
  // output power:                17 dBm
  // current limit:               100 mA
  // preamble length:             8 symbols
  // amplifier gain:              0 (automatic gain control)
  int state = lora.begin();
  if (state == ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }

  // set the function that will be called
  // when new packet is received
  lora.setDio0Action(setFlag);

  // start listening for LoRa packets
  // NOTE: for spreading factor 6, the packet length
  //       must be known in advance, and provided to both
  //       startReceive() and readData() methods!
  Serial.print(F("Starting to listen ... "));
  state = lora.startReceive();
  if (state == ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }

  // NOTE: 'listen' mode will be disabled
  // automatically by calling any of the
  // following methods:
  //
  // lora.standby()
  // lora.sleep()
  // lora.transmit()
  // lora.receive()
  // lora.scanChannel()
  //
  // LoRa module will not receive any new
  // packets until 'listen' mode is re-enabled
  // by calling lora.startReceive()
}

// flag to indicate that a packet was received
volatile bool receivedFlag = false;

// disable interrupt when it's not needed
volatile bool enableInterrupt = true;

// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
//            and MUST NOT have any arguments!
void setFlag(void) {
  // check if the interrupt is enabled
  if(!enableInterrupt) {
    return;
  }

  // we got a packet, set the flag
  receivedFlag = true;
}

void loop() {
  // check if the flag is set
  if(receivedFlag) {
    // disable the interrupt service routine while
    // processing the data
    enableInterrupt = false;

    // reset flag
    receivedFlag = false;

    // you can read received data as an Arduino String
    String str;
    int state = lora.readData(str);

    // you can also read received data as byte array
    /*
      byte byteArr[8];
      int state = lora.readData(byteArr, 8);
    */

    if (state == ERR_NONE) {
      // packet was successfully received
      Serial.println(F("Received packet!"));

      // print data of the packet
      Serial.print(F("Data:\t\t\t"));
      Serial.println(str);

      // print RSSI (Received Signal Strength Indicator)
      Serial.print(F("RSSI:\t\t\t"));
      Serial.print(lora.getRSSI());
      Serial.println(F(" dBm"));

      // print SNR (Signal-to-Noise Ratio)
      Serial.print(F("SNR:\t\t\t"));
      Serial.print(lora.getSNR());
      Serial.println(F(" dB"));

      // print frequency error
      Serial.print(F("Frequency error:\t"));
      Serial.print(lora.getFrequencyError());
      Serial.println(F(" Hz"));

    } else if (state == ERR_CRC_MISMATCH) {
      // packet was received, but is malformed
      Serial.println(F("CRC error!"));

    }

    // we're ready to receive more packets,
    // enable interrupt service routine
    enableInterrupt = true;
  }

}

Regards.
CH

I moved your topic to a more appropriate forum category @hanotte78.

The Nano Family > Nano ESP32 category you chose is only used for discussions directly related to the Arduino Nano ESP32 board.

In the future, when creating a topic please take the time to pick the forum category that best suits the subject of your question. There is an "About the _____ category" topic at the top of each category that explains its purpose.

This is the third time I've requested this of you. Since you aren't responding to polite requests, I have been forced to resort to a temporary account suspension to get your attention. Upon your return to our forum, I hope you will act in a more responsible manner. If not, a permanent account suspension will follow.

Thanks in advance for your cooperation.

you can use the lora.h callbacks which setup interrupt routines
remember keep the interrupt routines as short as possible, i.e. no calls to serial IO or TFT displays, etc
pass data to loop() etc using volatile variables

also have a look at SX12XX-LoRa library which supports the SX1262 module

Most all LoRa libraries can be setup so as there is an interrupt on a packet received or transmission complete, not heard of one where you cannot.

The SPI based LoRa modules have a IO pin that can be set to go high on packet receive etc. Connect that pin to a micro controller GPIO pin and you can have an interrupt, or just read the GPIO pin in loop.

You can in loop() is check for a flag that has been set in an interrupt ISR by the LoRa device, but then its more direct to just read the GPIO pin logic level in loop().

Hi. Many thans for your update but... I'm still wondering if it is better to use the interrupt process instead of checking a value in the loop().

On an operational point of view, is it better ?
Example : in the loop, I have written onReceive(LoRa.parsePacket());, but I also do many other actions [please read my script below]. Is there a risk that, when doing other actions, I may loose a LORA Signal (as my processor is used to do something else at this moment) ? If yes (I may loose a signal), such a risk could be avoided when using the interruption process ?

// Energie Mairie - Gway ALL - 20241230.02 - tracking des relais.txt
/*
  Projet = ENERGIE MAIRIE
  file = Energie Mairie - Gway LORA - ESP32 - 20240xxx---

  Sketch pour Gway / LORA & OLED / Gateway centrale
  P2P Lora - scenario Gway / Emission & reception
*/
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!!!!!!!!!!!! DEBUT CONFIGURATION DE LA SOLUTION
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

// Qd ajout de capteur : chercher // ---- AJOUT de sonde

// 1) definir la Gway
#define GATEWAY_FE
// #define GATEWAY_FD

// 2) - type de carte
// #define ESP32_TTGO
#define ESP32 -LILYGOT31_6_1

// 3) DEBUG
//#define DEBUG_SERIAL
//#define DEBUG_OLED
#define OLED_LITE

// 4) - outil de compimation
// #define COMPILATION_CLOUD_IoT
#define COMPILATION_CLOUD_IDE
// #define COMPILATION_IDE

// 5)
#define BANDWITH433
// #define BANDWITH868

// ************* Donnees arduino
// 6) - Données Lora
const byte Header1 = 0x06;  // pour reconnaire la trame Mairie
const byte Header2 = 0x07;  // pour reconnaire la trame Mairie
const byte Adresse_Broadcast = 0xFF;
const byte Version_du_protocole_lora = 0x01;  // version envoyée ds la trame Lora - prevu pour evolutions futures

const byte Message_de_donnee = 0x01;
const byte Message_de_keepalive = 0x02;

// 5) Connection Cloud ou non & Wifi
// #define DEVELOPPEMENT_NO_CLOUD_CONNEXION
#ifndef COMPILATION_CLOUD_IoT  //   // On exclut cette ligne en Cloud IoT car c'est déja inclu avec le Wifi etc...
#define WIFI_SSID "freecd9b4box8"
#define WIFI_PASSWORD "7869078690786"
#define SECRET_SSID WIFI_SSID
#define SECRET_OPTIONAL_PASS WIFI_PASSWORD
#endif

#ifdef GATEWAY_FE

int const Nbre_de_capteurs_configures = 8;  // sur cette Gway - pour contrôle des adresses recues // ---- AJOUT de capteur
int const ID_premier_capteurs_configure = 1;
#define SECRET_DEVICE_KEY "Uxe3l5kmFfx3VM?daa5EBiYGv"               // Ruches Connectees
const byte Adresse_Device = 0xFE;                                   // address of this device / CH = that is the Gateway - uniquement en reception
#if defined COMPILATION_CLOUD_IoT || defined COMPILATION_CLOUD_IDE  // Pour differencier complilation IDE & CLOUD
#include "thingProperties-Ruches-Connectees-GwayFE.h"
#endif
#endif

#ifdef GATEWAY_FD
int const Nbre_de_capteurs_configures = xxxx;  // sur cette Gway - pour contrôle des adresses recues
int const ID_premier_capteurs_configure = xxxx;
const byte Adresse_Device = 0xFD;  // address of this device / CH = that is the Gateway - uniquement en reception
#define SECRET_DEVICE_KEY "bJRc!2S#vVjap01YLGcRr#5H@"
#if defined COMPILATION_CLOUD_IoT || defined COMPILATION_CLOUD_IDE  // Pour differencier complilation IDE & CLOUD
#include "thingProperties-Energie-GwayFD.h"
#endif
#endif

float *Gway_donnee1OUT = &Gdonnee1OUT;
float *Gway_donnee2OUT = &Gdonnee2OUT;
float *Gway_donnee3OUT = &Gdonnee3OUT;  // 29/12/2024
bool *Gway_donnee4OUT = &Gdonnee4OUT;   // 29/12/2024
int *Gway_capteurIDOUT = &GcapteurIDOUT;
bool *Gway_donneeMAJOUT = &GdonneeMAJOUT;
String *PORTAIL_gateway_texte = &GTEXTE;

// 7) - Autres mesures
const int Duree_pour_MAJ_status_Gway_mn = 15;

// 8) - Données du PORTAIL non configurées - pour test avant déploiement IoT Mairie - DEBUT
#if not defined COMPILATION_CLOUD_IoT && not defined COMPILATION_CLOUD_IDE
float Gdonnee1OUT;
float Gdonnee2OUT;
float Gdonnee3OUT;  // 29/12/2024
bool Gdonnee4OUT;   // 29/12/2024
int GcapteurIDOUT;
bool GdonneeMAJOUT;
String Gtexte;
bool GSTATDEV;
#endif

//*** CONTEXT/CONSTANTES * TO BE UPDATED/FIN **********************************************************
//*******************************************************************************************************

#ifndef COMPILATION_CLOUD_IoT  //   // On exclut cette ligne en Cloud IoT car c'est déja inclu avec le Wifi etc...
#include <WiFi.h>
#endif

#include <SPI.h>  // include libraries
#include <LoRa.h>

//Libraries for OLED Display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#ifdef BANDWITH433
#define BAND 433E6
#endif
#ifdef BANDWITH868
#define BAND 868E6
#endif

// version TTGO ESP32
// ****************************************************************************************
#ifdef ESP32_TTGO
//define the pins used by the LoRa transceiver module
#define SCK 5
#define MISO 19
#define MOSI 27
#define SS 18
#define RST 14  // Changed CH - OLD = 16; NEW = 14
#define DIO0 26
#define DIO1 33
#define DIO2 32
//OLED pins
#define OLED_SDA 4
#define OLED_SCL 15
#define OLED_RST 16
#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels
#endif

// version 2 ESP32 LillyGo [from Bidouilleurs https://www.youtube.com/watch?v=o8Pd-hZDYwc]
// ****************************************************************************************
#ifdef ESP32 - LILYGOT31_6_1
//define the pins used by the LoRa transceiver module
#define SCK 5
#define MISO 19
#define MOSI 27
#define SS 18
#define RST 23  // OLD = 16
#define DIO0 26
//OLED pins LiLYGo / T3 version 1.6.1
#define OLED_SDA 21
#define OLED_SCL 22
#define OLED_RST 2        // n'est peut être pas le 2 mais e, tout cas, pas le 16
#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels
#endif

// Initialisation ecran OLED
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RST);

// constante OLED
const int debut_ligne_status = 0;
const int debut_ligne_received = 9;
const int debut_ligne_sent = 36;
const int increment_ligne = 9;
const int Clear_ecran_OLED = 1;      //25/11/2024
const int Pas_clear_ecran_OLED = 0;  //25/11/2024
const int Clear_ligne_OLED = 1;      //25/11/2024
const int Pas_clear_ligne_OLED = 0;  //25/11/2024
const int Couleur_OLED_blanc = 1;    //25/11/2024
String *PORTAIL_gateway_text;


// enregistrement des numeros de essage reçus pour éviter le traitement en double de messages relayés par les relais
const int taille_tab_messages_recus = 6;                               // taille de la table de suivi de smessages reçus pour éviter les doublons
int index_courant_tab_messages_recus = 0;                              // index de remplissage du suivi de smessages reçus pour éviter les doublons
int tab_messages_recus[taille_tab_messages_recus];                     // table qui garde les numéros des msg reçus pour éviter doublon
unsigned long tab_messages_recus_tempo_t0[taille_tab_messages_recus];  // table qui garde le moment "CurrentTime" où le message a été reçu
const float messages_recus_tempo_duree = 60 * 1000;                    // durée durant laquelle on garde les messages pour éviter les répets - en milisecondes

// Autres variables
unsigned long currentTime = 0;
const int MaxCurrentTime_Jour = 50;
unsigned long status_Gway_alive_tempo_t0;
unsigned long status_Gway_alive_tempo_duree = Duree_pour_MAJ_status_Gway_mn * 60 * 1000;
int nombre_de_fois_current_time_reached = 0;
int currentTimeJour = 0;
int currentTimeJourCumule = 0;
int currentTimeHeure = 0;
int currentTimeMinute = 0;
unsigned long keepalive_tempo_t0;
const int Duree_entre_keepalive_gateway_mn = 30;
const unsigned long keepalive_tempo_duree = Duree_entre_keepalive_gateway_mn * 60 * 1000;
unsigned long clean_portail_msg_text_t0 = 0;
unsigned long clean_portail_msg_text_duree = 3 * 24 * 60 * 60 * 1000;  // changé valeur : passé à 48
unsigned long impression_variable_delais = 60 * 60 * 1000;             // 08/01/2025
unsigned long impression_variable_t0 = 0;                              // 02/01/2025

#if defined DEBUG_OLED || defined OLED_LITE // 03/04/2025
// clignotement surt ecran //Ajputé 30/10/2024
unsigned long clignotement_OLED_t0 = 0;
unsigned long clignotement_OLED_duree = 3000; // 03/04/2025
int clignotement_OLED_horizontal = 120;
int clignotement_OLED_vertical = 60;
int clignotement_OLED_taille = 2;
#endif

// Structure relais - 27/11/2024
const int Nbre_de_relais = 3;
struct __attribute__((packed)) suivi_relais {
  byte adresse_du_relais;
  bool status_relais_Up;
  bool *LED_status_relais_Up;  // info fournie par paquest de mesures recus & keepalive du relais
  bool donnee_de_travail_relais_Up;
  bool status_relais_used;
  bool *LED_relais_used;  // info fournie par paquest de mesures recus
  bool donnee_de_travail_relais_used;
};
suivi_relais tableau_de_suivi_des_relais[Nbre_de_relais] = {  // 27/11/2024
  { 0xA0, false, &r01STATDEV, false, false, &r01USED, false },
  { 0xA1, false, &r02STATDEV, false, false, &r02USED, false },
  { 0xA2, false, &r03STATDEV, false, false, &r03USED, false }
};
unsigned long suivi_MAJ_relais_t0 = 0;
unsigned long suivi_MAJ_relais_duree_mn = 60 * 24 * 3;
unsigned long suivi_MAJ_relais_duree = suivi_MAJ_relais_duree_mn * 60 * 1000;
unsigned long clignotement_LED_relais_t0 = 0;
unsigned long clignotement_LED_relais_duree = 1 * 1000;
const int Check_if_relais_used = 1;  // 27/11/2024
const int Check_if_relais_Up = 2;    // 29/12/2024

String message_du_portail;
int numero_device = 0;
bool message_valable = false;
int index_numero_device = 0;
int message_status = 0;
int message_ERR = 0;
int n = 0;
bool bool_donnee_de_travail;

int suivi_automate = 0;
int phase_de_setup = 1;
const int debut_numero_du_message = 254;  // pour les msg envoyés par la gateway

// LORA - Donnees pour traitement des infos reçues
byte header1_du_message;
byte header2_du_message;
byte version_du_message;
byte emetteur_du_message;
byte destinataire_du_message;
byte relais1_du_message;
byte relais2_du_message;
byte relais3_du_message;
int numero_du_message = 0;
byte type_du_message;
float donnee1_du_message;
const float Donnee1_MAX = 100000;  //14/03/2025
const float Donnee1_MIN = 0;       //14/03/2025
const float Donnee2_MAX = 0;       //14/03/2025
const float Donnee2_MIN = 0;       //14/03/2025
float donnee2_du_message;
float donnee3_du_message;
boolean donnee4_du_message;
float checksum_du_message;
char text_du_message[30];
int taille_du_message;

// Structure Lora
struct __attribute__((packed)) MessageLora {
  byte header1;  // pour reconnaitre trame ruche
  byte header2;  // pour reconnaitre trame ruche
  byte version;  // pour évolutions future
  byte emetteur;
  byte destinataire;
  byte relais1;
  byte relais2;
  byte relais3;
  int32_t numero_du_message;
  byte type_du_message;
  float donnee1;    // poids de la ruche
  float donnee2;    // pour évolution future
  float donnee3;    // pour évolution future
  boolean donnee4;  // pour évolution future
  float checksum;   // pour évolution future
  char text[30];
};
MessageLora messageLora;
MessageLora messageLoraINIT;  //03/04/2025

// Msg d'erreur
char *tab_message_ERR[10] = { "", "1)hd/ver KO", "2)emet. KO", "3)dest. KO", "4)broad.", "5)type KO", "6)d1/d2 KO", "7)check KO", "8)Dup. msg", "" };

void setup()
// ****************************************************************************************
{
  // Initialize serial and wait for port to open:
#ifdef DEBUG_SERIAL
  Serial.begin(115200);
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  delay(10000);
  Serial.println("Entree / setup...");
#endif

#if defined COMPILATION_CLOUD_IoT || defined COMPILATION_CLOUD_IDE  // Pour differencier complilation IDE & CLOUD
  initProperties();
  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);

  // Mise en commentaire pour compilation IDE
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
#endif

#ifdef DEBUG_SERIAL
  Serial.println("Arduino initialisé");
#endif

#if defined DEBUG_OLED || defined OLED_LITE // 03/04/2025
  //reset OLED display via software
  pinMode(OLED_RST, OUTPUT);
  digitalWrite(OLED_RST, 0);
  delay(20);
  digitalWrite(OLED_RST, HIGH);

  //initialize OLED
  Wire.begin(OLED_SDA, OLED_SCL);
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3c, false, false)) {  // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;  // Don't proceed, loop forever
  }
  Serial.println("OLED ready");
#endif

  // override the default CS, reset, and  IRQ pins (optional)
  //SPI LoRa pins
  SPI.begin(SCK, MISO, MOSI, SS);
  //setup LoRa transceiver module
  LoRa.setPins(SS, RST, DIO0);

  if (!LoRa.begin(BAND)) {  // initialize ratio for Europe
#if defined DEBUG_OLED || defined OLED_LITE // 03/04/2025
    displayOLED(Clear_ecran_OLED, Pas_clear_ligne_OLED, 0, debut_ligne_status, 1, "LoRa init failed. Check your connections", 1);
#endif
    while (true)
      ;  // if failed, do nothing
  }

#if defined DEBUG_OLED || defined OLED_LITE // 03/04/2025
  displayOLED(Clear_ecran_OLED, Pas_clear_ligne_OLED, 0, debut_ligne_status, 1, "LoRa OK - Gway", 1);
#endif
#ifdef DEBUG_SERIAL
  Serial.println("LoRa init succeeded");
#endif

  LoRa.setSpreadingFactor(12);
  LoRa.setSignalBandwidth(62.5E3);
  LoRa.setCodingRate4(5);  //min 5- max 8
  currentTime = millis();
  // MAJ_des_donnees_ms_t0 = currentTime;
  *Gway_donneeMAJOUT = false;
  *Gway_donnee1OUT = 0;
  *Gway_donnee2OUT = 0;
  *Gway_donnee3OUT = 0;      // 29/12/2024
  *Gway_donnee4OUT = false;  // 29/12/2024
  *Gway_capteurIDOUT = 0;
  Serial.print("Gateway demarree - ");
  Serial.println("GATEWAY_" + String(Adresse_Device) + " - ");

  Serial.println("Données après initiaisation - ");
  Serial.print("GFxdonneeMAJOUT = " + String(*Gway_donneeMAJOUT) + " /");
  Serial.print("GFxcapteurIDOUT = " + String(*Gway_capteurIDOUT) + " /");
  Serial.print("GFxdonnee1OUT = " + String(*Gway_donnee1OUT) + " /");
  Serial.println("GFxdonnee2OUT = " + String(*Gway_donnee2OUT));
  Serial.print("GFxdonnee3OUT = " + String(*Gway_donnee3OUT) + " /");  // 29/12/2024
  Serial.println("GFxdonnee4OUT = " + String(*Gway_donnee4OUT));       // 29/12/2024

  keepalive_tempo_t0 = currentTime;
  status_Gway_alive_tempo_t0 = currentTime;
  clean_portail_msg_text_t0 = currentTime;
  suivi_MAJ_relais_t0 = currentTime;         // 26/11/2024
  clignotement_LED_relais_t0 = currentTime;  // 27/11/2024
  impression_variable_t0 = currentTime;      // 02/01/2025

  init_structure_lora();  // 03/04/2025

  for (n = 0; n < taille_tab_messages_recus; n++)  // 27/11/2024
  {
    tab_messages_recus[n] = 0;  //27/11/2024
    tab_messages_recus_tempo_t0[n] = 0;
  }

  for (n = 0; n < Nbre_de_relais; n++)  // 26/12/2024
  {
    tableau_de_suivi_des_relais[n].status_relais_Up = false;
    *tableau_de_suivi_des_relais[n].LED_status_relais_Up = false;
    tableau_de_suivi_des_relais[n].donnee_de_travail_relais_Up = false;
    tableau_de_suivi_des_relais[n].status_relais_used = false;
    *tableau_de_suivi_des_relais[n].LED_relais_used = false;  // info fournie par paquest de mesures recus
    tableau_de_suivi_des_relais[n].donnee_de_travail_relais_used = false;
  }

#if defined DEBUG_OLED || defined OLED_LITE // 03/04/2025
  clignotement_OLED_t0 = currentTime;  //30/10/2024
#endif

  // Traitement des données de l'application ruche
  index_courant_tab_messages_recus = 0;

#ifdef DEBUG_SERIAL
  Serial.println("Sortie / setup");
  Serial.print("Arduino Stack was set to bytes " + String(getArduinoLoopTaskStackSize()) + "bytes");  // 02/01/2025
  // Print unused stack for the task that is running setup()
  Serial.println(" - Free Stack Space: " + String(uxTaskGetStackHighWaterMark(NULL)));  // 02/01/2025

#endif
  // *PORTAIL_gateway_texte = PropertyActions::CLEAR; // on ne clean pas au depour voir si plantage - 19/01/2025 - CLEAR supprimé
  *PORTAIL_gateway_texte = String("Gateway_") + String(Adresse_Device) + String(" démarée et initialisée");
  *PORTAIL_gateway_texte = "Arduino Stack was set to " + String(getArduinoLoopTaskStackSize()) + " - Free Stack Space " + String(uxTaskGetStackHighWaterMark(NULL));  // 05/01/2025
  phase_de_setup = 0;

#ifdef OLED_LITE
    displayOLED(Clear_ecran_OLED, Clear_ligne_OLED, 0, debut_ligne_status, 1, "Gway Ruche on-line", 1);
#endif
}

void loop()
// ****************************************************************************************
{
#if defined COMPILATION_CLOUD_IoT || defined COMPILATION_CLOUD_IDE  // Pour differencier complilation IDE & CLOUD
#if not defined DEVELOPPEMENT_NO_CLOUD_CONNEXION
  if (WiFi.status() != WL_CONNECTED)  // 26/11/2024
  {
#if defined DEBUG_OLED // 03/04/2025
    displayOLED(Clear_ecran_OLED, Clear_ligne_OLED, 0, debut_ligne_status, 1, "WIFI KO !!!!!", 1);
#endif
#ifdef DEBUG_SERIAL
    Serial.println("WIFI KO !!!!!");
#endif
  }
  if (!ArduinoCloud.connected()) {
#if defined DEBUG_OLED // 03/04/2025
    displayOLED(Clear_ecran_OLED, Clear_ligne_OLED, 0, debut_ligne_status, 1, "Arduino Not connected", 1);
#endif
    delay(1000);
  }
  ArduinoCloud.update();
#endif
#endif

  if (currentTime - clignotement_OLED_t0 > clignotement_OLED_duree) {
    GSTATUSDEV = !GSTATUSDEV;
#if defined DEBUG_OLED || defined OLED_LITE // 03/04/2025
    display.fillCircle(clignotement_OLED_horizontal, clignotement_OLED_vertical, clignotement_OLED_taille, INVERSE);
    display.display();  // Update screen with each newly-drawn circle
#endif
    clignotement_OLED_t0 = currentTime;
  }

  if (suivi_automate != 1) {
#ifdef DEBUG_SERIAL
    Serial.println("Gway #" + String(Adresse_Device) + " - attente msg.");
#endif
#ifdef DEBUG_OLED
    displayOLED(Pas_clear_ecran_OLED, Clear_ligne_OLED, 0, debut_ligne_status, 1, "Gway/attente msg", 1);
#endif
    suivi_automate = 1;
  }

  currentTime = millis();

  // parse for a  packet, and call onReceive with the result:
  message_status = 0;
  onReceive(LoRa.parsePacket());

  if (message_status == 1)  // message recu
  {
    suivi_automate = 2;
    // lecture du message recu
    lecture_du_message();

    // controle du message recu
    message_ERR = 0;
    ctrl_du_message();

    if (message_ERR == 0)  // pas d'erreur - message correct
    {
      suivi_automate = 3;
#ifdef DEBUG_OLED
      displayOLED(Pas_clear_ecran_OLED, Clear_ligne_OLED, 0, debut_ligne_received, 1, "Msg received OK", 1);
      displayOLED(Pas_clear_ecran_OLED, Clear_ligne_OLED, 0, debut_ligne_received + increment_ligne, 1, String(emetteur_du_message) + "/" + String(destinataire_du_message) + "(r" + String(relais1_du_message) + "+" + String(relais2_du_message) + "+" + String(relais3_du_message) + ")-#" + String(numero_du_message) + "-d1:" + String(donnee1_du_message), 1);
#endif
      *PORTAIL_gateway_texte = "Msg received OK - #" + String(emetteur_du_message) + "/" + String(destinataire_du_message) + "(r" + String(relais1_du_message) + "+" + String(relais2_du_message) + "+" + String(relais3_du_message) + ") / Num msg = " + String(numero_du_message) + " /d1 = " + String(donnee1_du_message) + " /d2 = " + String(donnee2_du_message) + " /d3 = " + String(donnee3_du_message) + " /d4 = " + String(donnee4_du_message) + "/Rssi = " + String(LoRa.packetRssi()) + "/Snr: " + String(LoRa.packetSnr());  //13/01/2025 - correction display
      traitement_des_donnees();
    } else {
#ifdef DEBUG_OLED
      displayOLED(Pas_clear_ecran_OLED, Clear_ligne_OLED, 0, debut_ligne_received, 1, "Msg received KO", 1);
      displayOLED(Pas_clear_ecran_OLED, Clear_ligne_OLED, 0, debut_ligne_received + increment_ligne, 1, "ERR" + String(tab_message_ERR[message_ERR]) + "#" + String(numero_du_message), 1);
#endif
      // message par defaut
      message_du_portail = String("Msg received KO - ERR ");

      // Complément de message
      if (message_ERR == 1)  //pb header ou version
      {
#ifdef DEBUG_SERIAL
        Serial.println(String(tab_message_ERR[message_ERR]) + " - version = " + String(version_du_message) + " / h1 = " + String(header1_du_message) + " / h2 = " + String(header2_du_message));
#endif
        message_du_portail = message_du_portail + String(tab_message_ERR[message_ERR]) + " - ver = " + String(version_du_message) + " / dev# = " + String(numero_device) + " / h1 = " + String(header1_du_message) + " / h2 = " + String(header2_du_message) + " / d1 = " + String(donnee1_du_message) + " / d2 = " + String(donnee2_du_message) + " / d3 = " + String(donnee3_du_message) + " / d4 = " + String(donnee4_du_message);
      }
      if (message_ERR == 2)  // pb numero de device emetteur
      {
#ifdef DEBUG_SERIAL
        Serial.println(String(tab_message_ERR[message_ERR]) + " - dev# = " + String(numero_device));
#endif
        message_du_portail = message_du_portail + String(tab_message_ERR[message_ERR]) + " / dev# = " + String(numero_device) + " / d1 = " + String(donnee1_du_message) + " / d2 = " + String(donnee2_du_message) + " / d3 = " + String(donnee3_du_message) + " / d4 = " + String(donnee4_du_message);
      }
      if (message_ERR == 3)  // Pb destinataire
      {
#ifdef DEBUG_SERIAL
        Serial.println(String(tab_message_ERR[message_ERR]) + " – device dest = " + String(destinataire_du_message));
#endif
        message_du_portail = message_du_portail + String(tab_message_ERR[message_ERR]) + " – device dest = " + String(destinataire_du_message) + " / dev# = " + String(numero_device) + " / d1 = " + String(donnee1_du_message) + " / d2 = " + String(donnee2_du_message) + " / d3 = " + String(donnee3_du_message) + " / d4 = " + String(donnee4_du_message);
      }
      if (message_ERR == 4)  // Adresse Broadcast
      {
#ifdef DEBUG_SERIAL
        Serial.println(String(tab_message_ERR[message_ERR]) + " – De:" + String(emetteur_du_message));  //
#endif
        message_du_portail = message_du_portail + String(tab_message_ERR[message_ERR]) + " – De:" + String(emetteur_du_message) + "/Rssi = " + String(LoRa.packetRssi()) + "/Snr: " + String(LoRa.packetSnr());  // 19/03/2025

        // si keepalive, alors on regarde si cela vient d'1 relais -
        if (type_du_message == Message_de_keepalive) {
          suivi_fonctionnement_de_un_relais(emetteur_du_message, Check_if_relais_Up);  // on regarde si le msg est 1 keepalive et ds ce cas, on mentionne que le relais fonctionne. // 29/12/2024
        }
      }
      if (message_ERR == 5)  // erreur type de message
      {
#ifdef DEBUG_SERIAL
        Serial.println(String(tab_message_ERR[message_ERR]) + " - Type = " + String(type_du_message));
#endif
        message_du_portail = message_du_portail + String(tab_message_ERR[message_ERR]) + " - Type = " + String(type_du_message) + " / dev# = " + String(numero_device) + " / d1 = " + String(donnee1_du_message) + " / d2 = " + String(donnee2_du_message) + " / d3 = " + String(donnee3_du_message) + " / d4 = " + String(donnee4_du_message);
      }
      if (message_ERR == 6)  // Pb sur données
      {
#ifdef DEBUG_SERIAL
        Serial.println(String(tab_message_ERR[message_ERR]) + " - d1 = " + String(donnee1_du_message) + " / d2 = " + String(donnee2_du_message));
#endif
        message_du_portail = message_du_portail + String(tab_message_ERR[message_ERR]) + " / dev# = " + String(numero_device) + " / d1 = " + String(donnee1_du_message) + " / d2 = " + String(donnee2_du_message) + " / d3 = " + String(donnee3_du_message) + " / d4 = " + String(donnee4_du_message);
      }
      if (message_ERR == 7)  // pb Checksum
      {
#ifdef DEBUG_SERIAL
        Serial.println(String(tab_message_ERR[message_ERR]));
#endif
        message_du_portail = message_du_portail + String(tab_message_ERR[message_ERR]) + " / dev# = " + String(numero_device) + " / numero = " + String(numero_du_message) + " / d1 = " + String(donnee1_du_message) + " / d2 = " + String(donnee2_du_message) + " / d3 = " + String(donnee3_du_message) + " / d4 = " + String(donnee4_du_message) + " / check = " + String(checksum_du_message);
      }
      if (message_ERR == 8)  // duplicate msg - on peut supposer qu'il s"agit d'1 relais
      {
#ifdef DEBUG_SERIAL
        Serial.println(String(tab_message_ERR[message_ERR]));
#endif
        message_du_portail = message_du_portail + String(tab_message_ERR[message_ERR]) + " - #" + String(numero_du_message) + " / dev# = " + String(numero_device) + " - r" + String(relais1_du_message) + "+" + String(relais2_du_message) + "+" + String(relais3_du_message) + "/Rssi = " + String(LoRa.packetRssi()) + "/Snr: " + String(LoRa.packetSnr());  // 14/02/2025 - ajouté rrsi
        Check_etat_des_relais(Check_if_relais_Up);                                                                                                                                                                                                                                                                                                              // 29/12/2024 - C'est 1 message dupliqu. Mais on regarde si c'est à cause d'1 relais. Et ds ce cas, on mentionne que le relais est actif - mais pas utilisé car déja recu.
      }
      // MAj du message du portail pour signaler l'erreur
      *PORTAIL_gateway_texte = message_du_portail;
    }

    // nettoyage de la structure Lora
    nettoyage_structure_lora();
  }

  // envoi du keepalive pour test de distance
  if ((currentTime - keepalive_tempo_t0) > keepalive_tempo_duree) {
    envoi_keepalive();
    keepalive_tempo_t0 = currentTime;
#ifdef DEBUG_SERIAL
    Serial.println("keepalive envoyé");
#endif
    nettoyage_structure_lora();
  }

  // calcul du nbre de mn la Gway a été lancé
  if ((currentTime - status_Gway_alive_tempo_t0) > status_Gway_alive_tempo_duree) {
    MAJdonneesportailGway();
  }

  if ((currentTime - clean_portail_msg_text_t0) > clean_portail_msg_text_duree) {
    clean_portail_msg_text_t0 = currentTime;
    *PORTAIL_gateway_texte = PropertyActions::CLEAR;
  }

  // gestion des relais - 27/11/2024
  // Reinitialisation du tableau de MAJ
  if ((currentTime - suivi_MAJ_relais_t0) > suivi_MAJ_relais_duree) {
    suivi_MAJ_relais_t0 = currentTime;
    MAJ_des_infos_des_relais_sur_portail;
#ifdef DEBUG_SERIAL
    Serial.println("MAJ du tableau des relais");
#endif
  }

  // Clignotement des LEDs associées aux relais - 27/11/2024
  if ((currentTime - clignotement_LED_relais_t0) > clignotement_LED_relais_duree) {
    clignotement_LED_relais_t0 = currentTime;
    for (int h = 0; h < Nbre_de_relais; h++) {
      if (tableau_de_suivi_des_relais[h].status_relais_Up == true) {
        bool_donnee_de_travail = *tableau_de_suivi_des_relais[h].LED_status_relais_Up;
        *tableau_de_suivi_des_relais[h].LED_status_relais_Up = !bool_donnee_de_travail;
      } else
        *tableau_de_suivi_des_relais[h].LED_status_relais_Up = false;

      if (tableau_de_suivi_des_relais[h].status_relais_used == true) {
        bool_donnee_de_travail = *tableau_de_suivi_des_relais[h].LED_relais_used;
        *tableau_de_suivi_des_relais[h].LED_relais_used = !bool_donnee_de_travail;
      } else
        *tableau_de_suivi_des_relais[h].LED_relais_used = false;
    }
  }

  if ((currentTime - impression_variable_t0) > impression_variable_delais)  // 02/01/2025
  {
    impression_variable_t0 = currentTime;
    // Print unused stack for the task that is running loop() - the same as for setup()
#ifdef DEBUG_SERIAL
    Serial.println("Free Stack Space: " + String(uxTaskGetStackHighWaterMark(NULL)) + "Bytes");  // 02/01/2025
#endif
    *PORTAIL_gateway_texte = "Arduino Stack was set to " + String(getArduinoLoopTaskStackSize()) + "- Free Stack Space " + String(uxTaskGetStackHighWaterMark(NULL));  // 05/01/2025
  }
}

void MAJdonneesportailGway()
// ****************************************************************************************
{
#ifdef DEBUG_SERIAL
  Serial.println("Entrée / MAJdonneesportailGway");
#endif
  // Si le compteur currentTime a recommencé à zéro, alors on compte 1 boucle
  if (currentTime < status_Gway_alive_tempo_t0)
    nombre_de_fois_current_time_reached = nombre_de_fois_current_time_reached + 1;
  status_Gway_alive_tempo_t0 = currentTime;  // on réinitialise t0

  // calcul des données du portail
  currentTimeJourCumule = nombre_de_fois_current_time_reached * MaxCurrentTime_Jour + round(currentTime / 1000 / 60 / 60 / 24);
  currentTimeJour = currentTimeJourCumule - nombre_de_fois_current_time_reached * MaxCurrentTime_Jour;
  currentTimeHeure = round((currentTime - currentTimeJour * 24 * 60 * 60 * 1000) / 1000 / 60 / 60);
  currentTimeMinute = round(((currentTime - currentTimeHeure * 60 * 60 * 1000 - currentTimeJour * 24 * 60 * 60 * 1000) / 60 / 1000));

  // MAJ des données du portail
  /*
  *PORTAIL_gateway_jour = currentTimeJourCumule;
  *PORTAIL_gateway_heure = currentTimeHeure;
  *PORTAIL_gateway_minute = currentTimeMinute;
  */
  *PORTAIL_gateway_texte = "Gway Up&Running depuis " + String(currentTimeJour) + "j, " + String(currentTimeHeure) + "h, " + String(currentTimeMinute);

#ifdef DEBUG_SERIAL
  Serial.println("currentTimeJourCumule = " + String(currentTimeJourCumule));
  Serial.println("currentTimeHeure = " + String(currentTimeHeure));
  Serial.println("currentTimeMinute = " + String(currentTimeMinute));
  Serial.println("Sortie / Traitement_des_donnees");
#endif
}

void traitement_des_donnees()
// ****************************************************************************************
{
#ifdef DEBUG_SERIAL
  Serial.println("Entrée / Traitement_des_donnees");
#endif

  Serial.println("MAJ des donnees");
  *Gway_donnee1OUT = donnee1_du_message;
  *Gway_donnee2OUT = donnee2_du_message;
  *Gway_donnee3OUT = donnee3_du_message;  //29/12/2024
  *Gway_donnee4OUT = donnee4_du_message;  //29/12/2024
  // *Gway_donnee1OUT = random(0, 100);
  // *Gway_donnee2OUT = random(0, 100);
  *Gway_capteurIDOUT = index_numero_device + 1;
  *Gway_donneeMAJOUT = true;

#ifdef DEBUG_SERIAL
  Serial.println("AVANT - MAJ des donnees");
  Serial.print("Gxxdonnee1OUT = " + String(*Gway_donnee1OUT) + " /");
  Serial.print("Gxxdonnee2OUT = " + String(*Gway_donnee2OUT) + " /");
  Serial.print("Gxxdonnee3OUT = " + String(*Gway_donnee3OUT) + " /");  //29/12/2024
  Serial.print("Gxxdonnee4OUT = " + String(*Gway_donnee4OUT) + " /");  //29/12/2024
  Serial.print("GxxdonneeMAJOUT = " + String(*Gway_donneeMAJOUT) + " /");
  Serial.println("GxxcapteurIDOUT = " + String(*Gway_capteurIDOUT));
#endif

  Check_etat_des_relais(Check_if_relais_used);  // 27/11/2024 - c'est 1 msg correct - on regarde s'il a été retransmis par un relais, et ds ce cas, on mentionne que le relais est actif et est UTILISé

}  // fin du traitement des données

void Check_etat_des_relais(int type_de_controle) {  // 27/11/2024
  // ****************************************************************************************
  // Analyse des données relais reçues ds la trame
  if (relais1_du_message != 0)
    suivi_fonctionnement_de_un_relais(relais1_du_message, type_de_controle);
  if (relais2_du_message != 0)
    suivi_fonctionnement_de_un_relais(relais2_du_message, type_de_controle);
  if (relais3_du_message != 0)
    suivi_fonctionnement_de_un_relais(relais3_du_message, type_de_controle);
}

void suivi_fonctionnement_de_un_relais(byte adresse_du_relais_actif, int type_de_controle)  // 24/11/2024
// ****************************************************************************************
{
// si seulement controle relais actif > on en met à jour que les donnees du remais actif
// si demande de controle = relais used, alors on met aussi à jour relais used
#ifdef DEBUG_SERIAL
  Serial.println("Entrée suivi_fonctionnement_des_relais #" + String(adresse_du_relais_actif));
#endif
  for (int z = 0; z < Nbre_de_relais; z++) {
    if (tableau_de_suivi_des_relais[z].adresse_du_relais == adresse_du_relais_actif) {
#ifdef DEBUG_SERIAL
      Serial.println("Relais reconnu - " + String(adresse_du_relais_actif));
#endif
      tableau_de_suivi_des_relais[z].status_relais_Up = true;
      tableau_de_suivi_des_relais[z].donnee_de_travail_relais_Up = true;  // 29/12/2024
      // *PORTAIL_gateway_texte = "Relais [" + String(tableau_de_suivi_des_relais[z].adresse_du_relais) + "] Up";
      if (type_de_controle == Check_if_relais_used) {
        tableau_de_suivi_des_relais[z].status_relais_used = true;
        //  *PORTAIL_gateway_texte = "Relais [" + String(tableau_de_suivi_des_relais[z].adresse_du_relais) + "/" + String(adresse_du_relais_actif) + "] used - capteurID [#" + String(emetteur_du_message) + "] type ctrl=" + String(type_de_controle); // 30/12/24
        tableau_de_suivi_des_relais[z].donnee_de_travail_relais_used = true;
      }  //
    }
  }
}

void MAJ_des_infos_des_relais_sur_portail()  // 27/11/2024
// ****************************************************************************************
{
  // controle des relais qui ne sont plus utilisés
  for (int j = 0; j < Nbre_de_relais; j++) {
    if (tableau_de_suivi_des_relais[j].donnee_de_travail_relais_Up == true) {
      tableau_de_suivi_des_relais[j].status_relais_Up = true;
    } else {
      tableau_de_suivi_des_relais[j].status_relais_Up = false;
    }

    if (tableau_de_suivi_des_relais[j].donnee_de_travail_relais_used == true) {
      tableau_de_suivi_des_relais[j].status_relais_used = true;
    } else {
      tableau_de_suivi_des_relais[j].status_relais_used = false;
    }

    // reinitialisation des données de travai
    tableau_de_suivi_des_relais[j].donnee_de_travail_relais_Up = false;
    tableau_de_suivi_des_relais[j].donnee_de_travail_relais_used = false;
  }
}

void preparation_du_message_keepalive()
// ****************************************************************************************
{
#ifdef DEBUG_SERIAL
  Serial.println("Entree / preparation_du_message_keepalive");
#endif

  header1_du_message = Header1;
  header2_du_message = Header2;
  version_du_message = Version_du_protocole_lora;
  emetteur_du_message = Adresse_Device;
  destinataire_du_message = Adresse_Broadcast;
  relais1_du_message = 0x00;
  relais2_du_message = 0x00;
  relais3_du_message = 0x00;
  numero_du_message = random(debut_numero_du_message, debut_numero_du_message + 99);
  type_du_message = Message_de_keepalive;
  donnee1_du_message = 0;
  donnee2_du_message = 0;
  donnee3_du_message = 0;
  donnee4_du_message = 0;
  checksum_du_message = numero_du_message + donnee1_du_message + donnee2_du_message + donnee3_du_message + donnee4_du_message;
  // text_du_message = "";
#ifdef DEBUG_SERIAL
  Serial.println("Sortie / preparation_du_message_keepalive");
#endif
}

void envoi_keepalive()
// ****************************************************************************************
{
#ifdef DEBUG_SERIAL
  Serial.println("Entree / envoi_keepalive");
#endif

  preparation_du_message_keepalive();
  ecriture_du_message();
  sendMessage();
#ifdef DEBUG_SERIAL
  Serial.println("Sortie / envoi_keepalive");
#endif
}

void ctrl_du_message()
// ****************************************************************************************
{
#ifdef DEBUG_SERIAL
  Serial.println("Entree / ctrl_du_message");
#endif

  // Controle du message recu
  if ((version_du_message != Version_du_protocole_lora) || (header1_du_message != Header1) || (header2_du_message != Header2)) {
    message_ERR = 1;
    return;  // skip rest of function
  }

  // Controle du type message recu
  // Modifié 25/06/24 pour contrôle type du message
  if ((type_du_message != Message_de_donnee) && (type_du_message != Message_de_keepalive)) {
    message_ERR = 5;
    return;  // skip rest of function
  }

  // controle du numero de device recu
  if ((type_du_message == Message_de_donnee) && ((numero_device < ID_premier_capteurs_configure) || (numero_device > ID_premier_capteurs_configure + Nbre_de_capteurs_configures - 1)))  //
  {
    message_ERR = 2;
    return;  // skip rest of function
  }

  index_numero_device = numero_device - 1;

  // Contrôle broadcast
  if (destinataire_du_message == Adresse_Broadcast) {
    message_ERR = 4;
    return;  // skip rest of function
  }

  // Controle du destinataire recu
  if (destinataire_du_message != Adresse_Device) {
    message_ERR = 3;
    return;  // skip rest of function
  }

  // Contrôle de la valeur mesurée
  // Modifié 02/07/24
  if ((donnee1_du_message > Donnee1_MAX) || (donnee1_du_message < Donnee1_MIN) || (donnee2_du_message < Donnee2_MIN) || (donnee2_du_message > Donnee2_MAX)) {
    message_ERR = 6;
    return;  // skip rest of function
  }

  // Ctrl Checksum
  if (checksum_du_message != numero_du_message + donnee1_du_message + donnee2_du_message + donnee3_du_message + donnee4_du_message) {
    message_ERR = 7;
    return;  // skip rest of function
  }

  // verifiation que le message n'a pas déja été recu / eviter réémission par relais
  for (int i = 0; i < taille_tab_messages_recus; i++) {
    if (numero_du_message == tab_messages_recus[i] & (currentTime - tab_messages_recus_tempo_t0[i] < messages_recus_tempo_duree)) {
      message_ERR = 8;
      return;  // skip rest of function
    }
  }

  // enregistrement du numero de message
  tab_messages_recus[index_courant_tab_messages_recus] = numero_du_message;
  tab_messages_recus_tempo_t0[index_courant_tab_messages_recus] = currentTime;
  index_courant_tab_messages_recus++;

  if (index_courant_tab_messages_recus == taille_tab_messages_recus)
    index_courant_tab_messages_recus = 0;

    // Le message est valable
#ifdef DEBUG_SERIAL
  Serial.println("Message recu valable");
  Serial.println("Sortie / ctrl_du_message");
#endif
}

/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!
!!   FONCTIONS COMMUNES AUX DEVICES - SYSTEMES, RELAIS, GATEWAY
!!   A recopier
!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/

void onReceive(int packetSize)
// ****************************************************************************************
{
  if (packetSize == 0) {
    message_status = 0;
    return;  // if there's no packet,  return
  }
  taille_du_message = packetSize;

#ifdef DEBUG_SERIAL
  Serial.println("Message recu...........................................");
  Serial.print("Lora receive RSSI ");
  Serial.print(LoRa.packetRssi());
  Serial.print(" packet size ");
  Serial.println(packetSize);
#endif

  message_status = 1;
}

void nettoyage_structure_lora()
// ****************************************************************************************
{
#ifdef DEBUG_SERIAL
  Serial.println("nettoyage_structure_lora");
#endif

  memcpy(&messageLora, &messageLoraINIT, sizeof(messageLoraINIT));

  messageLora.header1 = 0x00;
  messageLora.header2 = 0x00;
  messageLora.version = 0x00;
  messageLora.emetteur = 0x00;
  messageLora.destinataire = 0x00;
  messageLora.relais1 = 0x00;
  messageLora.relais2 = 0x00;
  messageLora.relais3 = 0x00;
  messageLora.numero_du_message = 0;
  messageLora.donnee1 = 0;
  messageLora.donnee2 = 0;
  messageLora.donnee3 = 0;
  messageLora.donnee4 = false;
  messageLora.checksum = 0;
  for (n = 0; n < 30; n++)
    messageLora.text[n] = ' ';
}

void init_structure_lora()  // 03/04/2025
// ****************************************************************************************
{
#ifdef DEBUG_SERIAL  // 03/04/2025
  Serial.println("Entree / init_structure_lora");
#endif
  messageLoraINIT.header1 = 0x00;
  messageLoraINIT.header2 = 0x00;
  messageLoraINIT.version = 0x00;
  messageLoraINIT.emetteur = 0x00;
  messageLoraINIT.destinataire = 0x00;
  messageLoraINIT.relais1 = 0x00;
  messageLoraINIT.relais2 = 0x00;
  messageLoraINIT.relais3 = 0x00;
  messageLoraINIT.numero_du_message = 0;
  messageLoraINIT.type_du_message = 0x00;
  messageLoraINIT.donnee1 = 0;
  messageLoraINIT.donnee2 = 0;
  messageLoraINIT.donnee3 = 0;
  messageLoraINIT.donnee4 = 0;
  messageLoraINIT.checksum = 0;
  for (n = 0; n < 30; n++)
    messageLoraINIT.text[n] = ' ';

#ifdef DEBUG_SERIAL  // 03/04/2025
  Serial.println("Sortie / init_structure_lora");
#endif
}

void ecriture_du_message()
// ****************************************************************************************
{
#ifdef DEBUG_SERIAL
  Serial.println("ecriture_du_message");
#endif

  messageLora.header1 = header1_du_message;
  messageLora.header2 = header2_du_message;
  messageLora.version = version_du_message;
  messageLora.emetteur = emetteur_du_message;
  messageLora.destinataire = destinataire_du_message;
  messageLora.relais1 = relais1_du_message;
  messageLora.relais2 = relais2_du_message;
  messageLora.relais3 = relais3_du_message;
  messageLora.numero_du_message = numero_du_message;
  messageLora.donnee1 = donnee1_du_message;
  messageLora.donnee2 = donnee2_du_message;
  messageLora.donnee3 = donnee3_du_message;
  messageLora.donnee4 = donnee4_du_message;
  messageLora.checksum = checksum_du_message;
  *messageLora.text = *text_du_message;
}

void lecture_du_message()
// ****************************************************************************************
{
#ifdef DEBUG_SERIAL
  Serial.println("lecture_du_message");
#endif

  volatile int packetReceived = 0;
  packetReceived = taille_du_message;

  // lecture du message recu
  LoRa.readBytes((byte *)&messageLora, packetReceived);
  header1_du_message = messageLora.header1;
  header2_du_message = messageLora.header2;
  version_du_message = messageLora.version;
  emetteur_du_message = messageLora.emetteur;
  // numero_device = hexTodec(String(emetteur_du_message));
  numero_device = emetteur_du_message;  // Correction le 05/07/26
  destinataire_du_message = messageLora.destinataire;
  relais1_du_message = messageLora.relais1;
  relais2_du_message = messageLora.relais2;
  relais3_du_message = messageLora.relais3;
  numero_du_message = messageLora.numero_du_message;
  type_du_message = messageLora.type_du_message;
  donnee1_du_message = messageLora.donnee1;
  donnee2_du_message = messageLora.donnee2;
  donnee3_du_message = messageLora.donnee3;
  donnee4_du_message = messageLora.donnee4;
  checksum_du_message = messageLora.checksum;
  *text_du_message = *messageLora.text;

#ifdef DEBUG_SERIAL
  // display des données reçues
  Serial.print("/h1=" + String(header1_du_message) + "/h2/=" + String(header2_du_message) + "/ver=" + String(version_du_message) + "/rel=" + String(relais1_du_message) + "-" + String(relais2_du_message) + "-" + String(relais3_du_message) + "/De=" + String(emetteur_du_message) + "/num dev=" + String(numero_device) + "/A=" + String(destinataire_du_message) + "/Num=" + String(numero_du_message));
  Serial.println("/type=" + String(type_du_message) + "/d1=" + String(donnee1_du_message) + "/d2=" + String(donnee2_du_message) + "/d3=" + String(donnee3_du_message) + "/d4=" + String(donnee4_du_message) + "/check=" + String(checksum_du_message) + " text = " + String(text_du_message));
#endif

  packetReceived = 0;  // clear for next time
}

void sendMessage() {
  // ****************************************************************************************

  LoRa.beginPacket();                                     // start packet
  LoRa.write((byte *)&messageLora, sizeof(messageLora));  // transmit packet
  LoRa.endPacket(true);                                   // finish packet and send it

#ifdef DEBUG_SERIAL
  Serial.print("Message envoyé : ");
  Serial.print("Sent  to: 0x" + String(messageLora.destinataire));
  Serial.print(" - From: 0x" + String(messageLora.emetteur));
  Serial.print(" - Message ID: " + String(messageLora.numero_du_message));
  Serial.print("Message:  " + *messageLora.text);
  Serial.println();
  //Serial.println("Msg envoyé " + String(msgCount) + " destination= " + String(destination));
#endif

#ifdef DEBUG_OLED
  displayOLED(Pas_clear_ecran_OLED, Clear_ligne_OLED, 0, debut_ligne_sent, 1, "Msg sent ", 1);
  displayOLED(Pas_clear_ecran_OLED, Clear_ligne_OLED, 0, debut_ligne_sent + increment_ligne * 1, 1, "De=" + String(messageLora.emetteur) + "/A=" + String(messageLora.destinataire), 1);
  displayOLED(Pas_clear_ecran_OLED, Clear_ligne_OLED, 0, debut_ligne_sent + increment_ligne * 2, 1, "Num=" + String(messageLora.numero_du_message), 1);
#endif
}

void displayOLED(int clearEcran, int ClearLigne, int positionHorizontale, int positionVerticale, int tailleText, String messageText, int couleur)
// ****************************************************************************************
{
#if defined DEBUG_OLED || defined OLED_LITE // 03/04/2025
  // Affichage OLED
  if (clearEcran == 1) {
    display.clearDisplay();
  } else {
    if (ClearLigne == 1)
      nettoyage_ligne_OLED(positionVerticale, couleur);
  }

  display.setTextColor(couleur);
  display.setTextSize(tailleText);
  display.setCursor(positionHorizontale, positionVerticale);
  display.print(messageText);
  display.display();
#endif
}

void nettoyage_ligne_OLED(int ligne_a_nettoyer, int couleur_ligne)
// ****************************************************************************************
{
#if defined DEBUG_OLED || defined OLED_LITE // 03/04/2025
  const int largeur_ecran = 127;
  const int hauteur_d_une_ligne = 7;
  int couleur_inverse = 0;

  if (couleur_ligne == 1)
    couleur_inverse = 0;
  if (couleur_ligne == 0)
    couleur_inverse = 1;

  for (int h = ligne_a_nettoyer; h < ligne_a_nettoyer + hauteur_d_une_ligne; h++) {
    for (int l = 0; l < largeur_ecran; l++) {
      display.drawPixel(l, h, couleur_inverse);
    }
  }
#endif
}

#if defined COMPILATION_CLOUD_IoT || defined COMPILATION_CLOUD_IDE  // Pour differencier complilation IDE & CLOUD

void onGdonnee1OUTChange() {
  // Add your code here to act upon GFDdonnee1OUT change
}
void onGdonnee2OUTChange() {
  // Add your code here to act upon GFDdonnee2OUT change
}
void onGdonnee3OUTChange() {  // 29/12/2024
  // Add your code here to act upon GFDdonnee3OUT change
}
void onGdonnee4OUTChange() {  // 29/12/2024
  // Add your code here to act upon GFDdonnee4OUT change
}
void onGcapteurIDOUTChange() {
  // Add your code here to act upon GFDcapteurIDOUT change
}
void onGdonneeMAJOUTChange() {
  // Add your code here to act upon GFDdonneeMAJOUT change
}
#endif

If you insist on using interrupts, the preferred way on an ESP32 would be to use the ISR to send an inter-task notification to a high-priority FreeRTOS task that's pending on that notification.

That would bring the task out of the Blocked state to run in non-ISR context. It would then read the received data from the LoRa device and buffer it for other tasks to process.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.