robovac icon indicating copy to clipboard operation
robovac copied to clipboard

Add support for Eufy X10 Pro Omni

Open RickSisco opened this issue 1 year ago • 156 comments
trafficstars

Are there plans to add support for the X10 Pro Omni vac?

RickSisco avatar Mar 21 '24 06:03 RickSisco

As part of the work I'm doing on the better-dps branch, I'm making it so that devices with different commands can be supported. I'd need people to contribute/test the commands for the vacuums though.

CodeFoodPixels avatar Mar 22 '24 00:03 CodeFoodPixels

Happy to be a tester for my X10 Pro Omni as needed.

russilker avatar Mar 22 '24 03:03 russilker

If step by step instructions are supplied to test the commands, I would be willing to help test on my X10 Pro Omni

On Thu, Mar 21, 2024 at 11:11 PM russilker @.***> wrote:

Happy to be a tester for my X10 Pro Omni as needed.

— Reply to this email directly, view it on GitHub https://github.com/CodeFoodPixels/robovac/issues/68#issuecomment-2014268828, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABYCTSZ4Y3RTYSPTFPQUHXLYZOOMXAVCNFSM6AAAAABFA2MBG2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAMJUGI3DQOBSHA . You are receiving this because you authored the thread.Message ID: @.***>

RickSisco avatar Mar 22 '24 03:03 RickSisco

I am happy to help as well.

damfuu avatar Mar 22 '24 12:03 damfuu

Does that mean there might be some light at the horizon for: https://github.com/CodeFoodPixels/robovac/issues/46 ass well? 😎

RoadXY avatar Mar 22 '24 15:03 RoadXY

Yep, all of these are related to #28

On Fri, 22 Mar 2024, 15:08 Robin van Kekem, @.***> wrote:

Does that mean there might be some light at the horizon for: #46 https://github.com/CodeFoodPixels/robovac/issues/46 ass well? 😎

— Reply to this email directly, view it on GitHub https://github.com/CodeFoodPixels/robovac/issues/68#issuecomment-2015305298, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABEPFVAGWZHQUAFZGC4ZUDLYZRCQJAVCNFSM6AAAAABFA2MBG2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAMJVGMYDKMRZHA . You are receiving this because you commented.Message ID: @.***>

CodeFoodPixels avatar Mar 22 '24 16:03 CodeFoodPixels

Count me in as a tester for the #46 issue

daschick111 avatar Mar 24 '24 19:03 daschick111

Happy to help here as well.

gmagnus1 avatar Mar 27 '24 16:03 gmagnus1

Hello, I've been doing some work with my X10 to try and figure out where the setup process stalls. So far, I've noticed a couple of things:

First, the Eufy API endpoint to list devices seems to have changed. When hitting api/v1/device/list/devices-and-groups, I don't see anything in the items array.

{
  "res_code": 1,
  "message": "",
  "items": [],
  "global_config": {
    "enabled_multi_color_modes": [
      0,
      1,
      2,
      3
    ]
  }
}

I was able to MITM the traffic from the Eufy Clean app, though, and it looks like it instead makes a request to /api/v1/device/v2, which actually gives the device info:

{
  "res_code": 1,
  "message": "",
  "devices": [
    {
      "id": "<snipped>",
      "sn": "",
      "name": "X10 Pro Omni",
      "alias_name": "Dustin",
      "bluetooth": null,
      "wifi": {
        "mac": "<snipped>",
        "wifi_ssid": "",
        "lan_ip_addr": ""
      },
      "product": {
        "id": "<uuid>",
        "name": "X10 Pro Omni",
        "region": "[{\"regions\":[\"ALL\"],\"date\":\"2022-09-01 20:22:49\"}]",
        "default_name": "RoboVac",
        "icon_url": "https://d1teb1w17vl5yo.cloudfront.net/eufyhome/products/T2182_addProduct.png",
        "category": "Home",
        "appliance": "Cleaning",
        "connect_type": 2,
        "description": "T2182 eufy RoboVac L80, connected via EufyHome",
        "product_code": "T2351",
        "wifi_ssid_prefix": "eufy Clean X10 Pro Omni",
        "wifi_ssid_prefix_full": "eufy Clean X10 Pro Omni-",
        "index": 1,
        "create_time": 1640585895,
        "update_time": 1707192290,
        "is_show": false,
        "tuya_pid": "<id>",
        "app_ble_ssid_prefix": "eufy Clean X10 Pro Omni-",
        "device_ble_ssid_prefix": "eufy Clean X10 Omni-",
        "wifi_ssid_prefix_list": [
          "eufy Clean X10 Omni-",
          "eufy Clean X10 Pro Omni-"
        ],
        "device_ble_ssid_prefix_list": [
          "eufy Clean X10 Omni-",
          "eufy Clean X10 Pro Omni-"
        ]
      },
      "user_id": "<uuid>",
      "owner_info": null,
      "home_id": "<uuid>",
      "home_name": "",
      "room_id": "<uuid>",
      "room_name": "Default Room",
      "connect_type": 2,
      "grant_by": 0,
      "software_version": "",
      "index": 0,
      "device_key": "",
      "create_time": 1711493109,
      "update_time": 1711493549,
      "hardware_version": "",
      "scale_type": "",
      "local_code": "",
      "needUpdate": false,
      "setting": {
        "id": "",
        "device_id": "",
        "is_default": true
      },
      "update_packages": []
    }
  ],
  "groups": []
}

