NOT WORKING CONSISTENTLY -- Xiaomi Cube Controller (ZHA)

Blueprint to support the Xiaomi Cube Controller using ZHA. Thanks to @wmn79 for this inspiration.

Supported actions:

  • Slide without respect to which face is up
  • Slide with respect to which of the six faces are up
  • Knock without respect to which face is up
  • Knock with respect to which of the six faces are up
  • Flip to any face
  • Shake
  • Drop
  • Rotate clockwise
  • Rotate counter-clockwise

Blueprint

Click the badge to import this Blueprint: (needs Home Assistant Core 2021.3 or higher)

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

blueprint:
  name: Aqara Magic Cube (ZHA)
  description: 'Control anything using Aqara Magic Cube (ZHA)'
  domain: automation
  input:
    remote:
      name: Remote
      description: Magic Cube to use
      selector:
        device:
          integration: zha
          manufacturer: LUMI
          model: lumi.sensor_cube
    
    # --------------------------- SLIDE ANY FACE ----------------------------
    slide_any_face:
      name: Slide the cube with any face up
      default: []
      selector:
        action: {}


    # --------------------------- SLIDE FACE 1 UP ----------------------------
    slide_face_1:
      name: Slide the cube with face 1 up
      default: []
      selector:
        action: {}


    # --------------------------- SLIDE FACE 2 UP ----------------------------
    slide_face_2:
      name: Slide the cube with face 2 up
      default: []
      selector:
        action: {}


    # --------------------------- SLIDE FACE 3 UP ----------------------------
    slide_face_3:
      name: Slide the cube with face 3 up
      default: []
      selector:
        action: {}


    # --------------------------- SLIDE FACE 4 UP ----------------------------
    slide_face_4:
      name: Slide the cube with face 4 up
      default: []
      selector:
        action: {}


    # --------------------------- SLIDE FACE 5 UP ----------------------------
    slide_face_5:
      name: Slide the cube with face 5 up
      default: []
      selector:
        action: {}


    # --------------------------- SLIDE FACE 6 UP ----------------------------
    slide_face_6:
      name: Slide the cube with face 6 up
      default: []
      selector:
        action: {}


    # --------------------------- KNOCK ANY FACE ----------------------------
    knocked_any_face:
      name: Knock the cube with any face up
      default: []
      selector:
        action: {}


    # --------------------------- KNOCK FACE 1 UP ----------------------------
    knocked_face_1:
      name: Knock the cube with face 1 up
      default: []
      selector:
        action: {}


    # --------------------------- KNOCK FACE 2 UP ----------------------------
    knocked_face_2:
      name: Knock the cube with face 2 up
      default: []
      selector:
        action: {}


    # --------------------------- KNOCK FACE 3 UP ----------------------------
    knocked_face_3:
      name: Knock the cube with face 3 up
      default: []
      selector:
        action: {}


    # --------------------------- KNOCK FACE 4 UP ----------------------------
    knocked_face_4:
      name: Knock the cube with face 4 up
      default: []
      selector:
        action: {}


    # --------------------------- KNOCK FACE 5 UP ----------------------------
    knocked_face_5:
      name: Knock the cube with face 5 up
      default: []
      selector:
        action: {}


    # --------------------------- KNOCK FACE 6 UP ----------------------------
    knocked_face_6:
      name: Knock the cube with face 6 up
      default: []
      selector:
        action: {}

    # --------------------------- FLIP ANY FACE ----------------------------
    flipped_any_face:
      name: Flip the cube to any face
      default: []
      selector:
        action: {}


    # --------------------------- FLIP FACE 1 UP ----------------------------
    flipped_face_1:
      name: Flip the cube to face 1
      default: []
      selector:
        action: {}


    # --------------------------- FLIP FACE 2 UP ----------------------------
    flipped_face_2:
      name: Flip the cube to face 2
      default: []
      selector:
        action: {}


    # --------------------------- FLIP FACE 3 UP ----------------------------
    flipped_face_3:
      name: Flip the cube to face 3
      default: []
      selector:
        action: {}


    # --------------------------- FLIP FACE 4 UP ----------------------------
    flipped_face_4:
      name: Flip the cube to face 4
      default: []
      selector:
        action: {}


    # --------------------------- FLIP FACE 5 UP ----------------------------
    flipped_face_5:
      name: Flip the cube to face 5
      default: []
      selector:
        action: {}


    # --------------------------- FLIP FACE 6 UP ----------------------------
    flipped_face_6:
      name: Flip the cube to face 6
      default: []
      selector:
        action: {}

    # -------------------------- SHAKE ----------------------------
    shake:
      name: Shake the cube
      default: []
      selector:
        action: {}

    # -------------------------- DROP ----------------------------
    drop:
      name: Drop the cube
      default: []
      selector:
        action: {}

    # ------------------------- ROTATE CLOCKWISE --------------------
    rotate_cw:
      name: Rotate cube clockwise
      default: []
      selector:
        action: {}

    # ---------------------------- ROTATE COUNTER CLOCKWISE ----------------------------
    rotate_ccw:
      name: Rotate cube counter clockwise
      default: []
      selector:
        action: {}


