Xiaomi Vacuum Control

Hey @mari0,

glad you like it - and I hope I can help you.

I’m not calculating anything by roomId, so it should work with the letters as well.

Not had much time to look at the code, but from a first sight, I think the error is in the “calculation” of your command:

actionCommand: "='spotArea:' + ((vars.cleanA ? 'A';'') + (vars.cleanB ? 'B';'') + (vars.cleanC ? 'C';'') + (vars.cleanD ? 'D';'') + (vars.cleanD ? 'D';'') + (vars.cleanE ? 'E';'') + (vars.cleanF ? 'F';'') + (vars.cleanG ? 'G';'') + (vars.cleanH ? 'H';''))"

Just looking at the small part

spotArea:' + ((vars.cleanA ? 'A';'') + (vars.cleanB ? 'B';'')

would mean, that if vars.cleanA and vars.cleanB is true the result will be

spotArea:AB

if not an error in calculation.
In my opinion would be correct:

spotArea:' + ((vars.cleanA ? 'A;':'') + (vars.cleanB ? 'B;':'')

So the true option is not just the letter, but always a letter and ;. and the true and false options are seperated by : instead.

You need to change that in the whole line, but afterwards it should work.

Hope that helps
Tetsuo

Edit: Link to shorthand if statement might help to better understand the syntax of this “command-calculation”: Java Short Hand If...Else (Ternary Operator)
Edit 2: Be aware that I linked to Java instead of JavaScript but the syntax is identical.

Just had some more time to look at it - maybe you try to replace just this one line:

actionCommand: "='spotArea:' + ((vars.cleanA ? 'A;':'') + (vars.cleanB ? 'B;':'') + (vars.cleanC ? 'C;':'') + (vars.cleanD ? 'D;':'') + (vars.cleanD ? 'D;':'') + (vars.cleanE ? 'E;':'') + (vars.cleanF ? 'F;':'') + (vars.cleanG ? 'G;':'') + (vars.cleanH ? 'H;':''))"

i’m trying to find a room unfortunately i have a problem with Execute_Command has anyone used it in xiaomi mi robot vacuum mop 2 pro or is able to help me? I don’t know what I’m doing wrong anymore ?

I have a good connection… becomes Execute Command - app_segment_clean
Unfortunately, the vacuum cleaner does not respond.
I found information roomid max 255… I tried a lot of options unfortunately to no avail

uid: tetsuo-repo-oh3-widget-vacuum
tags:
  - vacuum
  - room
  - map
  - control
props:
  parameters:
    - description: Prefix of item names. Look in your items for e.g. _CleaningMap and use everything before the underscore as prefix
      label: Item prefix
      name: itemPrefix
      required: true
      type: TEXT
    - description: 'json array with key value rooms like this [{"icon": "chat_bubble_2","roomId": 16,"label": "Roomname"}]'
      label: Rooms
      name: rooms
      required: true
      type: TEXT
    - description: Number of buttons for each row
      label: Chunk size
      name: chunkSize
      required: false
