Problème pour envoi commande Mqtt vers ESP32

Bonsoir,

Je me suis lancé sur un projet de tracker photovoltaïque (ça fais déjà un mois que je suis dessus) et c’est aussi un grand défi car je ne suis pas spécialiste du code.

Je suis entrain de mettre en place le Mqtt pour remonter certaines infos et aussi pouvoir depuis jeedom envoyer des commandes sur le tracker.

Pour l’instant j’arrive à remonté les infos dans le plugin jmqtt.

J’ai fais a l’arrache un autre petit code pour pouvoir faire les tests pour les commandes reçu sur l’esp avant de mettre le mqtt complet sur le code du tracker, mais pas moyen de trouver comment faire.

Je post le code pour ceux qui pourrait m’aider :slightly_smiling_face:

/********* TEST-MQTT *************/
#include <ArduinoJson.h>
//#include <ArduinoJson.hpp>
#include <AsyncElegantOTA.h>
#include <ESPAsyncWebServer.h>
#include <AsyncTCP.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include "LiquidCrystal_I2C.h"
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2561_U.h>
#define TSL2561_SDA 21
#define TSL2561_SCL 22
//relais pour test mqtt
#define relais1 16 // gpio
int relais1State; //test etat relais test mqtt 
const int Boutonrelais1 = 32;
bool info_bouton = false; //test
bool led = false; //variable pour bouton ou seuil lumière

Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345);

const char* ssid = "xxxxxxxx";
const char* password = "xxxxxxxxx";
const char* mqttServer = "192.168.50.12";
const int mqttPort = 1883;
const char* clientId = "ESP32Client";

//variable RSSI pour tempo envoi
unsigned long lastMqttUpdate = 0;
const unsigned long mqttUpdateInterval = 30000;  // Intervalle en millisecondes (30 secondes)

WiFiClient espClient;
PubSubClient client(espClient);

//Créer objet  AsyncWebServer sur le port 80 :
AsyncWebServer server(80); //***

char message[10]; // Définissez un tableau de caractères pour stocker le message
//TEST MQTT**************
void MQTTsend() {
  char buffer[512];
  DynamicJsonDocument docMqtt(512);
  docMqtt["Lux"] = message;
  //docMqtt["notification"]= "Test envois sur le broker";  // exemple message texte
  // Convertir le RSSI WiFi en chaîne de caractères
  char rssiBuffer[5];
  itoa(WiFi.RSSI(), rssiBuffer, 10);
  docMqtt["RSSI du WiFi"]= rssiBuffer; //ok
  docMqtt["Relais1"]= relais1State;    //ok
  docMqtt["Bouton"]= info_bouton;      //ok
  //size_t n = serializeJson(docMqtt, buffer); //test
  String jsonString;
  serializeJson(docMqtt, jsonString);
  //client.publish("Tracker-ldr/sensor/state", buffer, n); //test
  client.publish("Tracker-ldr/sensor/state", jsonString.c_str()); //ok
}
// Connection au wifi
void setup_wifi() {
  delay(10);
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
  }
  Serial.println();
  Serial.print("Connecté au réseau WiFi avec l'adresse IP: ");
  Serial.println(WiFi.localIP());
  //Serial.print("Signal Wifi");
  //Serial.println(WiFi.RSSI());
  // connection sur navigateur = IP esp et IP/update pour mise a jour OTA
   server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send(200, "text/plain", "Je suis le test mqtt .");
  });

  AsyncElegantOTA.begin(&server);    // Start ElegantOTA
  server.begin();
  Serial.println("HTTP server started");
}

