diff --git a/custom_components/meross_lan/helpers/namespaces.py b/custom_components/meross_lan/helpers/namespaces.py index 881897cf..91cb785e 100644 --- a/custom_components/meross_lan/helpers/namespaces.py +++ b/custom_components/meross_lan/helpers/namespaces.py @@ -577,8 +577,9 @@ async def async_poll_all(self): NS_MULTIPLE, it will likely do more queries though but this is unlikely) """ device = self.device - if device._mqtt_active: - # on MQTT no need for updates since they're being PUSHed + if device.curr_protocol is mlc.CONF_PROTOCOL_MQTT and device._mqtt_active: + # When operating on MQTT no need for updates since they're being PUSHed. + # An auxiliary MQTT connection must not suppress HTTP reconciliation. if not self.polling_epoch_next: # just when onlining... await device.async_request_poll(self) diff --git a/tests/const.py b/tests/const.py index 9ce4125e..a89267dc 100644 --- a/tests/const.py +++ b/tests/const.py @@ -283,6 +283,7 @@ class MockProfileStoreType(TypedDict): EMULATOR_TRACES_PATH = "./emulator_traces/" EMULATOR_TRACES_MAP = { + mc.TYPE_MSG200: "U0123456789012345678901234567891C-Kpippo-msg200.json.txt", mc.TYPE_MTS200: "U0123456789012345678901234567890C-Kpippo-mts200b-1674112759.csv", mc.TYPE_MSS310: "U0123456789012345678901234567890E-Kpippo-mss310r-1676020598.csv", mc.TYPE_MSH300: "U0123456789012345678901234567890F-Kpippo-msh300-2024-02-23_06-57-23.csv", diff --git a/tests/test_config_entry.py b/tests/test_config_entry.py index 01ebc5f0..1084ff4b 100644 --- a/tests/test_config_entry.py +++ b/tests/test_config_entry.py @@ -1,12 +1,13 @@ """Test meross_lan config entry setup""" import asyncio -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, cast from homeassistant import const as hac from homeassistant.config_entries import ConfigEntryState from custom_components.meross_lan import const as mlc +from custom_components.meross_lan.devices.garagedoor import MLGarage from custom_components.meross_lan.helpers.component_api import ComponentApi from custom_components.meross_lan.light import MLDNDLightEntity from custom_components.meross_lan.merossclient.protocol import ( @@ -20,6 +21,8 @@ if TYPE_CHECKING: from homeassistant.core import HomeAssistant + from custom_components.meross_lan.helpers.mqtt_profile import MQTTConnection + # We can pass fixtures as defined in conftest.py to tell pytest to use the fixture # for a given test. We can also leverage fixtures and mocks that are available in @@ -113,6 +116,33 @@ async def test_device_entry(request, hass: "HomeAssistant"): assert state and state.state.isdigit() +async def test_device_http_poll_with_mqtt_active(request, hass: "HomeAssistant"): + async with helpers.DeviceContext(request, hass, mc.TYPE_MSG200) as context: + device = await context.perform_coldstart() + garage = device.entities[2] + assert isinstance(garage, MLGarage) + assert garage.is_closed + assert device.curr_protocol is mlc.CONF_PROTOCOL_HTTP + + for channel_state in context.emulator.descriptor.digest[mc.KEY_GARAGEDOOR]: + if channel_state[mc.KEY_CHANNEL] == garage.channel: + channel_state[mc.KEY_OPEN] = 1 + break + else: + raise AssertionError(f"Garage channel {garage.channel} not found") + + ns_all_handler = device.namespace_handlers[mn.Appliance_System_All.name] + ns_all_handler.polling_epoch_next = device._polling_epoch + device._mqtt_active = cast("MQTTConnection", object()) + try: + await ns_all_handler.async_poll_all() + await device._async_multiple_requests_flush() + finally: + device._mqtt_active = None + + assert garage.is_closed is False + + async def test_profile_entry(request, hass: "HomeAssistant"): """ Test a Meross cloud profile entry