2022-12-19 10:35:20 +01:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
#
|
|
|
|
"""
|
|
|
|
devices (DEVICES)
|
2022-12-20 19:38:57 +01:00
|
|
|
=================
|
2022-12-19 10:35:20 +01:00
|
|
|
|
|
|
|
**Author:**
|
|
|
|
|
|
|
|
* Dirk Alders <sudo-dirk@mount-mockery.de>
|
|
|
|
|
|
|
|
**Description:**
|
|
|
|
|
|
|
|
This Module supports smarthome devices
|
|
|
|
|
|
|
|
**Submodules:**
|
|
|
|
|
|
|
|
* :mod:`shelly`
|
|
|
|
* :mod:`silvercrest_powerplug`
|
|
|
|
|
|
|
|
**Unittest:**
|
|
|
|
|
|
|
|
See also the :download:`unittest <devices/_testresults_/unittest.pdf>` documentation.
|
|
|
|
|
|
|
|
**Module Documentation:**
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
__DEPENDENCIES__ = []
|
|
|
|
|
|
|
|
import json
|
|
|
|
import logging
|
|
|
|
|
|
|
|
try:
|
|
|
|
from config import APP_NAME as ROOT_LOGGER_NAME
|
|
|
|
except ImportError:
|
|
|
|
ROOT_LOGGER_NAME = 'root'
|
|
|
|
|
|
|
|
BATTERY_WARN_LEVEL = 5
|
|
|
|
|
|
|
|
|
|
|
|
def is_json(data):
|
|
|
|
try:
|
|
|
|
json.loads(data)
|
|
|
|
except json.decoder.JSONDecodeError:
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
class base(dict):
|
2022-12-25 16:31:22 +01:00
|
|
|
TX_TOPIC = "set"
|
2022-12-19 10:35:20 +01:00
|
|
|
TX_VALUE = 0
|
|
|
|
TX_DICT = 1
|
|
|
|
TX_TYPE = -1
|
|
|
|
TX_FILTER_DATA_KEYS = []
|
|
|
|
#
|
|
|
|
RX_KEYS = []
|
|
|
|
RX_IGNORE_TOPICS = []
|
|
|
|
RX_IGNORE_KEYS = []
|
|
|
|
RX_FILTER_DATA_KEYS = []
|
|
|
|
|
|
|
|
def __init__(self, mqtt_client, topic):
|
|
|
|
# data storage
|
|
|
|
self.mqtt_client = mqtt_client
|
|
|
|
self.topic = topic
|
2022-12-28 15:34:30 +01:00
|
|
|
self.logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__)
|
|
|
|
for entry in self.topic.split('/'):
|
|
|
|
self.logger = self.logger.getChild(entry)
|
2022-12-19 10:35:20 +01:00
|
|
|
# initialisations
|
|
|
|
dict.__init__(self)
|
|
|
|
mqtt_client.add_callback(
|
|
|
|
topic=self.topic, callback=self.receive_callback)
|
|
|
|
mqtt_client.add_callback(
|
|
|
|
topic=self.topic+"/#", callback=self.receive_callback)
|
|
|
|
#
|
|
|
|
self.callback_list = []
|
|
|
|
self.warning_callback = None
|
2022-12-23 11:45:00 +01:00
|
|
|
#
|
|
|
|
self.__previous__ = {}
|
2022-12-19 10:35:20 +01:00
|
|
|
|
|
|
|
def receive_callback(self, client, userdata, message):
|
|
|
|
self.unpack(message)
|
|
|
|
|
|
|
|
def unpack_filter(self, key):
|
|
|
|
if key in self.RX_FILTER_DATA_KEYS:
|
|
|
|
if self.get(key) == 1 or self.get(key) == 'on' or self.get(key) == 'ON':
|
|
|
|
self[key] = True
|
|
|
|
elif self.get(key) == 0 or self.get(key) == 'off' or self.get(key) == 'OFF':
|
|
|
|
self[key] = False
|
|
|
|
|
|
|
|
def unpack_single_value(self, key, data):
|
|
|
|
prev_value = self.get(key)
|
|
|
|
if key in self.RX_KEYS:
|
|
|
|
self[key] = data
|
2022-12-23 11:45:00 +01:00
|
|
|
self.__previous__[key] = prev_value
|
2022-12-19 10:35:20 +01:00
|
|
|
# Filter, if needed
|
|
|
|
self.unpack_filter(key)
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.debug("Received data %s - %s", key, str(self.get(key)))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.callback_caller(key, self[key], self.get(key) != self.__previous__.get(key))
|
2022-12-19 10:35:20 +01:00
|
|
|
elif key not in self.RX_IGNORE_KEYS:
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.warning('Got a message with unparsed content: "%s - %s"', key, str(data))
|
2022-12-19 10:35:20 +01:00
|
|
|
else:
|
2022-12-28 15:34:30 +01:00
|
|
|
self.logger.debug("Ignoring key %s", key)
|
2022-12-19 10:35:20 +01:00
|
|
|
|
|
|
|
def unpack(self, message):
|
|
|
|
content_key = message.topic[len(self.topic) + 1:]
|
2022-12-23 10:00:09 +01:00
|
|
|
if content_key not in self.RX_IGNORE_TOPICS and (not message.topic.endswith(self.TX_TOPIC) or len(self.TX_TOPIC) == 0):
|
2022-12-28 15:34:30 +01:00
|
|
|
self.logger.debug("Unpacking content_key \"%s\" from message.", content_key)
|
2022-12-19 10:35:20 +01:00
|
|
|
if is_json(message.payload):
|
|
|
|
data = json.loads(message.payload)
|
|
|
|
if type(data) is dict:
|
|
|
|
for key in data:
|
|
|
|
self.unpack_single_value(key, data[key])
|
|
|
|
else:
|
|
|
|
self.unpack_single_value(content_key, data)
|
|
|
|
# String
|
|
|
|
else:
|
|
|
|
self.unpack_single_value(
|
|
|
|
content_key, message.payload.decode('utf-8'))
|
|
|
|
self.warning_caller()
|
|
|
|
else:
|
2022-12-28 15:34:30 +01:00
|
|
|
self.logger.debug("Ignoring topic %s", content_key)
|
2022-12-19 10:35:20 +01:00
|
|
|
|
|
|
|
def pack_filter(self, key, data):
|
|
|
|
if key in self.TX_FILTER_DATA_KEYS:
|
|
|
|
if data is True:
|
|
|
|
return "on"
|
|
|
|
elif data is False:
|
|
|
|
return "off"
|
|
|
|
else:
|
|
|
|
return data
|
|
|
|
return data
|
|
|
|
|
2022-12-20 09:11:39 +01:00
|
|
|
def set(self, key, data):
|
|
|
|
self.pack(key, data)
|
|
|
|
|
2022-12-19 10:35:20 +01:00
|
|
|
def pack(self, key, data):
|
|
|
|
data = self.pack_filter(key, data)
|
|
|
|
if self.TX_TOPIC is not None:
|
|
|
|
if self.TX_TYPE < 0:
|
2022-12-28 15:34:30 +01:00
|
|
|
self.logger.error("Unknown tx type. Set TX_TYPE of class to a known value")
|
2022-12-19 10:35:20 +01:00
|
|
|
else:
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.debug("Sending data for %s - %s", key, str(data))
|
2022-12-19 10:35:20 +01:00
|
|
|
if self.TX_TYPE == self.TX_DICT:
|
|
|
|
self.mqtt_client.send('/'.join([self.topic, self.TX_TOPIC]), json.dumps({key: data}))
|
|
|
|
else:
|
|
|
|
if type(data) not in [str, bytes]:
|
|
|
|
data = json.dumps(data)
|
2022-12-25 16:31:22 +01:00
|
|
|
self.mqtt_client.send('/'.join([self.topic, key, self.TX_TOPIC] if len(self.TX_TOPIC) > 0 else [self.topic, key]), data)
|
2022-12-19 10:35:20 +01:00
|
|
|
else:
|
2022-12-28 15:34:30 +01:00
|
|
|
self.logger.error("Unknown tx toptic. Set TX_TOPIC of class to a known value")
|
2022-12-19 10:35:20 +01:00
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def add_callback(self, key, data, callback, on_change_only=False):
|
2022-12-19 10:35:20 +01:00
|
|
|
"""
|
|
|
|
key: key or None for all keys
|
|
|
|
data: data or None for all data
|
|
|
|
"""
|
2022-12-25 16:31:22 +01:00
|
|
|
cb_tup = (key, data, callback, on_change_only)
|
2022-12-19 10:35:20 +01:00
|
|
|
if cb_tup not in self.callback_list:
|
|
|
|
self.callback_list.append(cb_tup)
|
|
|
|
|
|
|
|
def add_warning_callback(self, callback):
|
|
|
|
self.warning_callback = callback
|
|
|
|
|
|
|
|
def warning_call_condition(self):
|
|
|
|
return False
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def callback_caller(self, key, data, value_changed):
|
|
|
|
for cb_key, cb_data, callback, on_change_only in self.callback_list:
|
2022-12-19 16:11:35 +01:00
|
|
|
if (cb_key == key or cb_key is None) and (cb_data == data or cb_data is None) and callback is not None:
|
2022-12-25 16:31:22 +01:00
|
|
|
if not on_change_only or value_changed:
|
|
|
|
callback(self, key, data)
|
2022-12-19 10:35:20 +01:00
|
|
|
|
|
|
|
def warning_caller(self):
|
|
|
|
if self.warning_call_condition():
|
|
|
|
warn_txt = self.warning_text()
|
2022-12-28 15:34:30 +01:00
|
|
|
self.logger.warning(warn_txt)
|
2022-12-19 10:35:20 +01:00
|
|
|
if self.warning_callback is not None:
|
|
|
|
self.warning_callback(self, warn_txt)
|
|
|
|
|
2022-12-25 20:05:06 +01:00
|
|
|
def warning_text(self):
|
2022-12-19 10:35:20 +01:00
|
|
|
return "default warning text - replace parent warning_text function"
|
|
|
|
|
2022-12-23 11:45:00 +01:00
|
|
|
def previous_value(self, key):
|
2022-12-23 11:51:41 +01:00
|
|
|
return self.__previous__.get(key)
|
2022-12-23 11:45:00 +01:00
|
|
|
|
2022-12-19 10:35:20 +01:00
|
|
|
|
|
|
|
class shelly(base):
|
|
|
|
KEY_OUTPUT_0 = "relay/0"
|
|
|
|
KEY_OUTPUT_1 = "relay/1"
|
|
|
|
KEY_INPUT_0 = "input/0"
|
|
|
|
KEY_INPUT_1 = "input/1"
|
2022-12-22 07:55:56 +01:00
|
|
|
KEY_LONGPUSH_0 = "longpush/0"
|
|
|
|
KEY_LONGPUSH_1 = "longpush/1"
|
2022-12-19 10:35:20 +01:00
|
|
|
KEY_TEMPERATURE = "temperature"
|
|
|
|
KEY_OVERTEMPERATURE = "overtemperature"
|
2022-12-25 16:31:22 +01:00
|
|
|
KEY_ID = "id"
|
|
|
|
KEY_MODEL = "model"
|
|
|
|
KEY_MAC = "mac"
|
|
|
|
KEY_IP = "ip"
|
|
|
|
KEY_NEW_FIRMWARE = "new_fw"
|
|
|
|
KEY_FIRMWARE_VERSION = "fw_ver"
|
|
|
|
#
|
|
|
|
TX_TOPIC = "command"
|
2022-12-19 10:35:20 +01:00
|
|
|
TX_TYPE = base.TX_VALUE
|
|
|
|
TX_FILTER_DATA_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1]
|
|
|
|
#
|
2022-12-25 16:31:22 +01:00
|
|
|
RX_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_INPUT_0, KEY_INPUT_1, KEY_LONGPUSH_0, KEY_LONGPUSH_1, KEY_OVERTEMPERATURE, KEY_TEMPERATURE,
|
|
|
|
KEY_ID, KEY_MODEL, KEY_MAC, KEY_IP, KEY_NEW_FIRMWARE, KEY_FIRMWARE_VERSION]
|
|
|
|
RX_IGNORE_TOPICS = [KEY_OUTPUT_0 + '/' + "energy", KEY_OUTPUT_1 + '/' + "energy", 'input_event/0', 'input_event/1']
|
2022-12-19 10:35:20 +01:00
|
|
|
RX_IGNORE_KEYS = ['temperature_f']
|
2022-12-25 16:31:22 +01:00
|
|
|
RX_FILTER_DATA_KEYS = [KEY_INPUT_0, KEY_INPUT_1, KEY_LONGPUSH_0, KEY_LONGPUSH_1, KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_OVERTEMPERATURE]
|
2022-12-19 10:35:20 +01:00
|
|
|
|
|
|
|
def __init__(self, mqtt_client, topic):
|
|
|
|
super().__init__(mqtt_client, topic)
|
|
|
|
|
|
|
|
#
|
|
|
|
# WARNING CALL
|
|
|
|
#
|
|
|
|
def warning_call_condition(self):
|
|
|
|
return self.get(self.KEY_OVERTEMPERATURE)
|
|
|
|
|
|
|
|
def warning_text(self):
|
|
|
|
if self.overtemperature:
|
|
|
|
if self.temperature is not None:
|
|
|
|
return "Overtemperature detected for %s. Temperature was %.1f°C." % (self.topic, self.temperature)
|
|
|
|
else:
|
|
|
|
return "Overtemperature detected for %s." % self.topic
|
|
|
|
|
|
|
|
#
|
|
|
|
# RX
|
|
|
|
#
|
|
|
|
@property
|
|
|
|
def output_0(self):
|
|
|
|
"""rv: [True, False]"""
|
|
|
|
return self.get(self.KEY_OUTPUT_0)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def output_1(self):
|
|
|
|
"""rv: [True, False]"""
|
|
|
|
return self.get(self.KEY_OUTPUT_1)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def input_0(self):
|
|
|
|
"""rv: [True, False]"""
|
|
|
|
return self.get(self.KEY_INPUT_0)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def input_1(self):
|
|
|
|
"""rv: [True, False]"""
|
|
|
|
return self.get(self.KEY_INPUT_1)
|
|
|
|
|
2022-12-22 07:55:56 +01:00
|
|
|
@property
|
|
|
|
def longpush_0(self):
|
|
|
|
"""rv: [True, False]"""
|
|
|
|
return self.get(self.KEY_LONGPUSH_0)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def longpush_1(self):
|
|
|
|
"""rv: [True, False]"""
|
|
|
|
return self.get(self.KEY_LONGPUSH_1)
|
|
|
|
|
2022-12-19 10:35:20 +01:00
|
|
|
@property
|
|
|
|
def temperature(self):
|
|
|
|
"""rv: numeric value"""
|
|
|
|
return self.get(self.KEY_TEMPERATURE)
|
|
|
|
|
|
|
|
#
|
|
|
|
# TX
|
|
|
|
#
|
|
|
|
def set_output_0(self, state):
|
|
|
|
"""state: [True, False, 'toggle']"""
|
|
|
|
self.pack(self.KEY_OUTPUT_0, state)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_output_0_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.log(logging.INFO if data != self.output_0 else logging.DEBUG, "Changing output 0 to %s", str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_0(data)
|
|
|
|
|
|
|
|
def toggle_output_0_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.info("Toggeling output 0")
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_0('toggle')
|
|
|
|
|
2022-12-19 10:35:20 +01:00
|
|
|
def set_output_1(self, state):
|
|
|
|
"""state: [True, False, 'toggle']"""
|
|
|
|
self.pack(self.KEY_OUTPUT_1, state)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_output_1_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.log(logging.INFO if data != self.output_1 else logging.DEBUG, "Changing output 1 to %s", str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_1(data)
|
|
|
|
|
|
|
|
def toggle_output_1_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.info("Toggeling output 1")
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_1('toggle')
|
|
|
|
|
2022-12-19 10:35:20 +01:00
|
|
|
|
|
|
|
class silvercrest_powerplug(base):
|
|
|
|
KEY_LINKQUALITY = "linkquality"
|
|
|
|
KEY_OUTPUT_0 = "state"
|
|
|
|
#
|
|
|
|
TX_TYPE = base.TX_DICT
|
|
|
|
TX_FILTER_DATA_KEYS = [KEY_OUTPUT_0]
|
|
|
|
#
|
|
|
|
RX_KEYS = [KEY_LINKQUALITY, KEY_OUTPUT_0]
|
|
|
|
RX_FILTER_DATA_KEYS = [KEY_OUTPUT_0]
|
|
|
|
|
|
|
|
def __init__(self, mqtt_client, topic):
|
|
|
|
super().__init__(mqtt_client, topic)
|
|
|
|
|
|
|
|
#
|
|
|
|
# RX
|
|
|
|
#
|
|
|
|
@property
|
|
|
|
def output_0(self):
|
|
|
|
"""rv: [True, False]"""
|
|
|
|
return self.get(self.KEY_OUTPUT_0)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def linkquality(self):
|
|
|
|
"""rv: numeric value"""
|
|
|
|
return self.get(self.KEY_LINKQUALITY)
|
|
|
|
|
|
|
|
#
|
|
|
|
# TX
|
|
|
|
#
|
|
|
|
def set_output_0(self, state):
|
|
|
|
"""state: [True, False, 'toggle']"""
|
|
|
|
self.pack(self.KEY_OUTPUT_0, state)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_output_0_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.log(logging.INFO if data != self.output_0 else logging.DEBUG, "Changing output 0 to %s", str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_0(data)
|
|
|
|
|
|
|
|
def toggle_output_0_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.info("Toggeling output 0")
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_0('toggle')
|
|
|
|
|
2022-12-19 10:35:20 +01:00
|
|
|
|
2022-12-25 20:05:06 +01:00
|
|
|
class silvercrest_motion_sensor(base):
|
|
|
|
KEY_BATTERY = "battery"
|
|
|
|
KEY_BATTERY_LOW = "battery_low"
|
|
|
|
KEY_LINKQUALITY = "linkquality"
|
|
|
|
KEY_OCCUPANCY = "occupancy"
|
|
|
|
KEY_UNMOUNTED = "tamper"
|
|
|
|
KEY_VOLTAGE = "voltage"
|
|
|
|
#
|
|
|
|
RX_KEYS = [KEY_BATTERY, KEY_BATTERY_LOW, KEY_LINKQUALITY, KEY_OCCUPANCY, KEY_UNMOUNTED, KEY_VOLTAGE]
|
|
|
|
|
|
|
|
def __init__(self, mqtt_client, topic):
|
|
|
|
super().__init__(mqtt_client, topic)
|
|
|
|
|
|
|
|
def warning_call_condition(self):
|
|
|
|
return self.get(self.KEY_BATTERY_LOW)
|
|
|
|
|
|
|
|
def warning_text(self, data):
|
|
|
|
return "Battery low: level=%d" % self.get(self.KEY_BATTERY)
|
|
|
|
|
|
|
|
#
|
|
|
|
# RX
|
|
|
|
#
|
|
|
|
|
|
|
|
@property
|
|
|
|
def linkquality(self):
|
|
|
|
"""rv: numeric value"""
|
|
|
|
return self.get(self.KEY_LINKQUALITY)
|
|
|
|
|
|
|
|
|
2022-12-19 10:35:20 +01:00
|
|
|
class my_powerplug(base):
|
|
|
|
KEY_OUTPUT_0 = "output/1"
|
|
|
|
KEY_OUTPUT_1 = "output/2"
|
|
|
|
KEY_OUTPUT_2 = "output/3"
|
|
|
|
KEY_OUTPUT_3 = "output/4"
|
|
|
|
KEY_OUTPUT_ALL = "output/all"
|
2022-12-23 11:45:00 +01:00
|
|
|
KEY_OUTPUT_LIST = [KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_OUTPUT_2, KEY_OUTPUT_3]
|
2022-12-19 10:35:20 +01:00
|
|
|
#
|
|
|
|
TX_TYPE = base.TX_VALUE
|
|
|
|
#
|
|
|
|
RX_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_OUTPUT_2, KEY_OUTPUT_3]
|
|
|
|
|
|
|
|
def __init__(self, mqtt_client, topic):
|
|
|
|
super().__init__(mqtt_client, topic)
|
|
|
|
|
|
|
|
#
|
|
|
|
# RX
|
|
|
|
#
|
|
|
|
@property
|
|
|
|
def output_0(self):
|
|
|
|
"""rv: [True, False]"""
|
|
|
|
return self.get(self.KEY_OUTPUT_0)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def output_1(self):
|
|
|
|
"""rv: [True, False]"""
|
|
|
|
return self.get(self.KEY_OUTPUT_1)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def output_2(self):
|
|
|
|
"""rv: [True, False]"""
|
|
|
|
return self.get(self.KEY_OUTPUT_2)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def output_3(self):
|
|
|
|
"""rv: [True, False]"""
|
|
|
|
return self.get(self.KEY_OUTPUT_3)
|
|
|
|
|
|
|
|
#
|
|
|
|
# TX
|
|
|
|
#
|
2022-12-23 11:45:00 +01:00
|
|
|
def set_output(self, key, state):
|
|
|
|
if key in self.KEY_OUTPUT_LIST:
|
|
|
|
self.pack(key, state)
|
|
|
|
else:
|
|
|
|
logging.error("Unknown key to set the output!")
|
|
|
|
|
2022-12-19 10:35:20 +01:00
|
|
|
def set_output_0(self, state):
|
|
|
|
"""state: [True, False, 'toggle']"""
|
|
|
|
self.pack(self.KEY_OUTPUT_0, state)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_output_0_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.log(logging.INFO if data != self.output_0 else logging.DEBUG, "Changing output 0 to %s", str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_0(data)
|
|
|
|
|
|
|
|
def toggle_output_0_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.info("Toggeling output 0")
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_0('toggle')
|
|
|
|
|
2022-12-19 10:35:20 +01:00
|
|
|
def set_output_1(self, state):
|
|
|
|
"""state: [True, False, 'toggle']"""
|
|
|
|
self.pack(self.KEY_OUTPUT_1, state)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_output_1_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.log(logging.INFO if data != self.output_1 else logging.DEBUG, "Changing output 1 to %s", str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_1(data)
|
|
|
|
|
|
|
|
def toggle_output_1_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.info("Toggeling output 1")
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_1('toggle')
|
|
|
|
|
2022-12-19 10:35:20 +01:00
|
|
|
def set_output_2(self, state):
|
|
|
|
"""state: [True, False, 'toggle']"""
|
|
|
|
self.pack(self.KEY_OUTPUT_2, state)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_output_2_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.log(logging.INFO if data != self.output_2 else logging.DEBUG, "Changing output 2 to %s", str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_2(data)
|
|
|
|
|
|
|
|
def toggle_output_2_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.info("Toggeling output 2")
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_2('toggle')
|
|
|
|
|
2022-12-19 10:35:20 +01:00
|
|
|
def set_output_3(self, state):
|
|
|
|
"""state: [True, False, 'toggle']"""
|
|
|
|
self.pack(self.KEY_OUTPUT_3, state)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_output_3_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.log(logging.INFO if data != self.output_3 else logging.DEBUG, "Changing output 3 to %s", str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_3(data)
|
|
|
|
|
|
|
|
def toggle_output_3_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.info("Toggeling output 3")
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_3('toggle')
|
|
|
|
|
2022-12-19 10:35:20 +01:00
|
|
|
def set_output_all(self, state):
|
|
|
|
"""state: [True, False, 'toggle']"""
|
|
|
|
self.pack(self.KEY_OUTPUT_ALL, state)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_output_all_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.info("Changing all outputs to %s", str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_all(data)
|
|
|
|
|
|
|
|
def toggle_output_all_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.info("Toggeling all outputs")
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_0('toggle')
|
|
|
|
|
2022-12-19 10:35:20 +01:00
|
|
|
|
|
|
|
class tradfri_light(base):
|
|
|
|
KEY_LINKQUALITY = "linkquality"
|
|
|
|
KEY_OUTPUT_0 = "state"
|
|
|
|
KEY_BRIGHTNESS = "brightness"
|
|
|
|
KEY_COLOR_TEMP = "color_temp"
|
2022-12-20 19:38:57 +01:00
|
|
|
KEY_BRIGHTNESS_FADE = "brightness_move"
|
2022-12-19 10:35:20 +01:00
|
|
|
#
|
|
|
|
TX_TYPE = base.TX_DICT
|
2022-12-20 19:38:57 +01:00
|
|
|
TX_FILTER_DATA_KEYS = [KEY_OUTPUT_0, KEY_BRIGHTNESS, KEY_COLOR_TEMP, KEY_BRIGHTNESS_FADE]
|
2022-12-19 10:35:20 +01:00
|
|
|
#
|
|
|
|
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 __init__(self, mqtt_client, topic):
|
|
|
|
super().__init__(mqtt_client, topic)
|
|
|
|
|
|
|
|
def unpack_filter(self, key):
|
|
|
|
if key == self.KEY_BRIGHTNESS:
|
2022-12-20 01:30:34 +01:00
|
|
|
self[key] = (self[key] - 1) * 100 / 254
|
2022-12-19 10:35:20 +01:00
|
|
|
elif key == self.KEY_COLOR_TEMP:
|
2022-12-25 16:31:22 +01:00
|
|
|
self[key] = (self[key] - 250) * 10 / 204
|
2022-12-19 10:35:20 +01:00
|
|
|
else:
|
|
|
|
super().unpack_filter(key)
|
|
|
|
|
|
|
|
def pack_filter(self, key, data):
|
|
|
|
if key == self.KEY_BRIGHTNESS:
|
2022-12-20 01:30:34 +01:00
|
|
|
return data * 254 / 100 + 1
|
2022-12-19 10:35:20 +01:00
|
|
|
elif key == self.KEY_COLOR_TEMP:
|
2022-12-25 16:31:22 +01:00
|
|
|
return data * 204 / 10 + 250
|
2022-12-19 10:35:20 +01:00
|
|
|
else:
|
|
|
|
return super().pack_filter(key, data)
|
|
|
|
|
|
|
|
#
|
|
|
|
# RX
|
|
|
|
#
|
|
|
|
@property
|
|
|
|
def output_0(self):
|
|
|
|
"""rv: [True, False]"""
|
2022-12-20 01:30:34 +01:00
|
|
|
return self.get(self.KEY_OUTPUT_0, False)
|
2022-12-19 10:35:20 +01:00
|
|
|
|
|
|
|
@property
|
|
|
|
def linkquality(self):
|
|
|
|
"""rv: numeric value"""
|
2022-12-20 01:30:34 +01:00
|
|
|
return self.get(self.KEY_LINKQUALITY, 0)
|
2022-12-19 10:35:20 +01:00
|
|
|
|
|
|
|
@property
|
|
|
|
def brightness(self):
|
2022-12-25 16:31:22 +01:00
|
|
|
"""rv: numeric value [0%, ..., 100%]"""
|
2022-12-20 01:30:34 +01:00
|
|
|
return self.get(self.KEY_BRIGHTNESS, 0)
|
2022-12-19 10:35:20 +01:00
|
|
|
|
|
|
|
@property
|
|
|
|
def color_temp(self):
|
2022-12-25 16:31:22 +01:00
|
|
|
"""rv: numeric value [0, ..., 10]"""
|
2022-12-20 01:30:34 +01:00
|
|
|
return self.get(self.KEY_COLOR_TEMP, 0)
|
2022-12-19 10:35:20 +01:00
|
|
|
|
|
|
|
#
|
|
|
|
# TX
|
|
|
|
#
|
|
|
|
def set_output_0(self, state):
|
|
|
|
"""state: [True, False, 'toggle']"""
|
|
|
|
self.pack(self.KEY_OUTPUT_0, state)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_output_0_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.log(logging.INFO if data != self.output_0 else logging.DEBUG, "Changing output 0 to %s", str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_0(data)
|
|
|
|
|
|
|
|
def toggle_output_0_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.info("Toggeling output 0")
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_output_0('toggle')
|
|
|
|
|
2022-12-19 10:35:20 +01:00
|
|
|
def set_brightness(self, brightness):
|
|
|
|
"""brightness: [0, ..., 100]"""
|
|
|
|
self.pack(self.KEY_BRIGHTNESS, brightness)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_brightness_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.log(logging.INFO if data != self.brightness else logging.DEBUG, "Changing brightness to %s", str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_brightness(data)
|
|
|
|
|
2022-12-22 20:12:57 +01:00
|
|
|
def default_inc(self, speed=40):
|
2022-12-20 19:38:57 +01:00
|
|
|
self.pack(self.KEY_BRIGHTNESS_FADE, speed)
|
|
|
|
|
2022-12-22 20:12:57 +01:00
|
|
|
def default_dec(self, speed=-40):
|
|
|
|
self.default_inc(speed)
|
2022-12-20 19:38:57 +01:00
|
|
|
|
2022-12-22 20:12:57 +01:00
|
|
|
def default_stop(self):
|
|
|
|
self.default_inc(0)
|
2022-12-20 19:38:57 +01:00
|
|
|
|
2022-12-19 10:35:20 +01:00
|
|
|
def set_color_temp(self, color_temp):
|
2022-12-25 16:31:22 +01:00
|
|
|
"""color_temp: [0, ..., 10]"""
|
2022-12-19 10:35:20 +01:00
|
|
|
self.pack(self.KEY_COLOR_TEMP, color_temp)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_color_temp_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.log(logging.INFO if data != self.color_temp else logging.DEBUG, "Changing color temperature to %s", str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_color_temp(data)
|
|
|
|
|
2022-12-19 10:35:20 +01:00
|
|
|
|
|
|
|
class tradfri_button(base):
|
2022-12-22 07:55:56 +01:00
|
|
|
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"
|
|
|
|
#
|
2022-12-19 10:35:20 +01:00
|
|
|
KEY_LINKQUALITY = "linkquality"
|
|
|
|
KEY_BATTERY = "battery"
|
|
|
|
KEY_ACTION = "action"
|
2022-12-22 07:55:56 +01:00
|
|
|
KEY_ACTION_DURATION = "action_duration"
|
2022-12-19 10:35:20 +01:00
|
|
|
#
|
|
|
|
RX_KEYS = [KEY_LINKQUALITY, KEY_BATTERY, KEY_ACTION]
|
2022-12-22 07:55:56 +01:00
|
|
|
RX_IGNORE_KEYS = ['update', KEY_ACTION_DURATION]
|
2022-12-19 10:35:20 +01:00
|
|
|
|
|
|
|
def __init__(self, mqtt_client, topic):
|
|
|
|
super().__init__(mqtt_client, topic)
|
|
|
|
|
|
|
|
#
|
|
|
|
# RX
|
|
|
|
#
|
|
|
|
@property
|
|
|
|
def action(self):
|
|
|
|
"""rv: action_txt"""
|
|
|
|
return self.get(self.KEY_ACTION)
|
|
|
|
|
|
|
|
#
|
|
|
|
# WARNING CALL
|
|
|
|
#
|
|
|
|
def warning_call_condition(self):
|
2023-01-04 01:20:00 +01:00
|
|
|
return self.get(self.KEY_BATTERY) is not None and self.get(self.KEY_BATTERY) <= BATTERY_WARN_LEVEL
|
2022-12-19 10:35:20 +01:00
|
|
|
|
|
|
|
def warning_text(self):
|
|
|
|
return "Low battery level detected for %s. Battery level was %.0f%%." % (self.topic, self.get(self.KEY_BATTERY))
|
2022-12-19 16:11:35 +01:00
|
|
|
|
|
|
|
|
2023-01-09 16:42:18 +01:00
|
|
|
class nodered_gui_leds(base):
|
|
|
|
KEY_LED_0 = "led0"
|
|
|
|
KEY_LED_1 = "led1"
|
|
|
|
KEY_LED_2 = "led2"
|
|
|
|
KEY_LED_3 = "led3"
|
|
|
|
KEY_LED_4 = "led4"
|
|
|
|
KEY_LED_5 = "led5"
|
|
|
|
KEY_LED_6 = "led6"
|
|
|
|
KEY_LED_7 = "led7"
|
|
|
|
KEY_LED_8 = "led8"
|
|
|
|
KEY_LED_9 = "led9"
|
|
|
|
KEY_LED_LIST = [KEY_LED_0, KEY_LED_1, KEY_LED_2, KEY_LED_3, KEY_LED_4, KEY_LED_5, KEY_LED_6, KEY_LED_7, KEY_LED_8, KEY_LED_9]
|
2022-12-19 16:11:35 +01:00
|
|
|
#
|
|
|
|
TX_TYPE = base.TX_VALUE
|
|
|
|
|
2023-01-09 16:42:18 +01:00
|
|
|
def set_led(self, key, data):
|
|
|
|
"""data: [True, False]"""
|
|
|
|
self.logger.debug("Sending %s with content %s", key, str(data))
|
|
|
|
self.pack(key, data)
|
2022-12-20 01:30:34 +01:00
|
|
|
|
2022-12-21 14:26:35 +01:00
|
|
|
|
2023-01-09 16:42:18 +01:00
|
|
|
class nodered_gui_timer(base):
|
|
|
|
KEY_TIMER = "timer"
|
|
|
|
#
|
|
|
|
TX_TYPE = base.TX_VALUE
|
2022-12-21 14:26:35 +01:00
|
|
|
|
2023-01-09 16:42:18 +01:00
|
|
|
def set_timer(self, data):
|
|
|
|
"""data: numeric"""
|
|
|
|
self.pack(self.KEY_TIMER, data)
|
2022-12-22 07:55:56 +01:00
|
|
|
|
2023-01-09 16:42:18 +01:00
|
|
|
def set_timer_mcb(self, device, key, data):
|
|
|
|
self.logger.debug("Sending %s with content %s", key, str(data))
|
|
|
|
self.set_timer(data)
|
2022-12-20 01:30:34 +01:00
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
|
|
|
|
class nodered_gui_button(base):
|
|
|
|
KEY_STATE = "state"
|
|
|
|
#
|
|
|
|
RX_KEYS = [KEY_STATE]
|
|
|
|
|
|
|
|
#
|
|
|
|
# RX
|
|
|
|
#
|
|
|
|
@property
|
|
|
|
def state(self):
|
|
|
|
"""rv: [True, False]"""
|
|
|
|
return self.get(self.KEY_STATE)
|
|
|
|
|
|
|
|
|
|
|
|
class nodered_gui_switch(nodered_gui_button):
|
|
|
|
TX_TYPE = base.TX_VALUE
|
|
|
|
|
|
|
|
#
|
|
|
|
# TX
|
|
|
|
#
|
|
|
|
def set_state(self, data):
|
|
|
|
"""data: [True, False]"""
|
|
|
|
self.pack(self.KEY_STATE, data)
|
|
|
|
|
|
|
|
def set_state_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.debug("Sending %s with content %s", key, str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_state(data)
|
|
|
|
|
|
|
|
|
2023-01-08 20:35:36 +01:00
|
|
|
class nodered_gui_light(nodered_gui_switch, nodered_gui_leds, nodered_gui_timer):
|
2022-12-25 16:31:22 +01:00
|
|
|
KEY_ENABLE = "enable"
|
|
|
|
KEY_BRIGHTNESS = "brightness"
|
|
|
|
KEY_COLOR_TEMP = "color_temp"
|
|
|
|
#
|
|
|
|
TX_TYPE = base.TX_VALUE
|
|
|
|
#
|
2023-01-08 11:41:08 +01:00
|
|
|
RX_KEYS = nodered_gui_switch.RX_KEYS + [KEY_ENABLE, KEY_BRIGHTNESS, KEY_COLOR_TEMP]
|
2022-12-25 16:31:22 +01:00
|
|
|
|
|
|
|
#
|
|
|
|
# RX
|
|
|
|
#
|
|
|
|
@property
|
|
|
|
def enable(self):
|
|
|
|
"""rv: [True, False]"""
|
|
|
|
return self.get(self.KEY_ENABLE)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def brightness(self):
|
|
|
|
"""rv: [True, False]"""
|
|
|
|
return self.get(self.KEY_BRIGHTNESS)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def color_temp(self):
|
|
|
|
"""rv: [True, False]"""
|
|
|
|
return self.get(self.KEY_COLOR_TEMP)
|
|
|
|
|
|
|
|
#
|
|
|
|
# TX
|
|
|
|
#
|
|
|
|
def set_enable(self, data):
|
2022-12-20 01:30:34 +01:00
|
|
|
"""data: [True, False]"""
|
|
|
|
self.pack(self.KEY_ENABLE, data)
|
2022-12-21 14:26:35 +01:00
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_enable_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.debug("Sending %s with content %s", key, str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_enable(data)
|
|
|
|
|
|
|
|
def set_brightness(self, data):
|
|
|
|
"""data: [0%, ..., 100%]"""
|
|
|
|
self.pack(self.KEY_BRIGHTNESS, data)
|
|
|
|
|
|
|
|
def set_brightness_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.debug("Sending %s with content %s", key, str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_brightness(data)
|
|
|
|
|
|
|
|
def set_color_temp(self, data):
|
|
|
|
"""data: [0, ..., 10]"""
|
|
|
|
self.pack(self.KEY_COLOR_TEMP, data)
|
|
|
|
|
|
|
|
def set_color_temp_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.debug("Sending %s with content %s", key, str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_color_temp(data)
|
|
|
|
|
|
|
|
|
2023-01-09 16:42:18 +01:00
|
|
|
class nodered_gui_radiator(nodered_gui_timer):
|
|
|
|
KEY_TEMPERATURE = "temperature"
|
|
|
|
KEY_SETPOINT_TEMP = "setpoint_temp"
|
|
|
|
KEY_SETPOINT_TO_DEFAULT = "setpoint_to_default"
|
|
|
|
KEY_BOOST = 'boost'
|
2023-01-10 23:17:47 +01:00
|
|
|
KEY_AWAY = "away"
|
|
|
|
KEY_SUMMER = "summer"
|
|
|
|
KEY_ENABLE = "enable"
|
2023-01-09 16:42:18 +01:00
|
|
|
#
|
2023-01-10 23:17:47 +01:00
|
|
|
RX_KEYS = [KEY_TEMPERATURE, KEY_SETPOINT_TEMP, KEY_SETPOINT_TO_DEFAULT, KEY_BOOST, KEY_AWAY, KEY_SUMMER]
|
|
|
|
|
2023-01-09 16:42:18 +01:00
|
|
|
#
|
|
|
|
# TX
|
|
|
|
#
|
|
|
|
def set_temperature(self, data):
|
|
|
|
"""data: [True, False]"""
|
|
|
|
self.pack(self.KEY_TEMPERATURE, data)
|
|
|
|
|
|
|
|
def set_temperature_mcb(self, device, key, data):
|
|
|
|
self.logger.debug("Sending %s with content %s", key, str(data))
|
|
|
|
self.set_temperature(data)
|
|
|
|
|
|
|
|
def set_setpoint_temperature(self, data):
|
|
|
|
"""data: [True, False]"""
|
|
|
|
self.pack(self.KEY_SETPOINT_TEMP, data)
|
|
|
|
|
|
|
|
def set_setpoint_temperature_mcb(self, device, key, data):
|
|
|
|
self.logger.debug("Sending %s with content %s", key, str(data))
|
|
|
|
self.set_setpoint_temperature(data)
|
|
|
|
|
2023-01-10 23:17:47 +01:00
|
|
|
def set_away(self, data):
|
|
|
|
"""data: [True, False]"""
|
|
|
|
self.pack(self.KEY_AWAY, data)
|
|
|
|
|
|
|
|
def set_away_mcb(self, device, key, data):
|
|
|
|
self.logger.debug("Sending %s with content %s", key, str(data))
|
|
|
|
self.set_away(data)
|
|
|
|
|
|
|
|
def set_summer(self, data):
|
|
|
|
"""data: [True, False]"""
|
|
|
|
self.pack(self.KEY_SUMMER, data)
|
|
|
|
|
|
|
|
def set_summer_mcb(self, device, key, data):
|
|
|
|
self.logger.debug("Sending %s with content %s", key, str(data))
|
|
|
|
self.set_summer(data)
|
|
|
|
|
2023-01-11 08:17:37 +01:00
|
|
|
def set_enable(self, data):
|
|
|
|
"""data: [True, False]"""
|
|
|
|
self.pack(self.KEY_ENABLE, data)
|
|
|
|
|
|
|
|
def set_enable_mcb(self, device, key, data):
|
|
|
|
self.logger.debug("Sending %s with content %s", key, str(data))
|
|
|
|
self.set_enable(data)
|
|
|
|
|
2023-01-09 16:42:18 +01:00
|
|
|
|
2022-12-21 14:26:35 +01:00
|
|
|
class brennenstuhl_heatingvalve(base):
|
|
|
|
KEY_LINKQUALITY = "linkquality"
|
|
|
|
KEY_BATTERY = "battery"
|
|
|
|
KEY_HEATING_SETPOINT = "current_heating_setpoint"
|
|
|
|
KEY_TEMPERATURE = "local_temperature"
|
|
|
|
#
|
|
|
|
KEY_AWAY_MODE = "away_mode"
|
|
|
|
KEY_CHILD_LOCK = "child_lock"
|
|
|
|
KEY_PRESET = "preset"
|
|
|
|
KEY_SYSTEM_MODE = "system_mode"
|
|
|
|
KEY_VALVE_DETECTION = "valve_detection"
|
|
|
|
KEY_WINDOW_DETECTION = "window_detection"
|
|
|
|
#
|
|
|
|
TX_TYPE = base.TX_DICT
|
|
|
|
#
|
|
|
|
RX_KEYS = [KEY_LINKQUALITY, KEY_BATTERY, KEY_HEATING_SETPOINT, KEY_TEMPERATURE]
|
2022-12-25 16:31:22 +01:00
|
|
|
RX_IGNORE_KEYS = [KEY_AWAY_MODE, KEY_CHILD_LOCK, KEY_PRESET, KEY_SYSTEM_MODE, KEY_VALVE_DETECTION, KEY_WINDOW_DETECTION]
|
2022-12-21 14:26:35 +01:00
|
|
|
|
|
|
|
def __init__(self, mqtt_client, topic):
|
|
|
|
super().__init__(mqtt_client, topic)
|
2022-12-25 16:31:22 +01:00
|
|
|
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"}))
|
2022-12-21 14:26:35 +01:00
|
|
|
|
|
|
|
def warning_call_condition(self):
|
2023-01-06 21:36:31 +01:00
|
|
|
return self.get(self.KEY_BATTERY, 100) <= BATTERY_WARN_LEVEL
|
2022-12-21 14:26:35 +01:00
|
|
|
|
|
|
|
def warning_text(self):
|
|
|
|
return "Low battery level detected for %s. Battery level was %.0f%%." % (self.topic, self.get(self.KEY_BATTERY))
|
|
|
|
|
|
|
|
#
|
|
|
|
# RX
|
|
|
|
#
|
|
|
|
@property
|
|
|
|
def linkqulity(self):
|
|
|
|
return self.get(self.KEY_LINKQUALITY)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def heating_setpoint(self):
|
|
|
|
return self.get(self.KEY_HEATING_SETPOINT)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def temperature(self):
|
|
|
|
return self.get(self.KEY_TEMPERATURE)
|
|
|
|
|
|
|
|
#
|
|
|
|
# TX
|
|
|
|
#
|
|
|
|
def set_heating_setpoint(self, setpoint):
|
|
|
|
self.pack(self.KEY_HEATING_SETPOINT, setpoint)
|
2022-12-22 20:12:57 +01:00
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_heating_setpoint_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.info("Changing heating setpoint to %s", str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_heating_setpoint(data)
|
|
|
|
|
2022-12-22 20:12:57 +01:00
|
|
|
|
|
|
|
class remote(base):
|
|
|
|
KEY_CD = "CD"
|
|
|
|
KEY_LINE1 = "LINE1"
|
|
|
|
KEY_LINE3 = "LINE3"
|
|
|
|
KEY_MUTE = "MUTE"
|
|
|
|
KEY_POWER = "POWER"
|
|
|
|
KEY_VOLDOWN = "VOLDOWN"
|
|
|
|
KEY_VOLUP = "VOLUP"
|
|
|
|
#
|
|
|
|
TX_TOPIC = ''
|
|
|
|
TX_TYPE = base.TX_VALUE
|
2022-12-23 10:00:09 +01:00
|
|
|
#
|
|
|
|
RX_IGNORE_TOPICS = [KEY_CD, KEY_LINE1, KEY_LINE3, KEY_MUTE, KEY_POWER, KEY_VOLUP, KEY_VOLDOWN]
|
2022-12-22 20:12:57 +01:00
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_cd(self, device=None, key=None, data=None):
|
2022-12-22 20:12:57 +01:00
|
|
|
self.pack(self.KEY_CD, None)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_line1(self, device=None, key=None, data=None):
|
2022-12-22 20:12:57 +01:00
|
|
|
self.pack(self.KEY_LINE1, None)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_line3(self, device=None, key=None, data=None):
|
2022-12-22 20:12:57 +01:00
|
|
|
self.pack(self.KEY_LINE3, None)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_mute(self, device=None, key=None, data=None):
|
2022-12-22 20:12:57 +01:00
|
|
|
self.pack(self.KEY_MUTE, None)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_power(self, device=None, key=None, data=None):
|
2022-12-22 20:12:57 +01:00
|
|
|
self.pack(self.KEY_POWER, None)
|
|
|
|
|
|
|
|
def set_volume_up(self, data=False):
|
|
|
|
"""data: [True, False]"""
|
|
|
|
self.pack(self.KEY_VOLUP, data)
|
|
|
|
|
|
|
|
def set_volume_down(self, data=False):
|
|
|
|
"""data: [True, False]"""
|
|
|
|
self.pack(self.KEY_VOLDOWN, data)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def default_inc(self, device=None, key=None, data=None):
|
2022-12-22 20:12:57 +01:00
|
|
|
self.set_volume_up(True)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def default_dec(self, device=None, key=None, data=None):
|
2022-12-22 20:12:57 +01:00
|
|
|
self.set_volume_down(True)
|
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def default_stop(self, device=None, key=None, data=None):
|
2022-12-22 20:12:57 +01:00
|
|
|
self.set_volume_up(False)
|
|
|
|
|
|
|
|
|
|
|
|
class status(base):
|
|
|
|
KEY_STATE = "state"
|
|
|
|
#
|
|
|
|
TX_TYPE = base.TX_VALUE
|
2022-12-23 10:00:09 +01:00
|
|
|
#
|
|
|
|
RX_KEYS = [KEY_STATE]
|
2022-12-22 20:12:57 +01:00
|
|
|
|
|
|
|
def set_state(self, num, data):
|
|
|
|
"""data: [True, False]"""
|
|
|
|
self.pack(self.KEY_STATE + "/" + str(num), data)
|
2022-12-23 10:00:09 +01:00
|
|
|
|
2022-12-25 16:31:22 +01:00
|
|
|
def set_state_mcb(self, device, key, data):
|
2023-01-04 01:20:00 +01:00
|
|
|
self.logger.info("Changing state to %s", str(data))
|
2022-12-25 16:31:22 +01:00
|
|
|
self.set_state(data)
|
|
|
|
|
2022-12-23 10:00:09 +01:00
|
|
|
|
|
|
|
class audio_status(status):
|
|
|
|
KEY_TITLE = "title"
|
|
|
|
#
|
|
|
|
RX_KEYS = [status.KEY_STATE, KEY_TITLE]
|