velbus-aio 2021.8.7__py3-none-any.whl → 2025.11.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. scripts/parse_specs.py +156 -0
  2. velbus_aio-2025.11.0.dist-info/METADATA +71 -0
  3. velbus_aio-2025.11.0.dist-info/RECORD +194 -0
  4. {velbus_aio-2021.8.7.dist-info → velbus_aio-2025.11.0.dist-info}/WHEEL +1 -1
  5. velbus_aio-2025.11.0.dist-info/top_level.txt +3 -0
  6. velbusaio/channels.py +443 -109
  7. velbusaio/command_registry.py +126 -13
  8. velbusaio/const.py +36 -12
  9. velbusaio/controller.py +252 -177
  10. velbusaio/discovery.py +2 -2
  11. velbusaio/exceptions.py +22 -0
  12. velbusaio/handler.py +311 -145
  13. velbusaio/helpers.py +6 -18
  14. velbusaio/message.py +46 -132
  15. velbusaio/messages/__init__.py +12 -2
  16. velbusaio/messages/blind_status.py +16 -25
  17. velbusaio/messages/bus_active.py +3 -9
  18. velbusaio/messages/bus_error_counter_status.py +3 -4
  19. velbusaio/messages/bus_error_counter_status_request.py +3 -4
  20. velbusaio/messages/bus_off.py +3 -4
  21. velbusaio/messages/channel_name_part1.py +49 -33
  22. velbusaio/messages/channel_name_part2.py +49 -33
  23. velbusaio/messages/channel_name_part3.py +49 -33
  24. velbusaio/messages/channel_name_request.py +26 -12
  25. velbusaio/messages/clear_led.py +3 -4
  26. velbusaio/messages/counter_status.py +3 -17
  27. velbusaio/messages/counter_status_request.py +6 -6
  28. velbusaio/messages/counter_value.py +44 -0
  29. velbusaio/messages/cover_down.py +4 -29
  30. velbusaio/messages/cover_off.py +5 -29
  31. velbusaio/messages/cover_position.py +4 -19
  32. velbusaio/messages/cover_up.py +4 -27
  33. velbusaio/messages/dali_device_settings.py +178 -0
  34. velbusaio/messages/dali_device_settings_request.py +53 -0
  35. velbusaio/messages/dali_dim_value_status.py +44 -0
  36. velbusaio/messages/dimmer_channel_status.py +6 -19
  37. velbusaio/messages/dimmer_status.py +14 -31
  38. velbusaio/messages/edge_set_color.py +114 -0
  39. velbusaio/messages/edge_set_custom_color.py +56 -0
  40. velbusaio/messages/fast_blinking_led.py +3 -4
  41. velbusaio/messages/forced_off.py +3 -4
  42. velbusaio/messages/forced_on.py +3 -4
  43. velbusaio/messages/interface_status_request.py +3 -4
  44. velbusaio/messages/ir_receiver_status.py +18 -0
  45. velbusaio/messages/kwh_status.py +3 -19
  46. velbusaio/messages/light_value_request.py +3 -4
  47. velbusaio/messages/memo_text.py +3 -5
  48. velbusaio/messages/memory_data.py +3 -16
  49. velbusaio/messages/memory_data_block.py +3 -4
  50. velbusaio/messages/memory_dump_request.py +3 -4
  51. velbusaio/messages/module_status.py +107 -55
  52. velbusaio/messages/module_status_request.py +7 -6
  53. velbusaio/messages/module_subtype.py +11 -19
  54. velbusaio/messages/module_type.py +132 -21
  55. velbusaio/messages/module_type_request.py +1 -0
  56. velbusaio/messages/psu_load.py +56 -0
  57. velbusaio/messages/psu_values.py +53 -0
  58. velbusaio/messages/push_button_status.py +3 -16
  59. velbusaio/messages/raw.py +74 -0
  60. velbusaio/messages/read_data_block_from_memory.py +3 -4
  61. velbusaio/messages/read_data_from_memory.py +3 -4
  62. velbusaio/messages/realtime_clock_status_request.py +3 -4
  63. velbusaio/messages/receive_buffer_full.py +3 -4
  64. velbusaio/messages/receive_ready.py +3 -4
  65. velbusaio/messages/relay_status.py +13 -42
  66. velbusaio/messages/restore_dimmer.py +33 -24
  67. velbusaio/messages/select_program.py +35 -0
  68. velbusaio/messages/sensor_settings_request.py +3 -4
  69. velbusaio/messages/sensor_temp_request.py +3 -4
  70. velbusaio/messages/sensor_temperature.py +15 -19
  71. velbusaio/messages/set_date.py +10 -30
  72. velbusaio/messages/set_daylight_saving.py +8 -24
  73. velbusaio/messages/set_dimmer.py +43 -41
  74. velbusaio/messages/set_led.py +3 -4
  75. velbusaio/messages/set_realtime_clock.py +10 -30
  76. velbusaio/messages/set_temperature.py +3 -4
  77. velbusaio/messages/slider_status.py +16 -20
  78. velbusaio/messages/slow_blinking_led.py +3 -4
  79. velbusaio/messages/start_relay_blinking_timer.py +3 -4
  80. velbusaio/messages/start_relay_timer.py +3 -4
  81. velbusaio/messages/switch_relay_off.py +3 -16
  82. velbusaio/messages/switch_relay_on.py +3 -16
  83. velbusaio/messages/switch_to_comfort.py +4 -15
  84. velbusaio/messages/switch_to_day.py +4 -15
  85. velbusaio/messages/switch_to_night.py +4 -15
  86. velbusaio/messages/switch_to_safe.py +4 -15
  87. velbusaio/messages/temp_sensor_settings_part1.py +3 -4
  88. velbusaio/messages/temp_sensor_settings_part2.py +27 -0
  89. velbusaio/messages/temp_sensor_settings_part3.py +27 -0
  90. velbusaio/messages/temp_sensor_settings_part4.py +27 -0
  91. velbusaio/messages/temp_sensor_settings_request.py +3 -4
  92. velbusaio/messages/temp_sensor_status.py +34 -35
  93. velbusaio/messages/temp_set_cooling.py +3 -13
  94. velbusaio/messages/temp_set_heating.py +3 -13
  95. velbusaio/messages/update_led_status.py +3 -4
  96. velbusaio/messages/very_fast_blinking_led.py +3 -4
  97. velbusaio/messages/write_data_to_memory.py +3 -4
  98. velbusaio/messages/write_memory_block.py +3 -4
  99. velbusaio/messages/write_module_address_and_serial_number.py +3 -4
  100. velbusaio/module.py +680 -158
  101. velbusaio/module_spec/01.json +62 -0
  102. velbusaio/module_spec/02.json +16 -0
  103. velbusaio/module_spec/03.json +23 -0
  104. velbusaio/module_spec/04.json +283 -0
  105. velbusaio/module_spec/05.json +54 -0
  106. velbusaio/module_spec/06.json +110 -0
  107. velbusaio/module_spec/07.json +16 -0
  108. velbusaio/module_spec/08.json +38 -0
  109. velbusaio/module_spec/09.json +30 -0
  110. velbusaio/module_spec/0A.json +58 -0
  111. velbusaio/module_spec/0B.json +58 -0
  112. velbusaio/module_spec/0C.json +18 -0
  113. velbusaio/module_spec/0E.json +25 -0
  114. velbusaio/module_spec/0F.json +16 -0
  115. velbusaio/module_spec/10.json +111 -0
  116. velbusaio/module_spec/11.json +111 -0
  117. velbusaio/module_spec/12.json +73 -0
  118. velbusaio/module_spec/13.json +4 -0
  119. velbusaio/module_spec/14.json +16 -0
  120. velbusaio/module_spec/15.json +83 -0
  121. velbusaio/module_spec/16.json +129 -0
  122. velbusaio/module_spec/17.json +129 -0
  123. velbusaio/module_spec/18.json +129 -0
  124. velbusaio/module_spec/1A.json +79 -0
  125. velbusaio/module_spec/1B.json +107 -0
  126. velbusaio/module_spec/1D.json +89 -0
  127. velbusaio/module_spec/1E.json +306 -0
  128. velbusaio/module_spec/1F.json +178 -0
  129. velbusaio/module_spec/20.json +178 -0
  130. velbusaio/module_spec/21.json +326 -0
  131. velbusaio/module_spec/22.json +426 -0
  132. velbusaio/module_spec/23.json +129 -0
  133. velbusaio/module_spec/24.json +30 -0
  134. velbusaio/module_spec/25.json +3 -0
  135. velbusaio/module_spec/28.json +454 -0
  136. velbusaio/module_spec/29.json +235 -0
  137. velbusaio/module_spec/2A.json +239 -0
  138. velbusaio/module_spec/2B.json +239 -0
  139. velbusaio/module_spec/2C.json +257 -0
  140. velbusaio/module_spec/2D.json +270 -0
  141. velbusaio/module_spec/2E.json +215 -0
  142. velbusaio/module_spec/2F.json +211 -0
  143. velbusaio/module_spec/30.json +58 -0
  144. velbusaio/module_spec/31.json +465 -0
  145. velbusaio/module_spec/32.json +385 -0
  146. velbusaio/module_spec/33.json +249 -0
  147. velbusaio/module_spec/34.json +313 -0
  148. velbusaio/module_spec/35.json +313 -0
  149. velbusaio/module_spec/36.json +313 -0
  150. velbusaio/module_spec/37.json +333 -0
  151. velbusaio/module_spec/38.json +111 -0
  152. velbusaio/module_spec/39.json +4 -0
  153. velbusaio/module_spec/3A.json +306 -0
  154. velbusaio/module_spec/3B.json +306 -0
  155. velbusaio/module_spec/3C.json +306 -0
  156. velbusaio/module_spec/3D.json +454 -0
  157. velbusaio/module_spec/3E.json +302 -0
  158. velbusaio/module_spec/3F.json +4 -0
  159. velbusaio/module_spec/40.json +4 -0
  160. velbusaio/module_spec/41.json +241 -0
  161. velbusaio/module_spec/42.json +4 -0
  162. velbusaio/module_spec/43.json +23 -0
  163. velbusaio/module_spec/44.json +38 -0
  164. velbusaio/module_spec/45.json +4 -0
  165. velbusaio/module_spec/48.json +111 -0
  166. velbusaio/module_spec/49.json +111 -0
  167. velbusaio/module_spec/4A.json +89 -0
  168. velbusaio/module_spec/4B.json +138 -0
  169. velbusaio/module_spec/4C.json +129 -0
  170. velbusaio/module_spec/4D.json +108 -0
  171. velbusaio/module_spec/4E.json +787 -0
  172. velbusaio/module_spec/4F.json +114 -0
  173. velbusaio/module_spec/50.json +114 -0
  174. velbusaio/module_spec/51.json +114 -0
  175. velbusaio/module_spec/52.json +456 -0
  176. velbusaio/module_spec/54.json +270 -0
  177. velbusaio/module_spec/55.json +270 -0
  178. velbusaio/module_spec/56.json +270 -0
  179. velbusaio/module_spec/57.json +260 -0
  180. velbusaio/module_spec/5A.json +4 -0
  181. velbusaio/module_spec/5B.json +4 -0
  182. velbusaio/module_spec/5C.json +90 -0
  183. velbusaio/module_spec/5F.json +78 -0
  184. velbusaio/module_spec/60.json +4 -0
  185. velbusaio/module_spec/61.json +89 -0
  186. velbusaio/module_spec/broadcast.json +67 -0
  187. velbusaio/module_spec/ignore.json +22 -0
  188. velbusaio/protocol.py +243 -0
  189. velbusaio/py.typed +0 -0
  190. velbusaio/raw_message.py +149 -0
  191. velbusaio/util.py +55 -0
  192. velbusaio/vlp_reader.py +249 -0
  193. velbus_aio-2021.8.7.dist-info/METADATA +0 -66
  194. velbus_aio-2021.8.7.dist-info/RECORD +0 -90
  195. velbus_aio-2021.8.7.dist-info/top_level.txt +0 -1
  196. velbusaio/messages/meteo_raw.py +0 -52
  197. velbusaio/module_registry.py +0 -64
  198. velbusaio/moduleprotocol/protocol.json +0 -25540
  199. velbusaio/parser.py +0 -142
  200. {velbus_aio-2021.8.7.dist-info → velbus_aio-2025.11.0.dist-info/licenses}/LICENSE +0 -0
