Difference between revisions of "MQTT"

From Fixme.ch
Jump to: navigation, search
(Initialisation d'un article)
Line 6: Line 6:
 
* Password: ask [[User:Francois]]
 
* Password: ask [[User:Francois]]
 
* No guest access allowed
 
* No guest access allowed
 +
 +
 +
== MQTT un protocole fabuleux ==
 +
MQTT est un protocole né à la fin des années 1990 permettant de transmettre des messages entre différents nœuds d'un réseau TCP/IP. Les objets situés sur les nœuds '''souscrivent''' à des services pour recevoir des données et/ou se déclarent pour en '''publier'''. Un broker situé à un point du réseau met en relation les ''souscripteurs''  (consommateurs de données) aux ''publieurs'' (fournisseurs de données).
 +
 +
Ce protocole simple et robuste était utilisé à l'origine pour gérer un grand nombre de capteurs/actionneurs sur des pipelines... Il est toujours utilisé en informatique industriel plus simple à mettre en œuvre et à déployer que les WebSockets.
 +
=== Souscrire ===
 +
Notre sonoff va s'instancier sur le réseau en contactant le broker dont nous lui avons donné l'adresse IP en souscrivant au service (topic) /sonoff. Quand un objet publiera une donnée 1 sur le topic /sonoff la lampe s'allumera et s'étendra à la réception d'un 0
 +
=== Publier ===
 +
Sur un smartphone Android on peut charger l'application '''MQTT Dash''', se raccorder au Broker mis en place par François et créer un service de bouton on/off qui publiera sur le topic /sonoff et enverra des ordres d'allumage (1) ou d'extinction (0).
 +
== Un exemple d'utilisation avec un SonOff en commande d'éclairage ==
 +
Les Sonoff sont de petits interrupteurs construits autour d'un ESP8266 et d'un relais 10A.
 +
On peut facilement hacker ces objets qui ne coutent que 6 CHF pour les insérer dans notre architecture selon nos besoins.
 +
Les PIN exposées du dispositif permettent de le reflasher pour commander le relais en souscrivant à un service n/off. (une pin-GPIO14) reste disponible pour y connecter un capteur et donc publier cette information.
 +
 +
=== Le code en service ===
 +
<nowiki>
 +
/***************************************************
 +
  Adafruit MQTT Library ESP8266 Example
 +
 +
  Must use ESP8266 Arduino from:
 +
    https://github.com/esp8266/Arduino
 +
 +
  Works great with Adafruit's Huzzah ESP board & Feather
 +
  ----> https://www.adafruit.com/product/2471
 +
  ----> https://www.adafruit.com/products/2821
 +
 +
  Adafruit invests time and resources providing this open source code,
 +
  please support Adafruit and open-source hardware by purchasing
 +
  products from Adafruit!
 +
 +
  Written by Tony DiCola for Adafruit Industries.
 +
  MIT license, all text above must be included in any redistribution
 +
****************************************************/
 +
#include <ESP8266WiFi.h>
 +
//#include <WiFi.h>
 +
 +
#include "Adafruit_MQTT.h"
 +
#include "Adafruit_MQTT_Client.h"
 +
 +
 +
 +
/************************* WiFi Access Point *********************************/
 +
 +
#define WLAN_SSID  "FIXME-NAT"
 +
#define WLAN_PASS  "xxxxxxxxx"
 +
 +
/************************* Adafruit.io Setup *********************************/
 +
 +
#define AIO_SERVER      "62.220.135.221"
 +
#define AIO_SERVERPORT  1883                  // use 8883 for SSL
 +
#define AIO_USERNAME    "fixme"
 +
#define AIO_KEY        "yyyyyyyyyy"
 +
#define LED_PIN 13
 +
#define RELAY_PIN 12
 +
 +
/************ Global State (you don't need to change this!) ******************/
 +
 +
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
 +
WiFiClient client;
 +
// or... use WiFiFlientSecure for SSL
 +
//WiFiClientSecure client;
 +
 +
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
 +
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
 +
//Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT);
 +
/****************************** Feeds ***************************************/
 +
 +
// Setup a feed called 'photocell' for publishing.
 +
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
 +
//Adafruit_MQTT_Publish photocell = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/photocell");
 +
//Adafruit_MQTT_Publish halleffect = Adafruit_MQTT_Publish(&mqtt, "/effethall");
 +
//Adafruit_MQTT_Publish lipocharge = Adafruit_MQTT_Publish(&mqtt, "/chargelipo");
 +
// Setup a feed called 'onoff' for subscribing to changes.
 +
 +
Adafruit_MQTT_Subscribe sonoff = Adafruit_MQTT_Subscribe(&mqtt, "/sonoff");
 +
/*************************** Sketch Code ************************************/
 +
//Adafruit_MQTT_Subscribe onoffbutton = Adafruit_MQTT_Subscribe(&mqtt, "/onoffbutton");
 +
 +
// Bug workaround for Arduino 1.6.6, it seems to need a function declaration
 +
// for some reason (only affects ESP8266, likely an arduino-builder bug).
 +
void MQTT_connect();
 +
 +
 +
 +
void setup() {
 +
  Serial.begin(115200);
 +
  delay(10);
 +
  pinMode(LED_PIN,OUTPUT);
 +
  pinMode(RELAY_PIN,OUTPUT);
 +
  Serial.println(F("Adafruit MQTT Sonoff demo"));
 +
  //ledcSetup(1, 50, TIMER_WIDTH); // channel 1, 50 Hz, 16-bit width
 +
  //ledcAttachPin(21, 1);  // GPIO 22 assigned to channel 1
 +
  // Connect to WiFi access point.
 +
  Serial.println(); Serial.println();
 +
  Serial.print("Connecting to ");
 +
  Serial.println(WLAN_SSID);
 +
 +
  WiFi.begin(WLAN_SSID, WLAN_PASS);
 +
  while (WiFi.status() != WL_CONNECTED) {
 +
    delay(500);
 +
    Serial.print(".");
 +
  }
 +
  Serial.println();
 +
 +
  Serial.println("WiFi connected");
 +
  Serial.println("IP address: "); Serial.println(WiFi.localIP());
 +
 +
  // Setup MQTT subscription for onoff feed.
 +
  mqtt.subscribe(&sonoff);
 +
}
 +
 +
void loop() {
 +
  // Ensure the connection to the MQTT server is alive (this will make the first
 +
  // connection and automatically reconnect when disconnected).  See the MQTT_connect
 +
  // function definition further below.
 +
  MQTT_connect();
 +
 +
  // this is our 'wait for incoming subscription packets' busy subloop
 +
  // try to spend your time here
 +
 +
  Adafruit_MQTT_Subscribe *subscription;
 +
 
 +
  while ((subscription = mqtt.readSubscription(1000))) {
 +
    if (subscription == &sonoff) {
 +
      Serial.print(F("Got: "));
 +
      String A = (char *)sonoff.lastread ;
 +
      Serial.println(A);
 +
        if (A == "1") {         
 +
          digitalWrite(RELAY_PIN, 255);
 +
          digitalWrite(LED_PIN, 0);
 +
        }
 +
        if(A == "0") {       
 +
          digitalWrite(RELAY_PIN, 0);
 +
          digitalWrite(LED_PIN, 255);
 +
        }
 +
     
 +
      }
 +
      }
 +
 +
 +
  // ping the server to keep the mqtt connection alive
 +
  // NOT required if you are publishing once every KEEPALIVE seconds
 +
 
 +
/*
 +
  if(! mqtt.ping()) {
 +
    mqtt.disconnect();
 +
  }
 +
*/
 +
}
 +
 +
// 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;
 +
 +
  // Stop if already connected.
 +
  if (mqtt.connected()) {
 +
    return;
 +
  }
 +
 +
  Serial.print("Connecting to MQTT... ");
 +
 +
  uint8_t retries = 3;
 +
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
 +
      Serial.println(mqtt.connectErrorString(ret));
 +
      Serial.println("Retrying MQTT connection in 5 seconds...");
 +
      mqtt.disconnect();
 +
      delay(5000);  // wait 5 seconds
 +
      retries--;
 +
      if (retries == 0) {
 +
        // basically die and wait for WDT to reset me
 +
        while (1);
 +
      }
 +
  }
 +
  Serial.println("MQTT Connected!");
 +
}
 +
</nowiki>

Revision as of 21:50, 28 October 2018

We're running mosquitto as MQTT broker running on Bellatrix and here's how to use it:

  • Host: 62.220.135.221
  • Port: 1883
  • User: fixme
  • Password: ask User:Francois
  • No guest access allowed


MQTT un protocole fabuleux

MQTT est un protocole né à la fin des années 1990 permettant de transmettre des messages entre différents nœuds d'un réseau TCP/IP. Les objets situés sur les nœuds souscrivent à des services pour recevoir des données et/ou se déclarent pour en publier. Un broker situé à un point du réseau met en relation les souscripteurs (consommateurs de données) aux publieurs (fournisseurs de données).

Ce protocole simple et robuste était utilisé à l'origine pour gérer un grand nombre de capteurs/actionneurs sur des pipelines... Il est toujours utilisé en informatique industriel plus simple à mettre en œuvre et à déployer que les WebSockets.

Souscrire

Notre sonoff va s'instancier sur le réseau en contactant le broker dont nous lui avons donné l'adresse IP en souscrivant au service (topic) /sonoff. Quand un objet publiera une donnée 1 sur le topic /sonoff la lampe s'allumera et s'étendra à la réception d'un 0

Publier

Sur un smartphone Android on peut charger l'application MQTT Dash, se raccorder au Broker mis en place par François et créer un service de bouton on/off qui publiera sur le topic /sonoff et enverra des ordres d'allumage (1) ou d'extinction (0).

Un exemple d'utilisation avec un SonOff en commande d'éclairage

Les Sonoff sont de petits interrupteurs construits autour d'un ESP8266 et d'un relais 10A. On peut facilement hacker ces objets qui ne coutent que 6 CHF pour les insérer dans notre architecture selon nos besoins. Les PIN exposées du dispositif permettent de le reflasher pour commander le relais en souscrivant à un service n/off. (une pin-GPIO14) reste disponible pour y connecter un capteur et donc publier cette information.

Le code en service

/***************************************************
  Adafruit MQTT Library ESP8266 Example

  Must use ESP8266 Arduino from:
    https://github.com/esp8266/Arduino

  Works great with Adafruit's Huzzah ESP board & Feather
  ----> https://www.adafruit.com/product/2471
  ----> https://www.adafruit.com/products/2821

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Tony DiCola for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 ****************************************************/
#include <ESP8266WiFi.h>
//#include <WiFi.h>

#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"


 
/************************* WiFi Access Point *********************************/

#define WLAN_SSID   "FIXME-NAT"
#define WLAN_PASS   "xxxxxxxxx"

/************************* Adafruit.io Setup *********************************/

#define AIO_SERVER      "62.220.135.221"
#define AIO_SERVERPORT  1883                   // use 8883 for SSL
#define AIO_USERNAME    "fixme"
#define AIO_KEY         "yyyyyyyyyy"
#define LED_PIN 13
#define RELAY_PIN 12

/************ Global State (you don't need to change this!) ******************/

// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;
// or... use WiFiFlientSecure for SSL
//WiFiClientSecure client;

// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
//Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT);
/****************************** Feeds ***************************************/

// Setup a feed called 'photocell' for publishing.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
//Adafruit_MQTT_Publish photocell = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/photocell");
//Adafruit_MQTT_Publish halleffect = Adafruit_MQTT_Publish(&mqtt, "/effethall");
//Adafruit_MQTT_Publish lipocharge = Adafruit_MQTT_Publish(&mqtt, "/chargelipo");
// Setup a feed called 'onoff' for subscribing to changes.

Adafruit_MQTT_Subscribe sonoff = Adafruit_MQTT_Subscribe(&mqtt, "/sonoff");
/*************************** Sketch Code ************************************/
//Adafruit_MQTT_Subscribe onoffbutton = Adafruit_MQTT_Subscribe(&mqtt, "/onoffbutton");

// Bug workaround for Arduino 1.6.6, it seems to need a function declaration
// for some reason (only affects ESP8266, likely an arduino-builder bug).
void MQTT_connect();



void setup() {
  Serial.begin(115200);
  delay(10);
  pinMode(LED_PIN,OUTPUT);
  pinMode(RELAY_PIN,OUTPUT);
  Serial.println(F("Adafruit MQTT Sonoff demo"));
  //ledcSetup(1, 50, TIMER_WIDTH); // channel 1, 50 Hz, 16-bit width
  //ledcAttachPin(21, 1);   // GPIO 22 assigned to channel 1
  // Connect to WiFi access point.
  Serial.println(); Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WLAN_SSID);

  WiFi.begin(WLAN_SSID, WLAN_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();

  Serial.println("WiFi connected");
  Serial.println("IP address: "); Serial.println(WiFi.localIP());

  // Setup MQTT subscription for onoff feed.
  mqtt.subscribe(&sonoff);
}

void loop() {
  // Ensure the connection to the MQTT server is alive (this will make the first
  // connection and automatically reconnect when disconnected).  See the MQTT_connect
  // function definition further below.
  MQTT_connect();

  // this is our 'wait for incoming subscription packets' busy subloop
  // try to spend your time here

  Adafruit_MQTT_Subscribe *subscription;
  
  while ((subscription = mqtt.readSubscription(1000))) {
    if (subscription == &sonoff) {
      Serial.print(F("Got: "));
      String A = (char *)sonoff.lastread ;
      Serial.println(A);
        if (A == "1") {          
          digitalWrite(RELAY_PIN, 255);
          digitalWrite(LED_PIN, 0);
        } 
        if(A == "0") {         
          digitalWrite(RELAY_PIN, 0);
          digitalWrite(LED_PIN, 255);
        }
      
      } 
      }


  // ping the server to keep the mqtt connection alive
  // NOT required if you are publishing once every KEEPALIVE seconds
  
 /*
  if(! mqtt.ping()) {
    mqtt.disconnect();
  }
*/
}

// 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;

  // Stop if already connected.
  if (mqtt.connected()) {
    return;
  }

  Serial.print("Connecting to MQTT... ");

  uint8_t retries = 3;
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
       Serial.println(mqtt.connectErrorString(ret));
       Serial.println("Retrying MQTT connection in 5 seconds...");
       mqtt.disconnect();
       delay(5000);  // wait 5 seconds
       retries--;
       if (retries == 0) {
         // basically die and wait for WDT to reset me
         while (1);
       }
  }
  Serial.println("MQTT Connected!");
}