Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

## Versions from 0.40 and up

## Ongoing
## v0.54.0

- Link to plugwise [v1.4.4](https://github.com/plugwise/python-plugwise/releases/tag/v1.4.4) and adapt.
- Link to plugwise [v1.5.0](https://github.com/plugwise/python-plugwise/releases/tag/v1.5.0) and adapt:
- Remove the connection-timeout function added in v0.53.3, not accepted in Core
- Remove the need to pass a connection-timeout value to the backend library, as suggested by a Core dev
- Link to plugwise [v1.4.4](https://github.com/plugwise/python-plugwise/releases/tag/v1.4.4) and adapt
- Fix coordinator connection-method: don't use defaults

## v0.53.5
Expand Down
34 changes: 16 additions & 18 deletions custom_components/plugwise/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
SERVICE_DELETE, # pw-beta delete_notifications
)
from .coordinator import PlugwiseDataUpdateCoordinator
from .util import get_timeout_for_version

type PlugwiseConfigEntry = ConfigEntry[PlugwiseDataUpdateCoordinator]

Expand All @@ -46,7 +45,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: PlugwiseConfigEntry) ->
await coordinator.async_config_entry_first_refresh()

await async_migrate_sensor_entities(hass, coordinator)
await async_migrate_plugwise_entry(hass, coordinator, entry)

entry.runtime_data = coordinator

Expand Down Expand Up @@ -146,23 +144,23 @@ async def async_migrate_sensor_entities(
# Upstream remove LOGGER debug
ent_reg.async_update_entity(entity_id, new_unique_id=new_unique_id)

async def async_migrate_plugwise_entry(
hass: HomeAssistant,
coordinator: PlugwiseDataUpdateCoordinator,
entry: ConfigEntry
) -> bool:
"""Migrate to new config entry."""
if entry.version == 1 and entry.minor_version < 2:
async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Migrate back to v1.1 config entry."""
if entry.version > 1:
# This means the user has downgraded from a future version
return False

if entry.version == 1 and entry.minor_version == 2:
new_data = {**entry.data}
new_data[CONF_TIMEOUT] = get_timeout_for_version(str(coordinator.api.smile_version))
new_data.pop(CONF_TIMEOUT)
hass.config_entries.async_update_entry(
entry, data=new_data, minor_version=2, version=1
entry, data=new_data, minor_version=1, version=1
)
LOGGER.debug(
"Migration to version %s.%s successful",
entry.version,
entry.minor_version,
)
return True

return False
LOGGER.debug(
"Migration to version %s.%s successful",
entry.version,
entry.minor_version,
)

return True
11 changes: 1 addition & 10 deletions custom_components/plugwise/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
CONF_PASSWORD,
CONF_PORT,
CONF_SCAN_INTERVAL,
CONF_TIMEOUT,
CONF_USERNAME,
)

Expand All @@ -50,7 +49,6 @@
CONTEXT,
DEFAULT_PORT,
DEFAULT_SCAN_INTERVAL, # pw-beta option
DEFAULT_TIMEOUT,
DEFAULT_USERNAME,
DOMAIN,
FLOW_ID,
Expand All @@ -71,7 +69,6 @@

# Upstream
from .coordinator import PlugwiseDataUpdateCoordinator
from .util import get_timeout_for_version

type PlugwiseConfigEntry = ConfigEntry[PlugwiseDataUpdateCoordinator]

Expand Down Expand Up @@ -119,7 +116,6 @@ async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> Smile:
host=data[CONF_HOST],
password=data[CONF_PASSWORD],
port=data[CONF_PORT],
timeout=data[CONF_TIMEOUT],
username=data[CONF_USERNAME],
websession=websession,
)
Expand All @@ -131,10 +127,9 @@ class PlugwiseConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Plugwise Smile."""

VERSION = 1
MINOR_VERSION = 2
MINOR_VERSION = 1

discovery_info: ZeroconfServiceInfo | None = None
_timeout: int = DEFAULT_TIMEOUT
_username: str = DEFAULT_USERNAME

async def async_step_zeroconf(
Expand All @@ -145,7 +140,6 @@ async def async_step_zeroconf(
_properties = discovery_info.properties
_product = _properties.get(PRODUCT, "Unknown Smile")
_version = _properties.get(VERSION, "n/a")
self._timeout = get_timeout_for_version(_version)
unique_id = discovery_info.hostname.split(".")[0].split("-")[0]
if DEFAULT_USERNAME not in unique_id:
self._username = STRETCH_USERNAME
Expand All @@ -158,7 +152,6 @@ async def async_step_zeroconf(
CONF_HOST: discovery_info.host,
CONF_PASSWORD: config_entry.data[CONF_PASSWORD],
CONF_PORT: discovery_info.port,
CONF_TIMEOUT: self._timeout,
CONF_USERNAME: config_entry.data[CONF_USERNAME],
},
)
Expand Down Expand Up @@ -228,8 +221,6 @@ async def async_step_user(
user_input[CONF_PORT] = self.discovery_info.port
user_input[CONF_USERNAME] = self._username

# Ensure a timeout-value is available, required for validation
user_input[CONF_TIMEOUT] = self._timeout
try:
api = await validate_input(self.hass, user_input)
except ConnectionFailedError:
Expand Down
5 changes: 1 addition & 4 deletions custom_components/plugwise/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
CONF_PASSWORD,
CONF_PORT,
CONF_SCAN_INTERVAL, # pw-beta options
CONF_TIMEOUT,
CONF_USERNAME,
)
from homeassistant.core import HomeAssistant
Expand All @@ -29,7 +28,7 @@
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from packaging.version import Version

from .const import DEFAULT_SCAN_INTERVAL, DEFAULT_TIMEOUT, DOMAIN, GATEWAY_ID, LOGGER
from .const import DEFAULT_SCAN_INTERVAL, DOMAIN, GATEWAY_ID, LOGGER


class PlugwiseDataUpdateCoordinator(DataUpdateCoordinator[PlugwiseData]):
Expand Down Expand Up @@ -67,8 +66,6 @@ def __init__(
host=self.config_entry.data[CONF_HOST],
password=self.config_entry.data[CONF_PASSWORD],
port=self.config_entry.data[CONF_PORT],
# Needs to stay .get() for config_entry migration-testing:
timeout=self.config_entry.data.get(CONF_TIMEOUT, DEFAULT_TIMEOUT),
username=self.config_entry.data[CONF_USERNAME],
websession=async_get_clientsession(hass, verify_ssl=False),
)
Expand Down
4 changes: 2 additions & 2 deletions custom_components/plugwise/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"integration_type": "hub",
"iot_class": "local_polling",
"loggers": ["plugwise"],
"requirements": ["plugwise==1.4.4"],
"version": "0.53.5",
"requirements": ["plugwise==1.5.0"],
"version": "0.54.0",
"zeroconf": ["_plugwise._tcp.local."]
}
13 changes: 0 additions & 13 deletions custom_components/plugwise/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@
from plugwise.exceptions import PlugwiseException

from homeassistant.exceptions import HomeAssistantError
from packaging import version

from .const import DEFAULT_TIMEOUT
from .entity import PlugwiseEntity

# For reference:
Expand All @@ -19,17 +17,6 @@
# _P = ParamSpec("_P")


def get_timeout_for_version(version_str: str) -> int:
"""Determine timeout value based on gateway version.

A gateway firmware version > 3.2.0 should mean a latest-generation-device, allowing for a timeout of 10s.
Legacy devices require a timeout of 30s.
"""
if version.parse(version_str) >= version.parse("3.2.0"):
return 10
return DEFAULT_TIMEOUT


def plugwise_command[_PlugwiseEntityT: PlugwiseEntity, **_P, _R](
func: Callable[Concatenate[_PlugwiseEntityT, _P], Awaitable[_R]],
) -> Callable[Concatenate[_PlugwiseEntityT, _P], Coroutine[Any, Any, _R]]:
Expand Down
27 changes: 0 additions & 27 deletions tests/components/plugwise/snapshots/test_init.ambr

This file was deleted.

17 changes: 5 additions & 12 deletions tests/components/plugwise/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@
TEST_HOSTNAME2 = "stretchabc"
TEST_PASSWORD = "test_password"
TEST_PORT = 81
TEST_TIMEOUT_LEGACY = 30
TEST_TIMEOUT = 10
TEST_USERNAME = "smile"
TEST_USERNAME2 = "stretch"
TEST_DISCOVERY = zeroconf.ZeroconfServiceInfo(
Expand Down Expand Up @@ -146,26 +144,25 @@ async def test_form(
CONF_PASSWORD: TEST_PASSWORD,
CONF_PORT: DEFAULT_PORT,
CONF_USERNAME: TEST_USERNAME,
CONF_TIMEOUT: TEST_TIMEOUT_LEGACY,
}

assert len(mock_setup_entry.mock_calls) == 1
assert len(mock_smile_config_flow.connect.mock_calls) == 1


@pytest.mark.parametrize(
("discovery", "parameters",),
("discovery", "username",),
[
(TEST_DISCOVERY, (TEST_USERNAME, TEST_TIMEOUT)),
(TEST_DISCOVERY2, (TEST_USERNAME2, TEST_TIMEOUT_LEGACY)),
(TEST_DISCOVERY, TEST_USERNAME),
(TEST_DISCOVERY2, TEST_USERNAME2),
],
)
async def test_zeroconf_form(
hass: HomeAssistant,
mock_setup_entry: AsyncMock,
mock_smile_config_flow: MagicMock,
discovery: ZeroconfServiceInfo,
parameters: tuple[str, str],
username: str,
) -> None:
"""Test config flow for Smile devices."""
result = await hass.config_entries.flow.async_init(
Expand All @@ -186,13 +183,11 @@ async def test_zeroconf_form(

assert result2.get("type") == FlowResultType.CREATE_ENTRY
assert result2.get("title") == "Test Smile Name"
username, timeout = parameters
assert result2.get("data") == {
CONF_HOST: TEST_HOST,
CONF_PASSWORD: TEST_PASSWORD,
CONF_PORT: DEFAULT_PORT,
CONF_USERNAME: username,
CONF_TIMEOUT: timeout,
}

assert len(mock_setup_entry.mock_calls) == 1
Expand Down Expand Up @@ -228,7 +223,6 @@ async def test_zeroconf_stretch_form(
CONF_PASSWORD: TEST_PASSWORD,
CONF_PORT: DEFAULT_PORT,
CONF_USERNAME: TEST_USERNAME2,
CONF_TIMEOUT: TEST_TIMEOUT_LEGACY,
}

assert len(mock_setup_entry.mock_calls) == 1
Expand Down Expand Up @@ -390,7 +384,6 @@ async def test_flow_errors(
CONF_PASSWORD: TEST_PASSWORD,
CONF_PORT: DEFAULT_PORT,
CONF_USERNAME: TEST_USERNAME,
CONF_TIMEOUT: TEST_TIMEOUT_LEGACY,
}

assert len(mock_setup_entry.mock_calls) == 1
Expand Down Expand Up @@ -432,7 +425,7 @@ async def test_options_flow_thermo(
data={
CONF_HOST: TEST_HOST,
CONF_PASSWORD: TEST_PASSWORD,
CONF_TIMEOUT: TEST_TIMEOUT,
CONF_TIMEOUT: 30,
},
minor_version=2,
options={
Expand Down
13 changes: 8 additions & 5 deletions tests/components/plugwise/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
CONF_MAC,
CONF_PASSWORD,
CONF_PORT,
CONF_TIMEOUT,
CONF_USERNAME,
Platform,
)
Expand Down Expand Up @@ -241,29 +242,31 @@ async def test_entry_migration(
hass: HomeAssistant,
mock_smile_anna_2: MagicMock,
snapshot: SnapshotAssertion) -> None:
"""Test config entry version 1 -> 2 migration."""
"""Test config entry version 2 -> 1 migration."""
entry = MockConfigEntry(
domain=DOMAIN,
data={
CONF_HOST: "127.0.0.1",
CONF_MAC: "AA:BB:CC:DD:EE:FF",
CONF_PASSWORD: "test-password",
CONF_PORT: 80,
CONF_TIMEOUT: 30,
CONF_USERNAME: "smile",
},
minor_version=1,
minor_version=2,
version=1,
unique_id="smile98765",
)

entry.runtime_data = MagicMock(api=mock_smile_anna_2)
entry.add_to_hass(hass)

await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()

# Assert that the migrated entry matches the expected structure
assert hass.config_entries.async_get_entry(entry.entry_id) == snapshot
assert entry.version == 1
assert entry.minor_version == 1
assert entry.data.get(CONF_TIMEOUT) is None
assert entry.state is ConfigEntryState.LOADED


async def test_update_device(
Expand Down