python-bitchat-client is a small, headless Python package for integrating with the
BitChat BLE mesh protocol. It comes with a basic sample client application, but it's
intended to be embedded and used by other tools.
It doesn't currently implement channel discovery.
- A minimal client interface (
BitChatClient) for:- starting/stopping BLE mesh connectivity
- joining a channel (defaults to
#mesh) - receiving inbound messages via callback
- sending text messages to the current channel
- receiving status telemetry (connected, disconnected, retries, errors)
- A BLE implementation (
BleBitChatClient) powered bybleak - A fallback no-op implementation (
NullBitChatClient) when BLE backend is not available - Protocol helpers for packet parsing/building
- Flood relay/rebroadcast with TTL decrement for transit packets
- Swappable dedupe cache (default exact LRU+TTL cache)
You can install this package from pypi using pip install python-bitchat-client
from python_bitchat_client import create_client
client = create_client()
client.set_handle("crystal-jim")
client.join_channel("#mesh")
def on_message(msg):
print(f"[{msg.channel}] <{msg.sender}> {msg.text}")
def on_status(status):
print(f"[{status.level}] {status.code}: {status.detail}")
client.set_message_handler(on_message)
client.set_status_handler(on_status)
client.start()
ok = client.send_message("@crystal-jim say hello from python")
print("sent:", ok)- Inbound packets with
ttl > 1may be relayed withttl - 1. - Relay suppression uses a dedupe key of
sender_id + timestamp + message_type. - Default dedupe is an exact in-memory LRU cache with TTL expiry (no false positives).
You can inject your own dedupe cache at construction time. If omitted, a default
LruTtlDedupeCache instance is created.
from python_bitchat_client.client import create_client
class BloomLikeCache:
def is_duplicate(self, key: str) -> bool:
...
def mark_seen(self, key: str) -> None:
...
client = create_client(dedupe_cache=BloomLikeCache())Note: probabilistic dedupe caches (for example Bloom filters) can produce false positives and may suppress legitimate relays.
A simple terminal harness is included for manual send/receive testing.
Path:
examples/terminal_harness.py
Run from repository root:
uv run python examples/terminal_harness.py --handle my-handle --channel "#mesh"
# Verbose packet/transport debugging
uv run python examples/terminal_harness.py --handle my-handle --channel "#mesh" --log-level DEBUGHarness commands:
- Type any line and press Enter to send it to the channel
/quitor/exitto stop/helpto print command help--log-level DEBUGto include package debug logs
Inbound channel messages are printed to stdout while the prompt remains active.
- This package does not require running your whole app as root.
- BLE access depends on host Bluetooth policy.
- On Linux, you typically need:
bluetoothdrunning- user permission to access BlueZ over D-Bus
- distro-specific group/polkit setup
If no peer is found, the client reports status code no_peer_found and keeps retrying.
Common status codes emitted by the BLE client:
startingpeer_foundconnecteddisconnectedno_peer_foundconnect_failedsend_failedstoppedbackend_unavailable(fallback client)
Run package-related tests from repository root:
uv run pytest tests/test_python_bitchat_client_protocol.py tests/test_python_bitchat_client_client.pySet up pre-commit hooks:
uvx pre-commit install
uvx pre-commit run --all-files