Next, I connected to the Tuya API and tried to retrieve the device with:

tuya.get_device("<device id>")

with both devices[0]['id'] and devices[0]['product']['id']

but I've only gotten back

{'t': 1711599563374, 'success': False, 'errorCode': 'PERMISSION_DENIED', 'status': 'error', 'errorMsg': 'PERMISSION_DENIED'}

and I'm not sure what to do from here. It looks like the response from Tuya is pretty generic, so I possibly messed up something about the parameters.

This is the code that I've been playing around with, for reference:

import requests

from tuyawebapi import TuyaAPISession

login = requests.post(
    "https://home-api.eufylife.com/v1/user/email/login",
    json={
        "client_id": "eufyhome-app",
        "client_secret": "GQCpr9dSp3uQpsOMgJ4xQ",
        "email": "<snipped>",
        "password": "<snipped>",
    },
)
login.raise_for_status()
login_data = login.json()

access_token = login_data["access_token"]
refresh_token = login_data["refresh_token"]
base = login_data["user_info"]["request_host"]

phone_code = login_data["user_info"]["phone_code"]
country = login_data["user_info"]["country"]
timezone = login_data["user_info"]["timezone"]
user_id = login_data["user_info"]["id"]

session = requests.Session()
session.headers["token"] = access_token

devices = session.get(f"{base}/v1/device/v2", headers={"category": "Home"})
devices.raise_for_status()
devices_data = devices.json()

tuya = TuyaAPISession(
    username=f"eh-{user_id}",
    region="AZ",
    timezone=timezone,
    phone_code=phone_code,
)

I also port-scanned the vacuum, in case that's helpful, but didn't find any of the known local Tuya ports to be open:

Nmap scan report for <snipped>
Host is up (0.010s latency).
Not shown: 1000 closed tcp ports (conn-refused)
PORT     STATE SERVICE
9668/tcp open  tec5-sdctp

Nmap done: 1 IP address (1 host up) scanned in 2.08 seconds

Unfortunately I wasn't able to glean that much other useful information from the app either. Starting a cleaning cycle triggers a bunch of requests to log.eufylife.com/push_log_hdfs and log.eufylife.com/push_log_es but nothing that is obviously the start signal. I'm happy to share more details about the flows. Note that I was only snooping on HTTP traffic, though, so if the app communicated locally with the vacuum over something else, I wouldn't have seen it.

terabyte128 avatar Mar 28 '24 04:03 terabyte128

That's some amazing work @terabyte128! Looks like the eufy endpoint you found works for older devices too, so I'm going to switch over to using that.

CodeFoodPixels avatar Mar 28 '24 23:03 CodeFoodPixels

Thanks! I also noticed that the vacuum is sending out broadcast UDP packets to port 9667 (not 6666/6667), so that may also be part of the puzzle. Unfortunately I'm not sure how to decrypt them. image (I doubt there's anything personal in the payload, but I'm gonna avoid posting it publicly – if you want it, let me know.)

terabyte128 avatar Mar 28 '24 23:03 terabyte128

Great work Sam. Look forward to seeing the progress Luke. :)

On Thu, Mar 28, 2024 at 7:08 PM Sam Wolfson @.***> wrote:

