Add IR remote control (LIRC) with a number-key content mapping
Adds a TCP client for lircd's classic protocol: play/pause/next/prev/ volume/mute map to the same intents every other front-end already emits, and number keys 0-9 play an assigned album/audiobook from the start or a podcast show's newest episode, resolved fresh on every press. The mapping is configured in config.yml and editable from the frontend: a small "Taste zuweisen" button on the play screen (or the A+digit keyboard shortcut) opens a 10-key picker to assign whatever is currently playing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -56,6 +56,46 @@ def test_ha_section_is_optional(config_dir: Path) -> None:
|
||||
assert load_config(write_config(config_dir, VALID_CONFIG)).general.ha is None
|
||||
|
||||
|
||||
def test_lirc_section_is_optional(config_dir: Path) -> None:
|
||||
assert load_config(write_config(config_dir, VALID_CONFIG)).general.lirc is None
|
||||
|
||||
data = _config(lirc={"host": "musicmouse-pi.local"})
|
||||
config = load_config(write_config(config_dir, data))
|
||||
assert config.general.lirc is not None
|
||||
assert config.general.lirc.port == 2222
|
||||
assert config.general.lirc.remote_name == "Hauppauge"
|
||||
|
||||
|
||||
def test_remote_mapping_is_optional_and_empty_by_default(config_dir: Path) -> None:
|
||||
assert load_config(write_config(config_dir, VALID_CONFIG)).remote == {}
|
||||
|
||||
|
||||
def test_remote_mapping_loads_album_and_series_slots(config_dir: Path) -> None:
|
||||
data = copy.deepcopy(VALID_CONFIG)
|
||||
data["remote"] = {
|
||||
"1": {"target_kind": "album", "target": "abc123"},
|
||||
"7": {"target_kind": "series", "target": "Wissen macht Ah"},
|
||||
}
|
||||
config = load_config(write_config(config_dir, data))
|
||||
assert config.remote["1"].target_kind == "album"
|
||||
assert config.remote["1"].target == "abc123"
|
||||
assert config.remote["7"].target_kind == "series"
|
||||
|
||||
|
||||
def test_remote_mapping_rejects_an_out_of_range_digit(config_dir: Path) -> None:
|
||||
data = copy.deepcopy(VALID_CONFIG)
|
||||
data["remote"] = {"10": {"target_kind": "album", "target": "abc123"}}
|
||||
message = _error(config_dir, data)
|
||||
assert "remote" in message
|
||||
|
||||
|
||||
def test_remote_mapping_rejects_an_unknown_target_kind(config_dir: Path) -> None:
|
||||
data = copy.deepcopy(VALID_CONFIG)
|
||||
data["remote"] = {"1": {"target_kind": "playlist", "target": "abc123"}}
|
||||
message = _error(config_dir, data)
|
||||
assert "remote" in message
|
||||
|
||||
|
||||
def test_ha_device_and_scene_name_is_optional(config_dir: Path) -> None:
|
||||
data = _config(
|
||||
ha={
|
||||
|
||||
Reference in New Issue
Block a user