// reconnection Mqtt
void reconnect() {
  // Boucle jusqu'à ce que nous soyons reconnectés
  while (!client.connected()) {
    Serial.print("Tentative de connexion au broker MQTT...");
    // Tentative de connexion
    if (client.connect("ESP32Client")) {
      Serial.println("Connecté");      
    } else {
      Serial.print("échoué, rc=");
      Serial.print(client.state());
      Serial.println(" nouvelle tentative dans 5 secondes");
      // Attendez 5 secondes avant de réessayer
      delay(5000);
    }
  }
}
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.println("Message MQTT reçu !");
  // Traite le message ici
  // Par exemple, allumez ou éteignez le relais en fonction du message reçu
  if (payload[0] == '1') {
    digitalWrite(relais1, HIGH);
    relais1State = 1;
  } else if (payload[0] == '0') {
    digitalWrite(relais1, LOW);
    relais1State = 0;
  }
} 
void setup() {
  Serial.begin(115200);
  delay(10);
  // TSL2561
  Wire.begin(TSL2561_SDA, TSL2561_SCL);
    
    if (!tsl.begin()) {
        Serial.println("Capteur TSL2561 non trouvé. Vérifiez votre câblage !");
        while (1);
    }
    tsl.enableAutoRange(true); 
  // connection wifi
  setup_wifi();
  AsyncElegantOTA.begin(&server);//***
  server.begin();                //***
  // Connexion au serveur MQTT
  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback); // Définir la fonction de rappel pour les messages MQTT reçus
  // S'abonner au sujet MQTT ? Pas de message!!!
  client.subscribe("Tracker-ldr");
  //type relais
 pinMode(relais1, OUTPUT); //*pour test mqtt
 pinMode(Boutonrelais1, INPUT_PULLUP); //*pour test mqtt
}

void loop() {
  delay(1000);
  //fonction de reconnection wifi
  if (!client.connected()) {
    reconnect();
  }   
  //Tempo envoi info MQTT
  // Vérifiez si le temps écoulé dépasse l'intervalle de mise à jour du RSSI (30 secondes)
  if (millis() - lastMqttUpdate >= mqttUpdateInterval) {
    // Mettez à jour le dernier temps d'envoi du RSSI
    lastMqttUpdate = millis(); 
    MQTTsend();  //lancement envoi info Mqtt 
        
  } 
  // info lux
  sensors_event_t event; // info tsl2561
  tsl.getEvent(&event);
  //variable pour lumière
  int lumiere = event.light; 
  // Convertir l'int en chaîne de caractères
  dtostrf(event.light, 6, 2, message);
  //snprintf(message, sizeof(message), "%d", event.light);
  Serial.print("Message à publier sur MQTT : ");
  Serial.println(message);

  if (event.light) {
      Serial.print("Luminosité: ");
      Serial.println(event.light);
  } else {
     Serial.println("Erreur lors de la lecture de la luminosité !");
   
  }   
  //int relaisporteState; //etat relais test mqtt
  int Boutonrelais1State = digitalRead(Boutonrelais1);  //test mqtt
  //test mise en marche relais auto et remonter mqtt
  if (lumiere > 150) {
    digitalWrite(relais1, HIGH);
    relais1State = 1;
    led = true;
  }
  if (lumiere < 50) {
    digitalWrite(relais1, LOW);
    relais1State = 0;
    led = false;
  }
   
  Serial.println(relais1State); //état relais moniteur série //debug
  //test en local esp
  if (led) {   
  } else{
  if (Boutonrelais1State == LOW) {
    digitalWrite(relais1, HIGH);
    relais1State = 1;
    info_bouton = true;    
    } else {
      
    digitalWrite(relais1, LOW);
    relais1State = 0;
    info_bouton = false;
    Serial.println("relais off sur bouton");//debug
   }
  }
  client.loop();
}

Merci

Hello,

C’est toujours intéressant de mettre les mains dans le code :slight_smile:

Par contre tu peux préciser ce que cherche à faire, par ce que là, juste avec le code brute de fonderie, ce n’est pas très clair…

C’est un ESP8266 ou un ESP32 ?
Ton IDE est Arduino ou Visual Studio ?
Tu cherches à récup des info depuis le broker ou en envoyer ?

Tu as regardé/trouvé des codes ou des projets tout faits qui se rapprochent ou pourraient t’aider à arriver à ton but ?

Bad

Hello,
Merci de me répondre :grinning:

Alors des projets, tuto et toutes sortes de lectures en C++ j’en ai lus a foison.
Et pour le mqtt c’est pas évident de trouver quelque chose de claire.

J’utilise un esp32 et l’ide arduino.
Pour l’instant je récupère les infos envoyé de l’esp vers jmqtt.
Et ce que je voudrais c’est de pouvoir depuis jmqtt piloter le relais pour commencer.

Quand j’envoie une commande depuis jmqtt, je la vois bien dans mqtt explorer mais elle n’arrive pas sur l’esp.
Je que j’essaie c’est de passer le bool info_bouton à false où true depuis jmqtt et dans le code de l’esp si il reçoit le message ça devrait allumer le relais ( enfin c’est comme ça que devrait exécuter le code si j’ai bien compris)
Je ne suis pas arrivé à trouvé comment remonter le relais1 en mqtt .

