mirror of
https://github.com/home-assistant/core.git
synced 2026-05-08 09:38:58 +01:00
Bump python-pooldose to 0.7.8 (#155307)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
This commit is contained in:
@@ -3,13 +3,15 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from pooldose.client import PooldoseClient
|
||||
from pooldose.request_status import RequestStatus
|
||||
|
||||
from homeassistant.const import CONF_HOST, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from .coordinator import PooldoseConfigEntry, PooldoseCoordinator
|
||||
|
||||
@@ -18,6 +20,36 @@ _LOGGER = logging.getLogger(__name__)
|
||||
PLATFORMS: list[Platform] = [Platform.SENSOR]
|
||||
|
||||
|
||||
async def async_migrate_entry(hass: HomeAssistant, entry: PooldoseConfigEntry) -> bool:
|
||||
"""Migrate old entry."""
|
||||
# Version 1.1 -> 1.2: Migrate entity unique IDs
|
||||
# - ofa_orp_value -> ofa_orp_time
|
||||
# - ofa_ph_value -> ofa_ph_time
|
||||
if entry.version == 1 and entry.minor_version < 2:
|
||||
|
||||
@callback
|
||||
def migrate_unique_id(entity_entry: er.RegistryEntry) -> dict[str, Any] | None:
|
||||
"""Migrate entity unique IDs for pooldose sensors."""
|
||||
new_unique_id = entity_entry.unique_id
|
||||
|
||||
# Check if this entry needs migration
|
||||
if "_ofa_orp_value" in new_unique_id:
|
||||
new_unique_id = new_unique_id.replace("_ofa_orp_value", "_ofa_orp_time")
|
||||
elif "_ofa_ph_value" in new_unique_id:
|
||||
new_unique_id = new_unique_id.replace("_ofa_ph_value", "_ofa_ph_time")
|
||||
else:
|
||||
# No migration needed
|
||||
return None
|
||||
|
||||
return {"new_unique_id": new_unique_id}
|
||||
|
||||
await er.async_migrate_entries(hass, entry.entry_id, migrate_unique_id)
|
||||
|
||||
hass.config_entries.async_update_entry(entry, version=1, minor_version=2)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: PooldoseConfigEntry) -> bool:
|
||||
"""Set up Seko PoolDose from a config entry."""
|
||||
# Get host from config entry data (connection-critical configuration)
|
||||
|
||||
@@ -31,6 +31,7 @@ class PooldoseConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
"""Config flow for the Pooldose integration including DHCP discovery."""
|
||||
|
||||
VERSION = 1
|
||||
MINOR_VERSION = 2
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initialize the config flow and store the discovered IP address and MAC."""
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"ofa_orp_value": {
|
||||
"ofa_orp_time": {
|
||||
"default": "mdi:clock"
|
||||
},
|
||||
"ofa_ph_value": {
|
||||
"ofa_ph_time": {
|
||||
"default": "mdi:clock"
|
||||
},
|
||||
"orp": {
|
||||
|
||||
@@ -11,5 +11,5 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/pooldose",
|
||||
"iot_class": "local_polling",
|
||||
"quality_scale": "bronze",
|
||||
"requirements": ["python-pooldose==0.7.0"]
|
||||
"requirements": ["python-pooldose==0.7.8"]
|
||||
}
|
||||
|
||||
@@ -48,8 +48,8 @@ SENSOR_DESCRIPTIONS: tuple[SensorEntityDescription, ...] = (
|
||||
options=["proportional", "on_off", "timed"],
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="ofa_ph_value",
|
||||
translation_key="ofa_ph_value",
|
||||
key="ofa_ph_time",
|
||||
translation_key="ofa_ph_time",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
device_class=SensorDeviceClass.DURATION,
|
||||
entity_registry_enabled_default=False,
|
||||
@@ -72,8 +72,8 @@ SENSOR_DESCRIPTIONS: tuple[SensorEntityDescription, ...] = (
|
||||
options=["off", "proportional", "on_off", "timed"],
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="ofa_orp_value",
|
||||
translation_key="ofa_orp_value",
|
||||
key="ofa_orp_time",
|
||||
translation_key="ofa_orp_time",
|
||||
device_class=SensorDeviceClass.DURATION,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
|
||||
@@ -34,10 +34,10 @@
|
||||
},
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"ofa_orp_value": {
|
||||
"ofa_orp_time": {
|
||||
"name": "ORP overfeed alert time"
|
||||
},
|
||||
"ofa_ph_value": {
|
||||
"ofa_ph_time": {
|
||||
"name": "pH overfeed alert time"
|
||||
},
|
||||
"orp": {
|
||||
|
||||
Generated
+1
-1
@@ -2525,7 +2525,7 @@ python-overseerr==0.7.1
|
||||
python-picnic-api2==1.3.1
|
||||
|
||||
# homeassistant.components.pooldose
|
||||
python-pooldose==0.7.0
|
||||
python-pooldose==0.7.8
|
||||
|
||||
# homeassistant.components.rabbitair
|
||||
python-rabbitair==0.0.8
|
||||
|
||||
Generated
+1
-1
@@ -2094,7 +2094,7 @@ python-overseerr==0.7.1
|
||||
python-picnic-api2==1.3.1
|
||||
|
||||
# homeassistant.components.pooldose
|
||||
python-pooldose==0.7.0
|
||||
python-pooldose==0.7.8
|
||||
|
||||
# homeassistant.components.rabbitair
|
||||
python-rabbitair==0.0.8
|
||||
|
||||
@@ -75,6 +75,19 @@ def mock_config_entry(device_info: dict[str, Any]) -> MockConfigEntry:
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config_entry_v1_1(device_info: dict[str, Any]) -> MockConfigEntry:
|
||||
"""Return a mocked config entry for migration testing with version 1.1."""
|
||||
return MockConfigEntry(
|
||||
title="Pool Device",
|
||||
domain=DOMAIN,
|
||||
data={CONF_HOST: "192.168.1.100"},
|
||||
unique_id=device_info["SERIAL_NUMBER"],
|
||||
version=1,
|
||||
minor_version=1,
|
||||
)
|
||||
|
||||
|
||||
async def init_integration(
|
||||
hass: HomeAssistant, mock_config_entry: MockConfigEntry
|
||||
) -> MockConfigEntry:
|
||||
|
||||
@@ -12,6 +12,14 @@
|
||||
"value": 718,
|
||||
"unit": "mV"
|
||||
},
|
||||
"cl": {
|
||||
"value": 1.2,
|
||||
"unit": "ppm"
|
||||
},
|
||||
"flow_rate": {
|
||||
"value": 150,
|
||||
"unit": "L/s"
|
||||
},
|
||||
"ph_type_dosing": {
|
||||
"value": "alcalyne",
|
||||
"unit": null
|
||||
@@ -20,7 +28,7 @@
|
||||
"value": "proportional",
|
||||
"unit": null
|
||||
},
|
||||
"ofa_ph_value": {
|
||||
"ofa_ph_time": {
|
||||
"value": 0,
|
||||
"unit": "min"
|
||||
},
|
||||
@@ -32,7 +40,7 @@
|
||||
"value": "proportional",
|
||||
"unit": null
|
||||
},
|
||||
"ofa_orp_value": {
|
||||
"ofa_orp_time": {
|
||||
"value": 0,
|
||||
"unit": "min"
|
||||
},
|
||||
@@ -62,25 +70,25 @@
|
||||
}
|
||||
},
|
||||
"binary_sensor": {
|
||||
"pump_running": {
|
||||
"pump_alarm": {
|
||||
"value": true
|
||||
},
|
||||
"ph_level_ok": {
|
||||
"ph_level_alarm": {
|
||||
"value": false
|
||||
},
|
||||
"orp_level_ok": {
|
||||
"orp_level_alarm": {
|
||||
"value": false
|
||||
},
|
||||
"flow_rate_ok": {
|
||||
"flow_rate_alarm": {
|
||||
"value": false
|
||||
},
|
||||
"alarm_relay": {
|
||||
"value": true
|
||||
},
|
||||
"relay_aux1_ph": {
|
||||
"relay_aux1": {
|
||||
"value": false
|
||||
},
|
||||
"relay_aux2_orpcl": {
|
||||
"relay_aux2": {
|
||||
"value": false
|
||||
}
|
||||
},
|
||||
@@ -108,10 +116,10 @@
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"stop_pool_dosing": {
|
||||
"pause_dosing": {
|
||||
"value": false
|
||||
},
|
||||
"pump_detection": {
|
||||
"pump_monitoring": {
|
||||
"value": true
|
||||
},
|
||||
"frequency_input": {
|
||||
|
||||
@@ -309,8 +309,8 @@
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'ofa_orp_value',
|
||||
'unique_id': 'TEST123456789_ofa_orp_value',
|
||||
'translation_key': 'ofa_orp_time',
|
||||
'unique_id': 'TEST123456789_ofa_orp_time',
|
||||
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
|
||||
})
|
||||
# ---
|
||||
@@ -699,8 +699,8 @@
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'ofa_ph_value',
|
||||
'unique_id': 'TEST123456789_ofa_ph_value',
|
||||
'translation_key': 'ofa_ph_time',
|
||||
'unique_id': 'TEST123456789_ofa_ph_time',
|
||||
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
|
||||
})
|
||||
# ---
|
||||
|
||||
@@ -8,7 +8,7 @@ from syrupy.assertion import SnapshotAssertion
|
||||
from homeassistant.components.pooldose.const import DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
|
||||
from .conftest import RequestStatus
|
||||
|
||||
@@ -117,3 +117,66 @@ async def test_setup_entry_timeout_error(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
||||
|
||||
async def test_migrate_entity_unique_ids(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
mock_config_entry_v1_1: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test migration of entity unique IDs."""
|
||||
mock_config_entry_v1_1.add_to_hass(hass)
|
||||
|
||||
# Create entities with old unique ID format
|
||||
entity_registry.async_get_or_create(
|
||||
"sensor",
|
||||
DOMAIN,
|
||||
"TEST123456789_ofa_orp_value",
|
||||
config_entry=mock_config_entry_v1_1,
|
||||
)
|
||||
entity_registry.async_get_or_create(
|
||||
"sensor",
|
||||
DOMAIN,
|
||||
"TEST123456789_ofa_ph_value",
|
||||
config_entry=mock_config_entry_v1_1,
|
||||
)
|
||||
# Create entity with correct unique ID that should not be changed
|
||||
unchanged_entity = entity_registry.async_get_or_create(
|
||||
"sensor",
|
||||
DOMAIN,
|
||||
"TEST123456789_orp",
|
||||
config_entry=mock_config_entry_v1_1,
|
||||
)
|
||||
|
||||
assert mock_config_entry_v1_1.version == 1
|
||||
assert mock_config_entry_v1_1.minor_version == 1
|
||||
|
||||
# Setup the integration - this will trigger migration
|
||||
await hass.config_entries.async_setup(mock_config_entry_v1_1.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Verify the config entry version was updated from 1.1 to 1.2
|
||||
assert mock_config_entry_v1_1.version == 1
|
||||
assert mock_config_entry_v1_1.minor_version == 2
|
||||
|
||||
# Verify the entities have been migrated
|
||||
assert entity_registry.async_get_entity_id(
|
||||
"sensor", DOMAIN, "TEST123456789_ofa_orp_time"
|
||||
)
|
||||
assert entity_registry.async_get_entity_id(
|
||||
"sensor", DOMAIN, "TEST123456789_ofa_ph_time"
|
||||
)
|
||||
|
||||
# Verify old unique IDs no longer exist
|
||||
assert not entity_registry.async_get_entity_id(
|
||||
"sensor", DOMAIN, "TEST123456789_ofa_orp_value"
|
||||
)
|
||||
assert not entity_registry.async_get_entity_id(
|
||||
"sensor", DOMAIN, "TEST123456789_ofa_ph_value"
|
||||
)
|
||||
|
||||
# Verify entity that didn't need migration is unchanged
|
||||
assert (
|
||||
entity_registry.async_get_entity_id("sensor", DOMAIN, "TEST123456789_orp")
|
||||
== unchanged_entity.entity_id
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user