core icon indicating copy to clipboard operation
core copied to clipboard

Implement Somfy local API in Overkiz integration

Open iMicknl opened this issue 3 years ago • 43 comments

The problem

Somfy just announced the Somfy TaHoma Developer Mode, which offers a local API on eligble TaHoma boxes (TaHoma V2, TaHoma switch, TaHoma DIN-Rail v1 & v2).

They also announced that they are sunsetting the Somfy Open API, which is used by the Somfy integration. The API will be supported until June 21st 2022.

The local API is based on the same architecture as the current Overkiz integration in core, thus it would make sense to sunset the Somfy integration and add local support to the Overkiz integration.

Full Announcement

Dear customer,

We are glad to contact you today for the release of a new service we call Developer Mode, available for the different types of TaHoma boxes*.

This new service allows to activate a local API on your TaHoma box and finally connect third-party software to your equipment. A complete documentation of the service is available on GitHub. In a nutshell, the API allows to monitor and control the devices which are paired locally with your TaHoma box without the constraint of going through our servers. Thanks to the new Developer Mode, you can easily integrate your Somfy equipment with third-party home automation softwares.

Support Our support teams are available for any problems or questions regarding the use or operation of the TaHoma system. However, for questions related to the development of third party software using the API, please refer to the page mentioned above for further details. Finally, for problems or questions concerning the use of said software, it is necessary to contact the supplier or developer of the chosen solution directly for assistance.

Warning The applications proposed by Somfy to use its boxes and connected solutions employ a certain number of rules designed to preserve the integrity of your equipment. Please be careful when using the API so as not to damage them. Somfy declines all responsibility for inappropriate use. Similarly, the use of the TaHoma application in conjunction with the API may cause conflicts or contrary actions for which Somfy cannot be held responsible. Also, to ensure the proper functioning of your box, be sure to limit the demands on it.

Sunsetting Somfy Open API It is always hard to say goodbye but Developer Mode is so much better ! Its release therefore announces the depreciation of the Somfy Open API (cloud-based) as the new service will provide a larger number of features (scenarios and group commands being included) but also a larger number of supported devices. Finally, the Developer Mode, by its local nature, avoid any downtime issue or traffic limitation.

If you are a Somfy Open API customer, from the entire Somfy team, we’d like to apologize for any inconvenience this may cause you. We’re committed to making the transition as smooth as possible and that’s why we’ll continue to support this API until June 21st 2022.

Thank you for your understanding and we hope you will enjoy this new service.

*Eligible TaHoma Boxes: TaHoma V2, TaHoma switch, TaHoma DIN-Rail v1 & v2

TODO

  • [x] Add deprecation notice (with date / migration path) to Somfy integration
  • [ ] Implement local API
    • [x] Support local API in python-overkiz-api
    • [x] Extend Config Flow
    • [ ] Check for self-signed SSL cert docs
    • [ ] Fix diagnostics (client.get_execution_history() does not exist)
    • [ ] Remove auth token when we unload the integration

Integration causing the issue

overkiz, somfy

Link to integration documentation on our website

https://www.home-assistant.io/integrations/overkiz/ https://www.home-assistant.io/integrations/somfy/

iMicknl avatar Apr 07 '22 09:04 iMicknl

overkiz documentation overkiz source (message by IssueLinks)

Hey there @vlebourl, @tetienne, mind taking a look at this issue as it has been labeled with an integration (overkiz) you are listed as a code owner for? Thanks! (message by CodeOwnersMention)

This actually sounds awesome! I have had quite a lot of issues with the cloud API limitations. Is there anything I can help with? I'm really looking forward to this being live in the Overkiz integration! 🚀

downdrown avatar Apr 22 '22 07:04 downdrown

This actually sounds awesome! I have had quite a lot of issues with the cloud API limitations. Is there anything I can help with? I'm really looking forward to this being live in the Overkiz integration! 🚀

