Browse Source

restructuring devices.nodered_gui* and the nodered_gui topics

tags/v1.0.0
Dirk Alders 2 years ago
parent
commit
fff16fd7d3

+ 1
- 1
.vscode/settings.json View File

2
     "python.defaultInterpreterPath": "./venv/bin/python",
2
     "python.defaultInterpreterPath": "./venv/bin/python",
3
     "editor.formatOnSave": true,
3
     "editor.formatOnSave": true,
4
     "autopep8.args": [
4
     "autopep8.args": [
5
-        "--max-line-length=120"
5
+        "--max-line-length=150"
6
     ],
6
     ],
7
     "editor.fontSize": 14,
7
     "editor.fontSize": 14,
8
     "emmet.includeLanguages": {
8
     "emmet.includeLanguages": {

+ 233
- 54
devices/__init__.py View File

40
 BATTERY_WARN_LEVEL = 5
40
 BATTERY_WARN_LEVEL = 5
41
 
41
 
42
 
42
 
43
-def DEVICE_TYPE_LIST():
44
-    return [shelly, silvercrest_powerplug, my_powerplug, tradfri_light, tradfri_button]
45
-
46
-
47
 def is_json(data):
43
 def is_json(data):
48
     try:
44
     try:
49
         json.loads(data)
45
         json.loads(data)
54
 
50
 
55
 
51
 
56
 class base(dict):
52
 class base(dict):
57
-    TX_TOPIC = None
53
+    TX_TOPIC = "set"
58
     TX_VALUE = 0
54
     TX_VALUE = 0
59
     TX_DICT = 1
55
     TX_DICT = 1
60
     TX_TYPE = -1
56
     TX_TYPE = -1
98
             self.__previous__[key] = prev_value
94
             self.__previous__[key] = prev_value
99
             # Filter, if needed
95
             # Filter, if needed
100
             self.unpack_filter(key)
96
             self.unpack_filter(key)
101
-            if prev_value != self.get(key):
102
-                logger.info("Received new data for (%s) %s - %s", self.topic, key, str(self.get(key)))
103
-            else:
104
-                logger.debug("Received data for (%s) %s - %s", self.topic, key, str(self.get(key)))
105
-            self.callback_caller(key, self[key])
97
+            logger.debug("Received data for (%s) %s - %s", self.topic, key, str(self.get(key)))
98
+            self.callback_caller(key, self[key], self.get(key) != self.__previous__.get(key))
106
         elif key not in self.RX_IGNORE_KEYS:
99
         elif key not in self.RX_IGNORE_KEYS:
107
             logger.warning('Got a message from \"%s\" with unparsed content "%s"', self.topic, key)
100
             logger.warning('Got a message from \"%s\" with unparsed content "%s"', self.topic, key)
108
         else:
101
         else:
147
                 logger.error(
140
                 logger.error(
148
                     "Unknown tx type. Set TX_TYPE of class to a known value")
141
                     "Unknown tx type. Set TX_TYPE of class to a known value")
149
             else:
142
             else:
150
-                logger.info("Sending data for (%s) %s - %s", self.topic, key, str(data))
143
+                logger.debug("Sending data for (%s) %s - %s", self.topic, key, str(data))
151
                 if self.TX_TYPE == self.TX_DICT:
144
                 if self.TX_TYPE == self.TX_DICT:
152
                     self.mqtt_client.send('/'.join([self.topic, self.TX_TOPIC]), json.dumps({key: data}))
145
                     self.mqtt_client.send('/'.join([self.topic, self.TX_TOPIC]), json.dumps({key: data}))
153
                 else:
146
                 else:
154
                     if type(data) not in [str, bytes]:
147
                     if type(data) not in [str, bytes]:
155
                         data = json.dumps(data)
148
                         data = json.dumps(data)
156
-                    self.mqtt_client.send('/'.join([self.topic, key, self.TX_TOPIC]
157
-                                          if len(self.TX_TOPIC) > 0 else [self.topic, key]), data)
149
+                    self.mqtt_client.send('/'.join([self.topic, key, self.TX_TOPIC] if len(self.TX_TOPIC) > 0 else [self.topic, key]), data)
158
         else:
150
         else:
159
             logger.error(
151
             logger.error(
160
                 "Unknown tx toptic. Set TX_TOPIC of class to a known value")
152
                 "Unknown tx toptic. Set TX_TOPIC of class to a known value")
161
 
153
 
162
-    def add_callback(self, key, data, callback):
154
+    def add_callback(self, key, data, callback, on_change_only=False):
163
         """
155
         """
164
         key: key or None for all keys
156
         key: key or None for all keys
165
         data: data or None for all data
157
         data: data or None for all data
166
         """
158
         """
167
-        cb_tup = (key, data, callback)
159
+        cb_tup = (key, data, callback, on_change_only)
168
         if cb_tup not in self.callback_list:
160
         if cb_tup not in self.callback_list:
169
             self.callback_list.append(cb_tup)
161
             self.callback_list.append(cb_tup)
170
 
162
 
174
     def warning_call_condition(self):
166
     def warning_call_condition(self):
175
         return False
167
         return False
176
 
168
 
177
-    def callback_caller(self, key, data):
178
-        for cb_key, cb_data, callback in self.callback_list:
169
+    def callback_caller(self, key, data, value_changed):
170
+        for cb_key, cb_data, callback, on_change_only in self.callback_list:
179
             if (cb_key == key or cb_key is None) and (cb_data == data or cb_data is None) and callback is not None:
171
             if (cb_key == key or cb_key is None) and (cb_data == data or cb_data is None) and callback is not None:
180
-                callback(self, key, data)
172
+                if not on_change_only or value_changed:
173
+                    callback(self, key, data)
181
 
174
 
182
     def warning_caller(self):
175
     def warning_caller(self):
183
         if self.warning_call_condition():
176
         if self.warning_call_condition():
202
     KEY_LONGPUSH_1 = "longpush/1"
195
     KEY_LONGPUSH_1 = "longpush/1"
203
     KEY_TEMPERATURE = "temperature"
196
     KEY_TEMPERATURE = "temperature"
204
     KEY_OVERTEMPERATURE = "overtemperature"
197
     KEY_OVERTEMPERATURE = "overtemperature"
205
-    #
206
-    TX_TOPIC = 'command'
198
+    KEY_ID = "id"
199
+    KEY_MODEL = "model"
200
+    KEY_MAC = "mac"
201
+    KEY_IP = "ip"
202
+    KEY_NEW_FIRMWARE = "new_fw"
203
+    KEY_FIRMWARE_VERSION = "fw_ver"
204
+    #
205
+    TX_TOPIC = "command"
207
     TX_TYPE = base.TX_VALUE
206
     TX_TYPE = base.TX_VALUE
208
     TX_FILTER_DATA_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1]
207
     TX_FILTER_DATA_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1]
209
     #
208
     #
210
-    RX_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1,
211
-               KEY_INPUT_0, KEY_INPUT_1, KEY_LONGPUSH_0, KEY_LONGPUSH_1,
212
-               KEY_OVERTEMPERATURE, KEY_TEMPERATURE]
213
-    RX_IGNORE_TOPICS = [KEY_OUTPUT_0 + '/' + "energy", KEY_OUTPUT_1 + '/' + "energy",
214
-                        'input_event/0', 'input_event/1']
209
+    RX_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_INPUT_0, KEY_INPUT_1, KEY_LONGPUSH_0, KEY_LONGPUSH_1, KEY_OVERTEMPERATURE, KEY_TEMPERATURE,
210
+               KEY_ID, KEY_MODEL, KEY_MAC, KEY_IP, KEY_NEW_FIRMWARE, KEY_FIRMWARE_VERSION]
211
+    RX_IGNORE_TOPICS = [KEY_OUTPUT_0 + '/' + "energy", KEY_OUTPUT_1 + '/' + "energy", 'input_event/0', 'input_event/1']
215
     RX_IGNORE_KEYS = ['temperature_f']
212
     RX_IGNORE_KEYS = ['temperature_f']
216
-    RX_FILTER_DATA_KEYS = [KEY_INPUT_0, KEY_INPUT_1, KEY_LONGPUSH_0, KEY_LONGPUSH_1,
217
-                           KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_OVERTEMPERATURE]
213
+    RX_FILTER_DATA_KEYS = [KEY_INPUT_0, KEY_INPUT_1, KEY_LONGPUSH_0, KEY_LONGPUSH_1, KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_OVERTEMPERATURE]
218
 
214
 
219
     def __init__(self, mqtt_client, topic):
215
     def __init__(self, mqtt_client, topic):
220
         super().__init__(mqtt_client, topic)
216
         super().__init__(mqtt_client, topic)
277
         """state: [True, False, 'toggle']"""
273
         """state: [True, False, 'toggle']"""
278
         self.pack(self.KEY_OUTPUT_0, state)
274
         self.pack(self.KEY_OUTPUT_0, state)
279
 
275
 
276
+    def set_output_0_mcb(self, device, key, data):
277
+        logger.log(logging.INFO if data != self.output_0 else logging.DEBUG, "%s: Changing output 0 to %s", self.topic, str(data))
278
+        self.set_output_0(data)
279
+
280
+    def toggle_output_0_mcb(self, device, key, data):
281
+        logger.info("%s: Toggeling output 0", self.topic)
282
+        self.set_output_0('toggle')
283
+
280
     def set_output_1(self, state):
284
     def set_output_1(self, state):
281
         """state: [True, False, 'toggle']"""
285
         """state: [True, False, 'toggle']"""
282
         self.pack(self.KEY_OUTPUT_1, state)
286
         self.pack(self.KEY_OUTPUT_1, state)
283
 
287
 
288
+    def set_output_1_mcb(self, device, key, data):
289
+        logger.log(logging.INFO if data != self.output_1 else logging.DEBUG, "%s: Changing output 1 to %s", self.topic, str(data))
290
+        self.set_output_1(data)
291
+
292
+    def toggle_output_1_mcb(self, device, key, data):
293
+        logger.info("%s: Toggeling output 1", self.topic)
294
+        self.set_output_1('toggle')
295
+
284
 
296
 
285
 class silvercrest_powerplug(base):
297
 class silvercrest_powerplug(base):
286
     KEY_LINKQUALITY = "linkquality"
298
     KEY_LINKQUALITY = "linkquality"
287
     KEY_OUTPUT_0 = "state"
299
     KEY_OUTPUT_0 = "state"
288
     #
300
     #
289
-    TX_TOPIC = 'set'
290
     TX_TYPE = base.TX_DICT
301
     TX_TYPE = base.TX_DICT
291
     TX_FILTER_DATA_KEYS = [KEY_OUTPUT_0]
302
     TX_FILTER_DATA_KEYS = [KEY_OUTPUT_0]
292
     #
303
     #
316
         """state: [True, False, 'toggle']"""
327
         """state: [True, False, 'toggle']"""
317
         self.pack(self.KEY_OUTPUT_0, state)
328
         self.pack(self.KEY_OUTPUT_0, state)
318
 
329
 
330
+    def set_output_0_mcb(self, device, key, data):
331
+        logger.log(logging.INFO if data != self.output_0 else logging.DEBUG, "%s: Changing output 0 to %s", self.topic, str(data))
332
+        self.set_output_0(data)
333
+
334
+    def toggle_output_0_mcb(self, device, key, data):
335
+        logger.info("%s: Toggeling output 0", self.topic)
336
+        self.set_output_0('toggle')
337
+
319
 
338
 
320
 class my_powerplug(base):
339
 class my_powerplug(base):
321
     KEY_OUTPUT_0 = "output/1"
340
     KEY_OUTPUT_0 = "output/1"
325
     KEY_OUTPUT_ALL = "output/all"
344
     KEY_OUTPUT_ALL = "output/all"
326
     KEY_OUTPUT_LIST = [KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_OUTPUT_2, KEY_OUTPUT_3]
345
     KEY_OUTPUT_LIST = [KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_OUTPUT_2, KEY_OUTPUT_3]
327
     #
346
     #
328
-    TX_TOPIC = 'set'
329
     TX_TYPE = base.TX_VALUE
347
     TX_TYPE = base.TX_VALUE
330
     #
348
     #
331
     RX_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_OUTPUT_2, KEY_OUTPUT_3]
349
     RX_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_OUTPUT_2, KEY_OUTPUT_3]
369
         """state: [True, False, 'toggle']"""
387
         """state: [True, False, 'toggle']"""
370
         self.pack(self.KEY_OUTPUT_0, state)
388
         self.pack(self.KEY_OUTPUT_0, state)
371
 
389
 
390
+    def set_output_0_mcb(self, device, key, data):
391
+        logger.log(logging.INFO if data != self.output_0 else logging.DEBUG, "%s: Changing output 0 to %s", self.topic, str(data))
392
+        self.set_output_0(data)
393
+
394
+    def toggle_output_0_mcb(self, device, key, data):
395
+        logger.info("%s: Toggeling output 0", self.topic)
396
+        self.set_output_0('toggle')
397
+
372
     def set_output_1(self, state):
398
     def set_output_1(self, state):
373
         """state: [True, False, 'toggle']"""
399
         """state: [True, False, 'toggle']"""
374
         self.pack(self.KEY_OUTPUT_1, state)
400
         self.pack(self.KEY_OUTPUT_1, state)
375
 
401
 
402
+    def set_output_1_mcb(self, device, key, data):
403
+        logger.log(logging.INFO if data != self.output_1 else logging.DEBUG, "%s: Changing output 1 to %s", self.topic, str(data))
404
+        self.set_output_1(data)
405
+
406
+    def toggle_output_1_mcb(self, device, key, data):
407
+        logger.info("%s: Toggeling output 1", self.topic)
408
+        self.set_output_1('toggle')
409
+
376
     def set_output_2(self, state):
410
     def set_output_2(self, state):
377
         """state: [True, False, 'toggle']"""
411
         """state: [True, False, 'toggle']"""
378
         self.pack(self.KEY_OUTPUT_2, state)
412
         self.pack(self.KEY_OUTPUT_2, state)
379
 
413
 
414
+    def set_output_2_mcb(self, device, key, data):
415
+        logger.log(logging.INFO if data != self.output_2 else logging.DEBUG, "%s: Changing output 2 to %s", self.topic, str(data))
416
+        self.set_output_2(data)
417
+
418
+    def toggle_output_2_mcb(self, device, key, data):
419
+        logger.info("%s: Toggeling output 2", self.topic)
420
+        self.set_output_2('toggle')
421
+
380
     def set_output_3(self, state):
