mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Powerview migrate scene to string unique_id (#128131)
This commit is contained in:
parent
1c4f191f42
commit
09e1f53b3e
@ -1,6 +1,7 @@
|
|||||||
"""The Hunter Douglas PowerView integration."""
|
"""The Hunter Douglas PowerView integration."""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from aiopvapi.helpers.aiorequest import AioRequest
|
from aiopvapi.helpers.aiorequest import AioRequest
|
||||||
from aiopvapi.hub import Hub
|
from aiopvapi.hub import Hub
|
||||||
@ -13,6 +14,7 @@ from homeassistant.const import CONF_API_VERSION, CONF_HOST, Platform
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
|
import homeassistant.helpers.entity_registry as er
|
||||||
|
|
||||||
from .const import DOMAIN, HUB_EXCEPTIONS
|
from .const import DOMAIN, HUB_EXCEPTIONS
|
||||||
from .coordinator import PowerviewShadeUpdateCoordinator
|
from .coordinator import PowerviewShadeUpdateCoordinator
|
||||||
@ -126,3 +128,45 @@ async def async_get_device_info(hub: Hub) -> PowerviewDeviceInfo:
|
|||||||
async def async_unload_entry(hass: HomeAssistant, entry: PowerviewConfigEntry) -> bool:
|
async def async_unload_entry(hass: HomeAssistant, entry: PowerviewConfigEntry) -> bool:
|
||||||
"""Unload a config entry."""
|
"""Unload a config entry."""
|
||||||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_migrate_entry(hass: HomeAssistant, entry: PowerviewConfigEntry) -> bool:
|
||||||
|
"""Migrate entry."""
|
||||||
|
|
||||||
|
_LOGGER.debug("Migrating from version %s.%s", entry.version, entry.minor_version)
|
||||||
|
|
||||||
|
if entry.version == 1:
|
||||||
|
# 1 -> 2: Unique ID from integer to string
|
||||||
|
if entry.minor_version == 1:
|
||||||
|
await _migrate_unique_ids(hass, entry)
|
||||||
|
hass.config_entries.async_update_entry(entry, minor_version=2)
|
||||||
|
|
||||||
|
_LOGGER.debug("Migrated to version %s.%s", entry.version, entry.minor_version)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def _migrate_unique_ids(hass: HomeAssistant, entry: PowerviewConfigEntry) -> None:
|
||||||
|
"""Migrate int based unique ids to str."""
|
||||||
|
entity_registry = er.async_get(hass)
|
||||||
|
registry_entries = er.async_entries_for_config_entry(
|
||||||
|
entity_registry, entry.entry_id
|
||||||
|
)
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
assert entry.unique_id
|
||||||
|
for reg_entry in registry_entries:
|
||||||
|
if isinstance(reg_entry.unique_id, int) or (
|
||||||
|
isinstance(reg_entry.unique_id, str)
|
||||||
|
and not reg_entry.unique_id.startswith(entry.unique_id)
|
||||||
|
):
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Migrating %s: %s to %s_%s",
|
||||||
|
reg_entry.entity_id,
|
||||||
|
reg_entry.unique_id,
|
||||||
|
entry.unique_id,
|
||||||
|
reg_entry.unique_id,
|
||||||
|
)
|
||||||
|
entity_registry.async_update_entity(
|
||||||
|
reg_entry.entity_id,
|
||||||
|
new_unique_id=f"{entry.unique_id}_{reg_entry.unique_id}",
|
||||||
|
)
|
||||||
|
@ -63,6 +63,7 @@ class PowerviewConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
"""Handle a config flow for Hunter Douglas PowerView."""
|
"""Handle a config flow for Hunter Douglas PowerView."""
|
||||||
|
|
||||||
VERSION = 1
|
VERSION = 1
|
||||||
|
MINOR_VERSION = 2
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
"""Initialize the powerview config flow."""
|
"""Initialize the powerview config flow."""
|
||||||
|
@ -595,7 +595,7 @@ class PowerViewShadeTDBUBottom(PowerViewShadeDualRailBase):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the shade."""
|
"""Initialize the shade."""
|
||||||
super().__init__(coordinator, device_info, room_name, shade, name)
|
super().__init__(coordinator, device_info, room_name, shade, name)
|
||||||
self._attr_unique_id = f"{self._shade.id}_bottom"
|
self._attr_unique_id = f"{self._attr_unique_id}_bottom"
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _clamp_cover_limit(self, target_hass_position: int) -> int:
|
def _clamp_cover_limit(self, target_hass_position: int) -> int:
|
||||||
@ -632,7 +632,7 @@ class PowerViewShadeTDBUTop(PowerViewShadeDualRailBase):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the shade."""
|
"""Initialize the shade."""
|
||||||
super().__init__(coordinator, device_info, room_name, shade, name)
|
super().__init__(coordinator, device_info, room_name, shade, name)
|
||||||
self._attr_unique_id = f"{self._shade.id}_top"
|
self._attr_unique_id = f"{self._attr_unique_id}_top"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self) -> bool:
|
def should_poll(self) -> bool:
|
||||||
@ -740,7 +740,7 @@ class PowerViewShadeDualOverlappedCombined(PowerViewShadeDualOverlappedBase):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the shade."""
|
"""Initialize the shade."""
|
||||||
super().__init__(coordinator, device_info, room_name, shade, name)
|
super().__init__(coordinator, device_info, room_name, shade, name)
|
||||||
self._attr_unique_id = f"{self._shade.id}_combined"
|
self._attr_unique_id = f"{self._attr_unique_id}_combined"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_closed(self) -> bool:
|
def is_closed(self) -> bool:
|
||||||
@ -806,7 +806,7 @@ class PowerViewShadeDualOverlappedFront(PowerViewShadeDualOverlappedBase):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the shade."""
|
"""Initialize the shade."""
|
||||||
super().__init__(coordinator, device_info, room_name, shade, name)
|
super().__init__(coordinator, device_info, room_name, shade, name)
|
||||||
self._attr_unique_id = f"{self._shade.id}_front"
|
self._attr_unique_id = f"{self._attr_unique_id}_front"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self) -> bool:
|
def should_poll(self) -> bool:
|
||||||
@ -862,7 +862,7 @@ class PowerViewShadeDualOverlappedRear(PowerViewShadeDualOverlappedBase):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the shade."""
|
"""Initialize the shade."""
|
||||||
super().__init__(coordinator, device_info, room_name, shade, name)
|
super().__init__(coordinator, device_info, room_name, shade, name)
|
||||||
self._attr_unique_id = f"{self._shade.id}_rear"
|
self._attr_unique_id = f"{self._attr_unique_id}_rear"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self) -> bool:
|
def should_poll(self) -> bool:
|
||||||
|
@ -26,12 +26,12 @@ class HDEntity(CoordinatorEntity[PowerviewShadeUpdateCoordinator]):
|
|||||||
coordinator: PowerviewShadeUpdateCoordinator,
|
coordinator: PowerviewShadeUpdateCoordinator,
|
||||||
device_info: PowerviewDeviceInfo,
|
device_info: PowerviewDeviceInfo,
|
||||||
room_name: str,
|
room_name: str,
|
||||||
unique_id: str,
|
powerview_id: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the entity."""
|
"""Initialize the entity."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self._room_name = room_name
|
self._room_name = room_name
|
||||||
self._attr_unique_id = unique_id
|
self._attr_unique_id = f"{device_info.serial_number}_{powerview_id}"
|
||||||
self._device_info = device_info
|
self._device_info = device_info
|
||||||
self._configuration_url = self.coordinator.hub.url
|
self._configuration_url = self.coordinator.hub.url
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ def firmware_json(api_version: int) -> str:
|
|||||||
def rooms_json(api_version: int) -> str:
|
def rooms_json(api_version: int) -> str:
|
||||||
"""Return the get_resources fixture for a specific device."""
|
"""Return the get_resources fixture for a specific device."""
|
||||||
if api_version == 1:
|
if api_version == 1:
|
||||||
return "gen2/rooms.json"
|
return "gen1/rooms.json"
|
||||||
if api_version == 2:
|
if api_version == 2:
|
||||||
return "gen2/rooms.json"
|
return "gen2/rooms.json"
|
||||||
if api_version == 3:
|
if api_version == 3:
|
||||||
@ -124,7 +124,7 @@ def rooms_json(api_version: int) -> str:
|
|||||||
def scenes_json(api_version: int) -> str:
|
def scenes_json(api_version: int) -> str:
|
||||||
"""Return the get_resources fixture for a specific device."""
|
"""Return the get_resources fixture for a specific device."""
|
||||||
if api_version == 1:
|
if api_version == 1:
|
||||||
return "gen2/scenes.json"
|
return "gen1/scenes.json"
|
||||||
if api_version == 2:
|
if api_version == 2:
|
||||||
return "gen2/scenes.json"
|
return "gen2/scenes.json"
|
||||||
if api_version == 3:
|
if api_version == 3:
|
||||||
@ -137,7 +137,7 @@ def scenes_json(api_version: int) -> str:
|
|||||||
def shades_json(api_version: int) -> str:
|
def shades_json(api_version: int) -> str:
|
||||||
"""Return the get_resources fixture for a specific device."""
|
"""Return the get_resources fixture for a specific device."""
|
||||||
if api_version == 1:
|
if api_version == 1:
|
||||||
return "gen2/shades.json"
|
return "gen1/shades.json"
|
||||||
if api_version == 2:
|
if api_version == 2:
|
||||||
return "gen2/shades.json"
|
return "gen2/shades.json"
|
||||||
if api_version == 3:
|
if api_version == 3:
|
||||||
|
@ -6,6 +6,7 @@ from homeassistant import config_entries
|
|||||||
from homeassistant.components import dhcp, zeroconf
|
from homeassistant.components import dhcp, zeroconf
|
||||||
|
|
||||||
MOCK_MAC = "AA::BB::CC::DD::EE::FF"
|
MOCK_MAC = "AA::BB::CC::DD::EE::FF"
|
||||||
|
MOCK_SERIAL = "A1B2C3D4E5G6H7"
|
||||||
|
|
||||||
HOMEKIT_DISCOVERY_GEN2 = zeroconf.ZeroconfServiceInfo(
|
HOMEKIT_DISCOVERY_GEN2 = zeroconf.ZeroconfServiceInfo(
|
||||||
ip_address="1.2.3.4",
|
ip_address="1.2.3.4",
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"roomIds": [4896],
|
||||||
|
"roomData": [
|
||||||
|
{
|
||||||
|
"id": 4896,
|
||||||
|
"name": "U3BpbmRsZQ==",
|
||||||
|
"order": 0,
|
||||||
|
"colorId": 11,
|
||||||
|
"iconId": 77,
|
||||||
|
"name_unicode": "Spindle"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,188 @@
|
|||||||
|
{
|
||||||
|
"sceneIds": [
|
||||||
|
19831, 4068, 55363, 43508, 59372, 48243, 54636, 20625, 4034, 59103, 61648,
|
||||||
|
24626, 64679, 22498, 28856, 25458, 51159, 959
|
||||||
|
],
|
||||||
|
"sceneData": [
|
||||||
|
{
|
||||||
|
"id": 19831,
|
||||||
|
"networkNumber": 0,
|
||||||
|
"name": "Q2xvc2UgTG91bmdlIFJvb20=",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 0,
|
||||||
|
"colorId": 7,
|
||||||
|
"iconId": 171,
|
||||||
|
"name_unicode": "Close Lounge Room"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4068,
|
||||||
|
"networkNumber": 1,
|
||||||
|
"name": "Q2xvc2UgQmVkIDQ=",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 1,
|
||||||
|
"colorId": 7,
|
||||||
|
"iconId": 10,
|
||||||
|
"name_unicode": "Close Bed 4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 55363,
|
||||||
|
"networkNumber": 2,
|
||||||
|
"name": "Q2xvc2UgQmVkIDI=",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 2,
|
||||||
|
"colorId": 11,
|
||||||
|
"iconId": 171,
|
||||||
|
"name_unicode": "Close Bed 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 43508,
|
||||||
|
"networkNumber": 3,
|
||||||
|
"name": "Q2xvc2UgTWFzdGVyIEJlZA==",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 3,
|
||||||
|
"colorId": 11,
|
||||||
|
"iconId": 10,
|
||||||
|
"name_unicode": "Close Master Bed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 59372,
|
||||||
|
"networkNumber": 4,
|
||||||
|
"name": "Q2xvc2UgRmFtaWx5",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 4,
|
||||||
|
"colorId": 0,
|
||||||
|
"iconId": 171,
|
||||||
|
"name_unicode": "Close Family"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 48243,
|
||||||
|
"networkNumber": 5,
|
||||||
|
"name": "T3BlbiBCZWQgNA==",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 5,
|
||||||
|
"colorId": 0,
|
||||||
|
"iconId": 10,
|
||||||
|
"name_unicode": "Open Bed 4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 54636,
|
||||||
|
"networkNumber": 6,
|
||||||
|
"name": "T3BlbiBNYXN0ZXIgQmVk",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 6,
|
||||||
|
"colorId": 0,
|
||||||
|
"iconId": 26,
|
||||||
|
"name_unicode": "Open Master Bed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 20625,
|
||||||
|
"networkNumber": 7,
|
||||||
|
"name": "T3BlbiBCZWQgMw==",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 7,
|
||||||
|
"colorId": 7,
|
||||||
|
"iconId": 26,
|
||||||
|
"name_unicode": "Open Bed 3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4034,
|
||||||
|
"networkNumber": 8,
|
||||||
|
"name": "T3BlbiBGYW1pbHk=",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 8,
|
||||||
|
"colorId": 11,
|
||||||
|
"iconId": 26,
|
||||||
|
"name_unicode": "Open Family"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 59103,
|
||||||
|
"networkNumber": 9,
|
||||||
|
"name": "Q2xvc2UgU3R1ZHk=",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 9,
|
||||||
|
"colorId": 0,
|
||||||
|
"iconId": 171,
|
||||||
|
"name_unicode": "Close Study"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 61648,
|
||||||
|
"networkNumber": 10,
|
||||||
|
"name": "T3BlbiBBbGw=",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 10,
|
||||||
|
"colorId": 11,
|
||||||
|
"iconId": 26,
|
||||||
|
"name_unicode": "Open All"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 24626,
|
||||||
|
"networkNumber": 11,
|
||||||
|
"name": "Q2xvc2UgQWxs",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 11,
|
||||||
|
"colorId": 0,
|
||||||
|
"iconId": 171,
|
||||||
|
"name_unicode": "Close All"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 64679,
|
||||||
|
"networkNumber": 12,
|
||||||
|
"name": "T3BlbiBLaXRjaGVu",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 12,
|
||||||
|
"colorId": 7,
|
||||||
|
"iconId": 26,
|
||||||
|
"name_unicode": "Open Kitchen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 22498,
|
||||||
|
"networkNumber": 13,
|
||||||
|
"name": "T3BlbiBMb3VuZ2UgUm9vbQ==",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 13,
|
||||||
|
"colorId": 7,
|
||||||
|
"iconId": 26,
|
||||||
|
"name_unicode": "Open Lounge Room"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 25458,
|
||||||
|
"networkNumber": 14,
|
||||||
|
"name": "T3BlbiBCZWQgMg==",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 14,
|
||||||
|
"colorId": 0,
|
||||||
|
"iconId": 26,
|
||||||
|
"name_unicode": "Open Bed 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 46225,
|
||||||
|
"networkNumber": 15,
|
||||||
|
"name": "Q2xvc2UgQmVkIDM=",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 15,
|
||||||
|
"colorId": 0,
|
||||||
|
"iconId": 26,
|
||||||
|
"name_unicode": "Close Bed 3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 51159,
|
||||||
|
"networkNumber": 16,
|
||||||
|
"name": "Q2xvc2UgS2l0Y2hlbg==",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 16,
|
||||||
|
"colorId": 0,
|
||||||
|
"iconId": 26,
|
||||||
|
"name_unicode": "Close Kitchen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 959,
|
||||||
|
"networkNumber": 17,
|
||||||
|
"name": "T3BlbiBTdHVkeQ==",
|
||||||
|
"roomId": 4896,
|
||||||
|
"order": 17,
|
||||||
|
"colorId": 0,
|
||||||
|
"iconId": 26,
|
||||||
|
"name_unicode": "Open Study"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"shadeIds": [36492, 65111, 7003, 53627],
|
||||||
|
"shadeData": [
|
||||||
|
{
|
||||||
|
"id": 36492,
|
||||||
|
"name": "S2l0Y2hlbiBOb3J0aA==",
|
||||||
|
"roomId": 4896,
|
||||||
|
"groupId": 35661,
|
||||||
|
"order": 0,
|
||||||
|
"type": 40,
|
||||||
|
"batteryStrength": 116,
|
||||||
|
"batteryStatus": 3,
|
||||||
|
"positions": { "position1": 65535, "posKind1": 1 },
|
||||||
|
"name_unicode": "Kitchen North"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 65111,
|
||||||
|
"name": "S2l0Y2hlbiBXZXN0",
|
||||||
|
"roomId": 4896,
|
||||||
|
"groupId": 35661,
|
||||||
|
"order": 1,
|
||||||
|
"type": 40,
|
||||||
|
"batteryStrength": 124,
|
||||||
|
"batteryStatus": 3,
|
||||||
|
"positions": { "position1": 65535, "posKind1": 3 },
|
||||||
|
"name_unicode": "Kitchen West"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7003,
|
||||||
|
"name": "QmF0aCBFYXN0",
|
||||||
|
"roomId": 4896,
|
||||||
|
"groupId": 35661,
|
||||||
|
"order": 2,
|
||||||
|
"type": 40,
|
||||||
|
"batteryStrength": 94,
|
||||||
|
"batteryStatus": 1,
|
||||||
|
"positions": { "position1": 65535, "posKind1": 1 },
|
||||||
|
"name_unicode": "Bath East"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 53627,
|
||||||
|
"name": "QmF0aCBTb3V0aA==",
|
||||||
|
"roomId": 4896,
|
||||||
|
"groupId": 35661,
|
||||||
|
"order": 3,
|
||||||
|
"type": 40,
|
||||||
|
"batteryStrength": 127,
|
||||||
|
"batteryStatus": 3,
|
||||||
|
"positions": { "position1": 65535, "posKind1": 3 },
|
||||||
|
"name_unicode": "Bath South"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -1,34 +1,34 @@
|
|||||||
{
|
{
|
||||||
"userData": {
|
"userData": {
|
||||||
"enableScheduledEvents": true,
|
|
||||||
"staticIp": false,
|
|
||||||
"sceneControllerCount": 0,
|
|
||||||
"accessPointCount": 0,
|
|
||||||
"shadeCount": 5,
|
|
||||||
"ip": "192.168.0.20",
|
|
||||||
"groupCount": 9,
|
|
||||||
"scheduledEventCount": 0,
|
|
||||||
"editingEnabled": true,
|
|
||||||
"roomCount": 5,
|
|
||||||
"setupCompleted": false,
|
|
||||||
"sceneCount": 18,
|
|
||||||
"sceneControllerMemberCount": 0,
|
|
||||||
"mask": "255.255.255.0",
|
|
||||||
"hubName": "UG93ZXJ2aWV3IEdlbmVyYXRpb24gMQ==",
|
|
||||||
"rfID": "0x8B2A",
|
|
||||||
"remoteConnectEnabled": false,
|
|
||||||
"multiSceneMemberCount": 0,
|
|
||||||
"rfStatus": 0,
|
|
||||||
"serialNumber": "A1B2C3D4E5G6H7",
|
"serialNumber": "A1B2C3D4E5G6H7",
|
||||||
"undefinedShadeCount": 0,
|
"rfID": "0x8B2A",
|
||||||
"sceneMemberCount": 18,
|
"rfIDInt": 35626,
|
||||||
"unassignedShadeCount": 0,
|
"rfStatus": 0,
|
||||||
"multiSceneCount": 0,
|
"hubName": "UG93ZXJ2aWV3IEdlbmVyYXRpb24gMQ==",
|
||||||
"addressKind": "newPrimary",
|
|
||||||
"gateway": "192.168.0.1",
|
|
||||||
"localTimeDataSet": true,
|
|
||||||
"dns": "192.168.0.1",
|
|
||||||
"macAddress": "AA:BB:CC:DD:EE:FF",
|
"macAddress": "AA:BB:CC:DD:EE:FF",
|
||||||
"rfIDInt": 35626
|
"roomCount": 1,
|
||||||
|
"shadeCount": 4,
|
||||||
|
"groupCount": 5,
|
||||||
|
"sceneCount": 9,
|
||||||
|
"sceneMemberCount": 24,
|
||||||
|
"multiSceneCount": 0,
|
||||||
|
"multiSceneMemberCount": 0,
|
||||||
|
"scheduledEventCount": 4,
|
||||||
|
"sceneControllerCount": 0,
|
||||||
|
"sceneControllerMemberCount": 0,
|
||||||
|
"accessPointCount": 0,
|
||||||
|
"localTimeDataSet": true,
|
||||||
|
"enableScheduledEvents": true,
|
||||||
|
"remoteConnectEnabled": true,
|
||||||
|
"editingEnabled": true,
|
||||||
|
"setupCompleted": false,
|
||||||
|
"gateway": "192.168.0.1",
|
||||||
|
"mask": "255.255.255.0",
|
||||||
|
"ip": "192.168.0.20",
|
||||||
|
"dns": "192.168.0.1",
|
||||||
|
"staticIp": false,
|
||||||
|
"addressKind": "newPrimary",
|
||||||
|
"unassignedShadeCount": 0,
|
||||||
|
"undefinedShadeCount": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,9 @@ from homeassistant.components.hunterdouglas_powerview.const import DOMAIN
|
|||||||
from homeassistant.const import CONF_API_VERSION, CONF_HOST, CONF_NAME
|
from homeassistant.const import CONF_API_VERSION, CONF_HOST, CONF_NAME
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import FlowResultType
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
|
import homeassistant.helpers.entity_registry as er
|
||||||
|
|
||||||
from .const import DHCP_DATA, DISCOVERY_DATA, HOMEKIT_DATA
|
from .const import DHCP_DATA, DISCOVERY_DATA, HOMEKIT_DATA, MOCK_SERIAL
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, load_json_object_fixture
|
from tests.common import MockConfigEntry, load_json_object_fixture
|
||||||
|
|
||||||
@ -40,7 +41,7 @@ async def test_user_form(
|
|||||||
assert result2["type"] is FlowResultType.CREATE_ENTRY
|
assert result2["type"] is FlowResultType.CREATE_ENTRY
|
||||||
assert result2["title"] == f"Powerview Generation {api_version}"
|
assert result2["title"] == f"Powerview Generation {api_version}"
|
||||||
assert result2["data"] == {CONF_HOST: "1.2.3.4", CONF_API_VERSION: api_version}
|
assert result2["data"] == {CONF_HOST: "1.2.3.4", CONF_API_VERSION: api_version}
|
||||||
assert result2["result"].unique_id == "A1B2C3D4E5G6H7"
|
assert result2["result"].unique_id == MOCK_SERIAL
|
||||||
|
|
||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
@ -100,7 +101,7 @@ async def test_form_homekit_and_dhcp_cannot_connect(
|
|||||||
assert result3["type"] is FlowResultType.CREATE_ENTRY
|
assert result3["type"] is FlowResultType.CREATE_ENTRY
|
||||||
assert result3["title"] == f"Powerview Generation {api_version}"
|
assert result3["title"] == f"Powerview Generation {api_version}"
|
||||||
assert result3["data"] == {CONF_HOST: "1.2.3.4", CONF_API_VERSION: api_version}
|
assert result3["data"] == {CONF_HOST: "1.2.3.4", CONF_API_VERSION: api_version}
|
||||||
assert result3["result"].unique_id == "A1B2C3D4E5G6H7"
|
assert result3["result"].unique_id == MOCK_SERIAL
|
||||||
|
|
||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
@ -142,7 +143,7 @@ async def test_form_homekit_and_dhcp(
|
|||||||
assert result2["type"] is FlowResultType.CREATE_ENTRY
|
assert result2["type"] is FlowResultType.CREATE_ENTRY
|
||||||
assert result2["title"] == f"Powerview Generation {api_version}"
|
assert result2["title"] == f"Powerview Generation {api_version}"
|
||||||
assert result2["data"] == {CONF_HOST: "1.2.3.4", CONF_API_VERSION: api_version}
|
assert result2["data"] == {CONF_HOST: "1.2.3.4", CONF_API_VERSION: api_version}
|
||||||
assert result2["result"].unique_id == "A1B2C3D4E5G6H7"
|
assert result2["result"].unique_id == MOCK_SERIAL
|
||||||
|
|
||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
@ -225,7 +226,7 @@ async def test_form_cannot_connect(
|
|||||||
assert result3["type"] is FlowResultType.CREATE_ENTRY
|
assert result3["type"] is FlowResultType.CREATE_ENTRY
|
||||||
assert result3["title"] == f"Powerview Generation {api_version}"
|
assert result3["title"] == f"Powerview Generation {api_version}"
|
||||||
assert result3["data"] == {CONF_HOST: "1.2.3.4", CONF_API_VERSION: api_version}
|
assert result3["data"] == {CONF_HOST: "1.2.3.4", CONF_API_VERSION: api_version}
|
||||||
assert result3["result"].unique_id == "A1B2C3D4E5G6H7"
|
assert result3["result"].unique_id == MOCK_SERIAL
|
||||||
|
|
||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
@ -269,7 +270,7 @@ async def test_form_no_data(
|
|||||||
assert result3["type"] is FlowResultType.CREATE_ENTRY
|
assert result3["type"] is FlowResultType.CREATE_ENTRY
|
||||||
assert result3["title"] == f"Powerview Generation {api_version}"
|
assert result3["title"] == f"Powerview Generation {api_version}"
|
||||||
assert result3["data"] == {CONF_HOST: "1.2.3.4", CONF_API_VERSION: api_version}
|
assert result3["data"] == {CONF_HOST: "1.2.3.4", CONF_API_VERSION: api_version}
|
||||||
assert result3["result"].unique_id == "A1B2C3D4E5G6H7"
|
assert result3["result"].unique_id == MOCK_SERIAL
|
||||||
|
|
||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
@ -308,7 +309,7 @@ async def test_form_unknown_exception(
|
|||||||
assert result2["type"] is FlowResultType.CREATE_ENTRY
|
assert result2["type"] is FlowResultType.CREATE_ENTRY
|
||||||
assert result2["title"] == f"Powerview Generation {api_version}"
|
assert result2["title"] == f"Powerview Generation {api_version}"
|
||||||
assert result2["data"] == {CONF_HOST: "1.2.3.4", CONF_API_VERSION: api_version}
|
assert result2["data"] == {CONF_HOST: "1.2.3.4", CONF_API_VERSION: api_version}
|
||||||
assert result2["result"].unique_id == "A1B2C3D4E5G6H7"
|
assert result2["result"].unique_id == MOCK_SERIAL
|
||||||
|
|
||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
@ -347,6 +348,57 @@ async def test_form_unsupported_device(
|
|||||||
assert result3["type"] is FlowResultType.CREATE_ENTRY
|
assert result3["type"] is FlowResultType.CREATE_ENTRY
|
||||||
assert result3["title"] == f"Powerview Generation {api_version}"
|
assert result3["title"] == f"Powerview Generation {api_version}"
|
||||||
assert result3["data"] == {CONF_HOST: "1.2.3.4", CONF_API_VERSION: api_version}
|
assert result3["data"] == {CONF_HOST: "1.2.3.4", CONF_API_VERSION: api_version}
|
||||||
assert result3["result"].unique_id == "A1B2C3D4E5G6H7"
|
assert result3["result"].unique_id == MOCK_SERIAL
|
||||||
|
|
||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("mock_hunterdouglas_hub")
|
||||||
|
@pytest.mark.parametrize("api_version", [1, 2, 3])
|
||||||
|
async def test_migrate_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
api_version: int,
|
||||||
|
) -> None:
|
||||||
|
"""Test migrate to newest version."""
|
||||||
|
entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
data={"host": "1.2.3.4"},
|
||||||
|
unique_id=MOCK_SERIAL,
|
||||||
|
version=1,
|
||||||
|
minor_version=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add entries with int unique_id
|
||||||
|
entity_registry.async_get_or_create(
|
||||||
|
domain="cover",
|
||||||
|
platform="hunterdouglas_powerview",
|
||||||
|
unique_id=123,
|
||||||
|
config_entry=entry,
|
||||||
|
)
|
||||||
|
# Add entries with a str unique_id not starting with entry.unique_id
|
||||||
|
entity_registry.async_get_or_create(
|
||||||
|
domain="cover",
|
||||||
|
platform="hunterdouglas_powerview",
|
||||||
|
unique_id="old_unique_id",
|
||||||
|
config_entry=entry,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert entry.version == 1
|
||||||
|
assert entry.minor_version == 1
|
||||||
|
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert entry.version == 1
|
||||||
|
assert entry.minor_version == 2
|
||||||
|
|
||||||
|
# Reload the registry entries
|
||||||
|
registry_entries = er.async_entries_for_config_entry(
|
||||||
|
entity_registry, entry.entry_id
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ensure the IDs have been migrated
|
||||||
|
for reg_entry in registry_entries:
|
||||||
|
assert reg_entry.unique_id.startswith(f"{entry.unique_id}_")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user