home-assistant / core

:house_with_garden: Open source home automation that puts local control and privacy first.
https://www.home-assistant.io
Apache License 2.0
71.76k stars 30k forks source link

Roth Touchline SL failing to setup #126503

Open ploughansen opened 2 days ago

ploughansen commented 2 days ago

The problem

I get the following error (Failed to set up: Check the logs) when I try to setup the integration:

Log details (ERROR)
Logger: homeassistant.config_entries
Source: config_entries.py:604
First occurred: 21:49:49 (2 occurrences)
Last logged: 21:56:34

Error setting up entry my_username for touchline_sl
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 604, in async_setup
    result = await component.async_setup_entry(hass, self)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/touchline_sl/__init__.py", line 29, in async_setup_entry
    TouchlineSLModuleCoordinator(hass, module) for module in await account.modules()
                                                             ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/pytouchlinesl/touchlinesl.py", line 66, in modules
    data = await self._client.modules()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/pytouchlinesl/client/client.py", line 98, in modules
    return [AccountModuleModel(**m) for m in resp]
            ^^^^^^^^^^^^^^^^^^^^^^^
  File "pydantic/main.py", line 341, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for AccountModuleModel
tag
  none is not an allowed value (type=type_error.none.not_allowed)

I am 1000% sure the username and password is correct (I can login to https://roth-touchlinesl.com/login just fine), but other than that, I have no idea what to make of the error?

What version of Home Assistant Core has the issue?

2024.9.2

What was the last working version of Home Assistant Core?

No response

What type of installation are you running?

Home Assistant OS

Integration causing the issue

Roth Touchline SL

Link to integration documentation on our website

https://www.home-assistant.io/integrations/touchline_sl/

Diagnostics information

No response

Example YAML snippet

No response

Anything in the logs that might be useful for us?

No response

Additional information

No response

home-assistant[bot] commented 2 days ago

touchlinesl documentation touchlinesl source

home-assistant[bot] commented 2 days ago

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

Code owner commands Code owners of `touchline_sl` can trigger bot actions by commenting: - `@home-assistant close` Closes the issue. - `@home-assistant rename Awesome new title` Renames the issue. - `@home-assistant reopen` Reopen the issue. - `@home-assistant unassign touchline_sl` Removes the current integration label and assignees on the issue, 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 issue. - `@home-assistant remove-label needs-more-information` Remove a label (needs-more-information, problem in dependency, problem in custom component) on the issue.

(message by CodeOwnersMention)


touchline_sl documentation touchline_sl source (message by IssueLinks)

jnsgruk commented 2 days ago

Hmm, that's very odd. I think I need some more information about the response you're getting from the API to work out what's happened here.

Can you try running the following script, editing the username and password as appropriate. You can check the output before posting to ensure you're happy. It will output three lines:

#!/usr/bin/env bash

USERNAME='YOUR_USERNAME'
PASSWORD='YOUR_PASSWORD'

API_URL="https://roth-touchlinesl.com/api/v1"
LOGIN_PATH="/authentication"

# POST to the login endpoint
LOGIN_DATA="{\"username\":\"$USERNAME\", \"password\":\"$PASSWORD\"}"
LOGIN_RESPONSE="$(curl -s -X POST -d "$LOGIN_DATA" "${API_URL}${LOGIN_PATH}")"

# Output 'true' if authenticated correctly
echo "$LOGIN_RESPONSE" | jq '.authenticated'

# GET the modules endpoint
USER_ID="$(echo "$LOGIN_RESPONSE" | jq -r '.user_id')"
TOKEN="$(echo "$LOGIN_RESPONSE" | jq -r '.token')"
MODULES_PATH="/users/${USER_ID}/modules"

MODULES_RESPONSE="$(curl -s -H "Authorization: Bearer ${TOKEN}" "${API_URL}${MODULES_PATH}")"

# Output some data
echo "$MODULES_RESPONSE" | jq length
echo "$MODULES_RESPONSE" | jq '.[].type'
echo
echo "Don't post this next bit, but check the details:"
echo
echo "$MODULES_RESPONSE"

It just needs curl and jq installed. For me, the output looks like this:

❯ bash test-roth-api.sh
true
1
"zones_controller"
ploughansen commented 1 day ago

Thank you for the quick response.

I am not sure I'm doing this correctly... (as I don't get the intended output 😉)

