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.14k stars 121 forks source link

Introduce mop path #356

Closed rospogrigio closed 1 year ago

rospogrigio commented 1 year ago

Introducing the drawing of mop path, for vacuums that support this info. Path width and color is configurable.

Here you can compare how it is displayed in the Mi Home app:

MI Home

... and in HA:

hass

PiotrMachowski commented 1 year ago

Can you also resolve conflicts?

rospogrigio commented 1 year ago

Done, and also updated the README. Let me know what you think of this... thank you for all your work 👍

rospogrigio commented 1 year ago

Gosh, after I have merged from dev I keep getting the error "Invalid calibration, please check your configuration" in the xiaomi map card, and in the JS console I see "xiaomi-vacuum-map-card.js:1052 Only one calibration source allowed". Can you suggest what I could check @PiotrMachowski ? Thank you.

PiotrMachowski commented 1 year ago

Can you show your config?

rospogrigio commented 1 year ago

Are you meaning the card config? Here it is, I am keeping the relevant part:

entity: vacuum.roborock_s7
preset_name: Live Map
map_source:
  camera: camera.roborock_live_map
  crop:
    top: 0
    bottom: 0
    left: 0
    right: 0
calibration_source:
  camera: true
debug: false
default_mode: predefined_zones
tiles:
  - label: Status
    entity: vacuum.roborock_s7_miot
    attribute: vacuum.status_desc
    icon: mdi:robot-vacuum
  - label: Battery
    entity: vacuum.roborock_s7_miot
    attribute: battery_level
    icon: mdi:battery-charging-100
    unit: '%'
  - label: Fan Speed
    icon: mdi:fan
    entity: vacuum.roborock_s7_miot
    attribute: fan_speed
type: custom:xiaomi-vacuum-map-card
map_modes:
  - template: vacuum_clean_segment
    predefined_selections:
      - id: 18
        outline:
          - - 31980
            - 29000
          - - 31980
            - 23750
          - - 27280
            - 23750
          - - 26000
            - 25000
          - - 26000
            - 29000
        label:
          text: Soggiorno
          x: 29030
          'y': 25500
          offset_y: 30
        icon:
          name: mdi:sofa
          x: 29030
          'y': 25500
  - template: vacuum_clean_zone_predefined
    predefined_selections:
      - label:
          text: Tavolino
          x: 29280
          'y': 26350
          offset_y: 30
        icon:
          name: mdi:table-furniture
          x: 29280
          'y': 26350
        zones:
          - - 30280
            - 28000
            - 28280
            - 25000
  - template: vacuum_clean_zone
  - template: vacuum_goto
map_locked: true
two_finger_pan: true
additional_presets:
  - preset_name: Static map
    entity: vacuum.roborock_s7
    map_source:
      image: /local/mappa_casa.png
    calibration_source:
      calibration_points:
        - map:
            x: 148
            'y': 384
          vacuum:
            x: 25500
            'y': 25500
        - map:
            x: 195
            'y': 338
          vacuum:
            x: 26500
            'y': 26500
        - map:
            x: 148
            'y': 338
          vacuum:
            x: 25500
            'y': 26500
    map_locked: true
    two_finger_pan: false
    map_modes:
      - template: vacuum_clean_segment
        predefined_selections:
          - id: 18
            outline:
              - - 23450
                - 27700
              - - 23450
                - 33320
              - - 28100
                - 33320
              - - 29550
                - 31800
              - - 29550
                - 27700
            label:
              text: Soggiorno
              x: 26550
              'y': 31300
              offset_y: 30
            icon:
              name: mdi:sofa
              x: 26550
              'y': 31300
      - template: vacuum_clean_zone_predefined
        predefined_selections:
          - label:
              text: Tavolino
              x: 26300
              'y': 30150
              offset_y: 30
            icon:
              name: mdi:table-furniture
              x: 26300
              'y': 30150
            zones:
              - - 25300
                - 28500
                - 27300
                - 31500
rospogrigio commented 1 year ago

The camera config is, instead:

  - platform: xiaomi_cloud_map_extractor
    host: 192.168.1.13
    token: !secret roborock_token
    username: !secret xiaomi_cloud_username
    password: !secret xiaomi_cloud_password
    country: "de"
    name: "Roborock live map"
    store_map_raw: false
    store_map_image: false
    store_map_path: .
    colors:
      color_map_inside: [32, 115, 185]
      color_map_outside: [255, 255, 255]
      color_map_wall: [100, 100, 100]
      color_map_wall_v2: [120, 120, 120]
      color_grey_wall: [255, 255, 255]
      color_cleaned_area: [0x55, 0x55, 0x55, 0x8F]
      color_new_discovered_area: [0x55, 0x55, 0x55, 0x8F]
      color_path: [255, 255, 255, 255]
      color_mop_path: [255, 255, 255, 0x48]
      color_goto_path: [0, 255, 0]
      color_predicted_path: [255, 255, 0, 0]
      color_zones: [0xAD, 0xD8, 0xFF, 0x8F]
      color_zones_outline: [0xAD, 0xD8, 0xFF]
      color_virtual_walls: [255, 0, 0]
      color_carpets: [0xA9, 0xF7, 0xA9 ]
      color_no_carpet_zones: [255, 33, 55, 0x5F]
      color_no_carpet_zones_outline: [255, 0, 0]
      color_no_go_zones: [255, 33, 55, 127]
      color_no_go_zones_outline: [255, 0, 0]
      color_no_mop_zones: [163, 130, 211, 127]
      color_no_mop_zones_outline: [163, 130, 211]
      color_charger: [0x66, 0xfe, 0xda, 0xdf]
      color_charger_outline: [0, 0, 0]
      color_robo: [0xFF, 0xFF, 0xFF]
      color_robo_outline: [0, 0, 0]
      color_unknown: [0, 0, 0]
      color_scan: [0xDF, 0xDF, 0xDF]
    room_colors:
      4: [240, 178, 122]
      5: [72,  201, 176]
      6: [255, 198, 255]
      16: [0xff, 0xc0, 0xd0]
      17: [0xfb, 0xcf, 0x9b]
      18: [112, 203, 222]
      19: [145, 200, 255]
      20: [0xca, 0xb5, 0xf4]
      21: [240, 178, 122]
      22: [245, 142, 111]
      23: [0x93, 0xcc, 0x99]
    draw:
      - charger
      - path
      - goto_path
      - mop_path
      - predicted_path
      - no_carpet_zones
      - no_go_zones
      - no_mopping_zones
      - vacuum_position
      - virtual_walls
#      - zones
    map_transformation:
      scale: 4.0
      rotate: 180
      trim:
        top: 19
        bottom: 23
        left: 22
        right: 22
    sizes:
      charger_radius: 12
      vacuum_radius: 16
      path_width: 2
      mop_path_width: 16
      obstacle_radius: 3
      ignored_obstacle_radius: 3
      obstacle_with_photo_radius: 3
      ignored_obstacle_with_photo_radius: 3
    attributes:
      - calibration_points
      - charger
      - goto
      - goto_path
      - goto_predicted_path
      - image
      - no_carpet_areas
      - no_go_areas
      - no_mopping_areas
      - obstacles
      - path
      - vacuum_position
      - walls
      - zones
PiotrMachowski commented 1 year ago

That's weird... What are attributes of camera entity?

rospogrigio commented 1 year ago
access_token: xxxxxxxx
entity_picture: /api/camera_proxy/camera.roborock_live_map?token=xxxxxxxxxx
friendly_name: Roborock live map
supported_features: 1
calibration_points: 
- vacuum:
    x: 25500
    'y': 25500
  map:
    x: 544
    'y': 140
- vacuum:
    x: 26500
    'y': 25500
  map:
    x: 464
    'y': 140
- vacuum:
    x: 25500
    'y': 26500
  map:
    x: 544
    'y': 220

charger: 
x: 25775
'y': 25297
a: 116

image: 
size: 159744
offset_y: 476
offset_x: 430
height: 242
scale: 4
rotation: 180
width: 216

no_carpet_areas: 
- x0: 29445
  y0: 33132
  x1: 30445
  y1: 33132
  x2: 30445
  y2: 32032
  x3: 29445
  y3: 32032

no_go_areas: 
no_mopping_areas: 
path: 
point_length: 256
point_size: 4
angle: 0
path:
  - x: 25696
    'y': 25454
  - x: 25657
    'y': 25515
  - x: 25605
    'y': 25598
  - x: 25586
    'y': 25628
  - x: 25586
    'y': 25628
  - x: 25587
    'y': 25624
  - x: 25588
    'y': 25628
  - x: 25645
    'y': 25783
  - x: 25716
    'y': 25969
  - x: 25833
    'y': 26120
 [...]

vacuum_position: 
x: 25698
'y': 25458
a: -64

walls: 
model: roborock.vacuum.a15
used_api: xiaomi
PiotrMachowski commented 1 year ago

It shouldn't happen... Here is code responsible for validation. Can you try to create another card with just basic config?

rospogrigio commented 1 year ago

I'll try tomorrow... too late now. Maybe you can try too from this PR, I have started getting this error since the first merge from the dev branch (I forked from master when I started developing this). Don't know if this might give you a hint...

BTW, what do you mean by "basic config"?

PiotrMachowski commented 1 year ago

To be honest I don't even see a possibility to trigger this error by backend change... It should be purely frontend.

Basic config would look like this: https://github.com/PiotrMachowski/lovelace-xiaomi-vacuum-map-card/blob/master/docs/basic_config.yaml

rospogrigio commented 1 year ago

OK I found the problem, it was in camera.py:

            ATTRIBUTE_MAP_NAME: map_data.map_name,
            ATTRIBUTE_MOP_PATH: self._map_data.mop_path,  <--- wrong self._map_data
            ATTRIBUTE_NO_GO_AREAS: map_data.no_go_areas,

May I ask you why you decided to change this: return Path(point_length, point_size, angle, [path_points])

Why did you make path.path a list of lists, actually containing only one element (the list of points)? I don't get the need... Hope this is fine now.

PiotrMachowski commented 1 year ago

Why did you make path.path a list of lists, actually containing only one element

Because it's possible for some models to have a path that will consist of several discontinuous sections

rospogrigio commented 1 year ago

Because it's possible for some models to have a path that will consist of several discontinuous sections

OK I see. Then I probably need to slightly review the code. Edit: actually no, since this part is specific for xiaomi. Let me have your comments on this PR, if you find it ok you might prefer to merge directly #358 that integrates this and the carpets handling. Edit 2: maybe changing the name into path.paths would be less confusing then? Just a suggestion

rospogrigio commented 1 year ago

I finally ended up with making the parse_mop_path method more general, supporting multiple vacuum paths should they be introduced in xiaomi models too, check this out.

rospogrigio commented 1 year ago

I noticed that there was a bug, and that a list of separate paths needed to be used also for the mop_paths (the Xiaomi S7 can lift the mop and push it down again when needed). I fixed this in this final version. This is how for example it was not displaying correctly (notice the wrong diagonal trail):

image

And here is after the fix:

image

I think it works perfectly now! 😉

PiotrMachowski commented 1 year ago

Thank you again, @rospogrigio! I have found some time to maintain this integration