From 2471ddaec6c85f45e12391f865e562b3488ea680 Mon Sep 17 00:00:00 2001 From: Aaron Bach Date: Tue, 25 Jan 2022 23:20:11 -0700 Subject: [PATCH] Add diagnostics to Tile (#64875) --- homeassistant/components/tile/diagnostics.py | 34 +++++++ homeassistant/components/tile/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/tile/conftest.py | 37 ++++---- .../tile/fixtures/tile_details_data.json | 95 +++++++++++++++++++ tests/components/tile/test_diagnostics.py | 31 ++++++ 7 files changed, 180 insertions(+), 23 deletions(-) create mode 100644 homeassistant/components/tile/diagnostics.py create mode 100644 tests/components/tile/fixtures/tile_details_data.json create mode 100644 tests/components/tile/test_diagnostics.py diff --git a/homeassistant/components/tile/diagnostics.py b/homeassistant/components/tile/diagnostics.py new file mode 100644 index 00000000000..7e85ef25047 --- /dev/null +++ b/homeassistant/components/tile/diagnostics.py @@ -0,0 +1,34 @@ +"""Diagnostics support for Tile.""" +from __future__ import annotations + +from typing import Any + +from pytile.tile import Tile + +from homeassistant.components.diagnostics import async_redact_data +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE +from homeassistant.core import HomeAssistant + +from .const import DATA_TILE, DOMAIN + +CONF_ALTITUDE = "altitude" +CONF_UUID = "uuid" + +TO_REDACT = { + CONF_ALTITUDE, + CONF_LATITUDE, + CONF_LONGITUDE, + CONF_UUID, +} + + +async def async_get_config_entry_diagnostics( + hass: HomeAssistant, entry: ConfigEntry +) -> dict[str, Any]: + """Return diagnostics for a config entry.""" + tiles: dict[str, Tile] = hass.data[DOMAIN][entry.entry_id][DATA_TILE] + + return async_redact_data( + {"tiles": [tile.as_dict() for tile in tiles.values()]}, TO_REDACT + ) diff --git a/homeassistant/components/tile/manifest.json b/homeassistant/components/tile/manifest.json index 8702f3b62bf..1b30e0483f7 100644 --- a/homeassistant/components/tile/manifest.json +++ b/homeassistant/components/tile/manifest.json @@ -3,7 +3,7 @@ "name": "Tile", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/tile", - "requirements": ["pytile==2021.12.0"], + "requirements": ["pytile==2022.01.0"], "codeowners": ["@bachya"], "iot_class": "cloud_polling" } diff --git a/requirements_all.txt b/requirements_all.txt index db215aef1f1..ade4f3ffce3 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1999,7 +1999,7 @@ python_opendata_transport==0.3.0 pythonegardia==1.0.40 # homeassistant.components.tile -pytile==2021.12.0 +pytile==2022.01.0 # homeassistant.components.touchline pytouchline==0.7 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 75ae3dcce52..f3c6f8d8d0d 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1230,7 +1230,7 @@ python-twitch-client==0.6.0 python_awair==0.2.1 # homeassistant.components.tile -pytile==2021.12.0 +pytile==2022.01.0 # homeassistant.components.traccar pytraccar==0.10.0 diff --git a/tests/components/tile/conftest.py b/tests/components/tile/conftest.py index 3fe25dc8549..0cb9a0080f6 100644 --- a/tests/components/tile/conftest.py +++ b/tests/components/tile/conftest.py @@ -1,37 +1,28 @@ """Define test fixtures for Tile.""" -from datetime import datetime +import json from unittest.mock import AsyncMock, Mock, patch import pytest +from pytile.tile import Tile from homeassistant.components.tile.const import DOMAIN from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.setup import async_setup_component -from tests.common import MockConfigEntry - -TILE_UUID = "tile_123" +from tests.common import MockConfigEntry, load_fixture @pytest.fixture(name="api") -def api_fixture(hass): +def api_fixture(hass, data_tile_details): """Define a pytile API object.""" - tile = Mock( - accuracy=20, - altitude=1000, - dead=False, - latitude=51.528308, - longitude=-0.3817765, - lost=False, - lost_timestamp=datetime(2022, 1, 1, 0, 0, 0), - ring_state="STOPPED", - uuid=TILE_UUID, - voip_state="OFFLINE", - async_update=AsyncMock(), - ) - tile.name = "Tile 123" + tile = Tile(None, data_tile_details) + tile.async_update = AsyncMock() - return Mock(async_get_tiles=AsyncMock(return_value={TILE_UUID: tile})) + return Mock( + async_get_tiles=AsyncMock( + return_value={data_tile_details["result"]["tile_uuid"]: tile} + ) + ) @pytest.fixture(name="config_entry") @@ -51,6 +42,12 @@ def config_fixture(hass): } +@pytest.fixture(name="data_tile_details", scope="session") +def data_tile_details_fixture(): + """Define a Tile details data payload.""" + return json.loads(load_fixture("tile_details_data.json", "tile")) + + @pytest.fixture(name="setup_tile") async def setup_tile_fixture(hass, api, config): """Define a fixture to set up Tile.""" diff --git a/tests/components/tile/fixtures/tile_details_data.json b/tests/components/tile/fixtures/tile_details_data.json new file mode 100644 index 00000000000..bfcc27f3c18 --- /dev/null +++ b/tests/components/tile/fixtures/tile_details_data.json @@ -0,0 +1,95 @@ +{ + "version": 1, + "revision": 1, + "timestamp": "2020-08-12T21:46:52.962Z", + "timestamp_ms": 1597268812962, + "result_code": 0, + "result": { + "group": null, + "parents": [], + "user_node_relationships": null, + "owner_user_uuid": "fd0c10a5-d0f7-4619-9bce-5b2cb7a6754b", + "node_type": null, + "name": "Wallet", + "description": null, + "image_url": "https://local-tile-pub.s3.amazonaws.com/images/wallet.jpeg", + "product": "DUTCH1", + "archetype": "WALLET", + "visible": true, + "user_node_data": {}, + "permissions_mask": null, + "tile_uuid": "19264d2dffdbca32", + "firmware_version": "01.12.14.0", + "category": null, + "superseded_tile_uuid": null, + "is_dead": false, + "hw_version": "02.09", + "configuration": { + "fw10_advertising_interval": null + }, + "last_tile_state": { + "uuid": "19264d2dffdbca32", + "connectionStateCode": 0, + "ringStateCode": 0, + "tile_uuid": "19264d2dffdbca32", + "client_uuid": "2cc56adc-b96a-4293-9b94-eda716e0aa17", + "timestamp": 1597254926000, + "advertised_rssi": -89, + "client_rssi": 0, + "battery_level": 0, + "latitude": 51.528308, + "longitude": -0.3817765, + "altitude": 0.4076319168123, + "raw_h_accuracy": 13.496111, + "v_accuracy": 9.395408, + "speed": 0.167378, + "course": 147.42035, + "authentication": null, + "owned": false, + "has_authentication": null, + "lost_timestamp": -1, + "connection_client_uuid": null, + "connection_event_timestamp": 0, + "last_owner_update": 0, + "partner_id": null, + "partner_client_id": null, + "speed_accuracy": null, + "course_accuracy": null, + "discovery_timestamp": 1597254933661, + "connection_state": "DISCONNECTED", + "ring_state": "STOPPED", + "is_lost": false, + "h_accuracy": 13.496111, + "voip_state": "OFFLINE" + }, + "firmware": { + "expected_firmware_version": "01.19.01.0", + "expected_firmware_imagename": "Tile_FW_Image_01.19.01.0.bin", + "expected_firmware_urlprefix": "https://s3.amazonaws.com/tile-tofu-fw/prod/", + "expected_firmware_publish_date": 1574380800000, + "expected_ppm": null, + "expected_advertising_interval": null, + "security_level": 1, + "expiry_timestamp": 1597290412960, + "expected_tdt_cmd_config": "xxxxxxxx" + }, + "auth_key": "xxxxxxxxxxxxxxxxxxxxxxxx", + "renewal_status": "NONE", + "metadata": { + "battery_state": "10" + }, + "battery_status": "NONE", + "serial_number": null, + "auto_retile": false, + "all_user_node_relationships": null, + "tile_type": "TILE", + "registration_timestamp": 1569634958090, + "is_lost": false, + "auth_timestamp": 1569634958090, + "status": "ACTIVATED", + "activation_timestamp": 1569634959186, + "thumbnail_image": "https://local-tile-pub.s3.amazonaws.com/images/thumb.jpeg", + "last_modified_timestamp": 1597268811531 + } +} + diff --git a/tests/components/tile/test_diagnostics.py b/tests/components/tile/test_diagnostics.py new file mode 100644 index 00000000000..e9cf0d34d77 --- /dev/null +++ b/tests/components/tile/test_diagnostics.py @@ -0,0 +1,31 @@ +"""Test Tile diagnostics.""" +from homeassistant.components.diagnostics import REDACTED + +from tests.components.diagnostics import get_diagnostics_for_config_entry + + +async def test_entry_diagnostics(hass, config_entry, hass_client, setup_tile): + """Test config entry diagnostics.""" + assert await get_diagnostics_for_config_entry(hass, hass_client, config_entry) == { + "tiles": [ + { + "accuracy": 13.496111, + "altitude": REDACTED, + "archetype": "WALLET", + "dead": False, + "firmware_version": "01.12.14.0", + "hardware_version": "02.09", + "kind": "TILE", + "last_timestamp": "2020-08-12T17:55:26", + "latitude": REDACTED, + "longitude": REDACTED, + "lost": False, + "lost_timestamp": "1969-12-31T23:59:59.999000", + "name": "Wallet", + "ring_state": "STOPPED", + "uuid": REDACTED, + "visible": True, + "voip_state": "OFFLINE", + } + ] + }