Skip to main content

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. img/cli.png 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.v1 subprotocol.
  • 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 json and protobuf encoded 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

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:

  1. zmq_relay.py: A simple script to run the relay, must be run first. Defaults to PUSH/PULL mode on ZMQ bind tcp://localhost:5555.
  2. zmq_puller.py: A ZMQ PULL client that connects to the relay and prints received messages.
  3. zmq_subber.py: A ZMQ SUB client that connects to the relay and subscribes to all topics.

Project Structure

foxglove2zmq/
├── foxglove2zmq/  
│   ├── __init__.py 
│   └── cli.py
│   └── relay.py
├── examples/
│   ├── zmq_puller.py 
│   └── zmq_relay.py
├── README.md
├── requirements.txt  
└── setup.py

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

foxglove2zmq-0.1.0.tar.gz (11.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

foxglove2zmq-0.1.0-py3-none-any.whl (10.1 kB view details)

Uploaded Python 3

File details

Details for the file foxglove2zmq-0.1.0.tar.gz.

File metadata

  • Download URL: foxglove2zmq-0.1.0.tar.gz
  • Upload date:
  • Size: 11.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.9.6

File hashes

Hashes for foxglove2zmq-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a203f3a8400b679220c3e8c8c2b8d85bef30d32042431ec9cfd79e04b1eac13e
MD5 22792c878703c7fa8ea8b105bb24bb15
BLAKE2b-256 a4ffea5afc6b816f332906b72cf0589e305f8d7bfcb9412f492e9f3e867d1521

See more details on using hashes here.

File details

Details for the file foxglove2zmq-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: foxglove2zmq-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.9.6

File hashes

Hashes for foxglove2zmq-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b1d6f801284bc4aefcdbaa3b200778d10bfcf4dcb1a56fc8331acecf8109d9ca
MD5 519c2048b7c80f268317b7913dc91c25
BLAKE2b-256 3b4b80ecf20a83d683fec624a1eb9c470730c6cf57e142988783ad70e6823a54

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page