mads-websockets is a MADS agent that exposes MADS topics over WebSockets and
can also serve a browser UI over plain HTTP. It subscribes to the MADS broker,
forwards matching MADS JSON messages to WebSocket clients, and accepts JSON
published by WebSocket clients back into the MADS network.
The bridge is implemented as a small layered runtime:
MadsTransporthandles broker-side I/O throughMads::AgentWebSocketTransporthandles client-side I/O throughlibwebsockets- the embedded web UI lives in
webas a single vanilla HTML file and is served as static assets bylibwebsockets BridgeCoreroutes validated messages between the two transports- the FSM in
src/fsm_agent_impl.hppmanages agent lifecycle
The WebSocket API is topic-oriented.
- A client connects to
ws://<host>:<port>/mads/<topic> - The WebSocket path selects the MADS topic
- The WebSocket payload is raw JSON, without any envelope
Examples:
- listen to one topic:
ws://localhost:8080/mads/perf_assess - listen to all topics:
ws://localhost:8080/mads/_all - publish JSON to one topic:
connect to
ws://localhost:8080/mads/mytopicand send the JSON payload
_all is a wildcard subscription for receiving data. A connection on
/mads/_all receives all MADS topics forwarded by the bridge.
The project expects these libraries to be available on the system:
- Mads
- libwebsockets
- readline
The current CMake configuration finds Mads with find_package(Mads CONFIG) and
finds libwebsockets through pkg-config. The terminal QR helper dependency
libqrcode is fetched automatically with CMake FetchContent.
Configure and build with CMake and Ninja:
cmake -B build -G Ninja
cmake --build buildThis produces two executables:
build/src/mads-websocketsbuild/src/ws_client
Run the unit test target with:
ctest --test-dir build --output-on-failureThe bridge reads its settings from the MADS broker or from a local mads.ini
file, depending on how the agent is launched.
A typical settings block is:
[websockets]
ws_port = 8080
ws_silent = true
sub_topic = [""]Relevant settings:
ws_host: interface to bind, default0.0.0.0ws_port: WebSocket server port, default9002ws_path: WebSocket root path, default/madshttp_enabled: serve the browser UI, defaulttruehttp_host: HTTP bind interface, default0.0.0.0http_port: HTTP UI port, default8080http_path: HTTP UI root path, default/madsperiod: FSM loop period in millisecondsreceive_timeout: MADS receive timeout in millisecondsws_silent: iftrue, suppresslibwebsocketslog messagessub_topic: MADS subscription topics for the bridge agent
sub_topic = [""] subscribes the bridge to all MADS topics.
Typical usage with broker-hosted settings:
./build/src/mads-websockets tcp://localhost:9092You can also override the agent name:
./build/src/mads-websockets --name websockets tcp://localhost:9092At startup the agent prints the standard MADS info block, then:
Websocket addr: ws://<host>:<port>/madsfor each detected external IPv4 endpointHTTP UI addr: http://<host>:<port>/madsfor each detected external IPv4 endpoint when HTTP is enabledBrowser QR:containing the first detected HTTP UI URLConnected clients: N
The connected client count is updated in place whenever a client connects or disconnects.
The repository includes a lightweight browser UI under web. It is a
single index.html file with inline CSS and JavaScript — no build tools, no
Node.js, no npm required. During the CMake build the contents of web/ are
embedded into the binary and served at http://<host>:<http_port>/mads.
The browser page fetches http://<host>:<http_port>/bootstrap.json from the
same origin to learn the WebSocket scheme, port, and path.
The UI provides two tabs:
- Listen — subscribe to one or more MADS topics (or
_all) and view incoming JSON messages in a collapsible tree - Publish — pick a topic, edit a JSON payload, and send it into the MADS network
All settings (topics, draft message, publish history) are persisted in
localStorage.
To enable the browser UI, launch the agent with the option
-wor--webserver.NOTE: upon launch, the command
mads-websockets -wpresents a QR code that links to the WebUI. Since the latter is exposed on unencrypted http://, though, come smartphone could point the browser tohttps://<ip>:8080, which is not available. If that happens, just manually edit the URL fromhttps://<ip>:8080tohttp://<ip>:8080(no 's').
ws_client is a simple CLI tool for testing the bridge.
-a, --address: base WebSocket address, defaultws://localhost:8080-t, --topic: repeatable topic name appended as/mads/<topic>-l, --listen: listen and print incoming JSON to stdout-p, --publish: read JSON from stdin usingreadlineand publish it--debug: enablelibwebsocketslogs
If no -t is given in listen mode, the default topic is _all.
Publish mode requires exactly one explicit -t.
Listen to all topics:
./build/src/ws_client -a ws://localhost:8080 -lListen to one topic:
./build/src/ws_client -a ws://localhost:8080 -t perf_assess -lListen to multiple selected topics:
./build/src/ws_client \
-a ws://localhost:8080 \
-t perf_assess \
-t agent_event \
-lEach topic opens its own WebSocket connection under the same client process.
Publish to one topic:
./build/src/ws_client -a ws://localhost:8080 -t mytopic -pThen type JSON payloads at the prompt, for example:
{"value": 42}An empty line exits publish mode.
- MADS messages are forwarded to WebSocket clients as raw JSON
- WebSocket client messages are published into MADS as raw JSON
- one WebSocket connection corresponds to one topic path
_allis supported for wildcard receive subscriptions- multiple topic subscriptions on the client side are implemented as multiple WebSocket connections
- CURVE-related CLI flags are accepted by
mads-websocketsfor interface compatibility with other MADS commands, but bridge-specific crypto handling is not implemented here. remote_controlis intentionally not used in this application.