Outils pour utilisateurs

Outils du site


mesh_et_mqtt

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
mesh_et_mqtt [2020/04/04 10:23] sergemesh_et_mqtt [2020/10/29 13:58] (Version actuelle) – ↷ Liens modifiés en raison d'un déplacement. serge
Ligne 1: Ligne 1:
-===== Réseau MESH avec des ESP et MQtt =====+====== Réseau MESH avec des ESP et MQtt ======
  
 L'objectif était de mettre en œuvre les informations contenues dans un article paru dans HACKABLE Magazine [[https://www.hackable.fr/?p=1142|27]] dans le contexte de l'internet des objets. L'objectif était de mettre en œuvre les informations contenues dans un article paru dans HACKABLE Magazine [[https://www.hackable.fr/?p=1142|27]] dans le contexte de l'internet des objets.
Ligne 5: Ligne 5:
 La structure est la suivante : La structure est la suivante :
  
-{{:mesh_design_schema_principe.png?200|}}+{{media_08:mesh_design_schema_principe.png?200|}}
  
 Choix du matériel. Choix du matériel.
Ligne 11: Ligne 11:
 Pour ce faire j'ai opté pour l'utilisation de ce type de carte : Pour ce faire j'ai opté pour l'utilisation de ce type de carte :
 //ESP8266 ESP-01 Module de relais WiFi 2 canaux Module de relais 2 canaux pour contrôleur d'application de téléphone intelligent IOT// disponible en chine . //ESP8266 ESP-01 Module de relais WiFi 2 canaux Module de relais 2 canaux pour contrôleur d'application de téléphone intelligent IOT// disponible en chine .
-{{::esp2relaiscarte.jpg?200|}}+{{media_03:esp2relaiscarte.jpg?200|}}
  
 Le programmateur utilisé est celui-ci : Le programmateur utilisé est celui-ci :
Ligne 39: Ligne 39:
 Ce qui au niveau du code engendre ceci dans le setup() Ce qui au niveau du code engendre ceci dans le setup()
  
 +<code>
 void setup() { void setup() {
   delay(5000);   delay(5000);
   //INIT de la liaison série pour le controle des relais   //INIT de la liaison série pour le controle des relais
   Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY);   Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY);
 +</code>  
      
 et pour la commande des relais là ou vous souhaitez dans le code, ici la fermeture du relais 1 : et pour la commande des relais là ou vous souhaitez dans le code, ici la fermeture du relais 1 :
 +<code>
     Serial.write(0xA0);     Serial.write(0xA0);
     Serial.write(0x01);     Serial.write(0x01);
     Serial.write(0x01);     Serial.write(0x01);
     Serial.write(0xA2);     Serial.write(0xA2);
 +</code>
  
 ===== Le MESH ===== ===== Le MESH =====
