diff --git a/README.md b/README.md index 5104e7d3..046a9a5b 100644 --- a/README.md +++ b/README.md @@ -2207,7 +2207,7 @@ For information on how to add, remove, and configure devices, please refer to th - Wireless Warning Code _(disabled)_ - LED Brightness _(disabled)_ - Heartbeat Frequency _(disabled)_ -- Status (Scheduled) +- Status *Sliders (numbers)* - Min Discharge Level @@ -2966,7 +2966,6 @@ For information on how to add, remove, and configure devices, please refer to th - mpptPv2.pwr - mpptPv2.amp - mpptPv2.vol -- Status (Scheduled) +- Status

- diff --git a/custom_components/ecoflow_cloud/__init__.py b/custom_components/ecoflow_cloud/__init__.py index 95274310..f18c6b4c 100644 --- a/custom_components/ecoflow_cloud/__init__.py +++ b/custom_components/ecoflow_cloud/__init__.py @@ -7,6 +7,7 @@ from homeassistant.const import Platform from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryNotReady +from homeassistant.helpers import entity_registry as er from . import _preload_proto # noqa: F401 # pyright: ignore[reportUnusedImport] from .device_data import DeviceData, DeviceOptions @@ -14,7 +15,7 @@ _LOGGER = logging.getLogger(__name__) ECOFLOW_DOMAIN = "ecoflow_cloud" -CONFIG_VERSION = 10 +CONFIG_VERSION = 11 _PLATFORMS = { Platform.BINARY_SENSOR, @@ -66,6 +67,23 @@ _STATUS_COORDINATOR_KEY = "__status_coordinator" +def _migrate_entity_unique_id( + hass: HomeAssistant, + platform: Platform, + old_unique_id: str, + new_unique_id: str, +) -> bool: + registry = er.async_get(hass) + entity_id = registry.async_get_entity_id(platform, ECOFLOW_DOMAIN, old_unique_id) + if entity_id is None: + return False + if registry.async_get_entity_id(platform, ECOFLOW_DOMAIN, new_unique_id) is not None: + return False + + registry.async_update_entity(entity_id, new_unique_id=new_unique_id) + return True + + async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry): updated: bool = False if config_entry.version in (5, 6): @@ -137,6 +155,24 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry): updated = hass.config_entries.async_update_entry(config_entry, version=10, options=new_options) _LOGGER.info("Config entries updated to version %d", config_entry.version) + if config_entry.version == 10: + if CONF_ACCESS_KEY in config_entry.data: + for sn, device_info in config_entry.data[CONF_DEVICE_LIST].items(): + if device_info[CONF_DEVICE_TYPE] not in ("PowerStream", "Power Ocean"): + continue + + migrated = _migrate_entity_unique_id( + hass, + Platform.SENSOR, + f"ecoflow-api-{sn}-status-scheduled", + f"ecoflow-api-{sn}-status", + ) + if migrated: + _LOGGER.info("Migrated scheduled status entity unique ID for %s", sn) + + updated = hass.config_entries.async_update_entry(config_entry, version=11) + _LOGGER.info("Config entries updated to version %d", config_entry.version) + return updated diff --git a/custom_components/ecoflow_cloud/devices/public/powerocean.py b/custom_components/ecoflow_cloud/devices/public/powerocean.py index 27f32d6a..db424441 100644 --- a/custom_components/ecoflow_cloud/devices/public/powerocean.py +++ b/custom_components/ecoflow_cloud/devices/public/powerocean.py @@ -226,7 +226,7 @@ def _prepare_data(self, raw_data) -> dict[str, Any]: def _status_sensor(self, client: EcoflowApiClient) -> QuotaScheduledStatusSensorEntity: # Keep quota fallback active even while MQTT stream is sparse. - return QuotaScheduledStatusSensorEntity(client, self, 60) + return QuotaScheduledStatusSensorEntity(client, self, 60, "Status", "status") def _flatten_param_branch(self, prefix: str, value: Any, target: dict[str, Any]) -> None: if isinstance(value, dict): diff --git a/custom_components/ecoflow_cloud/devices/public/powerstream.py b/custom_components/ecoflow_cloud/devices/public/powerstream.py index 7cab3a07..83c78a5d 100644 --- a/custom_components/ecoflow_cloud/devices/public/powerstream.py +++ b/custom_components/ecoflow_cloud/devices/public/powerstream.py @@ -195,4 +195,4 @@ def _prepare_data(self, raw_data: bytes) -> dict[str, Any]: def _status_sensor(self, client: EcoflowApiClient) -> QuotaScheduledStatusSensorEntity: # Keep quota fallback active even while MQTT stream is sparse. - return QuotaScheduledStatusSensorEntity(client, self, 60) + return QuotaScheduledStatusSensorEntity(client, self, 60, "Status", "status") diff --git a/custom_components/ecoflow_cloud/sensor.py b/custom_components/ecoflow_cloud/sensor.py index deaf6a11..b2617851 100644 --- a/custom_components/ecoflow_cloud/sensor.py +++ b/custom_components/ecoflow_cloud/sensor.py @@ -580,8 +580,15 @@ def __init__( class QuotaScheduledStatusSensorEntity(QuotaStatusSensorEntity): """QuotaStatusSensorEntity with additional periodic scheduled refresh.""" - def __init__(self, client: EcoflowApiClient, device: BaseDevice, reload_delay: int = 3600): - super().__init__(client, device, "Status (Scheduled)", "status.scheduled") + def __init__( + self, + client: EcoflowApiClient, + device: BaseDevice, + reload_delay: int = 3600, + title: str = "Status (Scheduled)", + key: str = "status.scheduled", + ): + super().__init__(client, device, title, key) self._scheduled_refresh_sec = reload_delay diff --git a/docs/devices/PowerStream-Public.md b/docs/devices/PowerStream-Public.md index 4f6d2976..f68b106e 100644 --- a/docs/devices/PowerStream-Public.md +++ b/docs/devices/PowerStream-Public.md @@ -58,7 +58,7 @@ - Wireless Warning Code (`20_1.wirelessWarnCode`) _(disabled)_ - LED Brightness (`20_1.invBrightness`) _(disabled)_ - Heartbeat Frequency (`20_1.heartbeatFrequency`) _(disabled)_ -- Status (Scheduled) +- Status *Sliders (numbers)* - Min Discharge Level (`20_1.lowerLimit` -> `{"sn": "SN", "cmdCode": "WN511_SET_BAT_LOWER_PACK", "params": {"lowerLimit": "VALUE"}}` [0 - 30]) @@ -69,4 +69,3 @@ *Selects* - Power supply mode (`20_1.supplyPriority` -> `{"sn": "SN", "cmdCode": "WN511_SET_SUPPLY_PRIORITY_PACK", "params": {"supplyPriority": "VALUE"}}` [Prioritize power supply (0), Prioritize power storage (1)]) - diff --git a/docs/devices/Power_Ocean-Public.md b/docs/devices/Power_Ocean-Public.md index 2e325705..69ad3a78 100644 --- a/docs/devices/Power_Ocean-Public.md +++ b/docs/devices/Power_Ocean-Public.md @@ -23,6 +23,5 @@ - mpptPv2.pwr (`96_1.mpptHeartBeat[0].mpptPv[1].pwr`) - mpptPv2.amp (`96_1.mpptHeartBeat[0].mpptPv[1].amp`) - mpptPv2.vol (`96_1.mpptHeartBeat[0].mpptPv[1].vol`) -- Status (Scheduled) - +- Status diff --git a/docs/summary.md b/docs/summary.md index e7567892..0dcb4e4b 100644 --- a/docs/summary.md +++ b/docs/summary.md @@ -2168,7 +2168,7 @@ - Wireless Warning Code _(disabled)_ - LED Brightness _(disabled)_ - Heartbeat Frequency _(disabled)_ -- Status (Scheduled) +- Status *Sliders (numbers)* - Min Discharge Level @@ -2927,8 +2927,7 @@ - mpptPv2.pwr - mpptPv2.amp - mpptPv2.vol -- Status (Scheduled) +- Status

-