mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 02:07:09 +00:00
Add tplink diagnostics (#65822)
This commit is contained in:
parent
4cd00a1a6f
commit
fd7e2e76e7
46
homeassistant/components/tplink/diagnostics.py
Normal file
46
homeassistant/components/tplink/diagnostics.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
"""Diagnostics support for TPLink."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from homeassistant.components.diagnostics import async_redact_data
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
from .coordinator import TPLinkDataUpdateCoordinator
|
||||||
|
|
||||||
|
TO_REDACT = {
|
||||||
|
# Entry fields
|
||||||
|
"unique_id", # based on mac address
|
||||||
|
# Device identifiers
|
||||||
|
"alias",
|
||||||
|
"mac",
|
||||||
|
"mic_mac",
|
||||||
|
"host",
|
||||||
|
"hwId",
|
||||||
|
"oemId",
|
||||||
|
"deviceId",
|
||||||
|
# Device location
|
||||||
|
"latitude",
|
||||||
|
"latitude_i",
|
||||||
|
"longitude",
|
||||||
|
"longitude_i",
|
||||||
|
# Cloud connectivity info
|
||||||
|
"username",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def async_get_config_entry_diagnostics(
|
||||||
|
hass: HomeAssistant, entry: ConfigEntry
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
"""Return diagnostics for a config entry."""
|
||||||
|
coordinator: TPLinkDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
device = coordinator.device
|
||||||
|
|
||||||
|
data = {}
|
||||||
|
data[
|
||||||
|
"device_last_response"
|
||||||
|
] = device._last_update # pylint: disable=protected-access
|
||||||
|
|
||||||
|
return async_redact_data(data, TO_REDACT)
|
@ -2,10 +2,16 @@
|
|||||||
|
|
||||||
from unittest.mock import AsyncMock, MagicMock, patch
|
from unittest.mock import AsyncMock, MagicMock, patch
|
||||||
|
|
||||||
from kasa import SmartBulb, SmartDimmer, SmartPlug, SmartStrip
|
from kasa import SmartBulb, SmartDevice, SmartDimmer, SmartPlug, SmartStrip
|
||||||
from kasa.exceptions import SmartDeviceException
|
from kasa.exceptions import SmartDeviceException
|
||||||
from kasa.protocol import TPLinkSmartHomeProtocol
|
from kasa.protocol import TPLinkSmartHomeProtocol
|
||||||
|
|
||||||
|
from homeassistant.components.tplink import CONF_HOST
|
||||||
|
from homeassistant.components.tplink.const import DOMAIN
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
MODULE = "homeassistant.components.tplink"
|
MODULE = "homeassistant.components.tplink"
|
||||||
MODULE_CONFIG_FLOW = "homeassistant.components.tplink.config_flow"
|
MODULE_CONFIG_FLOW = "homeassistant.components.tplink.config_flow"
|
||||||
IP_ADDRESS = "127.0.0.1"
|
IP_ADDRESS = "127.0.0.1"
|
||||||
@ -146,3 +152,23 @@ def _patch_single_discovery(device=None, no_device=False):
|
|||||||
return patch(
|
return patch(
|
||||||
"homeassistant.components.tplink.Discover.discover_single", new=_discover_single
|
"homeassistant.components.tplink.Discover.discover_single", new=_discover_single
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def initialize_config_entry_for_device(
|
||||||
|
hass: HomeAssistant, dev: SmartDevice
|
||||||
|
) -> MockConfigEntry:
|
||||||
|
"""Create a mocked configuration entry for the given device.
|
||||||
|
|
||||||
|
Note, the rest of the tests should probably be converted over to use this
|
||||||
|
instead of repeating the initialization routine for each test separately
|
||||||
|
"""
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
title="TP-Link", domain=DOMAIN, unique_id=dev.mac, data={CONF_HOST: dev.host}
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
with _patch_discovery(device=dev), _patch_single_discovery(device=dev):
|
||||||
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
return config_entry
|
||||||
|
@ -1,116 +0,0 @@
|
|||||||
"""Constants for the TP-Link component tests."""
|
|
||||||
|
|
||||||
SMARTPLUG_HS110_DATA = {
|
|
||||||
"sysinfo": {
|
|
||||||
"sw_ver": "1.0.4 Build 191111 Rel.143500",
|
|
||||||
"hw_ver": "4.0",
|
|
||||||
"model": "HS110(EU)",
|
|
||||||
"deviceId": "4C56447B395BB7A2FAC68C9DFEE2E84163222581",
|
|
||||||
"oemId": "40F54B43071E9436B6395611E9D91CEA",
|
|
||||||
"hwId": "A6C77E4FDD238B53D824AC8DA361F043",
|
|
||||||
"rssi": -24,
|
|
||||||
"longitude_i": 130793,
|
|
||||||
"latitude_i": 480582,
|
|
||||||
"alias": "SmartPlug",
|
|
||||||
"status": "new",
|
|
||||||
"mic_type": "IOT.SMARTPLUGSWITCH",
|
|
||||||
"feature": "TIM:ENE",
|
|
||||||
"mac": "69:F2:3C:8E:E3:47",
|
|
||||||
"updating": 0,
|
|
||||||
"led_off": 0,
|
|
||||||
"relay_state": 0,
|
|
||||||
"on_time": 0,
|
|
||||||
"active_mode": "none",
|
|
||||||
"icon_hash": "",
|
|
||||||
"dev_name": "Smart Wi-Fi Plug With Energy Monitoring",
|
|
||||||
"next_action": {"type": -1},
|
|
||||||
"err_code": 0,
|
|
||||||
},
|
|
||||||
"realtime": {
|
|
||||||
"voltage_mv": 233957,
|
|
||||||
"current_ma": 21,
|
|
||||||
"power_mw": 0,
|
|
||||||
"total_wh": 1793,
|
|
||||||
"err_code": 0,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
SMARTPLUG_HS100_DATA = {
|
|
||||||
"sysinfo": {
|
|
||||||
"sw_ver": "1.0.4 Build 191111 Rel.143500",
|
|
||||||
"hw_ver": "4.0",
|
|
||||||
"model": "HS100(EU)",
|
|
||||||
"deviceId": "4C56447B395BB7A2FAC68C9DFEE2E84163222581",
|
|
||||||
"oemId": "40F54B43071E9436B6395611E9D91CEA",
|
|
||||||
"hwId": "A6C77E4FDD238B53D824AC8DA361F043",
|
|
||||||
"rssi": -24,
|
|
||||||
"longitude_i": 130793,
|
|
||||||
"latitude_i": 480582,
|
|
||||||
"alias": "SmartPlug",
|
|
||||||
"status": "new",
|
|
||||||
"mic_type": "IOT.SMARTPLUGSWITCH",
|
|
||||||
"feature": "TIM:",
|
|
||||||
"mac": "A9:F4:3D:A4:E3:47",
|
|
||||||
"updating": 0,
|
|
||||||
"led_off": 0,
|
|
||||||
"relay_state": 0,
|
|
||||||
"on_time": 0,
|
|
||||||
"active_mode": "none",
|
|
||||||
"icon_hash": "",
|
|
||||||
"dev_name": "Smart Wi-Fi Plug",
|
|
||||||
"next_action": {"type": -1},
|
|
||||||
"err_code": 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SMARTSTRIP_KP303_DATA = {
|
|
||||||
"sysinfo": {
|
|
||||||
"sw_ver": "1.0.4 Build 210428 Rel.135415",
|
|
||||||
"hw_ver": "1.0",
|
|
||||||
"model": "KP303(AU)",
|
|
||||||
"deviceId": "03102547AB1A57A4E4AA5B4EFE34C3005726B97D",
|
|
||||||
"oemId": "1F950FC9BFF278D9D35E046C129D9411",
|
|
||||||
"hwId": "9E86D4F840D2787D3D7A6523A731BA2C",
|
|
||||||
"rssi": -74,
|
|
||||||
"longitude_i": 1158985,
|
|
||||||
"latitude_i": -319172,
|
|
||||||
"alias": "TP-LINK_Power Strip_00B1",
|
|
||||||
"status": "new",
|
|
||||||
"mic_type": "IOT.SMARTPLUGSWITCH",
|
|
||||||
"feature": "TIM",
|
|
||||||
"mac": "D4:DD:D6:95:B0:F9",
|
|
||||||
"updating": 0,
|
|
||||||
"led_off": 0,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": "8006B399B7FE68D4E6991CCCEA239C081DFA913000",
|
|
||||||
"state": 0,
|
|
||||||
"alias": "R-Plug 1",
|
|
||||||
"on_time": 0,
|
|
||||||
"next_action": {"type": -1},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "8006B399B7FE68D4E6991CCCEA239C081DFA913001",
|
|
||||||
"state": 1,
|
|
||||||
"alias": "R-Plug 2",
|
|
||||||
"on_time": 93835,
|
|
||||||
"next_action": {"type": -1},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "8006B399B7FE68D4E6991CCCEA239C081DFA913002",
|
|
||||||
"state": 1,
|
|
||||||
"alias": "R-Plug 3",
|
|
||||||
"on_time": 93834,
|
|
||||||
"next_action": {"type": -1},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"child_num": 3,
|
|
||||||
"err_code": 0,
|
|
||||||
},
|
|
||||||
"realtime": {
|
|
||||||
"voltage_mv": 233957,
|
|
||||||
"current_ma": 21,
|
|
||||||
"power_mw": 0,
|
|
||||||
"total_wh": 1793,
|
|
||||||
"err_code": 0,
|
|
||||||
},
|
|
||||||
"context": "1",
|
|
||||||
}
|
|
@ -0,0 +1,108 @@
|
|||||||
|
{
|
||||||
|
"device_last_response": {
|
||||||
|
"system": {
|
||||||
|
"get_sysinfo": {
|
||||||
|
"sw_ver": "1.8.8 Build 190613 Rel.123436",
|
||||||
|
"hw_ver": "1.0",
|
||||||
|
"model": "KL130(EU)",
|
||||||
|
"description": "Smart Wi-Fi LED Bulb with Color Changing",
|
||||||
|
"alias": "bedroom light",
|
||||||
|
"mic_type": "IOT.SMARTBULB",
|
||||||
|
"dev_state": "normal",
|
||||||
|
"mic_mac": "aa:bb:cc:dd:ee:ff",
|
||||||
|
"deviceId": "1234",
|
||||||
|
"oemId": "1234",
|
||||||
|
"hwId": "1234",
|
||||||
|
"is_factory": false,
|
||||||
|
"disco_ver": "1.0",
|
||||||
|
"ctrl_protocols": {
|
||||||
|
"name": "Linkie",
|
||||||
|
"version": "1.0"
|
||||||
|
},
|
||||||
|
"light_state": {
|
||||||
|
"on_off": 1,
|
||||||
|
"mode": "normal",
|
||||||
|
"hue": 0,
|
||||||
|
"saturation": 0,
|
||||||
|
"color_temp": 2500,
|
||||||
|
"brightness": 58
|
||||||
|
},
|
||||||
|
"is_dimmable": 1,
|
||||||
|
"is_color": 1,
|
||||||
|
"is_variable_color_temp": 1,
|
||||||
|
"preferred_state": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"hue": 0,
|
||||||
|
"saturation": 0,
|
||||||
|
"color_temp": 2500,
|
||||||
|
"brightness": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"hue": 299,
|
||||||
|
"saturation": 95,
|
||||||
|
"color_temp": 0,
|
||||||
|
"brightness": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 2,
|
||||||
|
"hue": 120,
|
||||||
|
"saturation": 75,
|
||||||
|
"color_temp": 0,
|
||||||
|
"brightness": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 3,
|
||||||
|
"hue": 240,
|
||||||
|
"saturation": 75,
|
||||||
|
"color_temp": 0,
|
||||||
|
"brightness": 100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rssi": -66,
|
||||||
|
"active_mode": "none",
|
||||||
|
"heapsize": 334532,
|
||||||
|
"err_code": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"smartlife.iot.common.emeter": {
|
||||||
|
"get_realtime": {
|
||||||
|
"power_mw": 6600,
|
||||||
|
"err_code": 0
|
||||||
|
},
|
||||||
|
"get_monthstat": {
|
||||||
|
"month_list": [
|
||||||
|
{
|
||||||
|
"year": 2022,
|
||||||
|
"month": 1,
|
||||||
|
"energy_wh": 321
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"year": 2022,
|
||||||
|
"month": 2,
|
||||||
|
"energy_wh": 321
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"err_code": 0
|
||||||
|
},
|
||||||
|
"get_daystat": {
|
||||||
|
"day_list": [
|
||||||
|
{
|
||||||
|
"year": 2022,
|
||||||
|
"month": 2,
|
||||||
|
"day": 1,
|
||||||
|
"energy_wh": 123
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"year": 2022,
|
||||||
|
"month": 2,
|
||||||
|
"day": 2,
|
||||||
|
"energy_wh": 123
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"err_code": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
{
|
||||||
|
"device_last_response": {
|
||||||
|
"system": {
|
||||||
|
"get_sysinfo": {
|
||||||
|
"sw_ver": "1.0.4 Build 191111 Rel.143500",
|
||||||
|
"hw_ver": "4.0",
|
||||||
|
"model": "HS110(EU)",
|
||||||
|
"deviceId": "1234",
|
||||||
|
"oemId": "1234",
|
||||||
|
"hwId": "1234",
|
||||||
|
"rssi": -57,
|
||||||
|
"longitude_i": "0.0",
|
||||||
|
"latitude_i": "0.0",
|
||||||
|
"alias": "some plug",
|
||||||
|
"status": "new",
|
||||||
|
"mic_type": "IOT.SMARTPLUGSWITCH",
|
||||||
|
"feature": "TIM:ENE",
|
||||||
|
"mac": "aa:bb:cc:dd:ee:ff",
|
||||||
|
"updating": 0,
|
||||||
|
"led_off": 1,
|
||||||
|
"relay_state": 1,
|
||||||
|
"on_time": 254454,
|
||||||
|
"active_mode": "none",
|
||||||
|
"icon_hash": "",
|
||||||
|
"dev_name": "Smart Wi-Fi Plug With Energy Monitoring",
|
||||||
|
"next_action": {
|
||||||
|
"type": -1
|
||||||
|
},
|
||||||
|
"err_code": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"emeter": {
|
||||||
|
"get_realtime": {
|
||||||
|
"voltage_mv": 230118,
|
||||||
|
"current_ma": 303,
|
||||||
|
"power_mw": 28825,
|
||||||
|
"total_wh": 18313,
|
||||||
|
"err_code": 0
|
||||||
|
},
|
||||||
|
"get_monthstat": {
|
||||||
|
"month_list": [
|
||||||
|
{
|
||||||
|
"year": 2022,
|
||||||
|
"month": 2,
|
||||||
|
"energy_wh": 321
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"year": 2022,
|
||||||
|
"month": 1,
|
||||||
|
"energy_wh": 321
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"err_code": 0
|
||||||
|
},
|
||||||
|
"get_daystat": {
|
||||||
|
"day_list": [
|
||||||
|
{
|
||||||
|
"year": 2022,
|
||||||
|
"month": 2,
|
||||||
|
"day": 1,
|
||||||
|
"energy_wh": 123
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"year": 2022,
|
||||||
|
"month": 2,
|
||||||
|
"day": 2,
|
||||||
|
"energy_wh": 123
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"err_code": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
tests/components/tplink/test_diagnostics.py
Normal file
60
tests/components/tplink/test_diagnostics.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
"""Tests for the diagnostics data provided by the TP-Link integration."""
|
||||||
|
import json
|
||||||
|
|
||||||
|
from aiohttp import ClientSession
|
||||||
|
from kasa import SmartDevice
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from . import _mocked_bulb, _mocked_plug, initialize_config_entry_for_device
|
||||||
|
|
||||||
|
from tests.common import load_fixture
|
||||||
|
from tests.components.diagnostics import get_diagnostics_for_config_entry
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"mocked_dev,fixture_file,sysinfo_vars",
|
||||||
|
[
|
||||||
|
(
|
||||||
|
_mocked_bulb(),
|
||||||
|
"tplink-diagnostics-data-bulb-kl130.json",
|
||||||
|
["mic_mac", "deviceId", "oemId", "hwId", "alias"],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
_mocked_plug(),
|
||||||
|
"tplink-diagnostics-data-plug-hs110.json",
|
||||||
|
["mac", "deviceId", "oemId", "hwId", "alias", "longitude_i", "latitude_i"],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_diagnostics(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
hass_client: ClientSession,
|
||||||
|
mocked_dev: SmartDevice,
|
||||||
|
fixture_file: str,
|
||||||
|
sysinfo_vars: list[str],
|
||||||
|
):
|
||||||
|
"""Test diagnostics for config entry."""
|
||||||
|
diagnostics_data = json.loads(load_fixture(fixture_file, "tplink"))
|
||||||
|
|
||||||
|
mocked_dev._last_update = diagnostics_data["device_last_response"]
|
||||||
|
|
||||||
|
config_entry = await initialize_config_entry_for_device(hass, mocked_dev)
|
||||||
|
result = await get_diagnostics_for_config_entry(hass, hass_client, config_entry)
|
||||||
|
|
||||||
|
assert isinstance(result, dict)
|
||||||
|
assert "device_last_response" in result
|
||||||
|
|
||||||
|
# There must be some redactions in place, so the raw data must not match
|
||||||
|
assert result["device_last_response"] != diagnostics_data["device_last_response"]
|
||||||
|
|
||||||
|
last_response = result["device_last_response"]
|
||||||
|
|
||||||
|
# We should always have sysinfo available
|
||||||
|
assert "system" in last_response
|
||||||
|
assert "get_sysinfo" in last_response["system"]
|
||||||
|
|
||||||
|
sysinfo = last_response["system"]["get_sysinfo"]
|
||||||
|
for var in sysinfo_vars:
|
||||||
|
assert sysinfo[var] == "**REDACTED**"
|
Loading…
x
Reference in New Issue
Block a user