Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
tutos:mqtt [2018/10/19 05:31] – ygangat | tutos:mqtt [2020/11/02 11:45] (Version actuelle) – [Raspberry Pi : Installation du broker] mdelsaut | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | ====== MQTT ====== | + | ====== MQTT (mosquitto) |
- | <note important> | + | Fait : |
+ | - [x] Comparatif | ||
+ | - [x] MQTT sur Raspberry Pi | ||
+ | - [x] MQTT sur Arduino | ||
+ | - [x] Relay + Capteur courant | ||
+ | - [x] MQTT et Node-Red | ||
+ | - [X] MQTT & InfluxDB | ||
+ | - [X] MQTT & Java | ||
+ | <WRAP center round important 60%> | ||
+ | L' | ||
+ | </ | ||
+ | |||
+ | //(Note : ces informations ont été compilées à partir de différentes sources anglaises/ | ||
+ | |||
+ | ===== Les technologies ===== | ||
+ | |||
+ | Il existe deux types d' | ||
+ | - **Request/ | ||
+ | - **Publish/ | ||
+ | |||
+ | Avantages et Inconvénients : [[https:// | ||
+ | |||
+ | ==== Request/ | ||
+ | |||
+ | === CoAP (Constrained Application Protocol) === | ||
+ | |||
+ | CoAP reprend les concepts du protocole HTTP en s’appuyant sur le protocole UDP et en allégeant les communications (paquet plus petit notamment) | ||
+ | |||
+ | Infos : [[https:// | ||
+ | |||
+ | **Points clefs**: | ||
+ | - Request/ | ||
+ | - UDP/IP Based | ||
+ | - QoS Support | ||
+ | - Supports Unicast as well as Multicast | ||
+ | - Uses DTLS for Security | ||
+ | - Supports Resource Discovery | ||
+ | - CoAP Node plays Server Role too (NAT Issues) | ||
+ | - Decentralised (No Single Point of Failure) | ||
+ | |||
+ | === REST/HTTP === | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | Le gros désavantage du REST est qu'il s'agit d'une connexion à un seul sens. | ||
+ | |||
+ | Infos : [[https:// | ||
+ | |||
+ | **Points clés**: | ||
+ | - Request/ | ||
+ | - TCP/IP Based | ||
+ | - No QoS Support | ||
+ | - Complex Implementation at Client Side | ||
+ | - Larger Header compared to other IoT Protocols (Higher Bandwidth Requirement) | ||
+ | - Uses SSL/TLS for Security | ||
+ | |||
+ | ==== Publish/ | ||
+ | |||
+ | === MQTT (Message Queuing Telemetry Transport) === | ||
+ | |||
+ | MQTT est un protocole de messagerie spécifiquement conçu pour des applications M2M (Machine To Machine) et IoT (Internet of Things), à cause notamment de sa légèreté (peu de consommation de bande passante et d' | ||
+ | |||
+ | De plus, il permet la publication des nouvelles données en temps, sans nécessiter d' | ||
+ | |||
+ | MQTT offre une Qualité de service (QoS) à 3 niveaux : | ||
+ | - **QoS 0** : transmission de message sans accusé de réception | ||
+ | - **QoS 1** : transmission de message avec accusé de réception | ||
+ | - **QoS 2** : transmission de message avec accusé de réception et vérification du message transmis afin d’éviter qu’un même message ne soit pas transmis de nombreuses fois. | ||
+ | |||
+ | MQTT-SN (MQTT for Sensor Network) est une version optimisée pour les objets à très faibles ressources communiquant sans fil. | ||
+ | |||
+ | **Points clés** : | ||
+ | - Publish/ | ||
+ | - Light Weight (Min Header Size: 2 Bytes) | ||
+ | - TCP/IP Based | ||
+ | - QoS Support | ||
+ | - Payload Agnostic | ||
+ | - Uses SSL/TLS for Security | ||
+ | - Broker could be Single Point of Failure | ||
+ | |||
+ | === XMPP (Extensible Messaging and Presence Protocol) === | ||
+ | |||
+ | XMPP est à la base un protocole pour la messagerie instantanée (Jabber, iChat, ICQ, MSN, Google Talk, etc.), mais elle a été conçue de manière plus large et ouverte qu'une simple messagerie instantanée populaire et propriétaire. Cela lui permet de supporter aussi bien l’architecture request/ | ||
+ | |||
+ | * Publish/ | ||
+ | * Widely used for Instant Messaging, Presence, Voice/Video Calls etc. | ||
+ | * No QoS Support | ||
+ | * Text Based Communication (XML Payload) | ||
+ | * Secure Authentication (SASL) and TLS Based Security | ||
+ | * XML Payload creation and parsing may need extra compute and battery power. | ||
+ | |||
+ | === AMQP (Advanced Message Queuing Protocol) === | ||
+ | |||
+ | AMQP est similaire à MQTT, à la différence prêt qu'il gère une file d' | ||
+ | |||
+ | **Points clés** : | ||
+ | - Point to Point Message Exchange (Server to Server) | ||
+ | - Flexible Messaging Patterns | ||
+ | - TCP/IP Based | ||
+ | - Smallest Packet Size: 60 Bytes | ||
+ | - QoS Support | ||
+ | - Uses SSL/TLS for Security | ||
+ | |||
+ | ==== Autres types de communications ==== | ||
+ | |||
+ | === DDS (Data Distribution Service): P2P, PubSup, ReqRep === | ||
+ | |||
+ | DDS a l' | ||
+ | |||
+ | **Points clés** : | ||
+ | - Publish/ | ||
+ | - Relational data modeling | ||
+ | - QoS Support | ||
+ | - Multicast support over plain UDP sockets | ||
+ | - Leverages both TCP/IP and UDP/IP Transport | ||
+ | - Uses TLS and DTLS for Security | ||
+ | - Decentralised (No Single Point of Failure) | ||
+ | |||
+ | ==== Résumé ==== | ||
+ | |||
+ | {{https:// | ||
+ | |||
+ | ===== Le choix ===== | ||
+ | |||
+ | Au vu des différentes options qui s' | ||
+ | |||
+ | MQTT est un [[https:// | ||
+ | |||
+ | Pour rappel, dans un système MQTT complet nous retrouvons quatre notions importantes : | ||
+ | - Les publishers : L’origine des messages | ||
+ | - Les subscribers : La destination des messages | ||
+ | - Le broker : L’élément qui fait le lien entre les publishers et les subscribers | ||
+ | - Les topics : Canaux de communications. | ||
+ | |||
+ | > Message Queue Telemetry Transport, MQTT pour abréger, est un protocole de messagerie utile dans la communication entre les dispositifs de l' | ||
+ | |||
+ | > Le MQTT utilise un paradigme de publication-abonnement. Nous comprenons tous les connexions point à point entre les pairs. C'est la base des conversations téléphoniques entre deux personnes. La connexion client-serveur est un autre liaison point à point bien connu. Pour afficher une page Web, un navigateur, qui est le client, demande la page à un serveur HTML qui peut envoyer la page ou qui peut refuser de le faire. Dans ces types de liens, chaque partie doit adresser ses messages à son interlocuteur intentionnellement. Avec MQTT, les dispositifs peuvent publier des données ou s' | ||
+ | |||
+ | > L' | ||
+ | |||
+ | {{https:// | ||
+ | |||
+ | > Le climatiseur est enregistré auprès du serveur MQTT pour recevoir toutes les messages au sujet de la «température» et de l' | ||
+ | |||
+ | > Toutes les dix minutes, le capteur de température publie la température ambiante. Dans la pratique, cela signifie qu'il envoie un seul numéro, disons 23, sous le sujet «température» au courtier MQTT, pour qu'il fait actuellement 23°C. De même, toutes les quinze minutes, le capteur d' | ||
+ | |||
+ | > Un programme de domotique qui prend en charge le protocole MQTT peut être ajouté au système pour fournir " | ||
+ | |||
+ | {{https:// | ||
+ | |||
+ | > Comme auparavant, les capteurs de température et d' | ||
+ | |||
+ | //Source : https: | ||
+ | |||
+ | ===== Pratique ===== | ||
+ | |||
+ | Dans cette partie, nous allons créer un broker sur un Raspberry Pi et les publishers seront des Arduino. | ||
+ | |||
+ | ==== Raspberry Pi : Préparation de la carte SD ==== | ||
+ | |||
+ | * Télécharger la [[http:// | ||
+ | * Télécharger [[http:// | ||
+ | * [[https:// | ||
+ | |||
+ | ==== Raspberry Pi : Installation et sécurisation ==== | ||
+ | |||
+ | Pour une configuration " | ||
+ | - **Activer la connexion SSH** en créant un fichier '' | ||
+ | - **Créer un fichier '' | ||
+ | |||
+ | < | ||
+ | country=fr | ||
+ | update_config=1 | ||
+ | ctrl_interface=/ | ||
+ | |||
+ | network={ | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | Remarque : | ||
+ | - // | ||
+ | - Faire '' | ||
+ | |||
+ | < | ||
+ | interface wlan0 | ||
+ | static ip_address=192.168.1.2/ | ||
+ | static routers=192.168.1.1 | ||
+ | static domain_name_servers=192.168.1.1 | ||
+ | </ | ||
+ | * | ||
+ | * Au besoin désactiver le ipV6 en éditant le faisant '' | ||
+ | * Faire ensuite '' | ||
+ | * **Configurer raspberry** avec '' | ||
+ | * Changer les options de localisations (FR etc.) | ||
+ | * '' | ||
+ | * '' | ||
+ | * **Changer le mot de passe** par défaut : '' | ||
+ | * **Mettre à jour la date du Raspberry** : | ||
+ | * Faire '' | ||
+ | * //Editer le fichier '' | ||
+ | * // | ||
+ | * Faire '' | ||
+ | * Faire '' | ||
+ | * Au besoin, supprimer l' | ||
+ | -remove-home pi%%'' | ||
+ | --lock pi%%'' | ||
+ | * // | ||
+ | * Interdire l' | ||
+ | * Obliger le mot de passe pour les '' | ||
+ | * Forcer l' | ||
+ | * Installer un firewall ('' | ||
+ | * Installer '' | ||
+ | |||
+ | ==== Raspberry Pi : Installation du broker ==== | ||
+ | |||
+ | L' | ||
+ | |||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | -c / | ||
+ | < | ||
+ | < | ||
+ | allow_anonymous false | ||
+ | password_file / | ||
+ | </ | ||
+ | Ensuite il faut faire : < | ||
+ | < | ||
+ | Faire '' | ||
+ | < | ||
+ | |||
+ | Nous interdisons l’accès en anonyme et nous allons autoriser les connexions uniquement avec un identifiant mot de passe (dont la liste se trouve le fichier '' | ||
+ | |||
+ | // | ||
+ | -b passwordfile user password%%'' | ||
+ | |||
+ | * Pour tester la connexion depuis un autre appareil, il est possible d' | ||
+ | |||
+ | ==== Rappel : Fonctionnement des flux ==== | ||
+ | |||
+ | //Source : https: | ||
+ | |||
+ | Les sujets/ | ||
+ | |||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | Pour des raisons évidentes, vous ne pouvez pas avoir un des caractères '' | ||
+ | |||
+ | Lors du débogage de la communication avec un serveur MQTT, il peut s' | ||
+ | -h 192.168.0.22 | ||
+ | -v | ||
+ | -t "#" | ||
+ | |||
+ | ==== Arduino : Matériel ==== | ||
+ | |||
+ | Dans notre cas, nous avons utilisé : | ||
+ | - Un [[https:// | ||
+ | - Un [[https:// | ||
+ | - Un [[http:// | ||
+ | - LCD RGB Backlight]] | ||
+ | - Un [[https:// | ||
+ | |||
+ | Le //Grove | ||
+ | - LCD RGB Backlight// est branché sur le 1er port //I2C// du //Grove Base Shield//. Ce dernier (mis sous 5V) a été placé entre le //WiFi Shield// et l'// | ||
+ | |||
+ | L'// | ||
+ | - à l’extérieur). | ||
+ | |||
+ | Les //Adafruit ATWINC1500 WiFi Shield// ont été mis à jour avec le dernier firmware (Voir [[https:// | ||
+ | |||
+ | Un réseau wifi (avec le ssid '' | ||
+ | |||
+ | ==== Arduino : Configuration ==== | ||
+ | |||
+ | Il est important de bien configurer l'IDE et d' | ||
+ | - Librairies : | ||
+ | - WiFi101 | ||
+ | - Adafruit IO Arduino | ||
+ | - Grove | ||
+ | - LCD RGB Backlight | ||
+ | - Pubsubclient //<- non utilisé// | ||
+ | - Configuration : | ||
+ | - Type de carte : **Arduino/ | ||
+ | - Serial : **9600 baud** | ||
+ | |||
+ | ==== Arduino : Code ==== | ||
+ | |||
+ | Le déroulement du programme est le suivant : | ||
+ | - Imports & Initialisations | ||
+ | - Connexion au Wifi | ||
+ | - Inscription au flux '' | ||
+ | - Boucle : | ||
+ | - Connexion au serveur MQTT (si non connecté ou si déconnexion) | ||
+ | - Ecoute au flux '' | ||
+ | - Publication d'un entier (croissant au fur et à mesure) sur le flux '' | ||
+ | |||
+ | Le code du programme '' | ||
+ | |||
+ | <code c> | ||
+ | / | ||
+ | Adafruit MQTT Library WINC1500 Modified by Yassine | ||
+ | |||
+ | Demo written by Limor Fried/ | ||
+ | Modified by Yassine Gangat for LE²P. | ||
+ | |||
+ | MIT license, all text above must be included in any redistribution | ||
+ | | ||
+ | #include < | ||
+ | #include " | ||
+ | #include " | ||
+ | #include < | ||
+ | |||
+ | // | ||
+ | ---------------------------- GROVE LCD Lib | ||
+ | ------------------------- | ||
+ | //#include < | ||
+ | #include " | ||
+ | |||
+ | #include " | ||
+ | /////// | ||
+ | const char ssid[] = SECRET_SSID; | ||
+ | const char pass[] = SECRET_PASS; | ||
+ | int status = WL_IDLE_STATUS; | ||
+ | // int keyIndex = 0; // your network key Index number (needed only for WEP) | ||
+ | |||
+ | / | ||
+ | |||
+ | #define SERVER | ||
+ | #define SERVERPORT | ||
+ | #define USERNAME | ||
+ | #define PWD " | ||
+ | |||
+ | / | ||
+ | |||
+ | //Set up the wifi client & Adafruit MQTT Client | ||
+ | WiFiClient client; | ||
+ | Adafruit_MQTT_Client mqtt(& | ||
+ | |||
+ | #define halt(s) { Serial.println(F( s )); while(1); | ||
+ | |||
+ | / | ||
+ | |||
+ | // Setup a feed called ' | ||
+ | // Notice MQTT paths for AIO follow the form: < | ||
+ | Adafruit_MQTT_Publish numbers = Adafruit_MQTT_Publish(& | ||
+ | |||
+ | // Setup a feed called ' | ||
+ | Adafruit_MQTT_Subscribe onoffmsg = Adafruit_MQTT_Subscribe(& | ||
+ | |||
+ | |||
+ | |||
+ | / | ||
+ | |||
+ | // | ||
+ | --------------------------- Variables & others | ||
+ | -------------------------------- | ||
+ | rgb_lcd lcd; | ||
+ | byte heart[8] = { | ||
+ | 0b00000, | ||
+ | 0b01010, | ||
+ | 0b11111, | ||
+ | 0b11111, | ||
+ | 0b11111, | ||
+ | 0b01110, | ||
+ | 0b00100, | ||
+ | 0b00000 | ||
+ | }; | ||
+ | |||
+ | void setup() { | ||
+ | // | ||
+ | ------------------------- Initialization Serial | ||
+ | ------------------------------ | ||
+ | while (!Serial); | ||
+ | Serial.begin(9600); | ||
+ | |||
+ | Serial.println(F(" | ||
+ | |||
+ | // | ||
+ | ---------------------- Initialization Wifi WINC1500 | ||
+ | -------------------------- | ||
+ | // Initialise the Client | ||
+ | Serial.print(F(" | ||
+ | // check for the presence of the breakout | ||
+ | if (WiFi.status() == WL_NO_SHIELD) { | ||
+ | Serial.println(F(" | ||
+ | // don't continue: | ||
+ | while (true); | ||
+ | } | ||
+ | Serial.println(F(" | ||
+ | |||
+ | // | ||
+ | ------------------------------ Physical part | ||
+ | ---------------------------------- | ||
+ | |||
+ | Serial.println(F(" | ||
+ | // set up the LCD's number of columns and rows: | ||
+ | lcd.begin(16, | ||
+ | |||
+ | // Print a message to the LCD. | ||
+ | #if 1 | ||
+ | lcd.createChar(0, | ||
+ | #endif | ||
+ | lcd.setCursor(0, | ||
+ | lcd.print(F(" | ||
+ | lcd.write((unsigned char)0); | ||
+ | lcd.setCursor(0, | ||
+ | lcd.print(F(" | ||
+ | |||
+ | // | ||
+ | --------------------------- Variables & others | ||
+ | -------------------------------- | ||
+ | mqtt.subscribe(& | ||
+ | } | ||
+ | |||
+ | uint32_t x = 0; | ||
+ | |||
+ | void loop() { | ||
+ | // | ||
+ | ------------------------------ MQTT Connection | ||
+ | -------------------------------- | ||
+ | // Ensure the connection to the MQTT server is alive (this will make the first | ||
+ | // connection and automatically reconnect when disconnected). | ||
+ | MQTT_connect(); | ||
+ | lcd.setRGB(255, | ||
+ | // | ||
+ | ------------------------------ Subscription | ||
+ | ----------------------------------- | ||
+ | Adafruit_MQTT_Subscribe *subscription; | ||
+ | while ((subscription = mqtt.readSubscription(5000))) { | ||
+ | if (subscription == & | ||
+ | Serial.print(F(" | ||
+ | Serial.println((char *)onoffmsg.lastread); | ||
+ | |||
+ | if (0 == strcmp((char *)onoffmsg.lastread, | ||
+ | lcd.setRGB(255, | ||
+ | lcd.setCursor(0, | ||
+ | lcd.print(F(" | ||
+ | } | ||
+ | if (0 == strcmp((char *)onoffmsg.lastread, | ||
+ | lcd.setRGB(0, | ||
+ | lcd.setCursor(0, | ||
+ | lcd.print(F(" | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // | ||
+ | ------------------------------ Publication | ||
+ | ---------------------------------- | ||
+ | Serial.print(F(" | ||
+ | Serial.print(x); | ||
+ | lcd.setCursor(0, | ||
+ | lcd.print(F(" | ||
+ | lcd.setCursor(8, | ||
+ | lcd.print(x); | ||
+ | |||
+ | if (! numbers.publish(x++)) { | ||
+ | Serial.println(F(" | ||
+ | } else { | ||
+ | Serial.println(F(" | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | // Function to connect and reconnect as necessary to the MQTT server. | ||
+ | // Should be called in the loop function and it will take care if connecting. | ||
+ | void MQTT_connect() { | ||
+ | int8_t ret; | ||
+ | |||
+ | // attempt to connect to Wifi network: | ||
+ | while (WiFi.status() != WL_CONNECTED) { | ||
+ | Serial.print(F(" | ||
+ | Serial.println(ssid); | ||
+ | // Connect to WPA/WPA2 network. Change this line if using open or WEP network: | ||
+ | status = WiFi.begin(ssid, | ||
+ | |||
+ | // wait 10 seconds for connection: | ||
+ | uint8_t timeout = 10; | ||
+ | while (timeout && (WiFi.status() != WL_CONNECTED)) { | ||
+ | timeout--; | ||
+ | delay(1000); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Stop if already connected. | ||
+ | if (mqtt.connected()) { | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | Serial.print(F(" | ||
+ | |||
+ | while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected | ||
+ | Serial.println(mqtt.connectErrorString(ret)); | ||
+ | Serial.println(ret); | ||
+ | Serial.println(F(" | ||
+ | mqtt.disconnect(); | ||
+ | delay(5000); | ||
+ | } | ||
+ | Serial.println(F(" | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | Remarques sur ce code : | ||
+ | - Le '' | ||
+ | - Le mot de passe du wifi est stocké dans '' | ||
+ | - Dès que la mémoire dynamique (vive) est utilisée à plus de 80%, il y a des soucis de connexion au wifi comme au MQTT. | ||
+ | - La solution la plus rapide pour diminuer ce nombre a été de remplacer '' | ||
+ | - Une autre solution est de mettre '' | ||
+ | - Une solution plus complexe, mais envisageable à la fin est d' | ||
+ | - Sachant que les '' | ||
+ | - de le supprimer lorsque tout fonctionne | ||
+ | - d' | ||
+ | |||
+ | <code cpp> | ||
+ | #define DEBUG //que l'on commente avant de téléverser | ||
+ | </ | ||
+ | puis dans le code... | ||
+ | |||
+ | <code cpp> | ||
+ | #ifdef DEBUG | ||
+ | Serial.prinlln(F(" | ||
+ | #endif | ||
+ | </ | ||
+ | Plus d' | ||
+ | - En français sur [[https:// | ||
+ | - En anglais sur [[https:// | ||
+ | |||
+ | Le fichier '' | ||
+ | |||
+ | <code c> | ||
+ | #define SECRET_SSID " | ||
+ | #define SECRET_PASS " | ||
+ | </ | ||
+ | ===== Application ===== | ||
+ | |||
+ | ==== Test préliminaire ==== | ||
+ | |||
+ | Pour la suite du test, nous avons fait le montage suivant sur le Arduino : | ||
+ | - Nous avons branché un [[https:// | ||
+ | |||
+ | {{http:// | ||
+ | |||
+ | * Nous avons utilisé un [[http:// | ||
+ | |||
+ | {{https:// | ||
+ | |||
+ | <code c> | ||
+ | // Initialise the Arduino data pins for INPUT/ | ||
+ | const int analogInPin = A0; | ||
+ | const int RELAY1 = 7; | ||
+ | |||
+ | void setup() { | ||
+ | pinMode(RELAY1, | ||
+ | Serial.begin(9600); | ||
+ | Serial.println(" | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | digitalWrite(RELAY1, | ||
+ | Serial.println(" | ||
+ | ----------------------" | ||
+ | delay(5000); | ||
+ | mesure(analogInPin); | ||
+ | delay(5000); | ||
+ | |||
+ | digitalWrite(RELAY1, | ||
+ | Serial.println(" | ||
+ | -----------------------" | ||
+ | delay(2000); | ||
+ | mesure(analogInPin); | ||
+ | delay(2000); | ||
+ | Serial.println(" | ||
+ | |||
+ | } | ||
+ | |||
+ | void mesure(int analogPin) { | ||
+ | |||
+ | float sensorValue = 0; // value read from the pot | ||
+ | // read the analog in value: | ||
+ | sensorValue = analogRead(analogPin); | ||
+ | // map it to the range of the analog out: | ||
+ | |||
+ | Serial.print(" | ||
+ | Serial.println(sensorValue); | ||
+ | sensorValue = ((sensorValue | ||
+ | - 506) * 5 / 1024 / 0.066); | ||
+ | // print the results to the serial monitor: | ||
+ | Serial.print(" | ||
+ | Serial.println(sensorValue); | ||
+ | Serial.print(" | ||
+ | Serial.println(map(sensorValue, | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | ==== Modification ==== | ||
+ | |||
+ | Ensuite nous avons modifié le code original de notre Arduino (voir [[# | ||
+ | - Le relai s' | ||
+ | - Le capteur permet de mesurer le courant que nous ferons varier avec un potentiomètre. L' | ||
+ | |||
+ | Nous avons donc le code suivant : | ||
+ | |||
+ | <code c> | ||
+ | / | ||
+ | Adafruit MQTT Library WINC1500 Modified by Yassine | ||
+ | |||
+ | Demo written by Limor Fried/ | ||
+ | Modified by Yassine Gangat for LE²P. | ||
+ | |||
+ | MIT license, all text above must be included in any redistribution | ||
+ | | ||
+ | #include < | ||
+ | #include " | ||
+ | #include " | ||
+ | #include < | ||
+ | |||
+ | // | ||
+ | ---------------------------- GROVE LCD Lib | ||
+ | ------------------------- | ||
+ | //#include < | ||
+ | #include " | ||
+ | |||
+ | #include " | ||
+ | /////// | ||
+ | const char ssid[] = SECRET_SSID; | ||
+ | const char pass[] = SECRET_PASS; | ||
+ | int status = WL_IDLE_STATUS; | ||
+ | // int keyIndex = 0; // your network key Index number (needed only for WEP) | ||
+ | |||
+ | // Initialise the Arduino data pins for INPUT/ | ||
+ | const int analogInPin = A0; | ||
+ | const int RELAY2 = 8; | ||
+ | const int mVperAmp = 185; // use 100 for 20A Module and 66 for 30A Module | ||
+ | |||
+ | |||
+ | / | ||
+ | |||
+ | #define SERVER | ||
+ | #define SERVERPORT | ||
+ | #define USERNAME | ||
+ | #define PWD " | ||
+ | |||
+ | / | ||
+ | |||
+ | //Set up the wifi client & Adafruit MQTT Client | ||
+ | WiFiClient client; | ||
+ | Adafruit_MQTT_Client mqtt(& | ||
+ | |||
+ | #define halt(s) { Serial.println(F( s )); while(1); | ||
+ | |||
+ | / | ||
+ | |||
+ | // Setup a feed called ' | ||
+ | // Notice MQTT paths for AIO follow the form: < | ||
+ | Adafruit_MQTT_Publish numbers = Adafruit_MQTT_Publish(& | ||
+ | |||
+ | // Setup a feed called ' | ||
+ | Adafruit_MQTT_Subscribe onoffmsg = Adafruit_MQTT_Subscribe(& | ||
+ | |||
+ | |||
+ | |||
+ | / | ||
+ | |||
+ | // | ||
+ | --------------------------- Variables & others | ||
+ | -------------------------------- | ||
+ | rgb_lcd lcd; | ||
+ | byte heart[8] = { | ||
+ | 0b00000, | ||
+ | 0b01010, | ||
+ | 0b11111, | ||
+ | 0b11111, | ||
+ | 0b11111, | ||
+ | 0b01110, | ||
+ | 0b00100, | ||
+ | 0b00000 | ||
+ | }; | ||
+ | |||
+ | void setup() { | ||
+ | // | ||
+ | ------------------------- Initialization Serial | ||
+ | ------------------------------ | ||
+ | while (!Serial); | ||
+ | Serial.begin(9600); | ||
+ | |||
+ | Serial.println(F(" | ||
+ | |||
+ | // | ||
+ | ---------------------- Initialization Wifi WINC1500 | ||
+ | -------------------------- | ||
+ | // Initialise the Client | ||
+ | Serial.print(F(" | ||
+ | // check for the presence of the breakout | ||
+ | if (WiFi.status() == WL_NO_SHIELD) { | ||
+ | Serial.println(F(" | ||
+ | // don't continue: | ||
+ | while (true); | ||
+ | } | ||
+ | Serial.println(F(" | ||
+ | |||
+ | // | ||
+ | ------------------------------ Physical part | ||
+ | ---------------------------------- | ||
+ | |||
+ | Serial.println(F(" | ||
+ | // set up the LCD's number of columns and rows: | ||
+ | lcd.begin(16, | ||
+ | |||
+ | // Print a message to the LCD. | ||
+ | #if 1 | ||
+ | lcd.createChar(0, | ||
+ | #endif | ||
+ | lcd.setCursor(0, | ||
+ | lcd.print(F(" | ||
+ | lcd.write((unsigned char)0); | ||
+ | lcd.setCursor(0, | ||
+ | lcd.print(F(" | ||
+ | |||
+ | pinMode(RELAY2, | ||
+ | |||
+ | // | ||
+ | --------------------------- Variables & others | ||
+ | -------------------------------- | ||
+ | mqtt.subscribe(& | ||
+ | } | ||
+ | |||
+ | // uint32_t x = 0; | ||
+ | |||
+ | void loop() { | ||
+ | // | ||
+ | ------------------------------ MQTT Connection | ||
+ | -------------------------------- | ||
+ | // Ensure the connection to the MQTT server is alive (this will make the first | ||
+ | // connection and automatically reconnect when disconnected). | ||
+ | MQTT_connect(); | ||
+ | lcd.setRGB(255, | ||
+ | // | ||
+ | ------------------------------ Subscription | ||
+ | ----------------------------------- | ||
+ | Adafruit_MQTT_Subscribe *subscription; | ||
+ | while ((subscription = mqtt.readSubscription(5000))) { | ||
+ | if (subscription == & | ||
+ | Serial.print(F(" | ||
+ | Serial.println((char *)onoffmsg.lastread); | ||
+ | |||
+ | if (0 == strcmp((char *)onoffmsg.lastread, | ||
+ | lcd.setRGB(255, | ||
+ | lcd.setCursor(0, | ||
+ | lcd.print(F(" | ||
+ | digitalWrite(RELAY2, | ||
+ | } | ||
+ | if (0 == strcmp((char *)onoffmsg.lastread, | ||
+ | lcd.setRGB(0, | ||
+ | lcd.setCursor(0, | ||
+ | lcd.print(F(" | ||
+ | digitalWrite(RELAY2, | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // | ||
+ | ------------------------------ Publication | ||
+ | ---------------------------------- | ||
+ | |||
+ | Serial.print(F(" | ||
+ | Serial.print(mesure(analogInPin)); | ||
+ | lcd.setCursor(0, | ||
+ | lcd.print(F(" | ||
+ | lcd.setCursor(8, | ||
+ | lcd.print(mesure(analogInPin)); | ||
+ | |||
+ | if (! numbers.publish((uint32_t) mesure(analogInPin))) { | ||
+ | Serial.println(F(" | ||
+ | } else { | ||
+ | Serial.println(F(" | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | // Function to connect and reconnect as necessary to the MQTT server. | ||
+ | // Should be called in the loop function and it will take care if connecting. | ||
+ | void MQTT_connect() { | ||
+ | int8_t ret; | ||
+ | |||
+ | // attempt to connect to Wifi network: | ||
+ | while (WiFi.status() != WL_CONNECTED) { | ||
+ | Serial.print(F(" | ||
+ | Serial.println(ssid); | ||
+ | // Connect to WPA/WPA2 network. Change this line if using open or WEP network: | ||
+ | status = WiFi.begin(ssid, | ||
+ | |||
+ | // wait 10 seconds for connection: | ||
+ | uint8_t timeout = 10; | ||
+ | while (timeout && (WiFi.status() != WL_CONNECTED)) { | ||
+ | timeout--; | ||
+ | delay(1000); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Stop if already connected. | ||
+ | if (mqtt.connected()) { | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | Serial.print(F(" | ||
+ | |||
+ | while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected | ||
+ | Serial.println(mqtt.connectErrorString(ret)); | ||
+ | Serial.println(ret); | ||
+ | Serial.println(F(" | ||
+ | mqtt.disconnect(); | ||
+ | delay(5000); | ||
+ | } | ||
+ | Serial.println(F(" | ||
+ | } | ||
+ | double mesure(int analogPin) { | ||
+ | int RawValue= 0; | ||
+ | int ACSoffset = 2500; | ||
+ | double Voltage = 0; | ||
+ | double Amps = 0; | ||
+ | RawValue = analogRead(analogPin); | ||
+ | Voltage = (RawValue / 1024.0) * 5000; // Gets you mV | ||
+ | Amps = ((Voltage | ||
+ | - ACSoffset) / mVperAmp); | ||
+ | / | ||
+ | Serial.print(RawValue); | ||
+ | Serial.print(" | ||
+ | Serial.print(Voltage, | ||
+ | // the ' | ||
+ | Serial.print(" | ||
+ | Serial.println(Amps, | ||
+ | // the ' | ||
+ | delay(2500); | ||
+ | return(Voltage); | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | Remarque : | ||
+ | - on est toujours confronté au problème de mémoire dynamique. Dans les logs de téléversement de Arduino, si dans la phrase '' | ||
+ | |||
+ | ====== Bonus(es) ====== | ||
+ | |||
+ | ===== Accès à MQTT depuis l' | ||
+ | |||
+ | Il est possible d' | ||
+ | |||
+ | ===== MQTT et Node-RED ===== | ||
+ | |||
+ | Node-RED est un outil puissant pour construire des applications de l' | ||
+ | |||
+ | La vocation de cette solution est de permettre de lier aisément des sources de données à des composants de traitement, locaux ou distants, et de créer des chaines de valeurs en quelques clics. | ||
+ | |||
+ | Node-RED est compatible avec MQTT : [[https:// | ||
+ | |||
+ | ==== Installation Node-RED ==== | ||
+ | |||
+ | Sur le raspberry-pi, | ||
+ | -> Preferences | ||
+ | -> Recommended Software" | ||
+ | |||
+ | Si déjà installé, il est possible (voire préférable) de faire un '' | ||
+ | |||
+ | Node-RED peut fonctionner tel quel, cependant, pour pouvoir rajouter des modules, il faut avoir '' | ||
+ | -g%%'' | ||
+ | |||
+ | Une autre possibilité est de lancer la commande suivante, qui permet de faire tout ce qu'il y a à faire : '' | ||
+ | -sL https:// | ||
+ | |||
+ | {{https:// | ||
+ | |||
+ | ==== Démarrage ==== | ||
+ | |||
+ | Pour démarrer Node-RED dans **" | ||
+ | -> Programmation | ||
+ | -> Node-RED" | ||
+ | |||
+ | Remarque : | ||
+ | - Pour permettre d' | ||
+ | - On accéde à Node-RED avec http: | ||
+ | |||
+ | {{https:// | ||
+ | |||
+ | ==== Module Dashboard ==== | ||
+ | |||
+ | === Installation du module === | ||
+ | |||
+ | Pour contrôler nos objets MQTT, nous allons utiliser le module Dashboard. Pour cela: | ||
+ | - Aller dans le menu de Node-RED en haut à droite | ||
+ | - Cliquer sur //" | ||
+ | - Dans l' | ||
+ | |||
+ | === Configuration du module === | ||
+ | |||
+ | * Aller dans le menu de Node-RED en haut à droite | ||
+ | * Cliquer sur //" | ||
+ | -> Dashboard"// | ||
+ | * Cliquer sur **+tab** pour rajouter un écran, dans lequel on mette ensuite 2 groupes avec **+group** Note : On accéde à Node-RED avec http: | ||
+ | |||
+ | === Création de Nodes === | ||
+ | |||
+ | Une fois les nodes créés et liés, en cliquant sur **" | ||
+ | |||
+ | == Nodes MQTT == | ||
+ | |||
+ | * Faire un drag & drop d'un node MQTT **A** en input | ||
+ | * Le configurer : | ||
+ | * Configurer le serveur la première fois | ||
+ | * Configurer le topic %%// | ||
+ | * Faire un drag & drop d'un node MQTT **B** en output | ||
+ | * Le configurer : | ||
+ | * Résutiliser le même serveur | ||
+ | * Configurer le topic %%// | ||
+ | |||
+ | == Nodes Dashboard == | ||
+ | |||
+ | * Faire un drag & drop d'un node switch (input du dashboard) | ||
+ | * Le connecter avec l' | ||
+ | * Le configurer | ||
+ | * Mettre **ON** pour %%// | ||
+ | * Mettre **OFF** pour %%// | ||
+ | * Faire un drag & drop d'un node text (output du dashboard) | ||
+ | * Le connecter avec la sortie du node **A** | ||
+ | * Le configurer (on peut laisser ce qu'il y a par défaut) | ||
+ | * Faire un drag & drop d'un node chart (output du dashboard) | ||
+ | * Le connecter avec la sortie du node **A** | ||
+ | * Le configurer (on peut laisser ce qu'il y a par défaut) | ||
+ | |||
+ | == Pour test: == | ||
+ | |||
+ | Pour aller plus rapidement, il est possible de faire directement un import du code json du flow au lieu de créer les nodes précédents : | ||
+ | |||
+ | < | ||
+ | [ | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | } | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | } | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | [ | ||
+ | " | ||
+ | ] | ||
+ | ] | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | [ | ||
+ | " | ||
+ | " | ||
+ | ] | ||
+ | ] | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | ], | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | [], | ||
+ | [] | ||
+ | ] | ||
+ | } | ||
+ | ] | ||
+ | </ | ||
+ | ===== MQTT et InfluxDB ===== | ||
+ | |||
+ | En partant du principe que InfluxDB a été installé (voir [[https:// | ||
+ | |||
+ | <code bash> | ||
+ | [[inputs.mqtt_consumer]] | ||
+ | ## MQTT broker URLs to be used. The format should be scheme:// | ||
+ | ## schema can be tcp, ssl, or ws. | ||
+ | | ||
+ | |||
+ | ## MQTT QoS, must be 0, 1, or 2 | ||
+ | qos = 0 | ||
+ | ## Connection timeout for initial connection in seconds | ||
+ | | ||
+ | |||
+ | ## Topics to subscribe to | ||
+ | | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | ] | ||
+ | |||
+ | # if true, messages that can't be delivered while the subscriber is offline | ||
+ | # will be delivered when it comes back (such as on service restart). | ||
+ | # NOTE: if true, client_id MUST be set | ||
+ | | ||
+ | # If empty, a random client ID will be generated. | ||
+ | | ||
+ | |||
+ | ## username and password to connect MQTT server. | ||
+ | | ||
+ | | ||
+ | |||
+ | ## Optional SSL Config | ||
+ | # ssl_ca = "/ | ||
+ | # ssl_cert = "/ | ||
+ | # ssl_key = "/ | ||
+ | ## Use SSL but skip chain & host verification | ||
+ | # insecure_skip_verify = false | ||
+ | |||
+ | ## Data format to consume. | ||
+ | ## Each data format has its own unique set of configuration options, read | ||
+ | ## more about them here: | ||
+ | ## https:// | ||
+ | | ||
+ | | ||
+ | |||
+ | </ | ||
+ | Les valeurs sont ensuite stocké avec les tag appropriés (par exemple '' | ||
+ | |||
+ | //Exemple local de dashboard : http: | ||
+ | |||
+ | ===== MQTT et Java ===== | ||
+ | |||
+ | L' | ||
+ | |||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | On utilisera les variables suivantes : | ||
+ | |||
+ | <code java> | ||
+ | | ||
+ | | ||
+ | int qos = 2; | ||
+ | | ||
+ | </ | ||
+ | La création de la connexion au broker se fait comme suit : | ||
+ | |||
+ | <code java> | ||
+ | | ||
+ | </ | ||
+ | On peut rajouter des options de connexions comme suit : | ||
+ | |||
+ | <code java> | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | puis on se connecte avec : | ||
+ | |||
+ | <code java> | ||
+ | | ||
+ | </ | ||
+ | Pour publier un message, il suffit de faire : | ||
+ | |||
+ | <code java> | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | Pour souscrire à un topic, il faut créer une classe qui reçoit et traite les messages : | ||
+ | |||
+ | <code java> | ||
+ | // Latch used for synchronizing b/w threads | ||
+ | final CountDownLatch latch = new CountDownLatch(1); | ||
+ | |||
+ | // Topic filter the client will subscribe to | ||
+ | final String subTopic = " | ||
+ | |||
+ | // Callback | ||
+ | - Anonymous inner-class for receiving messages | ||
+ | | ||
+ | |||
+ | | ||
+ | // Called when a message arrives from the server that | ||
+ | // matches any subscription made by the client | ||
+ | | ||
+ | | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | | ||
+ | } | ||
+ | |||
+ | }); | ||
+ | |||
+ | // Subscribe client to the topic filter and a QoS level of 0 | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | // Wait for the message to be received | ||
+ | try { | ||
+ | | ||
+ | } catch (InterruptedException e) { | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | Un [[https:// | ||
+ | |||
+ | //Source : https: | ||
+ | |||
+ | ====== Code final ====== | ||
+ | |||
+ | ===== Arduino ===== | ||
+ | |||
+ | <code c> | ||
+ | / | ||
+ | Adafruit MQTT Library WINC1500 Modified by Yassine | ||
+ | |||
+ | Demo written by Limor Fried/ | ||
+ | Modified by Yassine Gangat for LE²P. | ||
+ | |||
+ | MIT license, all text above must be included in any redistribution | ||
+ | | ||
+ | #include < | ||
+ | #include " | ||
+ | #include " | ||
+ | #include < | ||
+ | |||
+ | // | ||
+ | ---------------------------- GROVE LCD Lib | ||
+ | ------------------------- | ||
+ | //#include < | ||
+ | #include " | ||
+ | |||
+ | #include " | ||
+ | /////// | ||
+ | const char ssid[] = SECRET_SSID; | ||
+ | const char pass[] = SECRET_PASS; | ||
+ | int status = WL_IDLE_STATUS; | ||
+ | // int keyIndex = 0; // your network key Index number (needed only for WEP) | ||
+ | |||
+ | // Initialise the Arduino data pins for INPUT/ | ||
+ | const int analogInPin = A0; | ||
+ | const int RELAY2 = 8; | ||
+ | const int mVperAmp = 185; // use 100 for 20A Module and 66 for 30A Module | ||
+ | |||
+ | |||
+ | / | ||
+ | |||
+ | #define SERVER | ||
+ | #define SERVERPORT | ||
+ | #define USERNAME | ||
+ | - CtrlLoad | ||
+ | - SolarPan | ||
+ | #define PWD " | ||
+ | |||
+ | / | ||
+ | |||
+ | //Set up the wifi client & Adafruit MQTT Client | ||
+ | WiFiClient client; | ||
+ | Adafruit_MQTT_Client mqtt(& | ||
+ | |||
+ | #define halt(s) { Serial.println(F( s )); while(1); | ||
+ | |||
+ | / | ||
+ | |||
+ | // Setup a feed called ' | ||
+ | // Notice MQTT paths for AIO follow the form: < | ||
+ | Adafruit_MQTT_Publish numbers = Adafruit_MQTT_Publish(& | ||
+ | |||
+ | // Setup a feed called ' | ||
+ | Adafruit_MQTT_Subscribe onoffmsg = Adafruit_MQTT_Subscribe(& | ||
+ | |||
+ | |||
+ | |||
+ | / | ||
+ | |||
+ | // | ||
+ | --------------------------- Variables & others | ||
+ | -------------------------------- | ||
+ | rgb_lcd lcd; | ||
+ | byte heart[8] = { | ||
+ | 0b00000, | ||
+ | 0b01010, | ||
+ | 0b11111, | ||
+ | 0b11111, | ||
+ | 0b11111, | ||
+ | 0b01110, | ||
+ | 0b00100, | ||
+ | 0b00000 | ||
+ | }; | ||
+ | |||
+ | void setup() { | ||
+ | // | ||
+ | ------------------------- Initialization Serial | ||
+ | ------------------------------ | ||
+ | while (!Serial); | ||
+ | Serial.begin(9600); | ||
+ | |||
+ | // Serial.println(F(" | ||
+ | |||
+ | // | ||
+ | ---------------------- Initialization Wifi WINC1500 | ||
+ | -------------------------- | ||
+ | // Initialise the Client | ||
+ | // Serial.print(F(" | ||
+ | // check for the presence of the breakout | ||
+ | if (WiFi.status() == WL_NO_SHIELD) { | ||
+ | Serial.println(F(" | ||
+ | // don't continue: | ||
+ | while (true); | ||
+ | } | ||
+ | // Serial.println(F(" | ||
+ | |||
+ | // | ||
+ | ------------------------------ Physical part | ||
+ | ---------------------------------- | ||
+ | |||
+ | // Serial.println(F(" | ||
+ | // set up the LCD's number of columns and rows: | ||
+ | lcd.begin(16, | ||
+ | |||
+ | // Print a message to the LCD. | ||
+ | #if 1 | ||
+ | lcd.createChar(0, | ||
+ | #endif | ||
+ | lcd.setCursor(0, | ||
+ | lcd.print(F(" | ||
+ | lcd.write((unsigned char)0); | ||
+ | lcd.setCursor(0, | ||
+ | lcd.print(F(" | ||
+ | |||
+ | pinMode(RELAY2, | ||
+ | |||
+ | // | ||
+ | --------------------------- Variables & others | ||
+ | -------------------------------- | ||
+ | mqtt.subscribe(& | ||
+ | } | ||
+ | |||
+ | // uint32_t x = 0; | ||
+ | |||
+ | void loop() { | ||
+ | // | ||
+ | ------------------------------ MQTT Connection | ||
+ | -------------------------------- | ||
+ | // Ensure the connection to the MQTT server is alive (this will make the first | ||
+ | // connection and automatically reconnect when disconnected). | ||
+ | MQTT_connect(); | ||
+ | // lcd.setRGB(255, | ||
+ | // | ||
+ | ------------------------------ Subscription | ||
+ | ----------------------------------- | ||
+ | Adafruit_MQTT_Subscribe *subscription; | ||
+ | while ((subscription = mqtt.readSubscription(5000))) { | ||
+ | if (subscription == & | ||
+ | Serial.print(F(" | ||
+ | Serial.println((char *)onoffmsg.lastread); | ||
+ | |||
+ | if (0 == strcmp((char *)onoffmsg.lastread, | ||
+ | lcd.setRGB(255, | ||
+ | lcd.setCursor(0, | ||
+ | lcd.print(F(" | ||
+ | lcd.print(F(USERNAME)); | ||
+ | digitalWrite(RELAY2, | ||
+ | } | ||
+ | if (0 == strcmp((char *)onoffmsg.lastread, | ||
+ | lcd.setRGB(0, | ||
+ | lcd.setCursor(0, | ||
+ | lcd.print(F(" | ||
+ | lcd.print(F(USERNAME)); | ||
+ | digitalWrite(RELAY2, | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // | ||
+ | ------------------------------ Publication | ||
+ | ---------------------------------- | ||
+ | int32_t val = mesureSimple(analogInPin); | ||
+ | if (val < 0) { | ||
+ | lcd.setRGB(245, | ||
+ | } else { | ||
+ | lcd.setRGB(0, | ||
+ | } | ||
+ | |||
+ | |||
+ | // int32_t val = mesure(analogInPin) * 100; | ||
+ | |||
+ | Serial.print(F(" | ||
+ | Serial.print(val); | ||
+ | lcd.setCursor(0, | ||
+ | lcd.print(F(" | ||
+ | lcd.setCursor(0, | ||
+ | lcd.print(F(USERNAME)); | ||
+ | lcd.setCursor(9, | ||
+ | lcd.print(val); | ||
+ | |||
+ | // Si on met double au lieu de int32_t, plantage !!! | ||
+ | if (! numbers.publish(val)) { | ||
+ | Serial.println(F(" | ||
+ | } else { | ||
+ | Serial.println(F(" | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | // Function to connect and reconnect as necessary to the MQTT server. | ||
+ | // Should be called in the loop function and it will take care if connecting. | ||
+ | void MQTT_connect() { | ||
+ | int8_t ret; | ||
+ | |||
+ | // attempt to connect to Wifi network: | ||
+ | while (WiFi.status() != WL_CONNECTED) { | ||
+ | Serial.print(F(" | ||
+ | Serial.println(ssid); | ||
+ | // Connect to WPA/WPA2 network. Change this line if using open or WEP network: | ||
+ | status = WiFi.begin(ssid, | ||
+ | |||
+ | // wait 10 seconds for connection: | ||
+ | uint8_t timeout = 10; | ||
+ | while (timeout && (WiFi.status() != WL_CONNECTED)) { | ||
+ | timeout--; | ||
+ | delay(1000); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Stop if already connected. | ||
+ | if (mqtt.connected()) { | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | Serial.print(F(" | ||
+ | |||
+ | while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected | ||
+ | Serial.println(mqtt.connectErrorString(ret)); | ||
+ | Serial.println(ret); | ||
+ | Serial.println(F(" | ||
+ | mqtt.disconnect(); | ||
+ | delay(5000); | ||
+ | } | ||
+ | Serial.println(F(" | ||
+ | } | ||
+ | double mesure(int analogPin) { | ||
+ | |||
+ | const int ACSoffset = 2500; | ||
+ | double Amps = 0; | ||
+ | /*double Voltage = 0; | ||
+ | int RawValue= 0; | ||
+ | RawValue = analogRead(analogPin); | ||
+ | /*Voltage = (RawValue / 1024.0) * 5000; // Gets you mV | ||
+ | Amps = ((Voltage | ||
+ | - ACSoffset) / mVperAmp); | ||
+ | |||
+ | Amps = (((analogRead(analogPin) / 1024.0) * 5000 | ||
+ | - ACSoffset) / mVperAmp); | ||
+ | |||
+ | / | ||
+ | Serial.print(RawValue); | ||
+ | Serial.print(" | ||
+ | Serial.print(Voltage, | ||
+ | // the ' | ||
+ | Serial.print(" | ||
+ | Serial.println(Amps, | ||
+ | // the ' | ||
+ | delay(2500); | ||
+ | return (Amps); | ||
+ | } | ||
+ | int mesureSimple(int analogPin) { | ||
+ | |||
+ | int Valeur = analogRead(analogPin); | ||
+ | |||
+ | return (Valeur); | ||
+ | } | ||
+ | </ | ||
+ | ===== Node-RED ===== | ||
+ | |||
+ | < | ||
+ | [ | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | } | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | } | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | [ | ||
+ | " | ||
+ | ] | ||
+ | ] | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | [ | ||
+ | " | ||
+ | " | ||
+ | ] | ||
+ | ] | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | ], | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | [], | ||
+ | [] | ||
+ | ] | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | [ | ||
+ | " | ||
+ | ] | ||
+ | ] | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | [ | ||
+ | " | ||
+ | ] | ||
+ | ] | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | [ | ||
+ | " | ||
+ | ] | ||
+ | ] | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | "# | ||
+ | ], | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | [], | ||
+ | [] | ||
+ | ] | ||
+ | } | ||
+ | ] | ||
+ | </ | ||