I have installed HomeBrew, and JQ (I am on Macos).

I then copied your script into Terminal, replaced 'YOUR_USERNAME' and 'YOUR_PASSWORD' with my actual username and password, but this is what I get in response: {"error":{"authenticated":false}}

I understand this seems like I am typing the wrong username and password, but I am confident that is not the case.

I use a password manager, so I am not even typing the password. I copy/paste it directly from the password manager, and doing the same on https://roth-touchlinesl.com/login will log me in without any problems.

I place my username/password in your script like so (not my actual username/password):

#/usr/bin/env bash bash

USERNAME='johndoe'
PASSWORD='123456789'

API_URL="https://roth-touchlinesl.com/api/v1"
LOGIN_PATH="/authentication"

I have also tried without the 'ticks' but the result is the same.

Can it have anything to do with the fact that I have multiple modules in my account? Or do I need to use something else than my actual username/password (perhaps some sort of API authentication token?

jnsgruk commented 1 day ago

Huh. Can you try just a bare curl:

curl -X POST -d '{"username":"YOUR_USERNAME", "password":"YOUR_PASSWORD"}' "https://roth-touchlinesl.com/api/v1/authentication"
ploughansen commented 1 day ago

This returns: {"authenticated":true,"user_id":...

I take it you don't need to see the rest of the response?

jnsgruk commented 1 day ago

Aha that's interesting! So I wonder what's causing the authentication to fail in other circumstances. I don't suppose you have any crazy symbols in your password? I'd be surprised if that's causing issues in the python library, but I'm a bit perplexed!

ploughansen commented 1 day ago

Well I did have a few symbols in it, but I just tried resetting the password to a very simple one, and that had zero effect.

So yeah... wonder what's causing this 👀

jnsgruk commented 1 day ago

Okay, how about trying to use the Python module directly?

import asyncio
from pytouchlinesl import TouchlineSL

USERNAME = "jon@foobar.com"
PASSWORD = "deadbeef"

async def main():
    tsl = TouchlineSL(username=USERNAME, password=PASSWORD)
    print([module.id for module in await tsl.modules()])

if __name__ == "__main__":
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    asyncio.run(main())

You need to have pytouchlinesl installed, and if this file is saved as test.py, you can do that like so:

python3 -m venv venv
source venv/bin/activate
pip install pytouchlinesl

python3 test.py
ploughansen commented 1 day ago

I had to update pip, but after doing so, I got this error when trying to install pytouchlinesl:

ERROR: Ignored the following versions that require a different python version: 0.1.0 Requires-Python >=3.10; 0.1.1 Requires-Python >=3.10; 0.1.2 Requires-Python >=3.10; 0.1.3 Requires-Python >=3.10; 0.1.4 Requires-Python >=3.10; 0.1.5 Requires-Python >=3.10
ERROR: Could not find a version that satisfies the requirement pytouchlinesl (from versions: none)
ERROR: No matching distribution found for pytouchlinesl
/Users/myname/venv/bin/python3: can't open file '/Users/myname/test.py': [Errno 2] No such file or directory

Thank you for your patience... 😉

jnsgruk commented 1 day ago

Ah, interesting. The version of Python you're running is too old for pytouchlinesl, do you know how to install different versions? I can try and help if needs be.

ploughansen commented 1 day ago

I had version 3.10.x installed, so I just downloaded the latest stable release from https://www.python.org/downloads/ and installed that.

I then tried running the script again, and this time I got this:

Requirement already satisfied: pytouchlinesl in ./venv/lib/python3.12/site-packages (0.1.5)
Requirement already satisfied: aiohttp in ./venv/lib/python3.12/site-packages (from pytouchlinesl) (3.10.5)
Requirement already satisfied: pydantic in ./venv/lib/python3.12/site-packages (from pytouchlinesl) (2.9.2)
Requirement already satisfied: aiohappyeyeballs>=2.3.0 in ./venv/lib/python3.12/site-packages (from aiohttp->pytouchlinesl) (2.4.0)
Requirement already satisfied: aiosignal>=1.1.2 in ./venv/lib/python3.12/site-packages (from aiohttp->pytouchlinesl) (1.3.1)
Requirement already satisfied: attrs>=17.3.0 in ./venv/lib/python3.12/site-packages (from aiohttp->pytouchlinesl) (24.2.0)
Requirement already satisfied: frozenlist>=1.1.1 in ./venv/lib/python3.12/site-packages (from aiohttp->pytouchlinesl) (1.4.1)
Requirement already satisfied: multidict<7.0,>=4.5 in ./venv/lib/python3.12/site-packages (from aiohttp->pytouchlinesl) (6.1.0)
Requirement already satisfied: yarl<2.0,>=1.0 in ./venv/lib/python3.12/site-packages (from aiohttp->pytouchlinesl) (1.12.1)
Requirement already satisfied: annotated-types>=0.6.0 in ./venv/lib/python3.12/site-packages (from pydantic->pytouchlinesl) (0.7.0)
Requirement already satisfied: pydantic-core==2.23.4 in ./venv/lib/python3.12/site-packages (from pydantic->pytouchlinesl) (2.23.4)
Requirement already satisfied: typing-extensions>=4.6.1 in ./venv/lib/python3.12/site-packages (from pydantic->pytouchlinesl) (4.12.2)
Requirement already satisfied: idna>=2.0 in ./venv/lib/python3.12/site-packages (from yarl<2.0,>=1.0->aiohttp->pytouchlinesl) (3.10)
Traceback (most recent call last):
  File "/Users/myusername/venv/lib/python3.12/site-packages/aiohttp/connector.py", line 1080, in _wrap_create_connection
    return await self._loop.create_connection(*args, **kwargs, sock=sock)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/asyncio/base_events.py", line 1148, in create_connection
    transport, protocol = await self._create_connection_transport(
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/asyncio/base_events.py", line 1181, in _create_connection_transport
    await waiter
  File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/asyncio/sslproto.py", line 578, in _on_handshake_complete
    raise handshake_exc
  File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/asyncio/sslproto.py", line 560, in _do_handshake
    self._sslobj.do_handshake()
  File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/ssl.py", line 916, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1000)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/myusername/touchlinesl.py", line 16, in <module>
    asyncio.run(main())
  File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/asyncio/runners.py", line 194, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/asyncio/base_events.py", line 687, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/Users/myusername/touchlinesl.py", line 10, in main
    print([module.id for module in await tsl.modules()])
                                   ^^^^^^^^^^^^^^^^^^^
  File "/Users/myusername/venv/lib/python3.12/site-packages/pytouchlinesl/touchlinesl.py", line 66, in modules
    data = await self._client.modules()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/myusername/venv/lib/python3.12/site-packages/pytouchlinesl/client/client.py", line 95, in modules
    await self._login()
  File "/Users/myusername/venv/lib/python3.12/site-packages/pytouchlinesl/client/client.py", line 71, in _login
    resp = await self._post("/authentication", json=data)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/myusername/venv/lib/python3.12/site-packages/pytouchlinesl/client/client.py", line 209, in _post
    req = await session.post(f"{API_URL}{url}", headers=headers, json=json)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/myusername/venv/lib/python3.12/site-packages/aiohttp/client.py", line 657, in _request
    conn = await self._connector.connect(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/myusername/venv/lib/python3.12/site-packages/aiohttp/connector.py", line 564, in connect
    proto = await self._create_connection(req, traces, timeout)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/myusername/venv/lib/python3.12/site-packages/aiohttp/connector.py", line 975, in _create_connection
    _, proto = await self._create_direct_connection(req, traces, timeout)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/myusername/venv/lib/python3.12/site-packages/aiohttp/connector.py", line 1350, in _create_direct_connection
    raise last_exc
  File "/Users/myusername/venv/lib/python3.12/site-packages/aiohttp/connector.py", line 1319, in _create_direct_connection
    transp, proto = await self._wrap_create_connection(
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/myusername/venv/lib/python3.12/site-packages/aiohttp/connector.py", line 1082, in _wrap_create_connection
    raise ClientConnectorCertificateError(req.connection_key, exc) from exc
aiohttp.client_exceptions.ClientConnectorCertificateError: Cannot connect to host roth-touchlinesl.com:443 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1000)')]
(venv) myusername@myusername-MacBook ~ % 

Does this help?

jnsgruk commented 19 hours ago

Hmm not really -- I can't imagine why it would fail to validate the cert of the API, unless they've had some sort of outage today?

jnsgruk commented 4 hours ago

Have you tried totally removing the integration and re-adding it, and re-entering your credentials? I'm at a bit of a loss here.