timestamp: Dec 29, 2022, 4:24:48 PM
component: f7-block
config: {}
slots:
  default:
    - component: f7-row
      config: {}
      slots:
        default:
          - component: f7-block
            config:
              style:
                - width: 75%
                - margin: 0
                - padding: 0
            slots:
              default:
                - component: oh-image-card
                  config:
                    item: =props.itemPrefix+"Cleaning_Map"
                    hidden: =items[props.itemPrefix+"Cleaning_Map"] === undefined
                    style:
                      borderRadius: 2em
          - component: f7-block
            config:
              style:
                - width: 25%
                - margin: auto
                - padding: 0
            slots:
              default:
                - component: f7-gauge
                  config:
                    style:
                      - width: 100%
                      - height: 100%
                    value: =(items[props.itemPrefix+"Battery"].state/100)
                    valueText: =(items[props.itemPrefix+"Battery"].state) + "%"
                    valueTextColor: '=items[props.itemPrefix+"Battery"].state < 25 ? "#f32617" : items[props.itemPrefix+"Battery"].state < 60 ? "#ffe81e" : "#6ec071"'
                    borderWidth: 18
                    labelText: '=items[props.itemPrefix+"Vacuum_Action"].state !== "dock"? "Bateria" : "Wird aufgeladen"'
                    borderColor: '=items[props.itemPrefix+"Battery"].state < 25 ? "#f32617" : items[props.itemPrefix+"Battery"].state < 60 ? "#ffe81e" : "#6ec071"'
                - component: oh-trend
                  config:
                    trendItem: =props.itemPrefix+"Battery"
                    trendStrokeWidth: 2
                    trendGradient:
                      - "#6ec071"
                    style:
                      --f7-theme-color-bg-color: transparent
                      background: transparent
                      filter: opacity(20%)
                      width: 100%
                      height: 100%
                      top: 0
                      left: 0
                      z-index: 0
                - component: f7-card
                  slots:
                    default:
                      - component: f7-card-content
                        slots:
                          default:
                            - component: f7-card-header
                              slots:
                                default:
                                  - component: Label
                                    config:
                                      text: '=items[props.itemPrefix+"Vacuum_Action"].state === "vacuum" ? "Dauer" : "Czas trwania"'
                                      style:
                                        - fontWeight: 100
                                        - color: rgb(136, 136, 136)
                            - component: Label
                              config:
                                text: =items[props.itemPrefix+"Clean_time"].state
                                style:
                                  height: 2.5em
                                  line-height: 2.5em
                                  text-align: center
                                  color: var(--f7-theme-color)
                                  font-weight: bold
                                  font-size: 2em
                            - component: f7-progressbar
                              config:
                                visible: =items[props.itemPrefix+"Vacuum_Action"].state === "vacuum"
                                infinite: true
                                class: color-blue
    - component: f7-row
      config:
        visible: =items[props.itemPrefix+"Vacuum_Action"].state !== "vacuum"
      slots:
        default:
          - component: f7-col
            slots:
              default:
                - component: f7-card
                  slots:
                    default:
                      - component: f7-card-header
                        slots:
                          default:
                            - component: Label
                              config:
                                text: Akcja
                                style:
                                  - fontWeight: 100
                                  - color: rgb(136, 136, 136)
                      - component: f7-card-content
                        slots:
                          default:
                            - component: oh-button
                              config:
                                style:
                                  height: 2.5em
                                  line-height: 2.5em
                                  font-size: 2em
                                text: =items[props.itemPrefix+"Vacuum_Action"].displayState
                                large: true
                                action: options
                                actionItem: =props.itemPrefix+"Vacuum_Action"
                                item: =props.itemPrefix+"Vacuum_Action"
          - component: f7-col
            slots:
              default:
                - component: f7-card
                  slots:
                    default:
                      - component: f7-card-header
                        slots:
                          default:
                            - component: Label
                              config:
                                text: Moc
                                style:
                                  - fontWeight: 100
                                  - color: rgb(136, 136, 136)
                      - component: f7-card-content
                        slots:
                          default:
                            - component: oh-button
                              config:
                                style:
                                  height: 2.5em
                                  line-height: 2.5em
                                  font-size: 2em
                                text: =items[props.itemPrefix+"suction_grade"].displayState
                                large: true
                                action: options
                                actionItem: =props.itemPrefix+"suction_grade"
                                item: =props.itemPrefix+"suction_grade"
    - component: oh-repeater
      config:
        sourceType: range
        for: i
        rangeStart: 0
        rangeStop: =JSON.parse(props.rooms).length / props.chunkSize
        fragment: true
        visible: =items[props.itemPrefix+"Vacuum_Action"].state !== "vacuum"
      slots:
        default:
          - component: f7-row
            config: {}
            slots:
              default:
                - component: oh-repeater
                  config:
                    for: roomChunk
                    in: =JSON.parse(props.rooms).slice(loop.i * props.chunkSize, props.chunkSize * (loop.i + 1))
                    fragment: true
                  slots:
                    default:
                      - component: f7-col
                        slots:
                          default:
                            - component: f7-card
                              config:
                                style:
                                  height: 3rem
                                  line-height: 3rem
                              slots:
                                default:
                                  - component: f7-card-content
                                    config:
                                      style:
                                        padding: 0
                                        marging: 0
                                        height: 3rem
                                    slots:
                                      default:
                                        - component: oh-button
                                          config:
                                            iconF7: =loop.roomChunk.icon
                                            iconSize: 1.2em
                                            active: '=vars["clean" + loop.roomChunk.roomId] ? true : false'
                                            text: =loop.roomChunk.label
                                            large: true
                                            action: variable
                                            actionVariable: ="clean" + loop.roomChunk.roomId
                                            actionVariableValue: '=undefined === vars["clean" + loop.roomChunk.roomId] ? true : !vars["clean" + loop.roomChunk.roomId]'
                                            style:
                                              height: 3rem
                                              line-height: 3rem
                                              text-align: center
                                              font-size: 1.1em
    - component: f7-row
      config: {}
      slots:
        default:
          - component: f7-col
            slots:
              default:
                - component: f7-card
                  slots:
                    default:
                      - component: f7-card-content
                        config:
                          style:
                            padding: 0
                        slots:
                          default:
                            - component: oh-button
                              config:
                                visible: =items[props.itemPrefix+"Vacuum_Action"].state !== "vacuum"
                                iconF7: rocket
                                iconSize: 1.2em
                                text: '=items[props.itemPrefix+"Vacuum_Action"].state === "vacuum" ? "Wird ausgeführt" : "Rozpocznij"'
                                large: true
                                action: command
                                actionItem: =props.itemPrefix+"Execute_Command"
                                actionCommand: "='app_segment_clean[' + ((vars.clean16 ? '16,': '') + (vars.clean17 ? '17,': '') + (vars.clean18 ? '18,': '') + (vars.clean19 ? '19,': '') + (vars.clean20 ? '20,': '') + (vars.clean21 ? '21,': '') + (vars.clean22 ? '22,': '') + (vars.clean23 ? '23,': '') + (vars.clean24 ? '24,': '')).slice(0, -1) + ']'"
                                style:
                                  height: 2.5em
                                  line-height: 2.5em
                                  text-align: center
                                  font-size: 2em
                            - component: oh-button
                              config:
                                visible: =items[props.itemPrefix+"Vacuum_Action"].state === "vacuum"
                                iconF7: stop_circle
                                iconSize: 1.2em
                                text: Zurück zum Dock
                                large: true
                                action: command
                                actionItem: =props.itemPrefix+"Execute_Command"
                                actionCommand: ='app_charge'
                                style:
                                  height: 2.5em
                                  line-height: 2.5em
                                  text-align: center
                                  font-size: 2em