mode: restart
max_exceeded: silent
trigger:
- platform: event
  event_type: zha_event
  event_data:
    device_id: !input 'remote'
action:
- variables:
    event: '{{ trigger.event.data.event }}'
    sub_event: '{{ trigger.event.data.args.subtype }}'
- choose:

  # ---------------------------- SLIDE ANY FACE ----------------------------
  - conditions:
    - '{{ event == "slide" }}'
    - '{{ sub_event == "face_any" }}'
    sequence: !input 'slide_any_face'

  # ---------------------------- SLIDE FACE  1 ----------------------------
  - conditions:
    - '{{ event == "slide" }}'
    - '{{ sub_event == "face_1" }}'
    sequence: !input 'slide_face_1'

  # ---------------------------- SLIDE FACE  2 ----------------------------
  - conditions:
    - '{{ event == "slide" }}'
    - '{{ sub_event == "face_2" }}'
    sequence: !input 'slide_face_2'

  # ---------------------------- SLIDE FACE  3 ----------------------------
  - conditions:
    - '{{ event == "slide" }}'
    - '{{ sub_event == "face_3" }}'
    sequence: !input 'slide_face_3'

  # ---------------------------- SLIDE FACE  4 ----------------------------
  - conditions:
    - '{{ event == "slide" }}'
    - '{{ sub_event == "face_4" }}'
    sequence: !input 'slide_face_4'

  # ---------------------------- SLIDE FACE  5 ----------------------------
  - conditions:
    - '{{ event == "slide" }}'
    - '{{ sub_event == "face_5" }}'
    sequence: !input 'slide_face_5'

  # ---------------------------- SLIDE FACE  6 ----------------------------
  - conditions:
    - '{{ event == "slide" }}'
    - '{{ sub_event == "face_6" }}'
    sequence: !input 'slide_face_6'

  # ---------------------------- KNOCK ANY FACE ----------------------------
  - conditions:
    - '{{ event == "device_knocked" }}'
    - '{{ sub_event == "face_any" }}'
    sequence: !input 'knocked_any_face'

  # ---------------------------- KNOCK FACE  1 ----------------------------
  - conditions:
    - '{{ event == "device_knocked" }}'
    - '{{ sub_event == "face_1" }}'
    sequence: !input 'knocked_face_1'

  # ---------------------------- KNOCK FACE  2 ----------------------------
  - conditions:
    - '{{ event == "device_knocked" }}'
    - '{{ sub_event == "face_2" }}'
    sequence: !input 'knocked_face_2'

  # ---------------------------- KNOCK FACE  3 ----------------------------
  - conditions:
    - '{{ event == "device_knocked" }}'
    - '{{ sub_event == "face_3" }}'
    sequence: !input 'knocked_face_3'

  # ---------------------------- KNOCK FACE  4 ----------------------------
  - conditions:
    - '{{ event == "device_knocked" }}'
    - '{{ sub_event == "face_4" }}'
    sequence: !input 'knocked_face_4'

  # ---------------------------- KNOCK FACE  5 ----------------------------
  - conditions:
    - '{{ event == "device_knocked" }}'
    - '{{ sub_event == "face_5" }}'
    sequence: !input 'knocked_face_5'

  # ---------------------------- KNOCK FACE  6 ----------------------------
  - conditions:
    - '{{ event == "device_knocked" }}'
    - '{{ sub_event == "face_6" }}'
    sequence: !input 'knocked_face_6'

  # ---------------------------- FLIP ANY FACE ----------------------------
  - conditions:
    - '{{ event == "device_flipped" }}'
    - '{{ sub_event == "face_any" }}'
    sequence: !input 'flipped_any_face'

  # ---------------------------- FLIP FACE  1 ----------------------------
  - conditions:
    - '{{ event == "device_flipped" }}'
    - '{{ sub_event == "face_1" }}'
    sequence: !input 'flipped_face_1'

  # ---------------------------- FLIP FACE  2 ----------------------------
  - conditions:
    - '{{ event == "device_flipped" }}'
    - '{{ sub_event == "face_2" }}'
    sequence: !input 'flipped_face_2'

  # ---------------------------- FLIP FACE  3 ----------------------------
  - conditions:
    - '{{ event == "device_flipped" }}'
    - '{{ sub_event == "face_3" }}'
    sequence: !input 'flipped_face_3'

  # ---------------------------- FLIP FACE  4 ----------------------------
  - conditions:
    - '{{ event == "device_flipped" }}'
    - '{{ sub_event == "face_4" }}'
    sequence: !input 'flipped_face_4'

  # ---------------------------- FLIP FACE  5 ----------------------------
  - conditions:
    - '{{ event == "device_flipped" }}'
    - '{{ sub_event == "face_5" }}'
    sequence: !input 'flipped_face_5'

  # ---------------------------- FLIP FACE  6 ----------------------------
  - conditions:
    - '{{ event == "device_flipped" }}'
    - '{{ sub_event == "face_6" }}'
    sequence: !input 'flipped_face_6'

  # ---------------------------- SHAKE ----------------------------
  - conditions:
    - '{{ event == "device_shake" }}'
    - '{{ sub_event == "turn_on" }}'
    sequence: !input 'shake'

  # ---------------------------- DROP ----------------------------
  - conditions:
    - '{{ event == "device_dropped" }}'
    - '{{ sub_event == "turn_on" }}'
    sequence: !input 'drop'

  # ---------------------------- ROTATE CLOCKWISE ----------------------------
  - conditions:
    - '{{ event == "device_rotated" }}'
    - '{{ sub_event == "right" }}'
    sequence: !input 'rotate_cw'

  # ---------------------------- ROTATE COUNTER CLOCKWISE ----------------------------
  - conditions:
    - '{{ event == "device_rotated" }}'
    - '{{ sub_event == "left" }}'
    sequence: !input 'rotate_ccw'
