123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- #
- from devices.base import base
- import json
- import task
- import time
-
-
- class brennenstuhl_heatingvalve(base):
- """ Communication (MQTT)
-
- brennenstuhl_heatingvalve {
- | "away_mode": ["ON", "OFF"]
- | "battery": [0...100] %
- | "child_lock": ["LOCK", "UNLOCK"]
- | "current_heating_setpoint": [5...30] °C
- | "linkquality": [0...255] lqi
- | "local_temperature": [numeric] °C
- | "preset": ["manual", ...]
- | "system_mode": ["heat", ...]
- | "valve_detection": ["ON", "OFF"]
- | "window_detection": ["ON", "OFF"]
- | }
- +- set {
- "away_mode": ["ON", "OFF", "TOGGLE"]
- "child_lock": ["LOCK", "UNLOCK"]
- "current_heating_setpoint": [5...30] °C
- "preset": ["manual", ...]
- "system_mode": ["heat", ...]
- "valve_detection": ["ON", "OFF", "TOGGLE"]
- "window_detection": ["ON", "OFF", "TOGGLE"]
- }
- """
- 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"
- #
- RETRY_CYCLE_TIME = 2.5
- MAX_TX_RETRIES = 20
- RETRY_TIMEOUT = RETRY_CYCLE_TIME * MAX_TX_RETRIES
- #
- TX_TYPE = base.TX_DICT
- #
- 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]
- #
- CFG_DATA = {
- KEY_WINDOW_DETECTION: "ON",
- KEY_VALVE_DETECTION: "ON",
- KEY_SYSTEM_MODE: "heat",
- KEY_PRESET: "manual"
- }
-
- def __init__(self, mqtt_client, topic):
- super().__init__(mqtt_client, topic)
- self.add_callback(self.KEY_HEATING_SETPOINT, None, self.__valave_temp_rx__)
- self.__tx_temperature__ = None
- self.__rx_temperature__ = None
- self.__tx_timestamp__ = 0
- #
- self.task = task.periodic(self.RETRY_CYCLE_TIME, self.__task__)
- self.task.run()
-
- def __state_logging__(self, inst, key, data):
- if key in [self.KEY_HEATING_SETPOINT, self.KEY_CHILD_LOCK, self.KEY_WINDOW_DETECTION, self.KEY_VALVE_DETECTION]:
- self.logger.info("State change of '%s' to '%s'", key, repr(data))
-
- def send_command(self, key, data):
- if key == self.KEY_HEATING_SETPOINT:
- self.__tx_temperature__ = data
- self.__tx_timestamp__ = time.time()
- base.send_command(self, key, data)
-
- def __valave_temp_rx__(self, inst, key, data):
- if key == self.KEY_HEATING_SETPOINT:
- self.__rx_temperature__ = data
-
- def __task__(self, rt):
- if self.__tx_temperature__ is not None and self.__tx_timestamp__ is not None: # Already send a setpoint
- if self.__tx_temperature__ != self.__rx_temperature__: # Setpoint and valve feedback are unequal
- if time.time() - self.__tx_timestamp__ < self.RETRY_TIMEOUT: # Timeout condition allows resend of setpoint
- self.logger.warning("Setpoint not yet acknoledged by device. Sending setpoint again")
- self.set_heating_setpoint(self.__tx_temperature__)
- return
- else:
- self.__tx_timestamp__ = None # Disable resend logic, if setpoint and valve setpoint are equal
-
- #
- # 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.send_command(self.KEY_HEATING_SETPOINT, setpoint)
-
- def set_heating_setpoint_mcb(self, device, key, data):
- self.set_heating_setpoint(data)
|