velbus-aio 2025.4.2__py3-none-any.whl → 2025.5.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.
Potentially problematic release.
This version of velbus-aio might be problematic. Click here for more details.
- {velbus_aio-2025.4.2.dist-info → velbus_aio-2025.5.0.dist-info}/METADATA +1 -1
- {velbus_aio-2025.4.2.dist-info → velbus_aio-2025.5.0.dist-info}/RECORD +12 -12
- {velbus_aio-2025.4.2.dist-info → velbus_aio-2025.5.0.dist-info}/WHEEL +1 -1
- velbusaio/handler.py +1 -1
- velbusaio/messages/dali_dim_value_status.py +1 -1
- velbusaio/messages/dimmer_status.py +12 -1
- velbusaio/messages/module_type.py +7 -3
- velbusaio/module.py +7 -0
- velbusaio/module_spec/17.json +11 -1
- velbusaio/vlp_reader.py +102 -22
- {velbus_aio-2025.4.2.dist-info → velbus_aio-2025.5.0.dist-info}/licenses/LICENSE +0 -0
- {velbus_aio-2025.4.2.dist-info → velbus_aio-2025.5.0.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
velbus_aio-2025.
|
|
1
|
+
velbus_aio-2025.5.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
2
2
|
velbusaio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
velbusaio/channels.py,sha256=pR-y7Res_MAPSFEM62eLx844HU0EjX7SyyEpJT4YU74,23556
|
|
4
4
|
velbusaio/command_registry.py,sha256=nlx4__0ASr5WurOYLC-HEqswlg_qm3Y5trs4V8FhnvU,5350
|
|
@@ -6,15 +6,15 @@ velbusaio/const.py,sha256=aHClMaMS6NINTCrjeRwLbVzdvS91VgFKM8j61ks5tn0,1862
|
|
|
6
6
|
velbusaio/controller.py,sha256=Ohc-18ydnm76-5fOD_b24Aa_uYu6CdkI3ulfhska5og,8887
|
|
7
7
|
velbusaio/discovery.py,sha256=Px6qoZl4QhF17aMz6JxstCORBpLzZGWEK9h4Vyvg57o,1649
|
|
8
8
|
velbusaio/exceptions.py,sha256=FHkXaM3dK5Gkk-QGAf9dLE3FPlCU2FRZWUyY-4KRNnA,515
|
|
9
|
-
velbusaio/handler.py,sha256=
|
|
9
|
+
velbusaio/handler.py,sha256=DmL6dTbolJUD9yRaeKj1vr29eSx4zkDwVtS8fPeAs8I,11906
|
|
10
10
|
velbusaio/helpers.py,sha256=iqpoereRH4JY5WAkozIqWvXWyRmhko-J-UGXDylFyEM,2537
|
|
11
11
|
velbusaio/message.py,sha256=_MRuI4XnMcqeduCDJ3AwhAPL1B8VMstFDnjjLo8QuxM,5018
|
|
12
|
-
velbusaio/module.py,sha256=
|
|
12
|
+
velbusaio/module.py,sha256=pfYaUgMrbhYCWle8byqjYZvMhw2ikE-Ff5uAxKhY59w,37938
|
|
13
13
|
velbusaio/protocol.py,sha256=RIpdL0vPlL4qE4bC8sEZSD0SRS4tWtR9MdzjTPSd2zs,8002
|
|
14
14
|
velbusaio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
velbusaio/raw_message.py,sha256=ODoTPVAvyXXQSMXxtQO1U5OxcoQ4W8JJN5fotEDGSTo,4690
|
|
16
16
|
velbusaio/util.py,sha256=FW6YCiPYWOCgqHDs8-LbzME0h81mqftYVG0qqZ-oo7Y,1568
|
|
17
|
-
velbusaio/vlp_reader.py,sha256=
|
|
17
|
+
velbusaio/vlp_reader.py,sha256=2oSbBOR2bgaSGnL1JP8TJaHgbY20ZgmCfSivtINuiR8,3997
|
|
18
18
|
velbusaio/messages/__init__.py,sha256=2Zgrk4VBoSJXKYhwS18gxuiE96jDvnpBBjeYI1yHjqs,6072
|
|
19
19
|
velbusaio/messages/blind_status.py,sha256=q2CQgcU1ZsXMyjR2co8Eegj0LZRDfRqvpCTVvjovNWA,3432
|
|
20
20
|
velbusaio/messages/bus_active.py,sha256=AB1mEvbMXRuOaC2CQ7hzKSLmbaJnyFqqXrARi-aSdtg,749
|
|
@@ -35,9 +35,9 @@ velbusaio/messages/cover_position.py,sha256=_BgQz3DqZGirXDthj7xq72hxr51FYv2tyrdC
|
|
|
35
35
|
velbusaio/messages/cover_up.py,sha256=iFPCWuRhIc54oMQAFz5DZsUW23673_nNHoPFJC_HA_c,2561
|
|
36
36
|
velbusaio/messages/dali_device_settings.py,sha256=KzJ7OFkFRPuCXSOThuplM48J_kH0I3RE82ZRCpmiqYA,4870
|
|
37
37
|
velbusaio/messages/dali_device_settings_request.py,sha256=InTnrwLD7l9gCHXKlJ69FHMXcejtYMUZBtnffx9nDQU,1476
|
|
38
|
-
velbusaio/messages/dali_dim_value_status.py,sha256=
|
|
38
|
+
velbusaio/messages/dali_dim_value_status.py,sha256=MS3bWgBYUsQ9w7jrRRUI8QoQmziTVCYExfweAezT2E0,1089
|
|
39
39
|
velbusaio/messages/dimmer_channel_status.py,sha256=v3VszfQoPY05Dt3yzyWIlOJTKSXE1IP044x1x_sLHj4,2501
|
|
40
|
-
velbusaio/messages/dimmer_status.py,sha256=
|
|
40
|
+
velbusaio/messages/dimmer_status.py,sha256=AikJN-jfdFy8rXrGMSMfrhFcYE1yHlorffxk-bcKCXU,3067
|
|
41
41
|
velbusaio/messages/edge_set_color.py,sha256=YhxTv-WtDrZ_O67Ro6V-bcHrxj3tyBI1GuzTI5LkIVw,3306
|
|
42
42
|
velbusaio/messages/edge_set_custom_color.py,sha256=Lz-7prBveqPwuDWv2Mn13X9TAXGBEquw8xz2_y9NtTk,1338
|
|
43
43
|
velbusaio/messages/fast_blinking_led.py,sha256=_AaG6NcjzG_cBNARogzu56l7DNpGU11XGrDHIkMuKss,909
|
|
@@ -54,7 +54,7 @@ velbusaio/messages/memory_dump_request.py,sha256=xrPsdpygD9DUF3lp-BzJacuq1dNkqz2
|
|
|
54
54
|
velbusaio/messages/module_status.py,sha256=Y2OQUzijtA27snTEVHlyoOrcaLQbSq_3KHKAVDLGR_o,6662
|
|
55
55
|
velbusaio/messages/module_status_request.py,sha256=s3h8F6Dpmjcb4hqDQKIzdOgocW1F_st40cctcW7WmQ4,961
|
|
56
56
|
velbusaio/messages/module_subtype.py,sha256=KG-OC0eW-ZRnP1P8EWmcay6O-no6Mn2cklEjokaIW9M,1487
|
|
57
|
-
velbusaio/messages/module_type.py,sha256=
|
|
57
|
+
velbusaio/messages/module_type.py,sha256=re4DSM0YZF3Jm-rv6cSYoX24gxTZSgM6COmjkjpA6P8,4372
|
|
58
58
|
velbusaio/messages/module_type_request.py,sha256=fntMYCF1WVwSseCy3zRoZQH6JeGz8JDfTkwHC3AvcB4,754
|
|
59
59
|
velbusaio/messages/psu_load.py,sha256=001KIz84CbnC54gHxhfAiNbcEMRpVUBzDwQ7T-yxY8s,1232
|
|
60
60
|
velbusaio/messages/psu_values.py,sha256=Yd_ndU8yIei7CoL2NV6FHCefO5h_gzRsPNUYxGUGP0o,1300
|
|
@@ -121,7 +121,7 @@ velbusaio/module_spec/13.json,sha256=reXGXbaTfVVmLekrXHlfzjsV424bb0ozG7q-PxDv27U
|
|
|
121
121
|
velbusaio/module_spec/14.json,sha256=ym2T2jCds-lC7QBZr7mqb0L9PlSmQflwpFnlEDxByjk,161
|
|
122
122
|
velbusaio/module_spec/15.json,sha256=VDkI3bJRZgpfAsCiEzRJls7Hj7spmaKZ6XR8TjyymAQ,2698
|
|
123
123
|
velbusaio/module_spec/16.json,sha256=9sdbNwyQQRkGsd477Oyu279tRcSydQC0bGwSQrhnVTU,3459
|
|
124
|
-
velbusaio/module_spec/17.json,sha256=
|
|
124
|
+
velbusaio/module_spec/17.json,sha256=bLZ7JDt58vZUxPT6JY1xYeWWb1-jHkOhpBRUghjkQSA,3714
|
|
125
125
|
velbusaio/module_spec/18.json,sha256=ylZ7_86DYCkHxk40ZqsGYEkLeUslZ_-b_ftUihfJ2bQ,3484
|
|
126
126
|
velbusaio/module_spec/1A.json,sha256=dvIxgufmgIhZhsBuVEa27KmukJyvnFciorqpxwRNWFM,2581
|
|
127
127
|
velbusaio/module_spec/1B.json,sha256=JbHvdmoRnsqyqhCItsTOP-UK_Yz_ha1Km9CXDe68YVc,3159
|
|
@@ -184,7 +184,7 @@ velbusaio/module_spec/5C.json,sha256=yw_XlccuFp-buRL_NXThwQLwblVRa0diLpUDm9Exrg0
|
|
|
184
184
|
velbusaio/module_spec/5F.json,sha256=ebSwLMUW5A4LCRGOrF-vwxSVvrWZMNUWz10Xrmz7SwM,1259
|
|
185
185
|
velbusaio/module_spec/60.json,sha256=Teih3jAybl5AELjY3gFbZrFN0RIMSU1yuvdsYZlMvTo,74
|
|
186
186
|
velbusaio/module_spec/broadcast.json,sha256=L2Sc9FhZ7NOuu7K5g5jAhvUQGDP6a2CKrg-uWh_v-sA,2250
|
|
187
|
-
velbus_aio-2025.
|
|
188
|
-
velbus_aio-2025.
|
|
189
|
-
velbus_aio-2025.
|
|
190
|
-
velbus_aio-2025.
|
|
187
|
+
velbus_aio-2025.5.0.dist-info/METADATA,sha256=-oLAazmVHGSg3lWfQHYa6dKIZ2JKt3qtqG5EKT1B1Lo,4562
|
|
188
|
+
velbus_aio-2025.5.0.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
|
|
189
|
+
velbus_aio-2025.5.0.dist-info/top_level.txt,sha256=W0-lSOwD23mm8FqaIe9vY20fKicBMIdUVjF-zmfxRnY,15
|
|
190
|
+
velbus_aio-2025.5.0.dist-info/RECORD,,
|
velbusaio/handler.py
CHANGED
|
@@ -139,7 +139,7 @@ class PacketHandler:
|
|
|
139
139
|
if module is not None:
|
|
140
140
|
try:
|
|
141
141
|
self._log.debug(
|
|
142
|
-
f"Module {module.
|
|
142
|
+
f"Module {module.get_address()} detected: start loading"
|
|
143
143
|
)
|
|
144
144
|
await asyncio.wait_for(
|
|
145
145
|
module.load(from_cache=True),
|
|
@@ -10,7 +10,7 @@ from velbusaio.message import Message
|
|
|
10
10
|
COMMAND_CODE = 0xA5
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
@register(COMMAND_CODE, ["VMBDALI", "VMBDALI-20"])
|
|
13
|
+
@register(COMMAND_CODE, ["VMBDALI", "VMBDALI-20", "VMB8DC-20", "VMB4LEDPWM-20"])
|
|
14
14
|
class DimValueStatus(Message):
|
|
15
15
|
"""
|
|
16
16
|
send by: VMBDALI
|
|
@@ -25,7 +25,18 @@ LED_FAST_BLINKING = 1 << 5
|
|
|
25
25
|
LED_VERY_FAST_BLINKING = 1 << 4
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
@register(
|
|
28
|
+
@register(
|
|
29
|
+
COMMAND_CODE,
|
|
30
|
+
[
|
|
31
|
+
"VMB1DM",
|
|
32
|
+
"VMBDME",
|
|
33
|
+
"VMB1LED",
|
|
34
|
+
"VMBDALI",
|
|
35
|
+
"VMBDALI-20",
|
|
36
|
+
"VMB8DC-20",
|
|
37
|
+
"VMB4LEDPWM-20",
|
|
38
|
+
],
|
|
39
|
+
)
|
|
29
40
|
class DimmerStatusMessage(Message):
|
|
30
41
|
"""
|
|
31
42
|
sent by: VMBDME
|
|
@@ -6,7 +6,7 @@ from __future__ import annotations
|
|
|
6
6
|
|
|
7
7
|
import struct
|
|
8
8
|
|
|
9
|
-
from velbusaio.command_registry import register
|
|
9
|
+
from velbusaio.command_registry import MODULE_DIRECTORY, register
|
|
10
10
|
from velbusaio.message import Message
|
|
11
11
|
|
|
12
12
|
COMMAND_CODE = 0xFF
|
|
@@ -110,11 +110,15 @@ class ModuleTypeMessage(Message):
|
|
|
110
110
|
self.build_week = 0
|
|
111
111
|
self.set_defaults(address)
|
|
112
112
|
|
|
113
|
-
def
|
|
113
|
+
def module_type_name(self) -> str:
|
|
114
114
|
"""
|
|
115
115
|
:return: str
|
|
116
116
|
"""
|
|
117
|
-
return
|
|
117
|
+
return (
|
|
118
|
+
MODULE_DIRECTORY[self.module_type]
|
|
119
|
+
if self.module_type in MODULE_DIRECTORY
|
|
120
|
+
else "Unknown"
|
|
121
|
+
)
|
|
118
122
|
|
|
119
123
|
def populate(self, priority, address, rtr, data) -> None:
|
|
120
124
|
"""
|
velbusaio/module.py
CHANGED
|
@@ -243,6 +243,9 @@ class Module:
|
|
|
243
243
|
d["channels"][num] = chan.to_cache()
|
|
244
244
|
return d
|
|
245
245
|
|
|
246
|
+
def get_address(self) -> int:
|
|
247
|
+
return self._address
|
|
248
|
+
|
|
246
249
|
def get_addresses(self) -> list:
|
|
247
250
|
"""
|
|
248
251
|
Get all addresses for this module
|
|
@@ -550,6 +553,10 @@ class Module:
|
|
|
550
553
|
await self._update_channel(
|
|
551
554
|
message.channel, {"power": message.power, "energy": message.energy}
|
|
552
555
|
)
|
|
556
|
+
elif isinstance(message, DimValueStatus):
|
|
557
|
+
for offset, dim_value in enumerate(message.dim_values):
|
|
558
|
+
channel = message.channel + offset
|
|
559
|
+
await self._update_channel(channel, {"state": dim_value})
|
|
553
560
|
|
|
554
561
|
async def _update_channel(self, channel: int, updates: dict):
|
|
555
562
|
try:
|
velbusaio/module_spec/17.json
CHANGED
|
@@ -113,7 +113,17 @@
|
|
|
113
113
|
"03FE": { "ModuleName": "62" },
|
|
114
114
|
"03FF": { "ModuleName": "64:Save" }
|
|
115
115
|
},
|
|
116
|
-
"ModuleName": "03C0-03FF"
|
|
116
|
+
"ModuleName": "03C0-03FF",
|
|
117
|
+
"Channels": {
|
|
118
|
+
"01": "0000-000F",
|
|
119
|
+
"02": "0010-001F",
|
|
120
|
+
"03": "0020-002F",
|
|
121
|
+
"04": "0030-003F",
|
|
122
|
+
"05": "0040-004F",
|
|
123
|
+
"06": "0050-005F",
|
|
124
|
+
"07": "0060-006F",
|
|
125
|
+
"08": "0070-007F"
|
|
126
|
+
}
|
|
117
127
|
},
|
|
118
128
|
"Type": "VMB6PBN"
|
|
119
129
|
}
|
velbusaio/vlp_reader.py
CHANGED
|
@@ -1,33 +1,113 @@
|
|
|
1
|
+
import importlib.resources
|
|
2
|
+
import json
|
|
3
|
+
import logging
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
from aiofile import async_open
|
|
1
7
|
from bs4 import BeautifulSoup
|
|
2
8
|
|
|
9
|
+
from velbusaio.command_registry import MODULE_DIRECTORY
|
|
10
|
+
from velbusaio.helpers import h2
|
|
11
|
+
|
|
3
12
|
|
|
4
13
|
class vlpFile:
|
|
5
14
|
|
|
6
15
|
def __init__(self, file_path) -> None:
|
|
7
16
|
self._file_path = file_path
|
|
8
|
-
self._soup = None
|
|
9
17
|
self._modules = {}
|
|
10
|
-
self.
|
|
11
|
-
|
|
12
|
-
|
|
18
|
+
self._log = logging.getLogger("velbus-vlpFile")
|
|
19
|
+
|
|
20
|
+
def get(self) -> dict:
|
|
21
|
+
return self._modules
|
|
13
22
|
|
|
14
|
-
def
|
|
23
|
+
async def read(self) -> None:
|
|
15
24
|
with open(self._file_path) as file:
|
|
16
25
|
xml_content = file.read()
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
_soup = BeautifulSoup(xml_content, "xml")
|
|
27
|
+
for module in _soup.find_all("Module"):
|
|
28
|
+
self._modules[module["address"]] = vlpModule(
|
|
29
|
+
module.find("Caption").get_text(),
|
|
30
|
+
module["address"],
|
|
31
|
+
module["build"],
|
|
32
|
+
module["serial"],
|
|
33
|
+
module["type"],
|
|
34
|
+
module.find("Memory").get_text(),
|
|
35
|
+
)
|
|
36
|
+
await self._modules[module["address"]].load_module_spec()
|
|
37
|
+
print(self._modules[module["address"]].get_channel_name(1))
|
|
38
|
+
print(self._modules[module["address"]].get_channel_name(2))
|
|
39
|
+
print(self._modules[module["address"]].get_channel_name(3))
|
|
40
|
+
print(self._modules[module["address"]].get_channel_name(4))
|
|
41
|
+
print(self._modules[module["address"]].get_channel_name(5))
|
|
42
|
+
print(self._modules[module["address"]].get_channel_name(10))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class vlpModule:
|
|
46
|
+
|
|
47
|
+
def __init__(self, name, addresses, build, serial, type, memory) -> None:
|
|
48
|
+
self._name = name
|
|
49
|
+
self._addresses = addresses
|
|
50
|
+
self._build = build
|
|
51
|
+
self._serial = serial
|
|
52
|
+
self._type = type
|
|
53
|
+
self._memory = memory
|
|
54
|
+
self._spec = {}
|
|
55
|
+
self._type_id = next(
|
|
56
|
+
(key for key, value in MODULE_DIRECTORY.items() if value == self._type),
|
|
57
|
+
None,
|
|
58
|
+
)
|
|
59
|
+
self._log = logging.getLogger("velbus-vlpFile")
|
|
60
|
+
|
|
61
|
+
def get(self) -> dict:
|
|
62
|
+
return {
|
|
63
|
+
"name": self._name,
|
|
64
|
+
"addresses": self._addresses,
|
|
65
|
+
"build": self._build,
|
|
66
|
+
"serial": self._serial,
|
|
67
|
+
"type": self._type,
|
|
68
|
+
"memory": self._memory,
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
def get_name(self) -> str:
|
|
72
|
+
return self._name
|
|
73
|
+
|
|
74
|
+
def get_channel_name(self, chan: int) -> str | None:
|
|
75
|
+
self._log.debug(f"get_channel_name: {chan}")
|
|
76
|
+
if "Memory" not in self._spec:
|
|
77
|
+
self._log.debug(" => no Memory locations found")
|
|
78
|
+
return None
|
|
79
|
+
if "Channels" not in self._spec["Memory"]:
|
|
80
|
+
self._log.debug(" => no Channels Memory locations found")
|
|
81
|
+
return None
|
|
82
|
+
if h2(chan) not in self._spec["Memory"]["Channels"]:
|
|
83
|
+
self._log.debug(f" => no chan {chan} Memory locations found")
|
|
84
|
+
return None
|
|
85
|
+
byte_data = bytes.fromhex(
|
|
86
|
+
self._read_from_memory(self._spec["Memory"]["Channels"][h2(chan)]).replace(
|
|
87
|
+
"FF", ""
|
|
88
|
+
)
|
|
89
|
+
)
|
|
90
|
+
return byte_data.decode("ascii")
|
|
91
|
+
|
|
92
|
+
async def load_module_spec(self) -> None:
|
|
93
|
+
if sys.version_info >= (3, 13):
|
|
94
|
+
with importlib.resources.path(
|
|
95
|
+
__name__, f"module_spec/{h2(self._type_id)}.json"
|
|
96
|
+
) as fspath:
|
|
97
|
+
async with async_open(fspath) as protocol_file:
|
|
98
|
+
self._spec = json.loads(await protocol_file.read())
|
|
99
|
+
else:
|
|
100
|
+
async with async_open(
|
|
101
|
+
str(
|
|
102
|
+
importlib.resources.files(__name__.split(".")[0]).joinpath(
|
|
103
|
+
f"module_spec/{h2(self._type)}.json"
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
) as protocol_file:
|
|
107
|
+
self._spec = json.loads(await protocol_file.read())
|
|
108
|
+
|
|
109
|
+
def _read_from_memory(self, address_range) -> str | None:
|
|
110
|
+
start_str, end_str = address_range.split("-")
|
|
111
|
+
start = int(start_str, 16) * 2
|
|
112
|
+
end = (int(end_str, 16) + 1) * 2
|
|
113
|
+
return self._memory[start:end]
|
|
File without changes
|
|
File without changes
|