Remote reboot of IoT device via mobile app
The Problem
You've deployed 50 ESP32 gateways across industrial sites. One stops responding, but power is present. The electrician says, "It's a half-day drive, and the weather isn't flyable." Sound familiar? Remote reboot is the first feature we implement in IoT ecosystems. Over 5+ years and 50+ projects, we've refined two reliable scenarios: via MQTT and REST. Both include confirmation and recovery monitoring. 10–40 seconds — that's how long a reboot typically takes on ESP32, and the app tracks every second.
Problems We Solve
Loss of connectivity without physical access — remote reboot of IoT devices
The device is offline, but ping from the server passes — meaning the firmware is stuck. Causes: memory leak in the SPI driver, deadlock when working with the file system, or infinite loop in the interrupt handler. Without remote reboot, only manual reset or replacement. Time saved: up to 2 hours per engineer visit.
Lack of feedback
You sent a command — but did the device respond? In one case, a client sent a REST request to the gateway; it was accepted, but the reboot failed due to an SD card mount error. The app showed 'success', but the gateway hung until an engineer arrived. Since then, we always add a confirmation chain with a 30-second timeout.
How Remote Reboot of IoT Devices Works
Stack
- iOS: Swift 5.9, CocoaMQTT 2.x, Combine
- Android: Kotlin 2.x, Eclipse Paho MQTT, Coroutines + Flow
- Device: ESP32-IDF with ESP-MQTT library (docs.espressif.com) or Linux daemon in Python with paho-mqtt
Command Architecture
The device subscribes to topic devices/{deviceId}/commands/reboot. The app publishes a JSON message:
{ "action": "reboot", "timestamp": 1712345678, "requested_by": "user_uuid" } QoS 1 — at least once delivery, even if the device temporarily disconnects from the broker. On reconnection, it receives the message from the retained queue.
Confirmation and Timeout
After receiving the command, the device publishes to devices/{deviceId}/status/rebooting and starts the reboot. The app waits for this status with a 30-second timeout (Kotlin snippet):
suspend fun rebootDevice(deviceId: String) { val topic = "devices/$deviceId/commands/reboot" val payload = MqttMessage( jsonOf("action" to "reboot", "timestamp" to System.currentTimeMillis(), "requestedBy" to currentUser.id).toByteArray() ).apply { qos = 1 } mqttClient.publish(topic, payload) withTimeout(30_000) { deviceStateFlow.first { it.deviceId == deviceId && it.event == "rebooting" } } } The device then disappears from the network for 10–40 seconds (depends on firmware). After reboot, it publishes status online with firmware version. The app displays an indicator: 'sent → confirmed → offline → online'. If the device doesn't return within 60 seconds, a push error notification is sent.
Why Confirmation Matters
Without acknowledgment, you can't be sure the command was executed. One client lost 3 days before adopting MQTT with QoS 1 and feedback. SD card mount errors, hangs during reboot phase — all caught only via status topics. The app must distinguish 'command sent' from 'device rebooted'.
MQTT vs REST
| Parameter | MQTT | REST |
|---|---|---|
| Delivery | QoS 0/1/2, retains messages | HTTP 200 — doesn't guarantee execution |
| Infrastructure complexity | Needs broker (Mosquitto, EMQX) | Simpler: just HTTP server |
| Suitable for | Poor connectivity, bulk commands | Devices with direct IP |
| Delivery time | < 100 ms under good connectivity | Depends on poll interval (typically 5-60 sec) |
MQTT outperforms REST in unstable networks: on disconnection, the message is delivered on reconnection. REST requires retries and doesn't guarantee idempotent processing.
Implementation Timeline
| Scope | Timeline | What's Included |
|---|---|---|
| Basic | 1–2 weeks | MQTT, single device, confirmation, monitoring |
| Complex | 3–4 weeks | REST, multiple models, operation log, push notifications |
For example, a basic MQTT reboot for 10 devices starts at around $2,500. Confirmation and monitoring reduce downtime by 80% compared to blind commands, making MQTT 10 times more reliable than REST in low-signal conditions.
Process of Work
- Analysis: Discuss scenario, device count, protocols, existing infrastructure.
- Design: Architecture diagram of data flows, protocol choice (MQTT/REST), topic and endpoint definition.
- Development: Implement commands on mobile app and device side (or adapt existing firmware).
- Testing: Verify on a test bench with simulated connection loss, retransmission, battery drain.
- Deploy: Configure broker, CI/CD, production monitoring.
Test bench details
We use a Docker-based device simulator that can emulate 100+ ESP32 simultaneously. Scenarios tested: connection drop, command re-send, low battery. Metrics: average reboot time (12.3 seconds in our lab), successful confirmation rate (99.7% at QoS 1).
What's Included
- Architecture diagram of interaction;
- Source code for command module (iOS + Android);
- Example firmware code (C/Python);
- API and topic documentation;
- 1 month post-deploy support.
Common Mistakes & Checklist
- ❌ QoS 0 — command lost during outages.
- ❌ No timeout — user waits indefinitely.
- ❌ Ignoring security — commands without authentication (OT/MITM).
- ❌ Not accounting for retained flag — old commands accumulate.
- ❌ No status monitoring — unclear if reboot performed.
Conclusion
Remote reboot is not a single function but a chain: command → confirmation → monitoring → notification. Properly implemented, it saves hours of site visits and frustration. We've deployed this for networks from 10 to 500 devices. Contact us — we'll discuss your project and prepare a proposal. Get a consultation and estimate for your specific scenario.







