Building Embedded Web Device Dashboards
Overview
An embedded device dashboard serves as the user interface for managing and monitoring embedded systems. Whether it's for a smart home controller, an industrial automation unit, or an IoT-enabled sensor module, the embedded web dashboard provides a convenient way to interact with devices using a standard web browser. These dashboards are particularly valuable because they eliminate the need for additional software or proprietary interfaces, leveraging the universal access provided by web technologies.
Typical use cases include:
- Toggling outputs such as relays or LEDs
- Monitoring sensor data (temperature, humidity, voltage, etc.)
- Configuring network settings
- Diagnosing and troubleshooting device performance
Overview of Implementation Techniques
Building a device web dashboard requires integrating an embedded web server within the embedded device firmware. There are several techniques to render dynamic content and handle user interaction:
1. CGI (Common Gateway Interface)
The CGI technique is employed by lightweight web servers like LWIP HTTPD, a minimal web server commonly used in memory-constrained environments.
With CGI, the server maps specific URL paths to handler functions in the firmware. For example, accessing http://device-ip/led.cgi
might trigger a function in C that toggles an LED and returns HTML content as a response.
Advantages:
- Simple to implement
- Low overhead
Disadvantages:
- Not suitable for modern asynchronous UIs
- Limited interactivity
2. REST API (Representational State Transfer)
A RESTful interface allows a web dashboard to communicate with the device via HTTP requests. For example:
- GET
/api/led
– returns LED status - POST
/api/led
– writes LED
This approach separates data and presentation logic. The embedded web dashboard can be written using HTML/JS/CSS and fetch or update device states using AJAX calls to the embedded web server.
Advantages:
- Scalable and modular
- Well-supported by frontend frameworks
- Compatible with asynchronous updates (e.g., polling or WebSockets)
Disadvantages:
- Slightly more complex to implement
3. Server-Side Includes (SSI)
SSI allows embedding dynamic content into static HTML pages. In LWIP HTTPD, <!--#tag-->
style directives in HTML get replaced at runtime by server-side code.
Advantages:
- Simple to use for inserting small dynamic values (e.g., sensor readings)
Disadvantages:
- Limited flexibility for complex UIs
4. WebSocket Communication
WebSockets offer full-duplex communication channels, allowing the server to push updates to the browser. This is useful for real-time monitoring.
Advantages:
- Real-time updates
- Low-latency communication
Disadvantages:
- Requires more RAM and processing
- More complex protocol handling
5. MQTT over WebSockets
For devices already using MQTT, exposing MQTT data to a web dashboard via a WebSocket-MQTT bridge provides seamless integration.
Advantages:
- Leverages existing infrastructure
Disadvantages:
- Adds layers of complexity
All techniques rely on a properly configured embedded web server to serve content and handle client requests.
Step-by-Step: Simple REST API Implementation (LED Toggle Example)
Let's walk through a minimal example of building an embedded web dashboard using a REST API served by an embedded web server.
Step 1: Create Web Dashboard UI
web_root/index.html:
<!DOCTYPE html>
<html>
<head>
<link href="style.css" rel="stylesheet" />
</head>
<body>
<div class="main">
<h1>My Device</h1>
<span>LED status:</span>
<span id="status">0</span>
<button id="btn">Toggle LED</button>
<p><small>Note: this UI is intentionally minimal</small></p>
</div>
<script src="main.js"></script>
</body>
</html>
web_root/style.css:
.main { margin: 1em; }
#status { display: inline-block; width: 2em; }
web_root/main.js:
var getStatus = ev => fetch('api/led/get')
.then(r => r.json())
.then(r => { document.getElementById('status').innerHTML = r; });
var toggle = ev => fetch('api/led/toggle')
.then(r => getStatus());
document.getElementById('btn').onclick = toggle;
//window.addEventListener('load', getStatus);
Step 2: Set Up Embedded Web Server
Choose a lightweight server like Mongoose.
#include "mongoose.h"
static void event_handler(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_match(hm->uri, mg_str("/api/led/get"), NULL)) {
mg_http_reply(c, 200, "", "%d\n", HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0));
} else if (mg_match(hm->uri, mg_str("/api/led/toggle"), NULL)) {
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0); // Can be different on your board
mg_http_reply(c, 200, "", "true\n");
} else {
struct mg_http_serve_opts opts = {.root_dir = "/web_root", .fs = &mg_fs_packed};
mg_http_serve_dir(c, hm, &opts);
}
}
}
int main() {
struct mg_mgr mgr; // Mongoose event manager. Holds all connections
mg_mgr_init(&mgr); // Initialise event manager
mg_http_listen(&mgr, "http://0.0.0.0:80", event_handler, NULL); // Setup listener
for (;;) {
mg_mgr_poll(&mgr, 1000); // Infinite event loop
}
return 0;
}
If you point your browser against your running device, you should see this simple UI:
And here is the step-by-step explanation on the flow of requests:
This simple example demonstrates the key concepts: a REST endpoint on the embedded web server, and a frontend embedded device dashboard that sends POST requests to control hardware.
Conclusion
Implementing a device dashboard using an embedded web server offers a scalable, browser-based control panel for embedded systems. Techniques such as CGI, SSI, REST APIs, and WebSockets cater to different device capabilities and complexity requirements. For modern applications, REST APIs strike a balance between simplicity and power, making them ideal for implementing features like an embedded web dashboard.
By choosing the right implementation approach and leveraging a lightweight embedded web server, developers can craft efficient, interactive, and user-friendly dashboards to control and monitor embedded devices.