An async Python client for controlling Pulse8 HDBaseT Matrix devices via their REST API.
Project description
Pulse8 HDBaseT Matrix Client
An async Python client for controlling Pulse8 HDBaseT Matrix devices via their REST API.
Features
- ✅ Fully async using
aiohttp - ✅ Type hints throughout
- ✅ Comprehensive data models
- ✅ Easy-to-use API
- ✅ Route by port number or name
- ✅ Context manager support
- ✅ Proper error handling
Installation
Using uv:
uv pip install -e .
Or with pip:
pip install -e .
Quick Start
import asyncio
from pulse_eight_matrix_client import PulseEightMatrixClient
async def main():
# Connect to your matrix
async with PulseEightMatrixClient(host="192.168.1.150") as client:
# Get system info
details = await client.get_system_details()
print(f"Model: {details.model}, Version: {details.version}")
# List all ports
ports = await client.get_ports()
for port in ports:
print(f"{port.mode} {port.bay}: {port.name}")
# Route input to output
await client.set_port(input_bay=7, output_bay=5)
# Or route by name
await client.route_by_name("Sky", "Bedroom TV")
asyncio.run(main())
Auto-Polling for Instant State Access
Enable background polling to maintain cached state. This eliminates HTTP calls when querying routing information:
import asyncio
from pulse_eight_matrix_client import CachingPulseEightMatrixClient
async def main():
# Enable auto-polling (polls every 5 seconds by default)
async with CachingPulseEightMatrixClient(
host="192.168.1.150",
poll_interval=5
) as client:
# All get_ports() calls now return from cache instantly!
ports = await client.get_ports()
# Check routing from cache (no HTTP call)
routing = client.get_cached_routing_map()
# See which input feeds an output (instant)
source = client.get_cached_output_source(output_bay=5)
# Find where an input is going (instant)
destinations = client.get_cached_input_destinations(input_bay=7)
# Changes automatically update the cache
await client.set_port(7, 5)
Benefits of auto-polling:
- Zero latency for state queries - no HTTP overhead
- Always up-to-date - background polling keeps state fresh
- Automatic updates - cache refreshes after routing changes
- Real-time monitoring - detect changes as they happen
API Reference
Client Initialization
from pulse_eight_matrix_client import PulseEightMatrixClient
client = PulseEightMatrixClient(
host="192.168.1.150",
port=80,
timeout=10,
)
Parameters:
host: IP address or hostname of the matrixport: HTTP port (default: 80)timeout: Request timeout in seconds (default: 10)
System Methods
get_system_details() -> SystemDetails
Get system information including model, version, serial number, and status.
details = await client.get_system_details()
print(f"Model: {details.model}")
print(f"Version: {details.version}")
print(f"Serial: {details.serial}")
print(f"Status: {details.status_message}")
get_system_features() -> SystemFeatures
Get system features and capabilities.
features = await client.get_system_features()
print(f"HDBaseT: {features.hdbaset}")
print(f"Input Bays: {features.video.input['Bays']}")
Port Methods
get_ports() -> List[Port]
Get list of all ports (inputs and outputs).
When using CachingPulseEightMatrixClient, use get_cached_ports() to return cached data instantly. get_ports() will always perform a live HTTP call.
ports = await client.get_ports()
for port in ports:
print(f"{port.mode} {port.bay}: {port.name}")
get_ports() on CachingPulseEightMatrixClient
Get list of all ports with a fresh HTTP call, bypassing cache.
# Always fetches from the matrix, even with auto_poll enabled
ports = await client.get_ports()
#### `get_input_ports() -> List[Port]`
Get list of input ports only.
#### `get_output_ports() -> List[Port]`
Get list of output ports only.
#### `get_input_details(bay: int) -> PortDetails`
Get detailed information about an input port.
```python
details = await client.get_input_details(7)
print(f"Has Signal: {details.has_signal}")
print(f"Signal: {details.signal}")
get_output_details(bay: int) -> PortDetails
Get detailed information about an output port.
Routing Methods
set_port(input_bay: int, output_bay: int) -> SetPortResponse
Route an input to an output by bay numbers.
response = await client.set_port(input_bay=7, output_bay=5)
print(response.message) # "Changed"
route_by_name(input_name: str, output_name: str) -> SetPortResponse
Route an input to an output by port names (case-insensitive).
await client.route_by_name("Sky", "Bedroom TV")
get_port_by_name(name: str) -> Optional[Port]
Find a port by its name.
port = await client.get_port_by_name("Kitchen TV")
if port:
print(f"Found: {port.mode} bay {port.bay}")
Cached Query Methods
These methods only work when auto_poll=True and return data instantly from the cache without making HTTP calls.
get_cached_output_source(output_bay: int) -> Optional[int]
Get which input is currently routed to an output.
# Requires auto_poll=True
source = client.get_cached_output_source(5)
if source is not None:
print(f"Output 5 is receiving from Input {source}")
get_cached_input_destinations(input_bay: int) -> List[int]
Get which outputs are receiving from an input.
# Requires auto_poll=True
destinations = client.get_cached_input_destinations(7)
print(f"Input 7 is routed to outputs: {destinations}")
get_cached_routing_map() -> Dict[int, int]
Get a complete mapping of all outputs to their source inputs.
# Requires auto_poll=True
routing = client.get_cached_routing_map()
# Returns: {output_bay: input_bay, ...}
# Example: {0: 1, 2: 0, 5: 7}
get_last_poll_time() -> Optional[float]
Get the Unix timestamp of the last successful poll.
timestamp = client.get_last_poll_time()
get_cache_age() -> Optional[float]
Get the age of the cached data in seconds.
age = client.get_cache_age()
print(f"Cache is {age:.1f} seconds old")
get_cached_ports() -> List[Port]
Get all ports from the cached state.
# Only available on CachingPulseEightMatrixClient
ports = client.get_cached_ports()
for port in ports:
print(f"{port.mode} {port.bay}: {port.name}")
SystemDetails
model: Device model (e.g., "FF88A")version: Firmware versionserial: Serial numbermac: MAC addressstatus_message: Current statusstatus: Status code
Port
bay: Port bay numbermode: "Input" or "Output"type: Port type (e.g., "HDMI2", "HDBT-TXLITE")status: Connection statusname: User-assigned namereceive_from: (Output only) Which input it's receiving from
PortDetails
Extends Port with additional fields:
has_signal: Whether signal is detectedsignal: Signal informationhdcp: HDCP statusallowed_sinks: List of allowed output bays
Error Handling
The client raises specific exceptions for different error types:
from pulse_eight_matrix_client import (
PulseEightConnectionError,
PulseEightAPIError
)
try:
async with PulseEightMatrixClient(host="192.168.1.150") as client:
await client.set_port(7, 5)
except PulseEightConnectionError as e:
print(f"Connection failed: {e}")
except PulseEightAPIError as e:
print(f"API error: {e}")
Context Manager
The client supports async context managers for automatic session management:
# Session is automatically created and closed
async with PulseEightMatrixClient(host="192.168.1.150") as client:
await client.get_ports()
Or manage the session manually:
client = PulseEightMatrixClient(host="192.168.1.150")
await client.connect()
try:
await client.get_ports()
finally:
await client.close()
Monitoring Example
Below is a minimal example using CachingPulseEightMatrixClient. It polls in the background and allows instant reads from the cache.
async def monitor_matrix():
async with CachingPulseEightMatrixClient(
host="192.168.1.150",
poll_interval=5,
) as client:
while True:
routing = client.get_cached_routing_map()
print(f"Routing map: {routing}")
await asyncio.sleep(1)
Development
Install development dependencies:
uv pip install -e ".[dev]"
Run tests:
pytest
License
MIT
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 pulse_eight_matrix_client-0.5.0.tar.gz.
File metadata
- Download URL: pulse_eight_matrix_client-0.5.0.tar.gz
- Upload date:
- Size: 8.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b276c4ddcbb01443541e5ff1763a8993fe7ed4aff5af5f0116f76b550517d6c9
|
|
| MD5 |
545d229bd1a4abd9ecd017d975779316
|
|
| BLAKE2b-256 |
919136f9104b49963ef24af6ef0ae1bcfd394e32b03fcd9e48b577f1b28d2d89
|
File details
Details for the file pulse_eight_matrix_client-0.5.0-py3-none-any.whl.
File metadata
- Download URL: pulse_eight_matrix_client-0.5.0-py3-none-any.whl
- Upload date:
- Size: 10.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0ccbf1541c37758fb4d8b57d706d5e0c5eb8314e95ec8ac936ccce6780990311
|
|
| MD5 |
d7c4356a95b118193134f8f590c3f9c2
|
|
| BLAKE2b-256 |
2500299dbf2de5456043ed858f3f55b904dd6d430a7ca3f398cf5935d0b0c1fb
|