In the previous two posts, we set up an ESP32 development board with an IR receiver to read codes sent by a remote control. Now it’s time to add MQTT capability.
I chose the PubSubClient library – available in the Arduino IDE library manager – because it claims compatibility with the ESP32. When I looked closer, it turns out that the degree of support for the ESP32 is, shall we say, disputed. But several bloggers report success with it, so on we go…
The first thing to do is include the library (assuming you’ve installed it):
#include <PubSubClient.h>
Then let’s establish a few settings:
#define MQTT_SERVER_ADDR "10.0.0.59" // replace with the address of your MQTT server #define MQTT_DEVICE_ID "ESP32_IR_hub" // use whatever name you want #define MQTT_TOPIC "home/lights" // whatever topic you want
You’ll need to change the IP address to that of your MQTT broker. Mine is a Raspberry Pi pretending to be a PDP-8, but actually serving as our home intranet. The device name is arbitrary. And I’ve set only one topic for sending and subscribing – it’s possible that, once I actually come to use this device, I might create an array of topics rather than using a single, simple define.
We now need to create a couple of objects and two functions – one is the callback function that is invoked whenever we pick up a message on the subscribed topic and the other is used to connect to the broker.
The first – the callback – is needed only if you want the device to respond to topic messages sent by other devices. I decided to include it because I haven’t yet quite worked out what I’m going to use this device for. But if you want this device to be send-only, the callback isn’t needed.
WiFiClient mqttWifiClient; PubSubClient mqtt(mqttWifiClient); /** Callback function for incoming MQTT messages. **/ void mqttCallback(char* topic, byte* message, unsigned int length) { // Topic is a char array. Easiest to cast it to a string to test // for specific topics. if (String(topic) == MQTT_TOPIC) { /* Just a placeholder to show how this works. This is where you'd respond to the message - perhaps by setting a flag that could be dealt with in the main loop */ } // The message is a byte array. We can build a string from it with: String msg; for (int i = 0; i < length; i++) { msg += (char)message[i]; } } void mqttReconnect() { // Loop until we're reconnected while (!mqtt.connected()) { Serial.print("Attempting MQTT connection... "); // Attempt to connect if (mqtt.connect(MQTT_DEVICE_ID)) { Serial.println("MQTT connected"); mqtt.subscribe(MQTT_TOPIC); // only if you want to respond to incoming messages } else { Serial.print("failed, rc="); Serial.print(mqtt.state()); Serial.println(" - trying again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } }
In the setup() function, we’ll get the ball rolling:
mqtt.setServer(MQTT_SERVER_ADDR, 1883); mqtt.setCallback(mqttCallback);
And in the main loop we’ll check the connection and reconnect if necessary (this will always get called the first time through the loop):
if (!mqtt.connected()) { mqttReconnect(); } mqtt.loop();
Finally, also in the main loop, we can send out messages. For example, here we’re sending a message in response to receiving a specific code from the remote control:
// Send MQTT message according to code received switch (results.value) { case 0x807FC03F: Serial.println("- sending dim message"); mqtt.publish(MQTT_TOPIC, "dim"); break; }
There’s only one case in that switch block, but it’s just to give an idea of how it works.
So far it has been working a treat. You may notice, however, that we’re using only the most basic MQTT functionality. There is, for example, no security – no logging on to the broker or encryption of messages. As this is for use only on my home network, this doesn’t bother me. I don’t know how far you can go with PubSubClient on the ESP32 in terms of more advanced MQTT features, but this is enough for my needs.
I’ll probably leave this project here for the moment. The basic functionality is complete – ie, being able to receive and decode signals from a remote control and send out MQTT messages in response.
The truth is, this is a solution in search of a problem. I saw a couple of videos on the subject of using IR remotes and thought, ‘I have everything needed to do that, it looks like fun’. And so I wanted to dash off a quick project just to try it out.
I can see that adding the possibility of interacting with a REST API on the intranet server might be useful. But I’ve done that successfully on other projects, so that’ll be a cut and paste job. For now, I need to concentrate on finding a use for this device!
The code
The code for this project is in a GitHub repository: ESP32_IR_IoT_hub.
There’s also a simple sketch for decoding the signals from a remote control. This should work with most microcontroller boards – Arduinos, Teensy, ESP etc. The repo is: IR_remote_decode.