Thanks! I also noticed that the vacuum is sending out broadcast UDP packets from port 9667 (not 6666/6667), so that may also be part of the puzzle. Unfortunately I'm not sure how to decrypt them.

image.png (view on web) https://github.com/CodeFoodPixels/robovac/assets/1189703/d571e910-cb67-4ae5-b4fe-9a050c496620

(I doubt there's anything personal in the payload, but I'm gonna avoid posting it publicly – if you want it, let me know.)

— Reply to this email directly, view it on GitHub https://github.com/CodeFoodPixels/robovac/issues/68#issuecomment-2026292287, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABYCTS5ZHRNAFOCU4UOF74DY2SPGDAVCNFSM6AAAAABFA2MBG2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAMRWGI4TEMRYG4 . You are receiving this because you authored the thread.Message ID: @.***>

RickSisco avatar Mar 28 '24 23:03 RickSisco

@CodeFoodPixels do you know how the username eh-{user_id} was deduced? (from here). I think there might be something wrong with how I'm using the Tuya API.

Entering a random ID and calling list_homes() gives more or less the same answer as when I use my real ID, though, so it's hard to tell if my login is correct or not.

For example:

tuya = TuyaAPISession(
    username=f"FAKEUSERID"
    region="AZ",
    timezone=timezone,
    phone_code=phone_code,
)

gives the response:

[{'geoName': '', 'rooms': [], 'gmtModified': 1711668412, 'role': 2, 'gid': 192829708, 'groupId': 192829708, 'displayOrder': 1, 'admin': True, 'dealStatus': 2, 'gmtCreate': 1711668412, 'ownerId': '192829708', 'uid': 'az1711668412228EOl6W', 'groupUserId': 157327173, 'background': '', 'name': 'My Home', 'id': 147452158, 'status': True}]

and making the same request with eh-{user_id} gives the exact same response shape, just with different IDs etc.

terabyte128 avatar Mar 28 '24 23:03 terabyte128

Thanks! I also noticed that the vacuum is sending out broadcast UDP packets to port 9667 (not 6666/6667), so that may also be part of the puzzle.

Good spot! Doing a quick search through a decompiled version of the eufy app, 9667 and 9668 seem to be used in place of 6667 and 6668.

@CodeFoodPixels do you know how the username eh-{user_id} was deduced?

It was deduced before I had anything to do with this, but again, looking at the app code, it's right. Did you use an actual ID or literally FAKEUSERID?

CodeFoodPixels avatar Mar 28 '24 23:03 CodeFoodPixels

I literally

It was deduced before I had anything to do with this, but again, looking at the app code, it's right. Did you use an actual ID or literally FAKEUSERID?

I literally used FAKEUSERID, lol. Maybe that's a way for them to defend against attackers trying to enumerate valid user IDs? Especially since they don't seem to require any sort of client secret.

terabyte128 avatar Mar 28 '24 23:03 terabyte128

I didn't notice any requests from the app going directly to Tuya servers, but I wasn't specifically looking for that – I'll take another look.

terabyte128 avatar Mar 28 '24 23:03 terabyte128

I think the contact with the tuya servers is mainly to get keys etc, possibly also when you're not on the same network as the vacuum.

CodeFoodPixels avatar Mar 29 '24 00:03 CodeFoodPixels

@terabyte128 If you want some code to play around with, you can use this as a base: https://github.com/CodeFoodPixels/robovac-schema

CodeFoodPixels avatar Mar 29 '24 00:03 CodeFoodPixels

I see, I wonder if it only contacts the Tuya server for local keys on initial setup. Getting them on different LANs is a good tip. Thanks for the link – I’ll poke at it more this weekend!

terabyte128 avatar Mar 29 '24 14:03 terabyte128

I was able to capture some more information! I found that the app was making requests to /api.json, but on a different server than was encoded in tuyawebapi.py – in my case, https://a1-us.iotbing.com/api.json. Not sure if that makes a difference.

Perhaps more importantly, this is what the request format looks like:

Host:             a1-us.iotbing.com
Content-Type:     application/x-www-form-urlencoded
User-Agent:       EufyHome/20 CFNetwork/1474 Darwin/23.0.0
Connection:       keep-alive
Accept:           */*
Accept-Language:  en-US,en;q=0.9
Content-Length:   1555
Accept-Encoding:  gzip, deflate, br
Cache-Control:    no-cache
==== FORM DATA ===
lang:              en
bizData:           {"nd":1,"customDomainSupport":"1"}
deviceId:          83C29192-633C-4829-8CC0-CB30B65E6167
et:                0.0.2
osSystem:          17.0
bundleId:          com.eufylife.EufyHome
time:              1711840368
lon:               0
channel:           sdk
nd:                1
appVersion:        3.1.0
ttid:              appstore_d
os:                IOS
v:                 1.0
sid:               <snipped>
sign:              <snipped>
platform:          iPhone 11 Pro
postData:          USQUo1wT3zC1Mggnw4Dq8GiAp+pAFKpnkC1Bfiz53pphbXbtpMH2two1Bt/d9foJlYJXqxCUBe23WxRQy2w56kfAXQ18GEWFRK+u5TSULsgRJRW6q1ZOYkKBAU4Is++NMseQ2kMUXr/T3f+UvA4JeD+6xcoTqwrkd3zOa7Sbw878YMxkYklrFaaKOvK8lB+KL2h
zkOx/5rG34U8DQBwMv+aoVlMCZldQVNtd+5ahJhBweBIQ9gLZZkX90JarFy4F6dt4a+R3jwsZcv7L61ly3gJhopchbtzlWv0ETtx5F0NAN2MclLuyMvfoke4vR2XlihNzvdbZfVqEpzhvvMqDw2LFwVXy1Pfw8SHVRzuQCixxmI4lNJx/Jz3Ay++XKMQFTGPumbU7ryn4N+3ptsxGMIN/7
UP5WS3P5NQL50XvrjPsowkPAuMiCwnGw/Hfj29uIi2IobRL8MBspo6iM6pNCNZjexCFDJB4BkS4Vxk8YbqfIbCMmuHQJHoIE/qmico5q3684aVhNnI+fR/nRVRExHCkvl33+mpK8pSqVTRTyficFrpnHBbLnC1HdBpniayunxI5XNHjLfW3Pooj5Vp6DXE1t6pvuxqBmqpftQfQyFpKjwL
UAX2xccHevYnEMInLPxWuThci6yvQdU5yJEZOssfHpUpLnzDIcLTB8i5jc6PxZAnyi/FJPAiH5SUEhr0poIr0U4QCHS5AakCsNtz2p7bcwkrDQ9BwzMX7RoyxJKjDhc6nCyj9B3Pk6vXOyzx3WjEka0fSGfRRP+VlUY2z2sK2hRdF3ge6WH9IgesVmBokh2XQGggBGuSwab37PmgR6Iava
9rfU6bWO8qQX4kJGw==
uid:               az1711493114821bjS7C
sdkVersion:        4.3.0
timeZoneId:        America/Los_Angeles
requestId:         <snipped>
lat:               0
gid:               192606234
clientId:          <snipped>
deviceCoreVersion: 5.3.0
a:                 smartlife.m.api.batch.invoke
cp:                gzip

The most interesting thing here is that postData appears to be encrypted, which is different than what tuyawebapi.py does. (Simply base64-decoding it doesn't produce anything readable.) Looking at this link supports this idea as well, and it also offers a function that can apparently perform the encryption.

That's as far as I've gotten for now. I haven't looked into how to obtain tuya_bmpkey or tuya_appsecret.

terabyte128 avatar Mar 31 '24 00:03 terabyte128

I have another progress update. Long story short, from what I can tell it appears that the Eufy Clean app doesn't communicate directly with the vacuum at all. Instead, it sends all commands through a Eufy MQTT server (in my case, aiot-mqtt-us.anker.com:8883). The MQTT server uses TLS.

  • The username for the MQTT server appears to be {user id}-eufy_home, with no password.
  • The topic in my case is cmd/eufy_home/T2351/{vacuum ID}/req (not sure what T2351 represents)
  • The commands themselves look like:
{
    "head": {
        "client_id": "android-eufy_home-{user id}-eufy_android_Android SDK built for arm64_{some random hex digits, maybe a version number?}",
        "cmd": 65537,
        "cmd_status": 2,
        "msg_seq": 1,
        "seed": "",
        "sess_id": "android-eufy_home-{user id}-eufy_android_Android SDK built for arm64_{same hex digits as above}",
        "sign_code": 0,
        "timestamp": 1712295579241,
        "version": "1.0.0.1"
    },
    "payload": "{\"account_id\":\"{account id}\",\"data\":{\"153\":\"BwjpnJTm6jE\\u003d\"},\"device_sn\":\"{vacuum id}\",\"protocol\":2,\"t\":1712295579241}"
}

payload['data'] appears to be base64-encoded, and happily, not encrypted. The bytes seem to correspond exactly to the action performed, and don't change. For example (first digit is the key in the data dict):

154 16,10,14,10,2,8,2,26,0,34,2,8,1,42,2,8,1  # turn on 'auto' mode
154 14,10,12,10,2,8,2,26,0,34,2,8,1,42,0  # turn off 'auto' mode

Unfortunately I haven't been able to send out commands on my own yet. I suspect there might be another piece of auth that I'm missing before I can publish commands to the topic, and/or it might want a client certificate.

terabyte128 avatar Apr 05 '24 05:04 terabyte128

Thanks for the update. Glad to see you finding progress.

On Fri, Apr 5, 2024 at 1:45 AM Sam Wolfson @.***> wrote:

I have another progress update. Long story short, from what I can tell it appears that the Eufy Clean app doesn't communicate directly with the vacuum at all. Instead, it sends all commands through a Eufy MQTT server (in my case, aiot-mqtt-us.anker.com:8883). The MQTT server uses TLS.

  • The username for the MQTT server appears to be {user id}-eufy_home, with no password.
  • The topic in my case is cmd/eufy_home/T2351/{vacuum ID}/req (not sure what T2351 represents)
  • The commands themselves look like:

{ "head": { "client_id": "android-eufy_home-{user id}-eufy_android_Android SDK built for arm64_{some random hex digits, maybe a version number?}", "cmd": 65537, "cmd_status": 2, "msg_seq": 1, "seed": "", "sess_id": "android-eufy_home-{user id}-eufy_android_Android SDK built for arm64_{same hex digits as above}", "sign_code": 0, "timestamp": 1712295579241, "version": "1.0.0.1" }, "payload": "{"account_id":"{account id}","data":{"153":"BwjpnJTm6jE\u003d"},"device_sn":"{vacuum id}","protocol":2,"t":1712295579241}" }

payload['data'] appears to be base64-encoded, and happily, not encrypted. The bytes seem to correspond exactly to the action performed, and don't change. For example (first digit is the key in the data dict):

154 16,10,14,10,2,8,2,26,0,34,2,8,1,42,2,8,1 # turn on 'auto' mode 154 14,10,12,10,2,8,2,26,0,34,2,8,1,42,0 # turn off 'auto' mode

Unfortunately I haven't been able to send out commands on my own yet. I suspect there might be another piece of auth that I'm missing before I can publish commands to the topic, and/or it might want a client certificate.

— Reply to this email directly, view it on GitHub https://github.com/CodeFoodPixels/robovac/issues/68#issuecomment-2038993537, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABYCTS3Y7ISHWKZJZUPUJA3Y3Y3A7AVCNFSM6AAAAABFA2MBG2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAMZYHE4TGNJTG4 . You are receiving this because you authored the thread.Message ID: @.***>

RickSisco avatar Apr 05 '24 06:04 RickSisco

T2351 is the model number of your vacuum. T2351 = X10 Pro omni

https://support.eufy.com/s/article/T2351-EU-DOC

RoadXY avatar Apr 08 '24 16:04 RoadXY

I was able to connect to the MQTT server and inspect all the messages sent to the relevant topics. I could also publish on the topics and cause the vacuum to perform actions. The MQTT topics are:

  • cmd/eufy_home/T2351/{VACUUM_SERIAL}/req: requests send from the app to the vacuum
  • cmd/eufy_home/T2351/{VACUUM_SERIAL}/res responses from the vacuum

Below is the snippet that I used. The important pieces are:

  • The MQTT user is {USER_ID}-eufy_home
  • You can only subscribe to the topics namespaced under cmd/eufy_home/T2351/{VACUUM_SERIAL}
  • The MQTT server does require the client to present a certificate. I got it by instrumenting the Android Eufy Clean app. I'm not sure I should post the private key here, but you can pretty easily get it yourself. Here's the Frida snippet I used:
Java.perform(function () {
  let MqttConnectionNew = Java.use("com.anker.aiot_sdk.mqtt.MqttConnectionNew");
  MqttConnectionNew["s"].implementation = function (domainMqttBean) {
    console.log(
      `MqttConnectionNew.s is called: domainMqttBean=${domainMqttBean}`,
    );
    let result = this["s"](domainMqttBean);
    console.log(`MqttConnectionNew.s result=${result}`);
    return result;
  };
});

and the code I wrote to connect to the MQTT server:

import json
from base64 import b64decode

import paho.mqtt.client as mqtt
from paho.mqtt.enums import CallbackAPIVersion

# the following can be retrieved using existing scripts against Eufy's API
USER_ID = "<snipped>"
VACUUM_SERIAL = "<snipped>"

client = mqtt.Client(
    CallbackAPIVersion.VERSION2,
    client_id=(
        f"android-eufy_home-{USER_ID}-eufy_android_Android"
        f" SDK built for arm64_{USER_ID}"
    ),
)
client.tls_set(
    certfile="./certs/certificate.pem",
    keyfile="./certs/private_key.pem",
)


def print_bytes(bs: bytes):
    ret = ""
    for b in bs:
        formatted = f"{b:02x} "
        ret += formatted

    return ret


def on_message(client: mqtt.Client, userdata, message: mqtt.MQTTMessage):
    topic = message.topic
    payload = json.loads(message.payload)

    if isinstance(payload["payload"], str):
        payload["payload"] = json.loads(payload["payload"])

    if "res" in topic:
        return  # comment this if you also want the vacuum's responses printed out
        print("<-- ", end="")
    else:
        print("--> ", end="")

    for k, v in payload["payload"]["data"].items():
        try:
            decoded = b64decode(v)
            print(f"{k}: {print_bytes(decoded)}")
            print(v)
        except:
            print(f"failed to decode {k}: {v}")

    # print(topic)
    # print(json.dumps(payload, indent=4))


client.on_message = on_message
client.username = f"{USER_ID}-eufy_home"
client.connect("aiot-mqtt-us.anker.com", 8883)

client.subscribe(f"cmd/eufy_home/T2351/{VACUUM_SERIAL}/#")

client.loop_forever()

The Python snippet just prints out the payloads of each message. Next step is figuring out what they actually mean. It seems like most payloads carry the entire configuration of the vaccum's "mode", but since they're variable length, it's difficult to grok what bytes mean what. Here are some examples:

--> 154: 10 0a 0e 0a 02 08 02 1a 00 22 02 08 01 2a 02 08 01  # smart mode on
--> 154: 0e 0a 0c 0a 02 08 02 1a 00 22 02 08 01 2a 00  # smart mode off
--> 154: 10 0a 0e 0a 02 08 02 1a 02 08 02 22 02 08 01 2a 00 # fast, vacuum+mop, standard suction, medium water level

terabyte128 avatar Apr 09 '24 05:04 terabyte128

Eufy appears to be using some obscenely complicated protocol to generate the "set mode" payloads (seems like they're using an AST to build up the message like programming language syntax...why???) so rather than try and wade through all the code, I just brute-forced it. Below is the file that corresponds to the base64-encoded messages associated with each mode-tuple. Every "mode" message appears to be in the format of:

{
    "154": "<mode code>"
}

codes.csv

terabyte128 avatar Apr 12 '24 03:04 terabyte128

In a nicer format: https://gist.github.com/terabyte128/0598dcb735ec73842dfc5d204d968320

terabyte128 avatar Apr 12 '24 03:04 terabyte128

Are they encoded as protobufs? That was the case for another device: https://github.com/CodeFoodPixels/robovac/issues/40#issuecomment-2027798578

CodeFoodPixels avatar Apr 12 '24 07:04 CodeFoodPixels

Hmm, could be, I'll dig into that.

terabyte128 avatar Apr 12 '24 18:04 terabyte128

Has anyone got this working with their x10 pro? I just got my new hoover yesterday and cannot get it work.

samonthenetuk avatar Apr 19 '24 05:04 samonthenetuk

Home assistant Integration for the Eufy x10 is still in progress, but if you only want to start a cleaning cycle with a Lovelace card or automation, you can integrate your x10 with the Eufy skill in Alexa and create a cleaning routine in Alexa as well. In home assistant you can use the Alexa media player integration to start your routine. Here is my example:

service: media_player.play_media target: entity_id: media_player.echo_im_bad data: media_content_id: staubsaugen media_content_type: routine metadata: {}

apeschel780 avatar Apr 19 '24 10:04 apeschel780