shenxn / ha-dyson

HomeAssitant custom integration for dyson
MIT License
311 stars 59 forks source link

Can't login to dyson_cloud #42

Closed jorgenbosman closed 2 years ago

jorgenbosman commented 3 years ago

When I try to install dyson_cloud, I always get "Failed to connect". When I try manually with libdyson, I get:

Traceback (most recent call last): File "/usr/local/lib/python3.7/site-packages/urllib3/util/ssl_.py", line 343, in ssl_wrap_socket context.load_verify_locations(ca_certs, ca_cert_dir, ca_cert_data) ssl.SSLError: [X509] PEM lib (_ssl.c:4062)

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 677, in urlopen chunked=chunked, File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 381, in _make_request self._validate_conn(conn) File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 976, in _validate_conn conn.connect() File "/usr/local/lib/python3.7/site-packages/urllib3/connection.py", line 370, in connect sslcontext=context, File "/usr/local/lib/python3.7/site-packages/urllib3/util/ssl.py", line 345, in ssl_wrap_socket raise SSLError(e) urllib3.exceptions.SSLError: [X509] PEM lib (_ssl.c:4062)

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "/usr/local/lib/python3.7/site-packages/requests/adapters.py", line 449, in send timeout=timeout File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 725, in urlopen method, url, error=e, _pool=self, _stacktrace=sys.exc_info()[2] File "/usr/local/lib/python3.7/site-packages/urllib3/util/retry.py", line 439, in increment raise MaxRetryError(_pool, url, error or ResponseError(cause)) urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='appapi.cp.dyson.com', port=443): Max retries exceeded with url: /v3/userregistration/email/userstatus?country=GB (Caused by SSLError(SSLError(9, '[X509] PEM lib (_ssl.c:4062)')))

shenxn commented 3 years ago

I'm not sure what causes this. What is the environment your HA runs on?

jorgenbosman commented 3 years ago

Centos 7.9.2009 (Core) Python 3.8.3

shenxn commented 3 years ago

Sorry I cannot reproduce this problem. I'll try to setup a VM.

jorgenbosman commented 3 years ago

Installed hass in a docker container and now it works

FransHalsjes commented 3 years ago

