Add diagnostics to Withings (#102066)
parent
6f5a72edf2
commit
b4e4a98f17
|
@ -34,6 +34,7 @@ class WithingsDataUpdateCoordinator(DataUpdateCoordinator[_T]):
|
|||
config_entry: ConfigEntry
|
||||
_default_update_interval: timedelta | None = UPDATE_INTERVAL
|
||||
_last_valid_update: datetime | None = None
|
||||
webhooks_connected: bool = False
|
||||
|
||||
def __init__(self, hass: HomeAssistant, client: WithingsClient) -> None:
|
||||
"""Initialize the Withings data coordinator."""
|
||||
|
@ -45,6 +46,7 @@ class WithingsDataUpdateCoordinator(DataUpdateCoordinator[_T]):
|
|||
|
||||
def webhook_subscription_listener(self, connected: bool) -> None:
|
||||
"""Call when webhook status changed."""
|
||||
self.webhooks_connected = connected
|
||||
if connected:
|
||||
self.update_interval = None
|
||||
else:
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
"""Diagnostics support for Withings."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from yarl import URL
|
||||
|
||||
from homeassistant.components.webhook import async_generate_url as webhook_generate_url
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_WEBHOOK_ID
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import (
|
||||
CONF_CLOUDHOOK_URL,
|
||||
WithingsMeasurementDataUpdateCoordinator,
|
||||
WithingsSleepDataUpdateCoordinator,
|
||||
)
|
||||
from .const import DOMAIN, MEASUREMENT_COORDINATOR, SLEEP_COORDINATOR
|
||||
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
hass: HomeAssistant, entry: ConfigEntry
|
||||
) -> dict[str, Any]:
|
||||
"""Return diagnostics for a config entry."""
|
||||
|
||||
webhook_url = webhook_generate_url(hass, entry.data[CONF_WEBHOOK_ID])
|
||||
url = URL(webhook_url)
|
||||
has_valid_external_webhook_url = url.scheme == "https" and url.port == 443
|
||||
|
||||
has_cloudhooks = CONF_CLOUDHOOK_URL in entry.data
|
||||
|
||||
measurement_coordinator: WithingsMeasurementDataUpdateCoordinator = hass.data[
|
||||
DOMAIN
|
||||
][entry.entry_id][MEASUREMENT_COORDINATOR]
|
||||
sleep_coordinator: WithingsSleepDataUpdateCoordinator = hass.data[DOMAIN][
|
||||
entry.entry_id
|
||||
][SLEEP_COORDINATOR]
|
||||
|
||||
return {
|
||||
"has_valid_external_webhook_url": has_valid_external_webhook_url,
|
||||
"has_cloudhooks": has_cloudhooks,
|
||||
"webhooks_connected": measurement_coordinator.webhooks_connected,
|
||||
"received_measurements": list(measurement_coordinator.data.keys()),
|
||||
"received_sleep_data": sleep_coordinator.data is not None,
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
# serializer version: 1
|
||||
# name: test_diagnostics_cloudhook_instance
|
||||
dict({
|
||||
'has_cloudhooks': True,
|
||||
'has_valid_external_webhook_url': True,
|
||||
'received_measurements': list([
|
||||
1,
|
||||
8,
|
||||
5,
|
||||
76,
|
||||
88,
|
||||
4,
|
||||
12,
|
||||
71,
|
||||
73,
|
||||
6,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
54,
|
||||
77,
|
||||
91,
|
||||
]),
|
||||
'received_sleep_data': True,
|
||||
'webhooks_connected': True,
|
||||
})
|
||||
# ---
|
||||
# name: test_diagnostics_polling_instance
|
||||
dict({
|
||||
'has_cloudhooks': False,
|
||||
'has_valid_external_webhook_url': False,
|
||||
'received_measurements': list([
|
||||
1,
|
||||
8,
|
||||
5,
|
||||
76,
|
||||
88,
|
||||
4,
|
||||
12,
|
||||
71,
|
||||
73,
|
||||
6,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
54,
|
||||
77,
|
||||
91,
|
||||
]),
|
||||
'received_sleep_data': True,
|
||||
'webhooks_connected': False,
|
||||
})
|
||||
# ---
|
||||
# name: test_diagnostics_webhook_instance
|
||||
dict({
|
||||
'has_cloudhooks': False,
|
||||
'has_valid_external_webhook_url': True,
|
||||
'received_measurements': list([
|
||||
1,
|
||||
8,
|
||||
5,
|
||||
76,
|
||||
88,
|
||||
4,
|
||||
12,
|
||||
71,
|
||||
73,
|
||||
6,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
54,
|
||||
77,
|
||||
91,
|
||||
]),
|
||||
'received_sleep_data': True,
|
||||
'webhooks_connected': True,
|
||||
})
|
||||
# ---
|
|
@ -0,0 +1,80 @@
|
|||
"""Tests for the diagnostics data provided by the Withings integration."""
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from syrupy import SnapshotAssertion
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
from tests.components.diagnostics import get_diagnostics_for_config_entry
|
||||
from tests.components.withings import prepare_webhook_setup, setup_integration
|
||||
from tests.typing import ClientSessionGenerator
|
||||
|
||||
|
||||
async def test_diagnostics_polling_instance(
|
||||
hass: HomeAssistant,
|
||||
hass_client: ClientSessionGenerator,
|
||||
withings: AsyncMock,
|
||||
polling_config_entry: MockConfigEntry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test diagnostics."""
|
||||
await setup_integration(hass, polling_config_entry, False)
|
||||
|
||||
assert (
|
||||
await get_diagnostics_for_config_entry(hass, hass_client, polling_config_entry)
|
||||
== snapshot
|
||||
)
|
||||
|
||||
|
||||
async def test_diagnostics_webhook_instance(
|
||||
hass: HomeAssistant,
|
||||
hass_client: ClientSessionGenerator,
|
||||
withings: AsyncMock,
|
||||
webhook_config_entry: MockConfigEntry,
|
||||
snapshot: SnapshotAssertion,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test diagnostics."""
|
||||
await setup_integration(hass, webhook_config_entry)
|
||||
await prepare_webhook_setup(hass, freezer)
|
||||
|
||||
assert (
|
||||
await get_diagnostics_for_config_entry(hass, hass_client, webhook_config_entry)
|
||||
== snapshot
|
||||
)
|
||||
|
||||
|
||||
async def test_diagnostics_cloudhook_instance(
|
||||
hass: HomeAssistant,
|
||||
hass_client: ClientSessionGenerator,
|
||||
withings: AsyncMock,
|
||||
webhook_config_entry: MockConfigEntry,
|
||||
snapshot: SnapshotAssertion,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test diagnostics."""
|
||||
with patch(
|
||||
"homeassistant.components.cloud.async_is_logged_in", return_value=True
|
||||
), patch(
|
||||
"homeassistant.components.cloud.async_is_connected", return_value=True
|
||||
), patch(
|
||||
"homeassistant.components.cloud.async_active_subscription", return_value=True
|
||||
), patch(
|
||||
"homeassistant.components.cloud.async_create_cloudhook",
|
||||
return_value="https://hooks.nabu.casa/ABCD",
|
||||
), patch(
|
||||
"homeassistant.helpers.config_entry_oauth2_flow.async_get_config_entry_implementation",
|
||||
), patch(
|
||||
"homeassistant.components.cloud.async_delete_cloudhook"
|
||||
), patch(
|
||||
"homeassistant.components.withings.webhook_generate_url"
|
||||
):
|
||||
await setup_integration(hass, webhook_config_entry)
|
||||
await prepare_webhook_setup(hass, freezer)
|
||||
|
||||
assert (
|
||||
await get_diagnostics_for_config_entry(hass, hass_client, webhook_config_entry)
|
||||
== snapshot
|
||||
)
|
Loading…
Reference in New Issue