Use the existing api client for unifiprotect repairs if available (#119640)

Co-authored-by: TheJulianJES <TheJulianJES@users.noreply.github.com>
pull/119653/head
J. Nick Koston 2024-06-13 16:17:11 -05:00 committed by GitHub
parent 7bbd28d385
commit de27f24a4c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 88 additions and 19 deletions

View File

@ -376,7 +376,9 @@ def async_get_data_for_entry_id(
hass: HomeAssistant, entry_id: str
) -> ProtectData | None:
"""Find the ProtectData instance for a config entry id."""
if entry := hass.config_entries.async_get_entry(entry_id):
if (entry := hass.config_entries.async_get_entry(entry_id)) and hasattr(
entry, "runtime_data"
):
entry = cast(UFPConfigEntry, entry)
return entry.runtime_data
return None

View File

@ -11,11 +11,12 @@ import voluptuous as vol
from homeassistant import data_entry_flow
from homeassistant.components.repairs import ConfirmRepairFlow, RepairsFlow
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import issue_registry as ir
from .const import CONF_ALLOW_EA
from .data import UFPConfigEntry
from .data import UFPConfigEntry, async_get_data_for_entry_id
from .utils import async_create_api_client
@ -219,29 +220,34 @@ class RTSPRepair(ProtectRepair):
)
@callback
def _async_get_or_create_api_client(
hass: HomeAssistant, entry: ConfigEntry
) -> ProtectApiClient:
"""Get or create an API client."""
if data := async_get_data_for_entry_id(hass, entry.entry_id):
return data.api
return async_create_api_client(hass, entry)
async def async_create_fix_flow(
hass: HomeAssistant,
issue_id: str,
data: dict[str, str | int | float | None] | None,
) -> RepairsFlow:
"""Create flow."""
if data is not None and issue_id == "ea_channel_warning":
entry_id = cast(str, data["entry_id"])
if (entry := hass.config_entries.async_get_entry(entry_id)) is not None:
api = async_create_api_client(hass, entry)
if (
data is not None
and "entry_id" in data
and (entry := hass.config_entries.async_get_entry(cast(str, data["entry_id"])))
):
api = _async_get_or_create_api_client(hass, entry)
if issue_id == "ea_channel_warning":
return EAConfirmRepair(api=api, entry=entry)
elif data is not None and issue_id == "cloud_user":
entry_id = cast(str, data["entry_id"])
if (entry := hass.config_entries.async_get_entry(entry_id)) is not None:
api = async_create_api_client(hass, entry)
if issue_id == "cloud_user":
return CloudAccountRepair(api=api, entry=entry)
elif data is not None and issue_id.startswith("rtsp_disabled_"):
entry_id = cast(str, data["entry_id"])
camera_id = cast(str, data["camera_id"])
if (entry := hass.config_entries.async_get_entry(entry_id)) is not None:
api = async_create_api_client(hass, entry)
return RTSPRepair(api=api, entry=entry, camera_id=camera_id)
if issue_id.startswith("rtsp_disabled_"):
return RTSPRepair(
api=api, entry=entry, camera_id=cast(str, data["camera_id"])
)
return ConfirmRepairFlow()

View File

@ -357,3 +357,64 @@ async def test_rtsp_writable_fix(
ufp.api.update_device.assert_called_with(
ModelType.CAMERA, doorbell.id, {"channels": channels}
)
async def test_rtsp_writable_fix_when_not_setup(
hass: HomeAssistant,
ufp: MockUFPFixture,
doorbell: Camera,
hass_client: ClientSessionGenerator,
hass_ws_client: WebSocketGenerator,
) -> None:
"""Test RTSP disabled warning if the integration is no longer set up."""
for channel in doorbell.channels:
channel.is_rtsp_enabled = False
await init_entry(hass, ufp, [doorbell])
await async_process_repairs_platforms(hass)
ws_client = await hass_ws_client(hass)
client = await hass_client()
new_doorbell = deepcopy(doorbell)
new_doorbell.channels[0].is_rtsp_enabled = True
ufp.api.get_camera = AsyncMock(side_effect=[doorbell, new_doorbell])
ufp.api.update_device = AsyncMock()
issue_id = f"rtsp_disabled_{doorbell.id}"
await ws_client.send_json({"id": 1, "type": "repairs/list_issues"})
msg = await ws_client.receive_json()
assert msg["success"]
assert len(msg["result"]["issues"]) > 0
issue = None
for i in msg["result"]["issues"]:
if i["issue_id"] == issue_id:
issue = i
assert issue is not None
# Unload the integration to ensure the fix flow still works
# if the integration is no longer set up
await hass.config_entries.async_unload(ufp.entry.entry_id)
await hass.async_block_till_done()
url = RepairsFlowIndexView.url
resp = await client.post(url, json={"handler": DOMAIN, "issue_id": issue_id})
assert resp.status == HTTPStatus.OK
data = await resp.json()
flow_id = data["flow_id"]
assert data["step_id"] == "start"
url = RepairsFlowResourceView.url.format(flow_id=flow_id)
resp = await client.post(url)
assert resp.status == HTTPStatus.OK
data = await resp.json()
assert data["type"] == "create_entry"
channels = doorbell.unifi_dict()["channels"]
channels[0]["isRtspEnabled"] = True
ufp.api.update_device.assert_called_with(
ModelType.CAMERA, doorbell.id, {"channels": channels}
)