aiodisklavier
Async Python client for the Yamaha Disklavier ENSPIRE local HTTP API.
Talks to the piano directly over your own network. Verified against firmware 5.24.00 on a Disklavier ENSPIRE PRO grand.
Install
pip install aiodisklavier
Use
import aiohttp
from aiodisklavier import Disklavier, SongGroup
async with aiohttp.ClientSession() as session:
piano = Disklavier("192.168.1.50", session)
info = await piano.async_get_current_info()
print(info.song_title, info.playback_status, info.position_seconds)
# Fuzzy title search runs on the piano itself.
await piano.async_play_search("Clair de lune")
# Play one song and stop, rather than continuing through the library.
await piano.async_play_song(24, SongGroup.DOWNLOADED_SONGS, single=True)
Finding the piano is a plain SSDP M-SEARCH for urn:schemas-upnp-org:device:Disklavier:1; the library exposes that device type as UPNP_DEVICE_TYPE.
What it covers
| Area | Methods |
|---|---|
| State | async_get_static_info, async_get_current_info, async_get_master_state |
| Transport | async_play, async_pause, async_stop, async_play_pause, async_next_song, async_previous_song, async_restart_song, async_seek |
| Volume | async_set_volume, async_volume_up, async_volume_down |
| Power | async_turn_on, async_turn_off, async_set_power |
| Voicing | async_set_quiet_mode, async_set_repeat |
| Playback | async_play_song, async_play_search, async_play_genre, async_play_album, async_play_playlist, async_play_playlist_item |
| Browsing | async_get_songs, async_get_albums, async_get_songs_in_album, async_get_playlists, async_get_playlist_items |
| Radio | async_get_radio_channels, async_play_radio, async_stop_radio |
| Notifications | async_notify, async_snapshot_playback, async_restore_playback, async_play_test_chord |
| Library | async_refresh_library |
Firmware behaviours worth knowing
These are properties of the piano, not of this library, and each is easy to get wrong. The full reasoning, with provenance for every claim, is in docs/enspire-api.md.
- There is no stop state.
stopleavesplayback_statusreadingpauseat position zero. UseCurrentInfo.is_stoppedrather than looking for a stop constant. - Waking takes about twelve seconds, during which
power_statusreadswakeupand the piano ignores commands. The HTTP API answers normally while asleep, so reachability tells you nothing about power state. - Empty libraries are an error, not an empty list — HTTP 200 carrying
{"status": "error", "error_info": "no song"}. The browse methods translate that envelope back into the empty list it denotes, so callers just see[]. - State reads can come back truncated while a song is playing, because the daemon
rewrites those files in place. Reads retry automatically. Payloads may also carry a
trailing
\n\0, which is stripped rather than retried. - State lags a command. Reading
current_infostraight after aload_songor reselect returns the previous song. Allow a short settle before trusting a post-command read. - Radio's interaction with transport commands is not established. There is reason to think playback behaves differently while a radio channel is playing, but it has not been exercised on hardware — treat transport during radio as unknown.
async_play_test_chordmakes a sound — a C major triad for one second. It goes to the MIDI daemon rather than the sequencer, so it will not disturb a loaded song.
Two APIs, one preferred
The piano exposes a versioned open API at /api/1.0/<command> and an internal, unversioned
set of endpoints under /ctrl/ that its own web UI drives. This library uses the open API
wherever possible and drops to /ctrl/ only for what the open API cannot do: seeking, repeat
and shuffle, the extended state block, reindexing, and the test chord. Both funnel XML into
the same Unix socket inside the piano.
The open API takes some finding: nothing the piano normally serves links to it, and neither
the phone app nor the piano's own web UI calls it. The one client-side trail is
/ctrl/api_test.html, a test harness Yamaha ships on the device — that is where the
/api/1.0/ form is visible. /api/api.php?_com=<command> is the same surface by another
name, verified equivalent down to the error codes.
Development
python3 -m venv .venv
.venv/bin/pip install -e ".[test]"
.venv/bin/python -m pytest
Tests run against a real aiohttp test server that imitates the piano, so no hardware is
needed and the suite does not depend on any mocking library's grip on aiohttp internals.
Several tests encode behaviour found only on real hardware — those are commented as such,
because they look arbitrary otherwise.
Licence
MIT
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 aiodisklavier-0.1.0.tar.gz.
File metadata
- Download URL: aiodisklavier-0.1.0.tar.gz
- Upload date:
- Size: 45.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df558ef74707b359c48af31231910ca228bae4e0b58ca68dc0f434fa1587831f
|
|
| MD5 |
952e71954eb9e33d4e5ea2bc429249fd
|
|
| BLAKE2b-256 |
60d6fb43965f52d82a0f802d8c2a7d8e6b028df28c534b0b75a0f1731e1b4eeb
|
Provenance
The following attestation bundles were made for aiodisklavier-0.1.0.tar.gz:
Publisher:
publish.yml on reubenbijl/aiodisklavier
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aiodisklavier-0.1.0.tar.gz -
Subject digest:
df558ef74707b359c48af31231910ca228bae4e0b58ca68dc0f434fa1587831f - Sigstore transparency entry: 2475644606
- Sigstore integration time:
-
Permalink:
reubenbijl/aiodisklavier@4853ed56f5e471342fc6ea56abbad74be504641a -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/reubenbijl
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4853ed56f5e471342fc6ea56abbad74be504641a -
Trigger Event:
release
-
Statement type:
File details
Details for the file aiodisklavier-0.1.0-py3-none-any.whl.
File metadata
- Download URL: aiodisklavier-0.1.0-py3-none-any.whl
- Upload date:
- Size: 20.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
098deaf0353ad95314b7e446e6a56513efe2ea73eab5434c7d97983563017fb4
|
|
| MD5 |
1457c4fcf76c55455928cee7087b9e9b
|
|
| BLAKE2b-256 |
5a7f94eec0a9b63ac1da1e1cef06b0c7c211a7b4899556a3bef6d4b8d4c03221
|
Provenance
The following attestation bundles were made for aiodisklavier-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on reubenbijl/aiodisklavier
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aiodisklavier-0.1.0-py3-none-any.whl -
Subject digest:
098deaf0353ad95314b7e446e6a56513efe2ea73eab5434c7d97983563017fb4 - Sigstore transparency entry: 2475644635
- Sigstore integration time:
-
Permalink:
reubenbijl/aiodisklavier@4853ed56f5e471342fc6ea56abbad74be504641a -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/reubenbijl
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4853ed56f5e471342fc6ea56abbad74be504641a -
Trigger Event:
release
-
Statement type: