diff --git a/README.md b/README.md index 35e0b94..04e77b8 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,11 @@ Custom integration for Home Assistant to support Yamaha AV receivers with the YNCA protocol (serial and network). -According to reports of users and info found on the internet the following AV receivers should be working. There are probably more receivers that work, just give it a try. If your receiver works and is not in the list, please post a message in the [discussions](https://github.com/mvdwetering/yamaha_ynca/discussions) so the list can be updated. +According to reports of users the following AV receivers are working. There are probably more receivers that work, just give it a try. If your receiver works and is not in the list, please post a message in the [discussions](https://github.com/mvdwetering/yamaha_ynca/discussions) so the list can be updated. -> HTR-4065, HTR-4071, HTR-6064, RX-A2A, RX-A6A, RX-A660, RX-A700, RX-A710, RX-A720, RX-A740, RX-A750, RX-A800, RX-A810, RX-A820, RX-A830, RX-A840, RX-A850, RX-A870, RX-A1000, RX-A1010, RX-A1020, RX-A1030, RX-A1040, RX-A2000, RX-A2010, RX-A2020, RX-A2070, RX-A3000, RX-A3010, RX-A3020, RX-A3030, RX-A3070, RX-S600D, RX-V475, RX-V477, RX-V481D, RX-V483, RX-V500D, RX-V573, RX-V575, RX-V671, RX-V673, RX-V675, RX-V677, RX-V679, RX-V681, RX-V685, RX-V771, RX-V773, RX-V775, RX-V777, RX-V867, RX-V871, RX-V1067, RX-V1071, RX-V1085, RX-V2067, RX-V2071, RX-V3067, RX-V3071, TSR-700, TSR-7850 +> HTR-4065, HTR-4071, HTR-6064, R-N500, RX-A2A, RX-A4A, RX-A6A, RX-A660, RX-A700, RX-A710, RX-A720, RX-A740, RX-A750, RX-A800, RX-A810, RX-A820, RX-A830, RX-A840, RX-A850, RX-A870, RX-A1000, RX-A1010, RX-A1020, RX-A1030, RX-A1040, RX-A2000, RX-A2010, RX-A2020, RX-A2070, RX-A3000, RX-A3010, RX-A3020, RX-A3030, RX-A3070, RX-S600D, RX-V475, RX-V477, RX-V481D, RX-V483, RX-V500D, RX-V573, RX-V575, RX-V671, RX-V673, RX-V675, RX-V677, RX-V679, RX-V681, RX-V685, RX-V771, RX-V773, RX-V775, RX-V777, RX-V867, RX-V871, RX-V1067, RX-V1071, RX-V1085, RX-V2067, RX-V2071, RX-V3067, RX-V3071, TSR-700, TSR-7850 -In case of issues or feature requests please [submit an issue on Github](https://github.com/mvdwetering/yamaha_ynca/issues) +For issues or feature requests please [submit an issue on Github](https://github.com/mvdwetering/yamaha_ynca/issues) ## Features @@ -26,8 +26,12 @@ In case of issues or feature requests please [submit an issue on Github](https:/ * Local Push, so updates instantly * Support for zones * Power on/off -* Volume control and mute +* Mute/Unmute +* Volume control + * Standard Home Assistant media player + * Separate number entity with Volume in dB like on the receiver * Source selection +* Source names are taken from receiver (if supported by receiver) * Soundmode selection * Control playback state (depends on source) * Provide metadata like artist, album, song (depends on source) @@ -42,35 +46,50 @@ In case of issues or feature requests please [submit an issue on Github](https:/ * Initial volume * Max volume * Sleep timer - * Speaker bass/treble (default disabled) - * Headphone bass/treble (default disabled) * Surround Decoder * Pure Direct + * Speaker bass/treble (default disabled) + * Headphone bass/treble (default disabled) ## Installation ### Home Assistant Community Store (HACS) -*Recommended as you get notified of updates.* +*Recommended because you get notified of updates.* HACS is a 3rd party downloader for Home Assistant to easily install and update custom integrations made by the community. More information and installation instructions can be found on their site https://hacs.xyz/ -* Add integration within HACS (use the + button and search for "YNCA") +* Open the HACS page +* Search for "Yamaha (YNCA)" in the HACS search bar +* Press the Download button and wait for it to download * Restart Home Assistant -* Go to the Home Assistant integrations menu, press the Add button and search for "Yamaha (YNCA)". You might need to clear the browser cache for it to show up (e.g. reload with CTRL+F5). + +Then install the integration as usual: +* Go to the "Integration" page in Home Assistant (Settings > Devices & Services) +* Press the "Add Integration" button +* Search for "Yamaha (YNCA)" and select the integration. You might need to clear the browser cache for it to show up (e.g. reload with CTRL+F5). +* Follow the instructions ### Manual -* Download the zipfile from the releases. -* Extract the zip and copy the contents to the `custom_components` directory. +* Go to the releases section and download the zip file. +* Extract the zip +* Copy the contents to the `custom_components` directory in your `config` directory. * Restart Home Assistant -* Go to the Home Assistant integrations menu, press the Add button and search for "Yamaha (YNCA)". You might need to clear the browser cache for it to show up (e.g. reload with CTRL+F5). + +Then install the integration as usual: +* Go to the "Integration" page in Home Assistant (Settings > Devices & Services) +* Press the "Add Integration" button +* Search for "Yamaha (YNCA)" and select the integration. You might need to clear the browser cache for it to show up (e.g. reload with CTRL+F5). +* Follow the instructions ## Volume (dB) entity -The volume of a `media_player` entity in Home Assistant has to be in the range 0-to-1 (shown as 0-100% in the dashboard). The range of a Yamaha receiver is typically -80.5dB to 16.5dB and is shown in the dB unit on the display/overlay. To provide the full volume range to Home Assistant this integration maps the full dB range onto the 0-to-1 range in Home Assistant. However, this makes controlling volume in Home Assistant difficult as the Home Assistant numbers are not easily convertible to the dB numbers as shown by the receiver. +The "Volume (dB)" entity was added to simplify volume control in Home Assistant. It is a number entity that controls the volume of a zone, like the volume in the media_player, but using the familiar dB unit instead of the percent numbers. + +### Background -The "Volume (dB)" entity was added to simplify this. It is a number entity that controls the volume of a zone, but using the familiar dB unit. +The volume of a `media_player` entity in Home Assistant has to be in the range 0-to-1 (shown as 0-100% in the dashboard). The range of a Yamaha receiver is typically -80.5dB to 16.5dB and is shown in the dB unit on the display/overlay. To provide the full volume range to Home Assistant this integration maps the full dB range onto the 0-to-1 range in Home Assistant. However, this makes controlling volume in Home Assistant difficult because the Home Assistant numbers are not easily convertible to the dB numbers as shown by the receiver. ## Remote control @@ -564,18 +583,18 @@ The `media_content_type` is always "music". The `media_content_id` format is lis * **Q: Why are entities unavailable when receiver is in standby?** The receiver does not allow changing of settings when it is in standby, so the entities become Unavailable in Home Assistant to indicate this. -* **Q: Why does the integration not show all features mentioned in the README?** - The integration tries to autodetect as many features as possible, but it is not possible for all features on all receivers. You can adjust detected/supported some features for your receiver in the integration configuration. It can also be that your receiver does not expose that feature, you can make an issue if you believe it is supposed to be supported on your receiver. +* **Q: Why does the integration not show all features mentioned in the README even when my receiver supports them?** + The integration tries to autodetect as many features as possible, but it is not possible for all features on all receivers. You can adjust detected/supported some features for your receiver in the integration configuration. It can also be that your receiver does not expose that feature. You can make an issue if you believe it is supposed to be supported on your receiver. * **Q: How can I stream audio from a URL?** - You can't with this integration since the protocol does not support that. You might be able to use the [DLNA Digital Media Renderer integration](https://www.home-assistant.io/integrations/dlna_dmr/) that comes with Home Assistant. + You can't with this integration because the protocol does not support that. You might be able to use the [DLNA Digital Media Renderer integration](https://www.home-assistant.io/integrations/dlna_dmr/) that comes with Home Assistant. * **Q: Why are Scene buttons are not working for my receiver?** On some receivers (e.g. RX-V475) the command to activate the scenes does not work even though the receiver seems to indicate support for them. There might be more receivers with this issue, please report them in an issue or start a discussion. The non-working buttons can be disabled in the integration configuration by selecting "0" for number of scenes instead of "Auto detect". - As an alternative, the scenes can be activated by sending the scene commands by performing the `remote.send_command` action on the [Remote control entity](#remote-control). + As a workaround the scenes can be activated by sending the scene commands by performing the `remote.send_command` action on the [Remote control entity](#remote-control). ```yaml service: remote.send_command diff --git a/custom_components/yamaha_ynca/config_flow.py b/custom_components/yamaha_ynca/config_flow.py index 40037fa..e10b0e4 100644 --- a/custom_components/yamaha_ynca/config_flow.py +++ b/custom_components/yamaha_ynca/config_flow.py @@ -72,7 +72,7 @@ class YamahaYncaConfigFlow(ConfigFlow, domain=DOMAIN): # When updating also update the one used in `setup_integration` for tests VERSION = 7 - MINOR_VERSION = 5 + MINOR_VERSION = 6 reconfigure_entry: YamahaYncaConfigEntry | None = None diff --git a/custom_components/yamaha_ynca/input_helpers.py b/custom_components/yamaha_ynca/input_helpers.py index 30a8cfd..9e0fc94 100644 --- a/custom_components/yamaha_ynca/input_helpers.py +++ b/custom_components/yamaha_ynca/input_helpers.py @@ -55,10 +55,12 @@ class Mapping: Mapping(ynca.Input.HDMI6, []), Mapping(ynca.Input.HDMI7, []), Mapping(ynca.Input.MULTICH, []), + Mapping(ynca.Input.OPTICAL1, []), + Mapping(ynca.Input.OPTICAL2, []), Mapping(ynca.Input.PHONO, []), Mapping(ynca.Input.TV, []), - Mapping(ynca.Input.VAUX, []), Mapping(ynca.Input.USB, []), + Mapping(ynca.Input.VAUX, []), ] diff --git a/custom_components/yamaha_ynca/manifest.json b/custom_components/yamaha_ynca/manifest.json index 9e7dd48..a8e8a5c 100644 --- a/custom_components/yamaha_ynca/manifest.json +++ b/custom_components/yamaha_ynca/manifest.json @@ -13,7 +13,7 @@ "ynca" ], "requirements": [ - "ynca==5.17.0" + "ynca==5.17.1" ], - "version": "7.11.1" + "version": "7.12.0" } \ No newline at end of file diff --git a/custom_components/yamaha_ynca/migrations.py b/custom_components/yamaha_ynca/migrations.py index 2bb3884..95afb16 100644 --- a/custom_components/yamaha_ynca/migrations.py +++ b/custom_components/yamaha_ynca/migrations.py @@ -46,6 +46,8 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry): migrate_v7_3_to_v7_4(hass, config_entry) if config_entry.minor_version == 4: migrate_v7_4_to_v7_5(hass, config_entry) + if config_entry.minor_version == 5: + migrate_v7_5_to_v7_6(hass, config_entry) # When adding new migrations do _not_ forget # to increase the VERSION of the YamahaYncaConfigFlow @@ -61,6 +63,24 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry): return True +def migrate_v7_5_to_v7_6(hass: HomeAssistant, config_entry: ConfigEntry): + options = dict(config_entry.options) # Convert to dict to be able to use .get + + # Hide new TV input for existing users + # Code is robust against unsupported inputs being listed in "hidden_input"s + + # Upgrading from _really_ old version might not have zones key + if "zones" in config_entry.data: + for zone_id in config_entry.data["zones"]: + options[zone_id] = options.get(zone_id, {}) + options[zone_id]["hidden_inputs"] = options[zone_id].get( + "hidden_inputs", [] + ) + options[zone_id]["hidden_inputs"].extend(["OPTICAL1", "OPTICAL2"]) + + hass.config_entries.async_update_entry( + config_entry, options=options, minor_version=6 + ) def migrate_v7_4_to_v7_5(hass: HomeAssistant, config_entry: ConfigEntry): options = dict(config_entry.options) # Convert to dict to be able to use .get diff --git a/custom_components/yamaha_ynca/number.py b/custom_components/yamaha_ynca/number.py index f799569..00676a0 100644 --- a/custom_components/yamaha_ynca/number.py +++ b/custom_components/yamaha_ynca/number.py @@ -57,7 +57,6 @@ class YncaNumberEntityDescription(NumberEntityDescription): native_max_value_fn=volume_native_max_value_fn, native_step=0.5, native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS, - entity_registry_enabled_default=False, function_names=["VOL", "MAXVOL"], ), YncaNumberEntityDescription( # type: ignore diff --git a/requirements.txt b/requirements.txt index 4a9b88f..78f5343 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ # Also update manifest.json! -ynca==5.17.0 \ No newline at end of file +ynca==5.17.1 \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 2de0440..3434966 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -199,7 +199,7 @@ def device_reg(hass: HomeAssistant) -> device_registry.DeviceRegistry: def create_mock_config_entry(modelname=None, zones=None, serial_url=None): return MockConfigEntry( version=7, - minor_version=5, + minor_version=6, domain=yamaha_ynca.DOMAIN, entry_id="entry_id", title=MODELNAME, diff --git a/tests/test_migrations.py b/tests/test_migrations.py index abbc440..495c082 100644 --- a/tests/test_migrations.py +++ b/tests/test_migrations.py @@ -43,7 +43,7 @@ async def test_async_migration_entry(hass: HomeAssistant): new_entry = hass.config_entries.async_get_entry(old_entry.entry_id) assert new_entry is not None assert new_entry.version == 7 - assert new_entry.minor_version == 5 + assert new_entry.minor_version == 6 async def test_async_migration_entry_version_v1_to_v2(hass: HomeAssistant): @@ -534,4 +534,31 @@ async def test_async_migration_entry_version_v7_4_to_v7_5( assert len(new_entry.options.keys()) == 1 assert len(new_entry.options["ZONE2"]["hidden_inputs"]) == 2 assert "TV" in new_entry.options["ZONE2"]["hidden_inputs"] + assert "SOME INPUT" in new_entry.options["ZONE2"]["hidden_inputs"] + +async def test_async_migration_entry_version_v7_5_to_v7_6( + hass: HomeAssistant, +): + config_entry = MockConfigEntry( + domain=yamaha_ynca.DOMAIN, + entry_id="entry_id", + title="ModelName", + data={"serial_url": "SerialUrl", "zones": ["ZONE2"], "modelname": "ModelName"}, + options={"ZONE2": {"hidden_inputs": ["SOME INPUT"]}}, + version=7, + ) + config_entry.add_to_hass(hass) + + # Migrate + yamaha_ynca.migrations.migrate_v7_5_to_v7_6(hass, config_entry) + await hass.async_block_till_done() + + new_entry = hass.config_entries.async_get_entry(config_entry.entry_id) + assert new_entry is not None + assert new_entry.version == 7 + assert new_entry.minor_version == 6 + assert len(new_entry.options.keys()) == 1 + assert len(new_entry.options["ZONE2"]["hidden_inputs"]) == 3 + assert "OPTICAL1" in new_entry.options["ZONE2"]["hidden_inputs"] + assert "OPTICAL2" in new_entry.options["ZONE2"]["hidden_inputs"] assert "SOME INPUT" in new_entry.options["ZONE2"]["hidden_inputs"] \ No newline at end of file diff --git a/tests/test_options_flow.py b/tests/test_options_flow.py index 17d9eef..75d4cf4 100644 --- a/tests/test_options_flow.py +++ b/tests/test_options_flow.py @@ -66,6 +66,8 @@ "HDMI6", "HDMI7", "MULTI CH", + "OPTICAL1", + "OPTICAL2", "PHONO", "TV", "USB",