mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Fix onvif binary sensors (#90202)
* Fix httpx client creating a new ssl context with each client While working on https://github.com/home-assistant/core/issues/83524 it was discovered that each new httpx client creates a new ssl contextf1157dbc41/httpx/_transports/default.py (L261)
If an ssl context is passed in creating a new one is avoided heref1157dbc41/httpx/_config.py (L110)
This change makes httpx ssl no-verify behavior match aiohttp ssl no-verify behavior6da04694fd/aiohttp/connector.py (L892)
aiohttp solved this by wrapping the code that generates the ssl context in an lru_cache * compact * Fix onvif binary sensors fixes #83524 needs https://github.com/hunterjm/python-onvif-zeep-async/pull/9 first to avoid recreating the memory leak * Fix memory leak in onvif Work around until https://github.com/hunterjm/python-onvif-zeep-async/pull/9 followup to https://github.com/home-assistant/core/pull/83006 * move check * onvif-zeep-async 1.2.2 * fix unloading
This commit is contained in:
parent
bd08d88812
commit
0b8fb36a7e
@ -27,6 +27,13 @@ SUBSCRIPTION_ERRORS = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _stringify_onvif_error(error: Exception) -> str:
|
||||||
|
"""Stringify ONVIF error."""
|
||||||
|
if isinstance(error, Fault):
|
||||||
|
return error.message or str(error) or "Device sent empty error"
|
||||||
|
return str(error)
|
||||||
|
|
||||||
|
|
||||||
class EventManager:
|
class EventManager:
|
||||||
"""ONVIF Event Manager."""
|
"""ONVIF Event Manager."""
|
||||||
|
|
||||||
@ -79,30 +86,30 @@ class EventManager:
|
|||||||
|
|
||||||
async def async_start(self) -> bool:
|
async def async_start(self) -> bool:
|
||||||
"""Start polling events."""
|
"""Start polling events."""
|
||||||
if await self.device.create_pullpoint_subscription():
|
if not await self.device.create_pullpoint_subscription():
|
||||||
# Create subscription manager
|
return False
|
||||||
self._subscription = self.device.create_subscription_service(
|
|
||||||
"PullPointSubscription"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Renew immediately
|
# Create subscription manager
|
||||||
await self.async_renew()
|
self._subscription = self.device.create_subscription_service(
|
||||||
|
"PullPointSubscription"
|
||||||
|
)
|
||||||
|
|
||||||
# Initialize events
|
# Renew immediately
|
||||||
pullpoint = self.device.create_pullpoint_service()
|
await self.async_renew()
|
||||||
with suppress(*SUBSCRIPTION_ERRORS):
|
|
||||||
await pullpoint.SetSynchronizationPoint()
|
|
||||||
response = await pullpoint.PullMessages(
|
|
||||||
{"MessageLimit": 100, "Timeout": dt.timedelta(seconds=5)}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Parse event initialization
|
# Initialize events
|
||||||
await self.async_parse_messages(response.NotificationMessage)
|
pullpoint = self.device.create_pullpoint_service()
|
||||||
|
with suppress(*SUBSCRIPTION_ERRORS):
|
||||||
|
await pullpoint.SetSynchronizationPoint()
|
||||||
|
response = await pullpoint.PullMessages(
|
||||||
|
{"MessageLimit": 100, "Timeout": dt.timedelta(seconds=5)}
|
||||||
|
)
|
||||||
|
|
||||||
self.started = True
|
# Parse event initialization
|
||||||
return True
|
await self.async_parse_messages(response.NotificationMessage)
|
||||||
|
|
||||||
return False
|
self.started = True
|
||||||
|
return True
|
||||||
|
|
||||||
async def async_stop(self) -> None:
|
async def async_stop(self) -> None:
|
||||||
"""Unsubscribe from events."""
|
"""Unsubscribe from events."""
|
||||||
@ -112,7 +119,8 @@ class EventManager:
|
|||||||
if not self._subscription:
|
if not self._subscription:
|
||||||
return
|
return
|
||||||
|
|
||||||
await self._subscription.Unsubscribe()
|
with suppress(*SUBSCRIPTION_ERRORS):
|
||||||
|
await self._subscription.Unsubscribe()
|
||||||
self._subscription = None
|
self._subscription = None
|
||||||
|
|
||||||
async def async_restart(self, _now: dt.datetime | None = None) -> None:
|
async def async_restart(self, _now: dt.datetime | None = None) -> None:
|
||||||
@ -148,7 +156,7 @@ class EventManager:
|
|||||||
"Retrying later: %s"
|
"Retrying later: %s"
|
||||||
),
|
),
|
||||||
self.unique_id,
|
self.unique_id,
|
||||||
err,
|
_stringify_onvif_error(err),
|
||||||
)
|
)
|
||||||
|
|
||||||
if not restarted:
|
if not restarted:
|
||||||
@ -170,7 +178,11 @@ class EventManager:
|
|||||||
.isoformat(timespec="seconds")
|
.isoformat(timespec="seconds")
|
||||||
.replace("+00:00", "Z")
|
.replace("+00:00", "Z")
|
||||||
)
|
)
|
||||||
await self._subscription.Renew(termination_time)
|
with suppress(*SUBSCRIPTION_ERRORS):
|
||||||
|
# The first time we renew, we may get a Fault error so we
|
||||||
|
# suppress it. The subscription will be restarted in
|
||||||
|
# async_restart later.
|
||||||
|
await self._subscription.Renew(termination_time)
|
||||||
|
|
||||||
def async_schedule_pull(self) -> None:
|
def async_schedule_pull(self) -> None:
|
||||||
"""Schedule async_pull_messages to run."""
|
"""Schedule async_pull_messages to run."""
|
||||||
@ -203,7 +215,7 @@ class EventManager:
|
|||||||
" '%s': %s"
|
" '%s': %s"
|
||||||
),
|
),
|
||||||
self.unique_id,
|
self.unique_id,
|
||||||
err,
|
_stringify_onvif_error(err),
|
||||||
)
|
)
|
||||||
# Treat errors as if the camera restarted. Assume that the pullpoint
|
# Treat errors as if the camera restarted. Assume that the pullpoint
|
||||||
# subscription is no longer valid.
|
# subscription is no longer valid.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user