velbus-aio 2024.4.0__tar.gz → 2024.5.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-2024.4.0/velbus_aio.egg-info → velbus_aio-2024.5.1}/PKG-INFO +2 -2
- velbus_aio-2024.5.1/pyproject.toml +204 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/requirements.txt +1 -1
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1/velbus_aio.egg-info}/PKG-INFO +2 -2
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbus_aio.egg-info/requires.txt +1 -1
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/channels.py +5 -11
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/command_registry.py +12 -1
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/const.py +2 -1
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/controller.py +51 -79
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/handler.py +3 -2
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/helpers.py +1 -1
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/message.py +0 -1
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/cover_off.py +0 -2
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/cover_position.py +0 -2
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/set_date.py +4 -10
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/set_daylight_saving.py +2 -6
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/set_dimmer.py +7 -12
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/set_realtime_clock.py +4 -10
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/module.py +46 -42
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/protocol.json +9 -5
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/util.py +4 -0
- velbus-aio-2024.4.0/pyproject.toml +0 -65
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/LICENSE +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/MANIFEST.in +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/README.md +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/setup.cfg +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/setup.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbus_aio.egg-info/SOURCES.txt +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbus_aio.egg-info/dependency_links.txt +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbus_aio.egg-info/not-zip-safe +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbus_aio.egg-info/top_level.txt +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/__init__.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/discovery.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/exceptions.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/__init__.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/blind_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/bus_active.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/bus_error_counter_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/bus_error_counter_status_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/bus_off.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/channel_name_part1.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/channel_name_part2.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/channel_name_part3.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/channel_name_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/clear_led.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/counter_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/counter_status_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/cover_down.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/cover_up.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/dali_device_settings.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/dali_device_settings_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/dali_dim_value_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/dimmer_channel_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/dimmer_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/edge_set_color.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/edge_set_custom_color.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/fast_blinking_led.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/forced_off.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/forced_on.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/interface_status_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/ir_receiver_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/kwh_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/light_value_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/memo_text.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/memory_data.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/memory_data_block.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/memory_dump_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/module_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/module_status_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/module_subtype.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/module_type.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/module_type_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/push_button_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/raw.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/read_data_block_from_memory.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/read_data_from_memory.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/realtime_clock_status_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/receive_buffer_full.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/receive_ready.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/relay_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/restore_dimmer.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/select_program.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/sensor_settings_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/sensor_temp_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/sensor_temperature.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/set_led.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/set_temperature.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/slider_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/slow_blinking_led.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/start_relay_blinking_timer.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/start_relay_timer.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/switch_relay_off.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/switch_relay_on.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/switch_to_comfort.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/switch_to_day.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/switch_to_night.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/switch_to_safe.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/temp_sensor_settings_part1.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/temp_sensor_settings_part2.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/temp_sensor_settings_part3.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/temp_sensor_settings_part4.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/temp_sensor_settings_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/temp_sensor_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/temp_set_cooling.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/temp_set_heating.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/update_led_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/very_fast_blinking_led.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/write_data_to_memory.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/write_memory_block.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/messages/write_module_address_and_serial_number.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/protocol.py +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/py.typed +0 -0
- {velbus-aio-2024.4.0 → velbus_aio-2024.5.1}/velbusaio/raw_message.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: velbus-aio
|
|
3
|
-
Version: 2024.
|
|
3
|
+
Version: 2024.5.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
|
|
@@ -26,7 +26,7 @@ Requires-Python: >=3.8.0
|
|
|
26
26
|
Description-Content-Type: text/markdown
|
|
27
27
|
License-File: LICENSE
|
|
28
28
|
Requires-Dist: pyserial>=3.5.0
|
|
29
|
-
Requires-Dist: pyserial-
|
|
29
|
+
Requires-Dist: pyserial-asyncio_fast>=0.11
|
|
30
30
|
Requires-Dist: backoff>=1.10.0
|
|
31
31
|
|
|
32
32
|

