A relay for forwarding Foxglove WebSocket messages to a ZMQ server.
Project description
Foxglove to ZMQ Relay
A Python utility to connect to a Foxglove WebSocket server, decode messages (JSON and Protobuf), and relay them to a ZMQ server using either a PUSH/PULL or PUB/SUB pattern.
This is useful for integrating Foxglove data streams with other backend services, logging systems, or robotics
frameworks that use ZMQ for messaging. Also includes a command-line interface (foxglove2zmq) for easy setup and
configuration!
Features
- Connects to any Foxglove WebSocket Server: Natively connects using the
foxglove.sdk.v1subprotocol. - Automatic Channel Discovery: Discovers all available channels on connect.
- Topic Filtering: Easily blocklist topics you don't want to relay.
- Multi-Encoding Support: Decodes both standard
jsonandprotobufencoded messages on the fly. - Dynamic Protobuf Decoding: Parses Protobuf schemas
(
FileDescriptorSet) provided by the server to decode binary payloads into JSON. - Flexible ZMQ Patterns:
PUSH/PULL: Relays all messages to a single stream for worker distribution.PUB/SUB: Publishes messages on their original Foxglove topic for selective subscription.
- Handles Large Messages: Configured to accept WebSocket messages of any size.
Todo
- Add support for bi-directional messaging with
ClientPublishmessages andParameterupdates. - Add support for other binary messages:
-
0x02- Time -
0x03- Service call responses -
0x04- Fetch asset responses
-
Installation
You can install the package from PyPI:
pip install foxglove-zmq-relay
Alternatively, you can install it directly from the GitHub repository:
pip install git+https://github.com/helkebir/foxglove2zmq.git
Usage
The relay is designed to be run as a standalone script. You can import and use the classes in your own applications.
Command-Line Examples
A basic script is provided to run the relay from the command line. You can choose which ZMQ pattern to use. Currently,
the PUSH/PULL and PUB/SUB patterns are implemented.
A command-line interface is available via the foxglove2zmq command after installation.
foxglove2zmq --help
usage: foxglove2zmq [-h] -p {push,pub} [-w FOXGLOVE_WS] -z ZMQ_BIND [-v VERBOSITY] [-b [BLOCKLIST ...]] [--timeout TIMEOUT]
Relay Foxglove WebSocket messages to a ZMQ server.
optional arguments:
-h, --help show this help message and exit
-p {push,pub}, --pattern {push,pub}
The ZMQ socket pattern to use ('push' for PUSH/PULL or 'pub' for PUB/SUB).
-w FOXGLOVE_WS, --foxglove-ws FOXGLOVE_WS
The WebSocket URL of the Foxglove server (e.g., ws://localhost:8765).
-z ZMQ_BIND, --zmq-bind ZMQ_BIND
The TCP address for the ZMQ server to bind to (e.g., tcp://localhost:5555).
-v VERBOSITY, --verbosity VERBOSITY
The verbosity level (0 = errors only, 1 = info, 2 = debug).
-b [BLOCKLIST ...], --blocklist [BLOCKLIST ...]
A space-separated list of topics to ignore (e.g., /diagnostics /debug).
--timeout TIMEOUT Time in seconds to wait for channel advertisements.
PUSH/PULL Relay
This is the simplest pattern. It sends all messages from all topics to any connected ZMQ PULL client.
# In one terminal, run the relay
foxglove2zmq --pattern push --foxglove-ws ws://localhost:8765 --zmq-bind tcp://localhost:5555
And in another terminal, run a ZMQ PULL client to receive messages:
# ZMQ PULL client example (client.py)
import zmq
import json
context = zmq.Context()
socket = context.socket(zmq.PULL)
socket.connect("tcp://localhost:5555")
print("Receiving messages...")
while True:
msg_str = socket.recv_string()
msg_obj = json.loads(msg_str)
print(json.dumps(msg_obj, indent=2))
PUB/SUB Relay
This pattern publishes each message on its original Foxglove topic. ZMQ SUB clients can then subscribe to specific topics.
# In one terminal, run the relay
foxglove2zmq --pattern pub --foxglove-ws ws://localhost:8765 --zmq-bind tcp://localhost:5555
And in another terminal, run a ZMQ SUB client to receive messages from a specific topic:
# ZMQ SUB client example (client.py)
import zmq
import json
context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.connect("tcp://localhost:5555")
# Subscribe to a specific topic (e.g., /sensor/camera)
# To subscribe to all topics, use b""
socket.setsockopt(zmq.SUBSCRIBE, b"/sensor/camera")
print("Receiving messages...")
while True:
topic, msg_str = socket.recv_multipart()
msg_obj = json.loads(msg_str)
print(f"Topic: {topic.decode()}")
print(json.dumps(msg_obj, indent=2))
Library Usage
You can also import the classes into your own Python application for more advanced control.
import asyncio
from src.foxglove2zmq import FoxgloveToZMQPushRelay, FoxgloveToZMQPubSubRelay
async def main():
# Example for PUSH relay
push_relay = FoxgloveToZMQPushRelay(
foxglove_address="ws://localhost:8765",
zmq_address="tcp://localhost:5555",
topic_blocklist=["/diagnostics"],
discovery_timeout=5.0
)
await push_relay.run()
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
print("Relay stopped by user.")
Library Example
You can find example scripts in the examples/ directory that demonstrate how to use the relay in different scenarios,
including both PUSH/PULL and PUB/SUB patterns. First install the package, then run the examples:
zmq_relay.py: A simple script to run the relay, must be run first. Defaults toPUSH/PULLmode on ZMQ bindtcp://localhost:5555.zmq_puller.py: A ZMQPULLclient that connects to the relay and prints received messages.zmq_subber.py: A ZMQSUBclient that connects to the relay and subscribes to all topics.
Project Structure
foxglove2zmq/
├── src/
│ └── foxglove2zmq/
│ ├── __init__.py
│ ├── relay.py
│ └── cli.py
├── examples/
│ ├── zmq_puller.py
│ └── zmq_relay.py
├── LICENSE.md
├── pyproj.toml
├── README.md
└── requirements.txt
License
This project is licensed under the MIT License; see the LICENSE file for details.
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 foxglove2zmq-0.1.1.tar.gz.
File metadata
- Download URL: foxglove2zmq-0.1.1.tar.gz
- Upload date:
- Size: 11.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3cb09e554d708ff9221b98e6327fb5363d107b62fb890ae64064d2297fe61bce
|
|
| MD5 |
9120fa96203fd60d3d51112ed8420164
|
|
| BLAKE2b-256 |
d2f93ece7d2b5d0cd459d8ec0dad50927001fe430a26ace3ac0b6080c697afb0
|
File details
Details for the file foxglove2zmq-0.1.1-py3-none-any.whl.
File metadata
- Download URL: foxglove2zmq-0.1.1-py3-none-any.whl
- Upload date:
- Size: 10.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
766d3a9f7cb910196f5bb645bdef526b4da8984889e59c83e551b8894017eb65
|
|
| MD5 |
e0a302b910df883db89be63124cd1521
|
|
| BLAKE2b-256 |
af92a13a75ec7d2a10a30f38e5dd09180afe5a056a357addcf6d44510dba72ca
|