Browse Source

User interface for warning and triggering device warning states

tags/v1.2.0
Dirk Alders 1 year ago
parent
commit
60b18fac64
4 changed files with 96 additions and 7 deletions
  1. 92
    5
      simulation/devices.py
  2. 2
    1
      simulation/rooms.py
  3. 1
    0
      smart_brain_test.py
  4. 1
    1
      tests/all.py

+ 92
- 5
simulation/devices.py View File

11
 COLOR_POWERPLUG = colored.fg("light_cyan")
11
 COLOR_POWERPLUG = colored.fg("light_cyan")
12
 COLOR_LIGHT_ACTIVE = colored.fg("yellow")
12
 COLOR_LIGHT_ACTIVE = colored.fg("yellow")
13
 COLOR_LIGHT_PASSIVE = COLOR_LIGHT_ACTIVE + colored.attr("dim")
13
 COLOR_LIGHT_PASSIVE = COLOR_LIGHT_ACTIVE + colored.attr("dim")
14
-COLOR_MOTION_SENSOR = colored.fg("dark_orange_3b")
14
+COLOR_WARNINGS = colored.fg("dark_orange_3b")
15
 COLOR_HEATING_VALVE = colored.fg("red")
15
 COLOR_HEATING_VALVE = colored.fg("red")
16
 COLOR_REMOTE = colored.fg("green")
16
 COLOR_REMOTE = colored.fg("green")
17
 
17
 
125
     KEY_INPUT_1 = "input/1"
125
     KEY_INPUT_1 = "input/1"
126
     KEY_LONGPUSH_0 = "longpush/0"
126
     KEY_LONGPUSH_0 = "longpush/0"
127
     KEY_LONGPUSH_1 = "longpush/1"
127
     KEY_LONGPUSH_1 = "longpush/1"
128
+    KEY_TEMPERATURE = "temperature"
129
+    KEY_OVERTEMPERATURE = "overtemperature"
128
     #
130
     #
129
-    BOOL_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_INPUT_0, KEY_INPUT_1, KEY_LONGPUSH_0, KEY_LONGPUSH_1, ]
131
+    BOOL_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_INPUT_0, KEY_INPUT_1, KEY_LONGPUSH_0, KEY_LONGPUSH_1, KEY_OVERTEMPERATURE, ]
130
     #
132
     #
131
     INPUT_FUNC_OUT1_FOLLOW = "out1_follow"
133
     INPUT_FUNC_OUT1_FOLLOW = "out1_follow"
132
     INPUT_FUNC_OUT1_TRIGGER = "out1_trigger"
134
     INPUT_FUNC_OUT1_TRIGGER = "out1_trigger"
139
         "get_input_0", "toggle_input_0",
141
         "get_input_0", "toggle_input_0",
140
         "get_input_1", "toggle_input_1",
142
         "get_input_1", "toggle_input_1",
141
         "trigger_input_0_longpress", "trigger_input_1_longpress",
143
         "trigger_input_0_longpress", "trigger_input_1_longpress",
144
+        "toggle_overtemperature",
142
     ]
145
     ]
143
 
146
 
144
     def __init__(self, mqtt_client, topic, input_0_func=None, input_1_func=None, output_0_auto_off=None):
147
     def __init__(self, mqtt_client, topic, input_0_func=None, input_1_func=None, output_0_auto_off=None):
145
         super().__init__(mqtt_client, topic, default_values={self.KEY_OUTPUT_0: False, self.KEY_OUTPUT_1: False,
148
         super().__init__(mqtt_client, topic, default_values={self.KEY_OUTPUT_0: False, self.KEY_OUTPUT_1: False,
146
-                                                             self.KEY_INPUT_0: False, self.KEY_INPUT_1: False})
149
+                                                             self.KEY_INPUT_0: False, self.KEY_INPUT_1: False,
150
+                                                             self.KEY_TEMPERATURE: 35.2, self.KEY_OVERTEMPERATURE: False})
147
         #
