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.

Files changed (113) hide show
  1. {velbus-aio-2024.4.0/velbus_aio.egg-info → velbus-aio-2024.4.1}/PKG-INFO +1 -1
  2. velbus-aio-2024.4.1/pyproject.toml +204 -0
  3. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1/velbus_aio.egg-info}/PKG-INFO +1 -1
  4. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/channels.py +2 -11
  5. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/command_registry.py +12 -1
  6. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/const.py +2 -1
  7. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/controller.py +38 -68
  8. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/handler.py +3 -2
  9. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/helpers.py +1 -1
  10. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/message.py +0 -1
  11. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/cover_off.py +0 -2
  12. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/cover_position.py +0 -2
  13. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_date.py +4 -10
  14. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_daylight_saving.py +2 -6
  15. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_realtime_clock.py +4 -10
  16. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/module.py +33 -27
  17. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/protocol.json +9 -5
  18. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/util.py +4 -0
  19. velbus-aio-2024.4.0/pyproject.toml +0 -65
  20. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/LICENSE +0 -0
  21. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/MANIFEST.in +0 -0
  22. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/README.md +0 -0
  23. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/requirements.txt +0 -0
  24. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/setup.cfg +0 -0
  25. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/setup.py +0 -0
  26. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbus_aio.egg-info/SOURCES.txt +0 -0
  27. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbus_aio.egg-info/dependency_links.txt +0 -0
  28. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbus_aio.egg-info/not-zip-safe +0 -0
  29. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbus_aio.egg-info/requires.txt +0 -0
  30. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbus_aio.egg-info/top_level.txt +0 -0
  31. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/__init__.py +0 -0
  32. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/discovery.py +0 -0
  33. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/exceptions.py +0 -0
  34. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/__init__.py +0 -0
  35. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/blind_status.py +0 -0
  36. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/bus_active.py +0 -0
  37. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/bus_error_counter_status.py +0 -0
  38. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/bus_error_counter_status_request.py +0 -0
  39. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/bus_off.py +0 -0
  40. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/channel_name_part1.py +0 -0
  41. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/channel_name_part2.py +0 -0
  42. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/channel_name_part3.py +0 -0
  43. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/channel_name_request.py +0 -0
  44. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/clear_led.py +0 -0
  45. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/counter_status.py +0 -0
  46. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/counter_status_request.py +0 -0
  47. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/cover_down.py +0 -0
  48. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/cover_up.py +0 -0
  49. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/dali_device_settings.py +0 -0
  50. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/dali_device_settings_request.py +0 -0
  51. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/dali_dim_value_status.py +0 -0
  52. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/dimmer_channel_status.py +0 -0
  53. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/dimmer_status.py +0 -0
  54. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/edge_set_color.py +0 -0
  55. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/edge_set_custom_color.py +0 -0
  56. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/fast_blinking_led.py +0 -0
  57. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/forced_off.py +0 -0
  58. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/forced_on.py +0 -0
  59. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/interface_status_request.py +0 -0
  60. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/ir_receiver_status.py +0 -0
  61. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/kwh_status.py +0 -0
  62. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/light_value_request.py +0 -0
  63. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/memo_text.py +0 -0
  64. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/memory_data.py +0 -0
  65. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/memory_data_block.py +0 -0
  66. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/memory_dump_request.py +0 -0
  67. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/module_status.py +0 -0
  68. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/module_status_request.py +0 -0
  69. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/module_subtype.py +0 -0
  70. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/module_type.py +0 -0
  71. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/module_type_request.py +0 -0
  72. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/push_button_status.py +0 -0
  73. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/raw.py +0 -0
  74. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/read_data_block_from_memory.py +0 -0
  75. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/read_data_from_memory.py +0 -0
  76. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/realtime_clock_status_request.py +0 -0
  77. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/receive_buffer_full.py +0 -0
  78. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/receive_ready.py +0 -0
  79. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/relay_status.py +0 -0
  80. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/restore_dimmer.py +0 -0
  81. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/select_program.py +0 -0
  82. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/sensor_settings_request.py +0 -0
  83. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/sensor_temp_request.py +0 -0
  84. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/sensor_temperature.py +0 -0
  85. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_dimmer.py +0 -0
  86. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_led.py +0 -0
  87. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/set_temperature.py +0 -0
  88. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/slider_status.py +0 -0
  89. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/slow_blinking_led.py +0 -0
  90. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/start_relay_blinking_timer.py +0 -0
  91. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/start_relay_timer.py +0 -0
  92. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_relay_off.py +0 -0
  93. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_relay_on.py +0 -0
  94. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_to_comfort.py +0 -0
  95. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_to_day.py +0 -0
  96. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_to_night.py +0 -0
  97. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/switch_to_safe.py +0 -0
  98. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_settings_part1.py +0 -0
  99. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_settings_part2.py +0 -0
  100. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_settings_part3.py +0 -0
  101. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_settings_part4.py +0 -0
  102. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_settings_request.py +0 -0
  103. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_sensor_status.py +0 -0
  104. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_set_cooling.py +0 -0
  105. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/temp_set_heating.py +0 -0
  106. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/update_led_status.py +0 -0
  107. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/very_fast_blinking_led.py +0 -0
  108. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/write_data_to_memory.py +0 -0
  109. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/write_memory_block.py +0 -0
  110. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/messages/write_module_address_and_serial_number.py +0 -0
  111. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/protocol.py +0 -0
  112. {velbus-aio-2024.4.0 → velbus-aio-2024.4.1}/velbusaio/py.typed +0 -0
  113. {velbus-aio-2024.4.0 → velbus-aio-2024.4.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.4.0
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
@@ -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: 2024.4.0
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
@@ -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 to_json(self) -> dict:
140
- d = self.__dict__
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,4 +1,5 @@
1
- """
1
+ """Constant for velbusaio.
2
+
2
3
  Author: Maikel Punie <maikel.punie@gmail.com>
3
4
  """
4
5
 
@@ -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
- Add a found module to the module cache
86
- """
87
- mod = self._load_module_from_cache(self._cache_dir, addr)
88
- if mod is not None:
89
- self._log.info(f"Load module from CACHE: {addr}")
90
- self._modules[addr] = mod
91
- self._modules[addr].initialize(self.send)
92
- await self._modules[addr].load(True)
93
- else:
94
- self._log.info(f"Load NEW module: {typ} @ {addr}")
95
- self._modules[addr] = Module.factory(
96
- addr,
97
- typ,
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
- Get a module on an address
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() from err
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() from err
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
- This will send all the needed messages to sync the clock
275
- """
276
- await self.send(SetRealtimeClock())
277
- await self.send(SetDate())
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, command_value, ":".join(format(x, "02x") for x in data)
107
+ address,
108
+ command_value,
109
+ ":".join(format(x, "02x") for x in data),
109
110
  )
110
111
  )
111
112
  elif self._scan_complete:
@@ -6,7 +6,7 @@ from __future__ import annotations
6
6
 
7
7
  import os
8
8
  import re
9
- from typing import Any, Dict
9
+ from typing import Any
10
10
 
11
11
  from velbusaio.const import CACHEDIR
12
12
 
@@ -5,7 +5,6 @@ The velbus abstract message class
5
5
  from __future__ import annotations
6
6
 
7
7
  import json
8
- from typing import Optional
9
8
 
10
9
  from velbusaio.const import PRIORITY_FIRMWARE, PRIORITY_HIGH, PRIORITY_LOW
11
10
 
@@ -4,8 +4,6 @@
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
- import struct
8
-
9
7
  from velbusaio.command_registry import register
10
8
  from velbusaio.message import Message
11
9
 
@@ -4,8 +4,6 @@
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
- import struct
8
-
9
7
  from velbusaio.command_registry import register
10
8
  from velbusaio.message import Message
11
9
 
@@ -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 = None
24
- self._mon = None
25
- self._year = None
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 = None
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
  """