Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
refactor

refactor
  • Loading branch information
bdraco committed Apr 13, 2023
1 parent 7ec6284 commit 7a939bf
Showing 1 changed file with 46 additions and 37 deletions.
83 changes: 46 additions & 37 deletions homeassistant/components/reolink/host.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ def __init__(
self._base_url: str = ""
self._webhook_url: str = ""
self._webhook_reachable: asyncio.Event = asyncio.Event()
self._webhook_read_done: asyncio.Event = asyncio.Event()
self._lost_subscription: bool = False

@property
Expand Down Expand Up @@ -364,52 +363,62 @@ async def handle_webhook(
self, hass: HomeAssistant, webhook_id: str, request: Request
):
"""Shield the incoming webhook callback from cancellation."""
self._webhook_read_done.clear()
shielded_task = hass.async_create_task(
self._handle_webhook(hass, webhook_id, request)
)
asyncio.shield(shielded_task)
_LOGGER.debug("Webhook '%s' called", webhook_id)
await self._webhook_read_done.wait()
if not self._webhook_reachable.is_set():
self._webhook_reachable.set()
ir.async_delete_issue(self._hass, DOMAIN, "webhook_url")
await asyncio.shield(self._handle_webhook(hass, webhook_id, request))

async def _handle_webhook(
self, hass: HomeAssistant, webhook_id: str, request: Request
):
) -> None:
"""Handle incoming webhook from Reolink for inbound messages and calls."""
try:
try:
data = await request.text()
except ConnectionResetError:
_LOGGER.debug(
"Webhook '%s' called, but lost connection before reading message, issuing poll",
webhook_id,
)
if await self._api.get_motion_state_all_ch():
async_dispatcher_send(hass, f"{webhook_id}_all", {})
return
data = await request.text()
except ConnectionResetError:
# We lost the connection before reading the message, fallback to polling
# No need for a background task here as we already know the connection is lost
_LOGGER.debug(
"Webhook '%s' called, but lost connection before reading message, issuing poll",
webhook_id,
)
if not await self._api.get_motion_state_all_ch():
_LOGGER.error(
"Could not poll motion state after losing connection during receiving ONVIF event"
)
return
finally:
self._webhook_read_done.set()
if not self._webhook_reachable.is_set():
self._webhook_reachable.set()
ir.async_delete_issue(self._hass, DOMAIN, "webhook_url")
async_dispatcher_send(hass, f"{webhook_id}_all", {})
if not data:
_LOGGER.debug(
"Webhook '%s' triggered with unknown payload: %s", webhook_id, data
)
return
# We received the data but we want handle_webhook to return as soon as possible
# so we process the data in the background
hass.async_create_background_task(
self._process_webhook_data(hass, webhook_id, data),
"Process Reolink webhook",
)

if not data:
_LOGGER.debug(
"Webhook '%s' triggered with unknown payload: %s", webhook_id, data
)
return
async def _process_webhook_data(
self, hass: HomeAssistant, webhook_id: str, data: str
) -> None:
"""Process the data from the webhook."""
# This task is executed in the background so we need to catch exceptions
# and log them
try:
channels = await self._api.ONVIF_event_callback(data)
except Exception as ex: # pylint: disable=broad-except
_LOGGER.exception(
"Error processing ONVIF event for Reolink %s: %s",
self._api.nvr_name,
ex,
)
return

if (channels := await self._api.ONVIF_event_callback(data)) is None:
async_dispatcher_send(hass, f"{webhook_id}_all", {})
return
if channels is None:
async_dispatcher_send(hass, f"{webhook_id}_all", {})
return

for channel in channels:
async_dispatcher_send(hass, f"{webhook_id}_{channel}", {})
except Exception as err: # pylint: disable=broad-except
# Make sure unexpected error in "_handle_webhook" are logged,
# since nothing is awaiting this function
_LOGGER.exception(err)
for channel in channels:
async_dispatcher_send(hass, f"{webhook_id}_{channel}", {})

0 comments on commit 7a939bf

Please sign in to comment.