@@ -1,14 +1,16 @@
1
1
  """
2
2
  :author: Maikel Punie <maikel.punie@gmail.com>
3
3
  """
4
+
4
5
  from __future__ import annotations
5
6
 
6
- from velbusaio.command_registry import register_command
7
+ from velbusaio.command_registry import register
7
8
  from velbusaio.message import Message
8
9
 
9
10
  COMMAND_CODE = 0x14
10
11
 
11
12
 
13
+ @register(COMMAND_CODE)
12
14
  class ForcedOn(Message):
13
15
  def populate(self, priority, address, rtr, data):
14
16
  """
@@ -23,6 +25,3 @@ class ForcedOn(Message):
23
25
  :return: bytes
24
26
  """
25
27
  return bytes([COMMAND_CODE])
26
-
27
-
28
- register_command(COMMAND_CODE, ForcedOn)
@@ -1,14 +1,16 @@
1
1
  """
2
2
  :author: Thomas Delaet <thomas@delaet.org>
3
3
  """
4
+
4
5
  from __future__ import annotations
5
6
 
6
- from velbusaio.command_registry import register_command
7
+ from velbusaio.command_registry import register
7
8
  from velbusaio.message import Message
8
9
 
9
10
  COMMAND_CODE = 0x0E
10
11
 
