Skip to content

Add speaker settings: volume management, hardware controls, and LED controls#12

Open
danielpetrovic wants to merge 6 commits into
N0ciple:mainfrom
danielpetrovic:speaker-settings-pr
Open

Add speaker settings: volume management, hardware controls, and LED controls#12
danielpetrovic wants to merge 6 commits into
N0ciple:mainfrom
danielpetrovic:speaker-settings-pr

Conversation

@danielpetrovic

Copy link
Copy Markdown
Contributor

This PR adds 48 new methods (24 sync + 24 async) covering three related areas of speaker configuration that are currently missing from the library. All methods have been tested on LSX II, LSX II LT, and XIO hardware.

Volume Management (9 sync + 9 async)

Per-source default volumes and global volume settings:

  • get_default_volume(input_source) / set_default_volume(input_source, volume) — per-source startup volume (wifi, bluetooth, optical, coaxial, usb, analogue, tv)
  • get_all_default_volumes() — retrieve default volumes for all sources at once
  • get_volume_settings() / set_volume_settings(max_volume, step, limit) — max volume cap, step size, and limit
  • get_standby_volume_behavior() / set_standby_volume_behavior(use_global) — whether standby resumes at global or per-source volume
  • get_startup_volume_enabled() / set_startup_volume_enabled(enabled) — startup volume override

Hardware Settings (11 sync + 11 async)

Speaker behaviour and connectivity settings:

  • get_standby_mode() / set_standby_mode(mode) — standby timeout (off/20min/60min)
  • get_startup_tone() / set_startup_tone(enabled) — power-on chime
  • get_auto_switch_hdmi() / set_auto_switch_hdmi(enabled) — HDMI auto-source switching
  • get_cable_mode() / set_cable_mode(mode) — wired connection mode
  • get_master_channel() / set_master_channel(channel) — left/right master assignment
  • get_wake_source() / set_wake_source(source) — which input wakes the speaker
  • get_subwoofer_wake_on_startup() / set_subwoofer_wake_on_startup(enabled) — subwoofer auto-wake
  • get_kw1_wake_on_startup() / set_kw1_wake_on_startup(enabled) — KW1 wireless sub auto-wake
  • get_usb_charging() / set_usb_charging(enabled) — USB port charging
  • get_fixed_volume_mode() / set_fixed_volume_mode(volume) — fixed output level for AV receivers
  • set_request(path, roles, value) — generic write counterpart to the existing get_request()

LED Controls (5 sync + 5 async)

Visual indicator management:

  • get_front_led() / set_front_led(enabled) — front logo LED
  • get_standby_led() / set_standby_led(enabled) — standby indicator LED
  • get_top_panel_enabled() / set_top_panel_enabled(enabled) — top touch panel
  • get_top_panel_led() / set_top_panel_led(enabled) — top panel LED in active state
  • get_top_panel_standby_led() / set_top_panel_standby_led(enabled) — top panel LED in standby

Notes

  • All methods follow the same pattern as existing code (sync uses requests, async uses aiohttp)
  • Input validation and clear error messages included throughout
  • set_request() mirrors the existing get_request() signature for consistency

What's Coming Next

This is the first in a series of focused PRs. The full set of new endpoints was discovered by decompiling the KEF Connect Android APK (v1.26.1) using JADX, which gave us a definitive list of all 209 KEF API paths from ApiPath.java. Subsequent PRs will cover:

  • EQ & DSPget_eq_profile / set_eq_profile, desk mode, wall mode, bass extension, treble, balance, phase correction
  • XIO features — room calibration, BLE subwoofer firmware updates, dialogue mode, sound profiles
  • Device information — serial number, hardware version, KEF ID, full device info
  • Firmware updates — check, download, and install speaker firmware
  • Network diagnostics — internet ping, speed test, network stability
  • Privacy & streaming — analytics settings, streaming quality, UI language
  • Alerts & timers — alarm sounds, sleep timers

The goal is to eventually have complete API coverage in pykefcontrol, which will enable a much richer hass-kef-connector integration with full speaker configuration from Home Assistant.

@danielpetrovic

danielpetrovic commented Apr 15, 2026

Copy link
Copy Markdown
Contributor Author

Update — rebased onto latest main + firmware v4.0/3.0/2.0 fixes included

This branch has been rebased onto upstream main (which includes your 530a7d1 LS50WII POST fix). We have extended that approach with a firmware-version-based _set_data() helper that covers all models, since different models crossed to POST at different firmware versions:

Model POST threshold Status
LS50W II >= V4000 (fw 4.0) Released
LSX II LT >= V2000 (fw 2.0) Released
LSX II >= V3000 (fw 3.0) Released
LS60 Wireless >= V3000 (fw 3.0) Upcoming

The _set_data() helper auto-detects the model and firmware version on first write (lazy, cached), then routes to POST or GET accordingly. This supersedes the _POST_MODELS set approach and requires no manual configuration.

All setter methods in this PR use _set_data() and will automatically use POST or GET based on the detected firmware.

@danielpetrovic

danielpetrovic commented Apr 15, 2026

Copy link
Copy Markdown
Contributor Author

Update — rebased onto 0.9.1 (LSX II LT fix)

Rebased again onto your latest 421ae33 commit which adds LSX II LT to _POST_MODELS. The firmware-version-based _set_data() already covered this case (LSXIILT threshold >= V2000), so no changes were needed — the rebase just ensures the branch stays current with upstream.

@danielpetrovic