Having more or less the same error when installing Dyson Cloud. (Dyson local is present in HACS, but not installed in HA. HA running HASSos 2021.6.5 in a VM.

Getting: Logboekdetails (FOUT) Deze fout is ontstaan door een aangepaste integratie. Logger: aiohttp.server Source: custom_components/dyson_cloud/config_flow.py:71 Integration: Dyson Cloud (documentation, issues) First occurred: 13:25:49 (4 occurrences) Last logged: 13:26:22

Error handling request Traceback (most recent call last): File "/usr/local/lib/python3.8/site-packages/aiohttp/web_protocol.py", line 422, in _handle_request resp = await self._request_handler(request) File "/usr/local/lib/python3.8/site-packages/aiohttp/web_app.py", line 499, in _handle resp = await handler(request) File "/usr/local/lib/python3.8/site-packages/aiohttp/web_middlewares.py", line 119, in impl return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 60, in security_filter_middleware return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 76, in forwarded_middleware return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 24, in request_context_middleware return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 78, in ban_middleware return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 144, in auth_middleware return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/view.py", line 135, in handle result = await result File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 155, in post return await super().post(request, flow_id) File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 63, in wrapper result = await method(view, request, *args, *kwargs) File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 109, in post result = await self._flow_mgr.async_configure(flow_id, data) File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 202, in async_configure result = await self._async_handle_step(flow, cur_step["step_id"], user_input) File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 260, in _async_handle_step result: FlowResult = await getattr(flow, method)(user_input) File "/config/custom_components/dyson_cloud/config_flow.py", line 71, in async_step_email self._verify = await self.hass.async_add_executor_job( File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run result = self.fn(self.args, **self.kwargs) File "/usr/local/lib/python3.8/site-packages/libdyson/cloud/account.py", line 127, in login_email_otp response = self.request( File "/usr/local/lib/python3.8/site-packages/libdyson/cloud/account.py", line 119, in request raise DysonInvalidAuth libdyson.exceptions.DysonInvalidAuth

(might it have something to to with the two-phase autentication Dyson has put in in the app? You now have to add not only your email and password but also a code that, during login, is sent to you via email.)

shenxn commented 3 years ago

@FransHalsjes see #59.

HammerAce42 commented 3 years ago

I am seeing the “Failed to connect” error as soon as I enter my e-mail address as well. My config is as follows:

Home Assistant OS 6.3 on Raspberry Pi 4 core-2021.9.3

I have debug logs enabled, but nothing appears to get logged when this happens.

codexterous commented 3 years ago

I'm also getting this. core-2021.9.6 on FreeBSD 12. I believe it's related to their CloudFlare configuration.

>>> from libdyson.cloud import account      
>>> ac=account.DysonAccount()
>>> ac.login_email_otp('****@*****.***', 'US')
Traceback (most recent call last):
  File "/usr/home/homeassistant/.virtualenvs/homeassistant/lib/python3.8/site-packages/urllib3/connectionpool.py", line 699, in urlopen
    httplib_response = self._make_request(
  File "/usr/home/homeassistant/.virtualenvs/homeassistant/lib/python3.8/site-packages/urllib3/connectionpool.py", line 382, in _make_request
    self._validate_conn(conn)
  File "/usr/home/homeassistant/.virtualenvs/homeassistant/lib/python3.8/site-packages/urllib3/connectionpool.py", line 1010, in _validate_conn
    conn.connect()
  File "/usr/home/homeassistant/.virtualenvs/homeassistant/lib/python3.8/site-packages/urllib3/connection.py", line 411, in connect
    self.sock = ssl_wrap_socket(
  File "/usr/home/homeassistant/.virtualenvs/homeassistant/lib/python3.8/site-packages/urllib3/util/ssl_.py", line 449, in ssl_wrap_socket
    ssl_sock = _ssl_wrap_socket_impl(
  File "/usr/home/homeassistant/.virtualenvs/homeassistant/lib/python3.8/site-packages/urllib3/util/ssl_.py", line 493, in _ssl_wrap_socket_impl
    return ssl_context.wrap_socket(sock, server_hostname=server_hostname)
  File "/usr/local/lib/python3.8/ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "/usr/local/lib/python3.8/ssl.py", line 1040, in _create
    self.do_handshake()
  File "/usr/local/lib/python3.8/ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1136)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/home/homeassistant/.virtualenvs/homeassistant/lib/python3.8/site-packages/requests/adapters.py", line 439, in send
    resp = conn.urlopen(
  File "/usr/home/homeassistant/.virtualenvs/homeassistant/lib/python3.8/site-packages/urllib3/connectionpool.py", line 755, in urlopen
    retries = retries.increment(
  File "/usr/home/homeassistant/.virtualenvs/homeassistant/lib/python3.8/site-packages/urllib3/util/retry.py", line 574, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='appapi.cp.dyson.com', port=443): Max retries exceeded with url: /v3/userregistration/email/userstatus?country=US (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1136)')))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/home/homeassistant/.virtualenvs/homeassistant/lib/python3.8/site-packages/libdyson/cloud/account.py", line 107, in request
    response = requests.request(
  File "/usr/home/homeassistant/.virtualenvs/homeassistant/lib/python3.8/site-packages/requests/api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/home/homeassistant/.virtualenvs/homeassistant/lib/python3.8/site-packages/requests/sessions.py", line 542, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/home/homeassistant/.virtualenvs/homeassistant/lib/python3.8/site-packages/requests/sessions.py", line 655, in send
    r = adapter.send(request, **kwargs)
  File "/usr/home/homeassistant/.virtualenvs/homeassistant/lib/python3.8/site-packages/requests/adapters.py", line 514, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='appapi.cp.dyson.com', port=443): Max retries exceeded with url: /v3/userregistration/email/userstatus?country=US (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1136)')))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/home/homeassistant/.virtualenvs/homeassistant/lib/python3.8/site-packages/libdyson/cloud/account.py", line 127, in login_email_otp
    response = self.request(
  File "/usr/home/homeassistant/.virtualenvs/homeassistant/lib/python3.8/site-packages/libdyson/cloud/account.py", line 117, in request
    raise DysonNetworkError
libdyson.exceptions.DysonNetworkError

If I visit "https://appapi.cp.dyson.com" in my browser, I get a page generated by CloudFlare:

Error 1020 Ray ID: 68e28170a8b5640a • 2021-09-13 15:45:57 UTC Access denied What happened?

This website is using a security service to protect itself from online attacks.

tumma72 commented 2 years ago

I am having a similar issue, and I have tried to isolate the problem by removing from the equation the HA part, even using the command line tool get_devices.py there is an SSL error immediately after having entered the email address, so it isn't an authentication error, it is an issue with reading the SSL certificate when attempting to connect, at least it appears so:

$ python3 ./get_devices.py 
Please choose your account region
1: Mainland China
2: Rest of the World
Region [1/2]: 2
Region code: DE
Email: my@email.com [replaced with a fake one]
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 699, in urlopen
    httplib_response = self._make_request(
  File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 382, in _make_request
    self._validate_conn(conn)
  File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 1010, in _validate_conn
    conn.connect()
  File "/usr/local/lib/python3.9/site-packages/urllib3/connection.py", line 416, in connect
    self.sock = ssl_wrap_socket(
  File "/usr/local/lib/python3.9/site-packages/urllib3/util/ssl_.py", line 449, in ssl_wrap_socket
    ssl_sock = _ssl_wrap_socket_impl(
  File "/usr/local/lib/python3.9/site-packages/urllib3/util/ssl_.py", line 493, in _ssl_wrap_socket_impl
    return ssl_context.wrap_socket(sock, server_hostname=server_hostname)
  File "/usr/local/Cellar/python@3.9/3.9.0_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "/usr/local/Cellar/python@3.9/3.9.0_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ssl.py", line 1040, in _create
    self.do_handshake()
  File "/usr/local/Cellar/python@3.9/3.9.0_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1122)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/requests/adapters.py", line 439, in send
    resp = conn.urlopen(
  File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 755, in urlopen
    retries = retries.increment(
  File "/usr/local/lib/python3.9/site-packages/urllib3/util/retry.py", line 574, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='appapi.cp.dyson.com', port=443): Max retries exceeded with url: /v3/userregistration/email/userstatus?country=DE (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1122)')))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/atomasini/dev/libdyson/libdyson/cloud/account.py", line 107, in request
    response = requests.request(
  File "/usr/local/lib/python3.9/site-packages/requests/api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/requests/sessions.py", line 542, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.9/site-packages/requests/sessions.py", line 655, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/requests/adapters.py", line 514, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='appapi.cp.dyson.com', port=443): Max retries exceeded with url: /v3/userregistration/email/userstatus?country=DE (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1122)')))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/atomasini/dev/libdyson/./get_devices.py", line 22, in <module>
    verify = account.login_email_otp(email, region)
  File "/Users/atomasini/dev/libdyson/libdyson/cloud/account.py", line 127, in login_email_otp
    response = self.request(
  File "/Users/atomasini/dev/libdyson/libdyson/cloud/account.py", line 117, in request
    raise DysonNetworkError
libdyson.exceptions.DysonNetworkError

I have run the command line directly from inside the RBP using the supervisor shell and from my Mac OS running:

Python 3.9.0 (default, Oct 27 2020, 14:15:17) 
[Clang 12.0.0 (clang-1200.0.32.21)] on darwin

same results in both environments...

HTH let me know if you need other information and thanks for the great work :-)

codexterous commented 2 years ago

The original response had me thinking I was somehow being blocked by CloudFlare (https://appapi.cp.dyson.com is indeed a 403 generated by them), but in fact I was not. I had planned to try again later with a different IP address, but came back to it recently and tried over several VPNs and public networks with the same result. I then realized that a curl to an actual URL:

$ curl https://appapi.cp.dyson.com/v3/userregistration/email/userstatus?country=DE

Actually returned JSON, so, I wasn't actually being blocked. It seems something is wrong with their SSL configuration or something.

I worked around this issue, at least temporarily, by passing verify=False to the requests.request() call on line 114 of libdyson/cloud/account.py.

This obviously isn't a real fix, but I was at least able to get my air purifier's password so that I could control it with HomeAssistant.

Kakise commented 2 years ago

The problem is inside libdyson, previously Dyson used its own CA to make ssl certificates, now they have switched to CloudFlare and the lib needs to be updated. An update to fix this error is in the works

tumma72 commented 2 years ago

The original response had me thinking I was somehow being blocked by CloudFlare (https://appapi.cp.dyson.com is indeed a 403 generated by them), but in fact I was not. I had planned to try again later with a different IP address, but came back to it recently and tried over several VPNs and public networks with the same result. I then realized that a curl to an actual URL:

$ curl https://appapi.cp.dyson.com/v3/userregistration/email/userstatus?country=DE

Actually returned JSON, so, I wasn't actually being blocked. It seems something is wrong with their SSL configuration or something.

I worked around this issue, at least temporarily, by passing verify=False to the requests.request() call on line 114 of libdyson/cloud/account.py.

This obviously isn't a real fix, but I was at least able to get my air purifier's password so that I could control it with HomeAssistant.

Thanks for the quick reply, as you said it isn't a real fix, but it does the trick when everything you need is to extract the credentials :-) It worked for me at the second attempt... and I have now configured the Dyson using the Dyson Local module in the HA configuration page. What I have noticed though, is that setting it to Auto doesn't change the fan speed, but only the Humidity settings... perhaps some more tweaking is necessary on my side?

Kakise commented 2 years ago

I pushed an update to both ha-dyson and libdyson to account for the certificate change on Dyson's part, can you all try it and tell me if it works ? This way I can go ahead and close this issue. Thank you very much !

tumma72 commented 2 years ago

I pushed an update to both ha-dyson and libdyson to account for the certificate change on Dyson's part, can you all try it and tell me if it works ? This way I can go ahead and close this issue. Thank you very much !

Thanks for the push, I have tried the new version a couple of times, and I keep on getting this error, which is interestingly happening before I am prompted for a password:

$ python3 ./get_devices.py 
Please choose your account region
1: Mainland China
2: Rest of the World
Region [1/2]: 2
Region code: DE
Email: my@fake.email
Traceback (most recent call last):
  File "/Users/atomasini/dev/libdyson/./get_devices.py", line 22, in <module>
    verify = account.login_email_otp(email, region)
  File "/Users/atomasini/dev/libdyson/libdyson/cloud/account.py", line 121, in login_email_otp
    response = self.request(
  File "/Users/atomasini/dev/libdyson/libdyson/cloud/account.py", line 113, in request
    raise DysonInvalidAuth
libdyson.exceptions.DysonInvalidAuth

When I tried without SSL validation, I also got this error one time, and the second time after the warning for the SSL lack of validation it actually prompted for a password... and it worked. Now I have tried several times, but I never reach the point at which a password prompt appears... is it a synchronization issue?

Kakise commented 2 years ago

I pushed an update to both ha-dyson and libdyson to account for the certificate change on Dyson's part, can you all try it and tell me if it works ? This way I can go ahead and close this issue. Thank you very much !

Thanks for the push, I have tried the new version a couple of times, and I keep on getting this error, which is interestingly happening before I am prompted for a password:

$ python3 ./get_devices.py 
Please choose your account region
1: Mainland China
2: Rest of the World
Region [1/2]: 2
Region code: DE
Email: my@fake.email
Traceback (most recent call last):
  File "/Users/atomasini/dev/libdyson/./get_devices.py", line 22, in <module>
    verify = account.login_email_otp(email, region)
  File "/Users/atomasini/dev/libdyson/libdyson/cloud/account.py", line 121, in login_email_otp
    response = self.request(
  File "/Users/atomasini/dev/libdyson/libdyson/cloud/account.py", line 113, in request
    raise DysonInvalidAuth
libdyson.exceptions.DysonInvalidAuth

When I tried without SSL validation, I also got this error one time, and the second time after the warning for the SSL lack of validation it actually prompted for a password... and it worked. Now I have tried several times, but I never reach the point at which a password prompt appears... is it a synchronization issue?

I pushed a critical fix to the libdyson repo and yup, it is a synch issue. You need to actually disconnect your phone from the Dyson Link app, then right after that, use the script, and then you should be good to go (or at least that worked on my machine with a TP04)

tumma72 commented 2 years ago

The fix definitely removed the SSL problem, perhaps an explanation about having to disconnect the phone app would be helpful. For me it worked after some attempt even without removing the link from my phone... so there is something weird in the way the remote connection is handled, this is why I preferred to chose the local connection with the data at hand.

Kakise commented 2 years ago

What seems to be happening is that for some reason, the Dyson app will mark the account as inactive after a successful link to Dyson Cloud. The app probably sends another requests to "wake" the account up. Anyway I'm gonna close this issue and add something about it in the readme for the time being.

Thanks all for your help ! :)

jasonbwilliams commented 2 years ago

Hi All, I'm trying to use Dyson Cloud and I'm encountering the error described above (Failed to Connect after entering my email address). I have tried logging out of the Dyson app on my phone, but it doesn't seem to make a difference. Is there something else I can try? I did have this working before, but I'm starting over. My HA is Supervised on Debian and is v2021.12.4

EDelsman commented 2 years ago

I've got the same problem - either an unexpected error or simply 'aborted' right after I entered my email. This is a new integration for me, so I didn't have it working before. I've tried logging out from the app but that didn't help.

I also cannot use the wifi method for local connect since there's no wifi sticker to be found anywhere: the device uses bluetooth for the initial setup instead of it's own wifi hotspot it seems.

ctyd commented 2 years ago

same problem here, after entering the mail adress

EDelsman commented 2 years ago

After numerous attempts to get the cloud version working without succes, I finally did manage to get the local version running by using the manual method. I ran the python script from within Visual Studio Code on Windows 10. Maybe required certificates are present there that are missing in Home Assistant OS?

mriitan commented 2 years ago

can i news for the problem?

TheSpawnMan commented 2 years ago

having the same issue

erd82 commented 1 year ago

Maybe this post helps you: https://github.com/shenxn/ha-dyson/issues/178