Skip to content

Commit

Permalink
Allow device removal (#8)
Browse files Browse the repository at this point in the history
* Allow device removal

* Bump version to v0.1.7
  • Loading branch information
jbouwh committed Aug 2, 2022
1 parent f9b8ef2 commit a1d99ff
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 4 deletions.
18 changes: 17 additions & 1 deletion custom_components/elro_connects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import SERVICE_RELOAD, Platform
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

from .const import DEFAULT_INTERVAL, DOMAIN
Expand Down Expand Up @@ -39,7 +40,7 @@ async def _async_update_data() -> dict[int, dict]:
device_update = copy.deepcopy(elro_connects_api.data)
for device_id, device_data in device_update.items():
if ATTR_DEVICE_STATE not in device_data:
# Skip entries without device state
# Unlink entry without device state
continue
if device_id not in coordinator_update:
# new device, or known state
Expand Down Expand Up @@ -109,3 +110,18 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.data[DOMAIN].pop(entry.entry_id)

return unload_ok


async def async_remove_config_entry_device(
hass: HomeAssistant, entry: ConfigEntry, device_entry: DeviceEntry
) -> bool:
"""Allow manual removal of a device if not in use."""
elro_connects_api: ElroConnectsK1 = hass.data[DOMAIN][entry.entry_id]
device_unique_id: str = device_entry.identifiers.copy().pop()[1]
device_id_str = device_unique_id[len(elro_connects_api.connector_id) + 1 :]
if not device_id_str:
return False
device_id = int(device_id_str)
if device_id in elro_connects_api.data:
return False
return True
2 changes: 1 addition & 1 deletion custom_components/elro_connects/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"requirements": ["lib-elro-connects==0.5.2"],
"codeowners": ["@jbouwh"],
"iot_class": "local_polling",
"version": "0.2.0"
"version": "0.1.7"
}
2 changes: 1 addition & 1 deletion hacs.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "Elro Connects",
"hacs": "1.6.0",
"hacs": "1.0.0",
"homeassistant": "2022.7.0"
}
65 changes: 65 additions & 0 deletions tests/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,31 @@
import pytest
from pytest_homeassistant_custom_component.common import async_fire_time_changed

from custom_components.elro_connects import async_remove_config_entry_device
from custom_components.elro_connects.const import DOMAIN
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.setup import async_setup_component
from homeassistant.util import dt

from .test_common import MOCK_DEVICE_STATUS_DATA


async def help_remove_device(hass, ws_client, device_id, config_entry_id):
"""Remove config entry from a device."""
await ws_client.send_json(
{
"id": 5,
"type": "config/device_registry/remove_config_entry",
"config_entry_id": config_entry_id,
"device_id": device_id,
}
)
response = await ws_client.receive_json()
assert response["success"]


async def test_setup_integration_no_data(
hass: HomeAssistant,
mock_k1_connector: dict[AsyncMock],
Expand Down Expand Up @@ -113,3 +129,52 @@ async def test_configure_platforms_dynamically(
assert hass.states.get("siren.beganegrond").state == "off"
assert hass.states.get("siren.eerste_etage") is not None
assert hass.states.get("siren.zolder") is not None


async def test_remove_device_from_config_entry(
hass: HomeAssistant,
mock_k1_connector: dict[AsyncMock],
mock_entry: ConfigEntry,
) -> None:
"""Test the removing a device would work."""
# Initial status holds device info for device [1,2,4]
initial_status_data = copy.deepcopy(MOCK_DEVICE_STATUS_DATA)
# Updated status holds device info for device [1,2]
updated_status_data = copy.deepcopy(MOCK_DEVICE_STATUS_DATA)
updated_status_data.pop(4)

# setup integration with 3 siren entities
mock_k1_connector["result"].return_value = initial_status_data
assert await async_setup_component(hass, DOMAIN, {})
await hass.async_block_till_done()

# Simulate deactivation of siren 4
mock_k1_connector["result"].return_value = updated_status_data
time = dt.now() + timedelta(seconds=30)
async_fire_time_changed(hass, time)
# await coordinator.async_request_refresh()
await hass.async_block_till_done()
await hass.async_block_till_done()

connector_id = hass.data[DOMAIN][mock_entry.entry_id].connector_id
device_registry = dr.async_get(hass)
# Test removing the device for siren 4 will work
device_entry = device_registry.async_get_device(
identifiers={(DOMAIN, f"{connector_id}_4")}
)
assert device_entry
assert await async_remove_config_entry_device(hass, mock_entry, device_entry)

# Test removing the device for siren 2 will not work because it is in use
device_entry = device_registry.async_get_device(
identifiers={(DOMAIN, f"{connector_id}_2")}
)
assert device_entry
assert not await async_remove_config_entry_device(hass, mock_entry, device_entry)

# Test removing the the K1 connector device will not work
device_entry = device_registry.async_get_device(
identifiers={(DOMAIN, f"{connector_id}")}
)
assert device_entry
assert not await async_remove_config_entry_device(hass, mock_entry, device_entry)
2 changes: 1 addition & 1 deletion version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.6
0.1.7

0 comments on commit a1d99ff

Please sign in to comment.