diff --git a/CHANGELOG.md b/CHANGELOG.md index 12ff2979a..e95865381 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ Versions from 0.40 and up +## Ongoing + +- Implement Core PR [#159626](https://github.com/home-assistant/core/pull/159626) via PR [#994](https://github.com/plugwise/plugwise-beta/pull/994) + ## v0.62.2 - Bump plugwise to [v1.11.2](https://github.com/plugwise/python-plugwise/releases/tag/v1.11.2) diff --git a/custom_components/plugwise/config_flow.py b/custom_components/plugwise/config_flow.py index 9a14e7fa1..ba33abcd8 100644 --- a/custom_components/plugwise/config_flow.py +++ b/custom_components/plugwise/config_flow.py @@ -48,12 +48,13 @@ CONF_HOMEKIT_EMULATION, # pw-beta option CONF_REFRESH_INTERVAL, # pw-beta option DEFAULT_PORT, - DEFAULT_SCAN_INTERVAL, # pw-beta option + DEFAULT_UPDATE_INTERVAL, DEFAULT_USERNAME, DOMAIN, FLOW_SMILE, FLOW_STRETCH, INIT, + P1_UPDATE_INTERVAL, SMILE, SMILE_OPEN_THERM, SMILE_THERMO, @@ -317,7 +318,9 @@ def __init__(self, config_entry: ConfigEntry) -> None: self.options = deepcopy(dict(config_entry.options)) def _create_options_schema(self, coordinator: PlugwiseDataUpdateCoordinator) -> vol.Schema: - interval = DEFAULT_SCAN_INTERVAL[coordinator.api.smile.type] # pw-beta options + interval = DEFAULT_UPDATE_INTERVAL + if coordinator.api.smile.type == "power": + interval = P1_UPDATE_INTERVAL schema = { vol.Optional( CONF_SCAN_INTERVAL, diff --git a/custom_components/plugwise/const.py b/custom_components/plugwise/const.py index 6bf80f736..ea0c25feb 100644 --- a/custom_components/plugwise/const.py +++ b/custom_components/plugwise/const.py @@ -150,13 +150,10 @@ # Default directives DEFAULT_PORT: Final[int] = 80 -DEFAULT_SCAN_INTERVAL: Final[dict[str, timedelta]] = { - "power": timedelta(seconds=10), - "stretch": timedelta(seconds=60), - "thermostat": timedelta(seconds=60), -} DEFAULT_TIMEOUT: Final[int] = 30 +DEFAULT_UPDATE_INTERVAL: Final = timedelta(seconds=60) DEFAULT_USERNAME: Final = "smile" +P1_UPDATE_INTERVAL: Final = timedelta(seconds=10) # --- Const for Plugwise Smile and Stretch PLATFORMS: Final[list[str]] = [ diff --git a/custom_components/plugwise/coordinator.py b/custom_components/plugwise/coordinator.py index 363a9083f..e1d5e9266 100644 --- a/custom_components/plugwise/coordinator.py +++ b/custom_components/plugwise/coordinator.py @@ -29,7 +29,14 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from packaging.version import Version -from .const import DEFAULT_SCAN_INTERVAL, DEV_CLASS, DOMAIN, LOGGER, SWITCH_GROUPS +from .const import ( + DEFAULT_UPDATE_INTERVAL, + DEV_CLASS, + DOMAIN, + LOGGER, + P1_UPDATE_INTERVAL, + SWITCH_GROUPS, +) type PlugwiseConfigEntry = ConfigEntry[PlugwiseDataUpdateCoordinator] @@ -49,7 +56,6 @@ def __init__( hass: HomeAssistant, cooldown: float, config_entry: PlugwiseConfigEntry, - update_interval: timedelta = timedelta(seconds=60), ) -> None: # pw-beta cooldown """Initialize the coordinator.""" super().__init__( @@ -59,7 +65,7 @@ def __init__( name=DOMAIN, # Core directly updates from const's DEFAULT_SCAN_INTERVAL # Upstream check correct progress for adjusting - update_interval=update_interval, + update_interval=DEFAULT_UPDATE_INTERVAL, # Don't refresh immediately, give the device time to process # the change in state before we query it. request_refresh_debouncer=Debouncer( @@ -80,7 +86,6 @@ def __init__( self._current_devices = set() self._stored_devices = set() self.new_devices = set() - self.update_interval = update_interval async def _connect(self) -> None: """Connect to the Plugwise Smile. @@ -90,9 +95,8 @@ async def _connect(self) -> None: version = await self.api.connect() self._connected = isinstance(version, Version) if self._connected: - self.update_interval = DEFAULT_SCAN_INTERVAL.get( - self.api.smile.type, timedelta(seconds=60) - ) # pw-beta options scan-interval + if self.api.smile.type == "power": + self.update_interval = P1_UPDATE_INTERVAL if (custom_time := self.config_entry.options.get(CONF_SCAN_INTERVAL)) is not None: self.update_interval = timedelta( seconds=int(custom_time) diff --git a/tests/components/plugwise/test_init.py b/tests/components/plugwise/test_init.py index 035c52038..914842b60 100644 --- a/tests/components/plugwise/test_init.py +++ b/tests/components/plugwise/test_init.py @@ -14,7 +14,11 @@ import pytest from freezegun.api import FrozenDateTimeFactory -from homeassistant.components.plugwise.const import DOMAIN +from homeassistant.components.plugwise.const import ( + DEFAULT_UPDATE_INTERVAL, + DOMAIN, + P1_UPDATE_INTERVAL, +) from homeassistant.config_entries import ConfigEntryState from homeassistant.const import ( CONF_HOST, @@ -27,7 +31,6 @@ ) from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr, entity_registry as er -from homeassistant.setup import async_setup_component from tests.common import MockConfigEntry, async_fire_time_changed @@ -154,7 +157,7 @@ async def test_device_in_dr( ) -> None: """Test Gateway device registry data.""" mock_config_entry.add_to_hass(hass) - assert await async_setup_component(hass, DOMAIN, {}) + await hass.config_entries.async_setup(mock_config_entry.entry_id) await hass.async_block_till_done() device_entry = device_registry.async_get_device( @@ -279,7 +282,7 @@ async def test_update_device( data = mock_smile_adam_heat_cool.async_update.return_value mock_config_entry.add_to_hass(hass) - assert await async_setup_component(hass, DOMAIN, {}) + await hass.config_entries.async_setup(mock_config_entry.entry_id) await hass.async_block_till_done() assert ( @@ -375,6 +378,54 @@ async def test_delete_removed_device( assert "14df5c4dc8cb4ba69f9d1ac0eaf7c5c6" not in item_list +@pytest.mark.parametrize("chosen_env", ["m_adam_heating"], indirect=True) +@pytest.mark.parametrize("cooling_present", [False], indirect=True) +async def test_update_interval_adam( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_smile_adam_heat_cool: MagicMock, + freezer: FrozenDateTimeFactory, +) -> None: + """Test Adam update interval.""" + mock_config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(mock_config_entry.entry_id) + await hass.async_block_till_done() + + assert mock_config_entry.state is ConfigEntryState.LOADED + assert mock_smile_adam_heat_cool.async_update.call_count == 1 + + freezer.tick(DEFAULT_UPDATE_INTERVAL) + async_fire_time_changed(hass) + await hass.async_block_till_done() + + assert mock_smile_adam_heat_cool.async_update.call_count == 2 + + +@pytest.mark.parametrize("chosen_env", ["p1v4_442_single"], indirect=True) +@pytest.mark.parametrize( + "gateway_id", ["a455b61e52394b2db5081ce025a430f3"], indirect=True +) +async def test_update_interval_p1( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_smile_p1: MagicMock, + freezer: FrozenDateTimeFactory, +) -> None: + """Test Smile P1 update interval.""" + mock_config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(mock_config_entry.entry_id) + await hass.async_block_till_done() + + assert mock_config_entry.state is ConfigEntryState.LOADED + assert mock_smile_p1.async_update.call_count == 1 + + freezer.tick(P1_UPDATE_INTERVAL) + async_fire_time_changed(hass) + await hass.async_block_till_done() + + assert mock_smile_p1.async_update.call_count == 2 + + #### pw-beta only #### @pytest.mark.parametrize("chosen_env", ["m_anna_heatpump_cooling"], indirect=True) @pytest.mark.parametrize("cooling_present", [True], indirect=True)