Just figured it out how to send the room details to the Xiaomi Robot Mop 2S (thats to this and this post) , maybe it helps you as well.

actionItem: =props.itemPrefix+"_Execute_Command"
actionCommand: ='action{"siid":7,"aiid":3,"in":[{"piid":24,"value":"' + ((vars.clean10 ? "10,":"") + (vars.clean11 ? "11,":"")).slice(0, -1) + '"},{"piid":25,"value":0},{"piid":26,"value":1}]}'

@Tetsuo I needed to change .state to .displayState for the condition checks to work, e.g. text: '=items[props.itemPrefix+"_Status"].displayState === "Sweeping" ? "Wird ausgeführt" : "Ausführen"' instead of text: '=items[props.itemPrefix+"_Status"].state === "Sweeping" ? "Wird ausgeführt" : "Ausführen"', otherwise I would always see “Ausführen” (in this example).

Hello friend!
Tetsuo has moved on from openHAB so this widget is no longer getting updates unfortunately.

Well, I’m no developer but I can leave some hints if anyone is lost:
When configuring the widget, check all of your items and make sure they all begin with the same string, e.g.: “RoborockS6MaxV_BatteryLevel” and “RoborockS6MaxV_FanPower”.

Because the first thing you’ll configure is the “item prefix” and if you have different items with different prefixes it won’t work.

Additionally, to map the rooms and names you’ll want to follow this format:
[{“icon”: “chat_bubble_2”,“roomId”: 16,“label”: “Hallway”},{“icon”: “chat_bubble_2”,“roomId”: 17,“label”: “Kitchen”},{“icon”: “chat_bubble_2”,“roomId”: 18,“label”: “Bathroom”},{“icon”: “chat_bubble_2”,“roomId”: 19,“label”: “Living Room”}]

Replace the names for the ones you get, copy and paste to the widget config and you’re done.

Additionally, all of the items are hard coded in the widget. When it works it’s great, but when it doesn’t you need to edit the code of the widget, for example, I had to change the item name for battery because the widget is in German, and the item name mapped was “BatterieLandung”. Changed it to the name of my item “BatteryLevel” and all was good. If you like to edit channel names, I’m sorry to say you’ll probably have to do this on all of them.

I’m now considering translating the fields to English since I’m going to use this anyway. I’ll share it later here.

If anyone is interested in further developing this widget, I have an idea I’d like to see implemented: add the possibility of using the repeat function to tell the robot to clean the same room multiple times (seems like the limit is 3).

Anyone has a Xiaomi Vacuum X10+ running?

– Used “create support” according to the wiki page:
test-dreame.vacuum.p2114a-20231009-162035.txt (58.7 KB)

  • Channels are fine, getting data and I can start & stop the vacuum and change mode,…

MISSING: Is there any chance that I can get map-channel (as an image) or room channel added somehow? Dont know what to do with map-frame-info (NULL), map_extended_data (NULL) and map_mult_map_info ({“object_name”:“…”,“md5”:“…”})

map support for dreame… This is an open request, but currently no progress.

@marchino started some investigations in this area
https://community.openhab.org/t/xiaomi-miio/147365/6