Skip to content

Support Ecovacs device verification - #1706

Merged
edenhaus merged 4 commits into
DeebotUniverse:devfrom
bentbrain:agent/device-verification
Jul 30, 2026
Merged

Support Ecovacs device verification#1706
edenhaus merged 4 commits into
DeebotUniverse:devfrom
bentbrain:agent/device-verification

Conversation

@bentbrain

Copy link
Copy Markdown
Contributor

Summary

  • Add explicit errors for required device verification and invalid verification codes.
  • Support the signed getConfig, sendEmailVerifyCode, and verifyDevice requests used by current Ecovacs clients.
  • Encrypt the account identifier with Ecovacs' published RSA key and complete the existing token login flow after verification.
  • Avoid logging successful authentication response bodies, which may contain credentials.

Why

Ecovacs now returns error 1013 for client device IDs that have not completed device verification. Updating only the reported app version does not resolve the error; the client ID must complete the email verification flow and then remain stable across future logins.

The flow was validated against a live affected account: Ecovacs accepted the emailed code, and a separate fresh process subsequently completed password authentication with the same client ID and retrieved the account's device list.

This implementation has been validated for an email-based global account. China and phone-number account flows have not been validated.

Thanks to @christensenjames, @golf4r, @gatof81, and the other contributors who documented the current API behavior and device-ID requirement in the related Home Assistant investigation.

Fixes #1702.

Related to home-assistant/core#176484.

@Sanji78

Sanji78 commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

I tested it and I get:


