Event information deconz with Xiaomi Cube

Ah I understand. Did you try my suggestion for listening to all events? Try something like this below

def initialize(self) -> None:
    self.listen_event(self.action,
                      "deconz_event")

def action(self, event_name: str, data: dict, kwargs: dict) -> None:
    self.log(event_name)
    self.log(data)

This should put all the data for all deconz events in the log file.

I never did an appdaemon app (I do have hadashboard though).
I just create an app with that code under appdaemon/app and restart appdaemon?

Is it possible to put it in a separate log (my home assistant log is huge).

Tried but error
2019-02-02 16:17:00.842949 WARNING AppDaemon: No app description found for: /config/appdaemon/apps/deconz_event.py - ignoring

appdaemon has its own logging, which you set in appdaemon.yaml

every app you create also needs a yaml part to activate it.
if you want to learn the basics from creating apps then you can learn it here:

Ah I thought you want an appdaemon app because we are in the appdaemon section here :wink:

Check out the deconz component page, everything is explained there. Appdaemon or normal hass automation etc.

For the appdaemon app, I will not explain ypu how to create an app from scratch, please use the official documentation for this.

Thank you, will look at it

Hi I created a appdaemon app that creates an entity in Home-Assistant. But instead of the action to update the state of the sensor.aqara_cube you can off course put anything you like. Below is what I have now. Until now I have not yet took the time to think of actions I want on the different gestures there are with the cube. It might help you with setting it up.

import appdaemon.plugins.hass.hassapi as hass
import datetime
from datetime import datetime