11
12
 
13
+ @register(COMMAND_CODE)
12
14
  class InterfaceStatusRequestMessage(Message):
13
15
  """
14
16
  send by: VMB1USB
@@ -29,6 +31,3 @@ class InterfaceStatusRequestMessage(Message):
29
31
  :return: bytes
30
32
  """
31
33
  return bytes([COMMAND_CODE])
32
-
33
-
34
- register_command(COMMAND_CODE, InterfaceStatusRequestMessage)
@@ -0,0 +1,18 @@
1
+ """
2
+ :author: David Danssaert <david.danssaert@gmail.com>
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from velbusaio.command_registry import register
8
+ from velbusaio.messages.module_status import ModuleStatusMessage
9
+
10
+ COMMAND_CODE = 0xEB
11
+
12
+
13
+ @register(COMMAND_CODE, ["VMB8IR"])
14
+ class IRReceiverStatusMessage(ModuleStatusMessage):
15
+ """
16
+ send by: VMB8IR
17
+ received by:
18
+ """
@@ -1,16 +1,16 @@
1
1
  """
2
2
  :author: Maikel Punie <maikel.punie@gmail.com>
3
3
  """
4
- from __future__ import annotations
5
4
 
6
- import json
5
+ from __future__ import annotations
7
6
 
8
- from velbusaio.command_registry import register_command
7
+ from velbusaio.command_registry import register
9
8
  from velbusaio.message import Message
10
9
 
11
10
  COMMAND_CODE = 0xBE
12
11
 
13
12
 
13
+ @register(COMMAND_CODE)
14
14
  class KwhStatusMessage(Message):
15
15
  """
