Je suis fasse un problème d'envoi de donnée en MQTT avec la commande client.publish
Il s'agit d'un pluviomètre branché à un ESP32, la lecture sur le moniteur série fonctionne parfaitement par contre, je n'ai aucune réception avec mon serveur nodered hébergé sur une RaspberryPi 5 via le brocker MOSQUITO.
Voici le code de l'esp32 :
// -------------------------------------- Connection wifi et borker MOSQUITTO ----------------------//
#include <WiFi.h>
#include <PubSubClient.h>
#define ssid "########"
#define password "###########"
#define mqtt_server "192.168.1.##"
const char* mqttUser = "#########";
const char* mqttPassword = "##########";
char message_buff[100];
long lastMsg = 0;
// long lastRecu = 0;
bool debug = false;
char msg[50];
int value = 0;
String consigne;
WiFiClient espClient;
PubSubClient client(espClient);
//--------------------------------- WIFI -----------------------------------------//
void setupWifi()
{
Serial.println("\n");
WiFi.begin(ssid, password);
Serial.print("Tentative de connexion...");
while(WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(100);
}
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
payload[length]='\0';
String cons = String((char*)payload);
consigne = cons;
Serial.println();
}
void reconnect(){
//Boucle jusqu'à obtenur une reconnexion
while (!client.connected()) {
Serial.print("Connexion au serveur MQTT...");
// si MQTT sécurisé alors
if (client.connect("Esp32_abris_bassin_deux", mqttUser, mqttPassword )) {
Serial.println("Esp32_abris_bassin_deux");
//Une fois connecté, on peut s'inscrire à un Topic
client.subscribe("Relais/eclairage/jardin");
debug = true;
}
else {
Serial.print("failed, erreur : ");
Serial.print(client.state());
debug = false;
Serial.println("5 secondes avant de recommencer");
delay(5000);
}
}
}
// -------------------- Déclaration pluviomètre ---------------------
#include <CircularBuffer.hpp>
#define INTERVAL 120
CircularBuffer<float, 3> h_fifo;
const byte rainPin = 34;
unsigned int raincnt = 0;
unsigned long lastSend;
float pluie;
ICACHE_RAM_ATTR void cntRain() {
raincnt++;
}
void getSendRain() {
float h_total = 0.00;
lastSend = millis();
pluie = raincnt * 0.2794;
raincnt = 0;
Serial.print("Pluie = ");
Serial.print(String(pluie));
Serial.println(" mm ");
using index_h = decltype(h_fifo)::index_t;
for (index_h i = 0; i < h_fifo.size(); i++) {
h_total += h_fifo[i];
}
h_total = h_total * 10;
}
// ----------------- Déclaration des abonnements MQTT ----------------------------
#define sonde1_topic "Pluviometre/exterieure"
// ------------------------------------------------------------------ SETUP -------------------------------------------------------------------
void setup() {
Serial.begin(115200);
// ------------------------- Mise en route pluviomètre ---------------------------
pinMode(rainPin, INPUT); // Montage PullUp avec Condensateur pour éviter l’effet rebond.
attachInterrupt(digitalPinToInterrupt(rainPin), cntRain, FALLING);
lastSend = millis();
// ---------------------------- Lancement du wifi -----------------------------
setupWifi();
delay(1000);
Serial.println("\n");
Serial.println("Connexion etablie!");
Serial.print("Adresse IP: ");
Serial.println(WiFi.localIP());
delay(5000);
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
delay(500);
}
// -------------------------------------------------------------------- LOOP ---------------------------------------------------------------------
void loop() {
if ( millis() - lastSend > INTERVAL*1000 ) {
getSendRain();
}
//Publication des mesures:
if(debug) {
client.publish(sonde1_topic, String(pluie).c_str(), true);
}
}
J'ai déclaré la valeur pluie en : float pluie; et je la transforme en String pour que la chaine de caractère soit transmis via la commande publish : client.publish(sonde1_topic, String(pluie).c_str(), true);
A noter que le serveur fonctionne bien, j'ai plusieurs autres ESP32 avec d'autres sondes et tout remonte niquel se qui me dit que je dois mal manipuler la donnée du pluviomètre.
Quelqu’un a une idée pour me filer un coup de pouce ?
raincnt devrait être déclaré volatile et vous devriez mettre un mutex lors du traitement dans la loop car l'accès à des variables partagées peut poser un souci de cohérence. (une interruption pourrait survenir pendant que vous êtes en train de manipuler les octets de votre compteur).
sur ESP32 ça va fonctionner car un int est par défaut sur 32 bits mais sur AVR 120 x 1000 ne fait pas 120000 car on déborde ce qu'un entier peut représenter (32767)
il vaudrait mieux faire
const uint32_t INTERVAL = 120ul * 1000ul; // le ul dit au compilateur qu'on est en unsigned long
...
if ( millis() - lastSend > INTERVAL ) {
Ce sont des macros pour le debug. En utilisant D_print("coucou");
si le debug est activé c’est comme si j’avais mis Serial.print("coucou");
ou ça enlève la commande en entier si débug est désactivé. (La macro est remplacée par rien du tout, pas de code)
Les … veulent dire « n’importe quelle liste de paramètres » en entrée de la macro et __VA_ARGS__ dans ce par quoi on remplace la macro veut dire « mettre tous les paramètres ici ».
Ainsi, en utilisant ces macros et en modifiant juste une valeur de DEBUG, vous pouvez enlever toutes les traces de debug du code quand vous compilez. C’est plus simple que d’avoir a parcourir le code et mettre partout des //
constexpr ça veut dire qu’on veut s’assurer que ce soit définit à la compilation et que la valeur ne changera pas. Ce n’est pas obligatoire mais c’est une indication pour le compilateur. Vous pouvez juste conserver le type avec const tout seul.
La partie en section critique fait la copie du compteur et le remet à zéro avec les interruptions désactivées. Ça ne prend que quelques microsecondes donc on ne ratera pas grand chose même s’il pleut fort. De cette façon je suis sûr qu’aucune interruption va venir mettre le bazar dans mes 2 lignes pendant que j’utilise le compteur. Une fois sorti de la section critique j’utilise la copie pour les calculs - celle ci n’étant pas modifiable par une interruption, on est tranquille.