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.
- scripts/parse_specs.py +156 -0
- velbus_aio-2025.11.0.dist-info/METADATA +71 -0
- velbus_aio-2025.11.0.dist-info/RECORD +194 -0
- {velbus_aio-2021.8.7.dist-info → velbus_aio-2025.11.0.dist-info}/WHEEL +1 -1
- velbus_aio-2025.11.0.dist-info/top_level.txt +3 -0
- velbusaio/channels.py +443 -109
- velbusaio/command_registry.py +126 -13
- velbusaio/const.py +36 -12
- velbusaio/controller.py +252 -177
- velbusaio/discovery.py +2 -2
- velbusaio/exceptions.py +22 -0
- velbusaio/handler.py +311 -145
- velbusaio/helpers.py +6 -18
- velbusaio/message.py +46 -132
- velbusaio/messages/__init__.py +12 -2
- velbusaio/messages/blind_status.py +16 -25
- velbusaio/messages/bus_active.py +3 -9
- velbusaio/messages/bus_error_counter_status.py +3 -4
- velbusaio/messages/bus_error_counter_status_request.py +3 -4
- velbusaio/messages/bus_off.py +3 -4
- velbusaio/messages/channel_name_part1.py +49 -33
- velbusaio/messages/channel_name_part2.py +49 -33
- velbusaio/messages/channel_name_part3.py +49 -33
- velbusaio/messages/channel_name_request.py +26 -12
- velbusaio/messages/clear_led.py +3 -4
- velbusaio/messages/counter_status.py +3 -17
- velbusaio/messages/counter_status_request.py +6 -6
- velbusaio/messages/counter_value.py +44 -0
- velbusaio/messages/cover_down.py +4 -29
- velbusaio/messages/cover_off.py +5 -29
- velbusaio/messages/cover_position.py +4 -19
- velbusaio/messages/cover_up.py +4 -27
- velbusaio/messages/dali_device_settings.py +178 -0
- velbusaio/messages/dali_device_settings_request.py +53 -0
- velbusaio/messages/dali_dim_value_status.py +44 -0
- velbusaio/messages/dimmer_channel_status.py +6 -19
- velbusaio/messages/dimmer_status.py +14 -31
- velbusaio/messages/edge_set_color.py +114 -0
- velbusaio/messages/edge_set_custom_color.py +56 -0
- velbusaio/messages/fast_blinking_led.py +3 -4
- velbusaio/messages/forced_off.py +3 -4
- velbusaio/messages/forced_on.py +3 -4
- velbusaio/messages/interface_status_request.py +3 -4
- velbusaio/messages/ir_receiver_status.py +18 -0
- velbusaio/messages/kwh_status.py +3 -19
- velbusaio/messages/light_value_request.py +3 -4
- velbusaio/messages/memo_text.py +3 -5
- velbusaio/messages/memory_data.py +3 -16
- velbusaio/messages/memory_data_block.py +3 -4
- velbusaio/messages/memory_dump_request.py +3 -4
- velbusaio/messages/module_status.py +107 -55
- velbusaio/messages/module_status_request.py +7 -6
- velbusaio/messages/module_subtype.py +11 -19
- velbusaio/messages/module_type.py +132 -21
- velbusaio/messages/module_type_request.py +1 -0
- velbusaio/messages/psu_load.py +56 -0
- velbusaio/messages/psu_values.py +53 -0
- velbusaio/messages/push_button_status.py +3 -16
- velbusaio/messages/raw.py +74 -0
- velbusaio/messages/read_data_block_from_memory.py +3 -4
- velbusaio/messages/read_data_from_memory.py +3 -4
- velbusaio/messages/realtime_clock_status_request.py +3 -4
- velbusaio/messages/receive_buffer_full.py +3 -4
- velbusaio/messages/receive_ready.py +3 -4
- velbusaio/messages/relay_status.py +13 -42
- velbusaio/messages/restore_dimmer.py +33 -24
- velbusaio/messages/select_program.py +35 -0
- velbusaio/messages/sensor_settings_request.py +3 -4
- velbusaio/messages/sensor_temp_request.py +3 -4
- velbusaio/messages/sensor_temperature.py +15 -19
- velbusaio/messages/set_date.py +10 -30
- velbusaio/messages/set_daylight_saving.py +8 -24
- velbusaio/messages/set_dimmer.py +43 -41
- velbusaio/messages/set_led.py +3 -4
- velbusaio/messages/set_realtime_clock.py +10 -30
- velbusaio/messages/set_temperature.py +3 -4
- velbusaio/messages/slider_status.py +16 -20
- velbusaio/messages/slow_blinking_led.py +3 -4
- velbusaio/messages/start_relay_blinking_timer.py +3 -4
- velbusaio/messages/start_relay_timer.py +3 -4
- velbusaio/messages/switch_relay_off.py +3 -16
- velbusaio/messages/switch_relay_on.py +3 -16
- velbusaio/messages/switch_to_comfort.py +4 -15
- velbusaio/messages/switch_to_day.py +4 -15
- velbusaio/messages/switch_to_night.py +4 -15
- velbusaio/messages/switch_to_safe.py +4 -15
- velbusaio/messages/temp_sensor_settings_part1.py +3 -4
- velbusaio/messages/temp_sensor_settings_part2.py +27 -0
- velbusaio/messages/temp_sensor_settings_part3.py +27 -0
- velbusaio/messages/temp_sensor_settings_part4.py +27 -0
- velbusaio/messages/temp_sensor_settings_request.py +3 -4
- velbusaio/messages/temp_sensor_status.py +34 -35
- velbusaio/messages/temp_set_cooling.py +3 -13
- velbusaio/messages/temp_set_heating.py +3 -13
- velbusaio/messages/update_led_status.py +3 -4
- velbusaio/messages/very_fast_blinking_led.py +3 -4
- velbusaio/messages/write_data_to_memory.py +3 -4
- velbusaio/messages/write_memory_block.py +3 -4
- velbusaio/messages/write_module_address_and_serial_number.py +3 -4
- velbusaio/module.py +680 -158
- velbusaio/module_spec/01.json +62 -0
- velbusaio/module_spec/02.json +16 -0
- velbusaio/module_spec/03.json +23 -0
- velbusaio/module_spec/04.json +283 -0
- velbusaio/module_spec/05.json +54 -0
- velbusaio/module_spec/06.json +110 -0
- velbusaio/module_spec/07.json +16 -0
- velbusaio/module_spec/08.json +38 -0
- velbusaio/module_spec/09.json +30 -0
- velbusaio/module_spec/0A.json +58 -0
- velbusaio/module_spec/0B.json +58 -0
- velbusaio/module_spec/0C.json +18 -0
- velbusaio/module_spec/0E.json +25 -0
- velbusaio/module_spec/0F.json +16 -0
- velbusaio/module_spec/10.json +111 -0
- velbusaio/module_spec/11.json +111 -0
- velbusaio/module_spec/12.json +73 -0
- velbusaio/module_spec/13.json +4 -0
- velbusaio/module_spec/14.json +16 -0
- velbusaio/module_spec/15.json +83 -0
- velbusaio/module_spec/16.json +129 -0
- velbusaio/module_spec/17.json +129 -0
- velbusaio/module_spec/18.json +129 -0
- velbusaio/module_spec/1A.json +79 -0
- velbusaio/module_spec/1B.json +107 -0
- velbusaio/module_spec/1D.json +89 -0
- velbusaio/module_spec/1E.json +306 -0
- velbusaio/module_spec/1F.json +178 -0
- velbusaio/module_spec/20.json +178 -0
- velbusaio/module_spec/21.json +326 -0
- velbusaio/module_spec/22.json +426 -0
- velbusaio/module_spec/23.json +129 -0
- velbusaio/module_spec/24.json +30 -0
- velbusaio/module_spec/25.json +3 -0
- velbusaio/module_spec/28.json +454 -0
- velbusaio/module_spec/29.json +235 -0
- velbusaio/module_spec/2A.json +239 -0
- velbusaio/module_spec/2B.json +239 -0
- velbusaio/module_spec/2C.json +257 -0
- velbusaio/module_spec/2D.json +270 -0
- velbusaio/module_spec/2E.json +215 -0
- velbusaio/module_spec/2F.json +211 -0
- velbusaio/module_spec/30.json +58 -0
- velbusaio/module_spec/31.json +465 -0
- velbusaio/module_spec/32.json +385 -0
- velbusaio/module_spec/33.json +249 -0
- velbusaio/module_spec/34.json +313 -0
- velbusaio/module_spec/35.json +313 -0
- velbusaio/module_spec/36.json +313 -0
- velbusaio/module_spec/37.json +333 -0
- velbusaio/module_spec/38.json +111 -0
- velbusaio/module_spec/39.json +4 -0
- velbusaio/module_spec/3A.json +306 -0
- velbusaio/module_spec/3B.json +306 -0
- velbusaio/module_spec/3C.json +306 -0
- velbusaio/module_spec/3D.json +454 -0
- velbusaio/module_spec/3E.json +302 -0
- velbusaio/module_spec/3F.json +4 -0
- velbusaio/module_spec/40.json +4 -0
- velbusaio/module_spec/41.json +241 -0
- velbusaio/module_spec/42.json +4 -0
- velbusaio/module_spec/43.json +23 -0
- velbusaio/module_spec/44.json +38 -0
- velbusaio/module_spec/45.json +4 -0
- velbusaio/module_spec/48.json +111 -0
- velbusaio/module_spec/49.json +111 -0
- velbusaio/module_spec/4A.json +89 -0
- velbusaio/module_spec/4B.json +138 -0
- velbusaio/module_spec/4C.json +129 -0
- velbusaio/module_spec/4D.json +108 -0
- velbusaio/module_spec/4E.json +787 -0
- velbusaio/module_spec/4F.json +114 -0
- velbusaio/module_spec/50.json +114 -0
- velbusaio/module_spec/51.json +114 -0
- velbusaio/module_spec/52.json +456 -0
- velbusaio/module_spec/54.json +270 -0
- velbusaio/module_spec/55.json +270 -0
- velbusaio/module_spec/56.json +270 -0
- velbusaio/module_spec/57.json +260 -0
- velbusaio/module_spec/5A.json +4 -0
- velbusaio/module_spec/5B.json +4 -0
- velbusaio/module_spec/5C.json +90 -0
- velbusaio/module_spec/5F.json +78 -0
- velbusaio/module_spec/60.json +4 -0
- velbusaio/module_spec/61.json +89 -0
- velbusaio/module_spec/broadcast.json +67 -0
- velbusaio/module_spec/ignore.json +22 -0
- velbusaio/protocol.py +243 -0
- velbusaio/py.typed +0 -0
- velbusaio/raw_message.py +149 -0
- velbusaio/util.py +55 -0
- velbusaio/vlp_reader.py +249 -0
- velbus_aio-2021.8.7.dist-info/METADATA +0 -66
- velbus_aio-2021.8.7.dist-info/RECORD +0 -90
- velbus_aio-2021.8.7.dist-info/top_level.txt +0 -1
- velbusaio/messages/meteo_raw.py +0 -52
- velbusaio/module_registry.py +0 -64
- velbusaio/moduleprotocol/protocol.json +0 -25540
- velbusaio/parser.py +0 -142
- {velbus_aio-2021.8.7.dist-info → velbus_aio-2025.11.0.dist-info/licenses}/LICENSE +0 -0
velbusaio/message.py
CHANGED
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
"""
|
|
2
2
|
The velbus abstract message class
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from __future__ import annotations
|
|
5
6
|
|
|
7
|
+
import enum
|
|
6
8
|
import json
|
|
7
9
|
|
|
8
|
-
from velbusaio.const import
|
|
9
|
-
ETX,
|
|
10
|
-
PRIORITY_FIRMWARE,
|
|
11
|
-
PRIORITY_HIGH,
|
|
12
|
-
PRIORITY_LOW,
|
|
13
|
-
RTR,
|
|
14
|
-
STX,
|
|
15
|
-
)
|
|
16
|
-
from velbusaio.helpers import checksum
|
|
10
|
+
from velbusaio.const import PRIORITY_FIRMWARE, PRIORITY_HIGH, PRIORITY_LOW
|
|
17
11
|
|
|
18
12
|
|
|
19
13
|
class ParserError(Exception):
|
|
@@ -27,35 +21,27 @@ class Message:
|
|
|
27
21
|
Base Velbus message
|
|
28
22
|
"""
|
|
29
23
|
|
|
30
|
-
def __init__(self, address: int =
|
|
24
|
+
def __init__(self, address: int = 0) -> None:
|
|
31
25
|
self.priority = PRIORITY_LOW
|
|
32
|
-
self.address =
|
|
33
|
-
self.rtr = False
|
|
26
|
+
self.address: int = 0
|
|
27
|
+
self.rtr: bool = False
|
|
34
28
|
self.data = bytearray()
|
|
35
29
|
self.set_defaults(address)
|
|
36
30
|
|
|
37
|
-
def set_attributes(self, priority: int, address: int, rtr:
|
|
38
|
-
"""
|
|
39
|
-
:return: None
|
|
40
|
-
"""
|
|
31
|
+
def set_attributes(self, priority: int, address: int, rtr: bool) -> None:
|
|
41
32
|
self.priority = priority
|
|
42
33
|
self.address = address
|
|
43
34
|
self.rtr = rtr
|
|
44
35
|
|
|
45
|
-
def populate(self, priority, address: int, rtr:
|
|
46
|
-
"""
|
|
47
|
-
:return: None
|
|
48
|
-
"""
|
|
36
|
+
def populate(self, priority: int, address: int, rtr: bool, data: int) -> None:
|
|
49
37
|
raise NotImplementedError
|
|
50
38
|
|
|
51
|
-
def set_defaults(self, address) -> None:
|
|
39
|
+
def set_defaults(self, address: int | None) -> None:
|
|
52
40
|
"""
|
|
53
41
|
Set defaults
|
|
54
42
|
|
|
55
43
|
If a message has different than low priority or NO_RTR set,
|
|
56
44
|
then this method needs override in subclass
|
|
57
|
-
|
|
58
|
-
:return: None
|
|
59
45
|
"""
|
|
60
46
|
if address is not None:
|
|
61
47
|
self.set_address(address)
|
|
@@ -63,65 +49,44 @@ class Message:
|
|
|
63
49
|
self.set_no_rtr()
|
|
64
50
|
|
|
65
51
|
def set_address(self, address: int) -> None:
|
|
66
|
-
"""
|
|
67
|
-
:return: None
|
|
68
|
-
"""
|
|
69
52
|
self.address = address
|
|
70
53
|
|
|
71
|
-
def
|
|
72
|
-
|
|
73
|
-
:return: bytes
|
|
74
|
-
"""
|
|
75
|
-
data_bytes = self.data_to_binary()
|
|
76
|
-
if self.rtr:
|
|
77
|
-
rtr_and_size = RTR | len(data_bytes)
|
|
78
|
-
else:
|
|
79
|
-
rtr_and_size = len(data_bytes)
|
|
80
|
-
header = bytearray([STX, self.priority, self.address, rtr_and_size])
|
|
81
|
-
checksum_string = checksum(header + data_bytes)
|
|
82
|
-
return (
|
|
83
|
-
header
|
|
84
|
-
+ data_bytes
|
|
85
|
-
+ bytearray.fromhex(f"{checksum_string:02x}")
|
|
86
|
-
+ bytearray([ETX])
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
def data_to_binary(self):
|
|
90
|
-
"""
|
|
91
|
-
:return: bytes
|
|
92
|
-
"""
|
|
93
|
-
raise NotImplementedError
|
|
54
|
+
def data_to_binary(self) -> bytes:
|
|
55
|
+
raise NotImplementedError()
|
|
94
56
|
|
|
95
|
-
def to_json_basic(self):
|
|
57
|
+
def to_json_basic(self) -> dict:
|
|
96
58
|
"""
|
|
97
59
|
Create JSON structure with generic attributes
|
|
98
|
-
|
|
99
|
-
:return: dict
|
|
100
60
|
"""
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
"
|
|
106
|
-
|
|
61
|
+
me = {}
|
|
62
|
+
me["name"] = str(self.__class__.__name__)
|
|
63
|
+
me.update(self.__dict__.copy())
|
|
64
|
+
for key in me.copy():
|
|
65
|
+
if key == "name":
|
|
66
|
+
continue
|
|
67
|
+
if callable(getattr(self, key)) or key.startswith("__"):
|
|
68
|
+
del me[key]
|
|
69
|
+
if isinstance(me[key], (bytes, bytearray, enum.Enum)):
|
|
70
|
+
me[key] = str(me[key])
|
|
71
|
+
else:
|
|
72
|
+
try:
|
|
73
|
+
json.dumps(me[key]) # Test if the value is JSON serializable
|
|
74
|
+
except (TypeError, ValueError):
|
|
75
|
+
me[key] = str(me[key]) # Convert non-serializable objects to string
|
|
76
|
+
return me
|
|
107
77
|
|
|
108
78
|
def to_json(self) -> str:
|
|
109
79
|
"""
|
|
110
80
|
Dump object structure to JSON
|
|
111
81
|
|
|
112
82
|
This method should be overridden in subclasses to include more than just generic attributes
|
|
113
|
-
|
|
114
|
-
:return: str
|
|
115
83
|
"""
|
|
116
84
|
return json.dumps(self.to_json_basic())
|
|
117
85
|
|
|
118
86
|
def __str__(self) -> str:
|
|
119
87
|
return self.to_json()
|
|
120
88
|
|
|
121
|
-
def byte_to_channels(self, byte: int) ->
|
|
122
|
-
"""
|
|
123
|
-
:return: list(int)
|
|
124
|
-
"""
|
|
89
|
+
def byte_to_channels(self, byte: int) -> list[int]:
|
|
125
90
|
# pylint: disable-msg=R0201
|
|
126
91
|
result = []
|
|
127
92
|
for offset in range(0, 8):
|
|
@@ -129,10 +94,7 @@ class Message:
|
|
|
129
94
|
result.append(offset + 1)
|
|
130
95
|
return result
|
|
131
96
|
|
|
132
|
-
def channels_to_byte(self, channels) -> int:
|
|
133
|
-
"""
|
|
134
|
-
:return: int
|
|
135
|
-
"""
|
|
97
|
+
def channels_to_byte(self, channels: list[int]) -> int:
|
|
136
98
|
# pylint: disable-msg=R0201
|
|
137
99
|
result = 0
|
|
138
100
|
for offset in range(0, 8):
|
|
@@ -140,113 +102,65 @@ class Message:
|
|
|
140
102
|
result = result + (1 << offset)
|
|
141
103
|
return result
|
|
142
104
|
|
|
143
|
-
def byte_to_channel(self, byte):
|
|
144
|
-
"""
|
|
145
|
-
:return: int
|
|
146
|
-
"""
|
|
105
|
+
def byte_to_channel(self, byte: int) -> int:
|
|
147
106
|
channels = self.byte_to_channels(byte)
|
|
148
107
|
self.needs_one_channel(channels)
|
|
149
108
|
return channels[0]
|
|
150
109
|
|
|
151
|
-
def parser_error(self, message):
|
|
152
|
-
"""
|
|
153
|
-
:return: None
|
|
154
|
-
"""
|
|
110
|
+
def parser_error(self, message: str) -> None:
|
|
155
111
|
raise ParserError(self.__class__.__name__ + " " + message)
|
|
156
112
|
|
|
157
|
-
def needs_rtr(self, rtr):
|
|
158
|
-
"""
|
|
159
|
-
:return: None
|
|
160
|
-
"""
|
|
113
|
+
def needs_rtr(self, rtr: bool) -> None:
|
|
161
114
|
if not rtr:
|
|
162
115
|
self.parser_error("needs rtr set")
|
|
163
116
|
|
|
164
|
-
def set_rtr(self):
|
|
165
|
-
"""
|
|
166
|
-
:return: None
|
|
167
|
-
"""
|
|
117
|
+
def set_rtr(self) -> None:
|
|
168
118
|
self.rtr = True
|
|
169
119
|
|
|
170
|
-
def needs_no_rtr(self, rtr):
|
|
171
|
-
"""
|
|
172
|
-
:return: None
|
|
173
|
-
"""
|
|
120
|
+
def needs_no_rtr(self, rtr: bool) -> None:
|
|
174
121
|
if rtr:
|
|
175
122
|
self.parser_error("does not need rtr set")
|
|
176
123
|
|
|
177
|
-
def set_no_rtr(self):
|
|
178
|
-
"""
|
|
179
|
-
:return: None
|
|
180
|
-
"""
|
|
124
|
+
def set_no_rtr(self) -> None:
|
|
181
125
|
self.rtr = False
|
|
182
126
|
|
|
183
|
-
def needs_low_priority(self, priority):
|
|
184
|
-
"""
|
|
185
|
-
:return: None
|
|
186
|
-
"""
|
|
127
|
+
def needs_low_priority(self, priority: int) -> None:
|
|
187
128
|
if priority != PRIORITY_LOW:
|
|
188
129
|
self.parser_error("needs low priority set")
|
|
189
130
|
|
|
190
|
-
def set_low_priority(self):
|
|
191
|
-
"""
|
|
192
|
-
:return: None
|
|
193
|
-
"""
|
|
131
|
+
def set_low_priority(self) -> None:
|
|
194
132
|
self.priority = PRIORITY_LOW
|
|
195
133
|
|
|
196
|
-
def needs_high_priority(self, priority):
|
|
197
|
-
"""
|
|
198
|
-
:return: None
|
|
199
|
-
"""
|
|
134
|
+
def needs_high_priority(self, priority: int) -> None:
|
|
200
135
|
if priority != PRIORITY_HIGH:
|
|
201
136
|
self.parser_error("needs high priority set")
|
|
202
137
|
|
|
203
|
-
def set_high_priority(self):
|
|
204
|
-
"""
|
|
205
|
-
:return: None
|
|
206
|
-
"""
|
|
138
|
+
def set_high_priority(self) -> None:
|
|
207
139
|
self.priority = PRIORITY_HIGH
|
|
208
140
|
|
|
209
|
-
def needs_firmware_priority(self, priority):
|
|
210
|
-
"""
|
|
211
|
-
:return: None
|
|
212
|
-
"""
|
|
141
|
+
def needs_firmware_priority(self, priority: int) -> None:
|
|
213
142
|
if priority != PRIORITY_FIRMWARE:
|
|
214
143
|
self.parser_error("needs firmware priority set")
|
|
215
144
|
|
|
216
|
-
def set_firmware_priority(self):
|
|
217
|
-
"""
|
|
218
|
-
:return: None
|
|
219
|
-
"""
|
|
145
|
+
def set_firmware_priority(self) -> None:
|
|
220
146
|
self.priority = PRIORITY_FIRMWARE
|
|
221
147
|
|
|
222
|
-
def needs_no_data(self, data):
|
|
223
|
-
"""
|
|
224
|
-
:return: None
|
|
225
|
-
"""
|
|
148
|
+
def needs_no_data(self, data: bytes) -> None:
|
|
226
149
|
length = len(data)
|
|
227
150
|
if length != 0:
|
|
228
151
|
self.parser_error("has data included")
|
|
229
152
|
|
|
230
|
-
def needs_data(self, data, length):
|
|
231
|
-
"""
|
|
232
|
-
:return: None
|
|
233
|
-
"""
|
|
153
|
+
def needs_data(self, data: bytes, length: int) -> None:
|
|
234
154
|
if len(data) < length:
|
|
235
155
|
self.parser_error(
|
|
236
156
|
"needs " + str(length) + " bytes of data have " + str(len(data))
|
|
237
157
|
)
|
|
238
158
|
|
|
239
|
-
def needs_fixed_byte(self, byte, value):
|
|
240
|
-
"""
|
|
241
|
-
:return: None
|
|
242
|
-
"""
|
|
159
|
+
def needs_fixed_byte(self, byte: int, value: int) -> None:
|
|
243
160
|
if byte != value:
|
|
244
161
|
self.parser_error("expects " + chr(value) + " in byte " + chr(byte))
|
|
245
162
|
|
|
246
|
-
def needs_one_channel(self, channels):
|
|
247
|
-
"""
|
|
248
|
-
:return: None
|
|
249
|
-
"""
|
|
163
|
+
def needs_one_channel(self, channels: list[int]) -> None:
|
|
250
164
|
if (
|
|
251
165
|
len(channels) != 1
|
|
252
166
|
or not isinstance(channels[0], int)
|
velbusaio/messages/__init__.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
:author: Thomas Delaet <thomas@delaet.org>
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from __future__ import annotations
|
|
5
6
|
|
|
6
7
|
from velbusaio.messages.blind_status import BlindStatusMessage, BlindStatusNgMessage
|
|
@@ -32,29 +33,34 @@ from velbusaio.messages.channel_name_request import (
|
|
|
32
33
|
from velbusaio.messages.clear_led import ClearLedMessage
|
|
33
34
|
from velbusaio.messages.counter_status import CounterStatusMessage
|
|
34
35
|
from velbusaio.messages.counter_status_request import CounterStatusRequestMessage
|
|
36
|
+
from velbusaio.messages.counter_value import CounterValueMessage
|
|
35
37
|
from velbusaio.messages.cover_down import CoverDownMessage, CoverDownMessage2
|
|
36
38
|
from velbusaio.messages.cover_off import CoverOffMessage, CoverOffMessage2
|
|
37
39
|
from velbusaio.messages.cover_position import CoverPosMessage
|
|
38
40
|
from velbusaio.messages.cover_up import CoverUpMessage, CoverUpMessage2
|
|
41
|
+
from velbusaio.messages.dali_device_settings import DaliDeviceSettingMsg
|
|
39
42
|
from velbusaio.messages.dimmer_channel_status import DimmerChannelStatusMessage
|
|
40
43
|
from velbusaio.messages.dimmer_status import DimmerStatusMessage
|
|
41
44
|
from velbusaio.messages.fast_blinking_led import FastBlinkingLedMessage
|
|
42
45
|
from velbusaio.messages.forced_off import ForcedOff
|
|
43
46
|
from velbusaio.messages.forced_on import ForcedOn
|
|
44
47
|
from velbusaio.messages.interface_status_request import InterfaceStatusRequestMessage
|
|
48
|
+
from velbusaio.messages.ir_receiver_status import IRReceiverStatusMessage
|
|
45
49
|
from velbusaio.messages.kwh_status import KwhStatusMessage
|
|
46
50
|
from velbusaio.messages.light_value_request import LightValueRequest
|
|
47
51
|
from velbusaio.messages.memo_text import MemoTextMessage
|
|
48
52
|
from velbusaio.messages.memory_data import MemoryDataMessage
|
|
49
53
|
from velbusaio.messages.memory_data_block import MemoryDataBlockMessage
|
|
50
54
|
from velbusaio.messages.memory_dump_request import MemoryDumpRequestMessage
|
|
51
|
-
from velbusaio.messages.meteo_raw import MeteoRawMessage
|
|
52
55
|
from velbusaio.messages.module_status import ModuleStatusMessage, ModuleStatusMessage2
|
|
53
56
|
from velbusaio.messages.module_status_request import ModuleStatusRequestMessage
|
|
54
57
|
from velbusaio.messages.module_subtype import ModuleSubTypeMessage
|
|
55
|
-
from velbusaio.messages.module_type import ModuleTypeMessage
|
|
58
|
+
from velbusaio.messages.module_type import ModuleType2Message, ModuleTypeMessage
|
|
56
59
|
from velbusaio.messages.module_type_request import ModuleTypeRequestMessage
|
|
60
|
+
from velbusaio.messages.psu_load import PsuLoadMessage
|
|
61
|
+
from velbusaio.messages.psu_values import PsuValuesMessage
|
|
57
62
|
from velbusaio.messages.push_button_status import PushButtonStatusMessage
|
|
63
|
+
from velbusaio.messages.raw import MeteoRawMessage, SensorRawMessage
|
|
58
64
|
from velbusaio.messages.read_data_block_from_memory import (
|
|
59
65
|
ReadDataBlockFromMemoryMessage,
|
|
60
66
|
)
|
|
@@ -64,6 +70,7 @@ from velbusaio.messages.receive_buffer_full import ReceiveBufferFullMessage
|
|
|
64
70
|
from velbusaio.messages.receive_ready import ReceiveReadyMessage
|
|
65
71
|
from velbusaio.messages.relay_status import RelayStatusMessage
|
|
66
72
|
from velbusaio.messages.restore_dimmer import RestoreDimmerMessage
|
|
73
|
+
from velbusaio.messages.select_program import SelectProgramMessage
|
|
67
74
|
from velbusaio.messages.sensor_temp_request import SensorTempRequest
|
|
68
75
|
from velbusaio.messages.sensor_temperature import SensorTemperatureMessage
|
|
69
76
|
from velbusaio.messages.set_date import SetDate
|
|
@@ -83,6 +90,9 @@ from velbusaio.messages.switch_to_day import SwitchToDayMessage
|
|
|
83
90
|
from velbusaio.messages.switch_to_night import SwitchToNightMessage
|
|
84
91
|
from velbusaio.messages.switch_to_safe import SwitchToSafeMessage
|
|
85
92
|
from velbusaio.messages.temp_sensor_settings_part1 import TempSensorSettingsPart1
|
|
93
|
+
from velbusaio.messages.temp_sensor_settings_part2 import TempSensorSettingsPart2
|
|
94
|
+
from velbusaio.messages.temp_sensor_settings_part3 import TempSensorSettingsPart3
|
|
95
|
+
from velbusaio.messages.temp_sensor_settings_part4 import TempSensorSettingsPart4
|
|
86
96
|
from velbusaio.messages.temp_sensor_settings_request import TempSensorSettingsRequest
|
|
87
97
|
from velbusaio.messages.temp_sensor_status import TempSensorStatusMessage
|
|
88
98
|
from velbusaio.messages.temp_set_cooling import TempSetCoolingMessage
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
"""
|
|
2
2
|
:author: Tom Dupré <gitd8400@gmail.com>
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from __future__ import annotations
|
|
5
6
|
|
|
6
7
|
import json
|
|
7
8
|
|
|
8
|
-
from velbusaio.command_registry import
|
|
9
|
+
from velbusaio.command_registry import register
|
|
9
10
|
from velbusaio.message import Message
|
|
10
11
|
|
|
11
12
|
COMMAND_CODE = 0xEC
|
|
12
13
|
DSTATUS = {0: "off", 1: "up", 2: "down"}
|
|
13
14
|
|
|
14
15
|
|
|
16
|
+
@register(COMMAND_CODE, ["VMB1BLE", "VMB2BLE", "VMB1BLS", "VMB2BLE-10"])
|
|
15
17
|
class BlindStatusNgMessage(Message):
|
|
16
18
|
"""
|
|
17
19
|
sent by: VMB2BLE
|
|
@@ -37,7 +39,7 @@ class BlindStatusNgMessage(Message):
|
|
|
37
39
|
self.channel = self.byte_to_channel(data[0])
|
|
38
40
|
self.timeout = data[1] # Omzetter seconden ????
|
|
39
41
|
self.status = data[2]
|
|
40
|
-
self.position = data[4]
|
|
42
|
+
self.position = data[4] # 0..255 (0=open, 255=closed)
|
|
41
43
|
|
|
42
44
|
def to_json(self):
|
|
43
45
|
"""
|
|
@@ -46,21 +48,19 @@ class BlindStatusNgMessage(Message):
|
|
|
46
48
|
json_dict = self.to_json_basic()
|
|
47
49
|
json_dict["channel"] = self.channel
|
|
48
50
|
json_dict["timeout"] = self.timeout
|
|
51
|
+
json_dict["position"] = self.position
|
|
49
52
|
json_dict["status"] = DSTATUS[self.status]
|
|
50
53
|
return json.dumps(json_dict)
|
|
51
54
|
|
|
52
|
-
def
|
|
53
|
-
"""
|
|
54
|
-
:return: bool
|
|
55
|
-
"""
|
|
55
|
+
def is_moving_up(self) -> bool:
|
|
56
56
|
return self.status == 0x01
|
|
57
57
|
|
|
58
|
-
def
|
|
59
|
-
"""
|
|
60
|
-
:return: bool
|
|
61
|
-
"""
|
|
58
|
+
def is_moving_down(self) -> bool:
|
|
62
59
|
return self.status == 0x02
|
|
63
60
|
|
|
61
|
+
def is_stopped(self) -> bool:
|
|
62
|
+
return self.status == 0x00
|
|
63
|
+
|
|
64
64
|
def data_to_binary(self):
|
|
65
65
|
"""
|
|
66
66
|
:return: bytes
|
|
@@ -79,6 +79,7 @@ class BlindStatusNgMessage(Message):
|
|
|
79
79
|
)
|
|
80
80
|
|
|
81
81
|
|
|
82
|
+
@register(COMMAND_CODE, ["VMB1BL", "VMB2BL"])
|
|
82
83
|
class BlindStatusMessage(Message):
|
|
83
84
|
"""
|
|
84
85
|
sent by: VMB2BLE
|
|
@@ -107,7 +108,7 @@ class BlindStatusMessage(Message):
|
|
|
107
108
|
self.channel = self.byte_to_channel(tmp)
|
|
108
109
|
self.timeout = data[1] # Omzetter seconden ????
|
|
109
110
|
# 2 bits per channel used
|
|
110
|
-
self.status = data[2] >> ((self.channel - 1) * 2)
|
|
111
|
+
self.status = (data[2] >> ((self.channel - 1) * 2)) & 0x03
|
|
111
112
|
|
|
112
113
|
def to_json(self):
|
|
113
114
|
"""
|
|
@@ -119,21 +120,11 @@ class BlindStatusMessage(Message):
|
|
|
119
120
|
json_dict["status"] = DSTATUS[self.status]
|
|
120
121
|
return json.dumps(json_dict)
|
|
121
122
|
|
|
122
|
-
def
|
|
123
|
-
"""
|
|
124
|
-
:return: bool
|
|
125
|
-
"""
|
|
123
|
+
def is_moving_up(self) -> bool:
|
|
126
124
|
return self.status == 0x01
|
|
127
125
|
|
|
128
|
-
def
|
|
129
|
-
"""
|
|
130
|
-
:return: bool
|
|
131
|
-
"""
|
|
126
|
+
def is_moving_down(self) -> bool:
|
|
132
127
|
return self.status == 0x02
|
|
133
128
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
register_command(COMMAND_CODE, BlindStatusNgMessage, "VMB2BLE")
|
|
137
|
-
register_command(COMMAND_CODE, BlindStatusNgMessage, "VMB1BLS")
|
|
138
|
-
register_command(COMMAND_CODE, BlindStatusMessage, "VMB1BL")
|
|
139
|
-
register_command(COMMAND_CODE, BlindStatusMessage, "VMB2BL")
|
|
129
|
+
def is_stopped(self) -> bool:
|
|
130
|
+
return self.status == 0x00
|
velbusaio/messages/bus_active.py
CHANGED
|
@@ -1,20 +1,17 @@
|
|
|
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
|
|
7
|
+
from velbusaio.command_registry import register
|
|
7
8
|
from velbusaio.message import Message
|
|
8
9
|
|
|
9
10
|
COMMAND_CODE = 0x0A
|
|
10
11
|
|
|
11
12
|
|
|
13
|
+
@register(COMMAND_CODE)
|
|
12
14
|
class BusActiveMessage(Message):
|
|
13
|
-
"""
|
|
14
|
-
send by:
|
|
15
|
-
received by: VMB1USB
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
15
|
def set_defaults(self, address):
|
|
19
16
|
if address is not None:
|
|
20
17
|
self.set_address(address)
|
|
@@ -32,6 +29,3 @@ class BusActiveMessage(Message):
|
|
|
32
29
|
:return: bytes
|
|
33
30
|
"""
|
|
34
31
|
return bytes([COMMAND_CODE])
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
register_command(COMMAND_CODE, BusActiveMessage)
|
|
@@ -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
|
|
7
|
+
from velbusaio.command_registry import register
|
|
7
8
|
from velbusaio.message import Message
|
|
8
9
|
|
|
9
10
|
COMMAND_CODE = 0xDA
|
|
10
11
|
|
|
11
12
|
|
|
13
|
+
@register(COMMAND_CODE)
|
|
12
14
|
class BusErrorCounterStatusMessage(Message):
|
|
13
15
|
"""
|
|
14
16
|
send by: VMB6IN, VMB4RYLD
|
|
@@ -45,6 +47,3 @@ class BusErrorCounterStatusMessage(Message):
|
|
|
45
47
|
self.bus_off_counter,
|
|
46
48
|
]
|
|
47
49
|
)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
register_command(COMMAND_CODE, BusErrorCounterStatusMessage)
|
|
@@ -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
|
|
7
|
+
from velbusaio.command_registry import register
|
|
7
8
|
from velbusaio.message import Message
|
|
8
9
|
|
|
9
10
|
COMMAND_CODE = 0xD9
|
|
10
11
|
|
|
11
12
|
|
|
13
|
+
@register(COMMAND_CODE)
|
|
12
14
|
class BusErrorStatusRequestMessage(Message):
|
|
13
15
|
"""
|
|
14
16
|
send by:
|
|
@@ -29,6 +31,3 @@ class BusErrorStatusRequestMessage(Message):
|
|
|
29
31
|
:return: bytes
|
|
30
32
|
"""
|
|
31
33
|
return bytes([COMMAND_CODE])
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
register_command(COMMAND_CODE, BusErrorStatusRequestMessage)
|
velbusaio/messages/bus_off.py
CHANGED
|
@@ -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
|
|
7
|
+
from velbusaio.command_registry import register
|
|
7
8
|
from velbusaio.message import Message
|
|
8
9
|
|
|
9
10
|
COMMAND_CODE = 0x09
|
|
10
11
|
|
|
11
12
|
|
|
13
|
+
@register(COMMAND_CODE)
|
|
12
14
|
class BusOffMessage(Message):
|
|
13
15
|
"""
|
|
14
16
|
send by:
|
|
@@ -29,6 +31,3 @@ class BusOffMessage(Message):
|
|
|
29
31
|
:return: bytes
|
|
30
32
|
"""
|
|
31
33
|
return bytes([COMMAND_CODE])
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
register_command(COMMAND_CODE, BusOffMessage)
|
|
@@ -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
|
|
5
|
+
from __future__ import annotations
|
|
7
6
|
|
|
8
|
-
from velbusaio.command_registry import
|
|
7
|
+
from velbusaio.command_registry import register
|
|
9
8
|
from velbusaio.message import Message
|
|
10
9
|
|
|
11
10
|
COMMAND_CODE = 0xF0
|
|
12
11
|
|
|
13
12
|
|
|
13
|
+
@register(COMMAND_CODE)
|
|
14
14
|
class ChannelNamePart1Message(Message):
|
|
15
15
|
"""
|
|
16
16
|
send by: VMB6IN, VMB4RYLD
|
|
@@ -44,18 +44,54 @@ class ChannelNamePart1Message(Message):
|
|
|
44
44
|
self.name, "ascii", "ignore"
|
|
45
45
|
)
|
|
46
46
|
|
|
47
|
-
def to_json(self):
|
|
48
|
-
"""
|
|
49
|
-
:return: str
|
|
50
|
-
"""
|
|
51
|
-
json_dict = self.to_json_basic()
|
|
52
|
-
json_dict["channel"] = self.channel
|
|
53
|
-
return json.dumps(json_dict)
|
|
54
|
-
|
|
55
47
|
|
|
48
|
+
@register(
|
|
49
|
+
COMMAND_CODE,
|
|
50
|
+
[
|
|
51
|
+
"VMBGP1",
|
|
52
|
+
"VMBEL1",
|
|
53
|
+
"VMBGP1-2",
|
|
54
|
+
"VMBGP2",
|
|
55
|
+
"VMBEL2",
|
|
56
|
+
"VMBGP2-2",
|
|
57
|
+
"VMBGP4",
|
|
58
|
+
"VMBEL4",
|
|
59
|
+
"VMBGP4-2",
|
|
60
|
+
"VMBGPO",
|
|
61
|
+
"VMBGPOD",
|
|
62
|
+
"VMBGPOD-2",
|
|
63
|
+
"VMBELO",
|
|
64
|
+
"VMBGP4PIR",
|
|
65
|
+
"VMBGP4PIR-2",
|
|
66
|
+
"VMBDMI",
|
|
67
|
+
"VMBDMI-R",
|
|
68
|
+
"VMBIN",
|
|
69
|
+
"VMBKP",
|
|
70
|
+
"VMBELPIR",
|
|
71
|
+
"VMBDALI",
|
|
72
|
+
"VMB4AN",
|
|
73
|
+
"VMB6PB-20",
|
|
74
|
+
"VMBEL1-20",
|
|
75
|
+
"VMBEL2-20",
|
|
76
|
+
"VMBEL4-20",
|
|
77
|
+
"VMBELO-20",
|
|
78
|
+
"VMBGP1-20",
|
|
79
|
+
"VMBGP2-20",
|
|
80
|
+
"VMBGP4-20",
|
|
81
|
+
"VMBGPO-20",
|
|
82
|
+
"VMBDALI-20",
|
|
83
|
+
"VMBEL4PIR-20",
|
|
84
|
+
"VMBGP4PIR-20",
|
|
85
|
+
"VMB4LEDPWM-20",
|
|
86
|
+
"VMB8DC-20",
|
|
87
|
+
"VMB2DC-20",
|
|
88
|
+
"VMB8IN-20",
|
|
89
|
+
"VMBPSUMNGR-20",
|
|
90
|
+
],
|
|
91
|
+
)
|
|
56
92
|
class ChannelNamePart1Message2(ChannelNamePart1Message):
|
|
57
93
|
"""
|
|
58
|
-
send by: VMBGP
|
|
94
|
+
send by: VMBGP*, VMBDALI
|
|
59
95
|
received by:
|
|
60
96
|
"""
|
|
61
97
|
|
|
@@ -71,6 +107,7 @@ class ChannelNamePart1Message2(ChannelNamePart1Message):
|
|
|
71
107
|
self.name = "".join([chr(x) for x in data[1:]])
|
|
72
108
|
|
|
73
109
|
|
|
110
|
+
@register(COMMAND_CODE, ["VMB1BL", "VMB2BL"])
|
|
74
111
|
class ChannelNamePart1Message3(ChannelNamePart1Message):
|
|
75
112
|
"""
|
|
76
113
|
send by: VMBGP*
|
|
@@ -87,24 +124,3 @@ class ChannelNamePart1Message3(ChannelNamePart1Message):
|
|
|
87
124
|
self.set_attributes(priority, address, rtr)
|
|
88
125
|
self.channel = (data[0] >> 1) & 0x03
|
|
89
126
|
self.name = "".join([chr(x) for x in data[1:]])
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message)
|
|
93
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message2, "VMBGP1")
|
|
94
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message2, "VMBEL1")
|
|
95
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message2, "VMBGP1-2")
|
|
96
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message2, "VMBGP2")
|
|
97
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message2, "VMBEL2")
|
|
98
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message2, "VMBGP2-2")
|
|
99
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message2, "VMBGP4")
|
|
100
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message2, "VMBEL4")
|
|
101
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message2, "VMBGP4-2")
|
|
102
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message2, "VMBGPO")
|
|
103
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message2, "VMBGPOD")
|
|
104
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message2, "VMBGPOD-2")
|
|
105
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message2, "VMBELO")
|
|
106
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message2, "VMBGP4PIR")
|
|
107
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message2, "VMBDMI")
|
|
108
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message2, "VMBDMI-R")
|
|
109
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message3, "VMB1BL")
|
|
110
|
-
register_command(COMMAND_CODE, ChannelNamePart1Message3, "VMB2BL")
|