16
16
  send by: VMB7IN
@@ -46,24 +46,8 @@ class KwhStatusMessage(Message):
46
46
  if self.watt < 55:
47
47
  self.watt = 0
48
48
 
49
- def to_json(self):
50
- """
51
- :return: str
52
- """
53
- json_dict = self.to_json_basic()
54
- json_dict["pulses"] = self.pulses
55
- json_dict["counter"] = self.counter
56
- json_dict["kwh"] = self.kwh
57
- json_dict["delay"] = self.delay
58
- json_dict["watt"] = self.watt
59
- json_dict["channel"] = self.channel
60
- return json.dumps(json_dict)
61
-
62
49
  def get_channels(self):
63
50
  """
64
51
  :return: list
65
52
  """
66
53
  return self.channel
67
-
68
-
69
- register_command(COMMAND_CODE, KwhStatusMessage)
@@ -1,14 +1,16 @@
1
1
  """
2
2
  :author: Maikel Punie <maikel.punie@gmail.com>
3
3
  """
4
+
4
5
  from __future__ import annotations
5
6
 
6
- from velbusaio.command_registry import register_command
7
+ from velbusaio.command_registry import register
7
8
  from velbusaio.message import Message
8
9
 
9
10
  COMMAND_CODE = 0xAA
10
11
 
11
12
 
13
+ @register(COMMAND_CODE)
12
14
  class LightValueRequest(Message):
13
15
  def populate(self, priority, address, rtr, data):
14
16
  """
@@ -23,6 +25,3 @@ class LightValueRequest(Message):
23
25
  :return: bytes
24
26
  """
25
27
  return bytes([COMMAND_CODE])
26
-
27
-
28
- register_command(COMMAND_CODE, LightValueRequest)
@@ -1,14 +1,16 @@
1
1
  """
2
2
  :author: Maikel Punie <maikel.punie@gmail.com>
3
3
  """
4
+
4
5
  from __future__ import annotations
5
6
 
6
- from velbusaio.command_registry import register_command
7
+ from velbusaio.command_registry import register
7
8
  from velbusaio.message import Message
