DeterministicESPAsyncWebServer v6.28.0
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
dashboard_routes.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file dashboard_routes.cpp
6 * @brief Dashboard server wiring: page, layout JSON, and SSE value stream.
7 *
8 * Separated from the host-testable core (dashboard.cpp) so the serializers can be
9 * unit-tested without pulling in the server. Requires DETWS_ENABLE_SSE.
10 */
11
13
14#if DETWS_ENABLE_DASHBOARD
15
16// Dependency (DASHBOARD requires SSE) is enforced centrally in ServerConfig.h.
17
18#include "dwserver.h"
19#include "network_drivers/application/web_assets.h" // DETWS_DASHBOARD_PAGE
21#include <stdio.h>
22#if DETWS_ENABLE_WEBSOCKET
23#include "network_drivers/presentation/websocket/websocket.h" // ws_pool for inbound control messages
24#endif
25
26// All dashboard-routes state, owned by one instance (internal linkage): the server handle and
27// the SSE / WebSocket paths, grouped so it is one named owner, unreachable cross-TU. (The route
28// handlers are fixed-signature callbacks, so they reach this single owner directly.)
29struct DashRoutesCtx
30{
31 DetWebServer *srv = nullptr;
32 char stream_path[MAX_PATH_LEN] = {0};
33#if DETWS_ENABLE_WEBSOCKET
34 char ws_path[MAX_PATH_LEN] = {0};
35#endif
36};
37static DashRoutesCtx s_dashr;
38
39static void dash_page_handler(uint8_t slot_id, HttpReq *req)
40{
41 (void)req;
42 if (s_dashr.srv)
43 s_dashr.srv->send(slot_id, 200, DET_MIME_TEXT_HTML, DETWS_DASHBOARD_PAGE);
44}
45
46static void dash_layout_handler(uint8_t slot_id, HttpReq *req)
47{
48 (void)req;
50 detws_dashboard_layout_json(buf, sizeof(buf));
51 if (s_dashr.srv)
52 s_dashr.srv->send(slot_id, 200, DET_MIME_JSON, buf);
53}
54
55static void dash_sse_connect(uint8_t sse_id)
56{
58 if (s_dashr.srv && detws_dashboard_values_json(buf, sizeof(buf)) > 0)
59 s_dashr.srv->sse_send(sse_id, buf); // seed the new client with the latest values
60}
61
62#if DETWS_ENABLE_WEBSOCKET
63static void dash_ws_connect(uint8_t ws_id)
64{
65 (void)ws_id;
66}
67static void dash_ws_message(uint8_t ws_id)
68{
69 // Control widgets send {"k":"<key>","v":<num>}; parse + dispatch to the callback.
70 if (ws_id < MAX_WS_CONNS)
71 detws_dashboard_dispatch_control(ws_payload(ws_id));
72}
73static void dash_ws_close(uint8_t ws_id)
74{
75 (void)ws_id;
76}
77#endif
78
79void detws_dashboard_begin(DetWebServer &server, const char *path, const DetwsWidget *widgets, uint8_t count)
80{
81 s_dashr.srv = &server;
82 detws_dashboard_configure(widgets, count);
83
84 if (!path || !path[0])
85 path = "/dashboard";
86
87 char layout_path[MAX_PATH_LEN];
88 snprintf(layout_path, sizeof(layout_path), "%s/layout", path);
89 snprintf(s_dashr.stream_path, sizeof(s_dashr.stream_path), "%s/stream", path);
90
91 server.on(path, HttpMethod::HTTP_GET, dash_page_handler);
92 server.on(layout_path, HttpMethod::HTTP_GET, dash_layout_handler);
93 server.on_sse(s_dashr.stream_path, dash_sse_connect);
94#if DETWS_ENABLE_WEBSOCKET
95 snprintf(s_dashr.ws_path, sizeof(s_dashr.ws_path), "%s/ws", path);
96 server.on_ws(s_dashr.ws_path, dash_ws_connect, dash_ws_message, dash_ws_close);
97#endif
98}
99
100void detws_dashboard_publish()
101{
102 if (!s_dashr.srv)
103 return;
104 char buf[DETWS_DASHBOARD_JSON_BUF];
105 if (detws_dashboard_values_json(buf, sizeof(buf)) > 0)
106 s_dashr.srv->sse_broadcast(s_dashr.stream_path, buf);
107}
108
109#endif // DETWS_ENABLE_DASHBOARD
#define DETWS_DASHBOARD_JSON_BUF
Stack buffer for the dashboard layout / values JSON (bytes).
#define MAX_PATH_LEN
Maximum URL path length (including leading /).
#define MAX_WS_CONNS
Maximum simultaneous WebSocket connections.
Single-port HTTP server with deterministic, zero-allocation execution.
Definition dwserver.h:348
void on(const char *path, HttpMethod method, Handler callback)
Register a route handler.
Definition dwserver.cpp:759
Real-time SVG telemetry dashboard (DETWS_ENABLE_DASHBOARD).
Layer 7 (Application) - public HTTP routing API.
@ HTTP_GET
Safe, idempotent read.
Shared HTTP Content-Type ("MIME") string constants (one source of truth).
Fully-parsed HTTP/1.1 request.
const char DETWS_DASHBOARD_PAGE[]
Real-time SVG telemetry dashboard page (DETWS_ENABLE_DASHBOARD).
Layer 7 (Application) - embedded web assets generated from src/web/input/.
const char * ws_payload(uint8_t ws_id)
The NUL-terminated reassembled message payload for ws_id, or nullptr if the slot is out of range / in...
Definition websocket.cpp:45
Layer 6 (Presentation) – WebSocket frame parser and connection pool.