151
         #
148
         self.__input_0_func = input_0_func
152
         self.__input_0_func = input_0_func
149
         self.__input_1_func = input_1_func
153
         self.__input_1_func = input_1_func
154
         # publish state changes
158
         # publish state changes
155
         self.add_callback(self.KEY_OUTPUT_0, None, self.__send__, True)
159
         self.add_callback(self.KEY_OUTPUT_0, None, self.__send__, True)
156
         self.add_callback(self.KEY_OUTPUT_1, None, self.__send__, True)
160
         self.add_callback(self.KEY_OUTPUT_1, None, self.__send__, True)
161
+        self.add_callback(self.KEY_TEMPERATURE, None, self.__send__, True)
162
+        self.add_callback(self.KEY_OVERTEMPERATURE, None, self.__send__, True)
157
         #
163
         #
158
         if self.__output_0_auto_off__ is not None:
164
         if self.__output_0_auto_off__ is not None:
159
             self.__delayed_off__ = task.delayed(float(self.__output_0_auto_off__), self.__auto_off__, self.KEY_OUTPUT_0)
165
             self.__delayed_off__ = task.delayed(float(self.__output_0_auto_off__), self.__auto_off__, self.KEY_OUTPUT_0)
164
         #
170
         #
165
         self.__tx__((self.KEY_OUTPUT_0, self.KEY_OUTPUT_1))
171
         self.__tx__((self.KEY_OUTPUT_0, self.KEY_OUTPUT_1))
166
 
172
 
173
+    def __int_to_ext__(self, key, value):
174
+        if key == self.KEY_OVERTEMPERATURE:
175
+            return int(value)
176
+        return super().__int_to_ext__(key, value)
177
+
167
     def __rx__(self, client, userdata, message):
178
     def __rx__(self, client, userdata, message):
168
         value = self.__payload_filter__(message.payload)
179
         value = self.__payload_filter__(message.payload)
169
         if message.topic.startswith(self.topic) and message.topic.endswith("/command"):
180
         if message.topic.startswith(self.topic) and message.topic.endswith("/command"):
235
                 time.sleep(0.1)
246
                 time.sleep(0.1)
236
                 self.set(self.KEY_INPUT_1, not self[self.KEY_INPUT_1])
247
                 self.set(self.KEY_INPUT_1, not self[self.KEY_INPUT_1])
237
                 self.set(self.KEY_LONGPUSH_1, False)
248
                 self.set(self.KEY_LONGPUSH_1, False)
249
+            elif command == self.COMMANDS[10]:
250
+                if self.get(self.KEY_OVERTEMPERATURE):
251
+                    self.warning_state_off()
252
+                else:
253
+                    self.warning_state_on()
238
             else:
254
             else:
239
                 print("%s: not yet implemented!" % command)
255
                 print("%s: not yet implemented!" % command)
240
         else:
256
         else:
246
             channel = "(%s%s)" % (self.names.get(key, key), info)
262
             channel = "(%s%s)" % (self.names.get(key, key), info)
247
             self.print_formatted_light(COLOR_SHELLY, value, channel)
263
             self.print_formatted_light(COLOR_SHELLY, value, channel)
248
 
264
 
265
+    def warning_state_on(self):
266
+        self.set(self.KEY_TEMPERATURE, 78.3)
267
+        self.set(self.KEY_OVERTEMPERATURE, True)
268
+
269
+    def warning_state_off(self):
270
+        self.set(self.KEY_TEMPERATURE, 34.1)
271
+        self.set(self.KEY_OVERTEMPERATURE, False)
272
+
249
 
273
 
250
 class my_powerplug(base):
274
 class my_powerplug(base):
251
     KEY_OUTPUT_0 = "state"
275
     KEY_OUTPUT_0 = "state"
312
             self.set(self.KEY_OUTPUT_0, self.__ext_to_int__(self.KEY_OUTPUT_0, state))
336
             self.set(self.KEY_OUTPUT_0, self.__ext_to_int__(self.KEY_OUTPUT_0, state))
313
 
337
 
314
     def __tx__(self, keys_changed):
338
     def __tx__(self, keys_changed):
339
+        data = {}
340
+        for key in self:
341
+            data[key] = self.__int_to_ext__(key, self[key])
315
         for key in keys_changed:
342
         for key in keys_changed:
316
-            self.mqtt_client.send(self.topic + '/' + key, self.__int_to_ext__(self.KEY_OUTPUT_0, self.get(self.KEY_OUTPUT_0)))
343
+            self.mqtt_client.send(self.topic, json.dumps(data))
317
 
344
 
318
     def command(self, command):
345
     def command(self, command):
319
         if command in self.COMMANDS:
346
         if command in self.COMMANDS:
454
     #
481
     #
455
     KEY_TEMPERATURE_SETPOINT = "current_heating_setpoint"
482
     KEY_TEMPERATURE_SETPOINT = "current_heating_setpoint"
456
     KEY_TEMPERATURE = "local_temperature"
483
     KEY_TEMPERATURE = "local_temperature"
484
+    KEY_BATTERY = "battery"
457
     #
485
     #
458
     COMMANDS = [
486
     COMMANDS = [
459
-        "get_temperature_setpoint", "set_temperature_setpoint", "set_local_temperature",
487
+        "get_temperature_setpoint", "set_temperature_setpoint", "set_local_temperature", "set_battery",
460
     ]
488
     ]
461
 
489
 
462
     def __init__(self, mqtt_client, topic):
490
     def __init__(self, mqtt_client, topic):
463
         super().__init__(mqtt_client, topic, default_values={
491
         super().__init__(mqtt_client, topic, default_values={
464
             self.KEY_TEMPERATURE_SETPOINT: 20,
492
             self.KEY_TEMPERATURE_SETPOINT: 20,
465
             self.KEY_TEMPERATURE: 20.7,
493
             self.KEY_TEMPERATURE: 20.7,
494
+            self.KEY_BATTERY: 97,
466
         })
495
         })
467
         #
496
         #
468
         self.add_callback(self.KEY_TEMPERATURE_SETPOINT, None, self.print_formatted, True)
497
         self.add_callback(self.KEY_TEMPERATURE_SETPOINT, None, self.print_formatted, True)
469
         self.add_callback(self.KEY_TEMPERATURE_SETPOINT, None, self.__send__, True)
498
         self.add_callback(self.KEY_TEMPERATURE_SETPOINT, None, self.__send__, True)
470
         self.add_callback(self.KEY_TEMPERATURE, None, self.__send__, True)
499
         self.add_callback(self.KEY_TEMPERATURE, None, self.__send__, True)
500
+        self.add_callback(self.KEY_BATTERY, None, self.__send__, True)
471
         #
501
         #
472
         self.__tx__((self.KEY_TEMPERATURE_SETPOINT, ))
502
         self.__tx__((self.KEY_TEMPERATURE_SETPOINT, ))
473
 
503
 
495
                 self.set(self.KEY_TEMPERATURE_SETPOINT, self.__command_float_value__(value))
525
                 self.set(self.KEY_TEMPERATURE_SETPOINT, self.__command_float_value__(value))
496
             elif command == self.COMMANDS[2]:
526
             elif command == self.COMMANDS[2]:
497
                 self.set(self.KEY_TEMPERATURE, self.__command_float_value__(value))
527
                 self.set(self.KEY_TEMPERATURE, self.__command_float_value__(value))
528
+            elif command == self.COMMANDS[3]:
529
+                self.set(self.KEY_BATTERY, self.__command_float_value__(value))
498
 
530
 
499
     def print_formatted(self, device, key, value):
531
     def print_formatted(self, device, key, value):
500
         if key == self.KEY_TEMPERATURE_SETPOINT:
532
         if key == self.KEY_TEMPERATURE_SETPOINT:
503
             perc = 0 if perc < 0 else perc
535
             perc = 0 if perc < 0 else perc
504
             self.print_formatted_percent(COLOR_HEATING_VALVE, '\u03d1', perc, "%4.1f°C" % value, "")
536
             self.print_formatted_percent(COLOR_HEATING_VALVE, '\u03d1', perc, "%4.1f°C" % value, "")
505
 
537
 
538
+    def warning_state_on(self):
539
+        self.set(self.KEY_BATTERY, 7)
540
+
541
+    def warning_state_off(self):
542
+        self.set(self.KEY_BATTERY, 97)
543
+
506
 
544
 
507
 class videv_light(base_videv):
545
 class videv_light(base_videv):
508
     KEY_OUTPUT_0 = "state"
546
     KEY_OUTPUT_0 = "state"
733
                 self.print_formatted_percent(COLOR_GUI_ACTIVE, 't', perc, '%3d%%' % perc, '(%.1f)' % disp_value)
771
                 self.print_formatted_percent(COLOR_GUI_ACTIVE, 't', perc, '%3d%%' % perc, '(%.1f)' % disp_value)
734
 
772
 
735
 
773
 
774
+class videv_warnings(base):
775
+    KEY_WARNING = "html_short"
776
+    #
777
+    COMMANDS = [
778
+        "get_warnings",
779
+    ]
780
+
781
+    def __init__(self, mqtt_client, topic):
782
+        super().__init__(mqtt_client, topic, dict.fromkeys([self.KEY_WARNING]))
783
+        #
784
+        self.add_callback(self.KEY_WARNING, None, self.print_formatted, True)
785
+
786
+    def __rx__(self, client, userdata, message):
787
+        if message.topic == self.topic + "/" + self.KEY_WARNING:
788
+            self.set(self.KEY_WARNING, message.payload.decode("utf-8"))
789
+
790
+    def command(self, command):
791
+        if command in self.COMMANDS:
792
+            if command == self.COMMANDS[0]:
793
+                self.print_formatted(self, self.KEY_WARNING, self.get(self.KEY_WARNING))
794
+            else:
795
+                print("%s: not yet implemented!" % command)
796
+        else:
797
+            print("Unknown command!")
798
+
799
+    def print_formatted(self, device, key, value):
800
+        if OUTPUT_ACTIVE:
801
+            value = value.replace("<br><br>", "\n")
802
+            value = value.replace("<br>", " - ")
803
+            print(COLOR_WARNINGS + "** WARNINGS: *************************************************")
804
+            for line in value.split("\n"):
805
+                print("   ", line)
806
+            print("**************************************************************" + colored.attr("reset"))
807
+
736
 # class silvercrest_motion_sensor(base):
808
 # class silvercrest_motion_sensor(base):
737
 #     KEY_OCCUPANCY = "occupancy"
809
 #     KEY_OCCUPANCY = "occupancy"
810
+#     KEY_BATTERY = "battery"
811
+#     KEY_BATTERY_LOW = "battery_low"
738
 #     COMMANDS = ['motion']
812
 #     COMMANDS = ['motion']
739
 
813
 
740
 #     def __init__(self, mqtt_client, topic):
814
 #     def __init__(self, mqtt_client, topic):
761
 #         if value is not None:
835
 #         if value is not None:
762
 #             print_light(COLOR_MOTION_SENSOR, value, self.topic, "")
836
 #             print_light(COLOR_MOTION_SENSOR, value, self.topic, "")
763
 
837
 
838
+#    def warning_state_on(self):
839
+#        self.set(self.KEY_BATTERY, 7)
840
+#        self.set(self.KEY_BATTERY_LOW, True)
841
+#    def warning_state_off(self):
842
+#        self.set(self.KEY_BATTERY, 97)
843
+#        self.set(self.KEY_BATTERY_LOW, False)
844
+
764
 
845
 
765
 # class tradfri_button(base):
846
 # class tradfri_button(base):
766
 #     KEY_ACTION = "action"
847
 #     KEY_ACTION = "action"
848
+#     KEY_BATTERY = "battery"
767
 #     #
849
 #     #
768
 #     ACTION_TOGGLE = "toggle"
850
 #     ACTION_TOGGLE = "toggle"
769
 #     ACTION_BRIGHTNESS_UP = "brightness_up_click"
851
 #     ACTION_BRIGHTNESS_UP = "brightness_up_click"
800
 #                 time.sleep(value or 0.5)
882
 #                 time.sleep(value or 0.5)
801
 #                 action = '_'.join(action.split('_')[:-1] + ['release'])
883
 #                 action = '_'.join(action.split('_')[:-1] + ['release'])
802
 #                 self.mqtt_client.send(self.topic, json.dumps({self.KEY_ACTION: action}))
884
 #                 self.mqtt_client.send(self.topic, json.dumps({self.KEY_ACTION: action}))
885
+#
886
+#    def warning_state_on(self):
887
+#        self.set(self.KEY_BATTERY, 7)
888
+#    def warning_state_off(self):
889
+#        self.set(self.KEY_BATTERY, 97)
803
 
890
 
804
 
891
 
805
 # class remote(base):
892
 # class remote(base):

+ 2
- 1
simulation/rooms.py View File

1
 import config
1
 import config
2
 from simulation.devices import shelly, silvercrest_powerplug, tradfri_light, my_powerplug, brennenstuhl_heating_valve
2
 from simulation.devices import shelly, silvercrest_powerplug, tradfri_light, my_powerplug, brennenstuhl_heating_valve
3
-from simulation.devices import videv_light, videv_heating
3
+from simulation.devices import videv_light, videv_heating, videv_warnings
4
 import inspect
4
 import inspect
5
 
5
 
6
 
6
 
266
         self.ffw = ffw(mqtt_client)
266
         self.ffw = ffw(mqtt_client)
267
         self.ffe = ffe(mqtt_client)
267
         self.ffe = ffe(mqtt_client)
268
         self.stairway = stairway(mqtt_client)
268
         self.stairway = stairway(mqtt_client)
269
+        self.warnings = videv_warnings(mqtt_client, config.TOPIC_WARNINGS)

+ 1
- 0
smart_brain_test.py View File

6
 from tests.all import test_smarthome
6
 from tests.all import test_smarthome
7
 
7
 
8
 # TODO: Extend tests in simulation
8
 # TODO: Extend tests in simulation
9
+#         - Test: Check of warning messages for battery and overtemperature
9
 #         - Switching button functions (gfw_dirk, ffe.sleep)
10
 #         - Switching button functions (gfw_dirk, ffe.sleep)
10
 #         - Brightness button functions (gfw.dirk, ffe.sleep)
11
 #         - Brightness button functions (gfw.dirk, ffe.sleep)
11
 #         - Synch functions of amplifier with spotify, mpd
12
 #         - Synch functions of amplifier with spotify, mpd

+ 1
- 1
tests/all.py View File

83
         system_info[jsonlog.SYSI_USERNAME] = getpass.getuser()
83
         system_info[jsonlog.SYSI_USERNAME] = getpass.getuser()
84
         system_info[jsonlog.SYSI_PATH] = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
84
         system_info[jsonlog.SYSI_PATH] = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
85
 
85
 
86
-        self.tcl = report.testSession(['__unittest__', 'unittest', ROOT_LOGGER_NAME])
86
+        self.tcl = report.testSession(['__unittest__', ROOT_LOGGER_NAME])
87
         self.tcl[jsonlog.MAIN_KEY_SYSTEM_INFO] = system_info
87
         self.tcl[jsonlog.MAIN_KEY_SYSTEM_INFO] = system_info
88
         self.tcl["testcase_names"] = report.TCEL_NAMES
88
         self.tcl["testcase_names"] = report.TCEL_NAMES
89
 
89
 

Loading…
Cancel
Save