8
9
 
9
10
  COMMAND_CODE = 0xAC
10
11
 
11
12
 
13
+ @register(COMMAND_CODE)
12
14
  class MemoTextMessage(Message):
13
15
  """
14
16
  send by:
@@ -27,7 +29,6 @@ class MemoTextMessage(Message):
27
29
  """
28
30
  self.needs_low_priority(priority)
29
31
  self.needs_no_rtr(rtr)
30
- self.needs_data(data, 7)
31
32
  self.set_attributes(priority, address, rtr)
32
33
  self.start = data[1]
33
34
  self.name = "".join([chr(x) for x in data[2:]])
@@ -39,6 +40,3 @@ class MemoTextMessage(Message):
39
40
  while len(self.memo_text) < 5:
40
41
  self.memo_text += chr(0)
41
42
  return bytes([COMMAND_CODE, 0x00, self.start]) + bytes(self.memo_text, "utf-8")
42
-
43
-
44
- register_command(COMMAND_CODE, MemoTextMessage)
@@ -1,16 +1,16 @@
1
1
  """
2
2
  :author: Thomas Delaet <thomas@delaet.org>
3
3
  """
4
- from __future__ import annotations
5
4
 
6
- import json
5
+ from __future__ import annotations
7
6
 
8
- from velbusaio.command_registry import register_command
7
+ from velbusaio.command_registry import register
9
8
  from velbusaio.message import Message
10
9
 
11
10
  COMMAND_CODE = 0xFE
12
11
 
13
12
 
13
+ @register(COMMAND_CODE)
14
14
  class MemoryDataMessage(Message):
15
15
  """
16
16
  send by: VMB6IN, VMB4RYLD
@@ -41,16 +41,3 @@ class MemoryDataMessage(Message):
41
41
  :return: bytes
42
42
  """
43
43
  return bytes([COMMAND_CODE, self.high_address, self.low_address, self.data])
44
-
45
- def to_json(self):
46
- """
47
- :return: str
48
- """
49
- json_dict = self.to_json_basic()
50
- json_dict["high_add"] = self.high_address
51
- json_dict["low_addr"] = self.low_address
52
- json_dict["data"] = self.data
53
- return json.dumps(json_dict)
54
-
55
-
56
- register_command(COMMAND_CODE, MemoryDataMessage)
@@ -1,14 +1,16 @@
1
1
  """
2
2
  :author: Thomas Delaet <thomas@delaet.org>
3
3
  """
4
+
4
5
  from __future__ import annotations
5
6
 
6
- from velbusaio.command_registry import register_command
7
+ from velbusaio.command_registry import register
7
8
  from velbusaio.message import Message
8
9
 
9
10
  COMMAND_CODE = 0xCC
10
11
 
11
12
 
13
+ @register(COMMAND_CODE)
12
14
  class MemoryDataBlockMessage(Message):
13
15
  """
14
16
  send by: VMB6IN, VMB4RYLD
@@ -39,6 +41,3 @@ class MemoryDataBlockMessage(Message):
39
41
  :return: bytes
40
42
  """
41
43
  return bytes([COMMAND_CODE, self.high_address, self.low_address]) + self.data
42
-
43
-
44
- register_command(COMMAND_CODE, MemoryDataBlockMessage)
@@ -1,14 +1,16 @@
1
1
  """
2
2
  :author: Thomas Delaet <thomas@delaet.org>
3
3
  """
4
+
4
5
  from __future__ import annotations
5
6
 
6
- from velbusaio.command_registry import register_command
7
+ from velbusaio.command_registry import register
7
8
  from velbusaio.message import Message
8
9
 
9
10
  COMMAND_CODE = 0xCB
10
11
 
11
12
 
13
+ @register(COMMAND_CODE)
12
14
  class MemoryDumpRequestMessage(Message):
13
15
  """
14
16
  send by:
@@ -29,6 +31,3 @@ class MemoryDumpRequestMessage(Message):
29
31
  :return: bytes
30
32
  """
31
33
  return bytes([COMMAND_CODE])
32
-
33
-
34
- register_command(COMMAND_CODE, MemoryDumpRequestMessage)
@@ -1,16 +1,18 @@
1
1
  """
2
2
  :author: Thomas Delaet <thomas@delaet.org>
3
3
  """
4
- from __future__ import annotations
5
4
 
6
- import json
5
+ from __future__ import annotations
7
6
 
8
- from velbusaio.command_registry import register_command
7
+ from velbusaio.command_registry import register
9
8
  from velbusaio.message import Message
10
9
 
11
10
  COMMAND_CODE = 0xED
12
11
 
12
+ PROGRAM_SELECTION = {0: "none", 1: "summer", 2: "winter", 3: "holiday"}
13
13
 
14
+
15
+ @register(COMMAND_CODE)
14
16
  class ModuleStatusMessage(Message):
15
17
  """
16
18
  send by: VMB6IN
@@ -53,6 +55,41 @@ class ModuleStatusMessage(Message):
53
55
  )
54
56
 
55
57
 
58
+ @register(
59
+ COMMAND_CODE,
60
+ [
61
+ "VMB8PBU",
62
+ "VMB6PBN",
63
+ "VMB2PBN",
64
+ "VMB6PBB",
65
+ "VMBGP1",
66
+ "VMBEL1",
67
+ "VMBGP1-2",
68
+ "VMBGP2",
69
+ "VMBEL2",
70
+ "VMBGP2-2",
71
+ "VMBGP4",
72
+ "VMBEL4",
73
+ "VMBGP4-2",
74
+ "VMBGPO",
75
+ "VMBGPOD",
76
+ "VMBGPOD-2",
77
+ "VMBELO",
78
+ "VMB7IN",
79
+ "VMB6PB-20",
80
+ "VMBEL1-20",
81
+ "VMBEL2-20",
82
+ "VMBEL4-20",
83
+ "VMBELO-20",
84
+ "VMBGP1-20",
85
+ "VMBGP2-20",
86
+ "VMBGP4-20",
87
+ "VMBGPO-20",
88
+ "VMBEL4PIR-20",
89
+ "VMBGP4PIR-20",
90
+ "VMBPSUMNGR-20",
91
+ ],
92
+ )
56
93
  class ModuleStatusMessage2(Message):
57
94
  def __init__(self, address=None):
58
95
  Message.__init__(self)
@@ -61,6 +98,8 @@ class ModuleStatusMessage2(Message):
61
98
  self.normal = []
62
99
  self.locked = []
63
100
  self.programenabled = []
101
+ self.selected_program = 0
102
+ self.selected_program_str = PROGRAM_SELECTION[self.selected_program]
64
103
 
65
104
  def populate(self, priority, address, rtr, data):
66
105
  self.needs_low_priority(priority)
@@ -72,6 +111,8 @@ class ModuleStatusMessage2(Message):
72
111
  self.normal = self.byte_to_channels(data[2])
73
112
  self.locked = self.byte_to_channels(data[3])
74
113
  self.programenabled = self.byte_to_channels(data[4])
114
+ self.selected_program = data[5] & 0x03
115
+ self.selected_program_str = PROGRAM_SELECTION[self.selected_program]
75
116
 
76
117
  def data_to_binary(self):
77
118
  """
@@ -87,47 +128,42 @@ class ModuleStatusMessage2(Message):
87
128
  ]
88
129
  )
89
130
 
90
- def to_json(self):
91
- """
92
- :return: str
93
- """
94
- json_dict = self.to_json_basic()
95
- json_dict["closed"] = self.closed
96
- json_dict["enabled"] = self.enabled
97
- json_dict["normal"] = self.normal
98
- json_dict["locked"] = self.locked
99
- return json.dumps(json_dict)
100
-
101
131
 
132
+ @register(COMMAND_CODE, ["VMBPIRO", "VMBPIRM", "VMBPIRC", "VMBELPIR"])
102
133
  class ModuleStatusPirMessage(Message):
103
134
  def __init__(self, address=None):
104
135
  Message.__init__(self)
105
136
  # in data[0]
106
- self.dark = False # bit 1
107
- self.light = False # bit 2
108
- self.motion1 = False # bit 3
109
- self.light_motion1 = False # bit 4
110
- self.motion2 = False # bit 5
111
- self.light_motion2 = False # bit 6
112
- self.low_temp_alarm = False # bit 7
113
- self.high_temp_alarm = False # bit 8
137
+ self.dark: bool = False # bit 1
138
+ self.light: bool = False # bit 2
139
+ self.motion1: bool = False # bit 3
140
+ self.light_motion1: bool = False # bit 4
141
+ self.motion2: bool = False # bit 5
142
+ self.light_motion2: bool = False # bit 6
143
+ self.low_temp_alarm: bool = False # bit 7
144
+ self.high_temp_alarm: bool = False # bit 8
114
145
  # in data[1] and data[2]