We have a proof of concept working, however we wait until a fix on Somfy's side is released (https://github.com/Somfy-Developer/Somfy-TaHoma-Developer-Mode/issues/4). Until then, we cannot move forward.

iMicknl avatar Apr 28 '22 06:04 iMicknl

Grateful for all your effort, but I am getting nervous. The fix this was waiting for seems fixed some time ago, and the old integration is deprecated. Wasn't this supposed to be in the 2022.6 release? This is needed withing three weeks, so it cannot wait till the next major release 2022.7.

EDelsman avatar Jun 01 '22 20:06 EDelsman

@EDelsman , if I am not mistaking the depreciation of the Somfy API only affects the Somfy integration and not the Overkiz integration since they both use different login authentifications.

XalaTheShepard avatar Jun 05 '22 14:06 XalaTheShepard

Thanks. Let's hope you are indeed not mistaking ;-)

EDelsman avatar Jun 05 '22 14:06 EDelsman

It was also mentioned in the 2022.6.0 release notes

XalaTheShepard avatar Jun 05 '22 14:06 XalaTheShepard

I read those, but they just said: Switch to Overkiz. So I turned to the documentation, that states: "The Somfy Open API (cloud-based) has been deprecated in favor of the Somfy TaHoma Developer Mode and will shut down after June 21st, 2022. The Overkiz integration will support this new local API and can already be used to control your Somfy devices via the cloud."

So that the first deprecated cloud based is different from the second was not clear to me. I read in it that I should switch to local instead (Which I greatly prefer).

EDelsman avatar Jun 05 '22 15:06 EDelsman

They use different logins.

XalaTheShepard avatar Jun 05 '22 16:06 XalaTheShepard

For those using Somfy MyLink, does this deprecated Somfy integration will affect our HA instance?

donparlor avatar Jun 07 '22 03:06 donparlor

For those using Somfy MyLink, does this deprecated Somfy integration will affect our HA instance?

Since it is a separate integration, I would assume you won’t face any issues. This will use a different connection than the deprecated ‘Open with Somfy API’.

iMicknl avatar Jun 07 '22 07:06 iMicknl

Ok great! I guess you are right, I don't feel on a hurry anymore 😂

Have a good day!

donparlor avatar Jun 07 '22 14:06 donparlor

And news here? Local access would be extremely great! I can test, if that helps.

chheiss avatar Jul 05 '22 08:07 chheiss

so do: https://community.home-assistant.io/t/overkiz-api-and-somfy-api/61448/1829

Mariusthvdb avatar Jul 05 '22 08:07 Mariusthvdb

Adding a report here as per request in: https://community.home-assistant.io/t/overkiz-api-and-somfy-api/61448/1882

Results from testing the local integration branch following the instructions here: https://community.home-assistant.io/t/overkiz-api-and-somfy-api/61448/1829

My Tahoma Box is: https://www.somfy.me/en-gc/products/2401346/tahoma-box-home-automation and 'Developer Mode' is activated via the Somfy site.

HA version:

Home Assistant 2022.10.4
Frontend 20221010.0 - latest

Observed Behaviour

Autodiscovery of my Tahoma Hub occurs, although multiple instances of the same Hub are detected, although only one has the gateway.local address, others just prompt for the username and password.

Picking the one with the gateway.local address prompts for the username and password with the gateway address prepopulated:

screencapture-ha

Adding my username and password, this then completes, but the following error is shown in the home-assistant.log and the Overkiz integration is marked as 'Failed to Setup'.

Logger: homeassistant.config_entries
Source: custom_components/overkiz/__init__.py:64
Integration: Overkiz
First occurred: 10:48:16 (1 occurrences)
Last logged: 10:48:16

Error setting up entry gateway-XXXX-XXXX-XXXX.local:8443 for overkiz
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 365, in async_setup
    result = await component.async_setup_entry(hass, self)
  File "/config/custom_components/overkiz/__init__.py", line 64, in async_setup_entry
    token = entry.data[CONF_TOKEN]
KeyError: 'token'