2026-07-19 19:23:38.448 ERROR (MainThread) [homeassistant.components.ecovacs.config_flow] Unexpected exception during login
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/ecovacs/config_flow.py", line 85, in _validate_input
    await authenticator.authenticate()
  File "/usr/local/lib/python3.14/site-packages/deebot_client/authentication.py", line 504, in authenticate
    credentials = await self._auth_client.login()
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.14/site-packages/deebot_client/authentication.py", line 128, in login
    login_password_resp = await self.__call_login_api(
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        self._account_id, self._password_hash
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/local/lib/python3.14/site-packages/deebot_client/authentication.py", line 241, in __call_login_api
    response = await self.__do_auth_response(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        url, self.__sign(params, self._meta, _CLIENT_KEY, _CLIENT_SECRET)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/local/lib/python3.14/site-packages/deebot_client/authentication.py", line 217, in __do_auth_response
    raise DeviceVerificationRequiredError(json["msg"])
deebot_client.exceptions.DeviceVerificationRequiredError: Please update to the latest version to continue.

@bentbrain

Copy link
Copy Markdown
Contributor Author

Thanks for testing. This traceback shows the new DeviceVerificationRequiredError from this PR being raised as expected. The current Home Assistant config flow does not yet handle that exception or present the email verification step, so installing the library change alone will still produce this error.

The complete flow also requires the companion Home Assistant changes that request and submit the verification code. Could you confirm whether you tested only this library PR, or a custom integration containing both sets of changes?

@Sanji78

Sanji78 commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

I tested only this PR. Can you pls show me what else I should do to make this integration working again ?

@bentbrain

Copy link
Copy Markdown
Contributor Author

The complete Home Assistant flow requires both the library and companion Home Assistant changes.

A community member has packaged both as a temporary custom integration, with installation and removal instructions here:
home-assistant/core#176484 (comment)

Please note that it was built for Home Assistant Core 2026.7.2 and tested with a global email-based Ecovacs account. Make a backup first; China-region and phone-number accounts haven’t been validated yet.

@Sanji78

Sanji78 commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Thanks. I would not like to go with a temporary custom component. If I want to patch the component "ecovacs" to integrate with your PR, what shall I do? Any link or guidance?

@bentbrain

Copy link
Copy Markdown
Contributor Author

This PR only covers the deebot_client library; patching and testing the Home Assistant ecovacs integration is outside its scope. Please continue that discussion in home-assistant/core#176484.

In short, on Home Assistant OS the temporary custom component is the available way to override the bundled integration without building a custom Home Assistant Core image. Otherwise, you’ll need to wait for the companion Home Assistant Core PR.

@32Dexter

32Dexter commented Jul 21, 2026

Copy link
Copy Markdown

I successfully tested this PR with the following setup:

  • Home Assistant Core 2026.7.1 running as a Docker container
  • deebot-client 18.4.0 with the commit from PR Support Ecovacs device verification #1706 applied manually
  • ECOVACS DEEBOT 605 / D600
  • device class dl8fht
  • global email-based account
  • Italy / Europe region

To complete the flow, I applied the changes from this PR, generated a stable 8-character device ID, temporarily modified Home Assistant so that it always reused the same device ID, and completed the email verification using a standalone Python script.

After verification, authentication works correctly across subsequent Home Assistant restarts, and all vacuum entities and commands are available again.

Changing only the reported appVersion did not resolve error 1013. Completing device verification and consistently reusing the same device ID were the key parts of the fix.

During testing, however, I found a second issue. It is probably separate from the authentication change, but it became visible once the integration was able to connect again.

After every Home Assistant startup or Ecovacs integration reload, the DEEBOT is initially detected correctly as DOCKED:

GetChargeState:
<ctl ret='ok'><charge type='SlotCharging'/></ctl>

StateEvent(state=<State.DOCKED: 4>)

Approximately 20 seconds later, the device responds to GetError with:

<ctl ret='ok' errs='100'/>

The library then emits:

StateEvent(state=<State.ERROR: 5>)
ErrorEvent(code=100, description='NoError: Robot is operational')

The vacuum is physically sitting in the docking station, fully charged, and the official ECOVACS app reports no error.

I temporarily changed deebot_client/commands/xml/error.py as follows:

# Before
if error_code != 0:
    event_bus.notify(StateEvent(State.ERROR))

# Tested workaround
if error_code not in (0, 100):
    event_bus.notify(StateEvent(State.ERROR))

After restarting Home Assistant, the vacuum remains correctly in the DOCKED state even though the device continues to return errs='100'.

Timeouts for GetPos, GetChargerPos, GetMapSt, GetMapM, and GetTrM are still logged, probably because the DEEBOT 605 does not support these commands, but they no longer result in the incorrect ERROR state.

I cannot confirm that error code 100 is directly caused by the new authentication flow. It may be a pre-existing issue that only became visible again after authentication was restored. I am reporting it here because it was discovered while validating this PR and it may be worth addressing before the next deebot-client release.

@tgessendorfer

tgessendorfer commented Jul 24, 2026

Copy link
Copy Markdown

I can confirm it works for my Ecovacs Deebot X9 Pro Omni vaccum with the following Homeassistant setup:

  • Installation method: Home Assistant OS
  • Core: 2026.7.3
  • Supervisor: 2026.07.3
  • Operating System: 18.1
  • Frontend: 20260624.6
  • Ecovacs Cloud region: Germany

@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.14%. Comparing base (2a7b432) to head (8a9a38b).
⚠️ Report is 30 commits behind head on dev.

Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #1706      +/-   ##
==========================================
+ Coverage   95.08%   96.14%   +1.06%     
==========================================
  Files         161      161              
  Lines        6301     6385      +84     
  Branches      354      364      +10     
==========================================
+ Hits         5991     6139     +148     
+ Misses        248      180      -68     
- Partials       62       66       +4     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed-hq

codspeed-hq Bot commented Jul 27, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 226 untouched benchmarks


Comparing bentbrain:agent/device-verification (8a9a38b) with dev (4bc625b)

Open in CodSpeed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the Ecovacs authentication flow to handle the new “device verification required” behavior by adding a verification-code workflow (including RSA encryption of the account identifier and signed private API calls) and surfacing explicit errors for common verification failures.

Changes:

  • Add new authentication exceptions for device verification required and invalid verification codes.
  • Implement signed private API calls (getConfig, sendEmailVerifyCode, verifyDevice) and complete the existing token login flow after successful verification.
  • Add tests covering device-verification-required login, requesting a verification code, completing verification + credential caching, and invalid public key handling.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
deebot_client/authentication.py Implements the device verification flow (public key fetch, RSA encrypt, signed calls) and integrates it into authentication.
deebot_client/exceptions.py Adds explicit exception types for verification-required and invalid verification code scenarios.
tests/test_authentication.py Adds unit tests validating the new verification workflow and error handling.
pyproject.toml Adds cryptography dependency required for RSA operations.
uv.lock Locks new transitive dependencies (cryptography, cffi, pycparser).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread deebot_client/authentication.py
Comment thread deebot_client/authentication.py Outdated
Comment thread deebot_client/authentication.py Outdated
Comment thread deebot_client/authentication.py
Comment thread deebot_client/authentication.py Outdated
@edenhaus

Copy link
Copy Markdown
Member

From the PR it looks like that also a core PR is needed. Can you please open that one too (without the dependency bump), so I can review both in one go and understand more which changes are needed

Comment thread deebot_client/authentication.py Outdated
Comment thread deebot_client/authentication.py Outdated
Comment thread deebot_client/authentication.py
Comment thread deebot_client/authentication.py Outdated
@edenhaus edenhaus changed the title fix(auth): support Ecovacs device verification Support Ecovacs device verification Jul 29, 2026
@edenhaus edenhaus added the pr: new-feature PR, which adds a new feature label Jul 30, 2026

@edenhaus edenhaus left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks a lot @bentbrain 👍

@Alessandro9042

Copy link
Copy Markdown

Tested the agent/device-verification branch of deebot_client (18.5.1) together with the corresponding dev version of the ecovacs HA component, backported as a custom_components override on a Home Assistant Supervised install (Debian 12 host).

Result: the device verification step itself works, but the fix does not resolve the integration setup, because Ecovacs' server does not appear to persist the verified state beyond the single login session in which verify_device() succeeded.

Reproduction

With debug logging on deebot_client and custom_components.ecovacs, here's what happens on every reauth attempt:

  1. Config flow starts a fresh Authenticator, calls login(), gets 1013.
  2. request_device_verification_code() succeeds, email arrives, code entered.
  3. verify_device() succeeds — full credentials obtained (accessToken, authCode), loginByItToken succeeds, log shows Login to EcovacsAPI successfully.
  4. The config flow's connectivity check even opens and closes an MQTT connection successfully (CONNACK, "Connection successfully").
  5. Milliseconds later, async_setup_entry creates a brand-new EcovacsController → brand-new Authenticator (per the current architecture, the config-flow authenticator's in-memory credentials aren't handed off to the runtime controller) → calls authenticate() from scratch.
  6. This fresh login attempt, using the same account and the same persisted CONF_DEVICE_ID, immediately gets 1013 again — without even reaching the point of requesting a new verification email.

Log excerpt (redacted):

08:29:19.240 Performing login
08:29:20.855 got {'code': '1013', 'msg': 'Please update to the latest version to continue.', ...}
08:29:20.956 got PUBLIC.KEY.CONFIG ...
08:29:21.006 got {'verifyId': '...'}
08:29:55.943 got {'uid': ..., 'accessToken': ...}   <- verify_device succeeded
08:29:56.102 got {'authCode': ...}
08:29:56.710 Login to EcovacsAPI successfully
08:29:56.948 [mqtt_client] Connection successfully
08:29:56.969 Performing login                        <- new Authenticator, controller.initialize()
08:29:57.032 got {'code': '1013', ...}                <- fails again, immediately
08:29:57.049 ConfigEntryAuthFailed: Device verification required

Same CONF_DEVICE_ID (ikwmcdy2daad351c) in both login attempts — only the resource (session id) differs, which is expected/normal. So this isn't a device-id persistence bug on the HA side; the server itself seems to require verification per login session, not per device, at least on portal-eu.ecouser.net.

Why this matters

The current implementation (both this branch and the dev HA component) assumes verifying a device is a one-time action whose result is remembered by Ecovacs' backend for that device going forward. That assumption doesn't hold in my testing — every fresh Authenticator/login (i.e. every HA restart, every entry reload) re-triggers 1013, which makes the integration unusable for an unattended/headless setup: there's no way to complete an email-code challenge automatically on every restart.

Wondering whether:

  • the runtime controller should reuse/persist the credentials obtained by the config flow's authenticator instead of instantiating a new one and re-authenticating from scratch, and/or
  • there's additional state (e.g. a resource/session identifier) that needs to stay stable across the "verify" call and the subsequent "real" login for the server to recognize it as the same, already-verified session.

Happy to test further or provide more debug logs if useful. Region: EU (portal-eu.ecouser.net), account type: global/email-based.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr: bugfix PR, which fixes a bug pr: new-feature PR, which adds a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Integration Login Failure

7 participants