C’est la dernière petite pierre qu’il manque dans le code du tracter et c’est pour ça que j’ai bidouiller un code de test avant.
Bon je pense que mon code est sûrement pas propre pour le tracker mais tout fonctionne très bien.

Merci

Salut, dans les logs de l’esp est-ce que le serial print « message mqtt reçu » apparaît? Il faudrait mettre le code dans sa totalité.

Salut,
Non justement dans le moniteur série j’ai rien en message reçu.
Pour le code de test c’est celui que j’ai mis dans le post.
Je mettrai des screen ce soir de mon équipement jmqtt et ce qui remonte dans le json.

Je détaillerai de comment sont les fonctions du code par rapport à ce que je comprend.

Je ne vois que relais1State dans le callback, je ne sais pas trop si c’est de ce bool que tu parles.

La Doc de la lib Arduino mqtt est pourtant assez bien faite et il y a quelques exemples au début : GitHub - 256dpi/arduino-mqtt: MQTT library for Arduino

Tu fais ça pour apprendre le MQTT en C/C++ ou pour produire effectivement quelque chose ?

Je te pose la question, car avec ESP Easy et des Rules dans l’esp, tu fais exactement la même chose en 5 minutes et pas besoin de regarder comment fonctionne le code. Il y a aussi microPython, etc…

La Doc avec tous les devices supportés : Devices Page — ESP Easy 2.1-beta1 documentation

En résumé, si tu veux vraiment faire le code de zéro, regarde pour le faire avec platformIO, plutôt que Arduino, c’est plus « professionnel », et si tu n’est pas vraiment intéressé par le code en profondeur, part sur ESP Easy, Tasomta, microPython ou autre

Bad

Je fais ça pour apprendre car de commencer ce projet de tracker ma donné envie de faire par là suite d’autres projets.

Et espeasy n’est pas compatible pour piloter un tracker avec toutes les fonctions que j’ai mis en place.