4 Likes

I can’t download this blueprint.

The error message says: “No valid blueprint found in the topic. Blueprint syntax blocks need to be marked as YAML or no syntax.”

I am not sure if it is because of the formatted text for the supported actions or because there is no source_url.

Good job though. :wink:

Ah thanks for checking! Should be fixed!

All sorted.

Thank you for that.

These blueprints are so exciting. I have even used blueprints to create automations I already have, just for the sake of it.

1 Like

@bobchadwick

Just so you know I had to twerk the blueprint for me as my model for the device is lumi.sensor_cube.aqgl01

Just incase anyone else has an issue.

Maybe remove the model line from your blueprint and the all devices under LUMI will appear.

Thanks for the blueprint.

1 Like

Hey man – thanks for putting this together. Admittedly this is my first attempt at importing a Blueprint; but I can’t get this to work. The automation I’ve setup seems to be recognizing the trigger, but no actions are happening.

Opened the blueprint in File Editor to make the same change as above for the model name; and it’s showing this when I go to save (not sure if it’s related or not):

unknown tag !<!input> at line 146, column 31:
        device_id: !input 'remote'
                                  ^

@stx21 I’m also trying to get this to work just right now. The error you notice is most likely not related to the issue here. I’m seeing the same alert in other blueprints but they work fine…