422
     def set_output_3(self, state):
381
         """state: [True, False, 'toggle']"""
423
         """state: [True, False, 'toggle']"""
382
         self.pack(self.KEY_OUTPUT_3, state)
424
         self.pack(self.KEY_OUTPUT_3, state)
383
 
425
 
426
+    def set_output_3_mcb(self, device, key, data):
427
+        logger.log(logging.INFO if data != self.output_3 else logging.DEBUG, "%s: Changing output 3 to %s", self.topic, str(data))
428
+        self.set_output_3(data)
429
+
430
+    def toggle_output_3_mcb(self, device, key, data):
431
+        logger.info("%s: Toggeling output 3", self.topic)
432
+        self.set_output_3('toggle')
433
+
384
     def set_output_all(self, state):
434
     def set_output_all(self, state):
385
         """state: [True, False, 'toggle']"""
435
         """state: [True, False, 'toggle']"""
386
         self.pack(self.KEY_OUTPUT_ALL, state)
436
         self.pack(self.KEY_OUTPUT_ALL, state)
387
 
437
 
438
+    def set_output_all_mcb(self, device, key, data):
439
+        logger.info("%s: Changing all outputs to %s", self.topic, str(data))
440
+        self.set_output_all(data)
441
+
442
+    def toggle_output_all_mcb(self, device, key, data):
443
+        logger.info("%s: Toggeling all outputs", self.topic)
444
+        self.set_output_0('toggle')
445
+
388
 
446
 
389
 class tradfri_light(base):
447
 class tradfri_light(base):
390
     KEY_LINKQUALITY = "linkquality"
448
     KEY_LINKQUALITY = "linkquality"
393
     KEY_COLOR_TEMP = "color_temp"
451
     KEY_COLOR_TEMP = "color_temp"
394
     KEY_BRIGHTNESS_FADE = "brightness_move"
452
     KEY_BRIGHTNESS_FADE = "brightness_move"
395
     #
453
     #
396
-    TX_TOPIC = 'set'
397
     TX_TYPE = base.TX_DICT
454
     TX_TYPE = base.TX_DICT
398
     TX_FILTER_DATA_KEYS = [KEY_OUTPUT_0, KEY_BRIGHTNESS, KEY_COLOR_TEMP, KEY_BRIGHTNESS_FADE]
455
     TX_FILTER_DATA_KEYS = [KEY_OUTPUT_0, KEY_BRIGHTNESS, KEY_COLOR_TEMP, KEY_BRIGHTNESS_FADE]
399
     #
456
     #
408
         if key == self.KEY_BRIGHTNESS:
465
         if key == self.KEY_BRIGHTNESS:
409
             self[key] = (self[key] - 1) * 100 / 254
466
             self[key] = (self[key] - 1) * 100 / 254
410
         elif key == self.KEY_COLOR_TEMP:
467
         elif key == self.KEY_COLOR_TEMP:
411
-            self[key] = (self[key] - 250) * 100 / 204
468
+            self[key] = (self[key] - 250) * 10 / 204
412
         else:
469
         else:
413
             super().unpack_filter(key)
470
             super().unpack_filter(key)
414
 
471
 
416
         if key == self.KEY_BRIGHTNESS:
473
         if key == self.KEY_BRIGHTNESS:
417
             return data * 254 / 100 + 1
474
             return data * 254 / 100 + 1
418
         elif key == self.KEY_COLOR_TEMP:
475
         elif key == self.KEY_COLOR_TEMP:
419
-            return data * 204 / 100 + 250
476
+            return data * 204 / 10 + 250
420
         else:
477
         else:
421
             return super().pack_filter(key, data)
478
             return super().pack_filter(key, data)
422
 
479
 
435
 
492
 
436
     @property
493
     @property
437
     def brightness(self):
494
     def brightness(self):
438
-        """rv: numeric value [0%, ..., 100%"""
495
+        """rv: numeric value [0%, ..., 100%]"""
439
         return self.get(self.KEY_BRIGHTNESS, 0)
496
         return self.get(self.KEY_BRIGHTNESS, 0)
440
 
497
 
441
     @property
498
     @property
442
     def color_temp(self):
499
     def color_temp(self):
443
-        """rv: numeric value [0%, ..., 100%"""
500
+        """rv: numeric value [0, ..., 10]"""
444
         return self.get(self.KEY_COLOR_TEMP, 0)
501
         return self.get(self.KEY_COLOR_TEMP, 0)
445
 
502
 
446
     #
503
     #
450
         """state: [True, False, 'toggle']"""
507
         """state: [True, False, 'toggle']"""
451
         self.pack(self.KEY_OUTPUT_0, state)
508
         self.pack(self.KEY_OUTPUT_0, state)
452
 
509
 
510
+    def set_output_0_mcb(self, device, key, data):
511
+        logger.log(logging.INFO if data != self.output_0 else logging.DEBUG, "%s: Changing output 0 to %s", self.topic, str(data))
512
+        self.set_output_0(data)
513
+
514
+    def toggle_output_0_mcb(self, device, key, data):
515
+        logger.info("%s: Toggeling output 0", self.topic)
516
+        self.set_output_0('toggle')
517
+
453
     def set_brightness(self, brightness):
518
     def set_brightness(self, brightness):
454
         """brightness: [0, ..., 100]"""
519
         """brightness: [0, ..., 100]"""
455
         self.pack(self.KEY_BRIGHTNESS, brightness)
520
         self.pack(self.KEY_BRIGHTNESS, brightness)
456
 
521
 
522
+    def set_brightness_mcb(self, device, key, data):
523
+        logger.log(logging.INFO if data != self.brightness else logging.DEBUG, "%s: Changing brightness to %s", self.topic, str(data))
524
+        self.set_brightness(data)
525
+
457
     def default_inc(self, speed=40):
526
     def default_inc(self, speed=40):
458
         self.pack(self.KEY_BRIGHTNESS_FADE, speed)
527
         self.pack(self.KEY_BRIGHTNESS_FADE, speed)
459
 
528
 
464
         self.default_inc(0)
533
         self.default_inc(0)
465
 
534
 
466
     def set_color_temp(self, color_temp):
535
     def set_color_temp(self, color_temp):
467
-        """color_temp: [0, ..., 100]"""
536
+        """color_temp: [0, ..., 10]"""
468
         self.pack(self.KEY_COLOR_TEMP, color_temp)
537
         self.pack(self.KEY_COLOR_TEMP, color_temp)
469
 
538
 
539
+    def set_color_temp_mcb(self, device, key, data):
540
+        logger.log(logging.INFO if data != self.color_temp else logging.DEBUG, "%s: Changing color temperature to %s", self.topic, str(data))
541
+        self.set_color_temp(data)
542
+
470
 
543
 
471
 class tradfri_button(base):
544
 class tradfri_button(base):
472
     ACTION_TOGGLE = "toggle"
545
     ACTION_TOGGLE = "toggle"
488
     KEY_ACTION = "action"
561
     KEY_ACTION = "action"
489
     KEY_ACTION_DURATION = "action_duration"
562
     KEY_ACTION_DURATION = "action_duration"
490
     #
563
     #
491
-    TX_TOPIC = ''
492
-    #
493
     RX_KEYS = [KEY_LINKQUALITY, KEY_BATTERY, KEY_ACTION]
564
     RX_KEYS = [KEY_LINKQUALITY, KEY_BATTERY, KEY_ACTION]
494
     RX_IGNORE_KEYS = ['update', KEY_ACTION_DURATION]
565
     RX_IGNORE_KEYS = ['update', KEY_ACTION_DURATION]
495
 
566
 
514
         return "Low battery level detected for %s. Battery level was %.0f%%." % (self.topic, self.get(self.KEY_BATTERY))
585
         return "Low battery level detected for %s. Battery level was %.0f%%." % (self.topic, self.get(self.KEY_BATTERY))
515
 
586
 
516
 
587
 
517
-class nodered_gui(base):
588
+class nodered_gui_heatvalve(base):
518
     KEY_FEEDBACK = "feedback"
589
     KEY_FEEDBACK = "feedback"
519
     KEY_ENABLE = "enable"
590
     KEY_ENABLE = "enable"
520
     KEY_STATE = "state"
591
     KEY_STATE = "state"
524
     KEY_HEATING_SETPOINT = "heating_setpoint"
595
     KEY_HEATING_SETPOINT = "heating_setpoint"
525
     KEY_OFF_BUTTON = "off_button"
596
     KEY_OFF_BUTTON = "off_button"
526
     #
597
     #
527
-    TX_TOPIC = 'set'
528
     TX_TYPE = base.TX_VALUE
598
     TX_TYPE = base.TX_VALUE
529
     #
599
     #
530
     RX_KEYS = [KEY_STATE, KEY_BRIGHTNESS, KEY_COLOR_TEMP, KEY_HEATING_BOOST, KEY_HEATING_SETPOINT, KEY_OFF_BUTTON]
600
     RX_KEYS = [KEY_STATE, KEY_BRIGHTNESS, KEY_COLOR_TEMP, KEY_HEATING_BOOST, KEY_HEATING_SETPOINT, KEY_OFF_BUTTON]
571
     def set_feedback(self, data):
641
     def set_feedback(self, data):
572
         self.pack(self.KEY_FEEDBACK, data)
642
         self.pack(self.KEY_FEEDBACK, data)
573
 
643
 
574
-    def enable(self, data):
644
+
645
+
646
+class nodered_gui_button(base):
647
+    KEY_STATE = "state"
648
+    #
649
+    RX_KEYS = [KEY_STATE]
650
+
651
+    #
652
+    # RX
653
+    #
654
+    @property
655
+    def state(self):
656
+        """rv: [True, False]"""
657
+        return self.get(self.KEY_STATE)
658
+
659
+
660
+class nodered_gui_switch(nodered_gui_button):
661
+    TX_TYPE = base.TX_VALUE
662
+
663
+    #
664
+    # TX
665
+    #
666
+    def set_state(self, data):
667
+        """data: [True, False]"""
668
+        self.pack(self.KEY_STATE, data)
669
+
670
+    def set_state_mcb(self, device, key, data):
671
+        logger.log(logging.INFO if data != self.get(self.KEY_STATE) else logging.DEBUG, "%s: Changing data to %s", self.topic, str(data))
672
+        self.set_state(data)
673
+
674
+
675
+class nodered_gui_brightness_color_temp(base):
676
+    KEY_ENABLE = "enable"
677
+    KEY_BRIGHTNESS = "brightness"
678
+    KEY_COLOR_TEMP = "color_temp"
679
+    #
680
+    TX_TYPE = base.TX_VALUE
681
+    #
682
+    RX_KEYS = [KEY_ENABLE, KEY_BRIGHTNESS, KEY_COLOR_TEMP]
683
+
684
+    #
685
+    # RX
686
+    #
687
+    @property
688
+    def enable(self):
689
+        """rv: [True, False]"""
690
+        return self.get(self.KEY_ENABLE)
691
+
692
+    @property
693
+    def brightness(self):
694
+        """rv: [True, False]"""
695
+        return self.get(self.KEY_BRIGHTNESS)
696
+
697
+    @property
698
+    def color_temp(self):
699
+        """rv: [True, False]"""
700
+        return self.get(self.KEY_COLOR_TEMP)
701
+
702
+    #
703
+    # TX
704
+    #
705
+    def set_enable(self, data):
575
         """data: [True, False]"""
706
         """data: [True, False]"""
576
         self.pack(self.KEY_ENABLE, data)
707
         self.pack(self.KEY_ENABLE, data)
577
 
708
 
709
+    def set_enable_mcb(self, device, key, data):
710
+        logger.log(logging.INFO if data != self.get(self.KEY_ENABLE) else logging.DEBUG, "%s: Changing enable to %s", self.topic, str(data))
711
+        self.set_enable(data)
712
+
713
+    def set_brightness(self, data):
714
+        """data: [0%, ..., 100%]"""
715
+        self.pack(self.KEY_BRIGHTNESS, data)
716
+
717
+    def set_brightness_mcb(self, device, key, data):
718
+        logger.log(logging.INFO if data != self.get(self.KEY_BRIGHTNESS) else logging.DEBUG, "%s: Changing brightness to %s", self.topic, str(data))
719
+        self.set_brightness(data)
720
+
721
+    def set_color_temp(self, data):
722
+        """data: [0, ..., 10]"""
723
+        self.pack(self.KEY_COLOR_TEMP, data)
724
+
725
+    def set_color_temp_mcb(self, device, key, data):
726
+        logger.log(logging.INFO if data != self.get(self.KEY_COLOR_TEMP) else logging.DEBUG,
727
+                   "%s: Changing color temperature to %s", self.topic, str(data))
728
+        self.set_color_temp(data)
729
+
730
+
731
+class nodered_gui_leds(base):
732
+    KEY_LED_0 = "led0"
733
+    KEY_LED_1 = "led1"
734
+    KEY_LED_2 = "led2"
735
+    KEY_LED_3 = "led3"
736
+    KEY_LED_4 = "led4"
737
+    KEY_LED_5 = "led5"
738
+    KEY_LED_6 = "led6"
739
+    KEY_LED_7 = "led7"
740
+    KEY_LED_8 = "led8"
741
+    KEY_LED_9 = "led9"
742
+    #
743
+    TX_TYPE = base.TX_VALUE
744
+    #
745
+    RX_KEYS = [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]
746
+
747
+    def set_led(self, key, data):
748
+        """data: [True, False]"""
749
+        logger.log(logging.INFO if data != self.get(key) else logging.DEBUG, "%s: Changing led state for %s to %s", self.topic, key, str(data))
750
+        self.pack(key, data)
751
+
578
 
752
 
579
 class brennenstuhl_heatingvalve(base):
753
 class brennenstuhl_heatingvalve(base):
580
     KEY_LINKQUALITY = "linkquality"
754
     KEY_LINKQUALITY = "linkquality"
589
     KEY_VALVE_DETECTION = "valve_detection"
763
     KEY_VALVE_DETECTION = "valve_detection"
590
     KEY_WINDOW_DETECTION = "window_detection"
764
     KEY_WINDOW_DETECTION = "window_detection"
591
     #
765
     #
592
-    TX_TOPIC = 'set'
593
     TX_TYPE = base.TX_DICT
766
     TX_TYPE = base.TX_DICT
594
     #
767
     #
595
     RX_KEYS = [KEY_LINKQUALITY, KEY_BATTERY, KEY_HEATING_SETPOINT, KEY_TEMPERATURE]
768
     RX_KEYS = [KEY_LINKQUALITY, KEY_BATTERY, KEY_HEATING_SETPOINT, KEY_TEMPERATURE]
596
-    RX_IGNORE_KEYS = [KEY_AWAY_MODE, KEY_CHILD_LOCK, KEY_PRESET,
597
-                      KEY_SYSTEM_MODE, KEY_VALVE_DETECTION, KEY_WINDOW_DETECTION]
769
+    RX_IGNORE_KEYS = [KEY_AWAY_MODE, KEY_CHILD_LOCK, KEY_PRESET, KEY_SYSTEM_MODE, KEY_VALVE_DETECTION, KEY_WINDOW_DETECTION]
598
 
770
 
599
     def __init__(self, mqtt_client, topic):
771
     def __init__(self, mqtt_client, topic):
600
         super().__init__(mqtt_client, topic)
772
         super().__init__(mqtt_client, topic)
601
-        self.mqtt_client.send(self.topic + '/' + self.TX_TOPIC, json.dumps(
602
-            {self.KEY_WINDOW_DETECTION: "ON", self.KEY_CHILD_LOCK: "UNLOCK", self.KEY_VALVE_DETECTION: "ON", self.KEY_SYSTEM_MODE: "heat"}))
773
+        self.mqtt_client.send(self.topic + '/' + self.TX_TOPIC, json.dumps({self.KEY_WINDOW_DETECTION: "ON",
774
+                              self.KEY_CHILD_LOCK: "UNLOCK", self.KEY_VALVE_DETECTION: "ON", self.KEY_SYSTEM_MODE: "heat"}))
603
 
775
 
604
     def warning_call_condition(self):
776
     def warning_call_condition(self):
605
         return self.get(self.KEY_BATTERY) <= BATTERY_WARN_LEVEL
777
         return self.get(self.KEY_BATTERY) <= BATTERY_WARN_LEVEL
628
     def set_heating_setpoint(self, setpoint):
800
     def set_heating_setpoint(self, setpoint):
629
         self.pack(self.KEY_HEATING_SETPOINT, setpoint)
801
         self.pack(self.KEY_HEATING_SETPOINT, setpoint)
630
 
802
 
803
+    def set_heating_setpoint_mcb(self, device, key, data):
804
+        logger.info("%s: Changing heating setpoint to %s", self.topic, str(data))
805
+        self.set_heating_setpoint(data)
806
+
631
 
807
 
632
 class remote(base):
808
 class remote(base):
633
     KEY_CD = "CD"
809
     KEY_CD = "CD"
643
     #
819
     #
644
     RX_IGNORE_TOPICS = [KEY_CD, KEY_LINE1, KEY_LINE3, KEY_MUTE, KEY_POWER, KEY_VOLUP, KEY_VOLDOWN]
820
     RX_IGNORE_TOPICS = [KEY_CD, KEY_LINE1, KEY_LINE3, KEY_MUTE, KEY_POWER, KEY_VOLUP, KEY_VOLDOWN]
645
 
821
 
646
-    def set_cd(self):
822
+    def set_cd(self, device=None, key=None, data=None):
647
         self.pack(self.KEY_CD, None)
823
         self.pack(self.KEY_CD, None)
648
 
824
 
649
-    def set_line1(self):
825
+    def set_line1(self, device=None, key=None, data=None):
650
         self.pack(self.KEY_LINE1, None)
826
         self.pack(self.KEY_LINE1, None)
651
 
827
 
652
-    def set_line3(self):
828
+    def set_line3(self, device=None, key=None, data=None):
653
         self.pack(self.KEY_LINE3, None)
829
         self.pack(self.KEY_LINE3, None)
654
 
830
 
655
-    def set_mute(self):
831
+    def set_mute(self, device=None, key=None, data=None):
656
         self.pack(self.KEY_MUTE, None)
832
         self.pack(self.KEY_MUTE, None)
657
 
833
 
658
-    def set_power(self):
834
+    def set_power(self, device=None, key=None, data=None):
659
         self.pack(self.KEY_POWER, None)
835
         self.pack(self.KEY_POWER, None)
660
 
836
 
661
     def set_volume_up(self, data=False):
837
     def set_volume_up(self, data=False):
666
         """data: [True, False]"""
842
         """data: [True, False]"""
667
         self.pack(self.KEY_VOLDOWN, data)
843
         self.pack(self.KEY_VOLDOWN, data)
668
 
844
 
669
-    def default_inc(self):
845
+    def default_inc(self, device=None, key=None, data=None):
670
         self.set_volume_up(True)
846
         self.set_volume_up(True)
671
 
847
 
672
-    def default_dec(self):
848
+    def default_dec(self, device=None, key=None, data=None):
673
         self.set_volume_down(True)
849
         self.set_volume_down(True)
674
 
850
 
675
-    def default_stop(self):
851
+    def default_stop(self, device=None, key=None, data=None):
676
         self.set_volume_up(False)
852
         self.set_volume_up(False)
677
 
853
 
678
 
854
 
679
 class status(base):
855
 class status(base):
680
     KEY_STATE = "state"
856
     KEY_STATE = "state"
681
     #
857
     #
682
-    TX_TOPIC = 'set'
683
     TX_TYPE = base.TX_VALUE
858
     TX_TYPE = base.TX_VALUE
684
     #
859
     #
685
     RX_KEYS = [KEY_STATE]
860
     RX_KEYS = [KEY_STATE]
688
         """data: [True, False]"""
863
         """data: [True, False]"""
689
         self.pack(self.KEY_STATE + "/" + str(num), data)
864
         self.pack(self.KEY_STATE + "/" + str(num), data)
690
 
865
 
866
+    def set_state_mcb(self, device, key, data):
867
+        logger.info("%s: Changing state to %s", self.topic, str(data))
868
+        self.set_state(data)
869
+
691
 
870
 
692
 class audio_status(status):
871
 class audio_status(status):
693
     KEY_TITLE = "title"
872
     KEY_TITLE = "title"

+ 22
- 22
function/__init__.py View File

4
 import devices
4
 import devices
5
 from function.ground_floor_west import ground_floor_west_floor, ground_floor_west_marion, ground_floor_west_dirk
5
 from function.ground_floor_west import ground_floor_west_floor, ground_floor_west_marion, ground_floor_west_dirk
6
 from function.first_floor_west import first_floor_west_julian, first_floor_west_living
6
 from function.first_floor_west import first_floor_west_julian, first_floor_west_living
7
-from function.first_floor_east import first_floor_east_floor, first_floor_east_kitchen, first_floor_east_dining, first_floor_east_sleep_madi, first_floor_east_living
7
+from function.first_floor_east import first_floor_east_floor, first_floor_east_kitchen, first_floor_east_dining, first_floor_east_sleep, first_floor_east_living
8
 from function.common import common_heating, common_circulation_pump
8
 from function.common import common_heating, common_circulation_pump
9
 import inspect
9
 import inspect
10
 import logging
10
 import logging
15
     ROOT_LOGGER_NAME = 'root'
15
     ROOT_LOGGER_NAME = 'root'
16
 logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__)
16
 logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__)
17
 
17
 
18
-# TODO: usage of implementation strategy from gfw_dirk for ffe_sleep_madi
18
+# TODO: change topics for all zigbee devices to <type|[shellies, zigbee_*, gui, ...]>/<area|gfw, ffw, ffe>/<room>/<target|[main_light, floorlamp, ...]>/<function>
19
+# TODO: usage of implementation strategy from gfw_dirk for ffe_sleep
20
+# TODO: implement improved devices.nodered_gui_heatvalve incl. setpoint, boost, ... and functions from funtion.module
21
+#       implement nodered_gui_timer for circulation pump
19
 # TODO: implement garland (incl. day events like sunset, sunrise, ...)
22
 # TODO: implement garland (incl. day events like sunset, sunrise, ...)
20
 # TODO: implement warning message
23
 # TODO: implement warning message
21
 
24
 
26
         #
29
         #
27
         self.__devices__ = None
30
         self.__devices__ = None
28
         # heating and warm water
31
         # heating and warm water
29
-        self.common_heat_sleep_madi = common_heating(self.mqtt_client)
32
+        self.common_ffe_heat_sleep = common_heating(self.mqtt_client)
30
         self.common_circulation_pump = common_circulation_pump(self.mqtt_client)
33
         self.common_circulation_pump = common_circulation_pump(self.mqtt_client)
31
         # ground floor west
34
         # ground floor west
32
         self.gfw_floor = ground_floor_west_floor(self.mqtt_client)
35
         self.gfw_floor = ground_floor_west_floor(self.mqtt_client)
39
         self.ffe_floor = first_floor_east_floor(self.mqtt_client)
42
         self.ffe_floor = first_floor_east_floor(self.mqtt_client)
40
         self.ffe_kitchen = first_floor_east_kitchen(self.mqtt_client)
43
         self.ffe_kitchen = first_floor_east_kitchen(self.mqtt_client)
41
         self.ffe_dining = first_floor_east_dining(self.mqtt_client)
44
         self.ffe_dining = first_floor_east_dining(self.mqtt_client)
42
-        self.ffe_sleep_madi = first_floor_east_sleep_madi(self.mqtt_client)
45
+        self.ffe_sleep = first_floor_east_sleep(self.mqtt_client)
43
         self.ffe_living = first_floor_east_living(self.mqtt_client)
46
         self.ffe_living = first_floor_east_living(self.mqtt_client)
44
         #
47
         #
45
         # Interactions
48
         # Interactions
53
 
56
 
54
     def init_off_functionality(self):
57
     def init_off_functionality(self):
55
         # Off Buttons
58
         # Off Buttons
56
-        self.gui_button_all_off = devices.nodered_gui(self.mqtt_client, topic="gui/button_all_off")
57
-        self.gui_button_gfw_off = devices.nodered_gui(self.mqtt_client, topic="gui/button_gfw_off")
58
-        self.gui_button_ffw_off = devices.nodered_gui(self.mqtt_client, topic="gui/button_ffw_off")
59
-        self.gui_button_ffe_off = devices.nodered_gui(self.mqtt_client, topic="gui/button_ffe_off")
59
+        self.gui_button_all_off = devices.nodered_gui_button(self.mqtt_client, topic="gui/all/common/off/button")
60
+        self.gui_button_gfw_off = devices.nodered_gui_button(self.mqtt_client, topic="gui/gfw/common/off/button")
61
+        self.gui_button_ffw_off = devices.nodered_gui_button(self.mqtt_client, topic="gui/ffw/common/off/button")
62
+        self.gui_button_ffe_off = devices.nodered_gui_button(self.mqtt_client, topic="gui/ffe/common/off/button")
60
         #
63
         #
61
-        self.gui_button_all_off.add_callback(devices.nodered_gui.KEY_OFF_BUTTON, True, self.all_off)
62
-        self.gui_button_gfw_off.add_callback(devices.nodered_gui.KEY_OFF_BUTTON, True, self.gfw_off)
63
-        self.gui_button_ffw_off.add_callback(devices.nodered_gui.KEY_OFF_BUTTON, True, self.ffw_off)
64
-        self.gui_button_ffe_off.add_callback(devices.nodered_gui.KEY_OFF_BUTTON, True, self.ffe_off)
64
+        self.gui_button_all_off.add_callback(devices.nodered_gui_button.KEY_STATE, True, self.all_off)
65
+        self.gui_button_gfw_off.add_callback(devices.nodered_gui_button.KEY_STATE, True, self.gfw_off)
66
+        self.gui_button_ffw_off.add_callback(devices.nodered_gui_button.KEY_STATE, True, self.ffw_off)
67
+        self.gui_button_ffe_off.add_callback(devices.nodered_gui_button.KEY_STATE, True, self.ffe_off)
65
         # Long push ffe_floor
68
         # Long push ffe_floor
66
-        self.ffe_floor.main_light_shelly.add_callback(
67
-            devices.shelly.KEY_LONGPUSH_0, True, self.ffe_floor.all_off_feedback)
69
+        self.ffe_floor.main_light_shelly.add_callback(devices.shelly.KEY_LONGPUSH_0, True, self.ffe_floor.all_off_feedback)
68
         self.ffe_floor.main_light_shelly.add_callback(devices.shelly.KEY_LONGPUSH_0, True, self.ffe_off)
70
         self.ffe_floor.main_light_shelly.add_callback(devices.shelly.KEY_LONGPUSH_0, True, self.ffe_off)
69
         # Long push input device
71
         # Long push input device
70
-        self.ffe_sleep_madi.button_tradfri.add_callback(
71
-            devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_RIGHT_LONG, self.ffe_off)
72
+        self.ffe_sleep.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_RIGHT_LONG, self.ffe_off)
72
 
73
 
73
     def getmembers(self, prefix):
74
     def getmembers(self, prefix):
74
         rv = []
75
         rv = []
107
         # shelly dirk input 1
108
         # shelly dirk input 1
108
         self.last_gfw_dirk_input_1 = None
109
         self.last_gfw_dirk_input_1 = None
109
         self.gfw_dirk.main_light_shelly.add_callback(devices.shelly.KEY_INPUT_1, None, self.gfw_dirk_input_1)
110
         self.gfw_dirk.main_light_shelly.add_callback(devices.shelly.KEY_INPUT_1, None, self.gfw_dirk_input_1)
110
-        # tradfri button sleep madi right click
111
-        self.ffe_sleep_madi.button_tradfri.add_callback(
112
-            devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_RIGHT, self.ffe_floor.toggle_main_light)
111
+        # tradfri button ffe_sleep right click
112
+        self.ffe_sleep.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION,
113
+                                                   devices.tradfri_button.ACTION_RIGHT, self.ffe_floor.main_light_shelly.toggle_output_0_mcb)
113
 
114
 
114
     def init_circulation_pump(self):
115
     def init_circulation_pump(self):
115
-        self.common_circulation_pump.main_light_shelly.add_callback(
116
-            devices.shelly.KEY_OUTPUT_0, None, self.ffe_kitchen.flash_main_light)
116
+        self.common_circulation_pump.main_light_shelly.add_callback(devices.shelly.KEY_OUTPUT_0, None, self.ffe_kitchen.flash_main_light)
117
 
117
 
118
     def gfw_dirk_input_1(self, device, key, data):
