mesh_et_mqtt
Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédenteDernière révisionLes deux révisions suivantes | ||
mesh_et_mqtt [2020/03/25 16:44] – BILLARD | mesh_et_mqtt [2020/10/29 13:53] – ↷ 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' | L' | ||
+ | |||
+ | La structure est la suivante : | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Choix du matériel. | ||
Pour ce faire j'ai opté pour l' | Pour ce faire j'ai opté pour l' | ||
//ESP8266 ESP-01 Module de relais WiFi 2 canaux Module de relais 2 canaux pour contrôleur d' | //ESP8266 ESP-01 Module de relais WiFi 2 canaux Module de relais 2 canaux pour contrôleur d' | ||
- | {{:: | + | {{media_03: |
Le programmateur utilisé est celui-ci : | Le programmateur utilisé est celui-ci : | ||
CH340 USB à ESP8266 série ESP-01 ESP-01S ESP01 ESP01S sans fil Wifi développement Module de carte pour Arduino programmeur adaptateur | CH340 USB à ESP8266 série ESP-01 ESP-01S ESP01 ESP01S sans fil Wifi développement Module de carte pour Arduino programmeur adaptateur | ||
+ | |||
+ | Une carte Raspberry-PI ancien modèle avec une carte WI-FI sur Port USB -- Système Raspbian BUSTER. | ||
===== La carte ESP + Relais ===== | ===== La carte ESP + Relais ===== | ||
Ligne 31: | Ligne 39: | ||
Ce qui au niveau du code engendre ceci dans le setup() | Ce qui au niveau du code engendre ceci dans le setup() | ||
+ | < | ||
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.begin(115200, | ||
+ | </ | ||
| | ||
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 : | ||
+ | < | ||
Serial.write(0xA0); | Serial.write(0xA0); | ||
Serial.write(0x01); | Serial.write(0x01); | ||
Serial.write(0x01); | Serial.write(0x01); | ||
Serial.write(0xA2); | Serial.write(0xA2); | ||
+ | </ | ||
===== Le MESH ===== | ===== Le MESH ===== | ||
- | === La librairie Painless | + | === Le principe du |
- | Disponible ici : [[https:// | + | |
+ | D' | ||
+ | |||
+ | Le réseau maillé1 (ou maillage en réseau2) est une topologie de réseau (filaire et sans fil) où tous les hôtes sont connectés pair à pair sans hiérarchie centrale, formant ainsi une structure en forme de filet. | ||
+ | |||
+ | === Les librairies pour ESP8266 === | ||
+ | Pour le MESH : [[https:// | ||
+ | |||
+ | La gestion de la communication MQTT : [[http:// | ||
+ | |||
+ | Le gestionnaire de taches [[https:// | ||
- | === Premiers usages === | ||
===== Le MQtt ===== | ===== Le MQtt ===== | ||
Ligne 55: | Ligne 77: | ||
[[protocole_mqtt|Le protocole MQTT]] | [[protocole_mqtt|Le protocole MQTT]] | ||
- | === Installation des outils MOSQUITTO | + | ===== APPLICATION ===== |
- | Ici les éléments d' | + | === Configuration du RaspberryPI |
- | [[https:// | + | |
- | === Application | + | Sur la PI installation de |
+ | * Mosquitto [[corinne_dadat# | ||
+ | * Node-REd [[node-red|Node-Red]] | ||
+ | * HostApd pour le wifi [[http:// | ||
- | J'ai fait le choix d' | + | Notes : |
+ | Par défaut je n'ai rien modifié dans la configuration de mosquitto. | ||
- | ===== La passerelle MQTT <--> MESH ===== | + | Ajout du dashboard dans Node-Red. |
+ | Exemple de flow pour Node-Red | ||
- | ===== NODE-RED ===== | + | {{ pliboo-02: |
+ | |||
+ | {{media_07: | ||
+ | |||
+ | 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: | ||
+ | |||
+ | **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** | ||
+ | |||
+ | < | ||
+ | [{" | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | La partie iptable n'est pas mise en oeuvre du fait d'un changement dans Buster [[https:// | ||
+ | |||
+ | |||
+ | ===== Autres ressources | ||
Installation de node-red sur Raspbian [[https:// | Installation de node-red sur Raspbian [[https:// | ||
Ligne 74: | Ligne 127: | ||
{{tag> | {{tag> | ||
- | ===== Config du RaspberryPI | ||
- | Doc ici pour la mise en place du hotspot WIFI [[http:// | ||
- | La partie iptable | + | ===== La passerelle MQTT <--> MESH ===== |
+ | |||
+ | Réalisée avec un ESP8266. | ||
+ | Doit se connecter au MESH et au Broker pour assurer la passerelle. | ||
+ | < | ||
+ | // | ||
+ | // 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 < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | # | ||
+ | # | ||
+ | # | ||
+ | |||
+ | # | ||
+ | # | ||
+ | |||
+ | #define HOSTNAME " | ||
+ | |||
+ | // Prototypes | ||
+ | void receivedCallback( const uint32_t &from, const String &msg ); | ||
+ | void mqttCallback(char* topic, byte* payload, unsigned int length); | ||
+ | |||
+ | IPAddress getlocalIP(); | ||
+ | |||
+ | IPAddress myIP(0, | ||
+ | IPAddress mqttBroker(192, | ||
+ | boolean ErreurBroker = true; | ||
+ | |||
+ | |||
+ | painlessMesh | ||
+ | WiFiClient wifiClient; | ||
+ | PubSubClient mqttClient(mqttBroker, | ||
+ | |||
+ | 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.onReceive(& | ||
+ | |||
+ | mesh.stationManual(STATION_SSID, | ||
+ | mesh.setHostname(HOSTNAME); | ||
+ | |||
+ | // Bridge node, should (in most cases) be a root node. See [the wiki](https:// | ||
+ | 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' | ||
+ | myIP = getlocalIP(); | ||
+ | if (!mqttClient.connected() ) { //pas de connexion au Broker | ||
+ | if (mqttClient.connect(" | ||
+ | // si connexion établie | ||
+ | mqttClient.publish(" | ||
+ | mqttClient.subscribe(" | ||
+ | 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(" | ||
+ | String topic = " | ||
+ | mqttClient.publish(topic.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, | ||
+ | String msg = String(cleanPayload); | ||
+ | free(cleanPayload); | ||
+ | |||
+ | String targetStr = String(topic).substring(16); | ||
+ | |||
+ | if(targetStr == " | ||
+ | { | ||
+ | if(msg == " | ||
+ | { // renvoi les informations sur les noeuds connectés si | ||
+ | // message | ||
+ | auto nodes = mesh.getNodeList(true); | ||
+ | String str; | ||
+ | for (auto && | ||
+ | str += String(id) + String(" | ||
+ | mqttClient.publish(" | ||
+ | } | ||
+ | } | ||
+ | else if(targetStr == " | ||
+ | { | ||
+ | mesh.sendBroadcast(msg); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | uint32_t target = strtoul(targetStr.c_str(), | ||
+ | if(mesh.isConnected(target)) | ||
+ | { | ||
+ | mesh.sendSingle(target, | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | mqttClient.publish(" | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | IPAddress getlocalIP() { | ||
+ | return IPAddress(mesh.getStationIP()); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== Noeud du MESH ===== | ||
+ | |||
+ | Réalisée avec un ESP8266 avec deux relais dans mon cas. | ||
+ | Doit se connecter au MESH de manière automatique. | ||
+ | |||
+ | L' | ||
+ | |||
+ | La fonction **receivedCallback** est appelé en cas de reception | ||
+ | |||
+ | L' | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | < | ||
+ | // | ||
+ | // Exemple d' | ||
+ | // 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 | ||
+ | // 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 " | ||
+ | |||
+ | # | ||
+ | # | ||
+ | # | ||
+ | |||
+ | # | ||
+ | #define MAX_RELAIS_ON 3 | ||
+ | |||
+ | int etatRelais; // code l' | ||
+ | |||
+ | |||
+ | |||
+ | String message; | ||
+ | |||
+ | Scheduler userScheduler; | ||
+ | painlessMesh | ||
+ | |||
+ | void maj_Relais() ; // Prototype pour le traitement des relais | ||
+ | |||
+ | Task taskRelais( TASK_SECOND * 1 , TASK_FOREVER, | ||
+ | |||
+ | void maj_Relais() { | ||
+ | // | ||
+ | //cette fonction dépend du type de carte | ||
+ | for (int cpt=1; | ||
+ | |||
+ | 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: | ||
+ | | ||
+ | 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: | ||
+ | // | ||
+ | Serial.write(0xA0); | ||
+ | Serial.write(0x01); | ||
+ | Serial.write(0x00); | ||
+ | Serial.write(0xA1); | ||
+ | delay(10); | ||
+ | break; | ||
+ | case 2: | ||
+ | // | ||
+ | Serial.write(0xA0); | ||
+ | Serial.write(0x02); | ||
+ | Serial.write(0x00); | ||
+ | Serial.write(0xA2); | ||
+ | delay(10); | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | // User stub | ||
+ | void sendMessage() ; // Prototype so PlatformIO doesn' | ||
+ | |||
+ | |||
+ | Task taskSendMessage( TASK_SECOND * 1 , TASK_FOREVER, | ||
+ | |||
+ | void sendMessage() { | ||
+ | |||
+ | String msg = " | ||
+ | |||
+ | 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 ) { | ||
+ | // | ||
+ | | ||
+ | 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, | ||
+ | } | ||
+ | else { | ||
+ | if (cpt> | ||
+ | fin =true; | ||
+ | cpt=-1; | ||
+ | } | ||
+ | else { | ||
+ | cpt++; | ||
+ | |||
+ | } | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | if (msg==" | ||
+ | | ||
+ | etatRelais=MAX_RELAIS_ON; | ||
+ | message= message + " | ||
+ | } else | ||
+ | if (msg==" | ||
+ | etatRelais=0; | ||
+ | message= message + " | ||
+ | } else | ||
+ | if (msg==" | ||
+ | etatRelais=(etatRelais | valeur ); | ||
+ | message= message + " | ||
+ | } else | ||
+ | if (msg==" | ||
+ | etatRelais=(etatRelais & (~valeur) ); | ||
+ | message= message + " | ||
+ | } | ||
+ | else if (msg==" | ||
+ | // | ||
+ | message=" | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void newConnectionCallback(uint32_t nodeId) { | ||
+ | // | ||
+ | } | ||
+ | |||
+ | void changedConnectionCallback() { | ||
+ | //Serial.printf(" | ||
+ | } | ||
+ | |||
+ | void nodeTimeAdjustedCallback(int32_t offset) { | ||
+ | ////Serial.printf(" | ||
+ | } | ||
+ | |||
+ | void setup() { | ||
+ | // | ||
+ | // | ||
+ | Serial.begin(115200, | ||
+ | etatRelais = 0; //relais tous au repos | ||
+ | |||
+ | |||
+ | // | ||
+ | mesh.setDebugMsgTypes( ERROR | STARTUP ); // set before init() so that you can see startup messages | ||
+ | |||
+ | mesh.init( MESH_PREFIX, | ||
+ | // | ||
+ | mesh.onReceive(& | ||
+ | mesh.onNewConnection(& | ||
+ | mesh.onChangedConnections(& | ||
+ | mesh.onNodeTimeAdjusted(& | ||
+ | |||
+ | |||
+ | userScheduler.addTask( taskSendMessage ); | ||
+ | taskSendMessage.enable(); | ||
+ | |||
+ | userScheduler.addTask( taskRelais ); | ||
+ | taskRelais.enable(); | ||
+ | } | ||
+ | void loop() { | ||
+ | // tâche utilisateur et tâche mesh | ||
+ | userScheduler.execute(); | ||
+ | mesh.update(); | ||
+ | } | ||
+ | </ | ||
+ | {{tag> |
mesh_et_mqtt.txt · Dernière modification : 2020/10/29 13:58 de serge