Skip to content

Commit

Permalink
Start onvif events later (home-assistant#92354)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco authored and frenck committed May 2, 2023
1 parent 7c65166 commit 0db28dc
Showing 1 changed file with 35 additions and 12 deletions.
47 changes: 35 additions & 12 deletions homeassistant/components/onvif/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ async def async_setup(self) -> None:

# Get all device info
await self.device.update_xaddrs()
LOGGER.debug("%s: xaddrs = %s", self.name, self.device.xaddrs)

# Get device capabilities
self.onvif_capabilities = await self.device.get_capabilities()
Expand All @@ -112,21 +113,29 @@ async def async_setup(self) -> None:

# Fetch basic device info and capabilities
self.info = await self.async_get_device_info()
LOGGER.debug("Camera %s info = %s", self.name, self.info)
LOGGER.debug("%s: camera info = %s", self.name, self.info)

#
# We need to check capabilities before profiles, because we need the data
# from capabilities to determine profiles correctly.
#
# We no longer initialize events in capabilities to avoid the problem
# where cameras become slow to respond for a bit after starting events, and
# instead we start events last and than update capabilities.
#
LOGGER.debug("%s: fetching initial capabilities", self.name)
self.capabilities = await self.async_get_capabilities()

# Check profiles before capabilities since the camera may be slow to respond
# once the event manager is started in async_get_capabilities.
LOGGER.debug("%s: fetching profiles", self.name)
self.profiles = await self.async_get_profiles()
LOGGER.debug("Camera %s profiles = %s", self.name, self.profiles)

# No camera profiles to add
if not self.profiles:
raise ONVIFError("No camera profiles found")

self.capabilities = await self.async_get_capabilities()
LOGGER.debug("Camera %s capabilities = %s", self.name, self.capabilities)

if self.capabilities.ptz:
LOGGER.debug("%s: creating PTZ service", self.name)
self.device.create_ptz_service()

# Determine max resolution from profiles
Expand All @@ -136,6 +145,12 @@ async def async_setup(self) -> None:
if profile.video.encoding == "H264"
)

# Start events last since some cameras become slow to respond
# for a bit after starting events
LOGGER.debug("%s: starting events", self.name)
self.capabilities.events = await self.async_start_events()
LOGGER.debug("Camera %s capabilities = %s", self.name, self.capabilities)

async def async_stop(self, event=None):
"""Shut it all down."""
if self.events:
Expand Down Expand Up @@ -307,23 +322,31 @@ async def async_get_capabilities(self):
self.device.create_imaging_service()
imaging = True

events = False
return Capabilities(snapshot=snapshot, ptz=ptz, imaging=imaging)

async def async_start_events(self):
"""Start the event handler."""
with suppress(*GET_CAPABILITIES_EXCEPTIONS, XMLParseError):
onvif_capabilities = self.onvif_capabilities or {}
pull_point_support = onvif_capabilities.get("Events", {}).get(
"WSPullPointSupport"
)
LOGGER.debug("%s: WSPullPointSupport: %s", self.name, pull_point_support)
events = await self.events.async_start(
pull_point_support is not False, True
)
return await self.events.async_start(pull_point_support is not False, True)

return Capabilities(snapshot, events, ptz, imaging)
return False

async def async_get_profiles(self) -> list[Profile]:
"""Obtain media profiles for this device."""
media_service = self.device.create_media_service()
result = await media_service.GetProfiles()
LOGGER.debug("%s: xaddr for media_service: %s", self.name, media_service.xaddr)
try:
result = await media_service.GetProfiles()
except GET_CAPABILITIES_EXCEPTIONS:
LOGGER.debug(
"%s: Could not get profiles from ONVIF device", self.name, exc_info=True
)
raise
profiles: list[Profile] = []

if not isinstance(result, list):
Expand Down

0 comments on commit 0db28dc

Please sign in to comment.