Skip to main content

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. stop leaves playback_status reading pause at position zero. Use CurrentInfo.is_stopped rather than looking for a stop constant.
  • Waking takes about twelve seconds, during which power_status reads wakeup and 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_info straight after a load_song or 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_chord makes 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

aiodisklavier-0.1.0.tar.gz (45.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aiodisklavier-0.1.0-py3-none-any.whl (20.9 kB view details)

Uploaded Python 3

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

Hashes for aiodisklavier-0.1.0.tar.gz
Algorithm Hash digest
SHA256 df558ef74707b359c48af31231910ca228bae4e0b58ca68dc0f434fa1587831f
MD5 952e71954eb9e33d4e5ea2bc429249fd
BLAKE2b-256 60d6fb43965f52d82a0f802d8c2a7d8e6b028df28c534b0b75a0f1731e1b4eeb

See more details on using hashes here.

Provenance

The following attestation bundles were made for aiodisklavier-0.1.0.tar.gz:

Publisher: publish.yml on reubenbijl/aiodisklavier

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for aiodisklavier-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 098deaf0353ad95314b7e446e6a56513efe2ea73eab5434c7d97983563017fb4
MD5 1457c4fcf76c55455928cee7087b9e9b
BLAKE2b-256 5a7f94eec0a9b63ac1da1e1cef06b0c7c211a7b4899556a3bef6d4b8d4c03221

See more details on using hashes here.

Provenance

The following attestation bundles were made for aiodisklavier-0.1.0-py3-none-any.whl:

Publisher: publish.yml on reubenbijl/aiodisklavier

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.2.1

2 files

0.2.0

2 files

0.1.1

2 files

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page