1
0
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:
Lukas
2025-11-05 14:04:49 +01:00
committed by GitHub
parent 306b78ba5f
commit 5dc215a143
12 changed files with 144 additions and 27 deletions
+33 -1
View File
@@ -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."""
+2 -2
View File
@@ -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"]
}
+4 -4
View File
@@ -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": {
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+13
View File
@@ -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'>,
})
# ---
+64 -1
View File
@@ -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
)