velbus-aio 2024.4.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-2024.4.0/velbus_aio.egg-info → velbus-aio-2024.4.1}/PKG-INFO +1 -1
- velbus-aio-2024.4.1/pyproject.toml +204 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1/velbus_aio.egg-info}/PKG-INFO +1 -1
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/channels.py +2 -11
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/command_registry.py +12 -1
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/const.py +2 -1
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/controller.py +38 -68
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/handler.py +3 -2
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/helpers.py +1 -1
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/message.py +0 -1
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/cover_off.py +0 -2
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/cover_position.py +0 -2
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_date.py +4 -10
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_daylight_saving.py +2 -6
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_realtime_clock.py +4 -10
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/module.py +33 -27
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/protocol.json +9 -5
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/util.py +4 -0
- velbus-aio-2024.4.0/pyproject.toml +0 -65
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/LICENSE +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/MANIFEST.in +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/README.md +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/requirements.txt +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/setup.cfg +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/setup.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbus_aio.egg-info/SOURCES.txt +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbus_aio.egg-info/dependency_links.txt +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbus_aio.egg-info/not-zip-safe +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbus_aio.egg-info/requires.txt +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbus_aio.egg-info/top_level.txt +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/__init__.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/discovery.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/exceptions.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/__init__.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/blind_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/bus_active.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/bus_error_counter_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/bus_error_counter_status_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/bus_off.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/channel_name_part1.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/channel_name_part2.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/channel_name_part3.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/channel_name_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/clear_led.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/counter_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/counter_status_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/cover_down.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/cover_up.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/dali_device_settings.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/dali_device_settings_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/dali_dim_value_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/dimmer_channel_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/dimmer_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/edge_set_color.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/edge_set_custom_color.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/fast_blinking_led.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/forced_off.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/forced_on.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/interface_status_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/ir_receiver_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/kwh_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/light_value_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/memo_text.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/memory_data.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/memory_data_block.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/memory_dump_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/module_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/module_status_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/module_subtype.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/module_type.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/module_type_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/push_button_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/raw.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/read_data_block_from_memory.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/read_data_from_memory.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/realtime_clock_status_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/receive_buffer_full.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/receive_ready.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/relay_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/restore_dimmer.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/select_program.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/sensor_settings_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/sensor_temp_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/sensor_temperature.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_dimmer.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_led.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_temperature.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/slider_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/slow_blinking_led.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/start_relay_blinking_timer.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/start_relay_timer.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_relay_off.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_relay_on.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_to_comfort.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_to_day.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_to_night.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_to_safe.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_settings_part1.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_settings_part2.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_settings_part3.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_settings_part4.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_settings_request.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_set_cooling.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_set_heating.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/update_led_status.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/very_fast_blinking_led.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/write_data_to_memory.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/write_memory_block.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/write_module_address_and_serial_number.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/protocol.py +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/py.typed +0 -0
- {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/raw_message.py +0 -0
|
@@ -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
|
|
@@ -136,17 +136,8 @@ class Channel:
|
|
|
136
136
|
if k != "_writer" and k != "_on_status_update" and k != "_name_parts"
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
def
|
|
140
|
-
|
|
141
|
-
return {
|
|
142
|
-
k: d[k]
|
|
143
|
-
for k in d
|
|
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
|
+
return {"name": self._name, "type": type(self).__name__}
|
|
150
141
|
|
|
151
142
|
def __setstate__(self, state):
|
|
152
143
|
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,15 +1,13 @@
|
|
|
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
|
|
@@ -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,7 +155,7 @@ 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:
|
|
@@ -198,7 +171,7 @@ class Velbus:
|
|
|
198
171
|
rtscts=1,
|
|
199
172
|
)
|
|
200
173
|
except (FileNotFoundError, serial.SerialException) as err:
|
|
201
|
-
raise VelbusConnectionFailed
|
|
174
|
+
raise VelbusConnectionFailed from err
|
|
202
175
|
if test_connect:
|
|
203
176
|
return
|
|
204
177
|
# if auth is required send the auth key
|
|
@@ -209,6 +182,7 @@ class Velbus:
|
|
|
209
182
|
await self.scan()
|
|
210
183
|
|
|
211
184
|
async def scan(self) -> None:
|
|
185
|
+
"""Scan the bus."""
|
|
212
186
|
self._handler.scan_started()
|
|
213
187
|
for addr in range(1, 256):
|
|
214
188
|
msg = ModuleTypeRequestMessage(addr)
|
|
@@ -230,9 +204,7 @@ class Velbus:
|
|
|
230
204
|
)
|
|
231
205
|
|
|
232
206
|
async def _check_if_modules_are_loaded(self) -> None:
|
|
233
|
-
"""
|
|
234
|
-
Task to wait until modules are loaded
|
|
235
|
-
"""
|
|
207
|
+
"""Task to wait until modules are loaded."""
|
|
236
208
|
while True:
|
|
237
209
|
mods_loaded = 0
|
|
238
210
|
for mod in (self.get_modules()).values():
|
|
@@ -247,9 +219,7 @@ class Velbus:
|
|
|
247
219
|
await asyncio.sleep(15)
|
|
248
220
|
|
|
249
221
|
async def send(self, msg: Message) -> None:
|
|
250
|
-
"""
|
|
251
|
-
Send a packet
|
|
252
|
-
"""
|
|
222
|
+
"""Send a packet."""
|
|
253
223
|
await self._protocol.send_message(
|
|
254
224
|
RawMessage(
|
|
255
225
|
priority=msg.priority,
|
|
@@ -260,6 +230,7 @@ class Velbus:
|
|
|
260
230
|
)
|
|
261
231
|
|
|
262
232
|
def get_all(self, class_name: str) -> list[Channel]:
|
|
233
|
+
"""Get all channels."""
|
|
263
234
|
lst = []
|
|
264
235
|
for addr, mod in (self.get_modules()).items():
|
|
265
236
|
if addr in self._submodules:
|
|
@@ -270,9 +241,8 @@ class Velbus:
|
|
|
270
241
|
return lst
|
|
271
242
|
|
|
272
243
|
async def sync_clock(self) -> None:
|
|
273
|
-
"""
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
await self.send(
|
|
277
|
-
await self.send(
|
|
278
|
-
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]))
|
|
@@ -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:
|
|
@@ -4,8 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
-
import time
|
|
8
|
-
|
|
9
7
|
from velbusaio.command_registry import register
|
|
10
8
|
from velbusaio.message import Message
|
|
11
9
|
|
|
@@ -18,11 +16,11 @@ class SetDate(Message):
|
|
|
18
16
|
received by all modules
|
|
19
17
|
"""
|
|
20
18
|
|
|
21
|
-
def __init__(self, address=0x00) -> None:
|
|
19
|
+
def __init__(self, address=0x00, day=None, mon=None, year=None) -> None:
|
|
22
20
|
Message.__init__(self)
|
|
23
|
-
self._day =
|
|
24
|
-
self._mon =
|
|
25
|
-
self._year =
|
|
21
|
+
self._day = day
|
|
22
|
+
self._mon = mon
|
|
23
|
+
self._year = year
|
|
26
24
|
self.set_defaults(address)
|
|
27
25
|
|
|
28
26
|
def set_defaults(self, address) -> None:
|
|
@@ -30,10 +28,6 @@ class SetDate(Message):
|
|
|
30
28
|
self.set_address(address)
|
|
31
29
|
self.set_low_priority()
|
|
32
30
|
self.set_no_rtr()
|
|
33
|
-
lclt = time.localtime()
|
|
34
|
-
self._day = lclt[2]
|
|
35
|
-
self._mon = lclt[1]
|
|
36
|
-
self._year = lclt[0]
|
|
37
31
|
|
|
38
32
|
def populate(self, priority, address, rtr, data) -> None:
|
|
39
33
|
"""
|
|
@@ -4,8 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
-
import time
|
|
8
|
-
|
|
9
7
|
from velbusaio.command_registry import register
|
|
10
8
|
from velbusaio.message import Message
|
|
11
9
|
|
|
@@ -18,9 +16,9 @@ class SetDaylightSaving(Message):
|
|
|
18
16
|
received by all modules
|
|
19
17
|
"""
|
|
20
18
|
|
|
21
|
-
def __init__(self, address=0x00) -> None:
|
|
19
|
+
def __init__(self, address=0x00, ds=None) -> None:
|
|
22
20
|
Message.__init__(self)
|
|
23
|
-
self._ds =
|
|
21
|
+
self._ds = ds
|
|
24
22
|
self.set_defaults(address)
|
|
25
23
|
|
|
26
24
|
def set_defaults(self, address) -> None:
|
|
@@ -28,8 +26,6 @@ class SetDaylightSaving(Message):
|
|
|
28
26
|
self.set_address(address)
|
|
29
27
|
self.set_low_priority()
|
|
30
28
|
self.set_no_rtr()
|
|
31
|
-
lclt = time.localtime()
|
|
32
|
-
self._ds = not lclt[8]
|
|
33
29
|
|
|
34
30
|
def populate(self, priority, address, rtr, data) -> None:
|
|
35
31
|
"""
|