Talk To Your Device
Subscribe to a command topic, then trigger it from the dashboard.
The idea
So far, data has flowed one way: device → platform. Now we'll go the other direction. Your device will listen on a topic, and the dashboard will publish to it.
This is standard MQTT — publish and subscribe work in both directions. The dashboard is just another MQTT client.
Update the sketch
Start from the Your First Sensor sketch and add three things: a subscription list, a message callback, and an LED to toggle.
#include <Arduino.h>
#include "credentials.h"
#include "device_id.h"
#include "wifi_tools.h"
#include "mqtt.h"
#define LED 2
char DEVICE_ID[9];
unsigned long last_publish = 0;
// ── handle incoming messages ──
void on_message(char * topic, char * message) {
Serial.print("\n\treceived: ");
Serial.print(topic);
Serial.print(" → ");
Serial.println(message);
if (strcmp(message, "blink") == 0) {
for (int i = 0; i < 5; i++) {
digitalWrite(LED, HIGH);
delay(100);
digitalWrite(LED, LOW);
delay(100);
}
}
}
// ── subscriptions ──
static const char * my_topics[] = {
"~/~/command",
nullptr
};
void setup() {
Serial.begin(115200);
Serial.println("\n\n booting...\n");
pinMode(LED, OUTPUT);
device_id.get_or_set(DEVICE_ID);
wifi_tools.begin(WIFI_SSID, WIFI_PASS);
mqtt.setup(MQTT_HOST, MQTT_PORT, DEVICE_ID, MQTT_USER, MQTT_PASS);
mqtt.set_subscriptions(my_topics);
mqtt.set_callback(on_message);
}
void loop() {
if (wifi_tools.is_connected) {
mqtt.maintain();
if (mqtt.is_connected && millis() - last_publish > 5000) {
float temperature = 68.0 + random(-30, 30) / 10.0;
mqtt.publish("~/~/numb/temperature/temp", temperature);
last_publish = millis();
}
} else {
wifi_tools.reconnect();
mqtt.report_disconnect();
}
}~/~/ prefix expands to username/deviceID/ at publish and subscribe time, so you don't need to hardcode either value into the sketch. The values come from your credentials (MQTT_USER) and from device_id.get_or_set().What's new in this sketch
The subscription list is a null-terminated array of topic strings. The SDK subscribes to each one when MQTT connects, and re-subscribes automatically on every reconnect.
static const char * my_topics[] = {
"larry/device1/command",
nullptr
};This is a full MQTT topic — the same kind of string you'd type into any MQTT client. Your device is now listening for messages on larry/device1/command.
The callback fires whenever a message arrives on any subscribed topic. It receives the full topic and the payload as C strings:
void on_message(char * topic, char * message) {
// topic: "larry/device1/command"
// message: "blink"
}The blink is just a visual confirmation. When the message payload is "blink", the LED flashes five times. You could replace this with anything — toggle a relay, start a motor, change a setting.
Send a command from the dashboard
Upload the sketch and confirm it connects. Now open the dashboard and go to the Devices screen.
Find your device card and open its Controls section. Add a new control:
Type: MQTT
Name: Blink
Topic: larry/device1/command
Payload: blink
Save it. You'll see a "Blink" button on the device card. Click it.
How it works
When you clicked the button, the dashboard published the message blink to the topic larry/device1/command on the MQTT broker. Your ESP32 was subscribed to that exact topic, so the broker delivered the message. Your callback ran, matched the payload, and blinked the LED.
There's nothing OhioIoT-specific about this. The dashboard is just an MQTT client that publishes to the topic you configured. Anything that can publish MQTT can control your device — a Node.js script, a Python program, another ESP32, or a phone app.
Try adding more
Add a second command. In your callback, check for a different payload:
if (strcmp(message, "reboot") == 0) {
ESP.restart();
}Then add another control button in the dashboard with the same topic but payload reboot. One topic, multiple commands — the payload decides what happens.