rjlee avatar Oct 19 '22 10:10 rjlee

Thanks @rjlee! I will have a look why this can happen. Are there no other errors in the log? It seems that there is no token generated in the config flow, thus the next steps fail as well. I will see if I can make this more robust in an updated version :).

iMicknl avatar Oct 19 '22 10:10 iMicknl

No problem, thanks for the hard work. A quick review of the logs doesn't show any additional errors:

grep -i overkiz home-assistant.log
2022-10-19 09:47:25.572 WARNING (SyncWorker_0) [homeassistant.loader] We found a custom integration overkiz which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant
2022-10-19 09:48:16.837 ERROR (MainThread) [homeassistant.config_entries] Error setting up entry gateway-XXX-XXXX-XXXX.local:8443 for overkiz
  File "/config/custom_components/overkiz/__init__.py", line 64, in async_setup_entry

rjlee avatar Oct 19 '22 12:10 rjlee

@iMicknl

I had the same error locally and added some debug strings.

If I understand correctly, it seems that async_validate_input drops back to the else: statement. The check:

68         if user_input[CONF_HUB] == LOCAL:
69             LOGGER.error("LOCAL")
70             session = async_create_clientsession(self.hass)

Does not match because the value is actually somfy_europe. After changing that check I was able to setup the integration correctly (not sure if it's now actually talking locally) :-)

slyoldfox avatar Oct 19 '22 18:10 slyoldfox

I've done a bit more debugging. I've enabled debug and I now see this logline:

CONFIGURING LOCAL INTEGRATION

So, it's activating:

    # Local API vs Cloud API
    # TODO add a helper function to see if local API
    if entry.data.get(CONF_HOST):
        LOGGER.debug("CONFIGURING LOCAL INTEGRATION")
        host = entry.data[CONF_HOST]
        token = entry.data[CONF_TOKEN]


        # Verify SSL blocked by https://github.com/Somfy-Developer/Somfy-TaHoma-Developer-Mode/issues/5
        # Somfy (self-signed) SSL cert uses the wrong common name
        session = async_create_clientsession(hass, verify_ssl=False)

Permalink

Which fails on:

File "/config/custom_components/overkiz/__init__.py", line 67, in async_setup_entry
    token = entry.data[CONF_TOKEN]
KeyError: 'token'

Dumping entry.data gives:

{'host': 'gateway-xxxx-xxxx-xxxx.local:8443', 'username': '[email protected]', 'password': 'mypassword', 'hub': 'somfy_europe'}

From searching the code, I can't see anywhere that CONF_TOKEN gets set though, so I assume that's the issue.

Then, as per https://github.com/home-assistant/core/issues/69558#issuecomment-1284398066

I tried to force local instantiation via changing:

68         if user_input[CONF_HUB] == LOCAL:
69             LOGGER.error("LOCAL")
70             session = async_create_clientsession(self.hass)

To

68         if user_input[CONF_HUB] == 'somfy_europe':
69             LOGGER.error("LOCAL")
70             session = async_create_clientsession(self.hass)

This seemed to get further, but ultimately ended up with an error from pyoverkiz:

Not such token with UUID: aaa-bbb-ccc-ddd

Dumping token and uuid both seem to have valid values FWIW. Checking pyoverkiz shows the latest version is installed in the docker container:

 pip list | grep pyover
pyoverkiz                        1.5.5

At that point, I'm stuck, so hopefully that's helpful.

rjlee avatar Oct 19 '22 23:10 rjlee

@rjlee I think I had this at one point as well.

I'm not sure what I did though. Maybe the token is cached on disk and it didn't delete it (I think I saw that skimming through the code?).

Did you delete the integration after changing the line and restart - then readded it?

slyoldfox avatar Oct 20 '22 05:10 slyoldfox

After some debugging, I figured it out. The gateway-XXX-XXXX-XXXX.local:8443 doesn't appear to be resolvable on my network, so setting it to the IP address of my Tahama Box 192.168.x.x:8443 and the following change made it work for me:

LOCAL = "somfy_europe"
#LOCAL = "local"
LOCAL_HUB = {
    LOCAL: OverkizServer(
        name="Somfy TaHoma Developer Mode (local API)",
        endpoint="",
        manufacturer="Somfy",
        configuration_url=None,
    )
}

So as per https://github.com/home-assistant/core/issues/69558#issuecomment-1284398066.

@slyoldfox thanks for the help.

@iMicknl FYI - on the issue I experienced and a potential fix.

The only issue that remains is the autodiscovery of multiple instances of the Tahoma hub on the devices page, but that's more an annoyance than a blocker.

Hope that helps.

rjlee avatar Oct 20 '22 10:10 rjlee

Ah yah. That was it lol. The exception ended there but the root cause was an Address Could Not Be Resolved exception.

We might need to fix that first. The possible reason is that this is discovered using mdns (?) but my freshly setup ubuntu server doesn't hook into that.

I ended up adding it to my /etc/hosts file:

192.168.2.30 gateway-2017-0514-1111.local

I'm not sure if the hub responds with its IP address somewhere so we can use that instead during the setup?

slyoldfox avatar Oct 20 '22 11:10 slyoldfox

@slyoldfox that is interesting. My preference is to use the mdns address, but the Config Flow will accept the IP address as well for cases where the mdns address cannot be resolved.

iMicknl avatar Oct 20 '22 12:10 iMicknl

Well yes of course the mdns address must be the first option. But if the actual resolving fails during config flow, it would be interesting to have a better handling:

  • either fail completely with a decent error and link to documentation (add to hosts file or install a service that resolves it)
  • either fall back to IP with a warning message that mdns resolution was not available and it will use the IP instead (that is if that is available somewhere)

slyoldfox avatar Oct 20 '22 13:10 slyoldfox

For reference this is the stacktrace:

2022-10-20 15:45:00.418 ERROR (MainThread) [custom_components.overkiz] Not such token with UUID: f5a3dcdd-ac10-3e01-6199-5f1124cfffbf
Traceback (most recent call last):
  File "/home/hass/homeassistant/lib/python3.10/site-packages/aiohttp/connector.py", line 1154, in _create_direct_connection
    hosts = await asyncio.shield(host_resolved)
  File "/home/hass/homeassistant/lib/python3.10/site-packages/aiohttp/connector.py", line 880, in _resolve_host
    addrs = await self._resolver.resolve(host, port, family=self._family)
  File "/home/hass/homeassistant/lib/python3.10/site-packages/aiohttp/resolver.py", line 33, in resolve
    infos = await self._loop.getaddrinfo(
  File "/usr/lib/python3.10/asyncio/base_events.py", line 860, in getaddrinfo
    return await self.run_in_executor(
  File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/lib/python3.10/socket.py", line 955, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -3] Temporary failure in name resolution

Traceback (most recent call last):
  File "/home/hass/.homeassistant/custom_components/overkiz/config_flow.py", line 112, in async_validate_input
    await local_client.login()
  File "/home/hass/homeassistant/lib/python3.10/site-packages/pyoverkiz/client.py", line 159, in login
    await self.register_event_listener()
  File "/home/hass/homeassistant/lib/python3.10/site-packages/backoff/_async.py", line 133, in retry
    ret = await target(*args, **kwargs)
  File "/home/hass/homeassistant/lib/python3.10/site-packages/pyoverkiz/client.py", line 528, in register_event_listener
    response = await self.__post("events/register")
  File "/home/hass/homeassistant/lib/python3.10/site-packages/pyoverkiz/client.py", line 775, in __post
    async with self.session.post(
  File "/home/hass/homeassistant/lib/python3.10/site-packages/aiohttp/client.py", line 1138, in __aenter__
    self._resp = await self._coro
  File "/home/hass/homeassistant/lib/python3.10/site-packages/aiohttp/client.py", line 535, in _request
    conn = await self._connector.connect(
  File "/home/hass/homeassistant/lib/python3.10/site-packages/aiohttp/connector.py", line 542, in connect
    proto = await self._create_connection(req, traces, timeout)
  File "/home/hass/homeassistant/lib/python3.10/site-packages/aiohttp/connector.py", line 907, in _create_connection
    _, proto = await self._create_direct_connection(req, traces, timeout)
  File "/home/hass/homeassistant/lib/python3.10/site-packages/aiohttp/connector.py", line 1166, in _create_direct_connection
    raise ClientConnectorError(req.connection_key, exc) from exc
aiohttp.client_exceptions.ClientConnectorError: Cannot connect to host gateway-2017-0459-8156.local:8443 ssl:default [Temporary failure in name resolution]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/hass/.homeassistant/custom_components/overkiz/config_flow.py", line 245, in async_step_local
    user_input = await self.async_validate_input(user_input)
  File "/home/hass/.homeassistant/custom_components/overkiz/config_flow.py", line 114, in async_validate_input
    await client.delete_local_token(gateway_id, uuid)
  File "/home/hass/homeassistant/lib/python3.10/site-packages/backoff/_async.py", line 133, in retry
    ret = await target(*args, **kwargs)
  File "/home/hass/homeassistant/lib/python3.10/site-packages/pyoverkiz/client.py", line 727, in delete_local_token
    await self.__delete(f"config/{gateway_id}/local/tokens/{uuid}")
  File "/home/hass/homeassistant/lib/python3.10/site-packages/pyoverkiz/client.py", line 793, in __delete
    await self.check_response(response)
  File "/home/hass/homeassistant/lib/python3.10/site-packages/pyoverkiz/client.py", line 864, in check_response
    raise NotSuchTokenException(message)
pyoverkiz.exceptions.NotSuchTokenException: Not such token with UUID: f5a3dcdd-ac10-3e01-6399-5f1124ca0abf

slyoldfox avatar Oct 20 '22 13:10 slyoldfox

After some debugging, I figured it out. The gateway-XXX-XXXX-XXXX.local:8443 doesn't appear to be resolvable on my network, so setting it to the IP address of my Tahama Box 192.168.x.x:8443 and the following change made it work for me:

LOCAL = "somfy_europe"
#LOCAL = "local"
LOCAL_HUB = {
    LOCAL: OverkizServer(
        name="Somfy TaHoma Developer Mode (local API)",
        endpoint="",
        manufacturer="Somfy",
        configuration_url=None,
    )
}

So as per #69558 (comment).

@slyoldfox thanks for the help.

@iMicknl FYI - on the issue I experienced and a potential fix.

The only issue that remains is the autodiscovery of multiple instances of the Tahoma hub on the devices page, but that's more an annoyance than a blocker.

Hope that helps.

Thank you! I've managed to get it to work instantly by using IP!

HpNoTiQ56 avatar Oct 20 '22 14:10 HpNoTiQ56

@slyoldfox that is interesting. My preference is to use the mdns address, but the Config Flow will accept the IP address as well for cases where the mdns address cannot be resolved.

While I tested the local API, i did have the same issue: only IP address worked. In my understanding, it was due to the dev container and the way HA was loaded locally, which makes impossible to reach the host. it would need more testing while others elements will be finished, but IMHO this is not an issue real users will have.

nyroDev avatar Oct 20 '22 20:10 nyroDev

My Tahoma box registers itself in my DHCP as xxxx-xxxx-xxxx where they x's are the serial number of the box, no "gateway" infront of it and no .local after it . After entering xxxx-xxxx-xxxx.mylocaldomain.yy:8443 the local api works super (where mylocaldomain.yy is my local domain) . I hope this helps.

diedvdyk avatar Oct 25 '22 19:10 diedvdyk

@diedvdyk do you have any special networking setup? I don’t think this is default behavior at all..

iMicknl avatar Oct 25 '22 22:10 iMicknl