nitobuendia / oura-custom-component

Oura Custom Component for Home-Assistant. Adds Oura Ring sleep information.
106 stars 24 forks source link

DuckDNS breaks Oura integraion #34

Closed daswass closed 1 year ago

daswass commented 1 year ago

It looks like the request host is no longer available when using DuckDNS to access HA remotely.

======= Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 362, in _async_setup_platform await asyncio.shield(task) File "/config/custom_components/oura/sensor.py", line 50, in async_setup_platform sensors.append(sensor_activity.OuraActivitySensor(config, hass)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/config/custom_components/oura/sensor_activity.py", line 99, in init super(OuraActivitySensor, self).init(config, hass, activity_config) File "/config/custom_components/oura/sensor_base_dated.py", line 50, in init super(OuraDatedSensor, self).init(config, hass) File "/config/custom_components/oura/sensor_base.py", line 35, in init self._api = api.OuraApi(self, access_token) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/config/custom_components/oura/api.py", line 43, in init self._hass_url = hass_helper.get_url(self._sensor._hass) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/config/custom_components/oura/helpers/hass_helper.py", line 24, in get_url return network.get_url( ^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/helpers/network.py", line 167, in get_url request_host = _get_request_host() ^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/helpers/network.py", line 206, in _get_request_host raise NoURLAvailableError homeassistant.helpers.network.NoURLAvailableError

nitobuendia commented 1 year ago

@daswass Thanks for reporting the issue.

What version of Home-Assistant are you running?

The code is essentially calling hass network.get_url() helper function:

from homeassistant.helpers import network

 network.get_url(
          hass,
          allow_external=True,
          allow_internal=True,
          allow_ip=True,
          prefer_external=True,
          require_ssl=False)

Looking at the documentation. It seems that this error is raised "if absolutely no URL is available (or none match given requirements), an exception will be raised: NoURLAvailableError".

The code is allowing for external, internal and IP, and not needing SSL; so as long as one of these is available, I assume it would return it. Do you know why none of these are available on your case or where the instance URL is located in your case?

I can easily handle the exception, but I am not sure where to get the URL if it's not available there, though.

The backup used to be base_url = hass.config.api.base_url - but this method is deprecated, in favor of the one above.

I can see new parameters that were not built in before like allow_cloud. Although it seems that's enabled by default, so it should technically already be included implicitly in the code above.

allow_cloud: Allow a Home Assistant Cloud URL to be returned, set to False in case one requires anything but a Cloud URL.

daswass commented 1 year ago

Thanks for the quick reply.

Version: Home Assistant 2023.8.1

Maybe allow_cloud should be set to false, given the URL isn't the HA Cloud URL, but a custom one, in my case mydomain.duckdns.org:8123, which dynamically updates to the public IP periodically.

daswass commented 1 year ago

Fixed! The solution was to add the external url to the Network page, where previously this was not necessary because I was only accessing HA internally.

nitobuendia commented 1 year ago

Thanks @daswass for confirming.

Replying to:

Maybe allow_cloud should be set to false, given the URL isn't the HA Cloud URL, but a custom one, in my case mydomain.duckdns.org:8123, which dynamically updates to the public IP periodically.

I don't think so. allow_cloud only allows for the cloud URL if that's present. There's still a prioritization order, where it would fallback to this or others depending on which one is available. In your case, none of the URLs were present at all. As such, none could be retrieved. Therefore allow_cloud=True should either make no impact (another URL not found, your case) or help here (cloud URL would be available while the rest weren't).

In any case, glad you found a fix.

We could document this and link to this article. I will reopen the issue and close it once the documentation is updated.