Python library and CLI for controlling Blustream audio devices
Project description
Blustream
Open-source toolkit for controlling Blustream audio devices — starting with the DMP168 digital audio matrix processor — across three home-automation surfaces.
Components
This repository is a monorepo housing three deliverables that share a single
protocol contract under spec/:
- Python library + CLI (
blustream/). A clean async Python API and ablustreamconsole script. Ships to PyPI onv*tags. - Control4 driver (
control4/dmp168/). A Lua driver packaged as a.c4zarchive that exposes the matrix as a standard Control4 audio matrix. Ships as a GitHub release with the.c4zattached onc4-v*tags. - Home Assistant integration (
custom_components/blustream/). The directory is reserved and registered with HACS; the integration code itself is deferred to a future PRD. The eventual integration will depend on the publishedblustreamPyPI library rather than re-embedding the protocol code.
The protocol primitives shared between the library and the driver are
generated from spec/protocol.yaml via the codegen tooling under
spec/codegen/. The Python and Lua emitters write into
blustream/devices/dmp168/_generated.py and
control4/dmp168/src/generated.lua respectively, and CI fails when those
committed files drift from what the spec would produce.
Independent versioning
Each component releases on its own cadence using a distinct tag prefix. The prefixes are disjoint so a tag for one component cannot accidentally trigger the wrong release workflow.
| Component | Tag prefix | Workflow | Artifact |
|---|---|---|---|
| Python library | v* |
.github/workflows/release-pypi.yml |
blustream on PyPI (sdist + wheel) |
| Control4 driver | c4-v* |
.github/workflows/release-c4z.yml |
GitHub release with attached .c4z |
| HA integration | reserved | deferred | deferred (will use HACS once built) |
For example, a library bug-fix release tags v0.2.1, while a driver-only
update tags c4-v0.3.0. The shared spec/ directory is the coordination
point when a protocol change requires both components to move in lockstep.
Installation
Python library + CLI
Once published, the library installs from PyPI:
pip install blustream
For local development from a checkout:
pip install -e ".[dev]"
Or run the CLI directly from the checkout without installing:
uvx --from . blustream --host 192.168.1.100 status
Control4 driver
Download the .c4z from the latest GitHub release
tagged c4-v* and install it through Composer Pro. See
docs/control4-driver-plan.md for the dealer-load workflow.
Library Usage
import asyncio
from blustream import DMP168
async def main():
# Connect to device
device = DMP168(host='192.168.1.100', port=23)
await device.connect()
# Read status
status = await device.get_status()
print(f"Temperature: {status.temperature}°C")
print(f"DSP Usage: {status.dsp_usage}%")
# Control device
await device.power_on()
await device.set_output_volume(1, 75, unit='percent')
await device.route_input_to_output(input_ch=2, output=1)
# Context manager support
async with DMP168(host='192.168.1.100') as device:
status = await device.get_status()
await device.power_on()
# Disconnect
await device.disconnect()
# Run the async function
asyncio.run(main())
CLI Usage
Subcommand names are derived from the command registry. Use blustream --help
to list all commands and blustream <command> --help for parameter details.
Get Device Status
blustream --host 192.168.1.100 status
Power Control
blustream --host 192.168.1.100 power-on
blustream --host 192.168.1.100 power-off
Volume Control
# Set output 1 volume to 75%
blustream --host 192.168.1.100 output-volume --output 1 --level 75
# Set output 1 volume to -10 dB
blustream --host 192.168.1.100 output-volume --output 1 --level -10 --unit dB
# Increase output 1 volume by one step
blustream --host 192.168.1.100 output-volume --output 1 --increase-level
# Decrease output 1 volume by one step
blustream --host 192.168.1.100 output-volume --output 1 --decrease-level
Mute Control
# Mute output 1
blustream --host 192.168.1.100 output-mute --output 1 --mute
# Unmute output 1
blustream --host 192.168.1.100 output-mute --output 1 --no-mute
Routing
# Route input 2 to output 1
blustream --host 192.168.1.100 route --input 2 --output 1
Presets
# Save current configuration to preset 1
blustream --host 192.168.1.100 preset-save --preset 1
# Recall preset 1
blustream --host 192.168.1.100 preset-recall --preset 1
# Get preset status
blustream --host 192.168.1.100 preset-status --preset 1
JSON Output
# Get status as JSON
blustream --host 192.168.1.100 status --json
Command Line Options
Global flags must appear before the subcommand (e.g. blustream --yes reboot, not blustream reboot --yes).
--device: Device type (default: dmp168)--host: Device hostname or IP address (default: localhost)--port: TCP port (default: 23)--timeout: Connection timeout in seconds (default: 5.0)--verbose,-v: Enable verbose output--debug: Enable debug output--json: Output results as JSON--yes,-y: Skip confirmations
Architecture
The library is designed with extensibility in mind:
- Base Framework: Abstract base classes for devices and connections
- Device Implementations: Device-specific code in separate modules
- Command Registry: Commands are registered with metadata for introspection
- Connection Layer: Pluggable connection implementations (TCP/IP, serial, etc.)
Supported Devices
- DMP168: Digital audio matrix processor (16 inputs, 8 outputs)
Development
Project Structure
blustream/
├── blustream/ # Main package
│ ├── base/ # Base classes and interfaces
│ ├── connection/ # Connection implementations
│ ├── devices/ # Device-specific implementations
│ │ └── dmp168/ # DMP168 device
│ └── cli/ # CLI implementation
├── tests/ # Test suite
├── main.py # CLI entry point
└── README.md # This file
Running Tests
pytest tests/
Lua development
The Control4 driver lives under control4/ and targets Lua 5.1 (the version
the Control4 Composer sandbox runs). CI lints all Lua sources with
luacheck and runs the unit
tests with busted — see
.github/workflows/lua.yml.
To install the toolchain locally:
# macOS
brew install lua@5.1 luarocks
luarocks --lua-version=5.1 install luacheck
luarocks --lua-version=5.1 install busted
# Debian / Ubuntu
sudo apt-get install lua5.1 liblua5.1-0-dev luarocks
sudo luarocks --lua-version=5.1 install luacheck
sudo luarocks --lua-version=5.1 install busted
Then, from the repo root:
luacheck . # lint all Lua source
busted --pattern=_spec control4/ # run Lua unit tests
License
This project is licensed under the Apache License 2.0.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Future Enhancements
See FUTURE_ENHANCEMENTS.md for planned features and improvements.
Project details
Release history Release notifications | RSS feed
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 blustream-0.1.0.tar.gz.
File metadata
- Download URL: blustream-0.1.0.tar.gz
- Upload date:
- Size: 64.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d4ef0aba54f69faf8065e99c068cd925c67db2249174ffbd25e6e33d1e81216f
|
|
| MD5 |
7a6a7e54606f6b768f53f3f85c851668
|
|
| BLAKE2b-256 |
fbf201c111ad3553d72e3053f2044d030effb25f0a204635f3d4238438b8226a
|
Provenance
The following attestation bundles were made for blustream-0.1.0.tar.gz:
Publisher:
release-pypi.yml on caidurbin/blustream
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
blustream-0.1.0.tar.gz -
Subject digest:
d4ef0aba54f69faf8065e99c068cd925c67db2249174ffbd25e6e33d1e81216f - Sigstore transparency entry: 1673471844
- Sigstore integration time:
-
Permalink:
caidurbin/blustream@409f022b2936af5b800ac8da53748300a46a1dbf -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/caidurbin
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pypi.yml@409f022b2936af5b800ac8da53748300a46a1dbf -
Trigger Event:
push
-
Statement type:
File details
Details for the file blustream-0.1.0-py3-none-any.whl.
File metadata
- Download URL: blustream-0.1.0-py3-none-any.whl
- Upload date:
- Size: 40.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f7d3b9061d7cb91fdda4673008ab1eb4ef24ab5715fe172099f17358c6baf733
|
|
| MD5 |
2e034afffd81d52435f828171893763d
|
|
| BLAKE2b-256 |
d733475a74a5d7cbe4b7b577dcd0fabaff8e28c39743f3f1277d69741acf5f58
|
Provenance
The following attestation bundles were made for blustream-0.1.0-py3-none-any.whl:
Publisher:
release-pypi.yml on caidurbin/blustream
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
blustream-0.1.0-py3-none-any.whl -
Subject digest:
f7d3b9061d7cb91fdda4673008ab1eb4ef24ab5715fe172099f17358c6baf733 - Sigstore transparency entry: 1673471854
- Sigstore integration time:
-
Permalink:
caidurbin/blustream@409f022b2936af5b800ac8da53748300a46a1dbf -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/caidurbin
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pypi.yml@409f022b2936af5b800ac8da53748300a46a1dbf -
Trigger Event:
push
-
Statement type: