瀏覽代碼

User interface for warning and triggering device warning states

tags/v1.2.0
Dirk Alders 1 年之前
父節點
當前提交
60b18fac64
共有 4 個檔案被更改,包括 96 行新增7 行删除
  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 查看文件

@@ -11,7 +11,7 @@ COLOR_SHELLY = colored.fg("light_magenta")
11 11
 COLOR_POWERPLUG = colored.fg("light_cyan")
12 12
 COLOR_LIGHT_ACTIVE = colored.fg("yellow")
13 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 15
 COLOR_HEATING_VALVE = colored.fg("red")
16 16
 COLOR_REMOTE = colored.fg("green")
17 17
 
@@ -125,8 +125,10 @@ class shelly(base):
125 125
     KEY_INPUT_1 = "input/1"
126 126
     KEY_LONGPUSH_0 = "longpush/0"
127 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 133
     INPUT_FUNC_OUT1_FOLLOW = "out1_follow"
132 134
     INPUT_FUNC_OUT1_TRIGGER = "out1_trigger"
@@ -139,11 +141,13 @@ class shelly(base):
139 141
         "get_input_0", "toggle_input_0",
140 142
         "get_input_1", "toggle_input_1",
141 143
         "trigger_input_0_longpress", "trigger_input_1_longpress",
144
+        "toggle_overtemperature",
142 145
     ]
143 146
 
144 147
     def __init__(self, mqtt_client, topic, input_0_func=None, input_1_func=None, output_0_auto_off=None):
145 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 152
         self.__input_0_func = input_0_func
149 153
         self.__input_1_func = input_1_func
@@ -154,6 +158,8 @@ class shelly(base):
154 158
         # publish state changes
155 159
         self.add_callback(self.KEY_OUTPUT_0, None, self.__send__, True)
156 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 164
         if self.__output_0_auto_off__ is not None:
159 165
             self.__delayed_off__ = task.delayed(float(self.__output_0_auto_off__), self.__auto_off__, self.KEY_OUTPUT_0)
@@ -164,6 +170,11 @@ class shelly(base):
164 170
         #
165 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 178
     def __rx__(self, client, userdata, message):
168 179
         value = self.__payload_filter__(message.payload)
169 180
         if message.topic.startswith(self.topic) and message.topic.endswith("/command"):
@@ -235,6 +246,11 @@ class shelly(base):
235 246
                 time.sleep(0.1)
236 247
                 self.set(self.KEY_INPUT_1, not self[self.KEY_INPUT_1])
237 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 254
             else:
239 255
                 print("%s: not yet implemented!" % command)
240 256
         else:
@@ -246,6 +262,14 @@ class shelly(base):
246 262
             channel = "(%s%s)" % (self.names.get(key, key), info)
247 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 274
 class my_powerplug(base):
251 275
     KEY_OUTPUT_0 = "state"
@@ -312,8 +336,11 @@ class silvercrest_powerplug(base):
312 336
             self.set(self.KEY_OUTPUT_0, self.__ext_to_int__(self.KEY_OUTPUT_0, state))
313 337
 
314 338
     def __tx__(self, keys_changed):
339
+        data = {}
340
+        for key in self:
341
+            data[key] = self.__int_to_ext__(key, self[key])
315 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 345
     def command(self, command):
319 346
         if command in self.COMMANDS:
@@ -454,20 +481,23 @@ class brennenstuhl_heating_valve(base):
454 481
     #
455 482
     KEY_TEMPERATURE_SETPOINT = "current_heating_setpoint"
456 483
     KEY_TEMPERATURE = "local_temperature"
484
+    KEY_BATTERY = "battery"
457 485
     #
458 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 490
     def __init__(self, mqtt_client, topic):
463 491
         super().__init__(mqtt_client, topic, default_values={
464 492
             self.KEY_TEMPERATURE_SETPOINT: 20,
465 493
             self.KEY_TEMPERATURE: 20.7,
494
+            self.KEY_BATTERY: 97,
466 495
         })
467 496
         #
468 497
         self.add_callback(self.KEY_TEMPERATURE_SETPOINT, None, self.print_formatted, True)
469 498
         self.add_callback(self.KEY_TEMPERATURE_SETPOINT, None, self.__send__, True)
470 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 502
         self.__tx__((self.KEY_TEMPERATURE_SETPOINT, ))
473 503
 
@@ -495,6 +525,8 @@ class brennenstuhl_heating_valve(base):
495 525
                 self.set(self.KEY_TEMPERATURE_SETPOINT, self.__command_float_value__(value))
496 526
             elif command == self.COMMANDS[2]:
497 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 531
     def print_formatted(self, device, key, value):
500 532
         if key == self.KEY_TEMPERATURE_SETPOINT:
@@ -503,6 +535,12 @@ class brennenstuhl_heating_valve(base):
503 535
             perc = 0 if perc < 0 else perc
504 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 545
 class videv_light(base_videv):
508 546
     KEY_OUTPUT_0 = "state"
@@ -733,8 +771,44 @@ class videv_heating(base_videv):
733 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 808
 # class silvercrest_motion_sensor(base):
737 809
 #     KEY_OCCUPANCY = "occupancy"
810
+#     KEY_BATTERY = "battery"
811
+#     KEY_BATTERY_LOW = "battery_low"
738 812
 #     COMMANDS = ['motion']
739 813
 
740 814
 #     def __init__(self, mqtt_client, topic):
@@ -761,9 +835,17 @@ class videv_heating(base_videv):
761 835
 #         if value is not None:
762 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 846
 # class tradfri_button(base):
766 847
 #     KEY_ACTION = "action"
848
+#     KEY_BATTERY = "battery"
767 849
 #     #
768 850
 #     ACTION_TOGGLE = "toggle"
769 851
 #     ACTION_BRIGHTNESS_UP = "brightness_up_click"
@@ -800,6 +882,11 @@ class videv_heating(base_videv):
800 882
 #                 time.sleep(value or 0.5)
801 883
 #                 action = '_'.join(action.split('_')[:-1] + ['release'])
802 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 892
 # class remote(base):

+ 2
- 1
simulation/rooms.py 查看文件

@@ -1,6 +1,6 @@
1 1
 import config
2 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 4
 import inspect
5 5
 
6 6
 
@@ -266,3 +266,4 @@ class house(base):
266 266
         self.ffw = ffw(mqtt_client)
267 267
         self.ffe = ffe(mqtt_client)
268 268
         self.stairway = stairway(mqtt_client)
269
+        self.warnings = videv_warnings(mqtt_client, config.TOPIC_WARNINGS)

+ 1
- 0
smart_brain_test.py 查看文件

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

+ 1
- 1
tests/all.py 查看文件

@@ -83,7 +83,7 @@ class test_smarthome(object):
83 83
         system_info[jsonlog.SYSI_USERNAME] = getpass.getuser()
84 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 87
         self.tcl[jsonlog.MAIN_KEY_SYSTEM_INFO] = system_info
88 88
         self.tcl["testcase_names"] = report.TCEL_NAMES
89 89
 

Loading…
取消
儲存