Hue device (kitchen) and silvercrest button added as device
This commit is contained in:
parent
fd546ffcc3
commit
024877d2b3
2
devdi
2
devdi
@ -1 +1 @@
|
|||||||
Subproject commit 118e80f070072d7ac65531bfdf316baf04901a9a
|
Subproject commit 619d7f926f13ce03950db9c5dab3461e5b7da23a
|
114
device_development.py
Normal file
114
device_development.py
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
import config
|
||||||
|
import mqtt
|
||||||
|
import readline
|
||||||
|
import sys
|
||||||
|
import report
|
||||||
|
import logging
|
||||||
|
import devices
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
report.stdoutLoggingConfigure([[config.APP_NAME, logging.INFO], ], fmt=report.SHORT_FMT)
|
||||||
|
mc = mqtt.mqtt_client(
|
||||||
|
host=config.MQTT_SERVER,
|
||||||
|
port=config.MQTT_PORT,
|
||||||
|
username=config.MQTT_USER,
|
||||||
|
password=config.MQTT_PASSWORD,
|
||||||
|
name=config.APP_NAME + '_devicetest'
|
||||||
|
)
|
||||||
|
#
|
||||||
|
devicedict = {}
|
||||||
|
for device in [
|
||||||
|
# devices.shelly_pro3(mc, "shellies/gfw/pro3"),
|
||||||
|
# devices.brennenstuhl_heatingvalve(mc, "zigbee_raspi/heatvlv"),
|
||||||
|
# devices.silvercrest_button(mc, "zigbee_raspi/button"),
|
||||||
|
devices.hue_sw_br_ct(mc, "zigbee_ffe/kitchen/main_light_1"),
|
||||||
|
]:
|
||||||
|
devicedict[device.topic.replace("/", "_")] = device
|
||||||
|
#
|
||||||
|
COMMANDS = ['quit', 'help', 'action']
|
||||||
|
for key in devicedict:
|
||||||
|
device = devicedict[key]
|
||||||
|
for cmd in device.__class__.__dict__:
|
||||||
|
obj = getattr(device, cmd)
|
||||||
|
if callable(obj) and not cmd.startswith("_"):
|
||||||
|
COMMANDS.append(key + "." + cmd)
|
||||||
|
#
|
||||||
|
|
||||||
|
def reduced_list(text):
|
||||||
|
"""
|
||||||
|
Create reduced completation list
|
||||||
|
"""
|
||||||
|
reduced_list = {}
|
||||||
|
for cmd in COMMANDS:
|
||||||
|
next_dot = cmd[len(text):].find('.')
|
||||||
|
if next_dot >= 0:
|
||||||
|
reduced_list[cmd[:len(text) + next_dot + 1]] = None
|
||||||
|
else:
|
||||||
|
reduced_list[cmd] = None
|
||||||
|
return reduced_list.keys()
|
||||||
|
|
||||||
|
def completer(text, state):
|
||||||
|
"""
|
||||||
|
Our custom completer function
|
||||||
|
"""
|
||||||
|
options = [x for x in reduced_list(text) if x.startswith(text)]
|
||||||
|
return options[state]
|
||||||
|
|
||||||
|
def complete(text, state):
|
||||||
|
for cmd in COMMANDS:
|
||||||
|
if cmd.startswith(text):
|
||||||
|
if not state:
|
||||||
|
hit = ""
|
||||||
|
index = 0
|
||||||
|
sub_list = cmd.split('.')
|
||||||
|
while len(text) >= len(hit):
|
||||||
|
hit += sub_list[index] + '.'
|
||||||
|
return hit # cmd
|
||||||
|
else:
|
||||||
|
state -= 1
|
||||||
|
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
readline.parse_and_bind("tab: complete")
|
||||||
|
readline.set_completer(completer)
|
||||||
|
print("\nEnter command: ")
|
||||||
|
while True:
|
||||||
|
userfeedback = input('')
|
||||||
|
command = userfeedback.split(' ')[0]
|
||||||
|
if userfeedback == 'quit':
|
||||||
|
break
|
||||||
|
elif userfeedback == 'help':
|
||||||
|
print("Help is not yet implemented!")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
key, command = userfeedback.split(".", 1)
|
||||||
|
except ValueError:
|
||||||
|
print("Unknown device.")
|
||||||
|
else:
|
||||||
|
device = devicedict[key]
|
||||||
|
try:
|
||||||
|
command, params = command.split(" ", 1)
|
||||||
|
except ValueError:
|
||||||
|
params = None
|
||||||
|
try:
|
||||||
|
obj = getattr(device, command)
|
||||||
|
except AttributeError:
|
||||||
|
print("Unknown command.")
|
||||||
|
else:
|
||||||
|
if params is not None:
|
||||||
|
params = params.replace("True", "true")
|
||||||
|
params = params.replace("False", "false")
|
||||||
|
params = params.replace("None", "null")
|
||||||
|
params = params.replace(",", " ")
|
||||||
|
params = params.split(" ")
|
||||||
|
params = " ".join([p for p in params if p])
|
||||||
|
try:
|
||||||
|
params = json.loads("[" + params.replace(" ", ", ") + "]")
|
||||||
|
except json.decoder.JSONDecodeError:
|
||||||
|
print("You need to give python like parameters (e.g. 'test' for a string containing test).")
|
||||||
|
params = None
|
||||||
|
try:
|
||||||
|
obj(*params)
|
||||||
|
except TypeError:
|
||||||
|
print("Give the correct parameters to execute.")
|
@ -33,12 +33,14 @@ except ImportError:
|
|||||||
|
|
||||||
from devices.shelly import shelly as shelly_sw1
|
from devices.shelly import shelly as shelly_sw1
|
||||||
from devices.shelly import shelly_rpc as shelly_pro3
|
from devices.shelly import shelly_rpc as shelly_pro3
|
||||||
|
from devices.hue import hue_light as hue_sw_br_ct
|
||||||
from devices.tradfri import tradfri_light as tradfri_sw
|
from devices.tradfri import tradfri_light as tradfri_sw
|
||||||
from devices.tradfri import tradfri_light as tradfri_sw_br
|
from devices.tradfri import tradfri_light as tradfri_sw_br
|
||||||
from devices.tradfri import tradfri_light as tradfri_sw_br_ct
|
from devices.tradfri import tradfri_light as tradfri_sw_br_ct
|
||||||
from devices.tradfri import tradfri_button as tradfri_button
|
from devices.tradfri import tradfri_button as tradfri_button
|
||||||
from devices.tradfri import tradfri_light as livarno_sw_br_ct
|
from devices.tradfri import tradfri_light as livarno_sw_br_ct
|
||||||
from devices.brennenstuhl import brennenstuhl_heatingvalve
|
from devices.brennenstuhl import brennenstuhl_heatingvalve
|
||||||
|
from devices.silvercrest import silvercrest_button
|
||||||
from devices.silvercrest import silvercrest_powerplug
|
from devices.silvercrest import silvercrest_powerplug
|
||||||
from devices.silvercrest import silvercrest_motion_sensor
|
from devices.silvercrest import silvercrest_motion_sensor
|
||||||
from devices.mydevices import powerplug as my_powerplug
|
from devices.mydevices import powerplug as my_powerplug
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
from devices.base import base
|
from devices.base import base
|
||||||
import json
|
|
||||||
import task
|
import task
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
118
devices/hue.py
Normal file
118
devices/hue.py
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
from devices.base import base, base_output
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
class hue_light(base_output):
|
||||||
|
""" Communication (MQTT)
|
||||||
|
|
||||||
|
hue_light {
|
||||||
|
| "state": ["ON" / "OFF" / "TOGGLE"]
|
||||||
|
| "linkquality": [0...255] lqi
|
||||||
|
| "brightness": [0...254]
|
||||||
|
| "color_mode": ["color_temp"]
|
||||||
|
| "color_temp": ["coolest", "cool", "neutral", "warm", "warmest", 250...454]
|
||||||
|
| }
|
||||||
|
+- get {
|
||||||
|
| "state": ""
|
||||||
|
| }
|
||||||
|
+- set {
|
||||||
|
"state": ["ON" / "OFF"]
|
||||||
|
"brightness": [0...256]
|
||||||
|
"color_temp": [250...454]
|
||||||
|
"transition": [0...] seconds
|
||||||
|
"brightness_move": [-X...0...X] X/s
|
||||||
|
"brightness_step": [-X...0...X]
|
||||||
|
"color_temp_move": [-X...0...X] X/s
|
||||||
|
"color_temp_step": [-X...0...X]
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
KEY_LINKQUALITY = "linkquality"
|
||||||
|
KEY_OUTPUT_0 = "state"
|
||||||
|
KEY_BRIGHTNESS = "brightness"
|
||||||
|
KEY_COLOR_TEMP = "color_temp"
|
||||||
|
#
|
||||||
|
TX_TYPE = base.TX_DICT
|
||||||
|
TX_FILTER_DATA_KEYS = [KEY_OUTPUT_0, KEY_BRIGHTNESS, KEY_COLOR_TEMP]
|
||||||
|
STATE_KEYS = TX_FILTER_DATA_KEYS
|
||||||
|
#
|
||||||
|
RX_KEYS = [KEY_LINKQUALITY, KEY_OUTPUT_0, KEY_BRIGHTNESS, KEY_COLOR_TEMP]
|
||||||
|
RX_IGNORE_KEYS = ['update', 'color_mode']
|
||||||
|
RX_FILTER_DATA_KEYS = [KEY_OUTPUT_0, KEY_BRIGHTNESS, KEY_COLOR_TEMP]
|
||||||
|
|
||||||
|
def __state_logging__(self, inst, key, data):
|
||||||
|
if key in [self.KEY_OUTPUT_0, self.KEY_BRIGHTNESS, self.KEY_COLOR_TEMP]:
|
||||||
|
self.logger.info("State change of '%s' to '%s'", key, repr(data))
|
||||||
|
|
||||||
|
def __device_to_instance_filter__(self, key, data):
|
||||||
|
if key == self.KEY_BRIGHTNESS:
|
||||||
|
return int(round((data - 1) * 100 / 253, 0))
|
||||||
|
elif key == self.KEY_COLOR_TEMP:
|
||||||
|
return int(round((data - 250) * 10 / 204, 0))
|
||||||
|
return super().__device_to_instance_filter__(key, data)
|
||||||
|
|
||||||
|
def __instance_to_device_filter__(self, key, data):
|
||||||
|
if key == self.KEY_BRIGHTNESS:
|
||||||
|
return int(round(data * 253 / 100 + 1, 0))
|
||||||
|
elif key == self.KEY_COLOR_TEMP:
|
||||||
|
return int(round(data * 204 / 10 + 250, 0))
|
||||||
|
return super().__instance_to_device_filter__(key, data)
|
||||||
|
|
||||||
|
#
|
||||||
|
# RX
|
||||||
|
#
|
||||||
|
@property
|
||||||
|
def output_0(self):
|
||||||
|
"""rv: [True, False]"""
|
||||||
|
return self.get(self.KEY_OUTPUT_0, False)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def linkquality(self):
|
||||||
|
"""rv: numeric value"""
|
||||||
|
return self.get(self.KEY_LINKQUALITY, 0)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def brightness(self):
|
||||||
|
"""rv: numeric value [0%, ..., 100%]"""
|
||||||
|
return self.get(self.KEY_BRIGHTNESS, 0)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def color_temp(self):
|
||||||
|
"""rv: numeric value [0, ..., 10]"""
|
||||||
|
return self.get(self.KEY_COLOR_TEMP, 0)
|
||||||
|
|
||||||
|
#
|
||||||
|
# TX
|
||||||
|
#
|
||||||
|
def request_data(self, device=None, key=None, data=None):
|
||||||
|
self.mqtt_client.send(self.topic + "/set", '{"hue_power_on_behavior": "recover"}')
|
||||||
|
|
||||||
|
def set_output_0(self, state):
|
||||||
|
"""state: [True, False]"""
|
||||||
|
self.send_command(self.KEY_OUTPUT_0, state)
|
||||||
|
|
||||||
|
def set_output_0_mcb(self, device, key, data):
|
||||||
|
self.set_output_0(data)
|
||||||
|
|
||||||
|
def toggle_output_0_mcb(self, device, key, data):
|
||||||
|
self.set_output_0(not self.output_0)
|
||||||
|
|
||||||
|
def set_brightness(self, brightness):
|
||||||
|
"""brightness: [0, ..., 100]"""
|
||||||
|
self.send_command(self.KEY_BRIGHTNESS, brightness)
|
||||||
|
|
||||||
|
def set_brightness_mcb(self, device, key, data):
|
||||||
|
self.set_brightness(data)
|
||||||
|
|
||||||
|
def set_color_temp(self, color_temp):
|
||||||
|
"""color_temp: [0, ..., 10]"""
|
||||||
|
self.send_command(self.KEY_COLOR_TEMP, color_temp)
|
||||||
|
|
||||||
|
def set_color_temp_mcb(self, device, key, data):
|
||||||
|
self.set_color_temp(data)
|
||||||
|
|
||||||
|
def __all_off__(self):
|
||||||
|
if self.output_0:
|
||||||
|
self.set_output_0(False)
|
@ -65,8 +65,8 @@ class shelly(base_output):
|
|||||||
super().__init__(mqtt_client, topic)
|
super().__init__(mqtt_client, topic)
|
||||||
#
|
#
|
||||||
self.output_key_delayed = None
|
self.output_key_delayed = None
|
||||||
self.delayed_flash_task = task.delayed(0.3, self.flash_task)
|
self.delayed_flash_task = task.delayed(0.75, self.flash_task)
|
||||||
self.delayed_off_task = task.delayed(0.3, self.off_task)
|
self.delayed_off_task = task.delayed(0.75, self.off_task)
|
||||||
#
|
#
|
||||||
self.all_off_requested = False
|
self.all_off_requested = False
|
||||||
|
|
||||||
|
@ -5,6 +5,47 @@ from devices.base import base, base_output
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
class silvercrest_button(base):
|
||||||
|
""" Communication (MQTT)
|
||||||
|
|
||||||
|
tradfri_button {
|
||||||
|
"action": ["pressed"]
|
||||||
|
"battery": [0...100] %
|
||||||
|
"battery_low": [true | false]
|
||||||
|
"tamper": [true | false]
|
||||||
|
"linkquality": [0...255] lqi
|
||||||
|
"update": []
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
ACTION_PRESSED = "pressed"
|
||||||
|
#
|
||||||
|
KEY_LINKQUALITY = "linkquality"
|
||||||
|
KEY_BATTERY = "battery"
|
||||||
|
KEY_BATTERY_LOW = "battery_low"
|
||||||
|
KEY_TAMPER = "tamper"
|
||||||
|
KEY_ACTION = "action"
|
||||||
|
#
|
||||||
|
RX_KEYS = [KEY_LINKQUALITY, KEY_BATTERY, KEY_ACTION, KEY_BATTERY_LOW, KEY_TAMPER]
|
||||||
|
|
||||||
|
def __init__(self, mqtt_client, topic):
|
||||||
|
super().__init__(mqtt_client, topic)
|
||||||
|
|
||||||
|
def __state_logging__(self, inst, key, data):
|
||||||
|
if key == self.KEY_ACTION:
|
||||||
|
self.logger.info("Input '%s' with '%s'", key, repr(data))
|
||||||
|
self[self.KEY_ACTION] = None
|
||||||
|
elif key in [self.KEY_BATTERY_LOW, self.KEY_TAMPER]:
|
||||||
|
self.logger.info("Input '%s' with '%s'", key, repr(data))
|
||||||
|
|
||||||
|
#
|
||||||
|
# RX
|
||||||
|
#
|
||||||
|
@property
|
||||||
|
def action(self):
|
||||||
|
"""rv: action_txt"""
|
||||||
|
return self.get(self.KEY_ACTION)
|
||||||
|
|
||||||
|
|
||||||
class silvercrest_powerplug(base_output):
|
class silvercrest_powerplug(base_output):
|
||||||
""" Communication (MQTT)
|
""" Communication (MQTT)
|
||||||
|
|
||||||
|
@ -182,6 +182,7 @@ class tradfri_button(base):
|
|||||||
def __state_logging__(self, inst, key, data):
|
def __state_logging__(self, inst, key, data):
|
||||||
if key in [self.KEY_ACTION]:
|
if key in [self.KEY_ACTION]:
|
||||||
self.logger.info("Input '%s' with '%s'", key, repr(data))
|
self.logger.info("Input '%s' with '%s'", key, repr(data))
|
||||||
|
self[self.KEY_ACTION] = None
|
||||||
|
|
||||||
#
|
#
|
||||||
# RX
|
# RX
|
||||||
|
@ -7,7 +7,7 @@ from devdi import topic as props
|
|||||||
from devices import group
|
from devices import group
|
||||||
from function.db import get_radiator_data, set_radiator_data
|
from function.db import get_radiator_data, set_radiator_data
|
||||||
from function.helpers import day_event
|
from function.helpers import day_event
|
||||||
from function.modules import brightness_choose_n_action, timer_on_activation, heating_function
|
from function.modules import brightness_choose_n_action, timer_on_activation, heating_function, switched_light
|
||||||
from function.rooms import room, room_collection
|
from function.rooms import room, room_collection
|
||||||
from function.videv import videv_switching, videv_switch_brightness, videv_switching_timer, videv_switch_brightness_color_temp, videv_heating, videv_multistate
|
from function.videv import videv_switching, videv_switch_brightness, videv_switching_timer, videv_switch_brightness_color_temp, videv_heating, videv_multistate
|
||||||
import logging
|
import logging
|
||||||
@ -61,6 +61,8 @@ class first_floor_east_kitchen(room):
|
|||||||
# http://shelly1l-8CAAB5616C01
|
# http://shelly1l-8CAAB5616C01
|
||||||
# main light
|
# main light
|
||||||
self.main_light_shelly = pd.get(props.STG_SHE, loc, roo, props.FUN_MAL)
|
self.main_light_shelly = pd.get(props.STG_SHE, loc, roo, props.FUN_MAL)
|
||||||
|
self.main_light_hue = pd.get(props.STG_ZFE, loc, roo, props.FUN_MAL)
|
||||||
|
|
||||||
# http://shelly1-e89f6d85a466
|
# http://shelly1-e89f6d85a466
|
||||||
# circulation pump
|
# circulation pump
|
||||||
self.circulation_pump_shelly = pd.get(props.STG_SHE, loc, roo, props.FUN_CIR)
|
self.circulation_pump_shelly = pd.get(props.STG_SHE, loc, roo, props.FUN_CIR)
|
||||||
@ -75,6 +77,8 @@ class first_floor_east_kitchen(room):
|
|||||||
# circulation pump
|
# circulation pump
|
||||||
self.circulation_pump = timer_on_activation(self.circulation_pump_shelly, self.circulation_pump_shelly.KEY_OUTPUT_0, 10*60)
|
self.circulation_pump = timer_on_activation(self.circulation_pump_shelly, self.circulation_pump_shelly.KEY_OUTPUT_0, 10*60)
|
||||||
self.circulation_pump_shelly.add_callback(self.circulation_pump_shelly.KEY_OUTPUT_0, True, self.main_light_shelly.flash_0_mcb, True)
|
self.circulation_pump_shelly.add_callback(self.circulation_pump_shelly.KEY_OUTPUT_0, True, self.main_light_shelly.flash_0_mcb, True)
|
||||||
|
# Request hue data of lead light after power on
|
||||||
|
switched_light(self.main_light_shelly, self.main_light_shelly.KEY_OUTPUT_0, self.main_light_hue)
|
||||||
# heating function
|
# heating function
|
||||||
self.heating_function = heating_function(
|
self.heating_function = heating_function(
|
||||||
self.heating_valve,
|
self.heating_valve,
|
||||||
@ -87,9 +91,11 @@ class first_floor_east_kitchen(room):
|
|||||||
# Virtual Device Interface
|
# Virtual Device Interface
|
||||||
#
|
#
|
||||||
# main light
|
# main light
|
||||||
self.main_light_videv = videv_switching(
|
self.main_light_videv = videv_switch_brightness_color_temp(
|
||||||
mqtt_client, config.TOPIC_FFE_KITCHEN_MAIN_LIGHT_VIDEV,
|
mqtt_client, config.TOPIC_FFE_KITCHEN_MAIN_LIGHT_VIDEV,
|
||||||
self.main_light_shelly, self.main_light_shelly.KEY_OUTPUT_0
|
self.main_light_shelly, self.main_light_shelly.KEY_OUTPUT_0,
|
||||||
|
self.main_light_hue, self.main_light_hue.KEY_BRIGHTNESS,
|
||||||
|
self.main_light_hue, self.main_light_hue.KEY_COLOR_TEMP
|
||||||
)
|
)
|
||||||
# circulation pump
|
# circulation pump
|
||||||
self.circulation_pump_videv = videv_switching_timer(
|
self.circulation_pump_videv = videv_switching_timer(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user