Ligne 65: Ligne 69:
 Le gestionnaire de taches [[https://github.com/arkhipenko/TaskScheduler|TaskScheduler]] Le gestionnaire de taches [[https://github.com/arkhipenko/TaskScheduler|TaskScheduler]]
  
-=== Premiers usages ===+
  
 ===== Le MQtt ===== ===== Le MQtt =====
Ligne 87: Ligne 91:
  
 Ajout du dashboard dans Node-Red. Ajout du dashboard dans Node-Red.
 +
 +Exemple de flow pour Node-Red  
 +
 +{{ pliboo-02:flows.zip |}}
 +
 +{{media_07:le_diagramme_node-red_de_test.jpg?400|}}{{ :visu_diagramme_node-red_de_test.jpg?400|}}
 +
 +Le fichier json pour Node-Red.
 +
 +Un exemple de bouton poussoir Node-red avec changement de couleur et init à la mise sous-tension. 
 +
 +Illustration de boutons dynamique.
 +
 +{{media_04:bouton_poussoir_node_red.png?direct&200|}}
 +
 +**Reste à gérer les interaction entre les boutons, dans le cas d'une carte disposant de trois boutons R1/R2/R1 et 2 et la création d'un subflow paramétrable. Aide bienvenue -- MERCI**
 +
 +<code>
 +[{"id":"5e5c2e88.71aea","type":"ui_button","z":"d68fea03.31b0c8","name":"Bouton Poussoir","group":"65e2fa0d.4fb70c","order":0,"width":0,"height":0,"passthru":false,"label":"{{msg.state}}","tooltip":"","color":"","bgcolor":"{{msg.background}}","icon":"","payload":"true","payloadType":"bool","topic":"","x":450,"y":280,"wires":[["d450f8d3.7b7b1"]]},{"id":"7e81c5e9.f34c3c","type":"inject","z":"d68fea03.31b0c8","name":"","topic":"","payload":"reset","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":400,"y":220,"wires":[["d450f8d3.7b7b1"]]},{"id":"d450f8d3.7b7b1","type":"function","z":"d68fea03.31b0c8","name":"gestion BP","func":"\nvar state=context.get(\"state\") || \"OFF\";\n\nvar color = '';\nif (msg.payload===\"reset\") {\n    state=\"OFF\"\n    color = 'red';\n    txt = \"OFF\"\n    msg.state=\"ON\";\n}\nelse{\n\nif ((msg.payload===true) && (state==\"OFF\")) {\n    state=!state;\n    context.set(\"state\",\"ON\") ;\n    msg.payload=\"RON#1\";\n    color = \"green\";\n    txt = \"ON\"\n    msg.state=\"OFF\";\n\n} \nelse {\n    msg.payload=\"ROFF#1\";\n    context.set(\"state\",\"OFF\") ;\n    color = 'red';\n    txt = \"OFF\"\n    msg.state=\"ON\";\n}\n}\n\n node.status({\n    \tfill : color,\n    \tshape : 'dot',\n    \ttext : txt\n });\nnode.send(msg);\nmsg.background=color;\n\n\n\nreturn msg;\n","outputs":1,"noerr":0,"x":690,"y":280,"wires":[["5e5c2e88.71aea"]]},{"id":"65e2fa0d.4fb70c","type":"ui_group","z":"","name":"Carte 1 V2","tab":"3939b51c.a31712","disp":true,"width":"6","collapse":true},{"id":"3939b51c.a31712","type":"ui_tab","z":"","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]
 +</code>
 +
 +
 +
 +
 +
 +
  
 La partie iptable n'est pas mise en oeuvre du fait d'un changement dans Buster [[https://www.debian.org/releases/jessie/mips64el/release-notes/ch-whats-new.fr.html#nftables.|iptables vers nftables]] La partie iptable n'est pas mise en oeuvre du fait d'un changement dans Buster [[https://www.debian.org/releases/jessie/mips64el/release-notes/ch-whats-new.fr.html#nftables.|iptables vers nftables]]
Ligne 103: Ligne 133:
 Réalisée avec un ESP8266.  Réalisée avec un ESP8266. 
 Doit se connecter au MESH et au Broker pour assurer la passerelle. Doit se connecter au MESH et au Broker pour assurer la passerelle.
-Le code viendra ensuite.+<code
 +//***************************************************************************************************** 
 +// FICHIER DE FONCTIONNEMENT POUR ESP8266 COMME PONT 
 +// 
 +//    MQTT BROKER <---> MESH 
 +//            
 +//    François-Marie BILLARD 
 +// 
 +//    Test à faire  
 +//        envoyer un message depuis BROKER (via NODE- RED) vers le MESH OK le 2 avril 2020 
 +// 
 +//        envoyer un message depuis MESH vers BROKER : OK le 2 avril 2020 
 +// 
 +//***************************************************************************************************** 
 + 
 +#include <Arduino.h> 
 +#include <painlessMesh.h> 
 +#include <PubSubClient.h> 
 +#include <WiFiClient.h> 
 + 
 +#define   MESH_PREFIX     "meshexoposition" 
 +#define   MESH_PASSWORD   "passwordmesh" 
 +#define   MESH_PORT       5555 
 + 
 +#define   STATION_SSID     "EXPOSITION" 
 +#define   STATION_PASSWORD "1234567890" 
 + 
 +#define HOSTNAME "raspberrypi" 
 + 
 +// Prototypes 
 +void receivedCallback( const uint32_t &from, const String &msg ); 
 +void mqttCallback(char* topic, byte* payload, unsigned int length); 
 + 
 +IPAddress getlocalIP(); 
 + 
 +IPAddress myIP(0,0,0,0); 
 +IPAddress mqttBroker(192, 168, 50, 15); 
 +boolean ErreurBroker = true; 
 + 
 + 
 +painlessMesh  mesh; 
 +WiFiClient wifiClient; 
 +PubSubClient mqttClient(mqttBroker, 1883, mqttCallback, wifiClient); 
 + 
 +void setup() { 
 +  Serial.begin(115200); 
 + 
 +  mesh.setDebugMsgTypes( ERROR | STARTUP | CONNECTION );  // set before init() so that you can see startup messages 
 + 
 +  // Channel set to 6. Make sure to use the same channel for your mesh and for you other 
 +  // network (STATION_SSID) 
 +  mesh.init( MESH_PREFIX, MESH_PASSWORD, MESH_PORT, WIFI_AP_STA, 6 ); 
 +  mesh.onReceive(&receivedCallback); 
 + 
 +  mesh.stationManual(STATION_SSID, STATION_PASSWORD); 
 +  mesh.setHostname(HOSTNAME); 
 + 
 +  // Bridge node, should (in most cases) be a root node. See [the wiki](https://gitlab.com/painlessMesh/painlessMesh/wikis/Possible-challenges-in-mesh-formation) for some background 
 +  mesh.setRoot(true); 
 +  // This node and all other nodes should ideally know the mesh contains a root, so call this on all nodes 
 +  mesh.setContainsRoot(true); 
 +
 + 
 +void loop() { 
 +  mesh.update(); 
 +  mqttClient.loop(); 
 + 
 +   
 +   
 +  if (myIP != getlocalIP()) {               //pas d'adresse IP correcte 
 +    myIP = getlocalIP();                    //mise a jour de l'IP locale 
 +    if (!mqttClient.connected() ) {         //pas de connexion au Broker  
 +       if (mqttClient.connect("wifiClient")) {  //tentative de connexion  
 +          // si connexion établie 
 +          mqttClient.publish("painlessMesh/etatBridge","1");      // envoi une information de connexion via TOPIC 
 +          mqttClient.subscribe("painlessMesh/to/#");              // abonnement au TOPIC 
 +          ErreurBroker= false; 
 +          } 
 +          else { 
 +            ErreurBroker= true; 
 +          } 
 +      } 
 +    } 
 + 
 +  //ajout d'une gestion de la deconnexion. 
 + 
 +
 + 
 + 
 +//Reception depuis le MESH renvoi vers le MQTT 
 +void receivedCallback( const uint32_t &from, const String &msg ) { 
 +  Serial.printf("bridge: Received from %u msg=%s\n", from, msg.c_str()); 
 +  String topic = "painlessMesh/from/" + String(from); 
 +  mqttClient.publish(topic.c_str(), msg.c_str()); 
 +
 + 
 + 
 +//************************************************************************************ 
 + 
 +//  Cette fonction va renvoyer sur le MESH les messages en provenance du BRIDGE 
 + 
 +//************************************************************************************ 
 + 
 +void mqttCallback(char* topic, uint8_t* payload, unsigned int length) { 
 +  char* cleanPayload = (char*)malloc(length+1); 
 +  payload[length] = '\0'; 
 +  memcpy(cleanPayload, payload, length+1); 
 +  String msg = String(cleanPayload); 
 +  free(cleanPayload); 
 + 
 +  String targetStr = String(topic).substring(16); 
 + 
 +  if(targetStr == "gateway"
 +  { 
 +    if(msg == "getNodes"
 +    { // renvoi les informations sur les noeuds connectés si  
 +      // message est envoyé au TOPIC /painlessMesh/to/gateway avec message getNodes 
 +      auto nodes = mesh.getNodeList(true); 
 +      String str; 
 +      for (auto &&id : nodes) 
 +        str += String(id) + String(" "); 
 +      mqttClient.publish("painlessMesh/from/gateway", str.c_str()); 
 +    } 
 +  } 
 +  else if(targetStr == "broadcast")  
 +  { 
 +    mesh.sendBroadcast(msg); 
 +  } 
 +  else 
 +  { 
 +    uint32_t target = strtoul(targetStr.c_str(), NULL, 10); 
 +    if(mesh.isConnected(target)) 
 +    { 
 +      mesh.sendSingle(target, msg); 
 +    } 
 +    else 
 +    { 
 +      mqttClient.publish("painlessMesh/etatBridge", "0"); 
 +    } 
 +  } 
 +
 + 
 +IPAddress getlocalIP() { 
 +  return IPAddress(mesh.getStationIP()); 
 +
 +</code> 
  
 ===== Noeud du MESH  ===== ===== Noeud du MESH  =====
Ligne 119: Ligne 295:
    
    
-Le code viendra ensuite.+<code> 
 +//************************************************************ 
 +// Exemple d'usage de la librairie PainlessMESH 
 +// François-Marie BILLARD 
 +// 
 +//  Le 25 MArs 2020 
 +// 
 +// 1. Mesh sur le cana 6 
 +// 2. La commande des relais doit être du type  
 +//    RON + chiffre : Allume en fonction des données ci-dessous sans extinction des autres 
 +//    ROFF + chiffre : Eteint en fonction des données ci-dessous sans extinction des autres 
 +//    RONA : Allume tous les relais chiffrés 
 +//    ROFFA : Eteint tous les relais chiffrés 
 +// 
 +//  suivit d'un chiffre qui donne les relais actifs sous forme binaire 
 +//      0 Tout éteint 
 +//      1 Relais 1 allumé 
 +//      2 Relais 2 allumé 
 +//      3 Relais 1 et 2 allumés 
 +// 
 +//  FONCTIONNELLE le 6 AVRIL 2020 
 +// 
 +//************************************************************ 
 +#include "painlessMesh.h" 
 + 
 +#define   MESH_PREFIX     "meshexoposition" 
 +#define   MESH_PASSWORD   "passwordmesh" 
 +#define   MESH_PORT       5555 
 + 
 +#define   MAX_RELAIS   2 
 +#define MAX_RELAIS_ON 3 
 + 
 +int etatRelais; // code l'état des 16 relais chaque bit un relais 0 repos, 1 actif 
 + 
 + 
 + 
 +String message;  
 + 
 +Scheduler userScheduler; // Controluer  
 +painlessMesh  mesh; 
 + 
 +void maj_Relais() ; // Prototype pour le traitement des relais 
 + 
 +Task taskRelais( TASK_SECOND * 1 , TASK_FOREVER, &maj_Relais ); 
 + 
 +void maj_Relais() { 
 +   //traitement de l'état des relais du tableau etatRelais en fonction de la valeur ON 
 +  //cette fonction dépend du type de carte 
 +  for (int cpt=1;cpt<=MAX_RELAIS;cpt++) { 
 +    
 +    if ((etatRelais & cpt) == cpt) { //Mise à un du relais 
 +    switch (cpt) { 
 +       case 1:           
 +          //Allumage relais 1 
 +          Serial.write(0xA0); 
 +          Serial.write(0x01); 
 +          Serial.write(0x01); 
 +          Serial.write(0xA2); 
 +          delay(10); 
 +        break; 
 +      case 2: 
 +          //Allumage relais 2 
 +          Serial.write(0xA0); 
 +          Serial.write(0x02); 
 +          Serial.write(0x01); 
 +          Serial.write(0xA3); 
 +          delay(10); 
 +      break; 
 +    } 
 +     
 +    } else { //Mise à zéro du relais 
 +    switch (cpt) { 
 +       case 1: 
 +          //Extinction relais 1 
 +          Serial.write(0xA0); 
 +          Serial.write(0x01); 
 +          Serial.write(0x00); 
 +          Serial.write(0xA1); 
 +          delay(10); 
 +        break; 
 +      case 2: 
 +          //Extinction relais 2 
 +          Serial.write(0xA0); 
 +          Serial.write(0x02); 
 +          Serial.write(0x00); 
 +          Serial.write(0xA2); 
 +          delay(10); 
 +      break; 
 +    } 
 +    } 
 +
 +
 + 
 + 
 + 
 + 
 + 
 +// User stub 
 +void sendMessage() ; // Prototype so PlatformIO doesn't complain 
 + 
 + 
 +Task taskSendMessage( TASK_SECOND * 1 , TASK_FOREVER, &sendMessage ); 
 + 
 +void sendMessage() { 
 +   
 +  String msg = "Depuis le noeud  "; 
 +   
 +  msg += mesh.getNodeId(); 
 +  msg += message; 
 +  mesh.sendBroadcast( msg ); 
 +  taskSendMessage.setInterval( random( TASK_SECOND * 1, TASK_SECOND * 5 )); 
 +  message=""; 
 +
 + 
 +// Needed for painless library 
 +void receivedCallback( uint32_t from, String &msg ) { 
 + //fonctionnel le 6 Avril 2020 
 + boolean fin =false; 
 + int cpt =0; 
 + int valeur = -1; 
 + 
 + while (!fin){ 
 +  if (isDigit(msg[cpt])) { 
 +  
 +    fin=true; 
 +    String temp=msg.substring(cpt); 
 +    valeur= temp.toInt(); 
 +    msg=msg.substring(0,cpt); 
 +   } 
 +  else { 
 +    if (cpt>msg.length()) { 
 +    fin =true; 
 +    cpt=-1; 
 +  } 
 +  else { 
 +        cpt++; 
 + 
 +  } 
 + } 
 +
 + message = "recu : " + msg; 
 + if (msg=="RONA") { 
 +    //MAJ_Relais(MAX_RELAIS); 
 +    etatRelais=MAX_RELAIS_ON; 
 +    message= message + "Traite RONA"; 
 +  } else  
 +    if (msg=="ROFFA") { 
 +        etatRelais=0; 
 +        message= message + "Traite ROFFA"; 
 +    } else  
 +      if (msg=="RON") { 
 +        etatRelais=(etatRelais | valeur ); 
 +        message= message + "Traite RONx"; 
 +      } else  
 +        if (msg=="ROFF") { 
 +                    etatRelais=(etatRelais & (~valeur) ); 
 +                    message= message + "Traite ROFFx"; 
 +                    } 
 +                    else if (msg=="TYPE") { 
 +                    //sendMessage 
 +                    message="Relais_2"; 
 +                    } 
 +
 + 
 +void newConnectionCallback(uint32_t nodeId) { 
 +    //Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId); 
 +
 + 
 +void changedConnectionCallback() { 
 +  //Serial.printf("Changed connections\n"); 
 +
 + 
 +void nodeTimeAdjustedCallback(int32_t offset) { 
 +    ////Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset); 
 +
 + 
 +void setup() { 
 +  //Serial.begin(115200); 
 +   //INIT de la liaison série pour le controle des relais 
 +  Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY); 
 +  etatRelais = 0; //relais tous au repos 
 + 
 + 
 +//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on 
 +  mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages 
 + 
 +  mesh.init( MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT , WIFI_AP_STA, 6); 
 +  //mesh.init( MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT ); 
 +  mesh.onReceive(&receivedCallback); 
 +  mesh.onNewConnection(&newConnectionCallback); 
 +  mesh.onChangedConnections(&changedConnectionCallback); 
 +  mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback); 
 + 
 + 
 +  userScheduler.addTask( taskSendMessage ); 
 +  taskSendMessage.enable(); 
 + 
 +  userScheduler.addTask( taskRelais ); 
 +  taskRelais.enable(); 
 +
 + 
 +void loop() { 
 +   // tâche utilisateur et tâche mesh 
 +  userScheduler.execute(); 
 +  mesh.update(); 
 +
 +</code>
  
 {{tag>nodejs node-red développement mqtt iOT bj}} {{tag>nodejs node-red développement mqtt iOT bj}}
mesh_et_mqtt.1585995796.txt.gz · Dernière modification : 2020/04/04 10:23 de serge