Change AsusWRT entities unique id (#97066)
Migrate AsusWRT entities unique id
This commit is contained in:
parent
17e757af36
commit
345df715d6
3 changed files with 105 additions and 55 deletions
|
@ -20,7 +20,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_send
|
|||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.event import async_track_time_interval
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
from homeassistant.util import dt as dt_util
|
||||
from homeassistant.util import dt as dt_util, slugify
|
||||
|
||||
from .bridge import AsusWrtBridge, WrtDevice
|
||||
from .const import (
|
||||
|
@ -39,7 +39,6 @@ from .const import (
|
|||
)
|
||||
|
||||
CONF_REQ_RELOAD = [CONF_DNSMASQ, CONF_INTERFACE, CONF_REQUIRE_IP]
|
||||
DEFAULT_NAME = "Asuswrt"
|
||||
|
||||
SCAN_INTERVAL = timedelta(seconds=30)
|
||||
|
||||
|
@ -179,6 +178,44 @@ class AsusWrtRouter:
|
|||
self.hass, dict(self._entry.data), self._options
|
||||
)
|
||||
|
||||
def _migrate_entities_unique_id(self) -> None:
|
||||
"""Migrate router entities to new unique id format."""
|
||||
_ENTITY_MIGRATION_ID = {
|
||||
"sensor_connected_device": "Devices Connected",
|
||||
"sensor_rx_bytes": "Download",
|
||||
"sensor_tx_bytes": "Upload",
|
||||
"sensor_rx_rates": "Download Speed",
|
||||
"sensor_tx_rates": "Upload Speed",
|
||||
"sensor_load_avg1": "Load Avg (1m)",
|
||||
"sensor_load_avg5": "Load Avg (5m)",
|
||||
"sensor_load_avg15": "Load Avg (15m)",
|
||||
"2.4GHz": "2.4GHz Temperature",
|
||||
"5.0GHz": "5GHz Temperature",
|
||||
"CPU": "CPU Temperature",
|
||||
}
|
||||
|
||||
entity_reg = er.async_get(self.hass)
|
||||
router_entries = er.async_entries_for_config_entry(
|
||||
entity_reg, self._entry.entry_id
|
||||
)
|
||||
|
||||
migrate_entities: dict[str, str] = {}
|
||||
for entry in router_entries:
|
||||
if entry.domain == TRACKER_DOMAIN:
|
||||
continue
|
||||
old_unique_id = entry.unique_id
|
||||
if not old_unique_id.startswith(DOMAIN):
|
||||
continue
|
||||
for new_id, old_id in _ENTITY_MIGRATION_ID.items():
|
||||
if old_unique_id.endswith(old_id):
|
||||
migrate_entities[entry.entity_id] = slugify(
|
||||
f"{self.unique_id}_{new_id}"
|
||||
)
|
||||
break
|
||||
|
||||
for entity_id, unique_id in migrate_entities.items():
|
||||
entity_reg.async_update_entity(entity_id, new_unique_id=unique_id)
|
||||
|
||||
async def setup(self) -> None:
|
||||
"""Set up a AsusWrt router."""
|
||||
try:
|
||||
|
@ -215,6 +252,9 @@ class AsusWrtRouter:
|
|||
|
||||
self._devices[device_mac] = AsusWrtDevInfo(device_mac, entry.original_name)
|
||||
|
||||
# Migrate entities to new unique id format
|
||||
self._migrate_entities_unique_id()
|
||||
|
||||
# Update devices
|
||||
await self.update_devices()
|
||||
|
||||
|
@ -364,14 +404,9 @@ class AsusWrtRouter:
|
|||
return self._api.host
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str | None:
|
||||
def unique_id(self) -> str:
|
||||
"""Return router unique id."""
|
||||
return self._entry.unique_id
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Return router name."""
|
||||
return self.host if self.unique_id else DEFAULT_NAME
|
||||
return self._entry.unique_id or self._entry.entry_id
|
||||
|
||||
@property
|
||||
def devices(self) -> dict[str, AsusWrtDevInfo]:
|
||||
|
|
|
@ -22,6 +22,7 @@ from homeassistant.helpers.update_coordinator import (
|
|||
CoordinatorEntity,
|
||||
DataUpdateCoordinator,
|
||||
)
|
||||
from homeassistant.util import slugify
|
||||
|
||||
from .const import (
|
||||
DATA_ASUSWRT,
|
||||
|
@ -182,6 +183,9 @@ async def async_setup_entry(
|
|||
class AsusWrtSensor(CoordinatorEntity, SensorEntity):
|
||||
"""Representation of a AsusWrt sensor."""
|
||||
|
||||
entity_description: AsusWrtSensorEntityDescription
|
||||
_attr_has_entity_name = True
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: DataUpdateCoordinator,
|
||||
|
@ -190,13 +194,9 @@ class AsusWrtSensor(CoordinatorEntity, SensorEntity):
|
|||
) -> None:
|
||||
"""Initialize a AsusWrt sensor."""
|
||||
super().__init__(coordinator)
|
||||
self.entity_description: AsusWrtSensorEntityDescription = description
|
||||
self.entity_description = description
|
||||
|
||||
self._attr_name = f"{router.name} {description.name}"
|
||||
if router.unique_id:
|
||||
self._attr_unique_id = f"{DOMAIN} {router.unique_id} {description.name}"
|
||||
else:
|
||||
self._attr_unique_id = f"{DOMAIN} {self.name}"
|
||||
self._attr_unique_id = slugify(f"{router.unique_id}_{description.key}")
|
||||
self._attr_device_info = router.device_info
|
||||
self._attr_extra_state_attributes = {"hostname": router.host}
|
||||
|
||||
|
|
|
@ -9,9 +9,13 @@ from homeassistant.components import device_tracker, sensor
|
|||
from homeassistant.components.asuswrt.const import (
|
||||
CONF_INTERFACE,
|
||||
DOMAIN,
|
||||
MODE_ROUTER,
|
||||
PROTOCOL_TELNET,
|
||||
SENSORS_BYTES,
|
||||
SENSORS_LOAD_AVG,
|
||||
SENSORS_RATES,
|
||||
SENSORS_TEMPERATURES,
|
||||
)
|
||||
from homeassistant.components.asuswrt.router import DEFAULT_NAME
|
||||
from homeassistant.components.device_tracker import CONF_CONSIDER_HOME
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import (
|
||||
|
@ -43,7 +47,7 @@ CONFIG_DATA = {
|
|||
CONF_PROTOCOL: PROTOCOL_TELNET,
|
||||
CONF_USERNAME: "user",
|
||||
CONF_PASSWORD: "pwd",
|
||||
CONF_MODE: "router",
|
||||
CONF_MODE: MODE_ROUTER,
|
||||
}
|
||||
|
||||
MAC_ADDR = "a1:b2:c3:d4:e5:f6"
|
||||
|
@ -57,26 +61,8 @@ MOCK_MAC_2 = "A2:B2:C2:D2:E2:F2"
|
|||
MOCK_MAC_3 = "A3:B3:C3:D3:E3:F3"
|
||||
MOCK_MAC_4 = "A4:B4:C4:D4:E4:F4"
|
||||
|
||||
SENSORS_DEFAULT = [
|
||||
"Download Speed",
|
||||
"Download",
|
||||
"Upload Speed",
|
||||
"Upload",
|
||||
]
|
||||
|
||||
SENSORS_LOADAVG = [
|
||||
"Load Avg (1m)",
|
||||
"Load Avg (5m)",
|
||||
"Load Avg (15m)",
|
||||
]
|
||||
|
||||
SENSORS_TEMP = [
|
||||
"2.4GHz Temperature",
|
||||
"5GHz Temperature",
|
||||
"CPU Temperature",
|
||||
]
|
||||
|
||||
SENSORS_ALL = [*SENSORS_DEFAULT, *SENSORS_LOADAVG, *SENSORS_TEMP]
|
||||
SENSORS_DEFAULT = [*SENSORS_BYTES, *SENSORS_RATES]
|
||||
SENSORS_ALL = [*SENSORS_DEFAULT, *SENSORS_LOAD_AVG, *SENSORS_TEMPERATURES]
|
||||
|
||||
PATCH_SETUP_ENTRY = patch(
|
||||
"homeassistant.components.asuswrt.async_setup_entry",
|
||||
|
@ -105,7 +91,7 @@ def mock_available_temps_fixture():
|
|||
|
||||
|
||||
@pytest.fixture(name="create_device_registry_devices")
|
||||
def create_device_registry_devices_fixture(hass):
|
||||
def create_device_registry_devices_fixture(hass: HomeAssistant):
|
||||
"""Create device registry devices so the device tracker entities are enabled when added."""
|
||||
dev_reg = dr.async_get(hass)
|
||||
config_entry = MockConfigEntry(domain="something_else")
|
||||
|
@ -182,7 +168,7 @@ def mock_controller_connect_sens_fail():
|
|||
yield service_mock
|
||||
|
||||
|
||||
def _setup_entry(hass, config, sensors, unique_id=None):
|
||||
def _setup_entry(hass: HomeAssistant, config, sensors, unique_id=None):
|
||||
"""Create mock config entry with enabled sensors."""
|
||||
entity_reg = er.async_get(hass)
|
||||
|
||||
|
@ -195,16 +181,17 @@ def _setup_entry(hass, config, sensors, unique_id=None):
|
|||
)
|
||||
|
||||
# init variable
|
||||
obj_prefix = slugify(HOST if unique_id else DEFAULT_NAME)
|
||||
obj_prefix = slugify(HOST)
|
||||
sensor_prefix = f"{sensor.DOMAIN}.{obj_prefix}"
|
||||
unique_id_prefix = slugify(unique_id or config_entry.entry_id)
|
||||
|
||||
# Pre-enable the status sensor
|
||||
for sensor_name in sensors:
|
||||
sensor_id = slugify(sensor_name)
|
||||
for sensor_key in sensors:
|
||||
sensor_id = slugify(sensor_key)
|
||||
entity_reg.async_get_or_create(
|
||||
sensor.DOMAIN,
|
||||
DOMAIN,
|
||||
f"{DOMAIN} {unique_id or DEFAULT_NAME} {sensor_name}",
|
||||
f"{unique_id_prefix}_{sensor_id}",
|
||||
suggested_object_id=f"{obj_prefix}_{sensor_id}",
|
||||
config_entry=config_entry,
|
||||
disabled_by=None,
|
||||
|
@ -255,10 +242,10 @@ async def test_sensors(
|
|||
|
||||
assert hass.states.get(f"{device_tracker.DOMAIN}.test").state == STATE_HOME
|
||||
assert hass.states.get(f"{device_tracker.DOMAIN}.testtwo").state == STATE_HOME
|
||||
assert hass.states.get(f"{sensor_prefix}_download_speed").state == "160.0"
|
||||
assert hass.states.get(f"{sensor_prefix}_download").state == "60.0"
|
||||
assert hass.states.get(f"{sensor_prefix}_upload_speed").state == "80.0"
|
||||
assert hass.states.get(f"{sensor_prefix}_upload").state == "50.0"
|
||||
assert hass.states.get(f"{sensor_prefix}_sensor_rx_rates").state == "160.0"
|
||||
assert hass.states.get(f"{sensor_prefix}_sensor_rx_bytes").state == "60.0"
|
||||
assert hass.states.get(f"{sensor_prefix}_sensor_tx_rates").state == "80.0"
|
||||
assert hass.states.get(f"{sensor_prefix}_sensor_tx_bytes").state == "50.0"
|
||||
assert hass.states.get(f"{sensor_prefix}_devices_connected").state == "2"
|
||||
|
||||
# remove first tracked device
|
||||
|
@ -296,7 +283,7 @@ async def test_loadavg_sensors(
|
|||
connect,
|
||||
) -> None:
|
||||
"""Test creating an AsusWRT load average sensors."""
|
||||
config_entry, sensor_prefix = _setup_entry(hass, CONFIG_DATA, SENSORS_LOADAVG)
|
||||
config_entry, sensor_prefix = _setup_entry(hass, CONFIG_DATA, SENSORS_LOAD_AVG)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
# initial devices setup
|
||||
|
@ -306,9 +293,9 @@ async def test_loadavg_sensors(
|
|||
await hass.async_block_till_done()
|
||||
|
||||
# assert temperature sensor available
|
||||
assert hass.states.get(f"{sensor_prefix}_load_avg_1m").state == "1.1"
|
||||
assert hass.states.get(f"{sensor_prefix}_load_avg_5m").state == "1.2"
|
||||
assert hass.states.get(f"{sensor_prefix}_load_avg_15m").state == "1.3"
|
||||
assert hass.states.get(f"{sensor_prefix}_sensor_load_avg1").state == "1.1"
|
||||
assert hass.states.get(f"{sensor_prefix}_sensor_load_avg5").state == "1.2"
|
||||
assert hass.states.get(f"{sensor_prefix}_sensor_load_avg15").state == "1.3"
|
||||
|
||||
|
||||
async def test_temperature_sensors(
|
||||
|
@ -316,7 +303,7 @@ async def test_temperature_sensors(
|
|||
connect,
|
||||
) -> None:
|
||||
"""Test creating a AsusWRT temperature sensors."""
|
||||
config_entry, sensor_prefix = _setup_entry(hass, CONFIG_DATA, SENSORS_TEMP)
|
||||
config_entry, sensor_prefix = _setup_entry(hass, CONFIG_DATA, SENSORS_TEMPERATURES)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
# initial devices setup
|
||||
|
@ -326,9 +313,9 @@ async def test_temperature_sensors(
|
|||
await hass.async_block_till_done()
|
||||
|
||||
# assert temperature sensor available
|
||||
assert hass.states.get(f"{sensor_prefix}_2_4ghz_temperature").state == "40.0"
|
||||
assert not hass.states.get(f"{sensor_prefix}_5ghz_temperature")
|
||||
assert hass.states.get(f"{sensor_prefix}_cpu_temperature").state == "71.2"
|
||||
assert hass.states.get(f"{sensor_prefix}_2_4ghz").state == "40.0"
|
||||
assert not hass.states.get(f"{sensor_prefix}_5_0ghz")
|
||||
assert hass.states.get(f"{sensor_prefix}_cpu").state == "71.2"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
@ -396,3 +383,31 @@ async def test_options_reload(hass: HomeAssistant, connect) -> None:
|
|||
|
||||
assert setup_entry_call.called
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
|
||||
async def test_unique_id_migration(hass: HomeAssistant, connect) -> None:
|
||||
"""Test AsusWRT entities unique id format migration."""
|
||||
config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data=CONFIG_DATA,
|
||||
unique_id=MAC_ADDR,
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
entity_reg = er.async_get(hass)
|
||||
obj_entity_id = slugify(f"{HOST} Upload")
|
||||
entity_reg.async_get_or_create(
|
||||
sensor.DOMAIN,
|
||||
DOMAIN,
|
||||
f"{DOMAIN} {MAC_ADDR} Upload",
|
||||
suggested_object_id=obj_entity_id,
|
||||
config_entry=config_entry,
|
||||
disabled_by=None,
|
||||
)
|
||||
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
migr_entity = entity_reg.async_get(f"{sensor.DOMAIN}.{obj_entity_id}")
|
||||
assert migr_entity is not None
|
||||
assert migr_entity.unique_id == slugify(f"{MAC_ADDR}_sensor_tx_bytes")
|
||||
|
|
Loading…
Add table
Reference in a new issue