Copy link
Copy Markdown
Contributor Author

Update — branch rebased and expanded

This branch has been rebased onto the latest upstream main (includes your LSXIILT fw2.0 fix from 421ae33). One additional commit has been added on top of the original speaker settings work:

Add LSXII fw3.0 POST support, LSX2 alias, and raise_for_status

  • LSXII fw3.0 — Added "LSXII" to _POST_MODELS so setData calls use POST on fw3.0 (GET returns 405). This supersedes and closes PR Fix LSXII FW3.0 support #16.
  • LSX2 alias — Added "LSX2" → "LSXII" to _MODEL_ALIASES so older firmware or API responses using the legacy name still resolve correctly.
  • raise_for_status() — Added before every response.json() call (both sync and async) so HTTP errors surface instead of being silently swallowed. This incorporates and supersedes PR Correctly raise exceptions for HTTP errors #15 by @leccelecce — full credit to them for identifying the issue.

danielpetrovic and others added 5 commits May 4, 2026 09:59
…ontrols

Adds 48 new methods (24 sync + 24 async) across three areas:

Volume management:
- get/set_default_volume(input_source) — per-source startup volume
- get_all_default_volumes() — all source defaults at once
- get/set_volume_settings(max_volume, step, limit)
- get/set_standby_volume_behavior(use_global)
- get/set_startup_volume_enabled(enabled)

Hardware settings:
- get/set_standby_mode(mode) — standby timeout
- get/set_startup_tone(enabled) — power-on chime
- get/set_auto_switch_hdmi(enabled)
- get/set_cable_mode(mode)
- get/set_master_channel(channel)
- get/set_wake_source(source)
- get/set_subwoofer_wake_on_startup(enabled)
- get/set_kw1_wake_on_startup(enabled)
- get/set_usb_charging(enabled)
- get/set_fixed_volume_mode(volume)
- set_request(path, roles, value) — generic write counterpart to get_request()

LED controls:
- get/set_front_led(enabled)
- get/set_standby_led(enabled)
- get/set_top_panel_enabled(enabled)
- get/set_top_panel_led(enabled)
- get/set_top_panel_standby_led(enabled)

All methods available in both KefConnector (sync) and KefAsyncConnector (async).
Tested on LSX II, LSX II LT, and XIO hardware.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Document all 24 new methods added in this PR with usage examples:
- Volume management: default volumes per source, volume settings, standby behavior
- Hardware settings: standby mode, startup tone, HDMI, cable mode, wake source, LEDs
- LED controls: front LED, standby LED, top panel enable/LED states

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace simple stubs with full documentation sections matching
the detail level of the rest of the library:

- Volume Management: per-input defaults, volume settings, reset volume,
  all-sources vs individual-sources mode, async examples
- System Behavior Settings: standby mode, wake source, HDMI auto-switch,
  startup tone, USB charging, cable mode, master channel, async examples
- Do Not Disturb Settings: standby LED, startup tone, XIO control panel
  LEDs (front LED, top panel enable/standby), async examples

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add "LSXII" to _POST_MODELS so fw3.0 setData calls use POST
  instead of GET (which returns 405 on fw3.0). Supersedes PR N0ciple#16.
- Add "LSX2" → "LSXII" to _MODEL_ALIASES so older firmware or
  API responses using the legacy name still resolve correctly
- Add raise_for_status() before every response.json() call so HTTP
  errors surface instead of being silently swallowed, based on
  leccelecce's work in N0ciple#15

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
hass-kef-connector uses "LS60Wireless" as the model key (matching the
product name). Without this alias, LS60 owners using hass-kef-connector
PR N0ciple#17 would fall back to GET-based setData and hit 405 errors with
firmware 4.0+.
@danielpetrovic danielpetrovic force-pushed the speaker-settings-pr branch from 9751ca9 to 3350eed Compare May 4, 2026 08:32
@danielpetrovic

Copy link
Copy Markdown
Contributor Author

Update — rebased onto 0.9.3 + LS60Wireless alias

Rebased onto upstream main (0.9.3), which already includes LS60 in _POST_MODELS. One new commit on top:

  • Added "LS60Wireless": "LS60" to _MODEL_ALIASES — hass-kef-connector (PR #17) uses "LS60Wireless" as the model key (matching the product name). Without this alias, LS60 owners on that integration would fall back to GET-based setData and hit 405 errors with firmware 4.0+.

XIO firmware 1.4.135 switched setData from GET to POST.
LS60 firmware renamed the model ID from "LS60" to "LS60W" (fixes
upstream issue N0ciple#18). Changes:
- Add "XIO" and "LS60W" to _POST_MODELS
- Remove "LS60" from _POST_MODELS (no longer the active model ID)
- Add "LS60": "LS60W" alias for backward compat with older LS60 firmware
- Add "LS60Wireless": "LS60W" alias for integrations using the product name
@danielpetrovic

Copy link
Copy Markdown
Contributor Author

Update — XIO and LS60W POST support added

Following up on the LS60Wireless alias added in the previous update:

  • Added "XIO" to _POST_MODELS — XIO firmware 1.4.135 switched setData to POST. Verified working on XIO fw1.4.135.
  • Replaced "LS60" with "LS60W" in _POST_MODELS — LS60 firmware renamed the model ID (reported in issue #18). Added "LS60": "LS60W" alias for backward compat with older firmware.

These same fixes are also available as a standalone PR (#19) if a faster targeted merge is preferred.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant