HA-agnostic Sony BRAVIA Connect ControlDeviceService client
Project description
pybravia-connect
HA-agnostic Python client for Sony BRAVIA Connect local gRPC
(ControlDeviceService).
This is a protocol library, not a Home Assistant integration. Integrations that speak BRAVIA Connect (for example bravia-quad-homeassistant and bravia-tv-grpc-homeassistant) can depend on this package once cut over.
Protocol code was extracted from those integrations (MIT). Thanks to @steamEngineer and @braviafanboy.
Status
Alpha (0.1.x on PyPI). APIs may change before 1.0. See
CHANGELOG.md for release history. Apps that need a fixed
surface can pin a specific version in their own lockfile.
Install
Requires Python 3.12+.
pip install pybravia-connect
For TV app-list and icon reads (AES-GCM decrypt):
pip install "pybravia-connect[crypto]"
For local development:
pip install -e ".[dev]"
Quickstart
Obtain credentials JSON first (see Credentials CLI), then:
from pybravia_connect import (
BraviaConnectClient,
DEFAULT_THEATRE_PORT,
load_credentials,
)
HOST = "192.168.x.x"
CREDS_PATH = "/path/to/session_keys.json" # never commit
creds = load_credentials(CREDS_PATH)
client = BraviaConnectClient(
HOST,
DEFAULT_THEATRE_PORT, # or discover_grpc_port(HOST) for TVs
creds["device_id"],
creds["hmac_key"],
key_id=creds.get("key_id"),
session_key=creds.get("session_key"),
)
client.connect()
print(client.get_capabilities_json())
client.start_notify(lambda path, value: print(path, value))
# optional: client.get_states(["power", "volume"])
# optional write: client.exec_command("volume", 10) # power on first
client.close()
BraviaConnectClient is synchronous — run it in an executor from asyncio.
The example is read-mostly; volume/mute writes no-op while the control unit is
off. Public exports are listed in pybravia_connect.__all__.
Features
- Connect and auth handshake for local
ControlDeviceServicegRPC GetCapabilities/get_capabilities_jsonand capability helpersStartNotifyStatesdelta stream andget_statesExecCommandWithAuth(fresh session random per write)- OAuth / Seeds credential helpers (sync for scripts;
async_*for HA) - TCP port discovery for non-Theatre devices (
discover_grpc_port) - Optional TV AES-GCM app-list / icon reads (
session_key+[crypto])
Validated on HT-A9M2 for connect/handshake, capabilities, notify, get_states,
and volume writes while powered on.
Requirements
- Device on a trusted private LAN (do not expose the gRPC port)
- Credentials JSON with at least
device_idandhmac_key(optionalkey_id,session_key) - Theatre systems default to port
55051(DEFAULT_THEATRE_PORT); TVs often needdiscover_grpc_port - Stop any Home Assistant
bravia_quadgRPC session on the same device before experimenting — dualkey_idsessions flake
Credentials CLI
OAuth login and write credentials for local gRPC (never commit the output):
python tools/get_session_keys.py --login --open -o /tmp/session_keys.json
See python tools/get_session_keys.py --help for --code, --token,
--refresh, and --from-har.
Documentation
- CHANGELOG.md — release history
- SECURITY.md — reporting and operator guidance
- THREAT_MODEL.md — advisory scope
- Issues
- AGENTS.md — contributor / agent conventions
- docs/development.md — protobuf stub regeneration
- docs/releasing.md — tagging and PyPI publish
Security
Local gRPC control assumes a trusted private LAN. Do not expose the device’s gRPC port to the internet. Never commit session-key JSON, OAuth tokens, or HAR files from the CLI tools.
See SECURITY.md for reporting and operator guidance, and THREAT_MODEL.md for what is in scope for private advisories.
Development
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
ruff check . && ruff format --check .
mypy
pytest -q
Live device smoke (env details in the script docstring):
export BRAVIA_HOST=192.168.x.x
export BRAVIA_CREDENTIALS=/path/to/keys.json
python tools/live_smoke.py
Open PRs against main and complete
.github/PULL_REQUEST_TEMPLATE.md
(tick exactly one change type so CI can label the PR for release notes).
See AGENTS.md for agent/contributor conventions.
Protobuf regeneration and release steps: docs/development.md, docs/releasing.md.
License
MIT. Protocol code was extracted from the integrations listed above; thanks to @steamEngineer and @braviafanboy.
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 pybravia_connect-0.1.0a9.tar.gz.
File metadata
- Download URL: pybravia_connect-0.1.0a9.tar.gz
- Upload date:
- Size: 50.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1ae7dcb515231a45ae96b32ee32057d6584dd744b5a2796fac014789862f1db0
|
|
| MD5 |
07dc7f47184bb18d0bf9bf3edcac2119
|
|
| BLAKE2b-256 |
10201d42e06b743c9ee58b0d20ae300dbd42ebc765ec997bc10a2025fda5ad6c
|
Provenance
The following attestation bundles were made for pybravia_connect-0.1.0a9.tar.gz:
Publisher:
publish.yml on steamEngineer/pybravia-connect
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pybravia_connect-0.1.0a9.tar.gz -
Subject digest:
1ae7dcb515231a45ae96b32ee32057d6584dd744b5a2796fac014789862f1db0 - Sigstore transparency entry: 2255150598
- Sigstore integration time:
-
Permalink:
steamEngineer/pybravia-connect@89842b45d6b9f75a627a7d7d1e20dc6bf391ed92 -
Branch / Tag:
refs/tags/v0.1.0a9 - Owner: https://github.com/steamEngineer
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@89842b45d6b9f75a627a7d7d1e20dc6bf391ed92 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pybravia_connect-0.1.0a9-py3-none-any.whl.
File metadata
- Download URL: pybravia_connect-0.1.0a9-py3-none-any.whl
- Upload date:
- Size: 37.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
beac7f716df1deabe835e7ab2e141194121eff70ef9bab6a23d5a42bafcdb2e2
|
|
| MD5 |
57f3ab6f4ca227610ef661cfadfa9e50
|
|
| BLAKE2b-256 |
d0b62f6da98c8a147714e9073b9137735b1f21167c708b8cd9876c6823e445d1
|
Provenance
The following attestation bundles were made for pybravia_connect-0.1.0a9-py3-none-any.whl:
Publisher:
publish.yml on steamEngineer/pybravia-connect
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pybravia_connect-0.1.0a9-py3-none-any.whl -
Subject digest:
beac7f716df1deabe835e7ab2e141194121eff70ef9bab6a23d5a42bafcdb2e2 - Sigstore transparency entry: 2255150603
- Sigstore integration time:
-
Permalink:
steamEngineer/pybravia-connect@89842b45d6b9f75a627a7d7d1e20dc6bf391ed92 -
Branch / Tag:
refs/tags/v0.1.0a9 - Owner: https://github.com/steamEngineer
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@89842b45d6b9f75a627a7d7d1e20dc6bf391ed92 -
Trigger Event:
push
-
Statement type: