Custom Component: Dreame Vacuum

just like you’re doing the whole time? :wink:

ok, but jokes aside and in all seriousness - I wish you all the best in fighting those anger issues, so you can have a normal conversation with other users.

Thanks for that awesome template snippet that creates a single card for all room settings (dreame-vacuum/docs/room_entities.md at fe3133384e14b0d9b2da6cca2c794d1507a39f98 · Tasshack/dreame-vacuum · GitHub)! I’ve slightly edited that one to also include the cleaning mode, maybe somebody finds that useful:
image

{# ----------------- PROVIDE YOUR OWN ENTITY ID AND ROOM COUNT HERE ----------------- #}
{% set vacuum_entity = "vacuum." %}
{# ------------------- DO NOT CHANGE ANYTHING BELOW ------------------- #}
{%- set vacuum_name = states[vacuum_entity].entity_id.replace('vacuum.', '') %}
{%- set friendly_vacuum_name = states[vacuum_entity].attributes.friendly_name %}
{%- set mop_pad = ('mop_pad_humidity' in states[vacuum_entity].attributes)|bool %}
{% set rooms = namespace(list=[]) %}
{%- if 'rooms' in states[vacuum_entity].attributes %}
{%- for map in states[vacuum_entity].attributes.rooms.values() %}  
    {%- for room in map %}  
    {%- if room.id not in rooms.list %}
        {%- set rooms.list = rooms.list + [room.id] %}
    {%- endif %}
    {%- endfor %}
{%- endfor %}
{%- endif %}
{%- set rooms.list = rooms.list|sort() %}

type: entities
title: '{{ friendly_vacuum_name }} Room Settings'
show_header_toggle: false
entities:
{%- for room in rooms.list %}
{%- set room_exists = "states['" + vacuum_entity + "'].attributes.cleaning_sequence && states['" + vacuum_entity + "'].attributes.cleaning_sequence.length > " + (loop.index - 1)|string  %} 
{%- set room_id = "(" + room_exists + " ? (states['" + vacuum_entity + "'].attributes.cleaning_sequence[" + (loop.index - 1)|string + "]) : " + room|string + ")" %}
{%- set current_room = "(vars[6].state == 'unavailable' && states['select." + vacuum_name + "_cleaning_mode'].state == 'unavailable' && states['" + vacuum_entity + "'].attributes.current_segment == vars[0])" %}
  - type: custom:config-template-card
    variables:
      - >- 
        {{ room_id }}
      - states['select.{{ vacuum_name }}_room_' + vars[0] + '_name'] 
      - states['select.{{ vacuum_name }}_room_' + vars[0] + '_cleaning_mode']
      - states['select.{{ vacuum_name }}_room_' + vars[0] + '_suction_level']
      {%- if mop_pad %}
      - states['select.{{ vacuum_name }}_room_' + vars[0] + '_mop_pad_humidity']
      {%- else %}
      - states['select.{{ vacuum_name }}_room_' + vars[0] + '_water_volume']
      {%- endif %}
      - states['select.{{ vacuum_name }}_room_' + vars[0] + '_cleaning_times']
      - states['select.{{ vacuum_name }}_room_' + vars[0] + '_order']
      - >- 
        states['{{ vacuum_entity }}']
      - >-
        (vars[7].attributes.rooms && vars[7].attributes.selected_map ? vars[7].attributes.rooms[vars[7].attributes.selected_map].length : 1)
      - >-
        ({{ current_room }} ? 'var(--state-icon-active-color)' : 'var(--primary-text-color)')
      - >-
        (vars[7].attributes.cleaning_sequence ? 'inherit' : 'none')
      - >-
        (vars[6].state != 'unavailable' ? 'inherit' : 'none')
      - >-
        (vars[7].attributes.customized_cleaning && (!vars[7].attributes.active_segments || states['{{ vacuum_entity }}'].attributes.active_segments.includes(vars[0])) ? 'inherit' : 'none')
    entities:
      - ${vars[1].entity_id}
      - ${vars[2].entity_id}
      - ${vars[3].entity_id}
      - ${vars[4].entity_id}
      - ${vars[5].entity_id}
      - ${vars[6].entity_id}
      - ${vars[7].entity_id}
    card:
      type: conditional
      conditions:
        - entity: ${vars[1].entity_id}
          state_not: unavailable
      card:            
        type: custom:multiple-entity-row
        entity: ${vars[1].entity_id}
        show_state: false
        name: ${vars[1].state}
        entities:
          - icon: ${vars[2].attributes.icon}
            entity: ${vars[2].entity_id}
            name: ' '
            tap_action: 
              action: call-service
              service: dreame_vacuum.select_select_next
              service_data:
                entity_id: ${vars[2].entity_id}
            double_tap_action:
              action: call-service
              service: dreame_vacuum.select_select_previous
              service_data:
                entity_id: ${vars[2].entity_id}
            hold_action:
              action: more-info
            styles:
              display: ${vars[12]}
              pointer-events: >-
                ${vars[2].state != 'unavailable' ? 'inherit' : 'none'}
              width: 28px
              '--paper-item-icon-color': ${vars[9]}
          - icon: ${vars[3].attributes.icon}
            entity: ${vars[3].entity_id}
            name: ' '
            tap_action:
              action: call-service
              service: dreame_vacuum.select_select_next
              service_data:
                entity_id: ${vars[3].entity_id}
            double_tap_action:
              action: call-service
              service: dreame_vacuum.select_select_previous
              service_data:
                entity_id: ${vars[3].entity_id}
            styles:
              display: ${vars[12]}
              pointer-events: >-
                ${vars[3].state != 'unavailable' ? 'inherit' : 'none'}
              width: 28px
              '--paper-item-icon-color': ${vars[9]}
          - icon: ${vars[4].attributes.icon}
            entity: ${vars[4].entity_id}
            name: ' '
            tap_action:
              action: call-service
              service: dreame_vacuum.select_select_next
              service_data:
                entity_id: ${vars[4].entity_id}
            double_tap_action:
              action: call-service
              service: dreame_vacuum.select_select_previous
              service_data:
                entity_id: ${vars[4].entity_id}
            hold_action:
              action: more-info
            styles:
              display: ${vars[12]}
              pointer-events: >-
                ${vars[4].state != 'unavailable' ? 'inherit' : 'none'}
              width: 28px
              '--paper-item-icon-color': ${vars[9]}
          - icon: ${vars[5].attributes.icon}
            entity: ${vars[5].entity_id}
            name: ' '
            tap_action:
              action: call-service
              service: dreame_vacuum.select_select_next
              service_data:
                entity_id: ${vars[5].entity_id}
            double_tap_action:
              action: call-service
              service: dreame_vacuum.select_select_previous
              service_data:
                entity_id: ${vars[5].entity_id}
            hold_action:
              action: more-info
            styles:
              display: ${vars[12]}
              pointer-events: >-
                ${vars[5].state != 'unavailable' ? 'inherit' : 'none'}
              width: 28px
              '--paper-item-icon-color': ${vars[9]}
          - icon: mdi:chevron-down
            entity: ${vars[6].entity_id}
            name: ' '
            tap_action:
              action: call-service
              service: dreame_vacuum.select_select_next
              service_data:
                entity_id: ${vars[6].entity_id}
                cycle: false
            hold_action:
              action: more-info
            styles:
              display: ${vars[10]}
              margin-right: 0
              margin-left: 8px
              '--paper-item-icon-color': >-
                ${(vars[8] > {{ loop.index }} ? 'var(--primary-color)' : 'var(--state-unavailable-color)')}
              pointer-events: >-
                ${(vars[8] > {{ loop.index }} ? vars[11] : 'none')}
          - icon: mdi:chevron-up
            entity: ${vars[6].entity_id}
            name: ' '
            tap_action:
              action: call-service
              service: dreame_vacuum.select_select_previous
              service_data:
                entity_id: ${vars[6].entity_id}
                cycle: false
            hold_action:
              action: more-info
            styles:
              display: ${vars[10]}
              '--paper-item-icon-color': {{ 'var(--primary-color)' if loop.index > 1 else 'var(--state-unavailable-color)' }}
              pointer-events: {{ "${vars[11]}" if loop.index > 1 else 'none' }}
  {%- endfor %}
  - type: divider
  - entity: switch.{{vacuum_name}}_customized_cleaning
    name: Customized Cleaning
  - entity: switch.{{vacuum_name}}_cleaning_sequence
    name: Cleaning Sequence

Note: I’ve also fixed the icon color when using the light theme. You used --text-primary-color which is just white in light theme. You need to use --primary-text-color. Stupid variable naming :smiley: This now works in all themes

Yikes, I just ordered an X30 Ultra after watching the pinned X40 unboxing video here thinking the X30 was an X40 with a lower price and kPa, and without the extending side brush.

But, is the X30 really a one-off integration-wise and unsupported by this apparently wonderful integration? The video makes a big point about the X40s’ integration with this project. What to do?

Dev branch already has the card template with cleaning mode but I will fix the icon color, thanks.

1 Like

That was a very old post, it is currently supported on Beta.

1 Like

Could not login to Xiaomi Miio Cloud, check the credentials.

100% sure I have correct login, password, and server selected. Any tips to login for the first time?


Good afternoon, I have S30 Pro Ultra, HA version 2024.9.1, Dreame vacuum integration version 2.0.0.16b. I can’t add work to the integration in HA. Everything works in the program on the Dreame phone, the Dreamer and Xiaomi accounts are linked. I’m trying to log in with both a Dream home Account and a MiHome account. The robot + server and even the laptop from which I work all sit on the same network under VPN China (they have an IP on the same network on the router, and one IP on the Internet). I tried to take the server out from under the VPN, but I left it in the same subnet, there is no result.
Please help me to launch the integration.

Updated:
I checked the version of the robot in the list of supported models, and it is dreame.vacuum.r2310d.
I tried to make the first login via phone number+ password and email + password. I have an account in dreamecloud of mainland China, I also choose CN, I tried b15 and b16, there is no difference, the first login still does not work.
Other users even have a server and work in different networks on different routers and everything is connected and working, I do not.
I did a complete removal of all versions from acs and installing from scratch only b16 without the main version also does not work.
For the test, I made a bundle of the account together with the mihome account, I thought it would work in this application.
In Myhome, there is a connection between the systems, but there are no devices in the list, then the MiHome sent to Alice Yandex (voice assistant) the robot appeared in Yandex, but there it is limited in functionality by 99%.
I am 100% sure of the correctness of passwords and logins. It was the fifth day… I read the entire thread of this topic, everything that was suggested did not fit.
By the way, where can I clean the cache from which b16 can be installed with an error?

Hi im having some issues with the integration that i dont know how to solve. I only have some basic controls available. Most of them are greyed out. Could you please point me in the right direction?

I lost connection with the cloud. It keeps retrying. I tried to configure a new one, and it fails on 2FA (keep asking me to confirm my email). Even after confirming it (using the link popping up - the web page says “OK” after entering the 2FA code), again and again it asks it.

I deleted my device from HA, and try to re-add it → same problem.

I’ll have to try later, when I copy-paste the link to a computer within the same public IP space. I tried from work computer, but that is indeed a different public IP.