Referencia: Librería mqtt https://pubsubclient.knolleary.net/api
Para esta sección se supone que ha establecido la conexión a la red WiFi y dispone de un un servidor/broker MQTT de pruebas, semejante a lo realizado en las secciones anteriores.
1. Bloque de inicio
Para MQTT se incluye la libreria PubSubClient.h
para la activación de un cliente sobre WiFi. como se indica en las intrucciones siguientes:
#include <PubSubClient.h > // Clientes WiFi y MQTT WiFiClient wificlient; PubSubClient mqttclient(wificlient);
2. Configuración de inicio setup()
Para el bloque de configuración setup() se verifica el estado de la conexión WiFi antes del intento de conexión al broker MQTT-Mosquitto.
// conexión WIFI y MQTT inicia_wifi(); if (WiFi.status() == WL_CONNECTED){ inicia_mqtt(); }
El proceso inicia_mqtt()
se establecen los párámetros de servidor, identificación de usario, conexión y la primera actualización de estado con pub/sub que corresponda.
3. Procedimientos MQTT
Se usa el procedimiento de inicio de conexión y de publicación de estados con sensores. En el caso de actuador se añade el proceso de recepción de mensajes en el dispositivo (callback)
3.1 Procedimiento inicia_mqtt()
Con los parámetros del broker y dispositivo se establece la conexión con el servidor (setServer(), connect()).
Se tiene un periodo de espera mientras se parpadea el led y se presenta un punto en el puerto serial. En caso de que se verifica conexión se publica el estado inicial del sensor antes de volver al bucle de operación.
void inicia_mqtt() { int espera = 5; int cuenta = 0; mqttclient.setServer(MQTT_IP, MQTT_puerto); mqttclient.connect(MQTT_ID, MQTT_usuario, MQTT_contrasena); //mqttclient.setCallback(callback); if (serial_msg){ Serial.print(" MQTT Conectando a "); Serial.println(MQTT_IP); } while (!mqttclient.connected()&&(cuenta<=espera)){ cuenta = cuenta + 1; // LED Monitor parpadeo MQTT, enciende LOW digitalWrite(LED_pin, LOW); delay(600); digitalWrite(LED_pin, HIGH); delay(400); if (serial_msg){ Serial.print("."); } } // Si conectado, inicializa estado if (mqttclient.connected()){ publica_mqtt(); } if (serial_msg){ //Fin de "...." Serial.println(); Serial.print(" MQTT Conectado: "); Serial.println(mqttclient.connected()); Serial.print(" MQTT Estado: "); Serial.println(mqttclient.state()); } }
Se añaden algunos mensajes de estado hacia el computador como parte del proceso de depuración en la etapa de desarrollo y programación.
El resultado de esta subrutina en la pantalla "monitor_serie"
es;
inicia setup WIFI Conectando a miRouter ....... Estado: 3 MAC: 2C:3A:E8:0A:98:66 IP: 192.168.10.11 RSSI: -56 MQTT Conectando a 192.168.10.50 OFF MQTT Conectado: 1 MQTT Estado: 0 ON OFF ON OFF ON OFF .... OFF ON MQTT desconectado MQTT Conectando a 192.168.10.50 .....
Como una prueba de funcionamiento, al final se muestra el resultado al desconectar el cable del servidor MQTT.
Estos parámetros se deben actualizar para cada dispositivo específico a desarrolar.
Los valores para mqttclient.state() que se pueden obtener son:
-4 : MQTT_CONNECTION_TIMEOUT - the server didn't respond within the keepalive time -3 : MQTT_CONNECTION_LOST - the network connection was broken -2 : MQTT_CONNECT_FAILED - the network connection failed -1 : MQTT_DISCONNECTED - the client is disconnected cleanly 0 : MQTT_CONNECTED - the client is connected 1 : MQTT_CONNECT_BAD_PROTOCOL - the server doesn't support the requested version of MQTT 2 : MQTT_CONNECT_BAD_CLIENT_ID - the server rejected the client identifier 3 : MQTT_CONNECT_UNAVAILABLE - the server was unable to accept the connection 4 : MQTT_CONNECT_BAD_CREDENTIALS - the username/password were rejected 5 : MQTT_CONNECT_UNAUTHORIZED - the client was not authorized to connect
Referencia: https://pubsubclient.knolleary.net/api
3.2 Procedimiento publica_mqtt()
La publicación de estados se realiza como una subrutina, en el ejemplo es solo encendido y apagado de un LED
// Publicar el estados del dispositivo void publica_mqtt() { // formato para envio (Texto) if (sensor_estado == true ){ snprintf(MQTT_SensorEstado,10, "ON"); }else{ snprintf(MQTT_SensorEstado,10, "OFF"); } // publicar estados if (mqttclient.connected()==true) { mqttclient.publish(MQTT_TOPIC, MQTT_SensorEstado, true); } if (serial_msg){ if (mqttclient.connected()==true) { Serial.println(MQTT_SensorEstado); } if (mqttclient.connected()==false) { Serial.println("MQTT desconectado"); } } }
4. Instrucciones Arduino
Las instrucciones usadas para que el estado del parpadeo de un LED se transmita al broker MQTT se incluyen en para la parte principal en la pestaña principal.
/* ESP8266/ESP32 Sensor LED Parpadea. * edelros@espol.edu.ec * Actualice: WIFI:Router, MQTT:Servidor, MQTT:Dispositivo * ESP-01, NO USE Serial.print() */ // detectar placa al compilar # ifdef defined(ESP8266) #include <ESP8266WiFi.h> # elif defined(ESP32) #include <WiFi.h> # endif #include <PubSubClient.h> // Clientes WiFi y MQTT WiFiClient wificlient; PubSubClient mqttclient(wificlient); // WIFI: conexión a Router char* ssid = "miRouter"; char* password = "miRouterClave"; // MQTT: Servidor char* MQTT_IP = "192.168.10.50"; uint16_t MQTT_puerto = 1883; char* MQTT_usuario = "usuarioprueba"; char* MQTT_contrasena = "usuarioclave"; // MQTT: Dispositivo char* MQTT_ID = "Dispositivo"; char* MQTT_TOPIC = "oficina/mensaje"; char MQTT_SensorEstado[10] = "OFF"; boolean mqtt_desconectado = true; // Sensor const uint8_t sensor_pin = 1; volatile boolean sensor_estado = false; // LED monitor interno: ESP01-pin=1, ESP07-pin=2 const uint8_t LED_pin = 2; // Mensajes por Puerto Serial volatile boolean serial_msg = true; void setup() { if (serial_msg){ Serial.begin(115200);//74880, 115200 while (!Serial){delay(50);} Serial.println("inicia setup"); } // LED monitor, Enciende en LOW pinMode(LED_pin, OUTPUT); // conexión WIFI y MQTT inicia_wifi(); if (WiFi.status() == WL_CONNECTED){ inicia_mqtt(); } } void loop() { // Parpadea estado de sensor if (sensor_estado==true){ sensor_estado = false; }else{ sensor_estado = true; } // LED Monitor Parpadea, enciende en LOW if (sensor_estado ==true) { digitalWrite(LED_pin, LOW); delay(1000); // un segundo } #ifdef defined(ESP8266) yield(); // procesa wifi #endif if (sensor_estado ==false) { digitalWrite(LED_pin, HIGH); delay(1000); } if (mqttclient.connected()==true){ publica_mqtt(); } //Revisa estado de Wifi o reintenta conexión if (WiFi.status() != WL_CONNECTED){ inicia_wifi(); }else{ if (mqttclient.connected()==false){ inicia_mqtt(); // reintento } if (mqttclient.connected()==true){ mqttclient.loop(); } } #ifdef defined(ESP8266) yield(); // procesa wifi #endif }
Si no se ha implementado el broker MQTT solo obtendrá mensajes de «MQTT desconectado».
Al final, recuerde añadir los otros procedimientos inicia_wifi(), inicia_mqtt(), publica_mqtt().
void inicia_wifi(){ int espera = 10; // >=10 para conectar int cuenta = 0; // mensajes por serial activado if (serial_msg){ Serial.print(" WIFI Conectando a "); Serial.println(ssid); } WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while ((WiFi.status()!=WL_CONNECTED)&&(cuenta<espera)){ cuenta = cuenta+1; // Parpadeo de Monitor enciende en LOW digitalWrite(LED_pin, LOW); delay(300); digitalWrite(LED_pin, HIGH); delay(200); if (serial_msg){ Serial.print("."); } } //activado mensajes por serial if (serial_msg){ Serial.println(); //Fin de "..." if (WiFi.status() == WL_CONNECTED){ Serial.print(" Estado: "); Serial.println(WiFi.status()); Serial.print(" MAC: "); Serial.println(WiFi.macAddress()); Serial.print(" IP: "); Serial.println(WiFi.localIP()); Serial.print(" RSSI: "); Serial.println(WiFi.RSSI()); Serial.print(" Canal: "); Serial.println(WiFi.channel()); Serial.println(); } if (WiFi.status() != WL_CONNECTED){ WiFi.printDiag(Serial); Serial.println(); } } }