Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to LinkPlay to disregard HA hostname and use IP instead #137089

Draft
wants to merge 3 commits into
base: dev
Choose a base branch
from

Conversation

ozonejunkieau
Copy link
Contributor

Proposed change

Digging into the issue related to LinkPlay devices not supporting TTS, it appears the root cause of this is that the devices "ignore" URLs relating to local network resources. From the debugging that I've done (documented in the related issue), overriding this behaviour has not yet been possible through device configuration.

This PR adds in an option to the integraton that overwrites the generated URL's with the local HA IP address instead. By doing this, TTS works on these devices with no further issues. It doesn't feel elegant, but it does work. Due to the nature of the fix I wanted to invite comment before I finalised testing etc, as if this method can't reach the development standards of the project I'll just leave it until someone can find a better method to get this working.

TODO: At present I have been unable to find any documentation on how to change the displayed text adjacent to a boolean option. I would greatly appreciate some pointers on where to find the documentation for this! The tests also require updating at this time.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

  • This PR fixes or closes issue: fixes Linkplay speakers do not support tts #123993
  • This PR is related to issue:
  • Link to documentation pull request:
  • Link to developer documentation pull request:
  • Link to frontend pull request:

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • I have followed the perfect PR recommendations
  • The code has been formatted using Ruff (ruff format homeassistant tests)
  • Tests have been added to verify that the new code works.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies - a link to the changelog, or at minimum a diff between library versions is added to the PR description.

To help with the load of incoming pull requests:

Copy link

@home-assistant home-assistant bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ozonejunkieau

It seems you haven't yet signed a CLA. Please do so here.

Once you do that we will be able to review and accept this pull request.

Thanks!

@home-assistant
Copy link

home-assistant bot commented Feb 1, 2025

Hey there @Velleman, mind taking a look at this pull request as it has been labeled with an integration (linkplay) you are listed as a code owner for? Thanks!

Code owner commands

Code owners of linkplay can trigger bot actions by commenting:

  • @home-assistant close Closes the pull request.
  • @home-assistant rename Awesome new title Renames the pull request.
  • @home-assistant reopen Reopen the pull request.
  • @home-assistant unassign linkplay Removes the current integration label and assignees on the pull request, add the integration domain after the command.
  • @home-assistant add-label needs-more-information Add a label (needs-more-information, problem in dependency, problem in custom component) to the pull request.
  • @home-assistant remove-label needs-more-information Remove a label (needs-more-information, problem in dependency, problem in custom component) on the pull request.

Copy link
Contributor

@silamon silamon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your deep analysis and contribution trying to address it. I've left some first comments in this review to get started. Some basic test coverage for the option flow will be required to get this merged on the end.

The implementation of the LinkPlay protocol is generic is some form, but the implementation may differ from device to device depending on the manufacturer. Multiple companies have adjusted the firmware, making it hard to know what devices (and the firmwares) are actually affected by this bug.

I'm still thinking if it's required to present this as an option (flow), if the affected devices can be listed, it should be possible to handle all this based on the model ids.

Comment on lines 40 to 46
# Register update listener to update config entry when options are updated.
hass_data = dict(entry.data)
unsub_options_update_listener = entry.add_update_listener(options_update_listener)
# Store a reference to the unsubscribe function to cleanup if an entry is unloaded.
hass_data["unsub_options_update_listener"] = unsub_options_update_listener
hass.data[DOMAIN][entry.entry_id] = hass_data

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can replace this code with

entry.async_on_unload(entry.add_update_listener(async_update_options))

Add this code after initializing the platforms, so it only unloads after successful setup.

Comment on lines 262 to 267
# Modify the the url if required to use IP address instead of hostname.
# This is required for compatibility with some devices.
if self._use_ip_url:
parsed_url = yarl.URL(url)
# Update the parsed URL with the local ip
url = parsed_url.with_host(self.hass.config.api.local_ip)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given your analysis in the issue thread, I assume this is only required when you want to play a local(-only) url that isn't externally exposed?

How does this work for music coming from a streaming provider? When the toggle is enabled, it will replace dns always with it's ip address?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On first reading through the code I was under the impression that this function was only called with HA URL's. Upone re-reading I can see that this isn't a valid assumption, so I'll update the code to handle this case and update the PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use this utility method:

def is_hass_url(hass: HomeAssistant, url: str) -> bool:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for that, I'm still getting my head around how the options flow testing should work, will try and spend some time in the next couple of days and get that added.

@@ -25,10 +25,12 @@
MODELS_ARYLIC_A50: Final[str] = "A50"
MODELS_ARYLIC_A50S: Final[str] = "A50+"
MODELS_ARYLIC_UP2STREAM_AMP: Final[str] = "Up2Stream Amp 2.0"
MODELS_ARYLIC_UP2STREAM_AMP_2P1: Final[str] = "Up2Stream Amp 2.1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you open a preliminary pull request to add these models? Pull requests are as small as possible and should only address one change at a time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I've just submitted a separate PR with these.

Comment on lines 26 to 32
"selector": {
"sensor_select": {
"options": {
"use_ip_url": "Force IP in Home Assistant generated URLs to work around bugs in using local domain names with some devices."
}
}
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the option flow translation section to let them show up. Something like this:

Suggested change
"selector": {
"sensor_select": {
"options": {
"use_ip_url": "Force IP in Home Assistant generated URLs to work around bugs in using local domain names with some devices."
}
}
},
"options": {
"step": {
"init": {
"title": "LinkPlay options",
"data": {
"use_ip_url": "Force IP in Home Assistant generated URLs to work around bugs in using local domain names with some devices."
}
}
}
},

@silamon
Copy link
Contributor

silamon commented Feb 2, 2025

Have you tested if it worked for your devices with any of the custom components available? Some people mentioned that it works with the custom components in the issue thread and they have always been a good source for this core integration from the start.

@ozonejunkieau
Copy link
Contributor Author

Have you tested if it worked for your devices with any of the custom components available? Some people mentioned that it works with the custom components in the issue thread and they have always been a good source for this core integration from the start.

From reading online, I was under the impression that the previous custom components had been deprecated in favour of the built in component?

I haven't tested with the custom components, I figured that working with the core integration was likely a more reliable path?

@silamon
Copy link
Contributor

silamon commented Feb 10, 2025

Have you tested if it worked for your devices with any of the custom components available? Some people mentioned that it works with the custom components in the issue thread and they have always been a good source for this core integration from the start.

From reading online, I was under the impression that the previous custom components had been deprecated in favour of the built in component?

I haven't tested with the custom components, I figured that working with the core integration was likely a more reliable path?

Thanks for answering. Having it fixed in core is definiately the way to go. It's fine if you didn't test any custom integrations, just asking to know. I've went through the code of multiple custom integrations and couldn't spot if they would fix this issue.

Copy link
Contributor

@silamon silamon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking the time to further improve. At this point, I'm not sure it would be accepted to introduce a option flow for this, we will need to wait until a core reviewer comes by to step in.

Comment on lines +40 to +42
# Register update listener to update config entry when options are updated.
entry.async_on_unload(entry.add_update_listener(options_update_listener))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be at the bottom of the function, to ensure it only unloads when it was successfully setup.

@MartinHjelmare MartinHjelmare changed the title Add option to LinkPlay to disregard HA hostname and use IP instead. Add option to LinkPlay to disregard HA hostname and use IP instead Feb 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Linkplay speakers do not support tts
2 participants