PyPlumIO 0.5.49__tar.gz → 0.5.50__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.
- {pyplumio-0.5.49 → pyplumio-0.5.50}/PKG-INFO +1 -1
- {pyplumio-0.5.49 → pyplumio-0.5.50}/PyPlumIO.egg-info/PKG-INFO +1 -1
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/_version.py +2 -2
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/const.py +2 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/devices/__init__.py +8 -3
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/devices/ecomax.py +9 -9
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/devices/mixer.py +2 -2
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/devices/thermostat.py +2 -2
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/protocol.py +10 -13
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/devices/test_ecomax.py +19 -4
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/devices/test_init.py +20 -5
- {pyplumio-0.5.49 → pyplumio-0.5.50}/.gitattributes +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/.github/CODE_OF_CONDUCT.md +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/.github/dependabot.yml +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/.github/workflows/ci.yml +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/.github/workflows/codeql.yml +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/.github/workflows/deploy.yml +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/.github/workflows/documentation.yml +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/.gitignore +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/.pre-commit-config.yaml +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/.qlty/qlty.toml +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/.vscode/settings.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/LICENSE +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/MANIFEST.in +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/PyPlumIO.egg-info/SOURCES.txt +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/PyPlumIO.egg-info/dependency_links.txt +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/PyPlumIO.egg-info/requires.txt +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/PyPlumIO.egg-info/top_level.txt +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/README.md +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/docs/Makefile +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/docs/make.bat +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/docs/source/callbacks.rst +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/docs/source/conf.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/docs/source/connecting.rst +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/docs/source/frames.rst +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/docs/source/index.rst +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/docs/source/mixers_thermostats.rst +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/docs/source/protocol.rst +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/docs/source/reading.rst +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/docs/source/schedules.rst +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/docs/source/writing.rst +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/images/ecomax.png +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/images/rs485.png +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/__init__.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/__main__.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/connection.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/data_types.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/devices/ecoster.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/exceptions.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/filters.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/frames/__init__.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/frames/messages.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/frames/requests.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/frames/responses.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/helpers/__init__.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/helpers/async_cache.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/helpers/event_manager.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/helpers/factory.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/helpers/schedule.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/helpers/task_manager.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/helpers/timeout.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/helpers/uid.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/parameters/__init__.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/parameters/custom/__init__.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/parameters/custom/ecomax_860d3_hb.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/parameters/ecomax.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/parameters/mixer.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/parameters/thermostat.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/py.typed +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/stream.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/__init__.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/alerts.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/boiler_load.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/boiler_power.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/ecomax_parameters.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/fan_power.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/frame_versions.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/fuel_consumption.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/fuel_level.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/lambda_sensor.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/mixer_parameters.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/mixer_sensors.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/modules.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/network_info.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/output_flags.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/outputs.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/pending_alerts.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/product_info.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/program_version.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/regulator_data.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/regulator_data_schema.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/schedules.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/statuses.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/temperatures.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/thermostat_parameters.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/structures/thermostat_sensors.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyplumio/utils.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/pyproject.toml +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/requirements.txt +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/requirements_docs.txt +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/requirements_test.txt +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/setup.cfg +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/__init__.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/conftest.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/devices/__init__.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/devices/test_ecoster.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/devices/test_mixer.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/devices/test_thermostat.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/frames/test_init.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/frames/test_messages.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/frames/test_requests.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/frames/test_responses.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/helpers/__init__.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/helpers/test_async_cache.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/helpers/test_event_manager.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/helpers/test_factory.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/helpers/test_schedule.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/helpers/test_task_manager.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/helpers/test_timeout.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/helpers/test_uid.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/parameters/__init__.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/parameters/custom/__init__.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/parameters/custom/test_ecomax_860d3_hb.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/parameters/custom/test_init.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/parameters/test_ecomax.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/parameters/test_init.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/parameters/test_mixers.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/parameters/test_thermostats.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/ruff.toml +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/test_connection.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/test_data_types.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/test_filters.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/test_init.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/test_main.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/test_protocol.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/test_stream.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/test_utils.py +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/messages/regulator_data.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/messages/sensor_data.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/parameters/ecomax_860d3_hb.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/requests/alerts.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/requests/ecomax_control.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/requests/ecomax_parameters.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/requests/mixer_parameters.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/requests/set_ecomax_parameter.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/requests/set_mixer_parameter.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/requests/set_schedule.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/requests/set_thermostat_parameter.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/requests/thermostat_parameters.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/responses/alerts.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/responses/device_available.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/responses/ecomax_parameters.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/responses/mixer_parameters.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/responses/password.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/responses/program_version.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/responses/regulator_data_schema.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/responses/schedules.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/responses/thermostat_parameters.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/responses/uid.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/unknown/unknown_ecomax_parameter.json +0 -0
- {pyplumio-0.5.49 → pyplumio-0.5.50}/tests/testdata/unknown/unknown_mixer_parameter.json +0 -0
@@ -184,6 +184,7 @@ class FrameType(IntEnum):
|
|
184
184
|
REQUEST_SET_MIXER_PARAMETER = 52
|
185
185
|
REQUEST_SCHEDULES = 54
|
186
186
|
REQUEST_SET_SCHEDULE = 55
|
187
|
+
REQUEST_ECOMAX_PARAMETER_CHANGES = 56
|
187
188
|
REQUEST_UID = 57
|
188
189
|
REQUEST_PASSWORD = 58
|
189
190
|
REQUEST_ECOMAX_CONTROL = 59
|
@@ -203,6 +204,7 @@ class FrameType(IntEnum):
|
|
203
204
|
RESPONSE_ECOMAX_CONTROL = 187
|
204
205
|
RESPONSE_ALERTS = 189
|
205
206
|
RESPONSE_PROGRAM_VERSION = 192
|
207
|
+
RESPONSE_ECOMAX_PARAMETER_CHANGES = 212
|
206
208
|
RESPONSE_REGULATOR_DATA_SCHEMA = 213
|
207
209
|
RESPONSE_THERMOSTAT_PARAMETERS = 220
|
208
210
|
RESPONSE_SET_THERMOSTAT_PARAMETER = 221
|
@@ -145,21 +145,26 @@ class PhysicalDevice(Device, ABC):
|
|
145
145
|
@event_listener(filter=on_change)
|
146
146
|
async def on_event_frame_versions(self, versions: dict[int, int]) -> None:
|
147
147
|
"""Check frame versions and update outdated frames."""
|
148
|
-
_LOGGER.
|
148
|
+
_LOGGER.debug("Received frame version table")
|
149
149
|
for frame_type, version in versions.items():
|
150
150
|
if (
|
151
151
|
is_known_frame_type(frame_type)
|
152
152
|
and self.supports_frame_type(frame_type)
|
153
153
|
and not self.has_frame_version(frame_type, version)
|
154
154
|
):
|
155
|
-
|
155
|
+
request_frame_type = (
|
156
|
+
FrameType.REQUEST_ECOMAX_PARAMETERS
|
157
|
+
if frame_type == FrameType.REQUEST_ECOMAX_PARAMETER_CHANGES
|
158
|
+
else frame_type
|
159
|
+
)
|
160
|
+
await self._request_frame_version(request_frame_type, version)
|
156
161
|
self._frame_versions[frame_type] = version
|
157
162
|
|
158
163
|
async def _request_frame_version(
|
159
164
|
self, frame_type: FrameType | int, version: int
|
160
165
|
) -> None:
|
161
166
|
"""Request frame version from the device."""
|
162
|
-
_LOGGER.
|
167
|
+
_LOGGER.debug("Updating frame %s to version %i", repr(frame_type), version)
|
163
168
|
request = await Request.create(frame_type, recipient=self.address)
|
164
169
|
self.queue.put_nowait(request)
|
165
170
|
|
@@ -234,7 +234,7 @@ class EcoMAX(PhysicalDevice):
|
|
234
234
|
@event_listener
|
235
235
|
async def on_event_setup(self, setup: bool) -> None:
|
236
236
|
"""Request frames required to set up an ecoMAX entry."""
|
237
|
-
_LOGGER.
|
237
|
+
_LOGGER.debug("Setting up device entry")
|
238
238
|
await self.wait_for(ATTR_SENSORS)
|
239
239
|
results = await asyncio.gather(
|
240
240
|
*(
|
@@ -251,14 +251,14 @@ class EcoMAX(PhysicalDevice):
|
|
251
251
|
if errors:
|
252
252
|
self.dispatch_nowait(ATTR_FRAME_ERRORS, errors)
|
253
253
|
|
254
|
-
_LOGGER.
|
254
|
+
_LOGGER.debug("Device entry setup done")
|
255
255
|
|
256
256
|
@event_listener
|
257
257
|
async def on_event_ecomax_parameters(
|
258
258
|
self, parameters: list[tuple[int, ParameterValues]]
|
259
259
|
) -> bool:
|
260
260
|
"""Update ecoMAX parameters and dispatch the events."""
|
261
|
-
_LOGGER.
|
261
|
+
_LOGGER.debug("Received device parameters")
|
262
262
|
product_info: ProductInfo = await self.get(ATTR_PRODUCT)
|
263
263
|
parameter_types = await get_ecomax_parameter_types(product_info)
|
264
264
|
|
@@ -307,7 +307,7 @@ class EcoMAX(PhysicalDevice):
|
|
307
307
|
parameters: dict[int, list[tuple[int, ParameterValues]]] | None,
|
308
308
|
) -> bool:
|
309
309
|
"""Handle mixer parameters and dispatch the events."""
|
310
|
-
_LOGGER.
|
310
|
+
_LOGGER.debug("Received mixer parameters")
|
311
311
|
if parameters:
|
312
312
|
await asyncio.gather(
|
313
313
|
*(
|
@@ -324,7 +324,7 @@ class EcoMAX(PhysicalDevice):
|
|
324
324
|
self, sensors: dict[int, dict[str, Any]] | None
|
325
325
|
) -> bool:
|
326
326
|
"""Update mixer sensors and dispatch the events."""
|
327
|
-
_LOGGER.
|
327
|
+
_LOGGER.debug("Received mixer sensors")
|
328
328
|
if sensors:
|
329
329
|
await asyncio.gather(
|
330
330
|
*(
|
@@ -364,7 +364,7 @@ class EcoMAX(PhysicalDevice):
|
|
364
364
|
@event_listener
|
365
365
|
async def on_event_sensors(self, sensors: dict[str, Any]) -> bool:
|
366
366
|
"""Update ecoMAX sensors and dispatch the events."""
|
367
|
-
_LOGGER.
|
367
|
+
_LOGGER.debug("Received device sensors")
|
368
368
|
await asyncio.gather(
|
369
369
|
*(self.dispatch(name, value) for name, value in sensors.items())
|
370
370
|
)
|
@@ -376,7 +376,7 @@ class EcoMAX(PhysicalDevice):
|
|
376
376
|
parameters: dict[int, list[tuple[int, ParameterValues]]] | None,
|
377
377
|
) -> bool:
|
378
378
|
"""Handle thermostat parameters and dispatch the events."""
|
379
|
-
_LOGGER.
|
379
|
+
_LOGGER.debug("Received thermostat parameters")
|
380
380
|
if parameters:
|
381
381
|
await asyncio.gather(
|
382
382
|
*(
|
@@ -407,7 +407,7 @@ class EcoMAX(PhysicalDevice):
|
|
407
407
|
self, sensors: dict[int, dict[str, Any]] | None
|
408
408
|
) -> bool:
|
409
409
|
"""Update thermostat sensors and dispatch the events."""
|
410
|
-
_LOGGER.
|
410
|
+
_LOGGER.debug("Received thermostat sensors")
|
411
411
|
if sensors:
|
412
412
|
await asyncio.gather(
|
413
413
|
*(
|
@@ -427,7 +427,7 @@ class EcoMAX(PhysicalDevice):
|
|
427
427
|
self, schedules: list[tuple[int, list[list[bool]]]]
|
428
428
|
) -> dict[str, Schedule]:
|
429
429
|
"""Update schedules."""
|
430
|
-
_LOGGER.
|
430
|
+
_LOGGER.debug("Received device schedules")
|
431
431
|
return {
|
432
432
|
SCHEDULES[index]: Schedule(
|
433
433
|
name=SCHEDULES[index],
|
@@ -29,7 +29,7 @@ class Mixer(VirtualDevice):
|
|
29
29
|
@event_listener
|
30
30
|
async def on_event_mixer_sensors(self, sensors: dict[str, Any]) -> bool:
|
31
31
|
"""Update mixer sensors and dispatch the events."""
|
32
|
-
_LOGGER.
|
32
|
+
_LOGGER.debug("Received mixer %i sensors", self.index)
|
33
33
|
await asyncio.gather(
|
34
34
|
*(self.dispatch(name, value) for name, value in sensors.items())
|
35
35
|
)
|
@@ -40,7 +40,7 @@ class Mixer(VirtualDevice):
|
|
40
40
|
self, parameters: list[tuple[int, ParameterValues]]
|
41
41
|
) -> bool:
|
42
42
|
"""Update mixer parameters and dispatch the events."""
|
43
|
-
_LOGGER.
|
43
|
+
_LOGGER.debug("Received mixer %i parameters", self.index)
|
44
44
|
product_info: ProductInfo = await self.parent.get(ATTR_PRODUCT)
|
45
45
|
parameter_types = get_mixer_parameter_types(product_info)
|
46
46
|
|
@@ -28,7 +28,7 @@ class Thermostat(VirtualDevice):
|
|
28
28
|
@event_listener
|
29
29
|
async def on_event_thermostat_sensors(self, sensors: dict[str, Any]) -> bool:
|
30
30
|
"""Update thermostat sensors and dispatch the events."""
|
31
|
-
_LOGGER.
|
31
|
+
_LOGGER.debug("Received thermostat %i sensors", self.index)
|
32
32
|
await asyncio.gather(
|
33
33
|
*(self.dispatch(name, value) for name, value in sensors.items())
|
34
34
|
)
|
@@ -39,7 +39,7 @@ class Thermostat(VirtualDevice):
|
|
39
39
|
self, parameters: list[tuple[int, ParameterValues]]
|
40
40
|
) -> bool:
|
41
41
|
"""Update thermostat parameters and dispatch the events."""
|
42
|
-
_LOGGER.
|
42
|
+
_LOGGER.debug("Received thermostat %i parameters", self.index)
|
43
43
|
parameter_types = get_thermostat_parameter_types()
|
44
44
|
|
45
45
|
def _thermostat_parameter_events() -> Generator[Coroutine]:
|
@@ -230,20 +230,17 @@ class AsyncProtocol(Protocol, EventManager[PhysicalDevice]):
|
|
230
230
|
@acache
|
231
231
|
async def get_device_entry(self, device_type: DeviceType) -> PhysicalDevice:
|
232
232
|
"""Return the device entry."""
|
233
|
-
|
234
|
-
@acache
|
235
|
-
async def _setup_device_entry(device_type: DeviceType) -> PhysicalDevice:
|
236
|
-
"""Set up the device entry."""
|
237
|
-
device = await PhysicalDevice.create(
|
238
|
-
device_type, queue=self._queues.write, network=self._network
|
239
|
-
)
|
240
|
-
device.dispatch_nowait(ATTR_CONNECTED, True)
|
241
|
-
device.dispatch_nowait(ATTR_SETUP, True)
|
242
|
-
self.dispatch_nowait(device_type.name.lower(), device)
|
243
|
-
return device
|
244
|
-
|
245
233
|
async with self._entry_lock:
|
246
|
-
|
234
|
+
name = device_type.name.lower()
|
235
|
+
if name not in self.data:
|
236
|
+
device = await PhysicalDevice.create(
|
237
|
+
device_type, queue=self._queues.write, network=self._network
|
238
|
+
)
|
239
|
+
device.dispatch_nowait(ATTR_CONNECTED, True)
|
240
|
+
device.dispatch_nowait(ATTR_SETUP, True)
|
241
|
+
await self.dispatch(device_type.name.lower(), device)
|
242
|
+
|
243
|
+
return self.data[name]
|
247
244
|
|
248
245
|
|
249
246
|
__all__ = ["Protocol", "DummyProtocol", "AsyncProtocol"]
|
@@ -43,6 +43,7 @@ from pyplumio.frames.messages import SensorDataMessage
|
|
43
43
|
from pyplumio.frames.requests import (
|
44
44
|
AlertsRequest,
|
45
45
|
EcomaxControlRequest,
|
46
|
+
EcomaxParametersRequest,
|
46
47
|
SetEcomaxParameterRequest,
|
47
48
|
SetScheduleRequest,
|
48
49
|
SetThermostatParameterRequest,
|
@@ -104,10 +105,24 @@ async def test_ecomax_handle_frame(
|
|
104
105
|
mock_handle_frame.assert_called_once_with(request)
|
105
106
|
|
106
107
|
|
108
|
+
@pytest.mark.parametrize(
|
109
|
+
("frame_type", "frame_request"),
|
110
|
+
[
|
111
|
+
(FrameType.REQUEST_ALERTS, AlertsRequest(recipient=DeviceType.ECOMAX)),
|
112
|
+
(
|
113
|
+
FrameType.REQUEST_ECOMAX_PARAMETER_CHANGES,
|
114
|
+
EcomaxParametersRequest(recipient=DeviceType.ECOMAX),
|
115
|
+
),
|
116
|
+
],
|
117
|
+
)
|
107
118
|
@patch("asyncio.Queue.put_nowait")
|
108
119
|
@class_from_json(SensorDataMessage, "messages/sensor_data.json", arguments=("message",))
|
109
120
|
async def test_frame_versions_tracker(
|
110
|
-
mock_put_nowait,
|
121
|
+
mock_put_nowait,
|
122
|
+
ecomax: EcoMAX,
|
123
|
+
sensor_data: SensorDataMessage,
|
124
|
+
frame_type: FrameType,
|
125
|
+
frame_request: Request,
|
111
126
|
) -> None:
|
112
127
|
"""Test frame version tracker."""
|
113
128
|
|
@@ -116,7 +131,7 @@ async def test_frame_versions_tracker(
|
|
116
131
|
return {ATTR_SENSORS: {ATTR_FRAME_VERSIONS: {frame: version}}}
|
117
132
|
|
118
133
|
# Test with frame type that are handled during setup.
|
119
|
-
sensor_data.data = _frame_version_data(
|
134
|
+
sensor_data.data = _frame_version_data(frame_type, 1)
|
120
135
|
ecomax.data.clear()
|
121
136
|
ecomax.handle_frame(sensor_data)
|
122
137
|
await ecomax.wait_until_done()
|
@@ -124,12 +139,12 @@ async def test_frame_versions_tracker(
|
|
124
139
|
|
125
140
|
# Test with same frame type after setup done.
|
126
141
|
mock_put_nowait.reset_mock()
|
127
|
-
sensor_data.data = _frame_version_data(
|
142
|
+
sensor_data.data = _frame_version_data(frame_type, 2)
|
128
143
|
ecomax.data.clear()
|
129
144
|
ecomax.data[ATTR_SETUP] = True
|
130
145
|
ecomax.handle_frame(sensor_data)
|
131
146
|
await ecomax.wait_until_done()
|
132
|
-
mock_put_nowait.assert_called_once_with(
|
147
|
+
mock_put_nowait.assert_called_once_with(frame_request)
|
133
148
|
|
134
149
|
|
135
150
|
@pytest.mark.parametrize("state", [STATE_ON, STATE_OFF])
|
@@ -102,19 +102,34 @@ def fixture_physical_device() -> PhysicalDevice:
|
|
102
102
|
class TestPhysicalDevice:
|
103
103
|
"""Contains tests for PhysicalDevice class."""
|
104
104
|
|
105
|
+
@pytest.mark.parametrize(
|
106
|
+
("frame_type", "requested_frame_type"),
|
107
|
+
[
|
108
|
+
(FrameType.REQUEST_ALERTS, FrameType.REQUEST_ALERTS),
|
109
|
+
(
|
110
|
+
FrameType.REQUEST_ECOMAX_PARAMETER_CHANGES,
|
111
|
+
FrameType.REQUEST_ECOMAX_PARAMETERS,
|
112
|
+
),
|
113
|
+
],
|
114
|
+
)
|
105
115
|
@patch("pyplumio.frames.Request.create", autospec=True)
|
106
116
|
@patch("asyncio.Queue.put_nowait")
|
107
117
|
async def test_frame_versions_event_listener(
|
108
|
-
self,
|
118
|
+
self,
|
119
|
+
mock_put_nowait,
|
120
|
+
mock_request_create,
|
121
|
+
physical_device: PhysicalDevice,
|
122
|
+
frame_type: FrameType,
|
123
|
+
requested_frame_type: FrameType,
|
109
124
|
) -> None:
|
110
125
|
"""Test event listener for frame versions."""
|
111
|
-
assert physical_device.has_frame_version(
|
112
|
-
await physical_device.on_event_frame_versions({
|
126
|
+
assert physical_device.has_frame_version(frame_type, 1) is False
|
127
|
+
await physical_device.on_event_frame_versions({frame_type: 1})
|
113
128
|
mock_request_create.assert_awaited_once_with(
|
114
|
-
|
129
|
+
requested_frame_type, recipient=DummyPhysicalDevice.address
|
115
130
|
)
|
116
131
|
mock_put_nowait.assert_called_once_with(mock_request_create.return_value)
|
117
|
-
assert physical_device.has_frame_version(
|
132
|
+
assert physical_device.has_frame_version(frame_type, 1) is True
|
118
133
|
|
119
134
|
def test_frame_versions_event_listener_decorator(self) -> None:
|
120
135
|
"""Test decorator for the frame version event listener."""
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|