From 6b138a276a0842aa5fa5bd866c671c7d18876e4a Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Thu, 23 Nov 2023 12:55:21 +0100 Subject: [PATCH] Add diagnostics platform to Reolink (#104378) --- .../components/reolink/diagnostics.py | 46 +++++++++++++++++ homeassistant/components/reolink/host.py | 9 ++++ tests/components/reolink/conftest.py | 12 +++++ .../reolink/snapshots/test_diagnostics.ambr | 50 +++++++++++++++++++ tests/components/reolink/test_diagnostics.py | 25 ++++++++++ 5 files changed, 142 insertions(+) create mode 100644 homeassistant/components/reolink/diagnostics.py create mode 100644 tests/components/reolink/snapshots/test_diagnostics.ambr create mode 100644 tests/components/reolink/test_diagnostics.py diff --git a/homeassistant/components/reolink/diagnostics.py b/homeassistant/components/reolink/diagnostics.py new file mode 100644 index 00000000000..04b476296f8 --- /dev/null +++ b/homeassistant/components/reolink/diagnostics.py @@ -0,0 +1,46 @@ +"""Diagnostics support for Reolink.""" +from __future__ import annotations + +from typing import Any + +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant + +from . import ReolinkData +from .const import DOMAIN + + +async def async_get_config_entry_diagnostics( + hass: HomeAssistant, config_entry: ConfigEntry +) -> dict[str, Any]: + """Return diagnostics for a config entry.""" + reolink_data: ReolinkData = hass.data[DOMAIN][config_entry.entry_id] + host = reolink_data.host + api = host.api + + IPC_cam: dict[int, dict[str, Any]] = {} + for ch in api.channels: + IPC_cam[ch] = {} + IPC_cam[ch]["model"] = api.camera_model(ch) + IPC_cam[ch]["firmware version"] = api.camera_sw_version(ch) + + return { + "model": api.model, + "hardware version": api.hardware_version, + "firmware version": api.sw_version, + "HTTPS": api.use_https, + "HTTP(S) port": api.port, + "WiFi connection": api.wifi_connection, + "WiFi signal": api.wifi_signal, + "RTMP enabled": api.rtmp_enabled, + "RTSP enabled": api.rtsp_enabled, + "ONVIF enabled": api.onvif_enabled, + "event connection": host.event_connection, + "stream protocol": api.protocol, + "channels": api.channels, + "stream channels": api.stream_channels, + "IPC cams": IPC_cam, + "capabilities": api.capabilities, + "api versions": api.checked_api_versions, + "abilities": api.abilities, + } diff --git a/homeassistant/components/reolink/host.py b/homeassistant/components/reolink/host.py index 0075bbac4e6..f6eb4cb0e55 100644 --- a/homeassistant/components/reolink/host.py +++ b/homeassistant/components/reolink/host.py @@ -661,3 +661,12 @@ class ReolinkHost: for channel in channels: async_dispatcher_send(self._hass, f"{self.webhook_id}_{channel}", {}) + + @property + def event_connection(self) -> str: + """Type of connection to receive events.""" + if self._webhook_reachable: + return "ONVIF push" + if self._long_poll_received: + return "ONVIF long polling" + return "Fast polling" diff --git a/tests/components/reolink/conftest.py b/tests/components/reolink/conftest.py index e8980b615e2..75d2dc0c661 100644 --- a/tests/components/reolink/conftest.py +++ b/tests/components/reolink/conftest.py @@ -63,6 +63,8 @@ def reolink_connect_class( host_mock.use_https = TEST_USE_HTTPS host_mock.is_admin = True host_mock.user_level = "admin" + host_mock.protocol = "rtsp" + host_mock.channels = [0] host_mock.stream_channels = [0] host_mock.sw_version_update_required = False host_mock.hardware_version = "IPC_00000" @@ -75,6 +77,16 @@ def reolink_connect_class( host_mock.session_active = True host_mock.timeout = 60 host_mock.renewtimer.return_value = 600 + host_mock.wifi_connection = False + host_mock.wifi_signal = None + host_mock.whiteled_mode_list.return_value = [] + host_mock.zoom_range.return_value = { + "zoom": {"pos": {"min": 0, "max": 100}}, + "focus": {"pos": {"min": 0, "max": 100}}, + } + host_mock.capabilities = {"Host": ["RTSP"], "0": ["motion_detection"]} + host_mock.checked_api_versions = {"GetEvents": 1} + host_mock.abilities = {"abilityChn": [{"aiTrack": {"permit": 0, "ver": 0}}]} yield host_mock_class diff --git a/tests/components/reolink/snapshots/test_diagnostics.ambr b/tests/components/reolink/snapshots/test_diagnostics.ambr new file mode 100644 index 00000000000..604a9364320 --- /dev/null +++ b/tests/components/reolink/snapshots/test_diagnostics.ambr @@ -0,0 +1,50 @@ +# serializer version: 1 +# name: test_entry_diagnostics + dict({ + 'HTTP(S) port': 1234, + 'HTTPS': True, + 'IPC cams': dict({ + '0': dict({ + 'firmware version': 'v1.1.0.0.0.0000', + 'model': 'RLC-123', + }), + }), + 'ONVIF enabled': True, + 'RTMP enabled': True, + 'RTSP enabled': True, + 'WiFi connection': False, + 'WiFi signal': None, + 'abilities': dict({ + 'abilityChn': list([ + dict({ + 'aiTrack': dict({ + 'permit': 0, + 'ver': 0, + }), + }), + ]), + }), + 'api versions': dict({ + 'GetEvents': 1, + }), + 'capabilities': dict({ + '0': list([ + 'motion_detection', + ]), + 'Host': list([ + 'RTSP', + ]), + }), + 'channels': list([ + 0, + ]), + 'event connection': 'Fast polling', + 'firmware version': 'v1.0.0.0.0.0000', + 'hardware version': 'IPC_00000', + 'model': 'RLC-123', + 'stream channels': list([ + 0, + ]), + 'stream protocol': 'rtsp', + }) +# --- diff --git a/tests/components/reolink/test_diagnostics.py b/tests/components/reolink/test_diagnostics.py new file mode 100644 index 00000000000..57b474c13ad --- /dev/null +++ b/tests/components/reolink/test_diagnostics.py @@ -0,0 +1,25 @@ +"""Test Reolink diagnostics.""" + +from unittest.mock import MagicMock + +from syrupy.assertion import SnapshotAssertion + +from homeassistant.core import HomeAssistant + +from tests.common import MockConfigEntry +from tests.components.diagnostics import get_diagnostics_for_config_entry +from tests.typing import ClientSessionGenerator + + +async def test_entry_diagnostics( + hass: HomeAssistant, + hass_client: ClientSessionGenerator, + reolink_connect: MagicMock, + config_entry: MockConfigEntry, + snapshot: SnapshotAssertion, +) -> None: + """Test Reolink diagnostics.""" + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + diag = await get_diagnostics_for_config_entry(hass, hass_client, config_entry) + assert diag == snapshot