Bridge a delimiter-framed TCP binary stream into JSON over WebSocket for PlotJuggler.
Project description
pj-bridge
Bridge a delimiter-framed TCP binary stream into JSON over WebSocket for PlotJuggler.
Mode: PlotJuggler runs the WebSocket Server. The bridge connects as a WebSocket client and pushes JSON messages.
What’s in this repo
derive_struct.py— Parse a C header (typedef struct { ... } Name;) and derive the Pythonstructformat and expanded field labels.tcp_parser.py— Connect to the device, parse [DE AD BE EF][COUNT][PAYLOAD] × COUNT batches into NDJSON (one JSON per line).socket_client.py— Read NDJSON (stdin or file) and forward to PlotJuggler’s WebSocket Server.bridge.py— One-process solution: connect to device, parse, and forward to PlotJuggler (no shell pipes needed).
Requirements
-
Python 3.12+
-
Device emits batches framed like:
[ 0xDE 0xAD 0xBE 0xEF ][ COUNT:1 byte ][ PAYLOAD ] * COUNT -
The payload is a packed C struct defined in a header file.
-
PlotJuggler with the WebSocket Server plugin enabled (Protocol: JSON).
Install
python3.12 -m venv .venv
source .venv/bin/activate
pip install -e .
Start PlotJuggler’s WebSocket Server
- In PlotJuggler: Streaming → WebSocket Server
- Protocol: JSON
- Port: for example 9871
- Click Start
Start Bridge
Connect to device, parse batches, forward to PJ.
Default TCP port is 5000; default WS URL is ws://127.0.0.1:9871.
Timestamps are in milliseconds by default (--ts-scale 1e-3).
python3 bridge.py \
--host 192.168.1.91 \
--struct-header /path/to/telemetry.h \
--struct-name MyStruct \
--name-prefix "device_a."
Notes:
- Add
--ws-url ws://<pj_host>:9871if PlotJuggler runs elsewhere. - If needed, guard against corrupted batches with
--max-frames-per-batch N. - To fall back to single
[DELIM][PAYLOAD](no COUNT), pass--no-counted-batch.
Two-process pipeline (for debugging)
- Derive the struct (optional sanity check). Prints JSON describing the derived
struct_fmt,fields, andrecord_size.
python3 derive_struct.py \
--header /path/to/telemetry.h \
--struct-name MyStruct \
- Parse from device to NDJSON:
python3 tcp_parser.py \
--host 192.168.1.91 \
--struct-header /path/to/telemetry.h \
--struct-name MyStruct \
--name-prefix "device_a."
- Forward NDJSON to PlotJuggler:
python3 tcp_parser.py --host 192.168.1.91 --struct-header /path/to/telemetry.h --struct-name MyStruct | python3 socket_client.py --ws-url ws://127.0.0.1:9871
Field naming
-
All non-timestamp fields are emitted with the optional prefix:
--name-prefix "device_a."
Example JSON:
{"t": 1727370023.415, "device_a.ax": 0.02, "device_a.ay": -0.01, "device_a.az": 9.81}
-
Arrays like
float gyro[3];becomedevice_a.gyro[0],device_a.gyro[1],device_a.gyro[2].
Timestamp (t)
- If
--ts-field ts_msis provided,t = ts_ms * --ts-scale(default1e-3, ms → seconds). - If no
--ts-fieldis set, arrival time is used (time.time()in seconds). - If your device time is relative (since boot) and you want wall-clock, you can add an epoch offset in code; ask if you want a ready-made flag for that.
Uninstall
- Deactivate the venv and remove the project directory, or run
pip uninstall pj-bridgeinside the venv (if installed as a package).
License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pj_bridge-0.1.2.tar.gz.
File metadata
- Download URL: pj_bridge-0.1.2.tar.gz
- Upload date:
- Size: 12.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d6ed8512a606c3dec1a547d6ad9407adc607d797ba9540816d59c9ed54e65e5d
|
|
| MD5 |
8121b4b1de8dd754d768fa511011b3f8
|
|
| BLAKE2b-256 |
d1b8f1e79d8716625f0dfd1b62ba328a5a493057ecb5c041bbfc258263e94fd2
|
Provenance
The following attestation bundles were made for pj_bridge-0.1.2.tar.gz:
Publisher:
pypi-release.yml on DephyInc/pj-bridge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pj_bridge-0.1.2.tar.gz -
Subject digest:
d6ed8512a606c3dec1a547d6ad9407adc607d797ba9540816d59c9ed54e65e5d - Sigstore transparency entry: 564759201
- Sigstore integration time:
-
Permalink:
DephyInc/pj-bridge@f1efd05053a1952ed677694d5a67f551667fea0d -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/DephyInc
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-release.yml@f1efd05053a1952ed677694d5a67f551667fea0d -
Trigger Event:
push
-
Statement type:
File details
Details for the file pj_bridge-0.1.2-py3-none-any.whl.
File metadata
- Download URL: pj_bridge-0.1.2-py3-none-any.whl
- Upload date:
- Size: 14.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30ee8b0e49f7bea93f6e3cf66fe42cf2e99c45dc6540ddd39dbb7c7be7f46227
|
|
| MD5 |
0408056126425b50993fa9485d8aed6e
|
|
| BLAKE2b-256 |
5190f1a901cd3bf016783abbbc92dbd45ed38e3c8783b70d3df074b94dcbcf22
|
Provenance
The following attestation bundles were made for pj_bridge-0.1.2-py3-none-any.whl:
Publisher:
pypi-release.yml on DephyInc/pj-bridge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pj_bridge-0.1.2-py3-none-any.whl -
Subject digest:
30ee8b0e49f7bea93f6e3cf66fe42cf2e99c45dc6540ddd39dbb7c7be7f46227 - Sigstore transparency entry: 564759206
- Sigstore integration time:
-
Permalink:
DephyInc/pj-bridge@f1efd05053a1952ed677694d5a67f551667fea0d -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/DephyInc
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-release.yml@f1efd05053a1952ed677694d5a67f551667fea0d -
Trigger Event:
push
-
Statement type: