PiotrMachowski / Home-Assistant-custom-components-Xiaomi-Cloud-Map-Extractor

This custom integration provides a way to present a live view of a map for Xiaomi (Roborock/Viomi/Roidmi/Dreame) vacuums without a need for rooting.
MIT License
1.16k stars 123 forks source link

Map Extractor don't work for dreame.vacuum.p2114o #316

Closed hvbird closed 1 year ago

hvbird commented 2 years ago

Checklist

The problem

I installed Home-Assistant-custom-components-Xiaomi-Cloud-Map-Extractor but it's not working, my vacuum is dreame.vacuum.p2114o, does this mean that it's not supported yet?

map_data_dreame.vacuum.p2114o.b64.zip

What version of am integration has described problem?

v2.2.0

What was the last working version of an integration?

No response

What vacuum model do you have problems with?

dreame.vacuum.p2114o

What version of Home Assistant do you use?

2022.6.7

What type of installation are you running?

Home Assistant Core

Camera's configuration

camera:
  - platform: xiaomi_cloud_map_extractor
    host: !secret xiaomi_vacuum_host
    token: !secret xiaomi_vacuum_token
    username: !secret xiaomi_cloud_username
    password: !secret xiaomi_cloud_password
    name: "xiaomi Vacuum Camera"
    draw: ['all']
    attributes:
      - calibration_points

Errors shown in the HA logs (if applicable)

Traceback (most recent call last):
  File "/data/ym/git/opensource/homeassistant/lib/python3.9/site-packages/homeassistant/helpers/entity.py", line 515, in async_update_ha_state
    await self.async_device_update()
  File "/data/ym/git/opensource/homeassistant/lib/python3.9/site-packages/homeassistant/helpers/entity.py", line 743, in async_device_update
    raise exc
  File "/usr/local/lib/python3.9/concurrent/futures/thread.py", line 52, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/yang/.homeassistant/custom_components/xiaomi_cloud_map_extractor/camera.py", line 278, in update
    self._handle_map_data(map_name)
  File "/home/yang/.homeassistant/custom_components/xiaomi_cloud_map_extractor/camera.py", line 335, in _handle_map_data
    map_data, map_stored = self._device.get_map(map_name, self._colors, self._drawables, self._texts,
  File "/home/yang/.homeassistant/custom_components/xiaomi_cloud_map_extractor/common/vacuum.py", line 36, in get_map
    map_data = self.decode_map(response, colors, drawables, texts, sizes, image_config)
  File "/home/yang/.homeassistant/custom_components/xiaomi_cloud_map_extractor/dreame/vacuum.py", line 24, in decode_map
    return MapDataParserDreame.decode_map(raw_map_string, colors, drawables, texts, sizes, image_config)
  File "/home/yang/.homeassistant/custom_components/xiaomi_cloud_map_extractor/dreame/map_data_parser.py", line 51, in decode_map
    unzipped = zlib.decompress(base64.decodebytes(raw_map_string.encode("utf8")))
zlib.error: Error -3 while decompressing data: incorrect header check

Additional information

No response

PiotrMachowski commented 2 years ago

Can you try if any of these work? force_api: roidmi or force_api: viomi

hvbird commented 2 years ago

Can you try if any of these work? force_api: roidmi or force_api: viomi

I've tried all the apis but none of them work...

miquelrosell99 commented 2 years ago

I am having the exact same problem. Is there any way to get the map to show up? image

Mantoui commented 2 years ago

me too

DediCATeD88 commented 2 years ago

same here for dreame.vacuum.p2114a (Xiaomi Robot Vacuum X10+, Europe / German Version)

Tasshack commented 2 years ago

@PiotrMachowski i found out that these devices are using encrypted map data and aes key can be acquired from map_request action object_name response property.

Request: [{'piid': 2, 'value': '{"req_type":1,"frame_type":"I","force_type":1}'}] Response: [{'piid': 1, 'value': ''}, {'piid': 3, 'value': '1653707108/1034063228/0,f4LEmacnepfZGvaF'}, {'piid': 5, 'value': 1665910878849}]

object_name: 1653707108/1034063228/0 key: f4LEmacnepfZGvaF

App uses standard AES decrypt method with constant IV and decodes the decrypted map data exactly same with the other robots.

PiotrMachowski commented 2 years ago

Thanks @Tasshack!

ThemeIT commented 1 year ago

Any update on this? Couldnt figure out the encryption.

phit666 commented 1 year ago

@PiotrMachowski i found out that these devices are using encrypted map data and aes key can be acquired from map_request action object_name response property.

Request: [{'piid': 2, 'value': '{"req_type":1,"frame_type":"I","force_type":1}'}] Response: [{'piid': 1, 'value': ''}, {'piid': 3, 'value': '1653707108/1034063228/0,f4LEmacnepfZGvaF'}, {'piid': 5, 'value': 1665910878849}]

object_name: 1653707108/1034063228/0 key: f4LEmacnepfZGvaF

App uses standard AES decrypt method with constant IV and decodes the decrypted map data exactly same with the other robots.

In object_name given above, the key f4LEmacnepfZGvaF correspond specifically to map id 0 so before fetching the raw map get this map id first. Now if object_name has no value, send another request including the robot time stamp fetched from the initial request, it is 1665910878849 in the given above.

Request with time stamp [{'piid': 2, 'value': '{"req_type":1,"frame_type":"I","force_type":1,"time":1665910878849}'}]

Now to decrypt (dreame.vacuum.p2140p model)

_raw_map = base64.decodebytes(raw_map_string.encode("utf8"))

_iv = json.loads(zlib.decompress(base64.b64decode("H4sICGt+oGMEAGRldmljZWtleS50eHQAbc67DoIwAIXhd+nsQG8obhaDKFChEg0jBEGJgSIGgsZ3lwbcmL+c/OcDJIKQVGANdN+6u37k2W7/kEshwEIZMZQJfiQS0wQFTly1tjmZpmxVlycjrfMQm1LurvBvctbGXjzfeyKkGQPVlnNrq00trNDPHK6PRMlAneg1mkVucPCErXvFSFBXT0hjtjhA7JVczmzP0GiYDsRFV7KCWg33c8aTcJpBNUvLVAT4vdqYxTbdehX4/gAN9AoFFgEAAA=="), zlib.MAX_WBITS | 32)).get("p2140p")
_key = hashlib.sha256(enckey.encode()).hexdigest()[0:32].encode('utf8') iv = _iv.encode('utf8') cipher = Cipher(algorithms.AES(_key), modes.CBC(iv), backend=default_backend()) decryptor = cipher.decryptor() raw_map_dec = decryptor.update(_raw_map) + decryptor.finalize()

unzipped = zlib.decompress(raw_map_dec)

michal-tadeusiak-by commented 1 year ago

@PiotrMachowski i found out that these devices are using encrypted map data and aes key can be acquired from map_request action object_name response property. Request: [{'piid': 2, 'value': '{"req_type":1,"frame_type":"I","force_type":1}'}] Response: [{'piid': 1, 'value': ''}, {'piid': 3, 'value': '1653707108/1034063228/0,f4LEmacnepfZGvaF'}, {'piid': 5, 'value': 1665910878849}] object_name: 1653707108/1034063228/0 key: f4LEmacnepfZGvaF App uses standard AES decrypt method with constant IV and decodes the decrypted map data exactly same with the other robots.

In object_name given above, the key f4LEmacnepfZGvaF correspond specifically to map id 0 so before fetching the raw map get this map id first. Now if object_name has no value, send another request including the robot time stamp fetched from the initial request, it is 1665910878849 in the given above.

Request with time stamp [{'piid': 2, 'value': '{"req_type":1,"frame_type":"I","force_type":1,"time":1665910878849}'}]

Now to decrypt (dreame.vacuum.p2140p model)

_raw_map = base64.decodebytes(raw_map_string.encode("utf8"))

_iv = json.loads(zlib.decompress(base64.b64decode("H4sICGt+oGMEAGRldmljZWtleS50eHQAbc67DoIwAIXhd+nsQG8obhaDKFChEg0jBEGJgSIGgsZ3lwbcmL+c/OcDJIKQVGANdN+6u37k2W7/kEshwEIZMZQJfiQS0wQFTly1tjmZpmxVlycjrfMQm1LurvBvctbGXjzfeyKkGQPVlnNrq00trNDPHK6PRMlAneg1mkVucPCErXvFSFBXT0hjtjhA7JVczmzP0GiYDsRFV7KCWg33c8aTcJpBNUvLVAT4vdqYxTbdehX4/gAN9AoFFgEAAA=="), zlib.MAX_WBITS | 32)).get("p2140p") _key = hashlib.sha256(enckey.encode()).hexdigest()[0:32].encode('utf8') iv = _iv.encode('utf8') cipher = Cipher(algorithms.AES(_key), modes.CBC(iv), backend=default_backend()) decryptor = cipher.decryptor() raw_map_dec = decryptor.update(_raw_map) + decryptor.finalize()

unzipped = zlib.decompress(raw_map_dec)

Hi, could you give us a hint on requesting the key? How and where are you sending the request, to the vacuum, xiaomi cloud or a function is hidden somewhere in this package and i don't see it. Any help would be appreciated, thanks :)

PiotrMachowski commented 1 year ago

At this point I think it would be easier to use dreame-vacuum instead

michal-tadeusiak-by commented 1 year ago

At this point I think it would be easier to use dreame-vacuum instead

Thanks, somehow I didn't stumble on this repository. I'll give it a try, but I don't see my model on the supported list, so I'll have to see how it goes.

michal-tadeusiak-by commented 1 year ago

Unfortunately dreamy-vacuum integration does not work for my p2140p, so my only option is to retrive this key and modify map_parser :/ Any help with retriving the key would be appreciated.

Tasshack commented 1 year ago

@michal-tadeusiak-by VSLAM robots are not supported yet but will be on the next release. You can follow the related issue about this https://github.com/Tasshack/dreame-vacuum/issues/12. I can give you the private key but i don't think you will be able to add map decryption feature to this project.

phit666 commented 1 year ago

Unfortunately dreamy-vacuum integration does not work for my p2140p, so my only option is to retrive this key and modify map_parser :/ Any help with retriving the key would be appreciated.

xiaomi_cloud_map_extractor.zip

This is my hardcoded patch from the latest version v.2.2.0.

btw I also hardcoded the country (sg) in get_otherinfo function from xiaomi_cloud_connectior.py so update it accordingly :)

for those who wanted to access Home Assistant online try this https://github.com/phit666/tunnel-proxy, sorry for hijacking this thread.

lfdominguez commented 1 year ago

Unfortunately dreamy-vacuum integration does not work for my p2140p, so my only option is to retrive this key and modify map_parser :/ Any help with retriving the key would be appreciated.

xiaomi_cloud_map_extractor.zip

This is my hardcoded patch from the latest version v.2.2.0.

btw I also hardcoded the country (sg) in get_otherinfo function from xiaomi_cloud_connectior.py so update it accordingly :)

for those who wanted to access Home Assistant online try this https://github.com/phit666/tunnel-proxy, sorry for hijacking this thread.

Working perfect with my p2140o model, only changing to that model on your patch.

MarioKuester commented 1 year ago

Unfortunately dreamy-vacuum integration does not work for my p2140p, so my only option is to retrive this key and modify map_parser :/ Any help with retriving the key would be appreciated.

xiaomi_cloud_map_extractor.zip This is my hardcoded patch from the latest version v.2.2.0. btw I also hardcoded the country (sg) in get_otherinfo function from xiaomi_cloud_connectior.py so update it accordingly :) for those who wanted to access Home Assistant online try this https://github.com/phit666/tunnel-proxy, sorry for hijacking this thread.

Working perfect with my p2140o model, only changing to that model on your patch.

Tried this on my dreame.vacuum.p2114a (Xiaomi X10+) but without success.

PiotrMachowski commented 1 year ago

Moving the discussion to an issue for all affected vacuums: #459