Fix Reolink dispatcher ID for onvif fallback (#131953)

This commit is contained in:
starkillerOG 2024-12-02 22:18:24 +01:00 committed by GitHub
parent 0a977d070b
commit db430beb5b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 26 additions and 11 deletions

View File

@ -176,14 +176,14 @@ class ReolinkPushBinarySensorEntity(ReolinkBinarySensorEntity):
self.async_on_remove( self.async_on_remove(
async_dispatcher_connect( async_dispatcher_connect(
self.hass, self.hass,
f"{self._host.webhook_id}_{self._channel}", f"{self._host.unique_id}_{self._channel}",
self._async_handle_event, self._async_handle_event,
) )
) )
self.async_on_remove( self.async_on_remove(
async_dispatcher_connect( async_dispatcher_connect(
self.hass, self.hass,
f"{self._host.webhook_id}_all", f"{self._host.unique_id}_all",
self._async_handle_event, self._async_handle_event,
) )
) )

View File

@ -723,7 +723,7 @@ class ReolinkHost:
self._hass, POLL_INTERVAL_NO_PUSH, self._poll_job self._hass, POLL_INTERVAL_NO_PUSH, self._poll_job
) )
self._signal_write_ha_state(None) self._signal_write_ha_state()
async def handle_webhook( async def handle_webhook(
self, hass: HomeAssistant, webhook_id: str, request: Request self, hass: HomeAssistant, webhook_id: str, request: Request
@ -782,7 +782,7 @@ class ReolinkHost:
"Could not poll motion state after losing connection during receiving ONVIF event" "Could not poll motion state after losing connection during receiving ONVIF event"
) )
return return
async_dispatcher_send(hass, f"{webhook_id}_all", {}) self._signal_write_ha_state()
return return
message = data.decode("utf-8") message = data.decode("utf-8")
@ -795,14 +795,14 @@ class ReolinkHost:
self._signal_write_ha_state(channels) self._signal_write_ha_state(channels)
def _signal_write_ha_state(self, channels: list[int] | None) -> None: def _signal_write_ha_state(self, channels: list[int] | None = None) -> None:
"""Update the binary sensors with async_write_ha_state.""" """Update the binary sensors with async_write_ha_state."""
if channels is None: if channels is None:
async_dispatcher_send(self._hass, f"{self.webhook_id}_all", {}) async_dispatcher_send(self._hass, f"{self.unique_id}_all", {})
return return
for channel in channels: for channel in channels:
async_dispatcher_send(self._hass, f"{self.webhook_id}_{channel}", {}) async_dispatcher_send(self._hass, f"{self.unique_id}_{channel}", {})
@property @property
def event_connection(self) -> str: def event_connection(self) -> str:

View File

@ -21,13 +21,15 @@ from homeassistant.components.reolink.host import (
) )
from homeassistant.components.webhook import async_handle_webhook from homeassistant.components.webhook import async_handle_webhook
from homeassistant.config_entries import ConfigEntryState from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import Platform from homeassistant.const import STATE_OFF, STATE_ON, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.network import NoURLAvailableError from homeassistant.helpers.network import NoURLAvailableError
from homeassistant.util.aiohttp import MockRequest from homeassistant.util.aiohttp import MockRequest
from .conftest import TEST_NVR_NAME
from tests.common import MockConfigEntry, async_fire_time_changed from tests.common import MockConfigEntry, async_fire_time_changed
from tests.components.diagnostics import get_diagnostics_for_config_entry from tests.components.diagnostics import get_diagnostics_for_config_entry
from tests.typing import ClientSessionGenerator from tests.typing import ClientSessionGenerator
@ -92,23 +94,32 @@ async def test_webhook_callback(
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
) -> None: ) -> None:
"""Test webhook callback with motion sensor.""" """Test webhook callback with motion sensor."""
assert await hass.config_entries.async_setup(config_entry.entry_id) reolink_connect.motion_detected.return_value = False
with patch("homeassistant.components.reolink.PLATFORMS", [Platform.BINARY_SENSOR]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.LOADED assert config_entry.state is ConfigEntryState.LOADED
entity_id = f"{Platform.BINARY_SENSOR}.{TEST_NVR_NAME}_motion"
webhook_id = config_entry.runtime_data.host.webhook_id webhook_id = config_entry.runtime_data.host.webhook_id
unique_id = config_entry.runtime_data.host.unique_id
signal_all = MagicMock() signal_all = MagicMock()
signal_ch = MagicMock() signal_ch = MagicMock()
async_dispatcher_connect(hass, f"{webhook_id}_all", signal_all) async_dispatcher_connect(hass, f"{unique_id}_all", signal_all)
async_dispatcher_connect(hass, f"{webhook_id}_0", signal_ch) async_dispatcher_connect(hass, f"{unique_id}_0", signal_ch)
client = await hass_client_no_auth() client = await hass_client_no_auth()
assert hass.states.get(entity_id).state == STATE_OFF
# test webhook callback success all channels # test webhook callback success all channels
reolink_connect.motion_detected.return_value = True
reolink_connect.ONVIF_event_callback.return_value = None reolink_connect.ONVIF_event_callback.return_value = None
await client.post(f"/api/webhook/{webhook_id}") await client.post(f"/api/webhook/{webhook_id}")
signal_all.assert_called_once() signal_all.assert_called_once()
assert hass.states.get(entity_id).state == STATE_ON
freezer.tick(timedelta(seconds=FIRST_ONVIF_TIMEOUT)) freezer.tick(timedelta(seconds=FIRST_ONVIF_TIMEOUT))
async_fire_time_changed(hass) async_fire_time_changed(hass)
@ -120,10 +131,14 @@ async def test_webhook_callback(
await client.post(f"/api/webhook/{webhook_id}") await client.post(f"/api/webhook/{webhook_id}")
signal_all.assert_not_called() signal_all.assert_not_called()
assert hass.states.get(entity_id).state == STATE_ON
# test webhook callback success single channel # test webhook callback success single channel
reolink_connect.motion_detected.return_value = False
reolink_connect.ONVIF_event_callback.return_value = [0] reolink_connect.ONVIF_event_callback.return_value = [0]
await client.post(f"/api/webhook/{webhook_id}", data="test_data") await client.post(f"/api/webhook/{webhook_id}", data="test_data")
signal_ch.assert_called_once() signal_ch.assert_called_once()
assert hass.states.get(entity_id).state == STATE_OFF
# test webhook callback single channel with error in event callback # test webhook callback single channel with error in event callback
signal_ch.reset_mock() signal_ch.reset_mock()