|
|
@@ -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.5.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_fast>=0.11",
|
|
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.5.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: 2024.
|
|
3
|
+
Version: 2024.5.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
|
|
@@ -26,7 +26,7 @@ Requires-Python: >=3.8.0
|
|
|
26
26
|
Description-Content-Type: text/markdown
|
|
27
27
|
License-File: LICENSE
|
|
28
28
|
Requires-Dist: pyserial>=3.5.0
|
|
29
|
-
Requires-Dist: pyserial-
|
|
29
|
+
Requires-Dist: pyserial-asyncio_fast>=0.11
|
|
30
30
|
Requires-Dist: backoff>=1.10.0
|
|
31
31
|
|
|
32
32
|

|
|
@@ -136,17 +136,11 @@ class Channel:
|
|
|
136
136
|
if k != "_writer" and k != "_on_status_update" and k != "_name_parts"
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
def
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if k != "_writer"
|
|
145
|
-
and k != "_on_status_update"
|
|
146
|
-
and k != "_name_parts"
|
|
147
|
-
and k != "_module"
|
|
148
|
-
and k != "__name__"
|
|
149
|
-
}
|
|
139
|
+
def to_cache(self) -> dict:
|
|
140
|
+
dst = {"name": self._name, "type": type(self).__name__}
|
|
141
|
+
if hasattr(self, "_Unit"):
|
|
142
|
+
dst["Unit"] = self._Unit
|
|
143
|
+
return dst
|
|
150
144
|
|
|
151
145
|
def __setstate__(self, state):
|
|
152
146
|
self.__dict__.update(state)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Command registry.
|
|
2
|
+
|
|
2
3
|
:author: Maikel Punie <maikel.punie@gmail.com> and Thomas Delaet <thomas@delaet.org>
|
|
3
4
|
"""
|
|
4
5
|
|
|
@@ -87,7 +88,10 @@ MODULE_DIRECTORY = {
|
|
|
87
88
|
|
|
88
89
|
|
|
89
90
|
class CommandRegistry:
|
|
91
|
+
"""Command registry class."""
|
|
92
|
+
|
|
90
93
|
def __init__(self, module_directory: dict) -> None:
|
|
94
|
+
"""Init method."""
|
|
91
95
|
self._module_directory = module_directory
|
|
92
96
|
self._default_commands = {}
|
|
93
97
|
self._overrides = {}
|
|
@@ -95,6 +99,7 @@ class CommandRegistry:
|
|
|
95
99
|
def register_command(
|
|
96
100
|
self, command_value: int, command_class: type, module_name: str | None = None
|
|
97
101
|
) -> None:
|
|
102
|
+
"""Register a command."""
|
|
98
103
|
if command_value < 0 or command_value > 255:
|
|
99
104
|
raise ValueError("Command_value should be >=0 and <=255")
|
|
100
105
|
if module_name and module_name not in self._module_directory.values():
|
|
@@ -115,6 +120,7 @@ class CommandRegistry:
|
|
|
115
120
|
def _register_override(
|
|
116
121
|
self, command_value: int, command_class: type, module_type: str
|
|
117
122
|
) -> None:
|
|
123
|
+
"""Register and override."""
|
|
118
124
|
if module_type not in self._overrides:
|
|
119
125
|
self._overrides[module_type] = {}
|
|
120
126
|
if command_value not in self._overrides[module_type]:
|
|
@@ -125,12 +131,14 @@ class CommandRegistry:
|
|
|
125
131
|
)
|
|
126
132
|
|
|
127
133
|
def _register_default(self, command_value: int, command_class: type) -> None:
|
|
134
|
+
"""Register a default command."""
|
|
128
135
|
if command_value not in self._default_commands:
|
|
129
136
|
self._default_commands[command_value] = command_class
|
|
130
137
|
else:
|
|
131
138
|
raise Exception("double registration in command registry")
|
|
132
139
|
|
|
133
140
|
def has_command(self, command_value: int, module_type: int = 0) -> bool:
|
|
141
|
+
"""Find a command."""
|
|
134
142
|
if module_type in self._overrides:
|
|
135
143
|
if command_value in self._overrides[module_type]:
|
|
136
144
|
return True
|
|
@@ -139,6 +147,7 @@ class CommandRegistry:
|
|
|
139
147
|
return False
|
|
140
148
|
|
|
141
149
|
def get_command(self, command_value: int, module_type: int = 0) -> None | type:
|
|
150
|
+
"""Search a command in the registry."""
|
|
142
151
|
if module_type in self._overrides:
|
|
143
152
|
if command_value in self._overrides[module_type]:
|
|
144
153
|
return self._overrides[module_type][command_value]
|
|
@@ -151,6 +160,8 @@ commandRegistry = CommandRegistry(MODULE_DIRECTORY)
|
|
|
151
160
|
|
|
152
161
|
|
|
153
162
|
def register(command_value: int, module_types: list[str] | None = None):
|
|
163
|
+
"""Register decorator."""
|
|
164
|
+
|
|
154
165
|
def inner_register(command_class):
|
|
155
166
|
if module_types:
|
|
156
167
|
for module_type in module_types:
|
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Main interface for the velbusaio lib
|
|
3
|
-
"""
|
|
1
|
+
"""Main interface for the velbusaio lib."""
|
|
4
2
|
|
|
5
3
|
from __future__ import annotations
|
|
6
4
|
|
|
7
5
|
import asyncio
|
|
8
6
|
import logging
|
|
9
7
|
import pathlib
|
|
10
|
-
import pickle
|
|
11
8
|
import re
|
|
12
9
|
import ssl
|
|
10
|
+
import time
|
|
13
11
|
from urllib.parse import urlparse
|
|
14
12
|
|
|
15
13
|
import serial
|
|
16
|
-
import
|
|
14
|
+
import serial_asyncio_fast
|
|
17
15
|
|
|
18
16
|
from velbusaio.channels import Channel
|
|
19
17
|
from velbusaio.const import LOAD_TIMEOUT
|
|
@@ -31,15 +29,14 @@ from velbusaio.raw_message import RawMessage
|
|
|
31
29
|
|
|
32
30
|
|
|
33
31
|
class Velbus:
|
|
34
|
-
"""
|
|
35
|
-
A velbus controller
|
|
36
|
-
"""
|
|
32
|
+
"""A velbus controller."""
|
|
37
33
|
|
|
38
34
|
def __init__(
|
|
39
35
|
self,
|
|
40
36
|
dsn: str,
|
|
41
37
|
cache_dir: str = get_cache_dir(),
|
|
42
38
|
) -> None:
|
|
39
|
+
"""Init the Velbus controller."""
|
|
43
40
|
self._log = logging.getLogger("velbus")
|
|
44
41
|
|
|
45
42
|
self._protocol = VelbusProtocol(
|
|
@@ -60,6 +57,7 @@ class Velbus:
|
|
|
60
57
|
pathlib.Path(self._cache_dir).mkdir(parents=True, exist_ok=True)
|
|
61
58
|
|
|
62
59
|
async def _on_message_received(self, msg: RawMessage) -> None:
|
|
60
|
+
"""On message received function."""
|
|
63
61
|
await self._handler.handle(msg)
|
|
64
62
|
|
|
65
63
|
def _on_connection_lost(self, exc: Exception) -> None:
|
|
@@ -69,6 +67,7 @@ class Velbus:
|
|
|
69
67
|
asyncio.ensure_future(self.connect())
|
|
70
68
|
|
|
71
69
|
def _on_end_of_scan(self) -> None:
|
|
70
|
+
"""Notify the scan failure."""
|
|
72
71
|
self._handler.scan_finished()
|
|
73
72
|
|
|
74
73
|
async def add_module(
|
|
@@ -81,31 +80,23 @@ class Velbus:
|
|
|
81
80
|
build_year: int | None = None,
|
|
82
81
|
build_week: int | None = None,
|
|
83
82
|
) -> None:
|
|
84
|
-
"""
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
self.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
data,
|
|
99
|
-
serial=serial,
|
|
100
|
-
build_year=build_year,
|
|
101
|
-
build_week=build_week,
|
|
102
|
-
memorymap=memorymap,
|
|
103
|
-
cache_dir=self._cache_dir,
|
|
104
|
-
)
|
|
105
|
-
self._modules[addr].initialize(self.send)
|
|
106
|
-
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()
|
|
107
97
|
|
|
108
98
|
async def add_submodules(self, addr: int, subList: dict[int, int]) -> None:
|
|
99
|
+
"""Add submodules address to module."""
|
|
109
100
|
for sub_num, sub_addr in subList.items():
|
|
110
101
|
if sub_addr == 0xFF:
|
|
111
102
|
continue
|
|
@@ -114,48 +105,30 @@ class Velbus:
|
|
|
114
105
|
self._modules[sub_addr] = self._modules[addr]
|
|
115
106
|
self._modules[addr].cleanupSubChannels()
|
|
116
107
|
|
|
117
|
-
def _load_module_from_cache(self, cache_dir: str, address: int) -> None | Module:
|
|
118
|
-
try:
|
|
119
|
-
cfile = pathlib.Path(f"{cache_dir}/{address}.p")
|
|
120
|
-
with cfile.open("rb") as fl:
|
|
121
|
-
o = pickle.load(fl)
|
|
122
|
-
if isinstance(o, Module):
|
|
123
|
-
return o
|
|
124
|
-
except OSError:
|
|
125
|
-
pass
|
|
126
|
-
return None
|
|
127
|
-
|
|
128
108
|
def get_modules(self) -> dict:
|
|
129
|
-
"""
|
|
130
|
-
Return the module cache
|
|
131
|
-
"""
|
|
109
|
+
"""Return the module cache."""
|
|
132
110
|
return self._modules
|
|
133
111
|
|
|
134
112
|
def get_module(self, addr: str) -> None | Module:
|
|
135
|
-
"""
|
|
136
|
-
|
|
137
|
-
"""
|
|
138
|
-
if addr in self._modules.keys():
|
|
113
|
+
"""Get a module on an address."""
|
|
114
|
+
if addr in self._modules:
|
|
139
115
|
return self._modules[addr]
|
|
140
116
|
return None
|
|
141
117
|
|
|
142
118
|
def get_channels(self, addr: str) -> None | dict:
|
|
143
|
-
"""
|
|
144
|
-
Get the channels for an address
|
|
145
|
-
"""
|
|
119
|
+
"""Get the channels for an address."""
|
|
146
120
|
if addr in self._modules:
|
|
147
121
|
return (self._modules[addr]).get_channels()
|
|
148
122
|
return None
|
|
149
123
|
|
|
150
124
|
async def stop(self) -> None:
|
|
125
|
+
"""Stop the controller."""
|
|
151
126
|
self._closing = True
|
|
152
127
|
self._auto_reconnect = False
|
|
153
128
|
self._protocol.close()
|
|
154
129
|
|
|
155
130
|
async def connect(self, test_connect: bool = False) -> None:
|
|
156
|
-
"""
|
|
157
|
-
Connect to the bus and load all the data
|
|
158
|
-
"""
|
|
131
|
+
"""Connect to the bus and load all the data."""
|
|
159
132
|
auth = None
|
|
160
133
|
# connect to the bus
|
|
161
134
|
if ":" in self._dsn:
|
|
@@ -182,23 +155,25 @@ class Velbus:
|
|
|
182
155
|
)
|
|
183
156
|
|
|
184
157
|
except (ConnectionRefusedError, OSError) as err:
|
|
185
|
-
raise VelbusConnectionFailed
|
|
158
|
+
raise VelbusConnectionFailed from err
|
|
186
159
|
else:
|
|
187
160
|
# serial port
|
|
188
161
|
try:
|
|
189
|
-
_transport, _protocol =
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
162
|
+
_transport, _protocol = (
|
|
163
|
+
await serial_asyncio_fast.create_serial_connection(
|
|
164
|
+
asyncio.get_event_loop(),
|
|
165
|
+
lambda: self._protocol,
|
|
166
|
+
url=self._dsn,
|
|
167
|
+
baudrate=38400,
|
|
168
|
+
bytesize=serial.EIGHTBITS,
|
|
169
|
+
parity=serial.PARITY_NONE,
|
|
170
|
+
stopbits=serial.STOPBITS_ONE,
|
|
171
|
+
xonxoff=0,
|
|
172
|
+
rtscts=1,
|
|
173
|
+
)
|
|
199
174
|
)
|
|
200
175
|
except (FileNotFoundError, serial.SerialException) as err:
|
|
201
|
-
raise VelbusConnectionFailed
|
|
176
|
+
raise VelbusConnectionFailed from err
|
|
202
177
|
if test_connect:
|
|
203
178
|
return
|
|
204
179
|
# if auth is required send the auth key
|
|
@@ -209,6 +184,7 @@ class Velbus:
|
|
|
209
184
|
await self.scan()
|
|
210
185
|
|
|
211
186
|
async def scan(self) -> None:
|
|
187
|
+
"""Scan the bus."""
|
|
212
188
|
self._handler.scan_started()
|
|
213
189
|
for addr in range(1, 256):
|
|
214
190
|
msg = ModuleTypeRequestMessage(addr)
|
|
@@ -230,9 +206,7 @@ class Velbus:
|
|
|
230
206
|
)
|
|
231
207
|
|
|
232
208
|
async def _check_if_modules_are_loaded(self) -> None:
|
|
233
|
-
"""
|
|
234
|
-
Task to wait until modules are loaded
|
|
235
|
-
"""
|
|
209
|
+
"""Task to wait until modules are loaded."""
|
|
236
210
|
while True:
|
|
237
211
|
mods_loaded = 0
|
|
238
212
|
for mod in (self.get_modules()).values():
|
|
@@ -247,9 +221,7 @@ class Velbus:
|
|
|
247
221
|
await asyncio.sleep(15)
|
|
248
222
|
|
|
249
223
|
async def send(self, msg: Message) -> None:
|
|
250
|
-
"""
|
|
251
|
-
Send a packet
|
|
252
|
-
"""
|
|
224
|
+
"""Send a packet."""
|
|
253
225
|
await self._protocol.send_message(
|
|
254
226
|
RawMessage(
|
|
255
227
|
priority=msg.priority,
|
|
@@ -260,6 +232,7 @@ class Velbus:
|
|
|
260
232
|
)
|
|
261
233
|
|
|
262
234
|
def get_all(self, class_name: str) -> list[Channel]:
|
|
235
|
+
"""Get all channels."""
|
|
263
236
|
lst = []
|
|
264
237
|
for addr, mod in (self.get_modules()).items():
|
|
265
238
|
if addr in self._submodules:
|
|
@@ -270,9 +243,8 @@ class Velbus:
|
|
|
270
243
|
return lst
|
|
271
244
|
|
|
272
245
|
async def sync_clock(self) -> None:
|
|
273
|
-
"""
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
await self.send(
|
|
277
|
-
await self.send(
|
|
278
|
-
await self.send(SetDaylightSaving())
|
|
246
|
+
"""Will send all the needed messages to sync the clock."""
|
|
247
|
+
lclt = time.localtime()
|
|
248
|
+
await self.send(SetRealtimeClock(wday=lclt[6], hour=lclt[3], min=lclt[4]))
|
|
249
|
+
await self.send(SetDate(day=lclt[2], mon=lclt[1], year=lclt[0]))
|
|
250
|
+
await self.send(SetDaylightSaving(ds=not lclt[8]))
|
|
@@ -8,7 +8,6 @@ from __future__ import annotations
|
|
|
8
8
|
import asyncio
|
|
9
9
|
import json
|
|
10
10
|
import logging
|
|
11
|
-
import re
|
|
12
11
|
from typing import TYPE_CHECKING, Awaitable, Callable
|
|
13
12
|
import pkg_resources
|
|
14
13
|
|
|
@@ -105,7 +104,9 @@ class PacketHandler:
|
|
|
105
104
|
else:
|
|
106
105
|
self._log.warning(
|
|
107
106
|
"NOT FOUND IN command_registry: addr={} cmd={} packet={}".format(
|
|
108
|
-
address,
|
|
107
|
+
address,
|
|
108
|
+
command_value,
|
|
109
|
+
":".join(format(x, "02x") for x in data),
|
|
109
110
|
)
|
|
110
111
|
)
|
|
111
112
|
elif self._scan_complete:
|