ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
web_terminal.h
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 web_terminal.h
6 * @brief Browser "web serial" terminal over WebSocket (PC_ENABLE_WEB_TERMINAL).
7 *
8 * A zero-heap equivalent of the WebSerial-style remote serial monitor: it serves
9 * a self-contained terminal web page and a WebSocket endpoint on the same path.
10 * Device output is broadcast to every connected browser; each line a browser
11 * sends is delivered to a command callback. Rides the library's existing
12 * WebSocket layer (no extra connection state), so it is TLS-agnostic - the page
13 * auto-selects ws:// or wss:// from the page's own scheme.
14 *
15 * @code
16 * static const pc_field SAID[] = {{PC_FK_LIT, 0, 10, "you said: "}, PC_STR,
17 * {PC_FK_LIT, 0, 1, "\n"}, PC_END};
18 * static const pc_field UPTIME[] = {{PC_FK_LIT, 0, 7, "uptime "}, PC_U32,
19 * {PC_FK_LIT, 0, 1, "\n"}, PC_END};
20 * void on_cmd(const char *line, uint8_t client) {
21 * pc_web_terminal_frame(SAID, line);
22 * }
23 * void setup() {
24 * // ... wifi + server.on(...) ...
25 * pc_web_terminal_begin(server, "/terminal");
26 * pc_web_terminal_on_command(on_cmd);
27 * server.begin(80);
28 * }
29 * void loop() {
30 * server.handle();
31 * pc_web_terminal_frame(UPTIME, (uint32_t)millis()); // device -> browsers
32 * }
33 * @endcode
34 *
35 * No-op stubs when PC_ENABLE_WEB_TERMINAL is 0.
36 */
37
38#ifndef PROTOCORE_WEB_TERMINAL_H
39#define PROTOCORE_WEB_TERMINAL_H
40
41#include "protocore.h"
43
44#if PC_ENABLE_WEB_TERMINAL
45
46/**
47 * @brief Callback for a line typed in a connected browser terminal.
48 * @param line Null-terminated command text (no trailing newline).
49 * @param client_id WebSocket client index that sent it (ws_pool[] slot).
50 */
51typedef void (*TermCommandCb)(const char *line, uint8_t client_id);
52
53/**
54 * @brief Register the terminal page + WebSocket endpoint on @p server.
55 *
56 * Serves the HTML page at @p path (GET) and accepts the terminal WebSocket at
57 * `<path>/ws`. Call before server.begin().
58 *
59 * @param server The web server to attach to (must outlive the terminal).
60 * @param path URL path for the page (default "/terminal").
61 */
62void pc_web_terminal_begin(PC &server, const char *path = "/terminal");
63
64/** @brief Install the command callback (browser -> device). Pass nullptr to clear. */
65void pc_web_terminal_on_command(TermCommandCb cb);
66
67/** @brief Broadcast text to every connected terminal browser (device -> browsers). */
68void pc_web_terminal_print(const char *s);
69
70/** @brief Like print() but appends a newline. */
71void pc_web_terminal_println(const char *s);
72
73/**
74 * @brief Build @p spec and broadcast it to every connected browser (capped at TERM_TX_BUF_SIZE).
75 *
76 * The message shape is a `static const pc_field[]` the caller declares, so a terminal line costs a
77 * table walk rather than a format-string parse.
78 */
79void pc_web_terminal_frame(const pc_field *spec, ...);
80
81/** @brief Number of browsers currently connected to the terminal. */
82uint8_t pc_web_terminal_client_count();
83
84#else // PC_ENABLE_WEB_TERMINAL == 0 -> no-op stubs
85
86typedef void (*TermCommandCb)(const char *line, uint8_t client_id);
87static inline void pc_web_terminal_begin(PC &, const char * = "/terminal")
88{
89}
90static inline void pc_web_terminal_on_command(TermCommandCb)
91{
92}
93static inline void pc_web_terminal_print(const char *)
94{
95}
96static inline void pc_web_terminal_println(const char *)
97{
98}
99static inline void pc_web_terminal_frame(const pc_field *, ...)
100{
101}
102static inline uint8_t pc_web_terminal_client_count()
103{
104 return 0;
105}
106
107#endif // PC_ENABLE_WEB_TERMINAL
108
109#endif // PROTOCORE_WEB_TERMINAL_H
Single-port HTTP server with deterministic, zero-allocation execution.
Definition protocore.h:348
Declarative frame builder: a frame is a static table of typed fields, built by one engine.
Layer 7 (Application) - public HTTP routing API.
One field of a frame. Frames are static const pc_field[], so they live in rodata.
Definition frame.h:80
void(* TermCommandCb)(const char *line, uint8_t client_id)