This week, I’magain digging the MQTT messaging protocol, and how can use it with theESP8266 module, theRaspberry Pi, theCHIP and my linux notebook. The capability to easily send two-way messages between all these devices opens a lot of possibilities for interesting and possibly useful, remote and automated gadgets.
Installing the Mosquitto MQTT broker on a CHIP computer is an absolute no-brainer, as explained in last week’slast week’s article. By the way, if it doesn’t restart at boot-up, you may have to edit /etc/rc.local , as root and add a reference program at the bottom, along with the “&” (run in the background) symbol. It should then start up on the next boot.
Running Mosquitto on the CHIP is also painless. I had a spare outlet in the kitchen, so I simply plugged it into a 2-Amp wall wart and located the board on an out-of-the-way shelf. It’s been happily humming along, brokering MQTT messages, for the last couple of days. I can ssh and/or MQTT_subscribe into the CHIP from anywhere on my local area network, using a Linux notebook or my Android super-phone.
Dozens of Android MQTT client programs exist in the Google Play Store. Just punch “ MQTT client ” into the search bar and pick one. Use them for testing or a quick and dirty data monitoring solution. Once you have a client app on your phone, just enter your CHIP’s IP address along with the appropriate topic and you’re usually good to go.
Let’s talk about our data generator, next.
Modding the ESP8266 Firmware for MQTTESP8266-based sensors make great data generators. They are inexpensive, easy to program through theArduino IDE and can handle MQTT messages without a sweat. Pick your sensor, hook it to a GPIO pin and start sending data. Going the other direction, pick an output device, watch for a specific message and activate the pin connected to the device. We’ll cover watching for messages (on an ESP8266) and activating a GPIO pin in a future story.
I used the mqtt_esp8266 example program (in the Arduino IDE) as a baseline MQTT client on the ESP8266. Adding the PIR sensor code, which was covered in “Create an Early Warning Detector with Passive Infrared Sensors” produced a completely usable program for data generating purposes. Whenever a hot-body moves in front of the sensor, it sends an MQTT message to the CHIP broker. Look, Ma, no wires.
Here’s the code.
/*-----------------------------------------
drtorq's Modded - Basic ESP8266 MQTT example
filename: mqtt_esp8266_1
-----------------------------------------
*/
#include
#include
// Update these with values suitable for your network.
const char* ssid = "your AP name";
const char* password = "your AP password";
const char* mqtt_server = "192.168.1.111"; // IP address of the MQTT Broker
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
int calibrationTime = 20;
int pirPin = 2; //the digital pin connected to the PIR sensor's output
int ledPin = 13;
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
// Switch on the LED if an 1 was received as first character
if ((char)payload[0] == '1') {
digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level
// but actually the LED is on; this is because
// it is acive low on the ESP-01)
} else {
digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str())) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish("mqtt", "hello world");
// ... and resubscribe
client.subscribe("inTopic");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup() {
pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
// Calibrate sensor
Serial.print("calibrating sensor ");
for(int i = 0; i < calibrationTime; i++){
Serial.print(".");
delay(1000);
}
Serial.println(" done");
Serial.println("SENSOR ACTIVE");
delay(50);
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
// added PIR sensor code segment here
int proximity = digitalRead(pirPin);
if (proximity == LOW) // If the sensor's output goes low, motion is detected
{
digitalWrite(ledPin, HIGH);
snprintf (msg, 75, "Motion Detected #%ld", value);
++value;
Serial.println("Motion detected!");
client.publish("mqtt", msg);
delay(200);
}
else
{
digitalWrite(ledPin, LOW);
delay(200);
}
}
The setup has silently run for a few days, detecting every time I move, at my desk. Here’s a screen-shot of the mosquitto_sub command, on a Linux notebook window, monitoring the sensor from the network. That’s right, over 46,500 “Motion Detected” messages. Works like a charm.
mosquitto_sub Results On The Linux Notebook
The sensor is capable of seeing motion several times a second, so changing the code to ignore detection over a one- to three-second period, after it initially fires, would cut down on the amount of data streamed to the broker. I think it’s unlikely we’ll miss intruders, using this technique, in the real World.
ESP8266-based devices aren’t the only ones that can send MQTT messages.
Run an MQTT Client on the Raspberry Pi, tooThe Raspberry Pi can muscle itself into your little MQTT universe as a subscriber AND a publisher, as well.
Imagine having an ESP8266-enabled yard light, that’s toggled on/off with an MQTT message. It might be useful to be able to push a button on a Raspberry Pi and have the light turn on.
I wrote a python program a while back to detect button pushes on a Raspberry Pi. It’s a bit of a kludgesince it used the xdotool and a system call. Off-the-shelf hacking IS sometimes a kludge . Like I always say, get the prototype