|
@@ -10,17 +10,10 @@ Targets:
|
10
|
10
|
* No functionality should be implemented here
|
11
|
11
|
"""
|
12
|
12
|
|
13
|
|
-# TODO: Extend virtual devices
|
14
|
|
-# * Digital-Audio-Sources (Spotify, MPD, Currently playing) oder direkt von my_apps?!
|
15
|
|
-# *
|
16
|
|
-
|
17
|
13
|
from base import mqtt_base
|
18
|
14
|
import devices
|
19
|
15
|
import json
|
20
|
16
|
|
21
|
|
-BASETOPIC = "videv"
|
22
|
|
-
|
23
|
|
-
|
24
|
17
|
try:
|
25
|
18
|
from config import APP_NAME as ROOT_LOGGER_NAME
|
26
|
19
|
except ImportError:
|
|
@@ -28,174 +21,160 @@ except ImportError:
|
28
|
21
|
|
29
|
22
|
|
30
|
23
|
class base(mqtt_base):
|
31
|
|
- EXEC_RX_FUNC_ALWAYS = []
|
|
24
|
+ KEY_INFO = '__info__'
|
32
|
25
|
|
33
|
|
- def __init__(self, mqtt_client, topic, *args, default_values=None):
|
|
26
|
+ def __init__(self, mqtt_client, topic, default_values=None):
|
34
|
27
|
super().__init__(mqtt_client, topic, default_values=default_values)
|
35
|
|
- self.__device_list__ = {}
|
36
|
|
- for videv_key, device in [reduced[:2] for reduced in args]:
|
37
|
|
- self.__device_list__[videv_key] = device
|
38
|
|
- # send initial state
|
39
|
|
- for key in self.keys():
|
40
|
|
- self.__tx__(key, self[key])
|
41
|
|
- # add receive topics
|
42
|
|
- mqtt_client.add_callback(self.topic + "/#", self.__rx__)
|
|
28
|
+ self.__display_dict__ = {}
|
|
29
|
+ self.__control_dict__ = {}
|
|
30
|
+ self.__capabilities__ = None
|
|
31
|
+
|
|
32
|
+ def add_display(self, my_key, ext_device, ext_key, on_change_only=True):
|
|
33
|
+ """
|
|
34
|
+ listen to data changes of ext_device and update videv information
|
|
35
|
+ """
|
|
36
|
+ if ext_device.__class__.__name__ == "group":
|
|
37
|
+ # store information to identify callback from ext_device
|
|
38
|
+ self.__display_dict__[(id(ext_device[0]), ext_key)] = my_key
|
|
39
|
+ # register a callback to listen for data from external device
|
|
40
|
+ ext_device[0].add_callback(ext_key, None, self.__rx_ext_device_data__, on_change_only)
|
|
41
|
+ else:
|
|
42
|
+ # store information to identify callback from ext_device
|
|
43
|
+ self.__display_dict__[(id(ext_device), ext_key)] = my_key
|
|
44
|
+ # register a callback to listen for data from external device
|
|
45
|
+ ext_device.add_callback(ext_key, None, self.__rx_ext_device_data__, on_change_only)
|
|
46
|
+ # send default data to videv interface
|
|
47
|
+
|
|
48
|
+ def __rx_ext_device_data__(self, ext_device, ext_key, data):
|
|
49
|
+ self.__tx__(self.__display_dict__[(id(ext_device), ext_key)], data)
|
43
|
50
|
|
44
|
51
|
def __tx__(self, key, data):
|
45
|
52
|
if type(data) not in (str, ):
|
46
|
53
|
data = json.dumps(data)
|
47
|
|
- if key in self.keys():
|
48
|
|
- self.mqtt_client.send(self.topic + '/' + key, data)
|
49
|
|
- else:
|
50
|
|
- self.logger.warning("Ignoring send request for key %s (not available for this class)", key)
|
51
|
|
-
|
52
|
|
- def __rx__(self, client, userdata, message):
|
53
|
|
- key = message.topic.split('/')[-1]
|
54
|
|
- if key in self.keys():
|
|
54
|
+ self.mqtt_client.send(self.topic + '/' + key, data)
|
|
55
|
+ self.__tx_capabilities__()
|
|
56
|
+
|
|
57
|
+ def __tx_capabilities__(self):
|
|
58
|
+ self.mqtt_client.send(self.topic + '/' + self.KEY_INFO, json.dumps(self.capabilities))
|
|
59
|
+
|
|
60
|
+ def add_control(self, my_key, ext_device, ext_key, on_change_only=True):
|
|
61
|
+ """
|
|
62
|
+ listen to videv information and pass data to ext_device
|
|
63
|
+ """
|
|
64
|
+ self[my_key] = None
|
|
65
|
+ # store information to identify callback from videv
|
|
66
|
+ self.__control_dict__[my_key] = (ext_device, ext_key, on_change_only)
|
|
67
|
+ # add callback for videv changes
|
|
68
|
+ self.mqtt_client.add_callback(self.topic + '/' + my_key, self.__rx_videv_data__)
|
|
69
|
+
|
|
70
|
+ def __rx_videv_data__(self, client, userdata, message):
|
|
71
|
+ my_key = message.topic.split('/')[-1]
|
|
72
|
+ ext_device, ext_key, on_change_only = self.__control_dict__[my_key]
|
|
73
|
+ if my_key in self.keys():
|
55
|
74
|
try:
|
56
|
75
|
data = json.loads(message.payload)
|
57
|
76
|
except json.decoder.JSONDecodeError:
|
58
|
77
|
data = message.payload
|
59
|
|
- if data != self[key] or key in self.EXEC_RX_FUNC_ALWAYS:
|
60
|
|
- self.__rx_functionality__(key, data)
|
61
|
|
- self.set(key, data)
|
|
78
|
+ if data != self[my_key] or not on_change_only:
|
|
79
|
+ ext_device.set(ext_key, data)
|
|
80
|
+ self.set(my_key, data)
|
62
|
81
|
else:
|
63
|
82
|
self.logger.info("Ignoring rx message with topic %s", message.topic)
|
64
|
83
|
|
65
|
|
- def __rx_functionality__(self, key, data):
|
66
|
|
- raise NotImplemented("Method __rx_functionality__ needs to be implemented in child class")
|
67
|
|
-
|
68
|
|
- def __device_data__(self, device, key, data):
|
69
|
|
- raise NotImplemented("Method __device_data__ needs to be implemented in child class")
|
70
|
|
-
|
71
|
|
-
|
72
|
|
-class base_routing(base):
|
73
|
|
- def __init__(self, mqtt_client, topic, *args, default_values=None):
|
74
|
|
- super().__init__(mqtt_client, topic, *args, default_values=default_values)
|
75
|
|
- #
|
76
|
|
- self.__device_key__ = {}
|
77
|
|
- index = 0
|
78
|
|
- for videv_key, device, device_key in args:
|
79
|
|
- if self.__device_list__[videv_key] != device:
|
80
|
|
- raise ReferenceError("Parent class generated a deviating device list")
|
81
|
|
- self.__device_key__[videv_key] = device_key
|
82
|
|
- index += 1
|
83
|
|
- # add callbacks
|
84
|
|
- for key in self.__device_list__:
|
85
|
|
- if self.__device_list__[key].__class__.__name__ == "group":
|
86
|
|
- self.__device_list__[key][0].add_callback(self.__device_key__[key], None, self.__device_data__, True)
|
87
|
|
- else:
|
88
|
|
- self.__device_list__[key].add_callback(self.__device_key__[key], None, self.__device_data__, True)
|
89
|
|
-
|
90
|
|
- def __rx_functionality__(self, key, data):
|
91
|
|
- try:
|
92
|
|
- self.__device_list__[key].set(self.__device_key__[key], data)
|
93
|
|
- except KeyError:
|
94
|
|
- self.logger.warning("RX passthrough not possible for key %s", key)
|
95
|
|
-
|
96
|
|
- def __device_data__(self, device, key, data):
|
97
|
|
- l1 = []
|
98
|
|
- for k, v in self.__device_list__.items():
|
99
|
|
- if v.__class__.__name__ == "group":
|
100
|
|
- if id(device) in [id(d) for d in v]:
|
101
|
|
- l1.append(k)
|
102
|
|
- else:
|
103
|
|
- if id(v) == id(device):
|
104
|
|
- l1.append(k)
|
105
|
|
- l2 = [k for k, v in self.__device_key__.items() if v == key]
|
106
|
|
- try:
|
107
|
|
- videv_key = [k for k in l1 if k in l2][0]
|
108
|
|
- except IndexError:
|
109
|
|
- self.logger.warning("videv_key not available for %s::%s", device.__class__.__name__, device.topic)
|
110
|
|
- else:
|
111
|
|
- self.set(videv_key, data)
|
112
|
|
- self.__tx__(videv_key, data)
|
113
|
|
-
|
114
|
|
-
|
115
|
|
-class videv_switching(base_routing):
|
|
84
|
+ def add_routing(self, my_key, ext_device, ext_key, on_change_only_disp=True, on_change_only_videv=True):
|
|
85
|
+ """
|
|
86
|
+ listen to data changes of ext_device and update videv information
|
|
87
|
+ and
|
|
88
|
+ listen to videv information and pass data to ext_device
|
|
89
|
+ """
|
|
90
|
+ # add display
|
|
91
|
+ self.add_display(my_key, ext_device, ext_key, on_change_only_disp)
|
|
92
|
+ self.add_control(my_key, ext_device, ext_key, on_change_only_videv)
|
|
93
|
+
|
|
94
|
+ @property
|
|
95
|
+ def capabilities(self):
|
|
96
|
+ if self.__capabilities__ is None:
|
|
97
|
+ self.__capabilities__ = {}
|
|
98
|
+ self.__capabilities__['__type__'] = self.__class__.__name__
|
|
99
|
+ for key in self.__control_dict__:
|
|
100
|
+ if not key in self.__capabilities__:
|
|
101
|
+ self.__capabilities__[key] = {}
|
|
102
|
+ self.__capabilities__[key]['control'] = True
|
|
103
|
+ for key in self.__display_dict__.values():
|
|
104
|
+ if not key in self.__capabilities__:
|
|
105
|
+ self.__capabilities__[key] = {}
|
|
106
|
+ self.__capabilities__[key]['display'] = True
|
|
107
|
+ return self.__capabilities__
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+class videv_switching(base):
|
116
|
111
|
KEY_STATE = 'state'
|
117
|
|
- #
|
118
|
|
- DEFAULT_VALUES = {
|
119
|
|
- KEY_STATE: False,
|
120
|
|
- }
|
121
|
112
|
|
122
|
113
|
def __init__(self, mqtt_client, topic, sw_device, sw_key):
|
123
|
|
- super().__init__(mqtt_client, topic, (self.KEY_STATE, sw_device, sw_key))
|
|
114
|
+ super().__init__(mqtt_client, topic)
|
|
115
|
+ self.add_routing(self.KEY_STATE, sw_device, sw_key)
|
|
116
|
+ #
|
|
117
|
+ self.__tx_capabilities__()
|
124
|
118
|
|
125
|
119
|
|
126
|
|
-class videv_switching_timer(base_routing):
|
|
120
|
+class videv_switching_timer(base):
|
127
|
121
|
KEY_STATE = 'state'
|
128
|
122
|
KEY_TIMER = 'timer'
|
129
|
|
- #
|
130
|
|
- DEFAULT_VALUES = {
|
131
|
|
- KEY_STATE: False,
|
132
|
|
- KEY_TIMER: 0
|
133
|
|
- }
|
134
|
123
|
|
135
|
124
|
def __init__(self, mqtt_client, topic, sw_device, sw_key, tm_device, tm_key):
|
136
|
|
- super().__init__(mqtt_client, topic, (self.KEY_STATE, sw_device, sw_key), (self.KEY_TIMER, tm_device, tm_key))
|
|
125
|
+ super().__init__(mqtt_client, topic)
|
|
126
|
+ self.add_routing(self.KEY_STATE, sw_device, sw_key)
|
|
127
|
+ self.add_display(self.KEY_TIMER, tm_device, tm_key)
|
|
128
|
+ #
|
|
129
|
+ self.__tx_capabilities__()
|
137
|
130
|
|
138
|
131
|
|
139
|
|
-class videv_switching_motion(base_routing):
|
|
132
|
+class videv_switching_motion(base):
|
140
|
133
|
KEY_STATE = 'state'
|
|
134
|
+ #
|
141
|
135
|
KEY_TIMER = 'timer'
|
142
|
136
|
KEY_MOTION_SENSOR = 'motion_%d'
|
143
|
|
- #
|
144
|
|
- DEFAULT_VALUES = {
|
145
|
|
- KEY_STATE: False,
|
146
|
|
- KEY_TIMER: 0
|
147
|
|
- }
|
148
|
137
|
|
149
|
138
|
def __init__(self, mqtt_client, topic, sw_device, sw_key, motion_function):
|
150
|
|
- dv = {self.KEY_STATE: False, self.KEY_TIMER: 0}
|
151
|
|
- for i in range(0, len(motion_function.args)):
|
152
|
|
- dv[motion_function.KEY_MOTION_SENSOR % i] = False
|
153
|
|
- super().__init__(
|
154
|
|
- mqtt_client, topic,
|
155
|
|
- (self.KEY_STATE, sw_device, sw_key),
|
156
|
|
- (self.KEY_TIMER, motion_function, motion_function.KEY_TIMER),
|
157
|
|
- *[[self.KEY_MOTION_SENSOR % i, motion_function, motion_function.KEY_MOTION_SENSOR % i] for i in range(0, len(motion_function.args))],
|
158
|
|
- default_values=dv
|
159
|
|
- )
|
160
|
|
-
|
161
|
|
-
|
162
|
|
-class videv_switch_brightness(base_routing):
|
|
139
|
+ self.motion_sensors = motion_function.motion_sensors
|
|
140
|
+ #
|
|
141
|
+ super().__init__(mqtt_client, topic)
|
|
142
|
+ self.add_routing(self.KEY_STATE, sw_device, sw_key)
|
|
143
|
+ self.add_display(self.KEY_TIMER, motion_function, motion_function.KEY_TIMER)
|
|
144
|
+ # motion sensor state
|
|
145
|
+ for index, motion_sensor in enumerate(self.motion_sensors):
|
|
146
|
+ self.add_display(self.KEY_MOTION_SENSOR % index, motion_sensor, motion_sensor.KEY_OCCUPANCY)
|
|
147
|
+ #
|
|
148
|
+ self.__tx_capabilities__()
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+class videv_switch_brightness(base):
|
163
|
152
|
KEY_STATE = 'state'
|
164
|
153
|
KEY_BRIGHTNESS = 'brightness'
|
165
|
|
- #
|
166
|
|
- DEFAULT_VALUES = {
|
167
|
|
- KEY_STATE: False,
|
168
|
|
- KEY_BRIGHTNESS: 0
|
169
|
|
- }
|
170
|
154
|
|
171
|
155
|
def __init__(self, mqtt_client, topic, sw_device, sw_key, br_device, br_key):
|
|
156
|
+ super().__init__(mqtt_client, topic)
|
|
157
|
+ self.add_routing(self.KEY_STATE, sw_device, sw_key)
|
|
158
|
+ self.add_routing(self.KEY_BRIGHTNESS, br_device, br_key)
|
172
|
159
|
#
|
173
|
|
- super().__init__(mqtt_client, topic, (self.KEY_STATE, sw_device, sw_key), (self.KEY_BRIGHTNESS, br_device, br_key))
|
|
160
|
+ self.__tx_capabilities__()
|
174
|
161
|
|
175
|
162
|
|
176
|
|
-class videv_switch_brightness_color_temp(base_routing):
|
|
163
|
+class videv_switch_brightness_color_temp(base):
|
177
|
164
|
KEY_STATE = 'state'
|
178
|
165
|
KEY_BRIGHTNESS = 'brightness'
|
179
|
166
|
KEY_COLOR_TEMP = 'color_temp'
|
180
|
|
- #
|
181
|
|
- DEFAULT_VALUES = {
|
182
|
|
- KEY_STATE: False,
|
183
|
|
- KEY_BRIGHTNESS: 0,
|
184
|
|
- KEY_COLOR_TEMP: 0,
|
185
|
|
- }
|
186
|
167
|
|
187
|
168
|
def __init__(self, mqtt_client, topic, sw_device, sw_key, br_device, br_key, ct_device, ct_key):
|
|
169
|
+ super().__init__(mqtt_client, topic)
|
|
170
|
+ self.add_routing(self.KEY_STATE, sw_device, sw_key)
|
|
171
|
+ self.add_routing(self.KEY_BRIGHTNESS, br_device, br_key)
|
|
172
|
+ self.add_routing(self.KEY_COLOR_TEMP, ct_device, ct_key)
|
188
|
173
|
#
|
189
|
|
- super().__init__(
|
190
|
|
- mqtt_client, topic,
|
191
|
|
- (self.KEY_STATE, sw_device, sw_key),
|
192
|
|
- (self.KEY_BRIGHTNESS, br_device, br_key),
|
193
|
|
- (self.KEY_COLOR_TEMP, ct_device, ct_key)
|
194
|
|
- )
|
|
174
|
+ self.__tx_capabilities__()
|
195
|
175
|
|
196
|
176
|
|
197
|
|
-class videv_heating(base_routing):
|
198
|
|
- KEY_TEMPERATURE = 'temperature'
|
|
177
|
+class videv_heating(base):
|
199
|
178
|
KEY_USER_TEMPERATURE_SETPOINT = 'user_temperature_setpoint'
|
200
|
179
|
KEY_VALVE_TEMPERATURE_SETPOINT = 'valve_temperature_setpoint'
|
201
|
180
|
KEY_AWAY_MODE = 'away_mode'
|
|
@@ -204,69 +183,66 @@ class videv_heating(base_routing):
|
204
|
183
|
KEY_SET_DEFAULT_TEMPERATURE = 'set_default_temperature'
|
205
|
184
|
KEY_BOOST_TIMER = 'boost_timer'
|
206
|
185
|
#
|
207
|
|
- EXEC_RX_FUNC_ALWAYS = [KEY_START_BOOST, KEY_SET_DEFAULT_TEMPERATURE, KEY_USER_TEMPERATURE_SETPOINT]
|
|
186
|
+ KEY_TEMPERATURE = 'temperature'
|
208
|
187
|
|
209
|
188
|
def __init__(self, mqtt_client, topic, heating_function):
|
|
189
|
+ super().__init__(mqtt_client, topic)
|
|
190
|
+ #
|
|
191
|
+ self.add_routing(self.KEY_USER_TEMPERATURE_SETPOINT, heating_function, heating_function.KEY_USER_TEMPERATURE_SETPOINT)
|
|
192
|
+ self.add_routing(self.KEY_AWAY_MODE, heating_function, heating_function.KEY_AWAY_MODE)
|
|
193
|
+ self.add_routing(self.KEY_SUMMER_MODE, heating_function, heating_function.KEY_SUMMER_MODE)
|
210
|
194
|
#
|
211
|
|
- super().__init__(
|
212
|
|
- mqtt_client, topic,
|
213
|
|
- (self.KEY_TEMPERATURE, heating_function, heating_function.KEY_TEMPERATURE_CURRENT),
|
214
|
|
- (self.KEY_USER_TEMPERATURE_SETPOINT, heating_function, heating_function.KEY_USER_TEMPERATURE_SETPOINT),
|
215
|
|
- (self.KEY_VALVE_TEMPERATURE_SETPOINT, heating_function, heating_function.KEY_TEMPERATURE_SETPOINT),
|
216
|
|
- (self.KEY_AWAY_MODE, heating_function, heating_function.KEY_AWAY_MODE),
|
217
|
|
- (self.KEY_SUMMER_MODE, heating_function, heating_function.KEY_SUMMER_MODE),
|
218
|
|
- (self.KEY_START_BOOST, heating_function, heating_function.KEY_START_BOOST),
|
219
|
|
- (self.KEY_SET_DEFAULT_TEMPERATURE, heating_function, heating_function.KEY_SET_DEFAULT_TEMPERATURE),
|
220
|
|
- (self.KEY_BOOST_TIMER, heating_function, heating_function.KEY_BOOST_TIMER),
|
221
|
|
- default_values={
|
222
|
|
- self.KEY_TEMPERATURE: heating_function[heating_function.KEY_TEMPERATURE_CURRENT],
|
223
|
|
- self.KEY_VALVE_TEMPERATURE_SETPOINT: heating_function[heating_function.KEY_TEMPERATURE_SETPOINT],
|
224
|
|
- self.KEY_USER_TEMPERATURE_SETPOINT: heating_function[heating_function.KEY_USER_TEMPERATURE_SETPOINT],
|
225
|
|
- self.KEY_AWAY_MODE: heating_function[heating_function.KEY_AWAY_MODE],
|
226
|
|
- self.KEY_SUMMER_MODE: heating_function[heating_function.KEY_SUMMER_MODE],
|
227
|
|
- self.KEY_BOOST_TIMER: heating_function[heating_function.KEY_BOOST_TIMER],
|
228
|
|
- self.KEY_START_BOOST: True,
|
229
|
|
- self.KEY_SET_DEFAULT_TEMPERATURE: True,
|
230
|
|
- }
|
231
|
|
- )
|
|
195
|
+ self.add_control(self.KEY_START_BOOST, heating_function, heating_function.KEY_START_BOOST, False)
|
|
196
|
+ self.add_control(self.KEY_SET_DEFAULT_TEMPERATURE, heating_function, heating_function.KEY_SET_DEFAULT_TEMPERATURE, False)
|
|
197
|
+ #
|
|
198
|
+ self.add_display(self.KEY_VALVE_TEMPERATURE_SETPOINT, heating_function, heating_function.KEY_TEMPERATURE_SETPOINT)
|
|
199
|
+ self.add_display(self.KEY_BOOST_TIMER, heating_function, heating_function.KEY_BOOST_TIMER)
|
|
200
|
+ self.add_display(self.KEY_TEMPERATURE, heating_function, heating_function.KEY_TEMPERATURE_CURRENT)
|
|
201
|
+ #
|
|
202
|
+ self.__tx_capabilities__()
|
232
|
203
|
|
233
|
204
|
|
234
|
205
|
class videv_multistate(base):
|
|
206
|
+ KEY_STATE = 'state_%d'
|
|
207
|
+
|
235
|
208
|
def __init__(self, mqtt_client, topic, key_for_device, device, num_states, default_values=None):
|
236
|
|
- dv = dict.fromkeys(["state_%d" % i for i in range(0, num_states)])
|
237
|
|
- for key in dv:
|
238
|
|
- dv[key] = False
|
239
|
|
- super().__init__(mqtt_client, topic, (key_for_device, device), default_values=dv)
|
|
209
|
+ super().__init__(mqtt_client, topic)
|
|
210
|
+ self.num_states = num_states
|
|
211
|
+ # send default values
|
|
212
|
+ for i in range(0, num_states):
|
|
213
|
+ self.__tx__(self.KEY_STATE % i, False)
|
240
|
214
|
#
|
241
|
215
|
device.add_callback(key_for_device, None, self.__index_rx__, True)
|
|
216
|
+ #
|
|
217
|
+ self.__tx_capabilities__()
|
242
|
218
|
|
243
|
219
|
def __index_rx__(self, device, key, data):
|
244
|
|
- for index, key in enumerate(self):
|
245
|
|
- self.set(key, index == data)
|
246
|
|
- self.__tx__(key, self[key])
|
247
|
|
-
|
248
|
|
- def __rx_functionality__(self, key, data):
|
249
|
|
- pass # read only device
|
|
220
|
+ for i in range(0, self.num_states):
|
|
221
|
+ self.__tx__(self.KEY_STATE % i, i == data)
|
|
222
|
+ #
|
|
223
|
+ self.__tx_capabilities__()
|
250
|
224
|
|
251
|
225
|
|
252
|
|
-class videv_audio_player(base_routing):
|
|
226
|
+class videv_audio_player(base):
|
253
|
227
|
KEY_ACTIVE_PLAYER = 'player_%d'
|
254
|
228
|
KEY_TITLE = 'title'
|
255
|
229
|
NO_TITLE = '---'
|
256
|
230
|
|
257
|
231
|
def __init__(self, mqtt_client, topic, *args):
|
258
|
|
- dv = dict.fromkeys([self.KEY_ACTIVE_PLAYER % i for i in range(0, len(args))])
|
259
|
|
- for key in dv:
|
260
|
|
- dv[key] = False
|
261
|
|
- dv[self.KEY_TITLE] = self.NO_TITLE
|
262
|
|
- super().__init__(
|
263
|
|
- mqtt_client, topic,
|
264
|
|
- *[[self.KEY_ACTIVE_PLAYER % i, device, devices.audio_status.KEY_STATE] for i, device in enumerate(args)],
|
265
|
|
- default_values=dv
|
266
|
|
- )
|
|
232
|
+ super().__init__(mqtt_client, topic)
|
|
233
|
+ for i, device in enumerate(args):
|
|
234
|
+ self.add_display(self.KEY_ACTIVE_PLAYER % i, device, device.KEY_STATE)
|
|
235
|
+ #
|
267
|
236
|
for audio_device in args:
|
268
|
237
|
audio_device.add_callback(audio_device.KEY_TITLE, None, self.__title_rx__, True)
|
|
238
|
+ #
|
|
239
|
+ self.__tx_capabilities__()
|
269
|
240
|
|
270
|
241
|
def __title_rx__(self, device, key, data):
|
271
|
|
- self.set(self.KEY_TITLE, data or self.NO_TITLE)
|
272
|
|
- self.__tx__(self.KEY_TITLE, self[self.KEY_TITLE])
|
|
242
|
+ self.__tx__(self.KEY_TITLE, data or self.NO_TITLE)
|
|
243
|
+
|
|
244
|
+ @property
|
|
245
|
+ def capabilities(self):
|
|
246
|
+ super().capabilities
|
|
247
|
+ self.__capabilities__[self.KEY_TITLE] = {'display': True}
|
|
248
|
+ return self.__capabilities__
|