Eu tenho me divertido bastante fazendo coisas para Internet of Things (IoT). Hoje, eu quero usar o protocolo MQTT para fazer a comunicação entre diferentes dispositivos. Primeiro, eu criei um broker mqtt no meu laptop. Para testar, eu vou usar o servidor mosquitto. Na produção, podemos usar RabbitMQ ou mesmo um servidor de terceiros, como iot.eclipse.org ou mesmo o serviço de IoT da Amazon.
A ideia é emitir um valor com um dispositivo e ouvir esse valor com o resto dos dispositivos, e executar uma ação dependendo desse valor. Por exemplo, vou usar um potenciômetro conectado ao microcontrolador NodeMcu.
Esse controlador se conectará ao broker mqtt e emitirá o valor do potenciômetro (lendo a entrada analógica) em um tópico (chamado “potenciômetro”). Podemos programar nosso NodeMcu com Lua, mas fico mais confortável com C++ e Arduino IDE. Primeiro, eu preciso me conectar à minha rede Wi-fi, depois me conectar ao broker e começar a emitir os valores do potenciômetro.
#include <PubSubClient.h>
#include <ESP8266WiFi.h>
// Wifi configuration
const char* ssid = "MY_WIFI_SSID";
const char* password = "my_wifi_password";
// mqtt configuration
const char* server = "192.168.1.104";
const char* topic = "potentiometer";
const char* clientName = "com.gonzalo123.nodemcu";
int value;
int percent;
String payload;
WiFiClient wifiClient;
PubSubClient client(wifiClient);
void wifiConnect() {
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("WiFi connected.");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
if (client.connect(clientName)) {
Serial.print("Connected to MQTT broker at ");
Serial.print(server);
Serial.print(" as ");
Serial.println(clientName);
Serial.print("Topic is: ");
Serial.println(topic);
}
else {
Serial.println("MQTT connect failed");
Serial.println("Will reset and try again...");
abort();
}
}
void mqttReConnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect(clientName)) {
Serial.println("connected");
client.subscribe(topic);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void setup() {
Serial.begin(9600);
client.setServer(server, 1883);
wifiConnect();
delay(10);
}
void loop() {
value = analogRead(A0);
percent = (int) ((value * 100) / 1010);
payload = (String) percent;
if (client.connected()) {
if (client.publish(topic, (char*) payload.c_str())) {
Serial.print("Publish ok (");
Serial.print(payload);
Serial.println(")");
} else {
Serial.println("Publish failed");
}
} else {
mqttReConnect();
}
delay(200);
}
Agora, vamos usar outro Arduíno (com um escudo ethernet).
Vamos mover um servomotor de acordo com o valor do potenciômetro NodeMcu. Esse Arduino só precisa fazer um listen do tópico do MQTT e mover o servo.
#include <SPI.h>
#include <Servo.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#define SERVO_CONTROL 9
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
Servo servo;
EthernetClient ethClient;
// mqtt configuration
const char* server = "192.168.1.104";
const char* topic = "potentiometer";
const char* clientName = "com.gonzalo123.arduino";
PubSubClient client(ethClient);
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] angle:");
String data;
for (int i = 0; i < length; i++) {
data += (char)payload[i];
}
double angle = ((data.toInt() * 180) / 100);
constrain(angle, 0, 180);
servo.write((int) angle);
Serial.println((int) angle);
}
void mqttReConnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect(clientName)) {
Serial.println("connected");
client.subscribe(topic);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void setup()
{
Serial.begin(9600);
client.setServer(server, 1883);
client.setCallback(callback);
servo.attach(SERVO_CONTROL);
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
}
delay(1500); // Allow the hardware to sort itself out
}
void loop()
{
if (!client.connected()) {
mqttReConnect();
}
client.loop();
}
Finalmente, usaremos um Raspberry Pi com um Sense Hat e exibiremos com sua matriz de led diferentes cores e pontos, dependendo do valor do NodeMcu. Da mesma forma que o script Arduino, aqui só precisamos fazer um listen do tópico do broker e executar as ações com o Sense Hat. Agora com Python:
import paho.mqtt.client as mqtt
from sense_hat import SenseHat
sense = SenseHat()
sense.clear()
mqttServer = "192.168.1.104"
red = [255, 0, 0]
green = [0, 255, 0]
yellow = [255, 255, 0]
black = [0, 0, 0]
def on_connect(client, userdata, rc):
print("Connected!")
client.subscribe("potentiometer")
def on_message(client, userdata, msg):
value = (64 * int(msg.payload)) / 100
O = black
if value < 21:
X = red
elif value < 42:
X = yellow
else:
X = green
sense.set_pixels(([X] * value) + ([O] * (64 - value)))
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(mqttServer, 1883, 60)
client.loop_forever()
O hardware:
- 1 Arduino Uno
- 1 NodeMCU (V3)
- 1 potenciômetro
- 1 Servo (SG90)
- 1 Raspberry Pi 3 (com um Sense Hat)
O código-fonte está disponível no meu GitHub.
***
Gonzalo Ayuso faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela Redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://gonzalo123.com/2017/06/26/playing-with-raspberry-pi-arduino-nodemcu-and-mqtt/






