Compare commits
21 Commits
heat_valve
...
master
Author | SHA1 | Date | |
---|---|---|---|
b9fdd69a62 | |||
024877d2b3 | |||
fd546ffcc3 | |||
3e00f009f8 | |||
9fee0fc216 | |||
4a104a5034 | |||
a0375245b4 | |||
c9bf036591 | |||
248e9432d1 | |||
430a60456d | |||
d25e0167a7 | |||
24297fae5f | |||
3dfdb5803c | |||
8455facb1c | |||
8573dcf43f | |||
985e18e27f | |||
d613c1db5c | |||
48313a2245 | |||
3bc38120c4 | |||
4afb781cf8 | |||
084b340e70 |
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -6,7 +6,7 @@
|
|||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "Python: Main File execution",
|
"name": "Python: Main File execution",
|
||||||
"type": "python",
|
"type": "debugpy",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/smart_brain.py",
|
"program": "${workspaceFolder}/smart_brain.py",
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
|
@ -10,10 +10,10 @@ GEO_POSITION = geo.gps.coordinate(lat=49.519167, lon=9.3672222)
|
|||||||
|
|
||||||
APP_NAME = "smart_brain"
|
APP_NAME = "smart_brain"
|
||||||
|
|
||||||
MQTT_SERVER = "<hostname>"
|
MQTT_SERVER = "{{ smart_srv_brain_hostname }}"
|
||||||
MQTT_PORT = 1883
|
MQTT_PORT = 1883
|
||||||
MQTT_USER = "<username>"
|
MQTT_USER = "{{ smart_srv_brain_username }}"
|
||||||
MQTT_PASSWORD = "<password>"
|
MQTT_PASSWORD = "{{ smart_srv_brain_password }}"
|
||||||
|
|
||||||
|
|
||||||
CHRISTMAS = True
|
CHRISTMAS = True
|
2
devdi
2
devdi
@ -1 +1 @@
|
|||||||
Subproject commit 2e66d0e27416739a8e5c1fa096490882f1b9643c
|
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.")
|
@ -32,17 +32,21 @@ except ImportError:
|
|||||||
ROOT_LOGGER_NAME = 'root'
|
ROOT_LOGGER_NAME = 'root'
|
||||||
|
|
||||||
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.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
|
||||||
from devices.mydevices import audio_status
|
from devices.mydevices import audio_status
|
||||||
from devices.mydevices import remote
|
from devices.mydevices import remote
|
||||||
|
my_ambient = None
|
||||||
|
|
||||||
|
|
||||||
class group(object):
|
class group(object):
|
||||||
|
142
devices/base.py
142
devices/base.py
@ -4,7 +4,6 @@
|
|||||||
from base import mqtt_base
|
from base import mqtt_base
|
||||||
from base import videv_base
|
from base import videv_base
|
||||||
import json
|
import json
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def is_json(data):
|
def is_json(data):
|
||||||
@ -27,17 +26,32 @@ class base(mqtt_base):
|
|||||||
RX_IGNORE_TOPICS = []
|
RX_IGNORE_TOPICS = []
|
||||||
RX_IGNORE_KEYS = []
|
RX_IGNORE_KEYS = []
|
||||||
RX_FILTER_DATA_KEYS = []
|
RX_FILTER_DATA_KEYS = []
|
||||||
|
#
|
||||||
|
CFG_DATA = {}
|
||||||
|
|
||||||
def __init__(self, mqtt_client, topic):
|
def __init__(self, mqtt_client, topic):
|
||||||
super().__init__(mqtt_client, topic, default_values=dict.fromkeys(self.RX_KEYS))
|
super().__init__(mqtt_client, topic, default_values=dict.fromkeys(self.RX_KEYS))
|
||||||
# data storage
|
# data storage
|
||||||
|
self.__cfg_by_mid__ = None
|
||||||
# initialisations
|
# initialisations
|
||||||
mqtt_client.add_callback(topic=self.topic, callback=self.receive_callback)
|
mqtt_client.add_callback(topic=self.topic, callback=self.receive_callback)
|
||||||
mqtt_client.add_callback(topic=self.topic+"/#", callback=self.receive_callback)
|
mqtt_client.add_callback(topic=self.topic+"/#", callback=self.receive_callback)
|
||||||
#
|
#
|
||||||
self.add_callback(None, None, self.__state_logging__, on_change_only=True)
|
self.add_callback(None, None, self.__state_logging__, on_change_only=True)
|
||||||
|
|
||||||
def set(self, key, data, block_callback=[]):
|
def __cfg_callback__(self, key, value, mid):
|
||||||
|
if self.CFG_DATA.get(key) != value and self.__cfg_by_mid__ != mid and mid is not None:
|
||||||
|
self.__cfg_by_mid__ = mid
|
||||||
|
self.logger.warning("Differing configuration identified: Sending default configuration to defice: %s", repr(self.CFG_DATA))
|
||||||
|
if self.TX_TYPE == self.TX_DICT:
|
||||||
|
self.mqtt_client.send(self.topic + '/' + self.TX_TOPIC, json.dumps(self.CFG_DATA))
|
||||||
|
else:
|
||||||
|
for key in self.CFG_DATA:
|
||||||
|
self.send_command(key, self.CFG_DATA.get(key))
|
||||||
|
|
||||||
|
def set(self, key, data, mid=None, block_callback=[]):
|
||||||
|
if key in self.CFG_DATA:
|
||||||
|
self.__cfg_callback__(key, data, mid)
|
||||||
if key in self.RX_IGNORE_KEYS:
|
if key in self.RX_IGNORE_KEYS:
|
||||||
pass # ignore these keys
|
pass # ignore these keys
|
||||||
elif key in self.RX_KEYS:
|
elif key in self.RX_KEYS:
|
||||||
@ -54,12 +68,12 @@ class base(mqtt_base):
|
|||||||
data = json.loads(message.payload)
|
data = json.loads(message.payload)
|
||||||
if type(data) is dict:
|
if type(data) is dict:
|
||||||
for key in data:
|
for key in data:
|
||||||
self.set(key, self.__device_to_instance_filter__(key, data[key]))
|
self.set(key, self.__device_to_instance_filter__(key, data[key]), message.mid)
|
||||||
else:
|
else:
|
||||||
self.set(content_key, self.__device_to_instance_filter__(content_key, data))
|
self.set(content_key, self.__device_to_instance_filter__(content_key, data), message.mid)
|
||||||
# String
|
# String
|
||||||
else:
|
else:
|
||||||
self.set(content_key, self.__device_to_instance_filter__(content_key, message.payload.decode('utf-8')))
|
self.set(content_key, self.__device_to_instance_filter__(content_key, message.payload.decode('utf-8')), message.mid)
|
||||||
else:
|
else:
|
||||||
self.logger.debug("Ignoring topic %s", content_key)
|
self.logger.debug("Ignoring topic %s", content_key)
|
||||||
|
|
||||||
@ -101,3 +115,121 @@ class base(mqtt_base):
|
|||||||
self.mqtt_client.send('/'.join([self.topic, key, self.TX_TOPIC] if len(self.TX_TOPIC) > 0 else [self.topic, key]), data)
|
self.mqtt_client.send('/'.join([self.topic, key, self.TX_TOPIC] if len(self.TX_TOPIC) > 0 else [self.topic, key]), data)
|
||||||
else:
|
else:
|
||||||
self.logger.error("Unknown tx toptic. Set TX_TOPIC of class to a known value")
|
self.logger.error("Unknown tx toptic. Set TX_TOPIC of class to a known value")
|
||||||
|
|
||||||
|
|
||||||
|
class base_rpc(mqtt_base):
|
||||||
|
SRC_RESPONSE = "/response"
|
||||||
|
SRC_NULL = "/null"
|
||||||
|
#
|
||||||
|
EVENTS_TOPIC = "/events/rpc"
|
||||||
|
TX_TOPIC = "/rpc"
|
||||||
|
RESPONSE_TOPIC = SRC_RESPONSE + "/rpc"
|
||||||
|
NULL_TOPIC = SRC_NULL + "/rpc"
|
||||||
|
#
|
||||||
|
RPC_ID_GET_STATUS = 1
|
||||||
|
RPC_ID_SET = 1734
|
||||||
|
#
|
||||||
|
|
||||||
|
def __init__(self, mqtt_client, topic):
|
||||||
|
super().__init__(mqtt_client, topic, default_values=dict.fromkeys(self.RX_KEYS))
|
||||||
|
# data storage
|
||||||
|
self.__cfg_by_mid__ = None
|
||||||
|
# initialisations
|
||||||
|
mqtt_client.add_callback(topic=self.topic, callback=self.receive_callback)
|
||||||
|
mqtt_client.add_callback(topic=self.topic+"/#", callback=self.receive_callback)
|
||||||
|
#
|
||||||
|
self.add_callback(None, None, self.__state_logging__, on_change_only=False)
|
||||||
|
#
|
||||||
|
self.rpc_get_status()
|
||||||
|
|
||||||
|
def receive_callback(self, client, userdata, message):
|
||||||
|
data = json.loads(message.payload)
|
||||||
|
#
|
||||||
|
if message.topic == self.topic + self.EVENTS_TOPIC:
|
||||||
|
self.events(data)
|
||||||
|
elif message.topic == self.topic + self.RESPONSE_TOPIC:
|
||||||
|
self.response(data)
|
||||||
|
elif message.topic == self.topic + self.NULL_TOPIC or message.topic == self.topic + self.TX_TOPIC or message.topic == self.topic + "/online":
|
||||||
|
pass # Ignore response
|
||||||
|
else:
|
||||||
|
self.logger.warning("Unexpected message received: %s::%s", message.topic, json.dumps(data, sort_keys=True, indent=4))
|
||||||
|
|
||||||
|
def events(self, data):
|
||||||
|
for rx_key in data["params"]:
|
||||||
|
if rx_key == "events":
|
||||||
|
for evt in data["params"]["events"]:
|
||||||
|
key = evt["component"]
|
||||||
|
event = evt["event"]
|
||||||
|
if key in self.RX_KEYS:
|
||||||
|
if event == "btn_down":
|
||||||
|
self.set(key, True)
|
||||||
|
elif event == "btn_up":
|
||||||
|
self.set(key, False)
|
||||||
|
else:
|
||||||
|
key = key + ":" + event
|
||||||
|
if key in self.RX_KEYS:
|
||||||
|
self.set(key, True)
|
||||||
|
else:
|
||||||
|
self.logger.warning("Unexpected event with data=%s", json.dumps(data, sort_keys=True, indent=4))
|
||||||
|
elif rx_key in self.RX_KEYS:
|
||||||
|
state = data["params"][rx_key].get("output")
|
||||||
|
if state is not None:
|
||||||
|
self.set(rx_key, state)
|
||||||
|
|
||||||
|
def response(self, data):
|
||||||
|
try:
|
||||||
|
rpc_id = data.get("id")
|
||||||
|
except AttributeError:
|
||||||
|
rpc_id = None
|
||||||
|
try:
|
||||||
|
rpc_method = data.get("method")
|
||||||
|
except AttributeError:
|
||||||
|
rpc_method = None
|
||||||
|
if rpc_id == self.RPC_ID_GET_STATUS:
|
||||||
|
#
|
||||||
|
# Shelly.GetStatus
|
||||||
|
#
|
||||||
|
for rx_key in data.get("result", []):
|
||||||
|
if rx_key in self.RX_KEYS:
|
||||||
|
key_data = data["result"][rx_key]
|
||||||
|
state = key_data.get("output", key_data.get("state"))
|
||||||
|
if state is not None:
|
||||||
|
self.set(rx_key, state)
|
||||||
|
else:
|
||||||
|
self.logger.warning("Unexpected response with data=%s", json.dumps(data, sort_keys=True, indent=4))
|
||||||
|
|
||||||
|
def rpc_tx(self, **kwargs):
|
||||||
|
if not "id" in kwargs:
|
||||||
|
raise AttributeError("'id' is missing in keyword arguments")
|
||||||
|
self.mqtt_client.send(self.topic + self.TX_TOPIC, json.dumps(kwargs))
|
||||||
|
|
||||||
|
def rpc_get_status(self):
|
||||||
|
self.rpc_tx(
|
||||||
|
id=self.RPC_ID_GET_STATUS,
|
||||||
|
src=self.topic + self.SRC_RESPONSE,
|
||||||
|
method="Shelly.GetStatus"
|
||||||
|
)
|
||||||
|
|
||||||
|
def rpc_switch_set(self, key, state: bool):
|
||||||
|
self.rpc_tx(
|
||||||
|
id=self.RPC_ID_SET,
|
||||||
|
src=self.topic + self.SRC_NULL,
|
||||||
|
method="Switch.Set",
|
||||||
|
params={"id": int(key[-1]), "on": state}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class base_output(base):
|
||||||
|
def __init__(self, mqtt_client, topic):
|
||||||
|
super().__init__(mqtt_client, topic)
|
||||||
|
self.__all_off_enabled__ = True
|
||||||
|
|
||||||
|
def disable_all_off(self, state=True):
|
||||||
|
self.__all_off_enabled__ = not state
|
||||||
|
|
||||||
|
def all_off(self):
|
||||||
|
if self.__all_off_enabled__:
|
||||||
|
try:
|
||||||
|
self.__all_off__()
|
||||||
|
except (AttributeError, TypeError) as e:
|
||||||
|
self.logger.warning("Method all_off was used, but __all_off__ method wasn't callable: %s", repr(e))
|
||||||
|
@ -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
|
||||||
|
|
||||||
@ -52,11 +51,16 @@ class brennenstuhl_heatingvalve(base):
|
|||||||
#
|
#
|
||||||
RX_KEYS = [KEY_LINKQUALITY, KEY_BATTERY, KEY_HEATING_SETPOINT, KEY_TEMPERATURE]
|
RX_KEYS = [KEY_LINKQUALITY, KEY_BATTERY, KEY_HEATING_SETPOINT, KEY_TEMPERATURE]
|
||||||
RX_IGNORE_KEYS = [KEY_AWAY_MODE, KEY_CHILD_LOCK, KEY_PRESET, KEY_SYSTEM_MODE, KEY_VALVE_DETECTION, KEY_WINDOW_DETECTION]
|
RX_IGNORE_KEYS = [KEY_AWAY_MODE, KEY_CHILD_LOCK, KEY_PRESET, KEY_SYSTEM_MODE, KEY_VALVE_DETECTION, KEY_WINDOW_DETECTION]
|
||||||
|
#
|
||||||
|
CFG_DATA = {
|
||||||
|
KEY_WINDOW_DETECTION: "ON",
|
||||||
|
KEY_VALVE_DETECTION: "ON",
|
||||||
|
KEY_SYSTEM_MODE: "heat",
|
||||||
|
KEY_PRESET: "manual"
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self, mqtt_client, topic):
|
def __init__(self, mqtt_client, topic):
|
||||||
super().__init__(mqtt_client, topic)
|
super().__init__(mqtt_client, topic)
|
||||||
self.mqtt_client.send(self.topic + '/' + self.TX_TOPIC, json.dumps({self.KEY_WINDOW_DETECTION: "ON",
|
|
||||||
self.KEY_CHILD_LOCK: "UNLOCK", self.KEY_VALVE_DETECTION: "ON", self.KEY_SYSTEM_MODE: "heat", self.KEY_PRESET: "manual"}))
|
|
||||||
self.add_callback(self.KEY_HEATING_SETPOINT, None, self.__valave_temp_rx__)
|
self.add_callback(self.KEY_HEATING_SETPOINT, None, self.__valave_temp_rx__)
|
||||||
self.__tx_temperature__ = None
|
self.__tx_temperature__ = None
|
||||||
self.__rx_temperature__ = None
|
self.__rx_temperature__ = None
|
||||||
|
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)
|
@ -1,11 +1,11 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
from devices.base import base
|
from devices.base import base, base_output
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
class powerplug(base):
|
class powerplug(base_output):
|
||||||
""" Communication (MQTT)
|
""" Communication (MQTT)
|
||||||
|
|
||||||
my_powerplug
|
my_powerplug
|
||||||
@ -115,7 +115,7 @@ class powerplug(base):
|
|||||||
def set_output_all_mcb(self, device, key, data):
|
def set_output_all_mcb(self, device, key, data):
|
||||||
self.set_output_all(data)
|
self.set_output_all(data)
|
||||||
|
|
||||||
def all_off(self):
|
def __all_off__(self):
|
||||||
self.set_output_all(False)
|
self.set_output_all(False)
|
||||||
|
|
||||||
|
|
||||||
@ -172,7 +172,9 @@ class remote(base):
|
|||||||
"""
|
"""
|
||||||
KEY_CD = "CD"
|
KEY_CD = "CD"
|
||||||
KEY_LINE1 = "LINE1"
|
KEY_LINE1 = "LINE1"
|
||||||
|
KEY_LINE2 = "LINE2"
|
||||||
KEY_LINE3 = "LINE3"
|
KEY_LINE3 = "LINE3"
|
||||||
|
KEY_PHONO = "PHONO"
|
||||||
KEY_MUTE = "MUTE"
|
KEY_MUTE = "MUTE"
|
||||||
KEY_POWER = "POWER"
|
KEY_POWER = "POWER"
|
||||||
KEY_VOLDOWN = "VOLDOWN"
|
KEY_VOLDOWN = "VOLDOWN"
|
||||||
@ -181,7 +183,7 @@ class remote(base):
|
|||||||
TX_TOPIC = ''
|
TX_TOPIC = ''
|
||||||
TX_TYPE = base.TX_VALUE
|
TX_TYPE = base.TX_VALUE
|
||||||
#
|
#
|
||||||
RX_IGNORE_TOPICS = [KEY_CD, KEY_LINE1, KEY_LINE3, KEY_MUTE, KEY_POWER, KEY_VOLUP, KEY_VOLDOWN]
|
RX_IGNORE_TOPICS = [KEY_CD, KEY_LINE1, KEY_LINE2, KEY_LINE3, KEY_PHONO, KEY_MUTE, KEY_POWER, KEY_VOLUP, KEY_VOLDOWN]
|
||||||
|
|
||||||
def __state_logging__(self, inst, key, data):
|
def __state_logging__(self, inst, key, data):
|
||||||
pass # This is just a TX device using self.set_*
|
pass # This is just a TX device using self.set_*
|
||||||
@ -194,10 +196,18 @@ class remote(base):
|
|||||||
self.logger.info("Changing amplifier source to LINE1")
|
self.logger.info("Changing amplifier source to LINE1")
|
||||||
self.send_command(self.KEY_LINE1, None)
|
self.send_command(self.KEY_LINE1, None)
|
||||||
|
|
||||||
|
def set_line2(self, device=None, key=None, data=None):
|
||||||
|
self.logger.info("Changing amplifier source to LINE2")
|
||||||
|
self.send_command(self.KEY_LINE2, None)
|
||||||
|
|
||||||
def set_line3(self, device=None, key=None, data=None):
|
def set_line3(self, device=None, key=None, data=None):
|
||||||
self.logger.info("Changing amplifier source to LINE3")
|
self.logger.info("Changing amplifier source to LINE3")
|
||||||
self.send_command(self.KEY_LINE3, None)
|
self.send_command(self.KEY_LINE3, None)
|
||||||
|
|
||||||
|
def set_phono(self, device=None, key=None, data=None):
|
||||||
|
self.logger.info("Changing amplifier source to PHONO")
|
||||||
|
self.send_command(self.KEY_PHONO, None)
|
||||||
|
|
||||||
def set_mute(self, device=None, key=None, data=None):
|
def set_mute(self, device=None, key=None, data=None):
|
||||||
self.logger.info("Muting / Unmuting amplifier")
|
self.logger.info("Muting / Unmuting amplifier")
|
||||||
self.send_command(self.KEY_MUTE, None)
|
self.send_command(self.KEY_MUTE, None)
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
from devices.base import base
|
from devices.base import base_output
|
||||||
import logging
|
from devices.base import base_rpc
|
||||||
import task
|
import task
|
||||||
|
|
||||||
|
|
||||||
class shelly(base):
|
class shelly(base_output):
|
||||||
""" Communication (MQTT)
|
""" Communication (MQTT)
|
||||||
|
|
||||||
shelly
|
shelly
|
||||||
@ -52,7 +52,7 @@ class shelly(base):
|
|||||||
KEY_FIRMWARE_VERSION = "fw_ver"
|
KEY_FIRMWARE_VERSION = "fw_ver"
|
||||||
#
|
#
|
||||||
TX_TOPIC = "command"
|
TX_TOPIC = "command"
|
||||||
TX_TYPE = base.TX_VALUE
|
TX_TYPE = base_output.TX_VALUE
|
||||||
TX_FILTER_DATA_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1]
|
TX_FILTER_DATA_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1]
|
||||||
#
|
#
|
||||||
RX_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_INPUT_0, KEY_INPUT_1, KEY_LONGPUSH_0, KEY_LONGPUSH_1, KEY_OVERTEMPERATURE, KEY_TEMPERATURE,
|
RX_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_INPUT_0, KEY_INPUT_1, KEY_LONGPUSH_0, KEY_LONGPUSH_1, KEY_OVERTEMPERATURE, KEY_TEMPERATURE,
|
||||||
@ -65,8 +65,8 @@ class shelly(base):
|
|||||||
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
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ class shelly(base):
|
|||||||
self.toggle_output_1_mcb(device, key, data)
|
self.toggle_output_1_mcb(device, key, data)
|
||||||
self.delayed_flash_task.run()
|
self.delayed_flash_task.run()
|
||||||
|
|
||||||
def all_off(self):
|
def __all_off__(self):
|
||||||
if self.flash_active:
|
if self.flash_active:
|
||||||
self.all_off_requested = True
|
self.all_off_requested = True
|
||||||
else:
|
else:
|
||||||
@ -169,3 +169,70 @@ class shelly(base):
|
|||||||
self.set_output_0(False)
|
self.set_output_0(False)
|
||||||
if self.output_1:
|
if self.output_1:
|
||||||
self.set_output_1(False)
|
self.set_output_1(False)
|
||||||
|
|
||||||
|
|
||||||
|
class shelly_rpc(base_rpc):
|
||||||
|
KEY_OUTPUT_0 = "switch:0"
|
||||||
|
KEY_OUTPUT_1 = "switch:1"
|
||||||
|
KEY_OUTPUT_2 = "switch:2"
|
||||||
|
KEY_INPUT_0 = "input:0"
|
||||||
|
KEY_INPUT_1 = "input:1"
|
||||||
|
KEY_INPUT_2 = "input:2"
|
||||||
|
KEY_LONGPUSH_0 = "input:0:long_push"
|
||||||
|
KEY_LONGPUSH_1 = "input:1:long_push"
|
||||||
|
KEY_LONGPUSH_2 = "input:2:long_push"
|
||||||
|
KEY_SINGLEPUSH_0 = "input:0:single_push"
|
||||||
|
KEY_SINGLEPUSH_1 = "input:1:single_push"
|
||||||
|
KEY_SINGLEPUSH_2 = "input:2:single_push"
|
||||||
|
KEY_DOUBLEPUSH_0 = "input:0:double_push"
|
||||||
|
KEY_DOUBLEPUSH_1 = "input:1:double_push"
|
||||||
|
KEY_DOUBLEPUSH_2 = "input:2:double_push"
|
||||||
|
KEY_TRIPLEPUSH_0 = "input:0:triple_push"
|
||||||
|
KEY_TRIPLEPUSH_1 = "input:1:triple_push"
|
||||||
|
KEY_TRIPLEPUSH_2 = "input:2:triple_push"
|
||||||
|
|
||||||
|
RX_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_OUTPUT_2, KEY_INPUT_0, KEY_INPUT_1, KEY_INPUT_2,
|
||||||
|
KEY_LONGPUSH_0, KEY_LONGPUSH_1, KEY_LONGPUSH_2, KEY_SINGLEPUSH_0, KEY_SINGLEPUSH_1, KEY_SINGLEPUSH_2,
|
||||||
|
KEY_DOUBLEPUSH_0, KEY_DOUBLEPUSH_1, KEY_DOUBLEPUSH_2, KEY_TRIPLEPUSH_0, KEY_TRIPLEPUSH_1, KEY_TRIPLEPUSH_2]
|
||||||
|
|
||||||
|
def __state_logging__(self, inst, key, data):
|
||||||
|
if key in [self.KEY_OUTPUT_0, self.KEY_OUTPUT_1, self.KEY_OUTPUT_2]:
|
||||||
|
self.logger.info("State change of '%s' to '%s'", key, repr(data))
|
||||||
|
elif key in [self.KEY_INPUT_0, self.KEY_INPUT_1, self.KEY_INPUT_2]:
|
||||||
|
self.logger.info("Input action '%s' with '%s'", key, repr(data))
|
||||||
|
elif key in [self.KEY_LONGPUSH_0, self.KEY_LONGPUSH_1, self.KEY_LONGPUSH_2,
|
||||||
|
self.KEY_SINGLEPUSH_0, self.KEY_SINGLEPUSH_1, self.KEY_SINGLEPUSH_2,
|
||||||
|
self.KEY_DOUBLEPUSH_0, self.KEY_DOUBLEPUSH_1, self.KEY_DOUBLEPUSH_2,
|
||||||
|
self.KEY_TRIPLEPUSH_0, self.KEY_TRIPLEPUSH_1, self.KEY_TRIPLEPUSH_2]:
|
||||||
|
self.logger.info("Input action '%s'", key)
|
||||||
|
|
||||||
|
def set_output_0(self, state):
|
||||||
|
"""state: [True, False]"""
|
||||||
|
self.rpc_switch_set(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.get(self.KEY_OUTPUT_0))
|
||||||
|
|
||||||
|
def set_output_1(self, state):
|
||||||
|
"""state: [True, False]"""
|
||||||
|
self.rpc_switch_set(self.KEY_OUTPUT_1, state)
|
||||||
|
|
||||||
|
def set_output_1_mcb(self, device, key, data):
|
||||||
|
self.set_output_1(data)
|
||||||
|
|
||||||
|
def toggle_output_1_mcb(self, device, key, data):
|
||||||
|
print(self.get(self.KEY_OUTPUT_1))
|
||||||
|
self.set_output_1(not self.get(self.KEY_OUTPUT_1))
|
||||||
|
|
||||||
|
def set_output_2(self, state):
|
||||||
|
"""state: [True, False]"""
|
||||||
|
self.rpc_switch_set(self.KEY_OUTPUT_2, state)
|
||||||
|
|
||||||
|
def set_output_2_mcb(self, device, key, data):
|
||||||
|
self.set_output_2(data)
|
||||||
|
|
||||||
|
def toggle_output_2_mcb(self, device, key, data):
|
||||||
|
self.set_output_2(not self.get(self.KEY_OUTPUT_2))
|
||||||
|
@ -1,11 +1,52 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
from devices.base import base
|
from devices.base import base, base_output
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
class silvercrest_powerplug(base):
|
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):
|
||||||
""" Communication (MQTT)
|
""" Communication (MQTT)
|
||||||
|
|
||||||
silvercrest_powerplug {
|
silvercrest_powerplug {
|
||||||
@ -58,7 +99,7 @@ class silvercrest_powerplug(base):
|
|||||||
def toggle_output_0_mcb(self, device, key, data):
|
def toggle_output_0_mcb(self, device, key, data):
|
||||||
self.set_output_0(not self.output_0)
|
self.set_output_0(not self.output_0)
|
||||||
|
|
||||||
def all_off(self):
|
def __all_off__(self):
|
||||||
if self.output_0:
|
if self.output_0:
|
||||||
self.set_output_0(False)
|
self.set_output_0(False)
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
from devices.base import base
|
from devices.base import base, base_output
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
class tradfri_light(base):
|
class tradfri_light(base_output):
|
||||||
""" Communication (MQTT)
|
""" Communication (MQTT)
|
||||||
|
|
||||||
tradfri_light {
|
tradfri_light {
|
||||||
@ -124,7 +124,7 @@ class tradfri_light(base):
|
|||||||
def set_color_temp_mcb(self, device, key, data):
|
def set_color_temp_mcb(self, device, key, data):
|
||||||
self.set_color_temp(data)
|
self.set_color_temp(data)
|
||||||
|
|
||||||
def all_off(self):
|
def __all_off__(self):
|
||||||
if self.output_0:
|
if self.output_0:
|
||||||
self.set_output_0(False)
|
self.set_output_0(False)
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ from function.ground_floor_west import ground_floor_west
|
|||||||
from function.first_floor_west import first_floor_west
|
from function.first_floor_west import first_floor_west
|
||||||
from function.first_floor_east import first_floor_east
|
from function.first_floor_east import first_floor_east
|
||||||
from function.rooms import room_collection
|
from function.rooms import room_collection
|
||||||
from function.videv import all_off
|
from function.videv import all_off, videv_pure_switch
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -42,6 +42,8 @@ class all_functions(room_collection):
|
|||||||
self.init_cross_room_interactions()
|
self.init_cross_room_interactions()
|
||||||
# Off Buttons
|
# Off Buttons
|
||||||
self.init_off_functionality()
|
self.init_off_functionality()
|
||||||
|
# Summer / Winter mode
|
||||||
|
self.init_sumer_winter_mode()
|
||||||
|
|
||||||
def init_cross_room_interactions(self):
|
def init_cross_room_interactions(self):
|
||||||
# shelly dirk input 1
|
# shelly dirk input 1
|
||||||
@ -69,6 +71,19 @@ class all_functions(room_collection):
|
|||||||
# FFE ALL OFF - Long push input device
|
# FFE ALL OFF - Long push input device
|
||||||
self.ffe.sleep.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_RIGHT_LONG, self.ffe.all_off)
|
self.ffe.sleep.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_RIGHT_LONG, self.ffe.all_off)
|
||||||
|
|
||||||
|
# FFW ALL OFF - Long push ffw_floor
|
||||||
|
self.ffw.floor.main_light_shelly.add_callback(self.ffw.floor.main_light_shelly.KEY_LONGPUSH_0,
|
||||||
|
True, self.ffw.floor.main_light_shelly.flash_0_mcb)
|
||||||
|
self.ffw.floor.main_light_shelly.add_callback(self.ffw.floor.main_light_shelly.KEY_LONGPUSH_0, True, self.ffw.all_off)
|
||||||
|
|
||||||
|
def init_sumer_winter_mode(self):
|
||||||
|
# ALL summer/winter mode
|
||||||
|
self.videv_summer_mode = videv_pure_switch(self.mqtt_client, config.TOPIC_ALL_SUMMER_WINTER_MODE)
|
||||||
|
|
||||||
|
self.videv_summer_mode.add_callback(self.videv_summer_mode.KEY_STATE, None, self.gfw.summer_mode)
|
||||||
|
self.videv_summer_mode.add_callback(self.videv_summer_mode.KEY_STATE, None, self.ffw.summer_mode)
|
||||||
|
self.videv_summer_mode.add_callback(self.videv_summer_mode.KEY_STATE, None, self.ffe.summer_mode)
|
||||||
|
|
||||||
def gfw_dirk_input_1(self, device, key, data):
|
def gfw_dirk_input_1(self, device, key, data):
|
||||||
if self.last_gfw_dirk_input_1 is not None:
|
if self.last_gfw_dirk_input_1 is not None:
|
||||||
if self.last_gfw_dirk_input_1 != data:
|
if self.last_gfw_dirk_input_1 != data:
|
||||||
|
@ -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(
|
||||||
@ -191,6 +197,9 @@ class first_floor_east_sleep(room):
|
|||||||
self.heating_valve = pd.get(props.STG_ZFE, loc, roo, props.FUN_HEA)
|
self.heating_valve = pd.get(props.STG_ZFE, loc, roo, props.FUN_HEA)
|
||||||
# button
|
# button
|
||||||
self.button_tradfri = pd.get(props.STG_ZFE, loc, roo, props.FUN_INP)
|
self.button_tradfri = pd.get(props.STG_ZFE, loc, roo, props.FUN_INP)
|
||||||
|
# wardrobe light
|
||||||
|
self.wardrobe_light = pd.get(props.STG_ZFE, loc, roo, props.FUN_WLI)
|
||||||
|
self.wardrobe_light.disable_all_off() # Always on - Off by light sensor
|
||||||
|
|
||||||
super().__init__(mqtt_client, pd, vd)
|
super().__init__(mqtt_client, pd, vd)
|
||||||
|
|
||||||
@ -248,6 +257,11 @@ class first_floor_east_sleep(room):
|
|||||||
mqtt_client, config.TOPIC_FFE_SLEEP_ACTIVE_BRIGHTNESS_DEVICE_VIDEV,
|
mqtt_client, config.TOPIC_FFE_SLEEP_ACTIVE_BRIGHTNESS_DEVICE_VIDEV,
|
||||||
brightness_choose_n_action.KEY_ACTIVE_DEVICE, self.brightness_functions, 2
|
brightness_choose_n_action.KEY_ACTIVE_DEVICE, self.brightness_functions, 2
|
||||||
)
|
)
|
||||||
|
self.wardrobe_light_videv = videv_switch_brightness(
|
||||||
|
mqtt_client, config.TOPIC_FFE_SLEEP_WARDROBE_LIGHT_VIDEV,
|
||||||
|
self.wardrobe_light, self.wardrobe_light.KEY_OUTPUT_0,
|
||||||
|
self.wardrobe_light, self.wardrobe_light.KEY_BRIGHTNESS,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class first_floor_east_living(room):
|
class first_floor_east_living(room):
|
||||||
|
@ -7,7 +7,7 @@ from devdi import topic as props
|
|||||||
from function.db import get_radiator_data, set_radiator_data
|
from function.db import get_radiator_data, set_radiator_data
|
||||||
from function.modules import heating_function
|
from function.modules import heating_function
|
||||||
from function.rooms import room, room_collection
|
from function.rooms import room, room_collection
|
||||||
from function.videv import videv_switch_brightness, videv_switch_brightness_color_temp, videv_heating
|
from function.videv import videv_switch_brightness, videv_switch_brightness_color_temp, videv_heating, videv_switching
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
@ -23,12 +23,34 @@ loc = props.LOC_FFW
|
|||||||
class first_floor_west(room_collection):
|
class first_floor_west(room_collection):
|
||||||
def __init__(self, mqtt_client, pd, vd):
|
def __init__(self, mqtt_client, pd, vd):
|
||||||
super().__init__(mqtt_client, pd, vd)
|
super().__init__(mqtt_client, pd, vd)
|
||||||
|
self.floor = first_floor_west_floor(mqtt_client, pd, vd)
|
||||||
self.bath = first_floor_west_bath(mqtt_client, pd, vd)
|
self.bath = first_floor_west_bath(mqtt_client, pd, vd)
|
||||||
self.julian = first_floor_west_julian(mqtt_client, pd, vd)
|
self.julian = first_floor_west_julian(mqtt_client, pd, vd)
|
||||||
self.livingroom = first_floor_west_living(mqtt_client, pd, vd)
|
self.livingroom = first_floor_west_living(mqtt_client, pd, vd)
|
||||||
self.sleep = first_floor_west_sleep(mqtt_client, pd, vd)
|
self.sleep = first_floor_west_sleep(mqtt_client, pd, vd)
|
||||||
|
|
||||||
|
|
||||||
|
class first_floor_west_floor(room):
|
||||||
|
def __init__(self, mqtt_client, pd, vd):
|
||||||
|
roo = props.ROO_FLO
|
||||||
|
#
|
||||||
|
# Device initialisation
|
||||||
|
#
|
||||||
|
# http://shelly1-58BF25D848EA
|
||||||
|
# main light
|
||||||
|
self.main_light_shelly = pd.get(props.STG_SHE, loc, roo, props.FUN_MAL)
|
||||||
|
super().__init__(mqtt_client, pd, vd)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Virtual Device Interface
|
||||||
|
#
|
||||||
|
# main light
|
||||||
|
self.main_light = videv_switching(
|
||||||
|
mqtt_client, config.TOPIC_FFW_FLOOR_MAIN_LIGHT_VIDEV,
|
||||||
|
self.main_light_shelly, self.main_light_shelly.KEY_OUTPUT_0
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class first_floor_west_julian(room):
|
class first_floor_west_julian(room):
|
||||||
def __init__(self, mqtt_client, pd, vd):
|
def __init__(self, mqtt_client, pd, vd):
|
||||||
roo = props.ROO_JUL
|
roo = props.ROO_JUL
|
||||||
@ -76,6 +98,9 @@ class first_floor_west_bath(room):
|
|||||||
#
|
#
|
||||||
# Device initialisation
|
# Device initialisation
|
||||||
#
|
#
|
||||||
|
# http://shelly1-58BF25D84219
|
||||||
|
# main light
|
||||||
|
self.main_light_shelly = pd.get(props.STG_SHE, loc, roo, props.FUN_MAL)
|
||||||
# heating function
|
# heating function
|
||||||
self.heating_valve = pd.get(props.STG_ZFW, loc, roo, props.FUN_HEA)
|
self.heating_valve = pd.get(props.STG_ZFW, loc, roo, props.FUN_HEA)
|
||||||
super().__init__(mqtt_client, pd, vd)
|
super().__init__(mqtt_client, pd, vd)
|
||||||
@ -94,6 +119,11 @@ class first_floor_west_bath(room):
|
|||||||
#
|
#
|
||||||
# Virtual Device Interface
|
# Virtual Device Interface
|
||||||
#
|
#
|
||||||
|
# main light
|
||||||
|
self.main_light = videv_switching(
|
||||||
|
mqtt_client, config.TOPIC_FFW_BATH_MAIN_LIGHT_VIDEV,
|
||||||
|
self.main_light_shelly, self.main_light_shelly.KEY_OUTPUT_0
|
||||||
|
)
|
||||||
# heating function
|
# heating function
|
||||||
self.heating_function_videv = videv_heating(
|
self.heating_function_videv = videv_heating(
|
||||||
mqtt_client, config.TOPIC_FFW_BATH_HEATING_VALVE_VIDEV,
|
mqtt_client, config.TOPIC_FFW_BATH_HEATING_VALVE_VIDEV,
|
||||||
@ -155,6 +185,8 @@ class first_floor_west_sleep(room):
|
|||||||
self.main_light_tradfri = pd.get(props.STG_ZFW, loc, roo, props.FUN_MAL)
|
self.main_light_tradfri = pd.get(props.STG_ZFW, loc, roo, props.FUN_MAL)
|
||||||
# heating function
|
# heating function
|
||||||
self.heating_valve = pd.get(props.STG_ZFW, loc, roo, props.FUN_HEA)
|
self.heating_valve = pd.get(props.STG_ZFW, loc, roo, props.FUN_HEA)
|
||||||
|
# window light
|
||||||
|
self.window_light = pd.get(props.STG_ZFW, loc, roo, props.FUN_WIL)
|
||||||
super().__init__(mqtt_client, pd, vd)
|
super().__init__(mqtt_client, pd, vd)
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -168,6 +200,9 @@ class first_floor_west_sleep(room):
|
|||||||
)
|
)
|
||||||
self.heating_function.add_callback(None, None, set_radiator_data, True)
|
self.heating_function.add_callback(None, None, set_radiator_data, True)
|
||||||
|
|
||||||
|
# main light
|
||||||
|
self.main_light_shelly.add_callback(self.main_light_shelly.KEY_OUTPUT_0, None, self.window_light.set_output_0_mcb, True)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Virtual Device Interface
|
# Virtual Device Interface
|
||||||
#
|
#
|
||||||
@ -182,3 +217,10 @@ class first_floor_west_sleep(room):
|
|||||||
mqtt_client, config.TOPIC_FFW_SLEEP_HEATING_VALVE_VIDEV,
|
mqtt_client, config.TOPIC_FFW_SLEEP_HEATING_VALVE_VIDEV,
|
||||||
self.heating_function
|
self.heating_function
|
||||||
)
|
)
|
||||||
|
# window lamp
|
||||||
|
self.windowlamp_videv = videv_switch_brightness_color_temp(
|
||||||
|
mqtt_client, config.TOPIC_FFW_SLEEP_WINDOW_LAMP_VIDEV,
|
||||||
|
self.window_light, self.window_light.KEY_OUTPUT_0,
|
||||||
|
self.window_light, self.window_light.KEY_BRIGHTNESS,
|
||||||
|
self.window_light, self.window_light.KEY_COLOR_TEMP
|
||||||
|
)
|
||||||
|
@ -4,12 +4,9 @@
|
|||||||
|
|
||||||
import config
|
import config
|
||||||
import devdi.topic as props
|
import devdi.topic as props
|
||||||
from devices import group
|
|
||||||
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.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_pure_switch
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -35,7 +32,11 @@ class garden_garden(room):
|
|||||||
#
|
#
|
||||||
self.day_events = day_event((6, 0), (22, 0), 30, -30)
|
self.day_events = day_event((6, 0), (22, 0), 30, -30)
|
||||||
|
|
||||||
|
# garden powerplugs
|
||||||
self.garland_powerplug = pd.get(props.STG_ZGW, loc, roo, props.FUN_GAR)
|
self.garland_powerplug = pd.get(props.STG_ZGW, loc, roo, props.FUN_GAR)
|
||||||
|
# repeater
|
||||||
|
self.repeater = pd.get(props.STG_ZGW, loc, roo, props.FUN_REP)
|
||||||
|
|
||||||
super().__init__(mqtt_client, pd, vd)
|
super().__init__(mqtt_client, pd, vd)
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -46,13 +47,23 @@ class garden_garden(room):
|
|||||||
#
|
#
|
||||||
# Virtual Device Interface
|
# Virtual Device Interface
|
||||||
#
|
#
|
||||||
|
# mode
|
||||||
|
self.mode_videv = videv_pure_switch(
|
||||||
|
mqtt_client, config.TOPIC_GAR_GARDEN_MODE_VIDEV
|
||||||
|
)
|
||||||
# garland
|
# garland
|
||||||
self.garland_videv = videv_switching(
|
self.garland_videv = videv_switching(
|
||||||
mqtt_client, config.TOPIC_GAR_GARDEN_GARLAND_VIDEV,
|
mqtt_client, config.TOPIC_GAR_GARDEN_GARLAND_VIDEV,
|
||||||
self.garland_powerplug, self.garland_powerplug.KEY_OUTPUT_0
|
self.garland_powerplug, self.garland_powerplug.KEY_OUTPUT_0
|
||||||
)
|
)
|
||||||
|
# repeater
|
||||||
|
self.repeater_videv = videv_switching(
|
||||||
|
mqtt_client, config.TOPIC_GAR_GARDEN_REPEATER_VIDEV,
|
||||||
|
self.repeater, self.repeater.KEY_OUTPUT_0
|
||||||
|
)
|
||||||
|
|
||||||
def __day_events__(self, device, key, data):
|
def __day_events__(self, device, key, data):
|
||||||
|
if self.mode_videv.get(self.mode_videv.KEY_STATE):
|
||||||
if key in (self.day_events.KEY_SUNSET, self.day_events.KEY_START_OF_DAY):
|
if key in (self.day_events.KEY_SUNSET, self.day_events.KEY_START_OF_DAY):
|
||||||
self.garland_powerplug.set_output_0(True)
|
self.garland_powerplug.set_output_0(True)
|
||||||
elif key in (self.day_events.KEY_START_OF_NIGHT, self.day_events.KEY_SUNRISE):
|
elif key in (self.day_events.KEY_START_OF_NIGHT, self.day_events.KEY_SUNRISE):
|
||||||
|
@ -68,6 +68,8 @@ class ground_floor_west_marion(room):
|
|||||||
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)
|
||||||
# heating function
|
# heating function
|
||||||
self.heating_valve = pd.get(props.STG_ZGW, loc, roo, props.FUN_HEA)
|
self.heating_valve = pd.get(props.STG_ZGW, loc, roo, props.FUN_HEA)
|
||||||
|
# window light
|
||||||
|
self.window_light = pd.get(props.STG_ZGW, loc, roo, props.FUN_WIL)
|
||||||
super().__init__(mqtt_client, pd, vd)
|
super().__init__(mqtt_client, pd, vd)
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -81,6 +83,9 @@ class ground_floor_west_marion(room):
|
|||||||
)
|
)
|
||||||
self.heating_function.add_callback(None, None, set_radiator_data, True)
|
self.heating_function.add_callback(None, None, set_radiator_data, True)
|
||||||
|
|
||||||
|
# main light
|
||||||
|
self.main_light_shelly.add_callback(self.main_light_shelly.KEY_OUTPUT_0, None, self.window_light.set_output_0_mcb, True)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Virtual Device Interface
|
# Virtual Device Interface
|
||||||
#
|
#
|
||||||
@ -92,6 +97,13 @@ class ground_floor_west_marion(room):
|
|||||||
mqtt_client, config.TOPIC_GFW_MARION_HEATING_VALVE_VIDEV,
|
mqtt_client, config.TOPIC_GFW_MARION_HEATING_VALVE_VIDEV,
|
||||||
self.heating_function
|
self.heating_function
|
||||||
)
|
)
|
||||||
|
# window lamp
|
||||||
|
self.windowlamp_videv = videv_switch_brightness_color_temp(
|
||||||
|
mqtt_client, config.TOPIC_GFW_MARION_WINDOW_LAMP_VIDEV,
|
||||||
|
self.window_light, self.window_light.KEY_OUTPUT_0,
|
||||||
|
self.window_light, self.window_light.KEY_BRIGHTNESS,
|
||||||
|
self.window_light, self.window_light.KEY_COLOR_TEMP
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ground_floor_west_dirk(room):
|
class ground_floor_west_dirk(room):
|
||||||
@ -103,6 +115,7 @@ class ground_floor_west_dirk(room):
|
|||||||
AUDIO_SOURCE_PC = 0
|
AUDIO_SOURCE_PC = 0
|
||||||
AUDIO_SOURCE_CD = 1
|
AUDIO_SOURCE_CD = 1
|
||||||
AUDIO_SOURCE_RASPI = 2
|
AUDIO_SOURCE_RASPI = 2
|
||||||
|
AUDIO_SOURCE_BT = 3
|
||||||
|
|
||||||
def __init__(self, mqtt_client, pd, vd):
|
def __init__(self, mqtt_client, pd, vd):
|
||||||
roo = props.ROO_DIR
|
roo = props.ROO_DIR
|
||||||
@ -116,9 +129,11 @@ class ground_floor_west_dirk(room):
|
|||||||
# powerplug
|
# powerplug
|
||||||
self.powerplug_common = pd.get(props.STG_MYA, loc, roo, props.FUN_MPP)
|
self.powerplug_common = pd.get(props.STG_MYA, loc, roo, props.FUN_MPP)
|
||||||
self.KEY_POWERPLUG_AMPLIFIER = self.powerplug_common.KEY_OUTPUT_0
|
self.KEY_POWERPLUG_AMPLIFIER = self.powerplug_common.KEY_OUTPUT_0
|
||||||
self.KEY_POWERPLUG_DESK_LIGHT = self.powerplug_common.KEY_OUTPUT_1
|
self.KEY_POWERPLUG_PHONO = self.powerplug_common.KEY_OUTPUT_1
|
||||||
self.KEY_POWERPLUG_CD_PLAYER = self.powerplug_common.KEY_OUTPUT_2
|
self.KEY_POWERPLUG_CD_PLAYER = self.powerplug_common.KEY_OUTPUT_2
|
||||||
self.KEY_POWERPLUG_PC_DOCK = self.powerplug_common.KEY_OUTPUT_3
|
self.KEY_POWERPLUG_BT = self.powerplug_common.KEY_OUTPUT_3
|
||||||
|
# dock
|
||||||
|
self.dock_tradfri = pd.get(props.STG_ZGW, loc, roo, props.FUN_DCK)
|
||||||
# desk light
|
# desk light
|
||||||
self.desk_light_tradfri = pd.get(props.STG_ZGW, loc, roo, props.FUN_DEL)
|
self.desk_light_tradfri = pd.get(props.STG_ZGW, loc, roo, props.FUN_DEL)
|
||||||
# button
|
# button
|
||||||
@ -137,14 +152,14 @@ class ground_floor_west_dirk(room):
|
|||||||
# Button - Brightness functionality
|
# Button - Brightness functionality
|
||||||
self.brightness_functions = brightness_choose_n_action(self.button_tradfri)
|
self.brightness_functions = brightness_choose_n_action(self.button_tradfri)
|
||||||
self.brightness_functions.add(self.main_light_tradfri, self.main_light_shelly, self.main_light_shelly.KEY_OUTPUT_0)
|
self.brightness_functions.add(self.main_light_tradfri, self.main_light_shelly, self.main_light_shelly.KEY_OUTPUT_0)
|
||||||
self.brightness_functions.add(self.desk_light_tradfri, self.powerplug_common, self.KEY_POWERPLUG_DESK_LIGHT)
|
self.brightness_functions.add(self.desk_light_tradfri, self.desk_light_tradfri, self.desk_light_tradfri.KEY_OUTPUT_0)
|
||||||
self.brightness_functions.add(self.remote_amplifier, self.powerplug_common, self.KEY_POWERPLUG_AMPLIFIER)
|
self.brightness_functions.add(self.remote_amplifier, self.powerplug_common, self.KEY_POWERPLUG_AMPLIFIER)
|
||||||
# Button - Main light
|
# Button - Main light
|
||||||
self.button_tradfri.add_callback(self.button_tradfri.KEY_ACTION, self.button_tradfri.ACTION_TOGGLE,
|
self.button_tradfri.add_callback(self.button_tradfri.KEY_ACTION, self.button_tradfri.ACTION_TOGGLE,
|
||||||
self.main_light_shelly.toggle_output_0_mcb)
|
self.main_light_shelly.toggle_output_0_mcb)
|
||||||
# Button - Desk light
|
# Button - Desk light
|
||||||
self.button_tradfri.add_callback(self.button_tradfri.KEY_ACTION, self.button_tradfri.ACTION_RIGHT,
|
self.button_tradfri.add_callback(self.button_tradfri.KEY_ACTION, self.button_tradfri.ACTION_RIGHT,
|
||||||
self.powerplug_common.toggle_output_1_mcb)
|
self.desk_light_tradfri.toggle_output_0_mcb)
|
||||||
# Button - Amplifier
|
# Button - Amplifier
|
||||||
self.button_tradfri.add_callback(self.button_tradfri.KEY_ACTION, self.button_tradfri.ACTION_LEFT_LONG,
|
self.button_tradfri.add_callback(self.button_tradfri.KEY_ACTION, self.button_tradfri.ACTION_LEFT_LONG,
|
||||||
self.powerplug_common.toggle_output_0_mcb)
|
self.powerplug_common.toggle_output_0_mcb)
|
||||||
@ -153,16 +168,19 @@ class ground_floor_west_dirk(room):
|
|||||||
self.powerplug_common.toggle_output_2_mcb)
|
self.powerplug_common.toggle_output_2_mcb)
|
||||||
# Button - PC dock
|
# Button - PC dock
|
||||||
self.button_tradfri.add_callback(self.button_tradfri.KEY_ACTION, self.button_tradfri.ACTION_LEFT,
|
self.button_tradfri.add_callback(self.button_tradfri.KEY_ACTION, self.button_tradfri.ACTION_LEFT,
|
||||||
self.powerplug_common.toggle_output_3_mcb)
|
self.dock_tradfri.toggle_output_0_mcb)
|
||||||
|
|
||||||
# Mediaplayer - Amplifier auto on
|
# Mediaplayer - Amplifier auto on
|
||||||
|
self.powerplug_common.add_callback(self.KEY_POWERPLUG_PHONO, None, self.powerplug_common.set_output_0_mcb, True)
|
||||||
self.powerplug_common.add_callback(self.KEY_POWERPLUG_CD_PLAYER, None, self.powerplug_common.set_output_0_mcb, True)
|
self.powerplug_common.add_callback(self.KEY_POWERPLUG_CD_PLAYER, None, self.powerplug_common.set_output_0_mcb, True)
|
||||||
|
self.powerplug_common.add_callback(self.KEY_POWERPLUG_BT, None, self.powerplug_common.set_output_0_mcb, True)
|
||||||
self.spotify_state.add_callback(self.spotify_state.KEY_STATE, None, self.powerplug_common.set_output_0_mcb, True)
|
self.spotify_state.add_callback(self.spotify_state.KEY_STATE, None, self.powerplug_common.set_output_0_mcb, True)
|
||||||
self.mpd_state.add_callback(self.mpd_state.KEY_STATE, None, self.powerplug_common.set_output_0_mcb, True)
|
self.mpd_state.add_callback(self.mpd_state.KEY_STATE, None, self.powerplug_common.set_output_0_mcb, True)
|
||||||
self.bt_state.add_callback(self.bt_state.KEY_STATE, None, self.powerplug_common.set_output_0_mcb, True)
|
self.bt_state.add_callback(self.bt_state.KEY_STATE, None, self.powerplug_common.set_output_0_mcb, True)
|
||||||
# Mediaplayer - Audio source selection
|
# Mediaplayer - Audio source selection
|
||||||
self.powerplug_common.add_callback(self.KEY_POWERPLUG_AMPLIFIER, True, self.audio_source_selector, True)
|
self.powerplug_common.add_callback(self.KEY_POWERPLUG_AMPLIFIER, True, self.audio_source_selector, True)
|
||||||
self.powerplug_common.add_callback(self.KEY_POWERPLUG_CD_PLAYER, True, self.audio_source_selector, True)
|
self.powerplug_common.add_callback(self.KEY_POWERPLUG_CD_PLAYER, True, self.audio_source_selector, True)
|
||||||
|
self.powerplug_common.add_callback(self.KEY_POWERPLUG_BT, True, self.audio_source_selector, True)
|
||||||
self.spotify_state.add_callback(self.spotify_state.KEY_STATE, True, self.audio_source_selector, True)
|
self.spotify_state.add_callback(self.spotify_state.KEY_STATE, True, self.audio_source_selector, True)
|
||||||
self.mpd_state.add_callback(self.mpd_state.KEY_STATE, True, self.audio_source_selector, True)
|
self.mpd_state.add_callback(self.mpd_state.KEY_STATE, True, self.audio_source_selector, True)
|
||||||
self.bt_state.add_callback(self.bt_state.KEY_STATE, True, self.audio_source_selector, True)
|
self.bt_state.add_callback(self.bt_state.KEY_STATE, True, self.audio_source_selector, True)
|
||||||
@ -187,7 +205,7 @@ class ground_floor_west_dirk(room):
|
|||||||
)
|
)
|
||||||
self.desk_light_videv = videv_switch_brightness_color_temp(
|
self.desk_light_videv = videv_switch_brightness_color_temp(
|
||||||
mqtt_client, config.TOPIC_GFW_DIRK_DESK_LIGHT_VIDEV,
|
mqtt_client, config.TOPIC_GFW_DIRK_DESK_LIGHT_VIDEV,
|
||||||
self.powerplug_common, self.KEY_POWERPLUG_DESK_LIGHT,
|
self.desk_light_tradfri, self.desk_light_tradfri.KEY_OUTPUT_0,
|
||||||
self.desk_light_tradfri, self.desk_light_tradfri.KEY_BRIGHTNESS,
|
self.desk_light_tradfri, self.desk_light_tradfri.KEY_BRIGHTNESS,
|
||||||
self.desk_light_tradfri, self.desk_light_tradfri.KEY_COLOR_TEMP
|
self.desk_light_tradfri, self.desk_light_tradfri.KEY_COLOR_TEMP
|
||||||
)
|
)
|
||||||
@ -195,13 +213,21 @@ class ground_floor_west_dirk(room):
|
|||||||
mqtt_client, config.TOPIC_GFW_DIRK_AMPLIFIER_VIDEV,
|
mqtt_client, config.TOPIC_GFW_DIRK_AMPLIFIER_VIDEV,
|
||||||
self.powerplug_common, self.KEY_POWERPLUG_AMPLIFIER
|
self.powerplug_common, self.KEY_POWERPLUG_AMPLIFIER
|
||||||
)
|
)
|
||||||
|
self.phono_videv = videv_switching(
|
||||||
|
mqtt_client, config.TOPIC_GFW_DIRK_PHONO_VIDEV,
|
||||||
|
self.powerplug_common, self.KEY_POWERPLUG_PHONO
|
||||||
|
)
|
||||||
self.cd_player_videv = videv_switching(
|
self.cd_player_videv = videv_switching(
|
||||||
mqtt_client, config.TOPIC_GFW_DIRK_CD_PLAYER_VIDEV,
|
mqtt_client, config.TOPIC_GFW_DIRK_CD_PLAYER_VIDEV,
|
||||||
self.powerplug_common, self.KEY_POWERPLUG_CD_PLAYER
|
self.powerplug_common, self.KEY_POWERPLUG_CD_PLAYER
|
||||||
)
|
)
|
||||||
|
self.bt_videv = videv_switching(
|
||||||
|
mqtt_client, config.TOPIC_GFW_DIRK_BT_VIDEV,
|
||||||
|
self.powerplug_common, self.KEY_POWERPLUG_BT
|
||||||
|
)
|
||||||
self.pc_dock_videv = videv_switching(
|
self.pc_dock_videv = videv_switching(
|
||||||
mqtt_client, config.TOPIC_GFW_DIRK_PC_DOCK_VIDEV,
|
mqtt_client, config.TOPIC_GFW_DIRK_PC_DOCK_VIDEV,
|
||||||
self.powerplug_common, self.KEY_POWERPLUG_PC_DOCK
|
self.dock_tradfri, self.dock_tradfri.KEY_OUTPUT_0
|
||||||
)
|
)
|
||||||
self.heating_function_videv = videv_heating(
|
self.heating_function_videv = videv_heating(
|
||||||
mqtt_client, config.TOPIC_GFW_DIRK_HEATING_VALVE_VIDEV,
|
mqtt_client, config.TOPIC_GFW_DIRK_HEATING_VALVE_VIDEV,
|
||||||
@ -224,6 +250,9 @@ class ground_floor_west_dirk(room):
|
|||||||
if device == self.powerplug_common and key == self.KEY_POWERPLUG_CD_PLAYER:
|
if device == self.powerplug_common and key == self.KEY_POWERPLUG_CD_PLAYER:
|
||||||
# switch on of cd player
|
# switch on of cd player
|
||||||
self.audio_source = self.AUDIO_SOURCE_CD
|
self.audio_source = self.AUDIO_SOURCE_CD
|
||||||
|
elif device == self.powerplug_common and key == self.KEY_POWERPLUG_BT:
|
||||||
|
# switch on of bluetooth
|
||||||
|
self.audio_source = self.AUDIO_SOURCE_BT
|
||||||
elif device in [self.spotify_state, self.mpd_state, self.bt_state]:
|
elif device in [self.spotify_state, self.mpd_state, self.bt_state]:
|
||||||
# switch on raspi-source
|
# switch on raspi-source
|
||||||
self.audio_source = self.AUDIO_SOURCE_RASPI
|
self.audio_source = self.AUDIO_SOURCE_RASPI
|
||||||
@ -238,6 +267,9 @@ class ground_floor_west_dirk(room):
|
|||||||
elif self.audio_source == self.AUDIO_SOURCE_CD:
|
elif self.audio_source == self.AUDIO_SOURCE_CD:
|
||||||
logger.info("Sending IR command to change audio source to cd")
|
logger.info("Sending IR command to change audio source to cd")
|
||||||
self.remote_amplifier.set_cd()
|
self.remote_amplifier.set_cd()
|
||||||
|
elif self.audio_source == self.AUDIO_SOURCE_BT:
|
||||||
|
logger.info("Sending IR command to change audio source to tuner")
|
||||||
|
self.remote_amplifier.set_line2()
|
||||||
elif self.audio_source == self.AUDIO_SOURCE_RASPI:
|
elif self.audio_source == self.AUDIO_SOURCE_RASPI:
|
||||||
logger.info("Sending IR command to change audio source to raspi")
|
logger.info("Sending IR command to change audio source to raspi")
|
||||||
self.remote_amplifier.set_line1()
|
self.remote_amplifier.set_line1()
|
||||||
|
@ -27,6 +27,12 @@ class room(object):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass # not a module or has no method all_off
|
pass # not a module or has no method all_off
|
||||||
|
|
||||||
|
def summer_mode(self, enable):
|
||||||
|
for name, obj in inspect.getmembers(self):
|
||||||
|
if obj.__class__.__name__ == 'heating_function':
|
||||||
|
if obj.__module__ == 'function.modules':
|
||||||
|
obj.set(obj.KEY_SUMMER_MODE, enable)
|
||||||
|
|
||||||
|
|
||||||
class room_collection(object):
|
class room_collection(object):
|
||||||
ALLOWED_CLASSES = ("room", "room_collection")
|
ALLOWED_CLASSES = ("room", "room_collection")
|
||||||
@ -45,6 +51,15 @@ class room_collection(object):
|
|||||||
if sub.__class__.__bases__[0].__name__ in self.ALLOWED_CLASSES:
|
if sub.__class__.__bases__[0].__name__ in self.ALLOWED_CLASSES:
|
||||||
sub.all_off()
|
sub.all_off()
|
||||||
|
|
||||||
|
def summer_mode(self, device=None, key=None, data=None):
|
||||||
|
logger.info("Changing to %s \"%s\"", "summer mode" if data else "winter_mode", type(self).__name__)
|
||||||
|
for sub_name in dir(self):
|
||||||
|
# attribute name is not private
|
||||||
|
if not sub_name.startswith("__"):
|
||||||
|
sub = getattr(self, sub_name)
|
||||||
|
if sub.__class__.__bases__[0].__name__ in self.ALLOWED_CLASSES:
|
||||||
|
sub.summer_mode(data)
|
||||||
|
|
||||||
def all_devices(self, object_to_analyse=None, depth=0):
|
def all_devices(self, object_to_analyse=None, depth=0):
|
||||||
target = object_to_analyse or self
|
target = object_to_analyse or self
|
||||||
#
|
#
|
||||||
|
@ -20,6 +20,20 @@ except ImportError:
|
|||||||
ROOT_LOGGER_NAME = 'root'
|
ROOT_LOGGER_NAME = 'root'
|
||||||
|
|
||||||
|
|
||||||
|
class videv_pure_switch(videv_base):
|
||||||
|
KEY_STATE = 'state'
|
||||||
|
|
||||||
|
def __init__(self, mqtt_client, topic):
|
||||||
|
super().__init__(mqtt_client, topic)
|
||||||
|
self[self.KEY_STATE] = False
|
||||||
|
#
|
||||||
|
self.mqtt_client.add_callback(self.topic + '/state/set', self.__state__)
|
||||||
|
|
||||||
|
def __state__(self, mqtt_client, userdata, message):
|
||||||
|
self.set(self.KEY_STATE, message.payload == b'true')
|
||||||
|
self.__tx__(self.KEY_STATE, message.payload == b'true')
|
||||||
|
|
||||||
|
|
||||||
class videv_switching(videv_base):
|
class videv_switching(videv_base):
|
||||||
KEY_STATE = 'state'
|
KEY_STATE = 'state'
|
||||||
|
|
||||||
|
26
init_venv
26
init_venv
@ -1,8 +1,24 @@
|
|||||||
#!/bin/sh
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
BASEPATH=`realpath $(dirname $0)`
|
BASEPATH=`realpath $(dirname $0)`
|
||||||
|
|
||||||
python3 -m venv $BASEPATH/venv
|
#
|
||||||
$BASEPATH/venv/bin/pip install --upgrade pip
|
# Create venv
|
||||||
find $BASEPATH -name requirements.txt | xargs -L 1 $BASEPATH/venv/bin/pip install -r
|
#
|
||||||
$BASEPATH/venv/bin/pip list --outdated --format=json | jq -r '.[] | .name'|xargs -n1 $BASEPATH/venv/bin/pip install -U
|
if [[ ! -e $BASEPATH/venv ]]; then
|
||||||
|
python3 -m venv $BASEPATH/venv > /dev/null 2>&1
|
||||||
|
# $BASEPATH/venv/bin/pip install --upgrade pip
|
||||||
|
find $BASEPATH -name requirements.txt | xargs -L 1 $BASEPATH/venv/bin/pip install -r > /dev/null 2>&1
|
||||||
|
echo "venv changed"
|
||||||
|
fi
|
||||||
|
#
|
||||||
|
# Update venv modules
|
||||||
|
#
|
||||||
|
for req_mod in $($BASEPATH/venv/bin/pip list --format=json | jq -r '.[] | .name'); do
|
||||||
|
$BASEPATH/venv/bin/pip install -U $req_mod | grep install > /dev/null 2>&1
|
||||||
|
if [[ "$?" -eq "0" ]]; then
|
||||||
|
echo $req_mod changed
|
||||||
|
fi
|
||||||
|
|
||||||
|
done
|
||||||
|
#|xargs -n1 $BASEPATH/venv/bin/pip install -U
|
||||||
|
2
mqtt
2
mqtt
@ -1 +1 @@
|
|||||||
Subproject commit 1adfb0626e7777c6d29be65d4ad4ce2d57541301
|
Subproject commit 14e56ccdbf6594f699b4afcfb4acafe9b899e914
|
2
report
2
report
@ -1 +1 @@
|
|||||||
Subproject commit b53dd30eae1d679b7eec4999bec50aed55bc105b
|
Subproject commit 7003c13ef8c7e7c3a55a545cbbad4039cc024a9f
|
@ -13,8 +13,8 @@ logger = logging.getLogger(config.APP_NAME)
|
|||||||
|
|
||||||
|
|
||||||
VERS_MAJOR = 1
|
VERS_MAJOR = 1
|
||||||
VERS_MINOR = 2
|
VERS_MINOR = 3
|
||||||
VERS_PATCH = 6
|
VERS_PATCH = 0
|
||||||
|
|
||||||
INFO_TOPIC = "__info__"
|
INFO_TOPIC = "__info__"
|
||||||
INFO_DATA = {
|
INFO_DATA = {
|
||||||
|
18
topics.py
18
topics.py
@ -3,6 +3,8 @@
|
|||||||
#
|
#
|
||||||
TOPIC_WARNINGS = "videv/warnings"
|
TOPIC_WARNINGS = "videv/warnings"
|
||||||
TOPIC_ALL_OFF_VIDEV = "videv/off"
|
TOPIC_ALL_OFF_VIDEV = "videv/off"
|
||||||
|
TOPIC_ALL_SUMMER_WINTER_MODE = "videv/summer_mode"
|
||||||
|
|
||||||
# ground floor west
|
# ground floor west
|
||||||
# floor
|
# floor
|
||||||
TOPIC_GFW_FLOOR_MAIN_LIGHT_VIDEV = "videv/gfw/floor/main_light"
|
TOPIC_GFW_FLOOR_MAIN_LIGHT_VIDEV = "videv/gfw/floor/main_light"
|
||||||
@ -10,24 +12,34 @@ TOPIC_GFW_FLOOR_MAIN_LIGHT_VIDEV = "videv/gfw/floor/main_light"
|
|||||||
# marion
|
# marion
|
||||||
TOPIC_GFW_MARION_MAIN_LIGHT_VIDEV = "videv/gfw/marion/main_light"
|
TOPIC_GFW_MARION_MAIN_LIGHT_VIDEV = "videv/gfw/marion/main_light"
|
||||||
TOPIC_GFW_MARION_HEATING_VALVE_VIDEV = "videv/gfw/marion/heating_valve"
|
TOPIC_GFW_MARION_HEATING_VALVE_VIDEV = "videv/gfw/marion/heating_valve"
|
||||||
|
TOPIC_GFW_MARION_WINDOW_LAMP_VIDEV = "videv/gfw/marion/window_light"
|
||||||
|
|
||||||
# dirk
|
# dirk
|
||||||
TOPIC_GFW_DIRK_MAIN_LIGHT_VIDEV = "videv/gfw/dirk/main_light"
|
TOPIC_GFW_DIRK_MAIN_LIGHT_VIDEV = "videv/gfw/dirk/main_light"
|
||||||
TOPIC_GFW_DIRK_DESK_LIGHT_VIDEV = "videv/gfw/dirk/desk_light"
|
TOPIC_GFW_DIRK_DESK_LIGHT_VIDEV = "videv/gfw/dirk/desk_light"
|
||||||
TOPIC_GFW_DIRK_AMPLIFIER_VIDEV = "videv/gfw/dirk/amplifier"
|
TOPIC_GFW_DIRK_AMPLIFIER_VIDEV = "videv/gfw/dirk/amplifier"
|
||||||
|
TOPIC_GFW_DIRK_PHONO_VIDEV = "videv/gfw/dirk/phono"
|
||||||
TOPIC_GFW_DIRK_CD_PLAYER_VIDEV = "videv/gfw/dirk/cd_player"
|
TOPIC_GFW_DIRK_CD_PLAYER_VIDEV = "videv/gfw/dirk/cd_player"
|
||||||
|
TOPIC_GFW_DIRK_BT_VIDEV = "videv/gfw/dirk/bt"
|
||||||
TOPIC_GFW_DIRK_PC_DOCK_VIDEV = "videv/gfw/dirk/pc_dock"
|
TOPIC_GFW_DIRK_PC_DOCK_VIDEV = "videv/gfw/dirk/pc_dock"
|
||||||
TOPIC_GFW_DIRK_ACTIVE_BRIGHTNESS_DEVICE_VIDEV = "videv/gfw/dirk/active_brightness_device"
|
TOPIC_GFW_DIRK_ACTIVE_BRIGHTNESS_DEVICE_VIDEV = "videv/gfw/dirk/active_brightness_device"
|
||||||
TOPIC_GFW_DIRK_AUDIO_PLAYER_VIDEV = "videv/gfw/dirk/audio_player"
|
TOPIC_GFW_DIRK_AUDIO_PLAYER_VIDEV = "videv/gfw/dirk/audio_player"
|
||||||
TOPIC_GFW_DIRK_HEATING_VALVE_VIDEV = "videv/gfw/dirk/heating_valve"
|
TOPIC_GFW_DIRK_HEATING_VALVE_VIDEV = "videv/gfw/dirk/heating_valve"
|
||||||
TOPIC_GAR_GARDEN_GARLAND_VIDEV = 'videv/gar/garden/garland'
|
|
||||||
|
# garden
|
||||||
|
TOPIC_GAR_GARDEN_MODE_VIDEV = "videv/gar/garden/mode"
|
||||||
|
TOPIC_GAR_GARDEN_GARLAND_VIDEV = "videv/gar/garden/garland"
|
||||||
|
TOPIC_GAR_GARDEN_REPEATER_VIDEV = "videv/gar/garden/repeater"
|
||||||
|
|
||||||
# first floor west
|
# first floor west
|
||||||
|
# floor
|
||||||
|
TOPIC_FFW_FLOOR_MAIN_LIGHT_VIDEV = "videv/ffw/floor/main_light"
|
||||||
# julian
|
# julian
|
||||||
TOPIC_FFW_JULIAN_MAIN_LIGHT_VIDEV = "videv/ffw/julian/main_light"
|
TOPIC_FFW_JULIAN_MAIN_LIGHT_VIDEV = "videv/ffw/julian/main_light"
|
||||||
TOPIC_FFW_JULIAN_HEATING_VALVE_VIDEV = "videv/ffw/julian/heating_valve"
|
TOPIC_FFW_JULIAN_HEATING_VALVE_VIDEV = "videv/ffw/julian/heating_valve"
|
||||||
|
|
||||||
# bath
|
# bath
|
||||||
|
TOPIC_FFW_BATH_MAIN_LIGHT_VIDEV = "videv/ffw/bath/main_light"
|
||||||
TOPIC_FFW_BATH_HEATING_VALVE_VIDEV = "videv/ffw/bath/heating_valve"
|
TOPIC_FFW_BATH_HEATING_VALVE_VIDEV = "videv/ffw/bath/heating_valve"
|
||||||
|
|
||||||
# livingroom
|
# livingroom
|
||||||
@ -37,6 +49,7 @@ TOPIC_FFW_LIVINGROOM_HEATING_VALVE_VIDEV = "videv/ffw/livingroom/heating_valve"
|
|||||||
# sleep
|
# sleep
|
||||||
TOPIC_FFW_SLEEP_MAIN_LIGHT_VIDEV = "videv/ffw/sleep/main_light"
|
TOPIC_FFW_SLEEP_MAIN_LIGHT_VIDEV = "videv/ffw/sleep/main_light"
|
||||||
TOPIC_FFW_SLEEP_HEATING_VALVE_VIDEV = "videv/ffw/sleep/heating_valve"
|
TOPIC_FFW_SLEEP_HEATING_VALVE_VIDEV = "videv/ffw/sleep/heating_valve"
|
||||||
|
TOPIC_FFW_SLEEP_WINDOW_LAMP_VIDEV = "videv/ffw/sleep/window_light"
|
||||||
|
|
||||||
|
|
||||||
# first floor east
|
# first floor east
|
||||||
@ -60,6 +73,7 @@ TOPIC_FFE_SLEEP_BED_LIGHT_DI_VIDEV = "videv/ffe/sleep/bed_light_di"
|
|||||||
TOPIC_FFE_SLEEP_BED_LIGHT_MA_VIDEV = "videv/ffe/sleep/bed_light_ma"
|
TOPIC_FFE_SLEEP_BED_LIGHT_MA_VIDEV = "videv/ffe/sleep/bed_light_ma"
|
||||||
TOPIC_FFE_SLEEP_ACTIVE_BRIGHTNESS_DEVICE_VIDEV = "videv/ffe/sleep/active_brightness_device"
|
TOPIC_FFE_SLEEP_ACTIVE_BRIGHTNESS_DEVICE_VIDEV = "videv/ffe/sleep/active_brightness_device"
|
||||||
TOPIC_FFE_SLEEP_HEATING_VALVE_VIDEV = "videv/ffe/sleep/heating_valve"
|
TOPIC_FFE_SLEEP_HEATING_VALVE_VIDEV = "videv/ffe/sleep/heating_valve"
|
||||||
|
TOPIC_FFE_SLEEP_WARDROBE_LIGHT_VIDEV = "videv/ffe/sleep/wardrobe_light"
|
||||||
|
|
||||||
# livingroom
|
# livingroom
|
||||||
TOPIC_FFE_LIVINGROOM_MAIN_LIGHT_VIDEV = "videv/ffe/livingroom/main_light"
|
TOPIC_FFE_LIVINGROOM_MAIN_LIGHT_VIDEV = "videv/ffe/livingroom/main_light"
|
||||||
@ -68,6 +82,6 @@ TOPIC_FFE_LIVINGROOM_XMAS_TREE_VIDEV = "videv/ffe/livingroom/xmas_tree"
|
|||||||
TOPIC_FFE_LIVINGROOM_HEATING_VALVE_VIDEV = "videv/ffe/livingroom/heating_valve"
|
TOPIC_FFE_LIVINGROOM_HEATING_VALVE_VIDEV = "videv/ffe/livingroom/heating_valve"
|
||||||
|
|
||||||
|
|
||||||
# first floor east
|
# stairway
|
||||||
# floor
|
# floor
|
||||||
TOPIC_STW_STAIRWAY_MAIN_LIGHT_VIDEV = "videv/stw/stairway/main_light"
|
TOPIC_STW_STAIRWAY_MAIN_LIGHT_VIDEV = "videv/stw/stairway/main_light"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user