|
@@ -26,6 +26,8 @@ devices (DEVICES)
|
26
|
26
|
|
27
|
27
|
"""
|
28
|
28
|
|
|
29
|
+from base import mqtt_base
|
|
30
|
+from function.videv import base as videv_base
|
29
|
31
|
import json
|
30
|
32
|
import logging
|
31
|
33
|
import task
|
|
@@ -93,7 +95,7 @@ class group(object):
|
93
|
95
|
return rv
|
94
|
96
|
|
95
|
97
|
|
96
|
|
-class base(dict):
|
|
98
|
+class base(mqtt_base):
|
97
|
99
|
TX_TOPIC = "set"
|
98
|
100
|
TX_VALUE = 0
|
99
|
101
|
TX_DICT = 1
|
|
@@ -104,84 +106,60 @@ class base(dict):
|
104
|
106
|
RX_IGNORE_TOPICS = []
|
105
|
107
|
RX_IGNORE_KEYS = []
|
106
|
108
|
RX_FILTER_DATA_KEYS = []
|
|
109
|
+ #
|
|
110
|
+ KEY_WARNING = '__WARNING__'
|
107
|
111
|
|
108
|
112
|
def __init__(self, mqtt_client, topic):
|
|
113
|
+ super().__init__(mqtt_client, topic, default_values=dict.fromkeys(self.RX_KEYS))
|
109
|
114
|
# data storage
|
110
|
|
- self.mqtt_client = mqtt_client
|
111
|
|
- self.topic = topic
|
112
|
|
- self.logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__)
|
113
|
|
- for entry in self.topic.split('/'):
|
114
|
|
- self.logger = self.logger.getChild(entry)
|
115
|
115
|
# initialisations
|
116
|
|
- dict.__init__(self)
|
117
|
|
- mqtt_client.add_callback(
|
118
|
|
- topic=self.topic, callback=self.receive_callback)
|
119
|
|
- mqtt_client.add_callback(
|
120
|
|
- topic=self.topic+"/#", callback=self.receive_callback)
|
121
|
|
- #
|
122
|
|
- self.callback_list = []
|
123
|
|
- self.warning_callback = None
|
124
|
|
- #
|
125
|
|
- self.__previous__ = {}
|
|
116
|
+ mqtt_client.add_callback(topic=self.topic, callback=self.receive_callback)
|
|
117
|
+ mqtt_client.add_callback(topic=self.topic+"/#", callback=self.receive_callback)
|
|
118
|
+
|
|
119
|
+ def set(self, key, data, block_callback=[]):
|
|
120
|
+ if key in self.RX_IGNORE_KEYS:
|
|
121
|
+ pass # ignore these keys
|
|
122
|
+ elif key in self.RX_KEYS:
|
|
123
|
+ return super().set(key, data, block_callback)
|
|
124
|
+ else:
|
|
125
|
+ self.logger.warning("Unexpected key %s", key)
|
126
|
126
|
|
127
|
127
|
def receive_callback(self, client, userdata, message):
|
128
|
|
- self.unpack(message)
|
129
|
|
-
|
130
|
|
- def unpack_filter(self, key):
|
131
|
|
- if key in self.RX_FILTER_DATA_KEYS:
|
132
|
|
- if self.get(key) == 1 or self.get(key) == 'on' or self.get(key) == 'ON':
|
133
|
|
- self[key] = True
|
134
|
|
- elif self.get(key) == 0 or self.get(key) == 'off' or self.get(key) == 'OFF':
|
135
|
|
- self[key] = False
|
136
|
|
-
|
137
|
|
- def unpack_single_value(self, key, data):
|
138
|
|
- prev_value = self.get(key)
|
139
|
|
- if key in self.RX_KEYS:
|
140
|
|
- self[key] = data
|
141
|
|
- self.__previous__[key] = prev_value
|
142
|
|
- # Filter, if needed
|
143
|
|
- self.unpack_filter(key)
|
144
|
|
- self.logger.debug("Received data %s - %s", key, str(self.get(key)))
|
145
|
|
- self.callback_caller(key, self[key], self.get(key) != self.__previous__.get(key))
|
146
|
|
- elif key not in self.RX_IGNORE_KEYS:
|
147
|
|
- self.logger.warning('Got a message with unparsed content: "%s - %s"', key, str(data))
|
148
|
|
- else:
|
149
|
|
- self.logger.debug("Ignoring key %s", key)
|
150
|
|
-
|
151
|
|
- def unpack(self, message):
|
152
|
|
- content_key = message.topic[len(self.topic) + 1:]
|
153
|
|
- if content_key not in self.RX_IGNORE_TOPICS and (not message.topic.endswith(self.TX_TOPIC) or len(self.TX_TOPIC) == 0):
|
154
|
|
- self.logger.debug("Unpacking content_key \"%s\" from message.", content_key)
|
155
|
|
- if is_json(message.payload):
|
156
|
|
- data = json.loads(message.payload)
|
157
|
|
- if type(data) is dict:
|
158
|
|
- for key in data:
|
159
|
|
- self.unpack_single_value(key, data[key])
|
|
128
|
+ if message.topic != self.topic + '/' + videv_base.KEY_INFO:
|
|
129
|
+ content_key = message.topic[len(self.topic) + 1:]
|
|
130
|
+ if content_key not in self.RX_IGNORE_TOPICS and (not message.topic.endswith(self.TX_TOPIC) or len(self.TX_TOPIC) == 0):
|
|
131
|
+ self.logger.debug("Unpacking content_key \"%s\" from message.", content_key)
|
|
132
|
+ if is_json(message.payload):
|
|
133
|
+ data = json.loads(message.payload)
|
|
134
|
+ if type(data) is dict:
|
|
135
|
+ for key in data:
|
|
136
|
+ self.set(key, self.__device_to_instance_filter__(key, data[key]))
|
|
137
|
+ else:
|
|
138
|
+ self.set(content_key, self.__device_to_instance_filter__(content_key, data))
|
|
139
|
+ # String
|
160
|
140
|
else:
|
161
|
|
- self.unpack_single_value(content_key, data)
|
162
|
|
- # String
|
|
141
|
+ self.set(content_key, self.__device_to_instance_filter__(content_key, message.payload.decode('utf-8')))
|
163
|
142
|
else:
|
164
|
|
- self.unpack_single_value(
|
165
|
|
- content_key, message.payload.decode('utf-8'))
|
166
|
|
- self.warning_caller()
|
167
|
|
- else:
|
168
|
|
- self.logger.debug("Ignoring topic %s", content_key)
|
|
143
|
+ self.logger.debug("Ignoring topic %s", content_key)
|
169
|
144
|
|
170
|
|
- def pack_filter(self, key, data):
|
|
145
|
+ def __device_to_instance_filter__(self, key, data):
|
|
146
|
+ if key in self.RX_FILTER_DATA_KEYS:
|
|
147
|
+ if data in [1, 'on', 'ON']:
|
|
148
|
+ return True
|
|
149
|
+ elif data in [0, 'off', 'OFF']:
|
|
150
|
+ return False
|
|
151
|
+ return data
|
|
152
|
+
|
|
153
|
+ def __instance_to_device_filter__(self, key, data):
|
171
|
154
|
if key in self.TX_FILTER_DATA_KEYS:
|
172
|
155
|
if data is True:
|
173
|
156
|
return "on"
|
174
|
157
|
elif data is False:
|
175
|
158
|
return "off"
|
176
|
|
- else:
|
177
|
|
- return data
|
178
|
159
|
return data
|
179
|
160
|
|
180
|
|
- def set(self, key, data):
|
181
|
|
- self.pack(key, data)
|
182
|
|
-
|
183
|
|
- def pack(self, key, data):
|
184
|
|
- data = self.pack_filter(key, data)
|
|
161
|
+ def send_command(self, key, data):
|
|
162
|
+ data = self.__instance_to_device_filter__(key, data)
|
185
|
163
|
if self.TX_TOPIC is not None:
|
186
|
164
|
if self.TX_TYPE < 0:
|
187
|
165
|
self.logger.error("Unknown tx type. Set TX_TYPE of class to a known value")
|
|
@@ -196,40 +174,6 @@ class base(dict):
|
196
|
174
|
else:
|
197
|
175
|
self.logger.error("Unknown tx toptic. Set TX_TOPIC of class to a known value")
|
198
|
176
|
|
199
|
|
- def add_callback(self, key, data, callback, on_change_only=False):
|
200
|
|
- """
|
201
|
|
- key: key or None for all keys
|
202
|
|
- data: data or None for all data
|
203
|
|
- """
|
204
|
|
- cb_tup = (key, data, callback, on_change_only)
|
205
|
|
- if cb_tup not in self.callback_list:
|
206
|
|
- self.callback_list.append(cb_tup)
|
207
|
|
-
|
208
|
|
- def add_warning_callback(self, callback):
|
209
|
|
- self.warning_callback = callback
|
210
|
|
-
|
211
|
|
- def warning_call_condition(self):
|
212
|
|
- return False
|
213
|
|
-
|
214
|
|
- def callback_caller(self, key, data, value_changed):
|
215
|
|
- for cb_key, cb_data, callback, on_change_only in self.callback_list:
|
216
|
|
- if (cb_key == key or cb_key is None) and (cb_data == data or cb_data is None) and callback is not None:
|
217
|
|
- if not on_change_only or value_changed:
|
218
|
|
- callback(self, key, data)
|
219
|
|
-
|
220
|
|
- def warning_caller(self):
|
221
|
|
- if self.warning_call_condition():
|
222
|
|
- warn_txt = self.warning_text()
|
223
|
|
- self.logger.warning(warn_txt)
|
224
|
|
- if self.warning_callback is not None:
|
225
|
|
- self.warning_callback(self, warn_txt)
|
226
|
|
-
|
227
|
|
- def warning_text(self):
|
228
|
|
- return "default warning text - replace parent warning_text function"
|
229
|
|
-
|
230
|
|
- def previous_value(self, key):
|
231
|
|
- return self.__previous__.get(key)
|
232
|
|
-
|
233
|
177
|
|
234
|
178
|
class shelly(base):
|
235
|
179
|
KEY_OUTPUT_0 = "relay/0"
|
|
@@ -264,11 +208,13 @@ class shelly(base):
|
264
|
208
|
self.delayed_flash_task = task.delayed(0.3, self.flash_task)
|
265
|
209
|
self.delayed_off_task = task.delayed(0.3, self.off_task)
|
266
|
210
|
#
|
|
211
|
+ self.add_callback(self.KEY_OVERTEMPERATURE, True, self.__warning__, True)
|
|
212
|
+ #
|
267
|
213
|
self.all_off_requested = False
|
268
|
214
|
|
269
|
215
|
def flash_task(self, *args):
|
270
|
216
|
if self.flash_active:
|
271
|
|
- self.pack(self.output_key_delayed, not self.get(self.output_key_delayed))
|
|
217
|
+ self.send_command(self.output_key_delayed, not self.get(self.output_key_delayed))
|
272
|
218
|
self.output_key_delayed = None
|
273
|
219
|
if self.all_off_requested:
|
274
|
220
|
self.delayed_off_task.run()
|
|
@@ -283,15 +229,8 @@ class shelly(base):
|
283
|
229
|
#
|
284
|
230
|
# WARNING CALL
|
285
|
231
|
#
|
286
|
|
- def warning_call_condition(self):
|
287
|
|
- return self.get(self.KEY_OVERTEMPERATURE)
|
288
|
|
-
|
289
|
|
- def warning_text(self):
|
290
|
|
- if self.overtemperature:
|
291
|
|
- if self.temperature is not None:
|
292
|
|
- return "Overtemperature detected for %s. Temperature was %.1f°C." % (self.topic, self.temperature)
|
293
|
|
- else:
|
294
|
|
- return "Overtemperature detected for %s." % self.topic
|
|
232
|
+ def __warning__(self, client, key, data):
|
|
233
|
+ pass # TODO: implement warning feedback (key: KEY_OVERTEMPERATURE - info: KEY_TEMPERATURE)
|
295
|
234
|
|
296
|
235
|
#
|
297
|
236
|
# RX
|
|
@@ -335,8 +274,8 @@ class shelly(base):
|
335
|
274
|
# TX
|
336
|
275
|
#
|
337
|
276
|
def set_output_0(self, state):
|
338
|
|
- """state: [True, False, 'toggle']"""
|
339
|
|
- self.pack(self.KEY_OUTPUT_0, state)
|
|
277
|
+ """state: [True, False]"""
|
|
278
|
+ self.send_command(self.KEY_OUTPUT_0, state)
|
340
|
279
|
|
341
|
280
|
def set_output_0_mcb(self, device, key, data):
|
342
|
281
|
self.logger.log(logging.INFO if data != self.output_0 else logging.DEBUG, "Changing output 0 to %s", str(data))
|
|
@@ -344,11 +283,11 @@ class shelly(base):
|
344
|
283
|
|
345
|
284
|
def toggle_output_0_mcb(self, device, key, data):
|
346
|
285
|
self.logger.info("Toggeling output 0")
|
347
|
|
- self.set_output_0('toggle')
|
|
286
|
+ self.set_output_0(not self.output_0)
|
348
|
287
|
|
349
|
288
|
def set_output_1(self, state):
|
350
|
|
- """state: [True, False, 'toggle']"""
|
351
|
|
- self.pack(self.KEY_OUTPUT_1, state)
|
|
289
|
+ """state: [True, False]"""
|
|
290
|
+ self.send_command(self.KEY_OUTPUT_1, state)
|
352
|
291
|
|
353
|
292
|
def set_output_1_mcb(self, device, key, data):
|
354
|
293
|
self.logger.log(logging.INFO if data != self.output_1 else logging.DEBUG, "Changing output 1 to %s", str(data))
|
|
@@ -356,7 +295,7 @@ class shelly(base):
|
356
|
295
|
|
357
|
296
|
def toggle_output_1_mcb(self, device, key, data):
|
358
|
297
|
self.logger.info("Toggeling output 1")
|
359
|
|
- self.set_output_1('toggle')
|
|
298
|
+ self.set_output_1(not self.output_1)
|
360
|
299
|
|
361
|
300
|
def flash_0_mcb(self, device, key, data):
|
362
|
301
|
self.output_key_delayed = self.KEY_OUTPUT_0
|
|
@@ -408,8 +347,8 @@ class silvercrest_powerplug(base):
|
408
|
347
|
# TX
|
409
|
348
|
#
|
410
|
349
|
def set_output_0(self, state):
|
411
|
|
- """state: [True, False, 'toggle']"""
|
412
|
|
- self.pack(self.KEY_OUTPUT_0, state)
|
|
350
|
+ """state: [True, False]"""
|
|
351
|
+ self.send_command(self.KEY_OUTPUT_0, state)
|
413
|
352
|
|
414
|
353
|
def set_output_0_mcb(self, device, key, data):
|
415
|
354
|
self.logger.log(logging.INFO if data != self.output_0 else logging.DEBUG, "Changing output 0 to %s", str(data))
|
|
@@ -417,7 +356,7 @@ class silvercrest_powerplug(base):
|
417
|
356
|
|
418
|
357
|
def toggle_output_0_mcb(self, device, key, data):
|
419
|
358
|
self.logger.info("Toggeling output 0")
|
420
|
|
- self.set_output_0('toggle')
|
|
359
|
+ self.set_output_0(not self.output_0)
|
421
|
360
|
|
422
|
361
|
def all_off(self):
|
423
|
362
|
if self.output_0:
|
|
@@ -436,17 +375,18 @@ class silvercrest_motion_sensor(base):
|
436
|
375
|
|
437
|
376
|
def __init__(self, mqtt_client, topic):
|
438
|
377
|
super().__init__(mqtt_client, topic)
|
|
378
|
+ #
|
|
379
|
+ self.add_callback(self.KEY_BATTERY_LOW, True, self.__warning__, True)
|
439
|
380
|
|
440
|
|
- def warning_call_condition(self):
|
441
|
|
- return self.get(self.KEY_BATTERY_LOW)
|
442
|
|
-
|
443
|
|
- def warning_text(self, data):
|
444
|
|
- return "Battery low: level=%d" % self.get(self.KEY_BATTERY)
|
|
381
|
+ #
|
|
382
|
+ # WARNING CALL
|
|
383
|
+ #
|
|
384
|
+ def __warning__(self, client, key, data):
|
|
385
|
+ pass # TODO: implement warning feedback (key: KEY_BATTERY_LOW - info: KEY_BATTERY)
|
445
|
386
|
|
446
|
387
|
#
|
447
|
388
|
# RX
|
448
|
389
|
#
|
449
|
|
-
|
450
|
390
|
@property
|
451
|
391
|
def linkquality(self):
|
452
|
392
|
"""rv: numeric value"""
|
|
@@ -496,13 +436,13 @@ class my_powerplug(base):
|
496
|
436
|
#
|
497
|
437
|
def set_output(self, key, state):
|
498
|
438
|
if key in self.KEY_OUTPUT_LIST:
|
499
|
|
- self.pack(key, state)
|
|
439
|
+ self.send_command(key, state)
|
500
|
440
|
else:
|
501
|
441
|
logging.error("Unknown key to set the output!")
|
502
|
442
|
|
503
|
443
|
def set_output_0(self, state):
|
504
|
|
- """state: [True, False, 'toggle']"""
|
505
|
|
- self.pack(self.KEY_OUTPUT_0, state)
|
|
444
|
+ """state: [True, False]"""
|
|
445
|
+ self.send_command(self.KEY_OUTPUT_0, state)
|
506
|
446
|
|
507
|
447
|
def set_output_0_mcb(self, device, key, data):
|
508
|
448
|
self.logger.log(logging.INFO if data != self.output_0 else logging.DEBUG, "Changing output 0 to %s", str(data))
|
|
@@ -510,11 +450,11 @@ class my_powerplug(base):
|
510
|
450
|
|
511
|
451
|
def toggle_output_0_mcb(self, device, key, data):
|
512
|
452
|
self.logger.info("Toggeling output 0")
|
513
|
|
- self.set_output_0('toggle')
|
|
453
|
+ self.set_output_0(not self.output_0)
|
514
|
454
|
|
515
|
455
|
def set_output_1(self, state):
|
516
|
|
- """state: [True, False, 'toggle']"""
|
517
|
|
- self.pack(self.KEY_OUTPUT_1, state)
|
|
456
|
+ """state: [True, False]"""
|
|
457
|
+ self.send_command(self.KEY_OUTPUT_1, state)
|
518
|
458
|
|
519
|
459
|
def set_output_1_mcb(self, device, key, data):
|
520
|
460
|
self.logger.log(logging.INFO if data != self.output_1 else logging.DEBUG, "Changing output 1 to %s", str(data))
|
|
@@ -522,11 +462,11 @@ class my_powerplug(base):
|
522
|
462
|
|
523
|
463
|
def toggle_output_1_mcb(self, device, key, data):
|
524
|
464
|
self.logger.info("Toggeling output 1")
|
525
|
|
- self.set_output_1('toggle')
|
|
465
|
+ self.set_output_1(not self.output_1)
|
526
|
466
|
|
527
|
467
|
def set_output_2(self, state):
|
528
|
|
- """state: [True, False, 'toggle']"""
|
529
|
|
- self.pack(self.KEY_OUTPUT_2, state)
|
|
468
|
+ """state: [True, False]"""
|
|
469
|
+ self.send_command(self.KEY_OUTPUT_2, state)
|
530
|
470
|
|
531
|
471
|
def set_output_2_mcb(self, device, key, data):
|
532
|
472
|
self.logger.log(logging.INFO if data != self.output_2 else logging.DEBUG, "Changing output 2 to %s", str(data))
|
|
@@ -534,11 +474,11 @@ class my_powerplug(base):
|
534
|
474
|
|
535
|
475
|
def toggle_output_2_mcb(self, device, key, data):
|
536
|
476
|
self.logger.info("Toggeling output 2")
|
537
|
|
- self.set_output_2('toggle')
|
|
477
|
+ self.set_output_2(not self.output_2)
|
538
|
478
|
|
539
|
479
|
def set_output_3(self, state):
|
540
|
|
- """state: [True, False, 'toggle']"""
|
541
|
|
- self.pack(self.KEY_OUTPUT_3, state)
|
|
480
|
+ """state: [True, False]"""
|
|
481
|
+ self.send_command(self.KEY_OUTPUT_3, state)
|
542
|
482
|
|
543
|
483
|
def set_output_3_mcb(self, device, key, data):
|
544
|
484
|
self.logger.log(logging.INFO if data != self.output_3 else logging.DEBUG, "Changing output 3 to %s", str(data))
|
|
@@ -546,20 +486,16 @@ class my_powerplug(base):
|
546
|
486
|
|
547
|
487
|
def toggle_output_3_mcb(self, device, key, data):
|
548
|
488
|
self.logger.info("Toggeling output 3")
|
549
|
|
- self.set_output_3('toggle')
|
|
489
|
+ self.set_output_3(not self.output_3)
|
550
|
490
|
|
551
|
491
|
def set_output_all(self, state):
|
552
|
492
|
"""state: [True, False, 'toggle']"""
|
553
|
|
- self.pack(self.KEY_OUTPUT_ALL, state)
|
|
493
|
+ self.send_command(self.KEY_OUTPUT_ALL, state)
|
554
|
494
|
|
555
|
495
|
def set_output_all_mcb(self, device, key, data):
|
556
|
496
|
self.logger.info("Changing all outputs to %s", str(data))
|
557
|
497
|
self.set_output_all(data)
|
558
|
498
|
|
559
|
|
- def toggle_output_all_mcb(self, device, key, data):
|
560
|
|
- self.logger.info("Toggeling all outputs")
|
561
|
|
- self.set_output_0('toggle')
|
562
|
|
-
|
563
|
499
|
def all_off(self):
|
564
|
500
|
self.set_output_all(False)
|
565
|
501
|
|
|
@@ -581,21 +517,19 @@ class tradfri_light(base):
|
581
|
517
|
def __init__(self, mqtt_client, topic):
|
582
|
518
|
super().__init__(mqtt_client, topic)
|
583
|
519
|
|
584
|
|
- def unpack_filter(self, key):
|
|
520
|
+ def __device_to_instance_filter__(self, key, data):
|
585
|
521
|
if key == self.KEY_BRIGHTNESS:
|
586
|
|
- self[key] = round((self[key] - 1) * 100 / 253, 0)
|
|
522
|
+ return int(round((data - 1) * 100 / 253, 0))
|
587
|
523
|
elif key == self.KEY_COLOR_TEMP:
|
588
|
|
- self[key] = round((self[key] - 250) * 10 / 204, 0)
|
589
|
|
- else:
|
590
|
|
- super().unpack_filter(key)
|
|
524
|
+ return int(round((data - 250) * 10 / 204, 0))
|
|
525
|
+ return super().__device_to_instance_filter__(key, data)
|
591
|
526
|
|
592
|
|
- def pack_filter(self, key, data):
|
|
527
|
+ def __instance_to_device_filter__(self, key, data):
|
593
|
528
|
if key == self.KEY_BRIGHTNESS:
|
594
|
|
- return round(data * 253 / 100 + 1, 0)
|
|
529
|
+ return int(round(data * 253 / 100 + 1, 0))
|
595
|
530
|
elif key == self.KEY_COLOR_TEMP:
|
596
|
|
- return round(data * 204 / 10 + 250, 0)
|
597
|
|
- else:
|
598
|
|
- return super().pack_filter(key, data)
|
|
531
|
+ return int(round(data * 204 / 10 + 250, 0))
|
|
532
|
+ return super().__instance_to_device_filter__(key, data)
|
599
|
533
|
|
600
|
534
|
#
|
601
|
535
|
# RX
|
|
@@ -627,8 +561,8 @@ class tradfri_light(base):
|
627
|
561
|
self.mqtt_client.send(self.topic + "/get", '{"%s": ""}' % self.KEY_OUTPUT_0)
|
628
|
562
|
|
629
|
563
|
def set_output_0(self, state):
|
630
|
|
- """state: [True, False, 'toggle']"""
|
631
|
|
- self.pack(self.KEY_OUTPUT_0, state)
|
|
564
|
+ """state: [True, False]"""
|
|
565
|
+ self.send_command(self.KEY_OUTPUT_0, state)
|
632
|
566
|
|
633
|
567
|
def set_output_0_mcb(self, device, key, data):
|
634
|
568
|
self.logger.log(logging.INFO if data != self.output_0 else logging.DEBUG, "Changing output 0 to %s", str(data))
|
|
@@ -636,18 +570,18 @@ class tradfri_light(base):
|
636
|
570
|
|
637
|
571
|
def toggle_output_0_mcb(self, device, key, data):
|
638
|
572
|
self.logger.info("Toggeling output 0")
|
639
|
|
- self.set_output_0('toggle')
|
|
573
|
+ self.set_output_0(not self.output_0)
|
640
|
574
|
|
641
|
575
|
def set_brightness(self, brightness):
|
642
|
576
|
"""brightness: [0, ..., 100]"""
|
643
|
|
- self.pack(self.KEY_BRIGHTNESS, brightness)
|
|
577
|
+ self.send_command(self.KEY_BRIGHTNESS, brightness)
|
644
|
578
|
|
645
|
579
|
def set_brightness_mcb(self, device, key, data):
|
646
|
580
|
self.logger.log(logging.INFO if data != self.brightness else logging.DEBUG, "Changing brightness to %s", str(data))
|
647
|
581
|
self.set_brightness(data)
|
648
|
582
|
|
649
|
583
|
def default_inc(self, speed=40):
|
650
|
|
- self.pack(self.KEY_BRIGHTNESS_FADE, speed)
|
|
584
|
+ self.send_command(self.KEY_BRIGHTNESS_FADE, speed)
|
651
|
585
|
|
652
|
586
|
def default_dec(self, speed=-40):
|
653
|
587
|
self.default_inc(speed)
|
|
@@ -657,7 +591,7 @@ class tradfri_light(base):
|
657
|
591
|
|
658
|
592
|
def set_color_temp(self, color_temp):
|
659
|
593
|
"""color_temp: [0, ..., 10]"""
|
660
|
|
- self.pack(self.KEY_COLOR_TEMP, color_temp)
|
|
594
|
+ self.send_command(self.KEY_COLOR_TEMP, color_temp)
|
661
|
595
|
|
662
|
596
|
def set_color_temp_mcb(self, device, key, data):
|
663
|
597
|
self.logger.log(logging.INFO if data != self.color_temp else logging.DEBUG, "Changing color temperature to %s", str(data))
|
|
@@ -693,6 +627,20 @@ class tradfri_button(base):
|
693
|
627
|
|
694
|
628
|
def __init__(self, mqtt_client, topic):
|
695
|
629
|
super().__init__(mqtt_client, topic)
|
|
630
|
+ #
|
|
631
|
+ self.add_callback(self.KEY_BATTERY, None, self.__warning__, True)
|
|
632
|
+ self.__battery_warning__ = False
|
|
633
|
+
|
|
634
|
+ #
|
|
635
|
+ # WARNING CALL
|
|
636
|
+ #
|
|
637
|
+ def __warning__(self, client, key, data):
|
|
638
|
+ if data <= BATTERY_WARN_LEVEL:
|
|
639
|
+ if not self.__battery_warning__:
|
|
640
|
+ self.__battery_warning__ = True
|
|
641
|
+ pass # TODO: implement warning feedback (key: KEY_BATTERY_LOW - info: KEY_BATTERY)
|
|
642
|
+ else:
|
|
643
|
+ self.__battery_warning__ = False
|
696
|
644
|
|
697
|
645
|
#
|
698
|
646
|
# RX
|
|
@@ -702,15 +650,6 @@ class tradfri_button(base):
|
702
|
650
|
"""rv: action_txt"""
|
703
|
651
|
return self.get(self.KEY_ACTION)
|
704
|
652
|
|
705
|
|
- #
|
706
|
|
- # WARNING CALL
|
707
|
|
- #
|
708
|
|
- def warning_call_condition(self):
|
709
|
|
- return self.get(self.KEY_BATTERY) is not None and self.get(self.KEY_BATTERY) <= BATTERY_WARN_LEVEL
|
710
|
|
-
|
711
|
|
- def warning_text(self):
|
712
|
|
- return "Low battery level detected for %s. Battery level was %.0f%%." % (self.topic, self.get(self.KEY_BATTERY))
|
713
|
|
-
|
714
|
653
|
|
715
|
654
|
class brennenstuhl_heatingvalve(base):
|
716
|
655
|
KEY_LINKQUALITY = "linkquality"
|
|
@@ -734,12 +673,20 @@ class brennenstuhl_heatingvalve(base):
|
734
|
673
|
super().__init__(mqtt_client, topic)
|
735
|
674
|
self.mqtt_client.send(self.topic + '/' + self.TX_TOPIC, json.dumps({self.KEY_WINDOW_DETECTION: "ON",
|
736
|
675
|
self.KEY_CHILD_LOCK: "UNLOCK", self.KEY_VALVE_DETECTION: "ON", self.KEY_SYSTEM_MODE: "heat", self.KEY_PRESET: "manual"}))
|
|
676
|
+ #
|
|
677
|
+ self.add_callback(self.KEY_BATTERY, None, self.__warning__, True)
|
|
678
|
+ self.__battery_warning__ = False
|
737
|
679
|
|
738
|
|
- def warning_call_condition(self):
|
739
|
|
- return self.get(self.KEY_BATTERY, 100) <= BATTERY_WARN_LEVEL
|
740
|
|
-
|
741
|
|
- def warning_text(self):
|
742
|
|
- return "Low battery level detected for %s. Battery level was %.0f%%." % (self.topic, self.get(self.KEY_BATTERY))
|
|
680
|
+ #
|
|
681
|
+ # WARNING CALL
|
|
682
|
+ #
|
|
683
|
+ def __warning__(self, client, key, data):
|
|
684
|
+ if data <= BATTERY_WARN_LEVEL:
|
|
685
|
+ if not self.__battery_warning__:
|
|
686
|
+ self.__battery_warning__ = True
|
|
687
|
+ pass # TODO: implement warning feedback (key: KEY_BATTERY_LOW - info: KEY_BATTERY)
|
|
688
|
+ else:
|
|
689
|
+ self.__battery_warning__ = False
|
743
|
690
|
|
744
|
691
|
#
|
745
|
692
|
# RX
|
|
@@ -760,7 +707,7 @@ class brennenstuhl_heatingvalve(base):
|
760
|
707
|
# TX
|
761
|
708
|
#
|
762
|
709
|
def set_heating_setpoint(self, setpoint):
|
763
|
|
- self.pack(self.KEY_HEATING_SETPOINT, setpoint)
|
|
710
|
+ self.send_command(self.KEY_HEATING_SETPOINT, setpoint)
|
764
|
711
|
|
765
|
712
|
def set_heating_setpoint_mcb(self, device, key, data):
|
766
|
713
|
self.logger.info("Changing heating setpoint to %s", str(data))
|
|
@@ -782,27 +729,27 @@ class remote(base):
|
782
|
729
|
RX_IGNORE_TOPICS = [KEY_CD, KEY_LINE1, KEY_LINE3, KEY_MUTE, KEY_POWER, KEY_VOLUP, KEY_VOLDOWN]
|
783
|
730
|
|
784
|
731
|
def set_cd(self, device=None, key=None, data=None):
|
785
|
|
- self.pack(self.KEY_CD, None)
|
|
732
|
+ self.send_command(self.KEY_CD, None)
|
786
|
733
|
|
787
|
734
|
def set_line1(self, device=None, key=None, data=None):
|
788
|
|
- self.pack(self.KEY_LINE1, None)
|
|
735
|
+ self.send_command(self.KEY_LINE1, None)
|
789
|
736
|
|
790
|
737
|
def set_line3(self, device=None, key=None, data=None):
|
791
|
|
- self.pack(self.KEY_LINE3, None)
|
|
738
|
+ self.send_command(self.KEY_LINE3, None)
|
792
|
739
|
|
793
|
740
|
def set_mute(self, device=None, key=None, data=None):
|
794
|
|
- self.pack(self.KEY_MUTE, None)
|
|
741
|
+ self.send_command(self.KEY_MUTE, None)
|
795
|
742
|
|
796
|
743
|
def set_power(self, device=None, key=None, data=None):
|
797
|
|
- self.pack(self.KEY_POWER, None)
|
|
744
|
+ self.send_command(self.KEY_POWER, None)
|
798
|
745
|
|
799
|
746
|
def set_volume_up(self, data=False):
|
800
|
747
|
"""data: [True, False]"""
|
801
|
|
- self.pack(self.KEY_VOLUP, data)
|
|
748
|
+ self.send_command(self.KEY_VOLUP, data)
|
802
|
749
|
|
803
|
750
|
def set_volume_down(self, data=False):
|
804
|
751
|
"""data: [True, False]"""
|
805
|
|
- self.pack(self.KEY_VOLDOWN, data)
|
|
752
|
+ self.send_command(self.KEY_VOLDOWN, data)
|
806
|
753
|
|
807
|
754
|
def default_inc(self, device=None, key=None, data=None):
|
808
|
755
|
self.set_volume_up(True)
|
|
@@ -823,7 +770,7 @@ class status(base):
|
823
|
770
|
|
824
|
771
|
def set_state(self, num, data):
|
825
|
772
|
"""data: [True, False]"""
|
826
|
|
- self.pack(self.KEY_STATE + "/" + str(num), data)
|
|
773
|
+ self.send_command(self.KEY_STATE + "/" + str(num), data)
|
827
|
774
|
|
828
|
775
|
def set_state_mcb(self, device, key, data):
|
829
|
776
|
self.logger.info("Changing state to %s", str(data))
|