115
- self.light_value = 0
146
+ self.light_value: int = 0
147
+ # in data[5]
148
+ self.selected_program = 0
149
+ self.selected_program_str = PROGRAM_SELECTION[self.selected_program]
116
150
 
117
151
  def populate(self, priority, address, rtr, data):
118
152
  self.needs_low_priority(priority)
119
153
  self.needs_no_rtr(rtr)
120
154
  self.needs_data(data, 7)
121
155
  self.set_attributes(priority, address, rtr)
122
- self.dark = 0x01 & data[0]
123
- self.light = 0x02 & data[0]
124
- self.motion1 = 0x04 & data[0]
125
- self.light_motion1 = 0x08 & data[0]
126
- self.motion2 = 0x10 & data[0]
127
- self.light_motion2 = 0x20 & data[0]
128
- self.low_temp_alarm = 0x40 & data[0]
129
- self.high_temp_alarm = 0x80 & data[0]
156
+ self.dark = bool(data[0] & (1 << 0))
157
+ self.light = bool(data[0] & (1 << 1))
158
+ self.motion1 = bool(data[0] & (1 << 2))
159
+ self.light_motion1 = bool(data[0] & (1 << 3))
160
+ self.motion2 = bool(data[0] & (1 << 4))
161
+ self.light_motion2 = bool(data[0] & (1 << 5))
162
+ self.low_temp_alarm = bool(data[0] & (1 << 6))
163
+ self.high_temp_alarm = bool(data[0] & (1 << 7))
130
164
  self.light_value = (data[1] << 8) + data[2]
165
+ self.selected_program = data[5] & 0x03
166
+ self.selected_program_str = PROGRAM_SELECTION[self.selected_program]
131
167
 
132
168
  def data_to_binary(self):
133
169
  """
@@ -136,27 +172,43 @@ class ModuleStatusPirMessage(Message):
136
172
  raise NotImplementedError
137
173
 
138
174
 
139
- register_command(COMMAND_CODE, ModuleStatusMessage)
140
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMB8PBU")
141
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMB6PBN")
142
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMB2PBN")
143
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMB6PBB")
144
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMBGP1")
145
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMBEL1")
146
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMBGP1-2")
147
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMBGP2")
148
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMBEL2")
149
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMBGP2-2")
150
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMBGP4")
151
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMBEL4")
152
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMBGP4-2")
153
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMBGPO")
154
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMBGPOD")
155
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMBELO")
156
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMB7IN")
157
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMB4DC")
158
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMBDMI")
159
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMBDMI-R")
160
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMBDME")
161
- register_command(COMMAND_CODE, ModuleStatusMessage2, "VMB1RYS")
162
- register_command(COMMAND_CODE, ModuleStatusPirMessage, "VMBIRO")
175
+ @register(COMMAND_CODE, ["VMBGP4PIR", "VMBGP4PIR-2"])
176
+ class ModuleStatusGP4PirMessage(Message):
177
+ def __init__(self, address=None):
178
+ Message.__init__(self)
179
+ # in data[0]
180
+ self.closed = []
181
+ self.enabled = [] # only 4 bits
182
+ # self.normal = []
183
+ self.locked = []
184
+ self.programenabled = []
185
+ self.selected_program = 0
186
+ self.selected_program_str = PROGRAM_SELECTION[self.selected_program]
187
+
188
+ # in data[1] and data[2]
189
+ self.light_value: int = 0
190
+ # in data[5]
191
+ self.selected_program = 0
192
+ self.selected_program_str = PROGRAM_SELECTION[self.selected_program]
193
+ # in data[6]
194
+ self.light_value_send_interval = 0
195
+
196
+ def populate(self, priority, address, rtr, data):
197
+ self.needs_low_priority(priority)
198
+ self.needs_no_rtr(rtr)
199
+ self.needs_data(data, 7)
200
+ self.set_attributes(priority, address, rtr)
201
+ self.closed = self.byte_to_channels(data[0])
202
+ self.enabled = self.byte_to_channels(data[1])
203
+ self.locked = self.byte_to_channels(data[3])
204
+ self.light_value = ((data[1] & 0x30) << 4) + data[2]
205
+ self.programenabled = self.byte_to_channels(data[4])
206
+ self.selected_program = data[5] & 0x03
207
+ self.selected_program_str = PROGRAM_SELECTION[self.selected_program]
208
+ self.light_value_send_interval = data[6]
209
+
210
+ def data_to_binary(self):
211
+ """
212
+ :return: bytes
213
+ """
214
+ raise NotImplementedError
@@ -1,14 +1,16 @@
1
1
  """