The problem we both seem to have is that the trigger data is different to what is expected here. For example, this the event data I’m receiving when listening to zha_event via developer tools:

{
    "event_type": "zha_event",
    "data": {
        "device_ieee": "...",
        "unique_id": "...",
        "device_id": "....",
        "endpoint_id": 3,
        "cluster_id": 12,
        "command": "rotate_right",
        "args": {
            "relative_degrees": 18.53000259399414
        }
    },
    "origin": "LOCAL",
    "time_fired": "2020-12-17T00:12:58.525870+00:00",
    "context": {
        "id": "...",
        "parent_id": null,
        "user_id": null
    }
}

The blueprint expects to read trigger.event.data.event and trigger.event.data.args.subtype, but they are not set as you can see above.

I’m not sure where that difference comes from. Different hardware models? Different firmware? I’m not sure if the blueprint needs to be adjusted or if something with my setup is wrong…(?)

I see the same when listening to zha_event – however, in the past, I had automations setup with event and sub_event as triggers, and they worked totally fine. For example:

- id: ''
  alias: Play Favorites in Office
  description: ''
  trigger:
  - device_id: ...
    domain: zha
    platform: device
    type: device_knocked
    subtype: face_3
  condition: []
  action:
  - service: media_player.select_source
    data:
      source: Your Top Songs 2020
    entity_id: media_player.office

Ok it works for me now. Here is what needs to be changed:

   - conditions:
-    - '{{ event == "slide" }}'
-    - '{{ sub_event == "face_1" }}'
+    - condition: or
+      conditions:
+        - '{{ event == "slide" and sub_event == "face_1" }}'
+        - '{{ command == "slide" and activated_face|int == 1 }}'
     sequence: !input 'slide_face_1'

etc. using the commands “slide”, “knock”, “flip”, “shake”, “drop”, “rotate_right”, “rotate_left”.
I also noticed that the *_any events like flipped_any_face need to be moved to the bottom of the list because otherwise, events like “flipped_face_1” would never be triggered…
Note: I was unable to test the “drop” event. Not sure how to trigger this one…

@bobchadwick Can you update the blueprint, please? Or can I create a pull request for it somewhere? Not sure about the workflow yet for doing blueprints contributions…

2 Likes

Here’s something I didn’t know I needed! And it’s on Amazon so it should be here Saturday :sweat_smile:

1 Like

My guess is that the original author might not have the latest zigpy and/or zha-device-handlers – I think the command vs. event is a result of newer zha-device-handlers quirks for the cube being applied, since they take over translating the device’s events.

Hey, do you want to ZHA-ify my blueprint on the Cube? 45+ actions Mi Magic Cube - Deconz (45+ actions!)

2 Likes

Hey, thanks for the suggested fixes! I haven’t had time to implement them, and I don’t have the blueprint in a repo. Hopefully I’ll find the time this weekend, otherwise it’ll have to wait until after the weekend.

1 Like

Oh yeah, another thing. I’ve realized this probably isn’t the best use-case for a blueprint, since the actions are already mapped in ZHA. Seems like this is kinda duplicating the functionality you’d get by just using automations. Thoughts?

Well having a Blueprint available means you can share it with us and we don’t have to sift through it to replace your entity_id's with our own. It’s definitely worth having. Have a look at the deCONZ version that Andreas has made, it looks pretty awesome (but I use ZHA).

@bobchadwick Hi, can you please check if you are using the correct model? Mine is called lumi.sensor_cube.aqgl01 just like @AlexGreenUK

