diff --git a/devdi b/devdi index 773d0a6..5a94efb 160000 --- a/devdi +++ b/devdi @@ -1 +1 @@ -Subproject commit 773d0a6679810b365bbd4537156c513b0f496c5a +Subproject commit 5a94efbc8c4ca7e1a7ef6f40df53177717bb7c16 diff --git a/devices/__init__.py b/devices/__init__.py index 30802ee..edde23e 100644 --- a/devices/__init__.py +++ b/devices/__init__.py @@ -1,14 +1,14 @@ from devices.brennenstuhl import vlv as brennenstuhl_heatingvalve -from devices.livarno import sw as silvercrest_powerplug -from devices.livarno import sw_br_ct as livarno_sw_br_ct +from devices.silvercrest import sw as silvercrest_powerplug +from devices.silvercrest import sw_br_ct as livarno_sw_br_ct +from devices.silvercrest import motion_sensor as silvercrest_motion_sensor from devices.my import powerplug as my_powerplug from devices.shelly import shelly_sw1 from devices.tradfri import sw as tradfri_sw from devices.tradfri import sw_br as tradfri_sw_br from devices.tradfri import sw_br_ct as tradfri_sw_br_ct +from devices.tradfri import button as tradfri_button -tradfri_button = None -silvercrest_motion_sensor = None audio_status = None remote = None diff --git a/devices/livarno.py b/devices/livarno.py deleted file mode 100644 index 2aed307..0000000 --- a/devices/livarno.py +++ /dev/null @@ -1,14 +0,0 @@ -from devices.tradfri import sw as tradfri_sw -from devices.tradfri import sw_br_ct as tradfri_sw_br_ct - - -class sw(tradfri_sw): - pass - - -class sw_br_ct(tradfri_sw_br_ct): - def set_state(self, value): - self.__set__("state", "on" if value else "off") - - def power_on_action(self): - self["state"] = "on" diff --git a/devices/silvercrest.py b/devices/silvercrest.py new file mode 100644 index 0000000..06eb513 --- /dev/null +++ b/devices/silvercrest.py @@ -0,0 +1,56 @@ +from devices.base import base +from devices.tradfri import sw as tradfri_sw +from devices.tradfri import sw_br_ct as tradfri_sw_br_ct +import json + + +class sw(tradfri_sw): + pass + + +class sw_br_ct(tradfri_sw_br_ct): + def set_state(self, value): + self.__set__("state", "on" if value else "off") + + def power_on_action(self): + self["state"] = "on" + + +class motion_sensor(base): + """ Communication (MQTT) + + silvercrest_motion_sensor { + battery: [0...100] % + battery_low: [True, False] + linkquality: [0...255] lqi + occupancy: [True, False] + tamper: [True, False] + voltage: [0...] mV + } + """ + KEY_BATTERY = "battery" + KEY_BATTERY_LOW = "battery_low" + KEY_LINKQUALITY = "linkquality" + KEY_OCCUPANCY = "occupancy" + KEY_UNMOUNTED = "tamper" + KEY_VOLTAGE = "voltage" + # + PROPERTIES = [KEY_OCCUPANCY, KEY_UNMOUNTED] + + def __init__(self, mqtt_client, topic, **kwargs): + super().__init__(mqtt_client, topic, **kwargs) + # + self[self.KEY_OCCUPANCY] = False + # + cmd_base = self.topic.replace('/', '.') + '.' + self.user_cmds = { + cmd_base + 'toggle_occupancy': self.__ui_toggle_occupancy__, + } + + def send_device_status(self): + self.logger.info("Sending status: %s", repr(self)) + self.mqtt_client.send(self.topic, json.dumps(self)) + + def __ui_toggle_occupancy__(self, *args): + self.__set__(self.KEY_OCCUPANCY, not self.get(self.KEY_OCCUPANCY)) + self.send_device_status() diff --git a/devices/tradfri.py b/devices/tradfri.py index 6026576..8e1ae67 100644 --- a/devices/tradfri.py +++ b/devices/tradfri.py @@ -41,6 +41,8 @@ tradfri devices from devices.base import base import json +import task +import time class sw(base): @@ -106,12 +108,29 @@ class sw_br(sw): """ PROPERTIES = sw.PROPERTIES + [ "brightness", + "brightness_move", ] def __init__(self, mqtt_client, topic): super().__init__(mqtt_client, topic) + self.task = task.periodic(0.1, self.__task__) + self.task.run() + # self["brightness"] = 64 + def __task__(self, rt): + db = self.get('brightness_move', 0) + if db != 0: + b = self["brightness"] + b += (db / 10) + if b < 0: + b = 0 + elif b > 254: + b = 254 + if b != self["brightness"]: + self["brightness"] = b + self.send_device_status() + class sw_br_ct(sw_br): """A tradfri device with switching, brightness and colortemp functionality @@ -127,3 +146,118 @@ class sw_br_ct(sw_br): def __init__(self, mqtt_client, topic): super().__init__(mqtt_client, topic) self["color_temp"] = 413 + + +class button(base): + """ Communication (MQTT) + + tradfri_button { + "action": [ + "arrow_left_click", + "arrow_left_hold", + "arrow_left_release", + "arrow_right_click", + "arrow_right_hold", + "arrow_right_release", + "brightness_down_click", + "brightness_down_hold", + "brightness_down_release", + "brightness_up_click", + "brightness_up_hold", + "brightness_up_release", + "toggle" + ] + "action_duration": [0...] s + "battery": [0...100] % + "linkquality": [0...255] lqi + "update": [] + } + """ + ACTION_TOGGLE = "toggle" + ACTION_BRIGHTNESS_UP = "brightness_up_click" + ACTION_BRIGHTNESS_DOWN = "brightness_down_click" + ACTION_RIGHT = "arrow_right_click" + ACTION_LEFT = "arrow_left_click" + ACTION_BRIGHTNESS_UP_LONG = "brightness_up_hold" + ACTION_BRIGHTNESS_UP_RELEASE = "brightness_up_release" + ACTION_BRIGHTNESS_DOWN_LONG = "brightness_down_hold" + ACTION_BRIGHTNESS_DOWN_RELEASE = "brightness_down_release" + ACTION_RIGHT_LONG = "arrow_right_hold" + ACTION_RIGHT_RELEASE = "arrow_right_release" + ACTION_LEFT_LONG = "arrow_left_hold" + ACTION_LEFT_RELEASE = "arrow_left_release" + ACTION_RELEASE = { + ACTION_BRIGHTNESS_DOWN_LONG: ACTION_BRIGHTNESS_DOWN_RELEASE, + ACTION_BRIGHTNESS_UP_LONG: ACTION_BRIGHTNESS_UP_RELEASE, + ACTION_LEFT_LONG: ACTION_LEFT_RELEASE, + ACTION_RIGHT_LONG: ACTION_RIGHT_RELEASE + } + # + KEY_LINKQUALITY = "linkquality" + KEY_BATTERY = "battery" + KEY_ACTION = "action" + KEY_ACTION_DURATION = "action_duration" + + def __init__(self, mqtt_client, topic, **kwargs): + super().__init__(mqtt_client, topic, **kwargs) + self.__device_in_use__ = False + # + cmd_base = self.topic.replace('/', '.') + '.' + self.user_cmds = { + cmd_base + 'toggle': self.__ui_button_toggle__, + cmd_base + 'left': self.__ui_button_left__, + cmd_base + 'left_long': self.__ui_button_left_long__, + cmd_base + 'right': self.__ui_button_right__, + cmd_base + 'right_long': self.__ui_button_right_long__, + cmd_base + 'up': self.__ui_button_up__, + cmd_base + 'up_long': self.__ui_button_up_long__, + cmd_base + 'down': self.__ui_button_down__, + cmd_base + 'down_long': self.__ui_button_down_long__, + } + + def send_device_status(self, data): + self.logger.info("Sending status: %s", repr(data)) + self.mqtt_client.send(self.topic, json.dumps(data)) + + def __ui_button_toggle__(self, *args): + self.send_device_status({self.KEY_ACTION: self.ACTION_TOGGLE}) + + def __ui_button_left__(self, *args): + self.send_device_status({self.KEY_ACTION: self.ACTION_LEFT}) + + def __ui_button_left_long__(self, *args): + self.__ui_button_long_press__(self.ACTION_LEFT_LONG, *args) + + def __ui_button_right__(self, *args): + self.send_device_status({self.KEY_ACTION: self.ACTION_RIGHT}) + + def __ui_button_right_long__(self, *args): + self.__ui_button_long_press__(self.ACTION_RIGHT_LONG, *args) + + def __ui_button_up__(self, *args): + self.send_device_status({self.KEY_ACTION: self.ACTION_BRIGHTNESS_UP}) + + def __ui_button_up_long__(self, *args): + self.__ui_button_long_press__(self.ACTION_BRIGHTNESS_UP_LONG, *args) + + def __ui_button_down__(self, *args): + self.send_device_status({self.KEY_ACTION: self.ACTION_BRIGHTNESS_DOWN}) + + def __ui_button_down_long__(self, *args): + self.__ui_button_long_press__(self.ACTION_BRIGHTNESS_DOWN_LONG, *args) + + def __ui_button_long_press__(self, action, *args): + try: + dt = float(args[0]) + except (IndexError, ValueError): + print("You need to give a numeric argument to define the period.") + else: + if not self.__device_in_use__: + self.__device_in_use__ = True + self.send_device_status({self.KEY_ACTION: action}) + time.sleep(dt) + self.send_device_status({self.KEY_ACTION: self.ACTION_RELEASE[action]}) + self.__device_in_use__ = False + + def __ui_button_long_release__(self): + self.__device_in_use__ = False diff --git a/home.py b/home.py index 9208aa9..9d9359c 100644 --- a/home.py +++ b/home.py @@ -1,4 +1,4 @@ -import devdi.props as props +from devdi import topic as props def functions(pd): diff --git a/home_emulation.py b/home_emulation.py index c58d896..a06c156 100644 --- a/home_emulation.py +++ b/home_emulation.py @@ -1,5 +1,5 @@ import config -import devdi +import devdi.devices import home import logging import mqtt @@ -7,7 +7,6 @@ import os import report import user_interface -# TODO: Add some more ui commands for devices # TODO: Add some test for smart_brain # TODO: Implementation of missing devices in devices/__init__.py @@ -33,7 +32,7 @@ if __name__ == "__main__": # # Smarthome physical Devices # - pd = devdi.physical_devices(mc) + pd = devdi.devices.physical_devices(mc) # # Smart Home Functionality