118
     def gfw_dirk_input_1(self, device, key, data):
119
         if self.last_gfw_dirk_input_1 is not None:
119
         if self.last_gfw_dirk_input_1 is not None:
120
             if self.last_gfw_dirk_input_1 != data:
120
             if self.last_gfw_dirk_input_1 != data:
121
-                self.gfw_floor.toggle_main_light(device, key, data)
121
+                self.gfw_floor.main_light_shelly.toggle_main_light(device, key, data)
122
         self.last_gfw_dirk_input_1 = data
122
         self.last_gfw_dirk_input_1 = data
123
 
123
 
124
     def devicelist(self):
124
     def devicelist(self):

+ 2
- 2
function/common.py View File

19
 class common_circulation_pump(room_shelly):
19
 class common_circulation_pump(room_shelly):
20
     def __init__(self, mqtt_client):
20
     def __init__(self, mqtt_client):
21
         # http://shelly1-E89F6D85A466
21
         # http://shelly1-E89F6D85A466
22
-        super().__init__(mqtt_client, "shellies/circulation_pump", "gui/common_sw_circulation_pump")
22
+        super().__init__(mqtt_client, "shellies/circulation_pump", "gui/none/common/circulation_pump/switch")
23
         #
23
         #
24
         self.main_light_shelly.add_callback(devices.shelly.KEY_OUTPUT_0, None, self.circ_pump_actions)
24
         self.main_light_shelly.add_callback(devices.shelly.KEY_OUTPUT_0, None, self.circ_pump_actions)
25
         #
25
         #
26
-        self.gui_timer_view = devices.nodered_gui(mqtt_client, "gui/ffe_circ_pump_timer")
26
+        self.gui_timer_view = devices.nodered_gui_heatvalve(mqtt_client, "gui/ffe_circ_pump_timer")
27
         self.gui_timer_view.set_feedback('-')
27
         self.gui_timer_view.set_feedback('-')
28
         #
28
         #
29
         self.cvi = changed_value_indicator()
29
         self.cvi = changed_value_indicator()

+ 63
- 157
function/first_floor_east.py View File

18
 class first_floor_east_floor(room_shelly):
18
 class first_floor_east_floor(room_shelly):
19
     def __init__(self, mqtt_client):
19
     def __init__(self, mqtt_client):
20
         # http://shelly1l-3C6105E4E629
20
         # http://shelly1l-3C6105E4E629
21
-        super().__init__(mqtt_client, "shellies/floor_madi", "gui/ffe_sw_floor")
21
+        super().__init__(mqtt_client, "shellies/floor_madi", "gui/ffe/floor/main_light/switch")
22
 
22
 
23
 
23
 
24
 class first_floor_east_kitchen(room_shelly):
24
 class first_floor_east_kitchen(room_shelly):
25
-    # TODO: add circulation pump (switch, time)
26
     def __init__(self, mqtt_client):
25
     def __init__(self, mqtt_client):
27
         # http://shelly1l-8CAAB5616C01
26
         # http://shelly1l-8CAAB5616C01
28
-        super().__init__(mqtt_client, "shellies/kitchen", "gui/ffe_sw_kitchen")
27
+        super().__init__(mqtt_client, "shellies/kitchen", "gui/ffe/kitchen/main_light/switch")
29
 
28
 
30
 
29
 
31
 class first_floor_east_dining(room_shelly):
30
 class first_floor_east_dining(room_shelly):
32
     def __init__(self, mqtt_client):
31
     def __init__(self, mqtt_client):
33
         # http://shelly1l-84CCA8ADD055
32
         # http://shelly1l-84CCA8ADD055
34
-        super().__init__(mqtt_client, "shellies/diningroom", "gui/ffe_sw_diningroom")
33
+        super().__init__(mqtt_client, "shellies/diningroom", "gui/ffe/diningroom/main_light/switch")
35
         self.floorlamp_powerplug = devices.silvercrest_powerplug(mqtt_client, "zigbee_og_e/powerplug/dining_floorlamp")
34
         self.floorlamp_powerplug = devices.silvercrest_powerplug(mqtt_client, "zigbee_og_e/powerplug/dining_floorlamp")
36
         if config.CHRISTMAS:
35
         if config.CHRISTMAS:
37
             self.garland_powerplug = devices.silvercrest_powerplug(mqtt_client, topic="zigbee_og_e/powerplug/aux")
36
             self.garland_powerplug = devices.silvercrest_powerplug(mqtt_client, topic="zigbee_og_e/powerplug/aux")
38
         #
37
         #
39
-        self.gui_switch_floorlamp = devices.nodered_gui(mqtt_client, topic="gui/ffe_sw_dining_floorlamp")
38
+        self.gui_switch_floorlamp = devices.nodered_gui_switch(mqtt_client, topic="gui/ffe/diningroom/floorlamp/switch")
40
         #
39
         #
41
         # Callback initialisation
40
         # Callback initialisation
42
         #
41
         #
43
-        self.main_light_shelly.add_callback(devices.shelly.KEY_OUTPUT_0, None, self.floorlamp_synchronisation)
44
-        self.gui_switch_floorlamp.add_callback(devices.nodered_gui.KEY_STATE, None, self.gui_switch_command_floorlamp)
45
-        self.floorlamp_powerplug.add_callback(devices.silvercrest_powerplug.KEY_OUTPUT_0,
46
-                                              None, self.gui_switch_feedback_floorlamp)
47
-        #
48
-        self.cvi = changed_value_indicator()
42
+        self.main_light_shelly.add_callback(devices.shelly.KEY_OUTPUT_0, None, self.floorlamp_powerplug.set_output_0_mcb, True)
43
+        self.gui_switch_floorlamp.add_callback(devices.nodered_gui_switch.KEY_STATE, None, self.floorlamp_powerplug.set_output_0_mcb)
44
+        self.floorlamp_powerplug.add_callback(devices.silvercrest_powerplug.KEY_OUTPUT_0, None, self.gui_switch_floorlamp.set_state_mcb)
49
 
45
 
50
     def all_off(self, device=None, key=None, data=None):
46
     def all_off(self, device=None, key=None, data=None):
51
         super().all_off(device, key, data)
47
         super().all_off(device, key, data)
52
         self.floorlamp_powerplug.set_output_0(False)
48
         self.floorlamp_powerplug.set_output_0(False)
53
-
54
-    def floorlamp_synchronisation(self, device, key, data):
55
-        if self.cvi.changed_here(device.topic, key, data) and device.previous_value(key) is not None:
56
-            logger.info("Syncing \"%s\" floorlamp with main light (%s)", type(self).__name__, str(data))
57
-            self.floorlamp_powerplug.set_output_0(data)
58
-
59
-    def gui_switch_command_floorlamp(self, device, key, data):
60
-        logger.info("Switching \"%s\" floorlamp: %s", type(self).__name__, str(data))
61
-        self.floorlamp_powerplug.set_output_0(data)
62
-
63
-    def gui_switch_feedback_floorlamp(self, device, key, data):
64
-        self.gui_switch_floorlamp.set_feedback(data)
49
+        if config.CHRISTMAS:
50
+            self.garland_powerplug.set_output_0(False)
65
 
51
 
66
 
52
 
67
-class first_floor_east_sleep_madi(room_shelly_tradfri_light):
53
+class first_floor_east_sleep(room_shelly_tradfri_light):
68
     def __init__(self, mqtt_client):
54
     def __init__(self, mqtt_client):
69
         # http://shelly1l-E8DB84A254C7
55
         # http://shelly1l-E8DB84A254C7
70
-        super().__init__(mqtt_client, "shellies/sleep_madi", "gui/ffe_sw_sleep_madi",
71
-                         "zigbee_og_e/light/sleep_madi", "gui/ffe_br_sleep_madi", "gui/ffe_ct_sleep_madi")
56
+        super().__init__(mqtt_client, "shellies/sleep_madi", "gui/ffe/sleep/main_light/switch",
57
+                         "zigbee_og_e/light/sleep_madi", "gui/ffe/sleep/main_light/br_ct")
72
         #
58
         #
73
         self.bed_light_di_tradfri = devices.tradfri_light(mqtt_client, topic="zigbee_og_e/light/sleep_bed_di")
59
         self.bed_light_di_tradfri = devices.tradfri_light(mqtt_client, topic="zigbee_og_e/light/sleep_bed_di")
74
         #
60
         #
75
-        self.gui_switch_bed_light_di = devices.nodered_gui(mqtt_client, "gui/ffe_sw_bed_light_di")
76
-        self.gui_brightness_bed_light_di = devices.nodered_gui(mqtt_client, "gui/ffe_br_bed_light_di")
77
-        self.gui_brightness_bed_light_di.enable(False)
78
-        self.gui_brightness_bed_light_di.set_feedback(0)
61
+        self.gui_switch_bed_light_di = devices.nodered_gui_switch(mqtt_client, "gui/ffe/sleep/bed_light_di/switch")
62
+        self.gui_br_ct_bed_light_di = devices.nodered_gui_brightness_color_temp(mqtt_client, "gui/ffe/sleep/bed_light_di/br_ct")
63
+        self.gui_led_active_device = devices.nodered_gui_leds(mqtt_client, "gui/ffe/sleep/active_device_state/led")
79
         #
64
         #
80
         self.button_tradfri = devices.tradfri_button(mqtt_client, topic="zigbee_og_e/input_device/og_east")
65
         self.button_tradfri = devices.tradfri_button(mqtt_client, topic="zigbee_og_e/input_device/og_east")
81
         #
66
         #
82
         # Callback initialisation
67
         # Callback initialisation
83
         #
68
         #
84
-        self.init_bed_light_functions()
85
-        self.init_fade_function()
86
-        #
69
+        # button
87
         self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_TOGGLE,
70
         self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_TOGGLE,
88
-                                         self.toggle_main_light)
71
+                                         self.main_light_shelly.toggle_output_0_mcb)
89
         self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_BRIGHTNESS_UP,
72
         self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_BRIGHTNESS_UP,
90
-                                         self.toggle_bed_light_di)
73
+                                         self.bed_light_di_tradfri.toggle_output_0_mcb)
91
         self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_BRIGHTNESS_DOWN,
74
         self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_BRIGHTNESS_DOWN,
92
-                                         self.toggle_bed_light_di)
93
-        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, None,
94
-                                         self.fade_light)
75
+                                         self.bed_light_di_tradfri.toggle_output_0_mcb)
76
+        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, None, self.fade_light)
77
+
78
+        # bed light
79
+        # switch
80
+        self.gui_switch_bed_light_di.add_callback(devices.nodered_gui_switch.KEY_STATE, None, self.bed_light_di_tradfri.set_output_0_mcb)
81
+        self.bed_light_di_tradfri.add_callback(devices.tradfri_light.KEY_OUTPUT_0, None, self.gui_switch_bed_light_di.set_state_mcb)
82
+        # brightness and color temperature
83
+        self.bed_light_di_tradfri.add_callback(devices.tradfri_light.KEY_OUTPUT_0, None, self.gui_br_ct_bed_light_di.set_enable_mcb)
84
+        self.gui_br_ct_bed_light_di.add_callback(devices.nodered_gui_brightness_color_temp.KEY_BRIGHTNESS,
85
+                                                 None, self.bed_light_di_tradfri.set_brightness_mcb)
86
+        self.bed_light_di_tradfri.add_callback(devices.tradfri_light.KEY_OUTPUT_0, None, self.gui_br_ct_bed_light_di.set_enable_mcb)
87
+        self.bed_light_di_tradfri.add_callback(devices.tradfri_light.KEY_BRIGHTNESS, None, self.gui_br_ct_bed_light_di.set_brightness_mcb)
88
+
89
+        # fade function
90
+        self.main_light_shelly.add_callback(devices.shelly.KEY_OUTPUT_0, None, self.state_machine_last_activated_device)
91
+        self.bed_light_di_tradfri.add_callback(devices.tradfri_light.KEY_OUTPUT_0, None, self.state_machine_last_activated_device)
92
+        self.last_activated_device = None
95
 
93
 
96
     def all_off(self, device=None, key=None, data=None):
94
     def all_off(self, device=None, key=None, data=None):
97
         super().all_off(device, key, data)
95
         super().all_off(device, key, data)
98
         self.bed_light_di_tradfri.set_output_0(False)
96
         self.bed_light_di_tradfri.set_output_0(False)
99
 
97
 
100
-    # bed light
101
-    def init_bed_light_functions(self):
102
-        self.gui_switch_bed_light_di.add_callback(
103
-            devices.nodered_gui.KEY_STATE, None, self.gui_switch_command_bed_light_di)
104
-        self.bed_light_di_tradfri.add_callback(
105
-            devices.tradfri_light.KEY_OUTPUT_0, None, self.gui_switch_feedback_bed_light_di)
106
-        self.bed_light_di_tradfri.add_callback(
107
-            devices.tradfri_light.KEY_BRIGHTNESS, None, self.set_gui_brightness_bed_light_di)
108
-        self.gui_brightness_bed_light_di.add_callback(
109
-            devices.nodered_gui.KEY_BRIGHTNESS, None, self.set_brightness_bed_light_di)
110
-
111
-    def gui_switch_command_bed_light_di(self, device, key, data):
112
-        logger.info("Switching \"%s\" bed light dirk: %s", type(self).__name__, str(data))
113
-        self.bed_light_di_tradfri.set_output_0(data)
114
-
115
-    def gui_switch_feedback_bed_light_di(self, device, key, data):
116
-        self.gui_switch_bed_light_di.set_feedback(data)
117
-        self.gui_brightness_bed_light_di.enable(data)
118
-        if data is False:
119
-            self.gui_brightness_bed_light_di.set_feedback(0)
120
-        else:
121
-            self.gui_brightness_bed_light_di.set_feedback(self.bed_light_di_tradfri.brightness)
122
-
123
-    def set_gui_brightness_bed_light_di(self, device, key, data):
124
-        self.gui_brightness_bed_light_di.set_feedback(data)
125
-
126
-    def set_brightness_bed_light_di(self, device, key, data):
127
-        logger.info("Setting brightness \"%s\" bed light dirk: %.1f", type(self).__name__, data)
128
-        self.bed_light_di_tradfri.set_brightness(data)
129
-
130
-    def toggle_bed_light_di(self, device, key, data):
131
-        logger.info("Toggeling \"%s\" bed light dirk", type(self).__name__)
132
-        self.bed_light_di_tradfri.set_output_0("toggle")
133
-
134
-    # fade
135
-    def init_fade_function(self):
136
-        self.main_light_shelly.add_callback(devices.shelly.KEY_OUTPUT_0, None, self.state_machine_last_activated_device)
137
-        self.bed_light_di_tradfri.add_callback(devices.tradfri_light.KEY_OUTPUT_0,
138
-                                               None, self.state_machine_last_activated_device)
139
-        #
140
-        self.last_activated_device = None
141
-
142
     def state_machine_last_activated_device(self, device, topic, data):
98
     def state_machine_last_activated_device(self, device, topic, data):
143
         if data is True:
99
         if data is True:
144
             self.last_activated_device = device.topic
100
             self.last_activated_device = device.topic
149
                 self.last_activated_device = self.main_light_shelly.topic
105
                 self.last_activated_device = self.main_light_shelly.topic
150
             else:
106
             else:
151
                 self.last_activated_device = None
107
                 self.last_activated_device = None
152
-        self.mqtt_client.send("gui/ffe_led_main_light_sleep/set",
153
-                              json.dumps(self.last_activated_device == self.main_light_shelly.topic))
154
-        self.mqtt_client.send("gui/ffe_led_bed_light_sleep_di/set",
155
-                              json.dumps(self.last_activated_device == self.bed_light_di_tradfri.topic))
108
+        self.gui_led_active_device.set_led(devices.nodered_gui_leds.KEY_LED_0, self.last_activated_device == self.main_light_shelly.topic)
109
+        self.gui_led_active_device.set_led(devices.nodered_gui_leds.KEY_LED_1, self.last_activated_device == self.bed_light_di_tradfri.topic)
156
 
110
 
157
     def fade_light(self, device, topic, data):
111
     def fade_light(self, device, topic, data):
158
         if self.last_activated_device == self.main_light_shelly.topic:
112
         if self.last_activated_device == self.main_light_shelly.topic:
175
 class first_floor_east_living(room_shelly_tradfri_light):
129
 class first_floor_east_living(room_shelly_tradfri_light):
176
     def __init__(self, mqtt_client):
130
     def __init__(self, mqtt_client):
177
         # http://shelly1l-3C6105E3F910
131
         # http://shelly1l-3C6105E3F910
178
-        super().__init__(mqtt_client, "shellies/livingroom", "gui/ffe_sw_livingroom",
179
-                         "zigbee_og_e/light/livingroom", "gui/ffe_br_livingroom", "gui/ffe_ct_livingroom")
132
+        super().__init__(mqtt_client, "shellies/livingroom", "gui/ffe/livingroom/main_light/switch",
133
+                         "zigbee_og_e/light/livingroom", "gui/ffe/livingroom/main_light/br_ct")
180
         for i in range(1, 7):
134
         for i in range(1, 7):
181
-            setattr(self, 'floorlamp_tradfri_%d' % i,
182
-                    devices.tradfri_light(mqtt_client, topic="zigbee_og_e/light/living_floorlamp_%d" % i))
135
+            setattr(self, 'floorlamp_tradfri_%d' % i, devices.tradfri_light(mqtt_client, topic="zigbee_og_e/light/living_floorlamp_%d" % i))
136
+        #
183
         if config.CHRISTMAS:
137
         if config.CHRISTMAS:
184
             self.powerplug_xmas_tree = devices.silvercrest_powerplug(mqtt_client, "zigbee_og_e/powerplug/xmas-tree")
138
             self.powerplug_xmas_tree = devices.silvercrest_powerplug(mqtt_client, "zigbee_og_e/powerplug/xmas-tree")
185
             self.powerplug_xmas_star = devices.silvercrest_powerplug(mqtt_client, "zigbee_og_e/powerplug/xmas-star")
139
             self.powerplug_xmas_star = devices.silvercrest_powerplug(mqtt_client, "zigbee_og_e/powerplug/xmas-star")
186
         #
140
         #
187
-        self.gui_switch_floorlamp = devices.nodered_gui(mqtt_client, topic="gui/ffe_sw_living_floorlamp")
188
-        self.gui_brightness_floorlamp = devices.nodered_gui(mqtt_client, "gui/ffe_br_livingroom_floorlamp")
189
-        self.gui_brightness_floorlamp.enable(False)
190
-        self.gui_brightness_floorlamp.set_feedback(0)
191
-        self.gui_color_temp_floorlamp = devices.nodered_gui(mqtt_client, "gui/ffe_ct_livingroom_floorlamp")
192
-        self.gui_color_temp_floorlamp.enable(False)
193
-        self.gui_color_temp_floorlamp.set_feedback(0)
141
+        self.gui_switch_floorlamp = devices.nodered_gui_switch(mqtt_client, topic="gui/ffe/livingroom/floorlamp/switch")
142
+        self.gui_br_ct_floorlamp = devices.nodered_gui_brightness_color_temp(mqtt_client, "gui/ffe/livingroom/floorlamp/br_ct")
194
         #
143
         #
195
         if config.CHRISTMAS:
144
         if config.CHRISTMAS:
196
-            self.gui_switch_xmas_tree = devices.nodered_gui(mqtt_client, "gui/ffe_sw_livingroom_xmas_tree")
145
+            self.gui_switch_xmas_tree = devices.nodered_gui_switch(mqtt_client, "gui/ffe/livingroom/xmas_tree/switch")
197
         #
146
         #
198
         # Callback initialisation
147
         # Callback initialisation
199
         #
148
         #
200
-        self.main_light_shelly.add_callback(devices.shelly.KEY_OUTPUT_0, None, self.floorlamp_synchronisation)
201
-        self.gui_switch_floorlamp.add_callback(devices.nodered_gui.KEY_STATE, None, self.gui_switch_command_floorlamp)
202
-        self.floorlamp_tradfri_1.add_callback(
203
-            devices.tradfri_light.KEY_OUTPUT_0, None, self.gui_switch_feedback_floorlamp)
204
-        self.floorlamp_tradfri_1.add_callback(
205
-            devices.tradfri_light.KEY_BRIGHTNESS, None, self.set_gui_brightness_floorlamp)
206
-        self.floorlamp_tradfri_1.add_callback(
207
-            devices.tradfri_light.KEY_COLOR_TEMP, None, self.set_gui_color_temp_floorlamp)
208
-        self.gui_brightness_floorlamp.add_callback(
209
-            devices.nodered_gui.KEY_BRIGHTNESS, None, self.set_brightness_floorlamp)
210
-        self.gui_color_temp_floorlamp.add_callback(
211
-            devices.nodered_gui.KEY_COLOR_TEMP, None, self.set_color_temp_floorlamp)
149
+
150
+        # floor lamp
151
+        for device in self.__floorlamp_devices__():
152
+            self.main_light_shelly.add_callback(devices.shelly.KEY_OUTPUT_0, None, device.set_output_0_mcb, True)
153
+            self.gui_switch_floorlamp.add_callback(devices.nodered_gui_switch.KEY_STATE, None, device.set_output_0_mcb)
154
+            self.gui_br_ct_floorlamp.add_callback(devices.nodered_gui_brightness_color_temp.KEY_BRIGHTNESS, None, device.set_brightness_mcb)
155
+            self.gui_br_ct_floorlamp.add_callback(devices.nodered_gui_brightness_color_temp.KEY_COLOR_TEMP, None, device.set_color_temp_mcb)
156
+        self.floorlamp_tradfri_1.add_callback(devices.tradfri_light.KEY_OUTPUT_0, None, self.gui_switch_floorlamp.set_state_mcb)
157
+        self.floorlamp_tradfri_1.add_callback(devices.tradfri_light.KEY_OUTPUT_0, None, self.gui_br_ct_floorlamp.set_enable_mcb)
158
+        self.floorlamp_tradfri_1.add_callback(devices.tradfri_light.KEY_BRIGHTNESS, None, self.gui_br_ct_floorlamp.set_brightness_mcb)
159
+        self.floorlamp_tradfri_1.add_callback(devices.tradfri_light.KEY_COLOR_TEMP, None, self.gui_br_ct_floorlamp.set_color_temp_mcb)
212
         #
160
         #
213
         if config.CHRISTMAS:
161
         if config.CHRISTMAS:
214
-            self.powerplug_xmas_tree.add_callback(
215
-                devices.silvercrest_powerplug.KEY_OUTPUT_0, None, self.powerplug_xmas_action)
216
-            self.gui_switch_xmas_tree.add_callback(devices.nodered_gui.KEY_STATE, None, self.gui_switch_command_xmas)
162
+            self.powerplug_xmas_tree.add_callback(devices.silvercrest_powerplug.KEY_OUTPUT_0, None, self.gui_switch_xmas_tree.set_state_mcb)
163
+            self.gui_switch_xmas_tree.add_callback(devices.nodered_gui_switch.KEY_STATE, None, self.powerplug_xmas_tree.set_output_0_mcb)
164
+            #
165
+            self.powerplug_xmas_tree.add_callback(devices.silvercrest_powerplug.KEY_OUTPUT_0, None, self.powerplug_xmas_star.set_output_0_mcb)
217
         #
166
         #
218
         self.cvi = changed_value_indicator()
167
         self.cvi = changed_value_indicator()
219
 
168
 
221
         super().all_off(device, key, data)
170
         super().all_off(device, key, data)
222
         for floorlamp in self.__floorlamp_devices__():
171
         for floorlamp in self.__floorlamp_devices__():
223
             floorlamp.set_output_0(False)
172
             floorlamp.set_output_0(False)
173
+        if config.CHRISTMAS:
174
+            self.powerplug_xmas_tree.set_output_0(False)
175
+            self.powerplug_xmas_star.set_output_0(False)
224
 
176
 
225
     def __floorlamp_devices__(self):
177
     def __floorlamp_devices__(self):
226
         rv = []
178
         rv = []
227
         for i in range(1, 7):
179
         for i in range(1, 7):
228
             rv.append(getattr(self, 'floorlamp_tradfri_%d' % i))
180
             rv.append(getattr(self, 'floorlamp_tradfri_%d' % i))
229
         return rv
181
         return rv
230
-
231
-    def floorlamp_synchronisation(self, device, key, data):
232
-        if self.cvi.changed_here(device.topic, key, data) and device.previous_value(key) is not None:
233
-            logger.info("Syncing \"%s\" floorlamp with main light (%s)", type(self).__name__, str(data))
234
-            for device in self.__floorlamp_devices__():
235
-                device.set_output_0(data)
236
-
237
-    def gui_switch_command_floorlamp(self, device, key, data):
238
-        logger.info("Switching \"%s\" floorlamp: %s", type(self).__name__, str(data))
239
-        for device in self.__floorlamp_devices__():
240
-            device.set_output_0(data)
241
-
242
-    def gui_switch_feedback_floorlamp(self, device, key, data):
243
-        self.gui_switch_floorlamp.set_feedback(data)
244
-        self.gui_brightness_floorlamp.enable(data)
245
-        self.gui_color_temp_floorlamp.enable(data)
246
-        if data is False:
247
-            self.gui_brightness_floorlamp.set_feedback(0)
248
-            self.gui_color_temp_floorlamp.set_feedback(0)
249
-        else:
250
-            self.gui_brightness_floorlamp.set_feedback(self.floorlamp_tradfri_1.brightness)
251
-            self.gui_color_temp_floorlamp.set_feedback(self.floorlamp_tradfri_1.color_temp / 10)
252
-
253
-    def set_gui_brightness_floorlamp(self, device, key, data):
254
-        self.gui_brightness_floorlamp.set_feedback(data)
255
-
256
-    def set_gui_color_temp_floorlamp(self, device, key, data):
257
-        self.gui_color_temp_floorlamp.set_feedback(data / 10)
258
-
259
-    def set_brightness_floorlamp(self, device, key, data):
260
-        logger.info("Setting brightness \"%s\" floorlamp: %.1f", type(self).__name__, data)
261
-        for device in self.__floorlamp_devices__():
262
-            device.set_brightness(data)
263
-
264
-    def set_color_temp_floorlamp(self, device, key, data):
265
-        logger.info("Setting color_temp \"%s\" floorlamp: %.1f", type(self).__name__, data)
266
-        for device in self.__floorlamp_devices__():
267
-            device.set_color_temp(data * 10)
268
-
269
-    def powerplug_xmas_action(self, device, key, data):
270
-        self.gui_switch_xmas_tree.set_feedback(data)
271
-        self.powerplug_xmas_star.set_output_0(data)
272
-
273
-    def gui_switch_command_xmas(self, device, key, data):
274
-        logger.info("Switching \"%s\" xmas-tree: %s", type(self).__name__, data)
275
-        self.powerplug_xmas_tree.set_output_0(data)

+ 2
- 3
function/first_floor_west.py View File

15
 class first_floor_west_julian(room_shelly_tradfri_light):
15
 class first_floor_west_julian(room_shelly_tradfri_light):
16
     # http://shelly1l-3C6105E43452
16
     # http://shelly1l-3C6105E43452
17
     def __init__(self, mqtt_client):
17
     def __init__(self, mqtt_client):
18
-        super().__init__(mqtt_client, "shellies/julian", "gui/ffw_sw_julian",
19
-                         "zigbee_og_e/light/julian", "gui/ffw_br_julian", "gui/ffw_ct_julian")
18
+        super().__init__(mqtt_client, "shellies/julian", "gui/ffw/julian/main_light/switch", "zigbee_og_e/light/julian", "gui/ffw/julian/main_light/br_ct")
20
 
19
 
21
 
20
 
22
 class first_floor_west_living(room_shelly):
21
 class first_floor_west_living(room_shelly):
23
     # http://shelly1l-84CCA8ACE6A1
22
     # http://shelly1l-84CCA8ACE6A1
24
     def __init__(self, mqtt_client):
23
     def __init__(self, mqtt_client):
25
-        super().__init__(mqtt_client, "shellies/living_mika", "gui/ffw_sw_living")
24
+        super().__init__(mqtt_client, "shellies/living_mika", "gui/ffw/living/main_light/swicht")

+ 78
- 140
function/ground_floor_west.py View File

18
 class ground_floor_west_floor(room_shelly_silvercrest_light):
18
 class ground_floor_west_floor(room_shelly_silvercrest_light):
19
     # https://shelly1l-84CCA8AD1148
19
     # https://shelly1l-84CCA8AD1148
20
     def __init__(self, mqtt_client):
20
     def __init__(self, mqtt_client):
21
-        super().__init__(mqtt_client, "shellies/floor_eg_w", "gui/gfw_sw_floor",
22
-                         "zigbee_eg_w/light/floor_eg_w/a", "gui/gfw_br_floor", "gui/gfw_ct_floor")
21
+        super().__init__(mqtt_client, "shellies/floor_eg_w", "gui/gfw/floor/main_light/switch", "zigbee_eg_w/light/floor_eg_w/a", "gui/gfw/floor/main_light/br_ct")
23
         #
22
         #
24
         # Callback initialisation
23
         # Callback initialisation
25
         #
24
         #
26
         self.main_light_tradfri_2 = devices.tradfri_light(mqtt_client, "zigbee_eg_w/light/floor_eg_w/b")
25
         self.main_light_tradfri_2 = devices.tradfri_light(mqtt_client, "zigbee_eg_w/light/floor_eg_w/b")
27
-        self.main_light_tradfri.add_callback(devices.tradfri_light.KEY_BRIGHTNESS,
28
-                                             None, self.sync_brightness_main_light)
29
-        self.main_light_tradfri.add_callback(devices.tradfri_light.KEY_COLOR_TEMP,
30
-                                             None, self.sync_color_temp_main_light)
26
+        self.main_light_tradfri.add_callback(devices.tradfri_light.KEY_BRIGHTNESS, None, self.main_light_tradfri_2.set_brightness_mcb)
27
+        self.main_light_tradfri.add_callback(devices.tradfri_light.KEY_COLOR_TEMP, None, self.main_light_tradfri_2.set_color_temp_mcb)
31
 
28
 
32
     def send_init_message_main_light(self):
29
     def send_init_message_main_light(self):
33
-        return super().send_init_message_main_light()
30
+        super().send_init_message_main_light()
34
         self.main_light_tradfri_2.mqtt_client.send(self.main_light_tradfri_2.topic + "/get", '{"state": ""}')
31
         self.main_light_tradfri_2.mqtt_client.send(self.main_light_tradfri_2.topic + "/get", '{"state": ""}')
35
 
32
 
36
-    def sync_brightness_main_light(self, device, key, data):
37
-        self.main_light_tradfri_2.set_brightness(data)
38
-
39
-    def sync_color_temp_main_light(self, device, key, data):
40
-        self.main_light_tradfri_2.set_color_temp(data)
41
-
42
 
33
 
43
 class ground_floor_west_marion(room_shelly):
34
 class ground_floor_west_marion(room_shelly):
44
     # https://shelly1l-E8DB84A1E067
35
     # https://shelly1l-E8DB84A1E067
45
     def __init__(self, mqtt_client):
36
     def __init__(self, mqtt_client):
46
-        super().__init__(mqtt_client, "shellies/marion", "gui/gfw_sw_marion")
37
+        super().__init__(mqtt_client, "shellies/marion", "gui/gfw/marion/main_light/switch")
47
 
38
 
48
 
39
 
49
 class ground_floor_west_dirk(room_shelly_tradfri_light):
40
 class ground_floor_west_dirk(room_shelly_tradfri_light):
52
     STATE_ACTIVE_DEVICE_AMPLIFIER = 2
43
     STATE_ACTIVE_DEVICE_AMPLIFIER = 2
53
     STATE_ACTIVE_DEVICE_MAX_VALUE = STATE_ACTIVE_DEVICE_AMPLIFIER
44
     STATE_ACTIVE_DEVICE_MAX_VALUE = STATE_ACTIVE_DEVICE_AMPLIFIER
54
     #
45
     #
46
+    LED_ACTIVE_DEVICE_MAIN_LIGHT = devices.nodered_gui_leds.KEY_LED_0
47
+    LED_ACTIVE_DEVICE_DESK_LIGHT = devices.nodered_gui_leds.KEY_LED_1
48
+    LED_ACTIVE_DEVICE_AMPLIFIER = devices.nodered_gui_leds.KEY_LED_2
49
+    #
55
     KEY_POWERPLUG_AMPLIFIER = devices.my_powerplug.KEY_OUTPUT_0
50
     KEY_POWERPLUG_AMPLIFIER = devices.my_powerplug.KEY_OUTPUT_0
56
     KEY_POWERPLUG_CD_PLAYER = devices.my_powerplug.KEY_OUTPUT_2
51
     KEY_POWERPLUG_CD_PLAYER = devices.my_powerplug.KEY_OUTPUT_2
57
     KEY_POWERPLUG_DESK_LIGHT = devices.my_powerplug.KEY_OUTPUT_1
52
     KEY_POWERPLUG_DESK_LIGHT = devices.my_powerplug.KEY_OUTPUT_1
60
     AUDIO_SOURCE_PC = 0
55
     AUDIO_SOURCE_PC = 0
61
     AUDIO_SOURCE_CD = 1
56
     AUDIO_SOURCE_CD = 1
62
     AUDIO_SOURCE_RASPI = 2
57
     AUDIO_SOURCE_RASPI = 2
63
-    #
64
-    KEY_SPOTIFY = "hifi/spotify/state"
65
-    KEY_MPD = "hifi/mpd/state"
66
 
58
 
67
     # https://shelly1l-3C6105E44F27
59
     # https://shelly1l-3C6105E44F27
68
     def __init__(self, mqtt_client):
60
     def __init__(self, mqtt_client):
69
-        super().__init__(mqtt_client, "shellies/dirk", "gui/gfw_sw_dirk",
70
-                         "zigbee_eg_w/light/dirk", "gui/gfw_br_dirk", "gui/gfw_ct_dirk")
61
+        super().__init__(mqtt_client, "shellies/dirk", "gui/gfw/dirk/main_light/switch", "zigbee_eg_w/light/dirk", "gui/gfw/dirk/main_light/br_ct")
71
         #
62
         #
72
         self.powerplug_common = devices.my_powerplug(mqtt_client, "powerplug/dirk")
63
         self.powerplug_common = devices.my_powerplug(mqtt_client, "powerplug/dirk")
73
         self.desk_light_tradfri = devices.tradfri_light(mqtt_client, "zigbee_eg_w/light/dirk_desk")
64
         self.desk_light_tradfri = devices.tradfri_light(mqtt_client, "zigbee_eg_w/light/dirk_desk")
74
         self.button_tradfri = devices.tradfri_button(mqtt_client, "zigbee_eg_w/input_device/dirk")
65
         self.button_tradfri = devices.tradfri_button(mqtt_client, "zigbee_eg_w/input_device/dirk")
75
         #
66
         #
76
-        self.gui_switch_desk_light = devices.nodered_gui(mqtt_client, "gui/gfw_sw_desk_light")
77
-        self.gui_brightness_desk_light = devices.nodered_gui(mqtt_client, "gui/gfw_br_desk_light")
78
-        self.gui_brightness_desk_light.enable(False)
79
-        self.gui_brightness_desk_light.set_feedback(0)
80
-        self.gui_color_temp_desk_light = devices.nodered_gui(mqtt_client, "gui/gfw_ct_desk_light")
81
-        self.gui_color_temp_desk_light.enable(False)
82
-        self.gui_color_temp_desk_light.set_feedback(0)
67
+        self.gui_switch_desk_light = devices.nodered_gui_switch(mqtt_client, "gui/gfw/dirk/desk_light/switch")
68
+        self.gui_br_cr_desk_light = devices.nodered_gui_brightness_color_temp(mqtt_client, "gui/gfw/dirk/desk_light/br_ct")
83
         #
69
         #
84
-        self.gui_switch_amplifier = devices.nodered_gui(mqtt_client, "gui/gfw_sw_amplifier")
85
-        self.gui_switch_cd_player = devices.nodered_gui(mqtt_client, "gui/gfw_sw_cd_player")
86
-        self.gui_switch_pc_dock = devices.nodered_gui(mqtt_client, "gui/gfw_sw_pc_dock")
70
+        self.gui_switch_amplifier = devices.nodered_gui_switch(mqtt_client, "gui/gfw/dirk/amplifier/switch")
71
+        self.gui_switch_cd_player = devices.nodered_gui_switch(mqtt_client, "gui/gfw/dirk/cd_player/switch")
72
+        self.gui_switch_pc_dock = devices.nodered_gui_switch(mqtt_client, "gui/gfw/dirk/pc_dock/switch")
87
         #
73
         #
88
         self.remote_amplifier = devices.remote(mqtt_client, "hifi/remote/RAS5")
74
         self.remote_amplifier = devices.remote(mqtt_client, "hifi/remote/RAS5")
89
-        self.active_device_state_led = devices.status(mqtt_client, "gui/gfw_active_device_state")
75
+        self.gui_led_active_device = devices.nodered_gui_leds(mqtt_client, "gui/gfw/dirk/active_device_state/led")
90
         #
76
         #
91
         self.spotify_state = devices.audio_status(mqtt_client, "hifi/spotify")
77
         self.spotify_state = devices.audio_status(mqtt_client, "hifi/spotify")
92
         self.mpd_state = devices.audio_status(mqtt_client, "hifi/mpd")
78
         self.mpd_state = devices.audio_status(mqtt_client, "hifi/mpd")
95
         #
81
         #
96
         self.cvi = changed_value_indicator()
82
         self.cvi = changed_value_indicator()
97
         #
83
         #
98
-        self.powerplug_common.add_callback(None, None, self.powerplug_gui_feedback_actions)
84
+        # Callback initialisation
85
+        #
86
+
87
+        # main light
88
+        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_TOGGLE,
89
+                                         self.main_light_shelly.toggle_output_0_mcb)
90
+
91
+        # desk light
92
+        # switch
93
+        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_RIGHT,
94
+                                         self.powerplug_common.toggle_output_1_mcb)
95
+        self.gui_switch_desk_light.add_callback(devices.nodered_gui_switch.KEY_STATE, None, self.powerplug_common.set_output_1_mcb)
96
+        self.powerplug_common.add_callback(self.KEY_POWERPLUG_DESK_LIGHT, None, self.gui_switch_desk_light.set_state_mcb)
97
+        # brightness and color temp
98
+        self.gui_br_cr_desk_light.add_callback(devices.nodered_gui_brightness_color_temp.KEY_BRIGHTNESS,
99
+                                               None, self.desk_light_tradfri.set_brightness_mcb)
100
+        self.gui_br_cr_desk_light.add_callback(devices.nodered_gui_brightness_color_temp.KEY_COLOR_TEMP,
101
+                                               None, self.desk_light_tradfri.set_color_temp_mcb)
102
+        self.powerplug_common.add_callback(self.KEY_POWERPLUG_DESK_LIGHT, None, self.gui_br_cr_desk_light.set_enable_mcb)
103
+        self.desk_light_tradfri.add_callback(devices.tradfri_light.KEY_BRIGHTNESS, None, self.gui_br_cr_desk_light.set_brightness_mcb)
104
+        self.desk_light_tradfri.add_callback(devices.tradfri_light.KEY_COLOR_TEMP, None, self.gui_br_cr_desk_light.set_color_temp_mcb)
105
+
106
+        # amplifier
107
+        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_LEFT_LONG,
108
+                                         self.powerplug_common.toggle_output_0_mcb)
109
+        self.gui_switch_amplifier.add_callback(devices.nodered_gui_switch.KEY_STATE, None, self.powerplug_common.set_output_0_mcb)
110
+        self.powerplug_common.add_callback(self.KEY_POWERPLUG_AMPLIFIER, None, self.gui_switch_amplifier.set_state_mcb)
111
+        # amplifier auto on
99
         self.powerplug_common.add_callback(self.KEY_POWERPLUG_CD_PLAYER, None, self.cd_amplifier_synchronisation)
112
         self.powerplug_common.add_callback(self.KEY_POWERPLUG_CD_PLAYER, None, self.cd_amplifier_synchronisation)
100
         self.spotify_state.add_callback(devices.status.KEY_STATE, None, self.raspi_amplifier_synchronisation)
113
         self.spotify_state.add_callback(devices.status.KEY_STATE, None, self.raspi_amplifier_synchronisation)
101
         self.mpd_state.add_callback(devices.status.KEY_STATE, None, self.raspi_amplifier_synchronisation)
114
         self.mpd_state.add_callback(devices.status.KEY_STATE, None, self.raspi_amplifier_synchronisation)
102
-        #
103
-        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION,
104
-                                         devices.tradfri_button.ACTION_TOGGLE, self.toggle_main_light)
105
-        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION,
106
-                                         devices.tradfri_button.ACTION_RIGHT, self.desk_light_switch_action)
107
-        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION,
108
-                                         devices.tradfri_button.ACTION_LEFT_LONG, self.amplifier_switch_action)
109
-        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION,
110
-                                         devices.tradfri_button.ACTION_RIGHT_LONG, self.cd_player_switch_action)
111
-        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION,
112
-                                         devices.tradfri_button.ACTION_LEFT, self.pc_dock_switch_action)
113
-        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, None, self.brightness_action)
114
-        #
115
-        self.gui_switch_desk_light.add_callback(devices.nodered_gui.KEY_STATE, None, self.desk_light_switch_action)
116
-        self.gui_brightness_desk_light.add_callback(
117
-            devices.nodered_gui.KEY_BRIGHTNESS, None, self.desk_light_set_action)
118
-        self.gui_color_temp_desk_light.add_callback(
119
-            devices.nodered_gui.KEY_COLOR_TEMP, None, self.desk_light_set_action)
120
-        self.desk_light_tradfri.add_callback(devices.tradfri_light.KEY_BRIGHTNESS,
121
-                                             None, self.desk_light_set_gui_params_action)
122
-        self.desk_light_tradfri.add_callback(devices.tradfri_light.KEY_COLOR_TEMP,
123
-                                             None, self.desk_light_set_gui_params_action)
124
-        #
125
-        self.gui_switch_amplifier.add_callback(devices.nodered_gui.KEY_STATE, None, self.amplifier_switch_action)
126
-        self.gui_switch_cd_player.add_callback(devices.nodered_gui.KEY_STATE, None, self.cd_player_switch_action)
127
-        self.gui_switch_pc_dock.add_callback(devices.nodered_gui.KEY_STATE, None, self.pc_dock_switch_action)
128
-        #
129
-        self.main_light_shelly.add_callback(devices.shelly.KEY_OUTPUT_0, None, self.device_chooser_action)
130
-        self.powerplug_common.add_callback(None, None, self.device_chooser_action)
131
-        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION,
132
-                                         devices.tradfri_button.ACTION_BRIGHTNESS_UP, self.choose_next_device)
133
-        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION,
134
-                                         devices.tradfri_button.ACTION_BRIGHTNESS_DOWN, self.choose_prev_device)
135
-        #
115
+        # audio source
136
         self.powerplug_common.add_callback(self.KEY_POWERPLUG_AMPLIFIER, None, self.audio_source_selector)
116
         self.powerplug_common.add_callback(self.KEY_POWERPLUG_AMPLIFIER, None, self.audio_source_selector)
137
         self.powerplug_common.add_callback(self.KEY_POWERPLUG_CD_PLAYER, None, self.audio_source_selector)
117
         self.powerplug_common.add_callback(self.KEY_POWERPLUG_CD_PLAYER, None, self.audio_source_selector)
138
         self.spotify_state.add_callback(devices.status.KEY_STATE, None, self.audio_source_selector)
118
         self.spotify_state.add_callback(devices.status.KEY_STATE, None, self.audio_source_selector)
139
         self.mpd_state.add_callback(devices.status.KEY_STATE, None, self.audio_source_selector)
119
         self.mpd_state.add_callback(devices.status.KEY_STATE, None, self.audio_source_selector)
140
-        #
141
-        self.active_device_state = None
142
-        #
143
         self.audio_source = self.AUDIO_SOURCE_PC
120
         self.audio_source = self.AUDIO_SOURCE_PC
144
 
121
 
122
+        # cd player
123
+        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_RIGHT_LONG,
124
+                                         self.powerplug_common.toggle_output_2_mcb)
125
+        self.gui_switch_cd_player.add_callback(devices.nodered_gui_switch.KEY_STATE, None, self.powerplug_common.set_output_2_mcb)
126
+        self.powerplug_common.add_callback(self.KEY_POWERPLUG_CD_PLAYER, None, self.gui_switch_cd_player.set_state_mcb)
127
+
128
+        # pc dock
129
+        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_LEFT,
130
+                                         self.powerplug_common.toggle_output_3_mcb)
131
+        self.gui_switch_pc_dock.add_callback(devices.nodered_gui_switch.KEY_STATE, None, self.powerplug_common.set_output_3_mcb)
132
+        self.powerplug_common.add_callback(self.KEY_POWERPLUG_PC_DOCK, None, self.gui_switch_pc_dock.set_state_mcb)
133
+
134
+        # brightness
135
+        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, None, self.brightness_action)
136
+        self.main_light_shelly.add_callback(devices.shelly.KEY_OUTPUT_0, None, self.device_chooser_action)
137
+        self.powerplug_common.add_callback(None, None, self.device_chooser_action)
138
+        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_BRIGHTNESS_UP, self.choose_next_device)
139
+        self.button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_BRIGHTNESS_DOWN, self.choose_prev_device)
140
+        self.active_device_state = None
141
+        self.update_active_device_led()
142
+
145
     def all_off(self, device=None, key=None, data=None):
143
     def all_off(self, device=None, key=None, data=None):
146
         super().all_off(device, key, data)
144
         super().all_off(device, key, data)
147
         self.powerplug_common.set_output_all(False)
145
         self.powerplug_common.set_output_all(False)
148
 
146
 
149
-    def powerplug_gui_feedback_actions(self, device, key, data):
150
-        if key == self.KEY_POWERPLUG_AMPLIFIER:
151
-            self.gui_switch_amplifier.set_feedback(data)
152
-        elif key == self.KEY_POWERPLUG_DESK_LIGHT:
153
-            self.gui_switch_desk_light.set_feedback(data)
154
-            self.gui_brightness_desk_light.enable(data)
155
-            self.gui_color_temp_desk_light.enable(data)
156
-            if not data:
157
-                self.gui_brightness_desk_light.set_feedback(0)
158
-                self.gui_color_temp_desk_light.set_feedback(0)
159
-            else:
160
-                self.gui_brightness_desk_light.set_feedback(self.desk_light_tradfri.brightness)
161
-                self.gui_color_temp_desk_light.set_feedback(self.desk_light_tradfri.color_temp / 10)
162
-        elif key == self.KEY_POWERPLUG_CD_PLAYER:
163
-            self.gui_switch_cd_player.set_feedback(data)
164
-        elif key == self.KEY_POWERPLUG_PC_DOCK:
165
-            self.gui_switch_pc_dock.set_feedback(data)
166
-
167
     def cd_amplifier_synchronisation(self, device, key, data):
147
     def cd_amplifier_synchronisation(self, device, key, data):
168
         if self.cvi.changed_here(device.topic, key, data) and device.previous_value(key) is not None:
148
         if self.cvi.changed_here(device.topic, key, data) and device.previous_value(key) is not None:
169
             logger.info("Syncing \"%s\" amplifier with cd player: %s", type(self).__name__, data)
149
             logger.info("Syncing \"%s\" amplifier with cd player: %s", type(self).__name__, data)
174
             logger.info("Syncing \"%s\" amplifier with raspi player: %s", type(self).__name__, data)
154
             logger.info("Syncing \"%s\" amplifier with raspi player: %s", type(self).__name__, data)
175
             self.powerplug_common.set_output(self.KEY_POWERPLUG_AMPLIFIER, data)
155
             self.powerplug_common.set_output(self.KEY_POWERPLUG_AMPLIFIER, data)
176
 
156
 
177
-    def desk_light_switch_action(self, device, key, data):
178
-        if device == self.button_tradfri:
179
-            logger.info("Toggeling \"%s\" desk light to %s", type(self).__name__,
180
-                        not self.powerplug_common.get(self.KEY_POWERPLUG_DESK_LIGHT))
181
-            self.powerplug_common.set_output(self.KEY_POWERPLUG_DESK_LIGHT, "toggle")
182
-        else:
183
-            logger.info("Setting \"%s\" desk light: %s", type(self).__name__, data)
184
-            self.powerplug_common.set_output(self.KEY_POWERPLUG_DESK_LIGHT, data)
185
-
186
-    def desk_light_set_gui_params_action(self, device, key, data):
187
-        if key == devices.nodered_gui.KEY_BRIGHTNESS:
188
-            self.gui_brightness_desk_light.set_feedback(data)
189
-        elif key == devices.nodered_gui.KEY_COLOR_TEMP:
190
-            self.gui_color_temp_desk_light.set_feedback(data / 10)
191
-
192
-    def desk_light_set_action(self, device, key, data):
193
-        if key == devices.nodered_gui.KEY_BRIGHTNESS:
194
-            logger.info("Setting brightness \"%s\" desk light: %s", type(self).__name__, data)
195
-            self.desk_light_tradfri.set_brightness(data)
196
-        elif key == devices.nodered_gui.KEY_COLOR_TEMP:
197
-            logger.info("Setting color_temp \"%s\" desk light: %s", type(self).__name__, data)
198
-            self.desk_light_tradfri.set_color_temp(data * 10)
199
-
200
-    def amplifier_switch_action(self, device, key, data):
201
-        if device == self.button_tradfri:
202
-            logger.info("Toggeling \"%s\" amplifier to %s", type(self).__name__,
203
-                        not self.powerplug_common.get(self.KEY_POWERPLUG_AMPLIFIER))
204
-            self.powerplug_common.set_output(self.KEY_POWERPLUG_AMPLIFIER, "toggle")
205
-        else:
206
-            logger.info("Setting \"%s\" amplifier: %s", type(self).__name__, data)
207
-            self.powerplug_common.set_output(self.KEY_POWERPLUG_AMPLIFIER, data)
208
-
209
-    def cd_player_switch_action(self, device, key, data):
210
-        if device == self.button_tradfri:
211
-            logger.info("Toggeling \"%s\" cd_player to %s", type(self).__name__,
212
-                        not self.powerplug_common.get(self.KEY_POWERPLUG_CD_PLAYER))
213
-            self.powerplug_common.set_output(self.KEY_POWERPLUG_CD_PLAYER, "toggle")
214
-        else:
215
-            logger.info("Setting \"%s\" cd_player: %s", type(self).__name__, data)
216
-            self.powerplug_common.set_output(self.KEY_POWERPLUG_CD_PLAYER, data)
217
-
218
-    def pc_dock_switch_action(self, device, key, data):
219
-        if device == self.button_tradfri:
220
-            logger.info("Toggeling \"%s\" pc_dock to %s", type(self).__name__,
221
-                        not self.powerplug_common.get(self.KEY_POWERPLUG_PC_DOCK))
222
-            self.powerplug_common.set_output(self.KEY_POWERPLUG_PC_DOCK, "toggle")
223
-        else:
224
-            logger.info("Setting \"%s\" pc_dock: %s", type(self).__name__, data)
225
-            self.powerplug_common.set_output(self.KEY_POWERPLUG_PC_DOCK, data)
226
-
227
     def device_chooser_action(self, device, key, data):
157
     def device_chooser_action(self, device, key, data):
228
         if device == self.main_light_shelly:
158
         if device == self.main_light_shelly:
229
             if self.cvi.changed_here(device.topic, key, data):
159
             if self.cvi.changed_here(device.topic, key, data):
230
                 if data is True:
160
                 if data is True:
231
                     self.active_device_state = self.STATE_ACTIVE_DEVICE_MAIN_LIGHT
161
                     self.active_device_state = self.STATE_ACTIVE_DEVICE_MAIN_LIGHT
162
+                    self.update_active_device_led()
232
                 else:
163
                 else:
233
                     self.choose_next_device()
164
                     self.choose_next_device()
234
         elif device == self.powerplug_common and key == self.KEY_POWERPLUG_DESK_LIGHT:
165
         elif device == self.powerplug_common and key == self.KEY_POWERPLUG_DESK_LIGHT:
235
             if self.cvi.changed_here(device.topic, key, data):
166
             if self.cvi.changed_here(device.topic, key, data):
236
                 if data is True:
167
                 if data is True:
237
                     self.active_device_state = self.STATE_ACTIVE_DEVICE_DESK_LIGHT
168
                     self.active_device_state = self.STATE_ACTIVE_DEVICE_DESK_LIGHT
169
+                    self.update_active_device_led()
238
                 else:
170
                 else:
239
                     self.choose_next_device()
171
                     self.choose_next_device()
240
         elif device == self.powerplug_common and key == self.KEY_POWERPLUG_AMPLIFIER:
172
         elif device == self.powerplug_common and key == self.KEY_POWERPLUG_AMPLIFIER:
241
             if self.cvi.changed_here(device.topic, key, data):
173
             if self.cvi.changed_here(device.topic, key, data):
242
                 if data is True:
174
                 if data is True:
243
                     self.active_device_state = self.STATE_ACTIVE_DEVICE_AMPLIFIER
175
                     self.active_device_state = self.STATE_ACTIVE_DEVICE_AMPLIFIER
176
+                    self.update_active_device_led()
244
                 else:
177
                 else:
245
                     self.choose_next_device()
178
                     self.choose_next_device()
246
 
179
 
252
         elif state == self.STATE_ACTIVE_DEVICE_AMPLIFIER:
185
         elif state == self.STATE_ACTIVE_DEVICE_AMPLIFIER:
253
             return self.powerplug_common.get(self.KEY_POWERPLUG_AMPLIFIER)
186
             return self.powerplug_common.get(self.KEY_POWERPLUG_AMPLIFIER)
254
 
187
 
188
+    def update_active_device_led(self):
189
+        self.gui_led_active_device.set_led(self.LED_ACTIVE_DEVICE_AMPLIFIER, self.active_device_state == self.STATE_ACTIVE_DEVICE_AMPLIFIER)
190
+        self.gui_led_active_device.set_led(self.LED_ACTIVE_DEVICE_MAIN_LIGHT, self.active_device_state == self.STATE_ACTIVE_DEVICE_MAIN_LIGHT)
191
+        self.gui_led_active_device.set_led(self.LED_ACTIVE_DEVICE_DESK_LIGHT, self.active_device_state == self.STATE_ACTIVE_DEVICE_DESK_LIGHT)
192
+
255
     def choose_prev_device(self, device=None, key=None, data=None):
193
     def choose_prev_device(self, device=None, key=None, data=None):
256
         if self.active_device_state is not None:
194
         if self.active_device_state is not None:
257
             start_value = self.active_device_state
195
             start_value = self.active_device_state
259
                 target_state = (start_value + i + 1) % (self.STATE_ACTIVE_DEVICE_MAX_VALUE + 1)
197
                 target_state = (start_value + i + 1) % (self.STATE_ACTIVE_DEVICE_MAX_VALUE + 1)
260
                 if self.get_activity_state(target_state):
198
                 if self.get_activity_state(target_state):
261
                     self.active_device_state = target_state
199
                     self.active_device_state = target_state
262
-                    for num in range(0, self.STATE_ACTIVE_DEVICE_MAX_VALUE + 1):
263
-                        self.active_device_state_led.set_state(num, self.active_device_state == num)
200
+                    self.update_active_device_led()
264
                     return
201
                     return
265
         self.active_device_state = None
202
         self.active_device_state = None
203
+        self.update_active_device_led()
266
 
204
 
267
     def choose_next_device(self, device=None, key=None, data=None):
205
     def choose_next_device(self, device=None, key=None, data=None):
268
         if self.active_device_state is not None:
206
         if self.active_device_state is not None:
271
                 target_state = (start_value - i - 1) % (self.STATE_ACTIVE_DEVICE_MAX_VALUE + 1)
209
                 target_state = (start_value - i - 1) % (self.STATE_ACTIVE_DEVICE_MAX_VALUE + 1)
272
                 if self.get_activity_state(target_state):
210
                 if self.get_activity_state(target_state):
273
                     self.active_device_state = target_state
211
                     self.active_device_state = target_state
274
-                    for num in range(0, self.STATE_ACTIVE_DEVICE_MAX_VALUE + 1):
275
-                        self.active_device_state_led.set_state(num, self.active_device_state == num)
212
+                    self.update_active_device_led()
276
                     return
213
                     return
277
         self.active_device_state = None
214
         self.active_device_state = None
215
+        self.update_active_device_led()
278
 
216
 
279
     def brightness_action(self, device, key, data):
217
     def brightness_action(self, device, key, data):
280
         if self.active_device_state is not None:
218
         if self.active_device_state is not None:

+ 5
- 6
function/modules.py View File

