Some background on what I’m trying to achieve.
I got a magic cube from Aqara.
A really nice remote with one flaw:
The rotate events lack information which face of the cube was activated.
Worse case: if the cube was asleep and you flip it, this flip event might get lost and your cube rotation might be interpretated under the assumption that the previous face (kept in my sensor) was still facing up.
Hence, I’ve written a macro to determine from the events that do contain the activated face, which face is currently up:
{% macro cube_face(cube_event, faces) %}
{% set is_cube_event = cube_event is defined and cube_event.event_type == 'zha_event' and cube_event.data.command in ['slide','knock','flip'] %}
{% if is_cube_event and cube_event.data.command == 'flip' %}
{% set face_number = cube_event.data.args.activated_face | int | default(0) %}
{% if face_number > 0 and face_number <= faces | length %}
{{ faces[face_number-1] }}
{% else %}
{{ 'no face' }}
{% endif %}
{% elif is_cube_event and cube_event.data.command in ['slide','knock'] %}
{% set face_number = cube_event.data.args.activated_face | int | default(0) %}
{% if face_number == 0 or face_number > faces | length %}
{{ 'no face' }}
{% elif face_number in [1,4] %}
{{ faces[face_number-1] }}
{% elif face_number in [2,3] %}
{{ faces[face_number+2] }}
{% else %}
{{ faces[face_number-4] }}
{% endif %}
{% else %}
{{ '' }}
{% endif %}
{% endmacro %}
In my sensor I use this macro to update the activated face and would like to know which face that is to set my attributes (still a work in progress):
- trigger:
- platform: event
event_type: zha_event
action:
- variables:
woonkamer_cube_event: >
{{ trigger.event is defined and
trigger.event.event_type == 'zha_event' and
trigger.event.data.device_id == '5517cc098da2aa72bd77fe7e06a3776f' and
trigger.event.data.command in ['slide','rotate_left','rotate_right','knock','flip','shake'] }}
woonkamer_cube_reset: >
{{ (woonkamer_cube_event and
state_attr('sensor.woonkamer_magic_cube','command') == 'shake' and
trigger.event.data.command == 'shake') }}
woonkamer_lights: >
{{ ['light.dimmer_2_5','light.dimmer_2_3','light.dimmer_2_4'] }}
woonkamer_default_light: 1
sensor:
- name: "Woonkamer magic cube"
unique_id: woonkamer_magic_cube
state: >
{% from 'magic-cube.jinja' import cube_face %}
{% set active_face = cube_face(trigger.event,['lights','audio','speakers','climate','power','curtains']) %}
{% if woonkamer_cube_event and active_face != '' %}
{{ active_face }}
{% else %}
{{ states('sensor.woonkamer_magic_cube') }}
{% endif %}
attributes:
command: >
{% if woonkamer_cube_event %}
{{ trigger.event.data.command }}
{% else %}
{{ this.attributes.command }}
{% endif %}
relative_degrees: >
{% if woonkamer_cube_event and 'rotate' in trigger.event.data.command %}
{{ trigger.event.data.args.relative_degrees }}
{% elif woonkamer_cube_event %}
{{ 0.0 }}
{% else %}
{{ this.attributes.relative_degrees }}
{% endif %}
light: >
{% if woonkamer_cube_reset or (this.state == 'lights' and trigger.event.data.command == 'shake') %}
{{ '' }}
{% elif woonkamer_cube_event and this.state == 'lights' and (trigger.event.data.command == 'slide' or (this.attributes.light == '' and 'rotate' in trigger.event.data.command)) %}
{% set index = woonkamer_lights.index(this.attributes.light) + 1 if this.attributes.light != none and this.attributes.light != '' else woonkamer_default_light %}
{% if index < woonkamer_lights | length %}
{{ woonkamer_lights[index] }}
{% else %}
{{ woonkamer_lights[0] }}
{% endif %}
{% else %}
{{ this.attributes.light }}
{% endif %}
audio: >
{% if woonkamer_cube_event and this.state == 'audio' and trigger.event.data.command not in ['shake','flip'] %}
{{ 'manual' }}
{% elif woonkamer_cube_reset or (this.state == 'audio' and trigger.event.data.command == 'shake') %}
{{ 'auto' }}
{% else %}
{{ this.attributes.audio }}
{% endif %}
speakers: >
{% if woonkamer_cube_event and this.state == 'speakers' and trigger.event.data.command not in ['shake','flip'] %}
{{ 'manual' }}
{% elif woonkamer_cube_reset or (this.state == 'speakers' and trigger.event.data.command == 'shake') %}
{{ 'auto' }}
{% else %}
{{ this.attributes.speakers }}
{% endif %}
climate: >
{% if woonkamer_cube_event and this.state == 'climate' and trigger.event.data.command not in ['shake','flip'] %}
{{ 'manual' }}
{% elif woonkamer_cube_reset or (this.state == 'climate' and trigger.event.data.command == 'shake') %}
{{ 'auto' }}
{% else %}
{{ this.attributes.climate }}
{% endif %}
curtains: >
{% if woonkamer_cube_event and this.state == 'curtains' and trigger.event.data.command not in ['shake','flip'] %}
{{ 'manual' }}
{% elif woonkamer_cube_reset or (this.state == 'curtains' and trigger.event.data.command == 'shake') %}
{{ 'auto' }}
{% else %}
{{ this.attributes.curtains }}
{% endif %}
power: >
{% if woonkamer_cube_event and this.state == 'power' and 'rotate' in trigger.event.data.command %}
{% if this.attributes.power == 'bioscoop' %}
{{ '' }}
{% else %}
{{ 'bioscoop' }}
{% endif %}
{% elif woonkamer_cube_reset or (this.state == 'power' and trigger.event.data.command == 'shake') %}
{{ '' }}
{% else %}
{{ this.attributes.power }}
{% endif %}
What I tried and failed to do is a cube_face variable to hold what I currently do to set state.
And use cube_face instead of this.state (which is old) to update my attributes.
This way, if the cube awakes I can for instance ignore all rotation events until one of the other events has occured to first determine for sure which face is up.