Cloud IoT - Synchronisation between 2 variables no more working

Synchronisation between 2 variables no more working. It was working before and it stopped working from yesterday.... Here is the pb.

Variable 1 = GdonneeMAJOUT, boolean, variable ID = f9fe12d7-fa29-4b5e-a32d-0ab80bc4a945, Variable Permission = Read & Write, Update Policy = On change

Variable 2 = GdonneeMAJIN, boolean, variable ID = 98e07a55-80bc-4ec8-b554-1d40966016bc, Variable Permission = Read & Write, Update Policy = On change

In the Arduino IoT Cloud interface :

  • BEFORE YESTERDAY : I have been able to link (synchronise) the 2 variables, and it was working fin.

  • from Yesterday, the 2 variables are no more synchronised.

On the IoT Cloud Interface, I can seen that :

  • Variable 2 is well configured (synchronised with variable 1).

  • Variable 1 is NO MORE CONFIGURED as synchronised with Variable 2. When I want to modify the Variable 1 to have it synchronised with varaible 2, I can select Variable 2 in the list of the variables that can be synchronised, I « Save » the config… but it doesn’t appear as « being synchronised » with variable 2.

  • RESULTS : my 2 variables are NOT synchronised Variable 1 is TRUE, Variable 2 is false. And I cannot modify it.
    Please see the attached file with screenshots.
    Pb with synchronisation.pdf (143,9 Ko)

Hi @hanotte78. Thanks for reporting this. I apologize for any inconvenience this has caused.

The Arduino Cloud developers have made a possible fix for the problem. Please check to see if the Variable sync feature is now working correctly and let me know what you find.

Hello. Unfortunately it does not. I have seen that the 2 variables are configured as synchronised, but the values are still different.

Hello.
It works now. Many thanks ! I hope it will not appear again. Cheers.

Great news! Thanks for taking the time to post an update.

Regards, Per

Hello.
I'm using the synchronisation of things feature in the arduino IoT Cloud. The synchronisation is always between 2 variables (things) that are so synchronised. I works fine when only 1 variable of the 2 is updated by the sketch I have loaded on the board (variable 1 is updated by the sktech and the 2nd variable is updated throught the synchronisation process).

BUT the problem I'm facing is when the updates done with the sketch are done on the 2 variables : example variable 1 is updated by the sketch and variable 2 is updated via the synchronsation and other times that is the variable 2 that is updated by the sktech and the variable 1 is updated with the synchronisation.

The problem is appearing on a regular basis. It means that around every week, variable 2 is not updated via the synchronisation process when variable 1 is updated by the sketch. The problem is solved when I restart the board that is associated the the variable 1.

The variables that are not synchronised are :

  • variable 1 = GdonneeMAJOUT (80762d76-2c9d-4c00-8853-1559df5325f6) - associated device = 6cdd24f2-710e-4c78-b939-2ccf87c588f7
    and
  • variable 2 = GFEdonneeMAJIN (ee9be093-50c1-4006-a6ba-d7639cfaaaf1) - associated device = 7751cba4-9904-4afe-8d6e-0fce67c07b2e

The question is so : how to avoid that desynchronisation ?
Is there something wrong in my script ?

My script is quite simple (running in the device associated to the variable 1) :

// Energie Mairie - Gway ALL - 20241230.02 - tracking des relais.txt
/*
  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

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