28
         self.heating_valve.add_callback(
28
         self.heating_valve.add_callback(
29
             devices.brennenstuhl_heatingvalve.KEY_HEATING_SETPOINT, None, self.heating_setpoint_actions)
29
             devices.brennenstuhl_heatingvalve.KEY_HEATING_SETPOINT, None, self.heating_setpoint_actions)
30
 
30
 
31
-        self.gui_value_temp_setp = devices.nodered_gui(mqtt_client, topic_setpoint)
31
+        self.gui_value_temp_setp = devices.nodered_gui_heatvalve(mqtt_client, topic_setpoint)
32
         self.gui_value_temp_setp.add_callback(
32
         self.gui_value_temp_setp.add_callback(
33
-            devices.nodered_gui.KEY_HEATING_SETPOINT, None, self.heating_setpoint_actions)
33
+            devices.nodered_gui_heatvalve.KEY_HEATING_SETPOINT, None, self.heating_setpoint_actions)
34
 
34
 
35
-        self.gui_button_boost = devices.nodered_gui(mqtt_client, topic_boost)
35
+        self.gui_button_boost = devices.nodered_gui_heatvalve(mqtt_client, topic_boost)
36
         self.gui_button_boost.add_callback(None, None, self.boost_actions)
36
         self.gui_button_boost.add_callback(None, None, self.boost_actions)
37
 
37
 
38
-        self.gui_led_boost = devices.nodered_gui(mqtt_client, topic_led)
38
+        self.gui_led_boost = devices.nodered_gui_heatvalve(mqtt_client, topic_led)
39
 
39
 
40
         #
40
         #
41
         self.return_to_default_timer = None
41
         self.return_to_default_timer = None
71
             self.gui_led_boost.set_feedback(False)
71
             self.gui_led_boost.set_feedback(False)
72
 
72
 
73
     def boost_actions(self, davice, key, data):
73
     def boost_actions(self, davice, key, data):
74
-        logger.info('Starting boost mode \"%s\" with setpoint %.1f°C.',
75
-                    self.topic, self.default_temperature + self.BOOST_TEMP_OFFSET)
74
+        logger.info('Starting boost mode \"%s\" with setpoint %.1f°C.', self.topic, self.default_temperature + self.BOOST_TEMP_OFFSET)
76
         self.heating_valve.set_heating_setpoint(self.default_temperature + self.BOOST_TEMP_OFFSET)
75
         self.heating_valve.set_heating_setpoint(self.default_temperature + self.BOOST_TEMP_OFFSET)
77
 
76
 
78
     def cyclic_task(self, rt):
77
     def cyclic_task(self, rt):

+ 17
- 70
function/rooms.py View File

17
     def __init__(self, mqtt_client):
17
     def __init__(self, mqtt_client):
18
         self.mqtt_client = mqtt_client
18
         self.mqtt_client = mqtt_client
19
 
19
 
20
-    def gui_switch_feedback(self, device, key, data):
21
-        self.gui_switch_main_light.set_feedback(data)
22
-
23
 
20
 
24
 class room_shelly(room):
21
 class room_shelly(room):
25
     def __init__(self, mqtt_client, topic_shelly, topic_gui_switch):
22
     def __init__(self, mqtt_client, topic_shelly, topic_gui_switch):
26
         super().__init__(mqtt_client)
23
         super().__init__(mqtt_client)
27
         self.main_light_shelly = devices.shelly(mqtt_client, topic=topic_shelly)
24
         self.main_light_shelly = devices.shelly(mqtt_client, topic=topic_shelly)
28
         #
25
         #
29
-        self.gui_switch_main_light = devices.nodered_gui(mqtt_client, topic=topic_gui_switch)
26
+        self.gui_switch_main_light = devices.nodered_gui_switch(mqtt_client, topic=topic_gui_switch)
30
         #
27
         #
31
         # Callback initialisation
28
         # Callback initialisation
32
         #
29
         #
33
-        self.gui_switch_main_light.add_callback(devices.nodered_gui.KEY_STATE, None, self.gui_switch_command)
34
-        self.main_light_shelly.add_callback(devices.shelly.KEY_OUTPUT_0, None, self.gui_switch_feedback)
30
+        self.gui_switch_main_light.add_callback(devices.nodered_gui_switch.KEY_STATE, None, self.main_light_shelly.set_output_0_mcb)
31
+        self.main_light_shelly.add_callback(devices.shelly.KEY_OUTPUT_0, None, self.gui_switch_main_light.set_state_mcb)
35
         #
32
         #
36
         self.block_all_off = False
33
         self.block_all_off = False
37
         self.last_flash_data = None
34
         self.last_flash_data = None
38
-        self.delayed_task = task.delayed(.25, self.toggle_main_light, None, None, None)
35
+        self.delayed_task = task.delayed(.25, self.main_light_shelly.toggle_output_0_mcb, None, None, None)
39
 
36
 
40
     def all_off(self, device=None, key=None, data=None):
37
     def all_off(self, device=None, key=None, data=None):
41
         if not self.block_all_off:
38
         if not self.block_all_off:
51
             self.block_all_off = True
48
             self.block_all_off = True
52
             self.delayed_task.run()
49
             self.delayed_task.run()
53
 
50
 
54
-    def gui_switch_command(self, device, key, data):
55
-        logger.info("Switching \"%s\" main light: %s", type(self).__name__, str(data))
56
-        self.main_light_shelly.set_output_0(data)
57
-
58
-    def toggle_main_light(self, device, key, data):
59
-        logger.info("Toggeling \"%s\" main light", type(self).__name__)
60
-        self.main_light_shelly.set_output_0("toggle")
61
-
62
     def flash_main_light(self, device, key, data):
51
     def flash_main_light(self, device, key, data):
63
         if self.last_flash_data != data and data is True:
52
         if self.last_flash_data != data and data is True:
64
             logger.info("Flashing \"%s\" main light", type(self).__name__)
53
             logger.info("Flashing \"%s\" main light", type(self).__name__)
65
-            self.toggle_main_light(device, key, data)
54
+            self.main_light_shelly.toggle_output_0_mcb(device, key, data)
66
             self.delayed_task.run()
55
             self.delayed_task.run()
67
         self.last_flash_data = data
56
         self.last_flash_data = data
68
 
57
 
69
 
58
 
70
 class room_shelly_tradfri_light(room_shelly):
59
 class room_shelly_tradfri_light(room_shelly):
71
-    def __init__(self, mqtt_client, topic_shelly, topic_gui_switch, topic_tradfri_light, topic_gui_brightness, topic_gui_color_temp):
60
+    def __init__(self, mqtt_client, topic_shelly, topic_gui_switch, topic_tradfri_light, topic_gui_br_ct):
72
         super().__init__(mqtt_client, topic_shelly, topic_gui_switch)
61
         super().__init__(mqtt_client, topic_shelly, topic_gui_switch)
73
         self.main_light_tradfri = devices.tradfri_light(mqtt_client, topic=topic_tradfri_light)
62
         self.main_light_tradfri = devices.tradfri_light(mqtt_client, topic=topic_tradfri_light)
74
         #
63
         #
75
-        self.gui_brightness_main_light = devices.nodered_gui(mqtt_client, topic=topic_gui_brightness)
76
-        self.gui_brightness_main_light.enable(False)
77
-        self.gui_brightness_main_light.set_feedback(0)
78
-        self.gui_color_temp_main_light = devices.nodered_gui(mqtt_client, topic=topic_gui_color_temp)
79
-        self.gui_color_temp_main_light.enable(False)
80
-        self.gui_color_temp_main_light.set_feedback(0)
64
+        self.gui_br_ct_main_light = devices.nodered_gui_brightness_color_temp(mqtt_client, topic_gui_br_ct)
81
         #
65
         #
82
         # Callback initialisation
66
         # Callback initialisation
83
         #
67
         #
84
-        self.main_light_shelly.add_callback(devices.shelly.KEY_OUTPUT_0, None, self.enable_brightness_n_colortemp)
85
-        self.main_light_tradfri.add_callback(
86
-            devices.tradfri_light.KEY_BRIGHTNESS, None, self.set_gui_brightness_main_light)
87
-        self.main_light_tradfri.add_callback(
88
-            devices.tradfri_light.KEY_COLOR_TEMP, None, self.set_gui_color_temp_main_light)
89
-        self.gui_brightness_main_light.add_callback(
90
-            devices.nodered_gui.KEY_BRIGHTNESS, None, self.set_brightness_main_light)
91
-        self.gui_color_temp_main_light.add_callback(
92
-            devices.nodered_gui.KEY_COLOR_TEMP, None, self.set_color_temp_main_light)
93
-
94
-    def enable_brightness_n_colortemp(self, devive, key, data):
95
-        self.gui_brightness_main_light.enable(data)
96
-        self.gui_color_temp_main_light.enable(data)
97
-        if data is False:
98
-            self.gui_brightness_main_light.set_feedback(0)
99
-            self.gui_color_temp_main_light.set_feedback(0)
100
-        else:
101
-            self.gui_brightness_main_light.set_feedback(self.main_light_tradfri.brightness)
102
-            self.gui_color_temp_main_light.set_feedback(self.main_light_tradfri.color_temp / 10)
103
-
104
-    def set_gui_brightness_main_light(self, device, key, data):
105
-        self.gui_brightness_main_light.set_feedback(data)
106
-
107
-    def set_gui_color_temp_main_light(self, device, key, data):
108
-        self.gui_color_temp_main_light.set_feedback(data / 10)
109
-
110
-    def set_brightness_main_light(self, device, key, data):
111
-        logger.info("Setting brightness \"%s\" main light: %.1f", type(self).__name__, data)
112
-        self.main_light_tradfri.set_brightness(data)
113
-
114
-    def set_color_temp_main_light(self, device, key, data):
115
-        logger.info("Setting color_temp \"%s\" main light: %.1f", type(self).__name__, data)
116
-        self.main_light_tradfri.set_color_temp(data * 10)
117
-
118
-    def fade_light(self, device, topic, data):
119
-        if (data == 'brightness_up_hold'):
120
-            logger.info("Increasing brightness \"%s\" main light", type(self).__name__)
121
-            self.main_light_tradfri.brightness_inc()
122
-        elif (data == 'brightness_down_hold'):
123
-            logger.info("Decreasing brightness \"%s\" main light", type(self).__name__)
124
-            self.main_light_tradfri.brightness_dec()
125
-        elif (data.startswith('brightness') and data.endswith('release')):
126
-            logger.info("Stoping brightness change \"%s\" main light", type(self).__name__)
127
-            self.main_light_tradfri.brightness_stop()
68
+        self.main_light_shelly.add_callback(devices.shelly.KEY_OUTPUT_0, None, self.gui_br_ct_main_light.set_enable_mcb)
69
+        self.main_light_tradfri.add_callback(devices.tradfri_light.KEY_BRIGHTNESS, None, self.gui_br_ct_main_light.set_brightness_mcb)
70
+        self.main_light_tradfri.add_callback(devices.tradfri_light.KEY_COLOR_TEMP, None, self.gui_br_ct_main_light.set_color_temp_mcb)
71
+        self.gui_br_ct_main_light.add_callback(devices.nodered_gui_brightness_color_temp.KEY_BRIGHTNESS,
72
+                                               None, self.main_light_tradfri.set_brightness_mcb)
73
+        self.gui_br_ct_main_light.add_callback(devices.nodered_gui_brightness_color_temp.KEY_COLOR_TEMP,
74
+                                               None, self.main_light_tradfri.set_color_temp_mcb)
128
 
75
 
129
 
76
 
130
 class room_shelly_silvercrest_light(room_shelly_tradfri_light):
77
 class room_shelly_silvercrest_light(room_shelly_tradfri_light):
131
-    def __init__(self, mqtt_client, topic_shelly, topic_gui_switch, topic_tradfri_light, topic_gui_brightness, topic_gui_color_temp):
132
-        super().__init__(mqtt_client, topic_shelly, topic_gui_switch, topic_tradfri_light, topic_gui_brightness, topic_gui_color_temp)
78
+    def __init__(self, mqtt_client, topic_shelly, topic_gui_switch, topic_tradfri_light, topic_gui_br_ct):
79
+        super().__init__(mqtt_client, topic_shelly, topic_gui_switch, topic_tradfri_light, topic_gui_br_ct)
133
         #
80
         #
134
         # Callback initialisation
81
         # Callback initialisation
135
         #
82
         #
138
         self.main_light_shelly_last = None
85
         self.main_light_shelly_last = None
139
 
86
 
140
     def get_initial_main_light_data(self, device, key, data):
87
     def get_initial_main_light_data(self, device, key, data):
141
-        if data is True and self.main_light_shelly_last is not True:
88
+        if data is True and self.main_light_shelly_last != data:
142
             self.send_init_message_main_light()
89
             self.send_init_message_main_light()
143
         self.main_light_shelly_last = data
90
         self.main_light_shelly_last = data
144
 
91
 

+ 4
- 6
smart_brain.py View File

10
 
10
 
11
 if __name__ == "__main__":
11
 if __name__ == "__main__":
12
     if config.DEBUG:
12
     if config.DEBUG:
13
-        report.appLoggingConfigure(None, None, ((config.APP_NAME, logging.DEBUG), ),
14
-                                   fmt=report.SHORT_FMT, host='localhost', port=19996)
13
+        report.appLoggingConfigure(None, None, ((config.APP_NAME, logging.DEBUG), ), fmt=report.SHORT_FMT, host='localhost', port=19996)
15
     else:
14
     else:
16
-        report.stdoutLoggingConfigure(((config.APP_NAME, logging.INFO),
17
-                                      (config.APP_NAME+'.devices', logging.WARNING)), report.SHORT_FMT)
15
+        report.stdoutLoggingConfigure(((config.APP_NAME, logging.INFO), (config.APP_NAME+'.devices', logging.WARNING)), report.SHORT_FMT)
18
     #
16
     #
19
-    mc = mqtt.mqtt_client(host=config.MQTT_SERVER, port=config.MQTT_PORT,
20
-                          username=config.MQTT_USER, password=config.MQTT_PASSWORD, name=config.APP_NAME)
17
+    mc = mqtt.mqtt_client(host=config.MQTT_SERVER, port=config.MQTT_PORT, username=config.MQTT_USER,
18
+                          password=config.MQTT_PASSWORD, name=config.APP_NAME)
21
 
19
 
22
     func = function.all_functions(mc)
20
     func = function.all_functions(mc)
23
 
21
 

Loading…
Cancel
Save