Hey folks, sorry I haven’t been able to get this updated (new baby). If someone else wants to give it a go and post the updated blueprint, I can update the original post.

Mind sharing your fully updated blueprint? Sounds like OP is a bit busy at the moment and I am having a bit of difficulty getting your suggestion to work without errors.

Had to edit this pretty significantly to get it to work for me. I believe I may be using a newer version of ZHA than OP.

If your ZHA event for the cube looks like mine below then my edit should work for you:

{
    "event_type": "zha_event",
    "data": {
        "device_ieee": "xxxx",
        "unique_id": "xxxx",
        "device_id": "xxxx",
        "endpoint_id": 2,
        "cluster_id": 18,
        "command": "flip",
        "args": {
            "value": 131,
            "flip_degrees": 180,
            "activated_face": 4
        }
    }

I suppose the cleanest way would be to use the args.value key but I didn’t feel like sitting there and noting them all down.

blueprint:
  name: Aqara Magic Cube (ZHA)
  description: Control anything using Aqara Magic Cube (ZHA)
  domain: automation
  input:
    remote:
      name: Remote
      description: Magic Cube to use
      selector:
        device:
          integration: zha
          manufacturer: LUMI
          model: lumi.sensor_cube
    slide_any_face:
      name: Slide the cube with any face up
      default: []
      selector:
        action: {}
    slide_face_1:
      name: Slide the cube with face 1 up
      default: []
      selector:
        action: {}
    slide_face_2:
      name: Slide the cube with face 2 up
      default: []
      selector:
        action: {}
    slide_face_3:
      name: Slide the cube with face 3 up
      default: []
      selector:
        action: {}
    slide_face_4:
      name: Slide the cube with face 4 up
      default: []
      selector:
        action: {}
    slide_face_5:
      name: Slide the cube with face 5 up
      default: []
      selector:
        action: {}
    slide_face_6:
      name: Slide the cube with face 6 up
      default: []
      selector:
        action: {}
    knocked_any_face:
      name: Knock the cube with any face up
      default: []
      selector:
        action: {}
    knocked_face_1:
      name: Knock the cube with face 1 up
      default: []
      selector:
        action: {}
    knocked_face_2:
      name: Knock the cube with face 2 up
      default: []
      selector:
        action: {}
    knocked_face_3:
      name: Knock the cube with face 3 up
      default: []
      selector:
        action: {}
    knocked_face_4:
      name: Knock the cube with face 4 up
      default: []
      selector:
        action: {}
    knocked_face_5:
      name: Knock the cube with face 5 up
      default: []
      selector:
        action: {}
    knocked_face_6:
      name: Knock the cube with face 6 up
      default: []
      selector:
        action: {}
    flipped_any_face:
      name: Flip the cube to any face
      default: []
      selector:
        action: {}
    flipped_face_1:
      name: Flip the cube to face 1
      default: []
      selector:
        action: {}
    flipped_face_2:
      name: Flip the cube to face 2
      default: []
      selector:
        action: {}
    flipped_face_3:
      name: Flip the cube to face 3
      default: []
      selector:
        action: {}
    flipped_face_4:
      name: Flip the cube to face 4
      default: []
      selector:
        action: {}
    flipped_face_5:
      name: Flip the cube to face 5
      default: []
      selector:
        action: {}
    flipped_face_6:
      name: Flip the cube to face 6
      default: []
      selector:
        action: {}
    shake:
      name: Shake the cube
      default: []
      selector:
        action: {}
    drop:
      name: Drop the cube
      default: []
      selector:
        action: {}
    rotate_cw:
      name: Rotate cube clockwise
      default: []
      selector:
        action: {}
    rotate_ccw:
      name: Rotate cube counter clockwise
      default: []
      selector:
        action: {}
mode: restart
max_exceeded: silent
trigger:
- platform: event
  event_type: zha_event
  event_data:
    device_id: !input 'remote'
action:
- variables:
    event: '{{ trigger.event.data.command }}'
    activated_face: '{{ trigger.event.data.args.activated_face }}'
    flip_degrees: '{{ trigger.event.data.args.flip_degrees }}'
    relative_degrees: '{{ trigger.event.data.args.relative_degrees }}'
- choose:
  - conditions:
    - '{{ event == "slide" }}'
    - '{{ activated_face == 1 }}'
    sequence: !input 'slide_face_1'
  - conditions:
    - '{{ event == "slide" }}'
    - '{{ activated_face == 2 }}'
    sequence: !input 'slide_face_2'
  - conditions:
    - '{{ event == "slide" }}'
    - '{{ activated_face == 3 }}'
    sequence: !input 'slide_face_3'
  - conditions:
    - '{{ event == "slide" }}'
    - '{{ activated_face == 4 }}'
    sequence: !input 'slide_face_4'
  - conditions:
    - '{{ event == "slide" }}'
    - '{{ activated_face == 5 }}'
    sequence: !input 'slide_face_5'
  - conditions:
    - '{{ event == "slide" }}'
    - '{{ activated_face == 6 }}'
    sequence: !input 'slide_face_6'
  - conditions:
    - '{{ event == "slide" }}'
    sequence: !input 'slide_any_face'
  - conditions:
    - '{{ event == "knock" }}'
    - '{{ activated_face == 1 }}'
    sequence: !input 'knocked_face_1'
  - conditions:
    - '{{ event == "knock" }}'
    - '{{ activated_face == 2 }}'
    sequence: !input 'knocked_face_2'
  - conditions:
    - '{{ event == "knock" }}'
    - '{{ activated_face == 3 }}'
    sequence: !input 'knocked_face_3'
  - conditions:
    - '{{ event == "knock" }}'
    - '{{ activated_face == 4 }}'
    sequence: !input 'knocked_face_4'
  - conditions:
    - '{{ event == "knock" }}'
    - '{{ activated_face == 5 }}'
    sequence: !input 'knocked_face_5'
  - conditions:
    - '{{ event == "knock" }}'
    - '{{ activated_face == 6 }}'
    sequence: !input 'knocked_face_6'
  - conditions:
    - '{{ event == "knock" }}'
    sequence: !input 'knocked_any_face'
  - conditions:
    - '{{ event == "flip" }}'
    - '{{ activated_face == 1 }}'
    sequence: !input 'flipped_face_1'
  - conditions:
    - '{{ event == "flip" }}'
    - '{{ activated_face == 2 }}'
    sequence: !input 'flipped_face_2'
  - conditions:
    - '{{ event == "flip" }}'
    - '{{ activated_face == 3 }}'
    sequence: !input 'flipped_face_3'
  - conditions:
    - '{{ event == "flip" }}'
    - '{{ activated_face == 4 }}'
    sequence: !input 'flipped_face_4'
  - conditions:
    - '{{ event == "flip" }}'
    - '{{ activated_face == 5 }}'
    sequence: !input 'flipped_face_5'
  - conditions:
    - '{{ event == "flip" }}'
    - '{{ activated_face == 6 }}'
    sequence: !input 'flipped_face_6'
  - conditions:
    - '{{ event == "flip" }}'
    sequence: !input 'flipped_any_face'
  - conditions:
    - '{{ event == "shake" }}'
    sequence: !input 'shake'
  - conditions:
    - '{{ event == "drop" }}'
    sequence: !input 'drop'
  - conditions:
    - '{{ event == "rotate_right" }}'
    sequence: !input 'rotate_cw'
  - conditions:
    - '{{ event == "rotate_left" }}'
    sequence: !input 'rotate_ccw'

2 Likes

None of those blueprint work for me?
I can see the automation triggered but the action are not fired.

ZHA / Conbee 2 / Aqara Magic Cube.

The zha_event look like yours, don’t understand.
I’ve test the cube with a “normal” automation and it worked.