diff --git a/homeassistant/components/ambient_station/diagnostics.py b/homeassistant/components/ambient_station/diagnostics.py new file mode 100644 index 00000000000..f62e1e9d423 --- /dev/null +++ b/homeassistant/components/ambient_station/diagnostics.py @@ -0,0 +1,62 @@ +"""Diagnostics support for Ambient PWS.""" +from __future__ import annotations + +from types import MappingProxyType +from typing import Any + +from homeassistant.components.diagnostics import REDACTED +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import CONF_API_KEY +from homeassistant.core import HomeAssistant, callback + +from . import AmbientStation +from .const import CONF_APP_KEY, DOMAIN + +CONF_API_KEY_CAMEL = "apiKey" +CONF_APP_KEY_CAMEL = "appKey" +CONF_DEVICE_ID_CAMEL = "deviceId" +CONF_LOCATION = "location" +CONF_MAC_ADDRESS = "mac_address" +CONF_MAC_ADDRESS_CAMEL = "macAddress" +CONF_TZ = "tz" + + +@callback +def _async_redact_data(data: MappingProxyType | dict) -> dict[str, Any]: + """Redact sensitive data in a dict.""" + redacted = {**data} + + for key, value in redacted.items(): + if key in ( + CONF_API_KEY, + CONF_API_KEY_CAMEL, + CONF_APP_KEY, + CONF_APP_KEY_CAMEL, + CONF_DEVICE_ID_CAMEL, + CONF_LOCATION, + CONF_MAC_ADDRESS, + CONF_MAC_ADDRESS_CAMEL, + CONF_TZ, + ): + redacted[key] = REDACTED + elif isinstance(value, dict): + redacted[key] = _async_redact_data(value) + elif isinstance(value, list): + redacted[key] = [_async_redact_data(item) for item in value] + + return redacted + + +async def async_get_config_entry_diagnostics( + hass: HomeAssistant, entry: ConfigEntry +) -> dict[str, Any]: + """Return diagnostics for a config entry.""" + ambient: AmbientStation = hass.data[DOMAIN][entry.entry_id] + + return { + "entry": { + "title": entry.title, + "data": _async_redact_data(entry.data), + }, + "stations": _async_redact_data(ambient.stations), + } diff --git a/tests/components/ambient_station/conftest.py b/tests/components/ambient_station/conftest.py index 6cdeb2b40ad..680fa82303d 100644 --- a/tests/components/ambient_station/conftest.py +++ b/tests/components/ambient_station/conftest.py @@ -46,3 +46,9 @@ async def setup_ambient_station_fixture(hass, config, devices): assert await async_setup_component(hass, DOMAIN, config) await hass.async_block_till_done() yield + + +@pytest.fixture(name="station_data", scope="session") +def station_data_fixture(): + """Define devices data.""" + return json.loads(load_fixture("station_data.json", "ambient_station")) diff --git a/tests/components/ambient_station/fixtures/station_data.json b/tests/components/ambient_station/fixtures/station_data.json new file mode 100644 index 00000000000..31b9e7b4f0f --- /dev/null +++ b/tests/components/ambient_station/fixtures/station_data.json @@ -0,0 +1,43 @@ +{ + "devices": [ + { + "macAddress": "12:34:56:78:90:AB", + "lastData": { + "dateutc": 1642631880000, + "tempinf": 70.9, + "humidityin": 29, + "baromrelin": 29.953, + "baromabsin": 25.016, + "tempf": 21, + "humidity": 87, + "winddir": 25, + "windspeedmph": 0.2, + "windgustmph": 1.1, + "maxdailygust": 9.2, + "hourlyrainin": 0, + "eventrainin": 0, + "dailyrainin": 0, + "weeklyrainin": 0, + "monthlyrainin": 0.409, + "totalrainin": 35.398, + "solarradiation": 11.62, + "uv": 0, + "batt_co2": 1, + "feelsLike": 21, + "dewPoint": 17.75, + "feelsLikein": 69.1, + "dewPointin": 37, + "lastRain": "2022-01-07T19:45:00.000Z", + "deviceId": "1234567890abcdef12345678", + "tz": "America/New York", + "date": "2022-01-19T22:38:00.000Z" + }, + "info": { + "name": "Side Yard", + "location": "Home" + }, + "apiKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + } + ], + "method": "subscribe" +} diff --git a/tests/components/ambient_station/test_diagnostics.py b/tests/components/ambient_station/test_diagnostics.py new file mode 100644 index 00000000000..2295dad64d9 --- /dev/null +++ b/tests/components/ambient_station/test_diagnostics.py @@ -0,0 +1,58 @@ +"""Test Ambient PWS diagnostics.""" +from homeassistant.components.ambient_station import DOMAIN + +from tests.components.diagnostics import get_diagnostics_for_config_entry + + +async def test_entry_diagnostics( + hass, config_entry, hass_client, setup_ambient_station, station_data +): + """Test config entry diagnostics.""" + ambient = hass.data[DOMAIN][config_entry.entry_id] + ambient.stations = station_data + assert await get_diagnostics_for_config_entry(hass, hass_client, config_entry) == { + "entry": { + "data": {"api_key": "**REDACTED**", "app_key": "**REDACTED**"}, + "title": "Mock Title", + }, + "stations": { + "devices": [ + { + "apiKey": "**REDACTED**", + "info": {"location": "**REDACTED**", "name": "Side Yard"}, + "lastData": { + "baromabsin": 25.016, + "baromrelin": 29.953, + "batt_co2": 1, + "dailyrainin": 0, + "date": "2022-01-19T22:38:00.000Z", + "dateutc": 1642631880000, + "deviceId": "**REDACTED**", + "dewPoint": 17.75, + "dewPointin": 37, + "eventrainin": 0, + "feelsLike": 21, + "feelsLikein": 69.1, + "hourlyrainin": 0, + "humidity": 87, + "humidityin": 29, + "lastRain": "2022-01-07T19:45:00.000Z", + "maxdailygust": 9.2, + "monthlyrainin": 0.409, + "solarradiation": 11.62, + "tempf": 21, + "tempinf": 70.9, + "totalrainin": 35.398, + "tz": "**REDACTED**", + "uv": 0, + "weeklyrainin": 0, + "winddir": 25, + "windgustmph": 1.1, + "windspeedmph": 0.2, + }, + "macAddress": "**REDACTED**", + } + ], + "method": "subscribe", + }, + }