2
2
  :author: Thomas Delaet <thomas@delaet.org>
3
3
  """
4
+
4
5
  from __future__ import annotations
5
6
 
6
- from velbusaio.command_registry import register_command
7
+ from velbusaio.command_registry import register
7
8
  from velbusaio.message import Message
8
9
 
9
10
  COMMAND_CODE = 0xFA
10
11
 
11
12
 
13
+ @register(COMMAND_CODE)
12
14
  class ModuleStatusRequestMessage(Message):
13
15
  """
14
16
  send by:
@@ -17,7 +19,7 @@ class ModuleStatusRequestMessage(Message):
17
19
 
18
20
  def __init__(self, address=None):
19
21
  Message.__init__(self)
20
- self.channels = []
22
+ self.channels: list | str = []
21
23
  self.wait_after_send = 500
22
24
  self.set_defaults(address)
23
25
 
@@ -35,7 +37,6 @@ class ModuleStatusRequestMessage(Message):
35
37
  """
36
38
  :return: bytes
37
39
  """
38
- return bytes([COMMAND_CODE, self.channels_to_byte(self.channels)])
39
-
40
-
41
- register_command(COMMAND_CODE, ModuleStatusRequestMessage)
40
+ if isinstance(self.channels, list):
41
+ return bytes([COMMAND_CODE, self.channels_to_byte(self.channels)])
42
+ return bytes([COMMAND_CODE, int(self.channels, 16)])
@@ -1,17 +1,22 @@
1
1
  """
2
2
  :author: Thomas Delaet <thomas@delaet.org>
3
3
  """
4
+
4
5
  from __future__ import annotations
5
6
 
6
- import json
7
7
  import struct
8
8
 
9
- from velbusaio.command_registry import register_command
9
+ from velbusaio.command_registry import register
10
10
  from velbusaio.message import Message
11
11
 
12
12
  COMMAND_CODE = 0xB0
13
+ COMMAND_CODE_2 = 0xA7
14
+ COMMAND_CODE_3 = 0xA6
13
15
 
14
16
 
17
+ @register(COMMAND_CODE)
18
+ @register(COMMAND_CODE_2)
19
+ @register(COMMAND_CODE_3)
15
20
  class ModuleSubTypeMessage(Message):
16
21
  """
17
22
  send by: VMB6IN, VMB4RYLD
@@ -20,7 +25,7 @@ class ModuleSubTypeMessage(Message):
20
25
 
21
26
  # pylint: disable-msg=R0902
22
27
 
23
- def __init__(self, address=None):
28
+ def __init__(self, address=None, sub_address_offset: int = 0) -> None:
24
29
  Message.__init__(self)
25
30
  self.module_type = 0x00
26
31
  self.sub_address_1 = 0xFF
@@ -29,14 +34,15 @@ class ModuleSubTypeMessage(Message):
29
34
  self.sub_address_4 = 0xFF
30
35
  self.set_defaults(address)
31
36
  self.serial = 0
37
+ self.sub_address_offset = sub_address_offset
32
38
 
33
- def module_name(self):
39
+ def module_name(self) -> str:
34
40
  """
35
41
  :return: str
36
42
  """
37
43
  return "Unknown"
38
44
 
39
- def populate(self, priority, address, rtr, data):
45
+ def populate(self, priority, address, rtr, data) -> None:
40
46
  """
41
47
  :return: None
42
48
  """
@@ -50,17 +56,3 @@ class ModuleSubTypeMessage(Message):
50
56
  self.sub_address_2 = data[4]
51
57
  self.sub_address_3 = data[5]
52
58
  self.sub_address_4 = data[6]
53
-
54
- def to_json(self):
55
- """
56
- :return: str
57
- """
58
- json_dict = self.to_json_basic()
59
- json_dict["sub_1"] = self.sub_address_1
60
- json_dict["sub_2"] = self.sub_address_2
61
- json_dict["sub_3"] = self.sub_address_3
62
- json_dict["sub_4"] = self.sub_address_4
63
- return json.dumps(json_dict)
64
-
65
-
66
- register_command(COMMAND_CODE, ModuleSubTypeMessage)