velbus-aio 2023.12.0__tar.gz → 2024.4.1__tar.gz
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-2023.12.0 → velbus-aio-2024.4.1}/MANIFEST.in +1 -1
- {velbus-aio-2023.12.0/velbus_aio.egg-info → velbus-aio-2024.4.1}/PKG-INFO +2 -1
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/README.md +1 -0
- velbus-aio-2024.4.1/pyproject.toml +204 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1/velbus_aio.egg-info}/PKG-INFO +2 -1
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbus_aio.egg-info/SOURCES.txt +2 -2
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/channels.py +7 -11
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/command_registry.py +15 -1
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/const.py +3 -1
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/controller.py +39 -68
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/handler.py +5 -61
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/helpers.py +2 -1
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/message.py +1 -1
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/__init__.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/blind_status.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/bus_active.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/bus_error_counter_status.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/bus_error_counter_status_request.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/bus_off.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/channel_name_part1.py +15 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/channel_name_part2.py +14 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/channel_name_part3.py +14 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/channel_name_request.py +2 -1
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/clear_led.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/counter_status.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/counter_status_request.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/cover_down.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/cover_off.py +1 -2
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/cover_position.py +1 -2
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/cover_up.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/dali_device_settings.py +2 -1
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/dali_device_settings_request.py +2 -1
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/dali_dim_value_status.py +2 -1
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/dimmer_channel_status.py +2 -1
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/dimmer_status.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/edge_set_custom_color.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/fast_blinking_led.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/forced_off.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/forced_on.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/interface_status_request.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/ir_receiver_status.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/kwh_status.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/light_value_request.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/memo_text.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/memory_data.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/memory_data_block.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/memory_dump_request.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/module_status.py +12 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/module_status_request.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/module_subtype.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/module_type.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/module_type_request.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/push_button_status.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/raw.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/read_data_block_from_memory.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/read_data_from_memory.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/realtime_clock_status_request.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/receive_buffer_full.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/receive_ready.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/relay_status.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/restore_dimmer.py +6 -2
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/select_program.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/sensor_settings_request.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/sensor_temp_request.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/sensor_temperature.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_date.py +5 -10
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_daylight_saving.py +3 -6
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_dimmer.py +6 -2
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_led.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_realtime_clock.py +5 -10
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_temperature.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/slider_status.py +5 -1
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/slow_blinking_led.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/start_relay_blinking_timer.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/start_relay_timer.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_relay_off.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_relay_on.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_to_comfort.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_to_day.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_to_night.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_to_safe.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_settings_part1.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_settings_part2.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_settings_part3.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_settings_part4.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_settings_request.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_status.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_set_cooling.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_set_heating.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/update_led_status.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/very_fast_blinking_led.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/write_data_to_memory.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/write_memory_block.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/write_module_address_and_serial_number.py +1 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/module.py +44 -43
- velbus-aio-2024.4.1/velbusaio/protocol.json +10126 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/protocol.py +2 -2
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/raw_message.py +6 -6
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/util.py +4 -0
- velbus-aio-2023.12.0/pyproject.toml +0 -65
- velbus-aio-2023.12.0/velbusaio/moduleprotocol/protocol.json +0 -26507
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/LICENSE +0 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/requirements.txt +0 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/setup.cfg +0 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/setup.py +0 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbus_aio.egg-info/dependency_links.txt +0 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbus_aio.egg-info/not-zip-safe +0 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbus_aio.egg-info/requires.txt +0 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbus_aio.egg-info/top_level.txt +0 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/__init__.py +0 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/discovery.py +0 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/exceptions.py +0 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/messages/edge_set_color.py +0 -0
- {velbus-aio-2023.12.0 → velbus-aio-2024.4.1}/velbusaio/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: velbus-aio
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2024.4.1
|
|
4
4
|
Summary: Open-source home automation platform running on Python 3.
|
|
5
5
|
Author-email: Maikel Punie <maikel.punie@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -30,6 +30,7 @@ Requires-Dist: pyserial-asyncio>=0.5
|
|
|
30
30
|
Requires-Dist: backoff>=1.10.0
|
|
31
31
|
|
|
32
32
|

|
|
33
|
+
[](https://results.pre-commit.ci/latest/github/Cereal2nd/velbus-aio/master)
|
|
33
34
|
|
|
34
35
|
# velbus-aio
|
|
35
36
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|

|
|
2
|
+
[](https://results.pre-commit.ci/latest/github/Cereal2nd/velbus-aio/master)
|
|
2
3
|
|
|
3
4
|
# velbus-aio
|
|
4
5
|
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools", "wheel"]
|
|
3
|
+
|
|
4
|
+
[project]
|
|
5
|
+
name = "velbus-aio"
|
|
6
|
+
license = {text = "MIT"}
|
|
7
|
+
version = "2024.4.1"
|
|
8
|
+
description = "Open-source home automation platform running on Python 3."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [
|
|
11
|
+
{name = "Maikel Punie", email = "maikel.punie@gmail.com"}
|
|
12
|
+
]
|
|
13
|
+
keywords = ["home", "velbus", "automation"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 5 - Production/Stable",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Natural Language :: English",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python",
|
|
21
|
+
"Programming Language :: Python :: 3.8",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: Home Automation",
|
|
27
|
+
"Topic :: Software Development :: Libraries",
|
|
28
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
29
|
+
]
|
|
30
|
+
requires-python = ">=3.8.0"
|
|
31
|
+
dependencies = [
|
|
32
|
+
"pyserial>=3.5.0",
|
|
33
|
+
"pyserial-asyncio>=0.5",
|
|
34
|
+
"backoff>=1.10.0",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.urls]
|
|
38
|
+
"Source Code" = "https://github.com/Cereal2nd/velbus-aio"
|
|
39
|
+
"Bug Reports" = "https://github.com/Cereal2nd/velbus-aio/issues"
|
|
40
|
+
|
|
41
|
+
[tool.setuptools]
|
|
42
|
+
platforms = ["any"]
|
|
43
|
+
zip-safe = false
|
|
44
|
+
include-package-data = true
|
|
45
|
+
|
|
46
|
+
[tool.setuptools.packages.find]
|
|
47
|
+
exclude = ["tests", "tests.*", "examples"]
|
|
48
|
+
|
|
49
|
+
[tool.bandit]
|
|
50
|
+
exclude_dirs = ["tests"]
|
|
51
|
+
skips = ["B301", "B403", "B323", "B104", "B110"]
|
|
52
|
+
|
|
53
|
+
[tool.bumpver]
|
|
54
|
+
current_version = "2024.4.1"
|
|
55
|
+
version_pattern = "YYYY.MM.INC0"
|
|
56
|
+
commit_message = "bump version {old_version} -> {new_version}"
|
|
57
|
+
commit = true
|
|
58
|
+
tag = true
|
|
59
|
+
push = true
|
|
60
|
+
|
|
61
|
+
[tool.bumpver.file_patterns]
|
|
62
|
+
"pyproject.toml" = [
|
|
63
|
+
'^version = "{version}"',
|
|
64
|
+
'^current_version = "{version}"',
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
[tool.ruff]
|
|
68
|
+
required-version = ">=0.3.4"
|
|
69
|
+
|
|
70
|
+
[tool.ruff.lint]
|
|
71
|
+
select = [
|
|
72
|
+
"B002", # Python does not support the unary prefix increment
|
|
73
|
+
"B005", # Using .strip() with multi-character strings is misleading
|
|
74
|
+
"B007", # Loop control variable {name} not used within loop body
|
|
75
|
+
"B014", # Exception handler with duplicate exception
|
|
76
|
+
"B015", # Pointless comparison. Did you mean to assign a value? Otherwise, prepend assert or remove it.
|
|
77
|
+
"B018", # Found useless attribute access. Either assign it to a variable or remove it.
|
|
78
|
+
"B023", # Function definition does not bind loop variable {name}
|
|
79
|
+
"B026", # Star-arg unpacking after a keyword argument is strongly discouraged
|
|
80
|
+
"B032", # Possible unintentional type annotation (using :). Did you mean to assign (using =)?
|
|
81
|
+
"B904", # Use raise from to specify exception cause
|
|
82
|
+
"C", # complexity
|
|
83
|
+
"COM818", # Trailing comma on bare tuple prohibited
|
|
84
|
+
"D", # docstrings
|
|
85
|
+
"DTZ003", # Use datetime.now(tz=) instead of datetime.utcnow()
|
|
86
|
+
"DTZ004", # Use datetime.fromtimestamp(ts, tz=) instead of datetime.utcfromtimestamp(ts)
|
|
87
|
+
"E", # pycodestyle
|
|
88
|
+
"F", # pyflakes/autoflake
|
|
89
|
+
"G", # flake8-logging-format
|
|
90
|
+
"I", # isort
|
|
91
|
+
"ISC", # flake8-implicit-str-concat
|
|
92
|
+
"ICN001", # import concentions; {name} should be imported as {asname}
|
|
93
|
+
"LOG", # flake8-logging
|
|
94
|
+
"N804", # First argument of a class method should be named cls
|
|
95
|
+
"N805", # First argument of a method should be named self
|
|
96
|
+
"N815", # Variable {name} in class scope should not be mixedCase
|
|
97
|
+
"PERF", # Perflint
|
|
98
|
+
"PGH004", # Use specific rule codes when using noqa
|
|
99
|
+
"PIE", # flake8-pie
|
|
100
|
+
"PL", # pylint
|
|
101
|
+
"PT", # flake8-pytest-style
|
|
102
|
+
"RET", # flake8-return
|
|
103
|
+
"RSE", # flake8-raise
|
|
104
|
+
"RUF005", # Consider iterable unpacking instead of concatenation
|
|
105
|
+
"RUF006", # Store a reference to the return value of asyncio.create_task
|
|
106
|
+
# "RUF100", # Unused `noqa` directive; temporarily every now and then to clean them up
|
|
107
|
+
"S102", # Use of exec detected
|
|
108
|
+
"S103", # bad-file-permissions
|
|
109
|
+
"S108", # hardcoded-temp-file
|
|
110
|
+
"S306", # suspicious-mktemp-usage
|
|
111
|
+
"S307", # suspicious-eval-usage
|
|
112
|
+
"S313", # suspicious-xmlc-element-tree-usage
|
|
113
|
+
"S314", # suspicious-xml-element-tree-usage
|
|
114
|
+
"S315", # suspicious-xml-expat-reader-usage
|
|
115
|
+
"S316", # suspicious-xml-expat-builder-usage
|
|
116
|
+
"S317", # suspicious-xml-sax-usage
|
|
117
|
+
"S318", # suspicious-xml-mini-dom-usage
|
|
118
|
+
"S319", # suspicious-xml-pull-dom-usage
|
|
119
|
+
"S320", # suspicious-xmle-tree-usage
|
|
120
|
+
"S601", # paramiko-call
|
|
121
|
+
"S602", # subprocess-popen-with-shell-equals-true
|
|
122
|
+
"S604", # call-with-shell-equals-true
|
|
123
|
+
"S608", # hardcoded-sql-expression
|
|
124
|
+
"S609", # unix-command-wildcard-injection
|
|
125
|
+
"SIM", # flake8-simplify
|
|
126
|
+
"T100", # Trace found: {name} used
|
|
127
|
+
"T20", # flake8-print
|
|
128
|
+
"TID251", # Banned imports
|
|
129
|
+
"TRY", # tryceratops
|
|
130
|
+
"UP", # pyupgrade
|
|
131
|
+
"W", # pycodestyle
|
|
132
|
+
]
|
|
133
|
+
ignore = [
|
|
134
|
+
"D202", # No blank lines allowed after function docstring
|
|
135
|
+
"D203", # 1 blank line required before class docstring
|
|
136
|
+
"D213", # Multi-line docstring summary should start at the second line
|
|
137
|
+
"D406", # Section name should end with a newline
|
|
138
|
+
"D407", # Section name underlining
|
|
139
|
+
"E501", # line too long
|
|
140
|
+
"E731", # do not assign a lambda expression, use a def
|
|
141
|
+
|
|
142
|
+
"PLC1901", # {existing} can be simplified to {replacement} as an empty string is falsey; too many false positives
|
|
143
|
+
"PLR0911", # Too many return statements ({returns} > {max_returns})
|
|
144
|
+
"PLR0912", # Too many branches ({branches} > {max_branches})
|
|
145
|
+
"PLR0913", # Too many arguments to function call ({c_args} > {max_args})
|
|
146
|
+
"PLR0915", # Too many statements ({statements} > {max_statements})
|
|
147
|
+
"PLR2004", # Magic value used in comparison, consider replacing {value} with a constant variable
|
|
148
|
+
"PLW2901", # Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target
|
|
149
|
+
"PT004", # Fixture {fixture} does not return anything, add leading underscore
|
|
150
|
+
"PT011", # pytest.raises({exception}) is too broad, set the `match` parameter or use a more specific exception
|
|
151
|
+
"PT012", # `pytest.raises()` block should contain a single simple statement
|
|
152
|
+
"PT018", # Assertion should be broken down into multiple parts
|
|
153
|
+
"SIM102", # Use a single if statement instead of nested if statements
|
|
154
|
+
"SIM108", # Use ternary operator {contents} instead of if-else-block
|
|
155
|
+
"SIM115", # Use context handler for opening files
|
|
156
|
+
"TRY003", # Avoid specifying long messages outside the exception class
|
|
157
|
+
"TRY400", # Use `logging.exception` instead of `logging.error`
|
|
158
|
+
"UP006", # keep type annotation style as is
|
|
159
|
+
"UP007", # keep type annotation style as is
|
|
160
|
+
# Ignored due to performance: https://github.com/charliermarsh/ruff/issues/2923
|
|
161
|
+
"UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)`
|
|
162
|
+
# Ignored due to incompatible with mypy: https://github.com/python/mypy/issues/15238
|
|
163
|
+
"UP040", # Checks for use of TypeAlias annotation for declaring type aliases.
|
|
164
|
+
|
|
165
|
+
# May conflict with the formatter, https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
|
|
166
|
+
"W191",
|
|
167
|
+
"E111",
|
|
168
|
+
"E114",
|
|
169
|
+
"E117",
|
|
170
|
+
"D206",
|
|
171
|
+
"D300",
|
|
172
|
+
"Q",
|
|
173
|
+
"COM812",
|
|
174
|
+
"COM819",
|
|
175
|
+
"ISC001",
|
|
176
|
+
|
|
177
|
+
# Disabled because ruff does not understand type of __all__ generated by a function
|
|
178
|
+
"PLE0605",
|
|
179
|
+
|
|
180
|
+
# temporarily disabled
|
|
181
|
+
"PT019",
|
|
182
|
+
"RET504",
|
|
183
|
+
"RET503",
|
|
184
|
+
"RET502",
|
|
185
|
+
"RET501",
|
|
186
|
+
"TRY002",
|
|
187
|
+
"TRY301"
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
[tool.ruff.lint.flake8-pytest-style]
|
|
191
|
+
fixture-parentheses = false
|
|
192
|
+
mark-parentheses = false
|
|
193
|
+
|
|
194
|
+
[tool.ruff.lint.flake8-tidy-imports.banned-api]
|
|
195
|
+
"async_timeout".msg = "use asyncio.timeout instead"
|
|
196
|
+
"pytz".msg = "use zoneinfo instead"
|
|
197
|
+
|
|
198
|
+
[tool.ruff.lint.isort]
|
|
199
|
+
force-sort-within-sections = true
|
|
200
|
+
combine-as-imports = true
|
|
201
|
+
split-on-trailing-comma = false
|
|
202
|
+
|
|
203
|
+
[tool.ruff.lint.mccabe]
|
|
204
|
+
max-complexity = 25
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: velbus-aio
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2024.4.1
|
|
4
4
|
Summary: Open-source home automation platform running on Python 3.
|
|
5
5
|
Author-email: Maikel Punie <maikel.punie@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -30,6 +30,7 @@ Requires-Dist: pyserial-asyncio>=0.5
|
|
|
30
30
|
Requires-Dist: backoff>=1.10.0
|
|
31
31
|
|
|
32
32
|

|
|
33
|
+
[](https://results.pre-commit.ci/latest/github/Cereal2nd/velbus-aio/master)
|
|
33
34
|
|
|
34
35
|
# velbus-aio
|
|
35
36
|
|
|
@@ -21,6 +21,7 @@ velbusaio/handler.py
|
|
|
21
21
|
velbusaio/helpers.py
|
|
22
22
|
velbusaio/message.py
|
|
23
23
|
velbusaio/module.py
|
|
24
|
+
velbusaio/protocol.json
|
|
24
25
|
velbusaio/protocol.py
|
|
25
26
|
velbusaio/py.typed
|
|
26
27
|
velbusaio/raw_message.py
|
|
@@ -106,5 +107,4 @@ velbusaio/messages/update_led_status.py
|
|
|
106
107
|
velbusaio/messages/very_fast_blinking_led.py
|
|
107
108
|
velbusaio/messages/write_data_to_memory.py
|
|
108
109
|
velbusaio/messages/write_memory_block.py
|
|
109
|
-
velbusaio/messages/write_module_address_and_serial_number.py
|
|
110
|
-
velbusaio/moduleprotocol/protocol.json
|
|
110
|
+
velbusaio/messages/write_module_address_and_serial_number.py
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
author: Maikel Punie <maikel.punie@gmail.com>
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from __future__ import annotations
|
|
5
6
|
|
|
6
7
|
import asyncio
|
|
@@ -135,17 +136,8 @@ class Channel:
|
|
|
135
136
|
if k != "_writer" and k != "_on_status_update" and k != "_name_parts"
|
|
136
137
|
}
|
|
137
138
|
|
|
138
|
-
def
|
|
139
|
-
|
|
140
|
-
return {
|
|
141
|
-
k: d[k]
|
|
142
|
-
for k in d
|
|
143
|
-
if k != "_writer"
|
|
144
|
-
and k != "_on_status_update"
|
|
145
|
-
and k != "_name_parts"
|
|
146
|
-
and k != "_module"
|
|
147
|
-
and k != "__name__"
|
|
148
|
-
}
|
|
139
|
+
def to_cache(self) -> dict:
|
|
140
|
+
return {"name": self._name, "type": type(self).__name__}
|
|
149
141
|
|
|
150
142
|
def __setstate__(self, state):
|
|
151
143
|
self.__dict__.update(state)
|
|
@@ -276,6 +268,10 @@ class Blind(Channel):
|
|
|
276
268
|
|
|
277
269
|
async def set_position(self, position: int) -> None:
|
|
278
270
|
# may not be supported by the module
|
|
271
|
+
if position == 100:
|
|
272
|
+
# at least VMB1BLS ignores command 0x1C with position 0x64
|
|
273
|
+
await self.close()
|
|
274
|
+
return
|
|
279
275
|
cls = commandRegistry.get_command(0x1C, self._module.get_type())
|
|
280
276
|
msg = cls(self._address)
|
|
281
277
|
msg.channel = self._num
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Command registry.
|
|
2
|
+
|
|
2
3
|
:author: Maikel Punie <maikel.punie@gmail.com> and Thomas Delaet <thomas@delaet.org>
|
|
3
4
|
"""
|
|
5
|
+
|
|
4
6
|
from __future__ import annotations
|
|
5
7
|
|
|
6
8
|
MODULE_DIRECTORY = {
|
|
7
9
|
0x01: "VMB8PB",
|
|
8
10
|
0x02: "VMB1RY",
|
|
9
11
|
0x03: "VMB1BL",
|
|
12
|
+
0x04: "VMB4LEDPWM-20",
|
|
10
13
|
0x05: "VMB6IN",
|
|
11
14
|
0x07: "VMB1DM",
|
|
12
15
|
0x08: "VMB4RY",
|
|
@@ -68,6 +71,7 @@ MODULE_DIRECTORY = {
|
|
|
68
71
|
0x48: "VMB4RYLD-10",
|
|
69
72
|
0x49: "VMB4RYNO-10",
|
|
70
73
|
0x4A: "VMB2BLE-10",
|
|
74
|
+
0x4B: "VMB8DC-20",
|
|
71
75
|
0x4C: "VMB6PB-20",
|
|
72
76
|
0x4F: "VMBEL1-20",
|
|
73
77
|
0x50: "VMBEL2-20",
|
|
@@ -84,7 +88,10 @@ MODULE_DIRECTORY = {
|
|
|
84
88
|
|
|
85
89
|
|
|
86
90
|
class CommandRegistry:
|
|
91
|
+
"""Command registry class."""
|
|
92
|
+
|
|
87
93
|
def __init__(self, module_directory: dict) -> None:
|
|
94
|
+
"""Init method."""
|
|
88
95
|
self._module_directory = module_directory
|
|
89
96
|
self._default_commands = {}
|
|
90
97
|
self._overrides = {}
|
|
@@ -92,6 +99,7 @@ class CommandRegistry:
|
|
|
92
99
|
def register_command(
|
|
93
100
|
self, command_value: int, command_class: type, module_name: str | None = None
|
|
94
101
|
) -> None:
|
|
102
|
+
"""Register a command."""
|
|
95
103
|
if command_value < 0 or command_value > 255:
|
|
96
104
|
raise ValueError("Command_value should be >=0 and <=255")
|
|
97
105
|
if module_name and module_name not in self._module_directory.values():
|
|
@@ -112,6 +120,7 @@ class CommandRegistry:
|
|
|
112
120
|
def _register_override(
|
|
113
121
|
self, command_value: int, command_class: type, module_type: str
|
|
114
122
|
) -> None:
|
|
123
|
+
"""Register and override."""
|
|
115
124
|
if module_type not in self._overrides:
|
|
116
125
|
self._overrides[module_type] = {}
|
|
117
126
|
if command_value not in self._overrides[module_type]:
|
|
@@ -122,12 +131,14 @@ class CommandRegistry:
|
|
|
122
131
|
)
|
|
123
132
|
|
|
124
133
|
def _register_default(self, command_value: int, command_class: type) -> None:
|
|
134
|
+
"""Register a default command."""
|
|
125
135
|
if command_value not in self._default_commands:
|
|
126
136
|
self._default_commands[command_value] = command_class
|
|
127
137
|
else:
|
|
128
138
|
raise Exception("double registration in command registry")
|
|
129
139
|
|
|
130
140
|
def has_command(self, command_value: int, module_type: int = 0) -> bool:
|
|
141
|
+
"""Find a command."""
|
|
131
142
|
if module_type in self._overrides:
|
|
132
143
|
if command_value in self._overrides[module_type]:
|
|
133
144
|
return True
|
|
@@ -136,6 +147,7 @@ class CommandRegistry:
|
|
|
136
147
|
return False
|
|
137
148
|
|
|
138
149
|
def get_command(self, command_value: int, module_type: int = 0) -> None | type:
|
|
150
|
+
"""Search a command in the registry."""
|
|
139
151
|
if module_type in self._overrides:
|
|
140
152
|
if command_value in self._overrides[module_type]:
|
|
141
153
|
return self._overrides[module_type][command_value]
|
|
@@ -148,6 +160,8 @@ commandRegistry = CommandRegistry(MODULE_DIRECTORY)
|
|
|
148
160
|
|
|
149
161
|
|
|
150
162
|
def register(command_value: int, module_types: list[str] | None = None):
|
|
163
|
+
"""Register decorator."""
|
|
164
|
+
|
|
151
165
|
def inner_register(command_class):
|
|
152
166
|
if module_types:
|
|
153
167
|
for module_type in module_types:
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
3
|
-
"""
|
|
1
|
+
"""Main interface for the velbusaio lib."""
|
|
2
|
+
|
|
4
3
|
from __future__ import annotations
|
|
5
4
|
|
|
6
5
|
import asyncio
|
|
7
6
|
import logging
|
|
8
7
|
import pathlib
|
|
9
|
-
import pickle
|
|
10
8
|
import re
|
|
11
9
|
import ssl
|
|
10
|
+
import time
|
|
12
11
|
from urllib.parse import urlparse
|
|
13
12
|
|
|
14
13
|
import serial
|
|
@@ -30,15 +29,14 @@ from velbusaio.raw_message import RawMessage
|
|
|
30
29
|
|
|
31
30
|
|
|
32
31
|
class Velbus:
|
|
33
|
-
"""
|
|
34
|
-
A velbus controller
|
|
35
|
-
"""
|
|
32
|
+
"""A velbus controller."""
|
|
36
33
|
|
|
37
34
|
def __init__(
|
|
38
35
|
self,
|
|
39
36
|
dsn: str,
|
|
40
37
|
cache_dir: str = get_cache_dir(),
|
|
41
38
|
) -> None:
|
|
39
|
+
"""Init the Velbus controller."""
|
|
42
40
|
self._log = logging.getLogger("velbus")
|
|
43
41
|
|
|
44
42
|
self._protocol = VelbusProtocol(
|
|
@@ -59,6 +57,7 @@ class Velbus:
|
|
|
59
57
|
pathlib.Path(self._cache_dir).mkdir(parents=True, exist_ok=True)
|
|
60
58
|
|
|
61
59
|
async def _on_message_received(self, msg: RawMessage) -> None:
|
|
60
|
+
"""On message received function."""
|
|
62
61
|
await self._handler.handle(msg)
|
|
63
62
|
|
|
64
63
|
def _on_connection_lost(self, exc: Exception) -> None:
|
|
@@ -68,6 +67,7 @@ class Velbus:
|
|
|
68
67
|
asyncio.ensure_future(self.connect())
|
|
69
68
|
|
|
70
69
|
def _on_end_of_scan(self) -> None:
|
|
70
|
+
"""Notify the scan failure."""
|
|
71
71
|
self._handler.scan_finished()
|
|
72
72
|
|
|
73
73
|
async def add_module(
|
|
@@ -80,31 +80,23 @@ class Velbus:
|
|
|
80
80
|
build_year: int | None = None,
|
|
81
81
|
build_week: int | None = None,
|
|
82
82
|
) -> None:
|
|
83
|
-
"""
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
self.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
data,
|
|
98
|
-
serial=serial,
|
|
99
|
-
build_year=build_year,
|
|
100
|
-
build_week=build_week,
|
|
101
|
-
memorymap=memorymap,
|
|
102
|
-
cache_dir=self._cache_dir,
|
|
103
|
-
)
|
|
104
|
-
self._modules[addr].initialize(self.send)
|
|
105
|
-
await self._modules[addr].load()
|
|
83
|
+
"""Add a found module to the module cache."""
|
|
84
|
+
self._log.info(f"Found module: type:{typ} address:{addr}")
|
|
85
|
+
self._modules[addr] = Module.factory(
|
|
86
|
+
addr,
|
|
87
|
+
typ,
|
|
88
|
+
data,
|
|
89
|
+
serial=serial,
|
|
90
|
+
build_year=build_year,
|
|
91
|
+
build_week=build_week,
|
|
92
|
+
memorymap=memorymap,
|
|
93
|
+
cache_dir=self._cache_dir,
|
|
94
|
+
)
|
|
95
|
+
self._modules[addr].initialize(self.send)
|
|
96
|
+
await self._modules[addr].load()
|
|
106
97
|
|
|
107
98
|
async def add_submodules(self, addr: int, subList: dict[int, int]) -> None:
|
|
99
|
+
"""Add submodules address to module."""
|
|
108
100
|
for sub_num, sub_addr in subList.items():
|
|
109
101
|
if sub_addr == 0xFF:
|
|
110
102
|
continue
|
|
@@ -113,48 +105,30 @@ class Velbus:
|
|
|
113
105
|
self._modules[sub_addr] = self._modules[addr]
|
|
114
106
|
self._modules[addr].cleanupSubChannels()
|
|
115
107
|
|
|
116
|
-
def _load_module_from_cache(self, cache_dir: str, address: int) -> None | Module:
|
|
117
|
-
try:
|
|
118
|
-
cfile = pathlib.Path(f"{cache_dir}/{address}.p")
|
|
119
|
-
with cfile.open("rb") as fl:
|
|
120
|
-
o = pickle.load(fl)
|
|
121
|
-
if isinstance(o, Module):
|
|
122
|
-
return o
|
|
123
|
-
except OSError:
|
|
124
|
-
pass
|
|
125
|
-
return None
|
|
126
|
-
|
|
127
108
|
def get_modules(self) -> dict:
|
|
128
|
-
"""
|
|
129
|
-
Return the module cache
|
|
130
|
-
"""
|
|
109
|
+
"""Return the module cache."""
|
|
131
110
|
return self._modules
|
|
132
111
|
|
|
133
112
|
def get_module(self, addr: str) -> None | Module:
|
|
134
|
-
"""
|
|
135
|
-
|
|
136
|
-
"""
|
|
137
|
-
if addr in self._modules.keys():
|
|
113
|
+
"""Get a module on an address."""
|
|
114
|
+
if addr in self._modules:
|
|
138
115
|
return self._modules[addr]
|
|
139
116
|
return None
|
|
140
117
|
|
|
141
118
|
def get_channels(self, addr: str) -> None | dict:
|
|
142
|
-
"""
|
|
143
|
-
Get the channels for an address
|
|
144
|
-
"""
|
|
119
|
+
"""Get the channels for an address."""
|
|
145
120
|
if addr in self._modules:
|
|
146
121
|
return (self._modules[addr]).get_channels()
|
|
147
122
|
return None
|
|
148
123
|
|
|
149
124
|
async def stop(self) -> None:
|
|
125
|
+
"""Stop the controller."""
|
|
150
126
|
self._closing = True
|
|
151
127
|
self._auto_reconnect = False
|
|
152
128
|
self._protocol.close()
|
|
153
129
|
|
|
154
130
|
async def connect(self, test_connect: bool = False) -> None:
|
|
155
|
-
"""
|
|
156
|
-
Connect to the bus and load all the data
|
|
157
|
-
"""
|
|
131
|
+
"""Connect to the bus and load all the data."""
|
|
158
132
|
auth = None
|
|
159
133
|
# connect to the bus
|
|
160
134
|
if ":" in self._dsn:
|
|
@@ -181,7 +155,7 @@ class Velbus:
|
|
|
181
155
|
)
|
|
182
156
|
|
|
183
157
|
except (ConnectionRefusedError, OSError) as err:
|
|
184
|
-
raise VelbusConnectionFailed
|
|
158
|
+
raise VelbusConnectionFailed from err
|
|
185
159
|
else:
|
|
186
160
|
# serial port
|
|
187
161
|
try:
|
|
@@ -197,7 +171,7 @@ class Velbus:
|
|
|
197
171
|
rtscts=1,
|
|
198
172
|
)
|
|
199
173
|
except (FileNotFoundError, serial.SerialException) as err:
|
|
200
|
-
raise VelbusConnectionFailed
|
|
174
|
+
raise VelbusConnectionFailed from err
|
|
201
175
|
if test_connect:
|
|
202
176
|
return
|
|
203
177
|
# if auth is required send the auth key
|
|
@@ -208,6 +182,7 @@ class Velbus:
|
|
|
208
182
|
await self.scan()
|
|
209
183
|
|
|
210
184
|
async def scan(self) -> None:
|
|
185
|
+
"""Scan the bus."""
|
|
211
186
|
self._handler.scan_started()
|
|
212
187
|
for addr in range(1, 256):
|
|
213
188
|
msg = ModuleTypeRequestMessage(addr)
|
|
@@ -229,9 +204,7 @@ class Velbus:
|
|
|
229
204
|
)
|
|
230
205
|
|
|
231
206
|
async def _check_if_modules_are_loaded(self) -> None:
|
|
232
|
-
"""
|
|
233
|
-
Task to wait until modules are loaded
|
|
234
|
-
"""
|
|
207
|
+
"""Task to wait until modules are loaded."""
|
|
235
208
|
while True:
|
|
236
209
|
mods_loaded = 0
|
|
237
210
|
for mod in (self.get_modules()).values():
|
|
@@ -246,9 +219,7 @@ class Velbus:
|
|
|
246
219
|
await asyncio.sleep(15)
|
|
247
220
|
|
|
248
221
|
async def send(self, msg: Message) -> None:
|
|
249
|
-
"""
|
|
250
|
-
Send a packet
|
|
251
|
-
"""
|
|
222
|
+
"""Send a packet."""
|
|
252
223
|
await self._protocol.send_message(
|
|
253
224
|
RawMessage(
|
|
254
225
|
priority=msg.priority,
|
|
@@ -259,6 +230,7 @@ class Velbus:
|
|
|
259
230
|
)
|
|
260
231
|
|
|
261
232
|
def get_all(self, class_name: str) -> list[Channel]:
|
|
233
|
+
"""Get all channels."""
|
|
262
234
|
lst = []
|
|
263
235
|
for addr, mod in (self.get_modules()).items():
|
|
264
236
|
if addr in self._submodules:
|
|
@@ -269,9 +241,8 @@ class Velbus:
|
|
|
269
241
|
return lst
|
|
270
242
|
|
|
271
243
|
async def sync_clock(self) -> None:
|
|
272
|
-
"""
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
await self.send(
|
|
276
|
-
await self.send(
|
|
277
|
-
await self.send(SetDaylightSaving())
|
|
244
|
+
"""Will send all the needed messages to sync the clock."""
|
|
245
|
+
lclt = time.localtime()
|
|
246
|
+
await self.send(SetRealtimeClock(wday=lclt[6], hour=lclt[3], min=lclt[4]))
|
|
247
|
+
await self.send(SetDate(day=lclt[2], mon=lclt[1], year=lclt[0]))
|
|
248
|
+
await self.send(SetDaylightSaving(ds=not lclt[8]))
|