Et oui c’est bien pour le mettre en place sur le code du tracker donc je commence par le mettre en place sur quelque chose de plus simple pourcomprendre ( code que j’ai mis dans le 1er post.

Merci

Code de test je veux bien mais il manque toutes les defines topic mqtt et les chemins json, donc pour moi ce n’est pas complet

Ah ben le problème viens sûrement de la car pour l’envoi d’info esp vers jmqtt fonctionne très bien, donc si je comprend bien il faut rajouter du code pour la réception.
Si c’est le cas, j’ai pas trouvé de tuto pour ce type de réception, pourtant j’ai écumé de la lecture

Bonjour.

Le subscribe doit se faire après une connexion réussie à MQTT, comme ceci

    if (client.connect("ESP32Client")) {
      Serial.println("Connecté");     
      client.subscribe("Tracker-ldr/relais1");

J’ai aussi modifié le nom du topic ( ajout de relais1 ) : Tracker-ldr/relais1 pour que ça corresponde à la commande sur jmqtt

Philippe

Hello,
Merci je vais tester
Edit , il y a du mieux j’ai bien message reçu dans le moniteur série, mais le relais ne s’allume pas.
Donc comme le dit @Math82 il doit manquer certaine chose dans le code.

Alors pour expliquer:
J’ai mis en place en premier pour testé, juste l’envoi d’info sur jmqtt et cela fonctionne très bien.

Et c’est cette partie du code pour l’envoi d’info:

//TEST MQTT**************
void MQTTsend() {
  char buffer[512];
  DynamicJsonDocument docMqtt(512);
  docMqtt["Lux"] = message;
  //docMqtt["notification"]= "Test envois sur le broker";  // exemple message texte
  // Convertir le RSSI WiFi en chaîne de caractères
  char rssiBuffer[5];
  itoa(WiFi.RSSI(), rssiBuffer, 10);
  docMqtt["RSSI du WiFi"]= rssiBuffer; //ok
  docMqtt["Relais1"]= relais1State;    //ok
  docMqtt["Bouton"]= info_bouton;      //ok
  //size_t n = serializeJson(docMqtt, buffer); //test
  String jsonString;
  serializeJson(docMqtt, jsonString);
  //client.publish("Tracker-ldr/sensor/state", buffer, n); //test
  client.publish("Tracker-ldr/sensor/state", jsonString.c_str()); //ok
}

Ensuite j’ai voulu rajouter la réception de msg pour envoyer certaine commandes depuis jmqtt et ce qui pour moi correspond a cette partie du code:

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.println("Message MQTT reçu !");
  // Traite le message ici
  // Par exemple, allumez ou éteignez le relais en fonction du message reçu
  if (payload[0] == '1') {
    digitalWrite(relais1, HIGH);
    relais1State = 1;
  } else if (payload[0] == '0') {
    digitalWrite(relais1, LOW);
    relais1State = 0;
  }
} 

Actuellement sur le moniteur série:

17:46:37.059 -> HTTP server started
17:46:38.037 -> Tentative de connexion au broker MQTT...Connecté
17:46:38.118 -> Message à publier sur MQTT :  58.00
17:46:38.161 -> Luminosité: 58.00
17:46:38.161 -> Etat relais = 0
17:46:38.161 -> relais off sur bouton
17:46:39.167 -> Message à publier sur MQTT :  52.00
17:46:39.167 -> Luminosité: 52.00
17:46:39.167 -> Etat relais = 0
17:46:39.167 -> relais off sur bouton
17:46:40.174 -> Message à publier sur MQTT :  54.00
17:46:40.174 -> Luminosité: 54.00
17:46:40.174 -> Etat relais = 0
17:46:40.174 -> relais off sur bouton
17:46:41.200 -> Message à publier sur MQTT :  51.00
17:46:41.200 -> Luminosité: 51.00
17:46:41.200 -> Etat relais = 0
17:46:41.200 -> relais off sur bouton
17:46:41.200 -> Message MQTT reçu !
17:46:42.222 -> Message à publier sur MQTT :  60.00
17:46:42.222 -> Luminosité: 60.00
17:46:42.222 -> Etat relais = 1
17:46:42.222 -> relais off sur bouton
17:46:43.240 -> Message à publier sur MQTT :  63.00
17:46:43.240 -> Luminosité: 63.00

et ce qui ce passe sur jmqtt:
mqtt-relais

Alors , @PhilippeJ je viens de retesté la commande depuis jmqtt en plaçant

client.subscribe("Tracker-ldr/relais1");

comme tu la dis et ben ça fonctionne au final :grin: mais il manque quand même quelque chose dans le code car la c’est juste pour le relais, mais je vais utiliser plusieurs commandes envoyé depuis jmqtt et je vais avoir des commandes qui doivent passer certaine variable de true à false ou vice-versa.

Mais là c’est un peu le trou noir pour moi, faut que je fouille.

Oui, tu n’est pas loin, tu envoies le string true depuis jMQTT, pas 1 :smiley:

Après, pour différencier les infos, il faut que tu utilises le topic, en plus du payload :

Perso, je partirais plutôt sur la callback en String que des char* et byte* :
void callback(const String& topic, const String& payload, const size_t size);
cf : GitHub - hideakitai/MQTTPubSubClient: MQTT and MQTT over WebSoket Client for Arduino

Ou alors directement bool subscribe(const String& topic, const topic_callback_t& cb);, avec une callback par topic.

Et je comparerais simplement payload == "true"

Ok , je vais analyser un peu le truc car ça fiat beaucoup d’info a digérer :face_with_head_bandage:(pas évident pour mon cas de néophyte sur le code) .

Pour les commandes depuis jmqtt , je vais en avoir certaines qui doivent envoyer MANUEL ou JOUR ou VEILLE ou bien NUIT qui sont des enum dans le code du tracker.
Merci

Je précise :

Ton test ici :

Vérifie que le 1er char du payload est égal au char 1.
Or, vu que tu envoies true ou false dans jMQTT, le 1er char vaut soit t, soit f.

Donc tu ne rentres jamais dans les cas du IF,
d’ou la présence d’un message en serial mais pas d’action.

Ok, je vois ça un peu plus tard dans la soirée pour tester.
Merci

Hello,

Petit retour car j’avais pas eu le temps de voir plus pour le mqtt.

Ayant fait une modification matériel, il a fallut que je reprenne le code pour le tracker et j’ai fini par le mqtt.

Au final après réflexion et analyse de ce que je voulais faire depuis jmqtt, j’ai besoin de piloter qu’un seul relais depuis jmqtt pour activer certaine fonctions qui sont pris en charge sur le code du tracker.
Donc j’ai gardé le :

void callback(char* topic, byte* payload, unsigned int length)

Je vais pouvoir passer sur la partie PCB.

Merci

Ce sujet a été automatiquement fermé après 24 heures suivant le dernier commentaire. Aucune réponse n’est permise dorénavant.