class CubeControl(hass.Hass):

    def initialize(self):
        if 'event' in self.args:
            self.listen_event(self.handle_event, self.args['event'])

    def handle_event(self, event_name, data, kwargs):
        event_data = data["event"]
        event_id = data["id"]
        event_received = datetime.now()
        if data['id'] == self.args['id']:
            self.log(data['event'])
            if data['event'] in [1000, 2000, 3000, 4000, 5000, 6000]:
                self.set_state("sensor.aqara_cube", state = 'slide', attributes = {"event_data": event_data, "event_received": str(event_received)})
            elif data['event'] in [1001, 2002, 3003, 4004, 5005, 6006]:
                self.set_state("sensor.aqara_cube", state = 'double tap', attributes = {"event_data": event_data, "event_received": str(event_received)})
            elif data['event'] in [1006, 2005, 3004, 4003, 5002, 6001]:
                self.set_state("sensor.aqara_cube", state = 'flip180', attributes = {"event_data": event_data, "event_received": str(event_received)})
            elif data['event'] in [1002, 1003, 1004, 1005, 2001, 2003, 2004, 2006, 3001, 3002, 3005, 3006, 4001, 4002, 4005, 4006, 5001, 5003, 5004, 5006, 6002, 6003, 6004, 6005]:
                self.set_state("sensor.aqara_cube", state = 'flip90', attributes = {"event_data": event_data, "event_received": str(event_received)})
            elif data['event'] == 7007:
                self.set_state("sensor.aqara_cube", state = 'shake', attributes = {"event_data": event_data, "event_received": str(event_received)})
            elif data['event'] == 7008:
                self.set_state("sensor.aqara_cube", state = 'fall', attributes = {"event_data": event_data, "event_received": str(event_received)})                              
            elif data['event'] == 7000:
                self.set_state("sensor.aqara_cube", state = 'wake', attributes = {"event_data": event_data, "event_received": str(event_received)})
            elif len(str(event_data)) != 4 or str(event_data)[1:3] != '00':
                if data['event'] > 0:
                    self.set_state("sensor.aqara_cube", state = 'rotate cw', attributes = {"event_data": event_data, "event_received": str(event_received)})
                elif data['event'] < 0:                                 
                    self.set_state("sensor.aqara_cube", state = 'rotate ccw', attributes = {"event_data": event_data, "event_received": str(event_received)})'''
6 Likes

I did the same thing but with templates instead of AppDaemon. Anyway there is something to fix in deCONZ event handling behaviour inside of corresponding component, so users will not have to worry about it.

What needs to be fixed with the deconz event handling behaviour?
Everything works perfectly fine for me with deconz.

Aqara cube. Rotation and sides switches in events are with the same id. So I can’t just use trigger.event.data.event > 0 in templates for positive rotation and < 0 for negative. Because if I switch the cube from 6 to 1 side, it gives me the 6001 code, which will be recognized as positive rotation, because the event will be with the same id in event.data.
deCONZ sends events with different sensor IDs. So I can differ one from another one if I use deCONZ rest API directly.

Aha I understand. I don’t use the aqara cube, I thought you were talking about the event handling in general, sorry for the confusion.

Is there nothing else in the event data only the 4 digit key?

event.data is something like

{
  "id": "mi_cube",
  "event": "3003"
}

if I rotate the cube to the right for 30.03 degrees (it is degrees, I guess).
The same data for double tapping cube on the side 3.

Ah okay. So maybe you could talk to the developer of the deconz component to include the sensor id in the data of the event.

1 Like

That is why I am using appdaemon for it instead of templates, the last two lines of the code are for the rotation.

Thank you for sharing! After a day of reading and testing it finally works. But now I am not sure whats the best way to use these events. Right now I can only toggle lights, but it would be great to adjust the brightness by rotating.

        elif len(str(event_data)) != 4 or str(event_data)[1:3] != '00':
            if data['event'] > 0:
                self.set_state("sensor.aqara_cube", state = 'rotate cw', attributes = {"event_data": event_data, "event_received": str(event_received)})
                self.set_state("light.desk", state= 'on', attributes = {"brightness": 252})
            elif data['event'] < 0:
                self.set_state("sensor.aqara_cube", state = 'rotate ccw', attributes = {"event_data": event_data, "event_received": str(event_received)})
                self.turn_on("light.desk")

Using the turn_on action works flawlessly, so I thought I could also just use set_state to adjust the brightness (in a static way at first), but the changes will not “stick”. I can see the brightness attribute change in dev tools, but only for some seconds. The actual lamp is not affected.

I am (fairly) new to Home Assistant and its my first time using appdaemon, so any help would be appreciated. Should I use these events from your app for regular automations and if so, whats the right way to handle rotation events?

Update:
Rotate to adjust brightness now works, so here is the snippet:

            elif len(str(event_data)) != 4 or str(event_data)[1:3] != '00':
            if data['event'] > 0:

                if self.entities.light.desk.state != 'off':
                    self.cur_brightness = self.entities.light.desk.attributes.brightness
                else:
                    self.cur_brightness = 0
                self.new_brightness = (data['event'] // 300) + self.cur_brightness
                if self.new_brightness >= 255:
                    self.new_brightness = 255
                elif self.new_brightness <= 0:
                    self.new_brightness = 0
                if self.new_brightness == 0:
                    self.turn_off('light.desk')
                else:
                    self.turn_on('light.desk', brightness = self.new_brightness)

            elif data['event'] < 0:

                if self.entities.light.desk.state != 'off':
                    self.cur_brightness = self.entities.light.desk.attributes.brightness
                else:
                    self.cur_brightness = 0
                self.new_brightness = (data['event'] // 300) + self.cur_brightness
                if self.new_brightness >= 255:
                    self.new_brightness = 255
                elif self.new_brightness <= 0:
                    self.new_brightness = 0
                if self.new_brightness == 0:
                    self.turn_off('light.desk')
                else:
                    self.turn_on('light.desk', brightness = self.new_brightness)

I know that the code is repetitive, so any help for decoupling into a seperate function is appreciated - these are my first steps with python. But since it is working, I leave it here.

Can you please show your whole code?

Does this really work?
self.cur_brightness = self.entities.light.desk.attributes.brightness?
I don’t think that this works, you haven’t declared self.entities anywhere. Are there no errors in the logs?

Thats right. I did not declare entities, at least not knowingly, and currently there are no errors. Everything works as aspected and when i logged cur_brightness it printed the same value as seen in dev tools.

import appdaemon.plugins.hass.hassapi as hass
import datetime
from datetime import datetime

class CubeControl(hass.Hass):

def initialize(self):
    if 'event' in self.args:
        self.listen_event(self.handle_event, self.args['event'])
        self.log('CubeControl running')

def handle_event(self, event_name, data, kwargs):
    event_data = data['event']
    event_id = data['id']
    event_received = datetime.now()
    if data['id'] == self.args['id']:
        self.log(data['event'])
        if data['event'] in [1000, 2000, 3000, 4000, 5000, 6000]:
            self.set_state('sensor.aqara_cube', state = 'slide', attributes = {'event_data': event_data, 'event_received': str(event_received)})
            # self.toggle('light.bedroombulb')
        elif data['event'] in [1001, 2002, 3003, 4004, 5005, 6006]:
            self.set_state('sensor.aqara_cube', state = 'double tap', attributes = {'event_data': event_data, 'event_received': str(event_received)})
        elif data['event'] in [1006, 2005, 3004, 4003, 5002, 6001]:
            self.set_state('sensor.aqara_cube', state = 'flip180', attributes = {'event_data': event_data, 'event_received': str(event_received)})
            self.toggle('light.bedroombulb')
        elif data['event'] in [1002, 1003, 1004, 1005, 2001, 2003, 2004, 2006, 3001, 3002, 3005, 3006, 4001, 4002, 4005, 4006, 5001, 5003, 5004, 5006, 6002, 6003, 6004, 6005]:
            self.set_state('sensor.aqara_cube', state = 'flip90', attributes = {'event_data': event_data, 'event_received': str(event_received)})
            self.toggle('light.bedroom')
        elif data['event'] == 7007:
            self.set_state('sensor.aqara_cube', state = 'shake', attributes = {'event_data': event_data, 'event_received': str(event_received)})
            self.turn_off('group.all_lights')
        elif data['event'] == 7008:
            self.set_state('sensor.aqara_cube', state = 'fall', attributes = {'event_data': event_data, 'event_received': str(event_received)})
        elif data['event'] == 7000:
            self.set_state('sensor.aqara_cube', state = 'wake', attributes = {'event_data': event_data, 'event_received': str(event_received)})
        elif len(str(event_data)) != 4 or str(event_data)[1:3] != '00':
            if data['event'] > 0:
                if self.entities.light.bedroombulb.state != 'off':
                    self.cur_brightness = self.entities.light.bedroombulb.attributes.brightness
                else:
                    self.cur_brightness = 0
                self.new_brightness = (data['event'] // 300) + self.cur_brightness
                if self.new_brightness >= 255:
                    self.new_brightness = 255
                elif self.new_brightness <= 0:
                    self.new_brightness = 0
                if self.new_brightness == 0:
                    self.turn_off('light.bedroombulb')
                else:
                    self.turn_on('light.bedroombulb', brightness = self.new_brightness)
            elif data['event'] < 0:
                if self.entities.light.bedroombulb.state != 'off':
                    self.cur_brightness = self.entities.light.bedroombulb.attributes.brightness
                else:
                    self.cur_brightness = 0
                self.new_brightness = (data['event'] // 300) + self.cur_brightness
                if self.new_brightness >= 255:
                    self.new_brightness = 255
                elif self.new_brightness <= 0:
                    self.new_brightness = 0
                if self.new_brightness == 0:
                    self.turn_off('light.bedroombulb')
                else:
                    self.turn_on('light.bedroombulb', brightness = self.new_brightness)

This is pretty much the same code as above, with the rotation block (found in another thread) pasted in between.

Try this for the brightness part. I hope it is what you want.

    elif len(str(event_data)) != 4 or str(event_data)[1:3] != '00':
        cur_brightness = self.get_state('light.bedroombulb',
                                        attribute='brightness') or 0
        if data['event'] > 0:
            new_brightness = (data['event'] // 300) + cur_brightness

            if new_brightness > 255:
                new_brightness = 255
            self.turn_on('light.bedroombulb', brightness=new_brightness)
        elif data['event'] < 0:
            new_brightness = (data['event'] // 300) - cur_brightness
            if new_brightness <= 0:
                self.turn_off('light.bedroombulb')
            else:
                self.turn_on('light.bedroombulb', brightness=new_brightness)

There is a small error in the second line, it should be
self.cur_brightness = self.get_state(‘light.bedroombulb’, attribute=‘brightness’) or 0

Without self there will be following error:
AttributeError: ‘CubeControl’ object has no attribute ‘cur_brightness’

Otherwise it works as expected and is much cleaner. Thanks for your help!

is a basic part from AD since AD 3
but its still rarely used.

Thanks for the info.
Interesting, didn’t know about that.Looks like I overread this in the documentation.