Merge remote-tracking branch 'upstream/master' into feat/power_protection

This commit is contained in:
Steven B
2025-01-23 15:17:26 +00:00
302 changed files with 28083 additions and 3492 deletions

0
tests/cli/__init__.py Normal file
View File

53
tests/cli/test_hub.py Normal file
View File

@@ -0,0 +1,53 @@
import pytest
from pytest_mock import MockerFixture
from kasa import DeviceType, Module
from kasa.cli.hub import hub
from ..device_fixtures import HUBS_SMART, hubs_smart, parametrize, plug_iot
@hubs_smart
async def test_hub_pair(dev, mocker: MockerFixture, runner, caplog):
"""Test that pair calls the expected methods."""
cs = dev.modules.get(Module.ChildSetup)
# Patch if the device supports the module
if cs is not None:
mock_pair = mocker.patch.object(cs, "pair")
res = await runner.invoke(hub, ["pair"], obj=dev, catch_exceptions=False)
if cs is None:
assert "is not a hub" in res.output
return
mock_pair.assert_awaited()
assert "Finding new devices for 10 seconds" in res.output
assert res.exit_code == 0
@parametrize("hubs smart", model_filter=HUBS_SMART, protocol_filter={"SMART"})
async def test_hub_unpair(dev, mocker: MockerFixture, runner):
"""Test that unpair calls the expected method."""
if not dev.children:
pytest.skip("Cannot test without child devices")
id_ = next(iter(dev.children)).device_id
cs = dev.modules.get(Module.ChildSetup)
mock_unpair = mocker.spy(cs, "unpair")
res = await runner.invoke(hub, ["unpair", id_], obj=dev, catch_exceptions=False)
mock_unpair.assert_awaited()
assert f"Unpaired {id_}" in res.output
assert res.exit_code == 0
@plug_iot
async def test_non_hub(dev, mocker: MockerFixture, runner):
"""Test that hub commands return an error if executed on a non-hub."""
assert dev.device_type is not DeviceType.Hub
res = await runner.invoke(
hub, ["unpair", "dummy_id"], obj=dev, catch_exceptions=False
)
assert "is not a hub" in res.output

114
tests/cli/test_vacuum.py Normal file
View File

@@ -0,0 +1,114 @@
from pytest_mock import MockerFixture
from kasa import DeviceType, Module
from kasa.cli.vacuum import vacuum
from ..device_fixtures import plug_iot
from ..device_fixtures import vacuum as vacuum_devices
@vacuum_devices
async def test_vacuum_records_group(dev, mocker: MockerFixture, runner):
"""Test that vacuum records calls the expected methods."""
rec = dev.modules.get(Module.CleanRecords)
assert rec
res = await runner.invoke(vacuum, ["records"], obj=dev, catch_exceptions=False)
latest = rec.parsed_data.last_clean
expected = (
f"Totals: {rec.total_clean_area} {rec.area_unit} in {rec.total_clean_time} "
f"(cleaned {rec.total_clean_count} times)\n"
f"Last clean: {latest.clean_area} {rec.area_unit} @ {latest.clean_time}"
)
assert expected in res.output
assert res.exit_code == 0
@vacuum_devices
async def test_vacuum_records_list(dev, mocker: MockerFixture, runner):
"""Test that vacuum records list calls the expected methods."""
rec = dev.modules.get(Module.CleanRecords)
assert rec
res = await runner.invoke(
vacuum, ["records", "list"], obj=dev, catch_exceptions=False
)
data = rec.parsed_data
for record in data.records:
expected = (
f"* {record.timestamp}: cleaned {record.clean_area} {rec.area_unit}"
f" in {record.clean_time}"
)
assert expected in res.output
assert res.exit_code == 0
@vacuum_devices
async def test_vacuum_consumables(dev, runner):
"""Test that vacuum consumables calls the expected methods."""
cons = dev.modules.get(Module.Consumables)
assert cons
res = await runner.invoke(vacuum, ["consumables"], obj=dev, catch_exceptions=False)
expected = ""
for c in cons.consumables.values():
expected += f"{c.name} ({c.id}): {c.used} used, {c.remaining} remaining\n"
assert expected in res.output
assert res.exit_code == 0
@vacuum_devices
async def test_vacuum_consumables_reset(dev, mocker: MockerFixture, runner):
"""Test that vacuum consumables reset calls the expected methods."""
cons = dev.modules.get(Module.Consumables)
assert cons
reset_consumable_mock = mocker.spy(cons, "reset_consumable")
for c_id in cons.consumables:
reset_consumable_mock.reset_mock()
res = await runner.invoke(
vacuum, ["consumables", "reset", c_id], obj=dev, catch_exceptions=False
)
reset_consumable_mock.assert_awaited_once_with(c_id)
assert f"Consumable {c_id} reset" in res.output
assert res.exit_code == 0
res = await runner.invoke(
vacuum, ["consumables", "reset", "foobar"], obj=dev, catch_exceptions=False
)
expected = (
"Consumable foobar not found in "
f"device consumables: {', '.join(cons.consumables.keys())}."
)
assert expected in res.output.replace("\n", "")
assert res.exit_code != 0
@plug_iot
async def test_non_vacuum(dev, mocker: MockerFixture, runner):
"""Test that vacuum commands return an error if executed on a non-vacuum."""
assert dev.device_type is not DeviceType.Vacuum
res = await runner.invoke(vacuum, ["records"], obj=dev, catch_exceptions=False)
assert "This device does not support records" in res.output
assert res.exit_code != 0
res = await runner.invoke(
vacuum, ["records", "list"], obj=dev, catch_exceptions=False
)
assert "This device does not support records" in res.output
assert res.exit_code != 0
res = await runner.invoke(vacuum, ["consumables"], obj=dev, catch_exceptions=False)
assert "This device does not support consumables" in res.output
assert res.exit_code != 0
res = await runner.invoke(
vacuum, ["consumables", "reset", "foobar"], obj=dev, catch_exceptions=False
)
assert "This device does not support consumables" in res.output
assert res.exit_code != 0

View File

@@ -1,6 +1,7 @@
from __future__ import annotations
import asyncio
import os
import sys
import warnings
from pathlib import Path
@@ -8,6 +9,9 @@ from unittest.mock import MagicMock, patch
import pytest
# TODO: this and runner fixture could be moved to tests/cli/conftest.py
from asyncclick.testing import CliRunner
from kasa import (
DeviceConfig,
SmartProtocol,
@@ -149,3 +153,12 @@ def mock_datagram_endpoint(request): # noqa: PT004
side_effect=_create_datagram_endpoint,
):
yield
@pytest.fixture
def runner():
"""Runner fixture that unsets the KASA_ environment variables for tests."""
KASA_VARS = {k: None for k, v in os.environ.items() if k.startswith("KASA_")}
runner = CliRunner(env=KASA_VARS)
return runner

View File

@@ -79,8 +79,6 @@ PLUGS_IOT = {
"KP125",
"KP401",
}
# P135 supports dimming, but its not currently support
# by the library
PLUGS_SMART = {
"P100",
"P110",
@@ -98,6 +96,7 @@ PLUGS = {
SWITCHES_IOT = {
"HS200",
"HS210",
"KS200",
"KS200M",
}
SWITCHES_SMART = {
@@ -111,7 +110,7 @@ SWITCHES_SMART = {
}
SWITCHES = {*SWITCHES_IOT, *SWITCHES_SMART}
STRIPS_IOT = {"HS107", "HS300", "KP303", "KP200", "KP400", "EP40"}
STRIPS_SMART = {"P300", "P304M", "TP25", "EP40M"}
STRIPS_SMART = {"P300", "P304M", "TP25", "EP40M", "P210M", "P306"}
STRIPS = {*STRIPS_IOT, *STRIPS_SMART}
DIMMERS_IOT = {"ES20M", "HS220", "KS220", "KS220M", "KS230", "KP405"}
@@ -122,9 +121,22 @@ DIMMERS = {
}
HUBS_SMART = {"H100", "KH100"}
SENSORS_SMART = {"T310", "T315", "T300", "T100", "T110", "S200B", "S200D"}
SENSORS_SMART = {
"T310",
"T315",
"T300",
"T100",
"T110",
"S200B",
"S200D",
"S210",
"S220",
"D100C", # needs a home category?
}
THERMOSTATS_SMART = {"KE100"}
VACUUMS_SMART = {"RV20"}
WITH_EMETER_IOT = {"HS110", "HS300", "KP115", "KP125", *BULBS_IOT}
WITH_EMETER_SMART = {"P110", "P110M", "P115", "KP125M", "EP25", "P304M"}
WITH_EMETER = {*WITH_EMETER_IOT, *WITH_EMETER_SMART}
@@ -142,6 +154,7 @@ ALL_DEVICES_SMART = (
.union(SENSORS_SMART)
.union(SWITCHES_SMART)
.union(THERMOSTATS_SMART)
.union(VACUUMS_SMART)
)
ALL_DEVICES = ALL_DEVICES_IOT.union(ALL_DEVICES_SMART)
@@ -326,13 +339,24 @@ device_smartcam = parametrize("devices smartcam", protocol_filter={"SMARTCAM"})
camera_smartcam = parametrize(
"camera smartcam",
device_type_filter=[DeviceType.Camera],
protocol_filter={"SMARTCAM"},
protocol_filter={"SMARTCAM", "SMARTCAM.CHILD"},
)
hub_smartcam = parametrize(
"hub smartcam",
device_type_filter=[DeviceType.Hub],
protocol_filter={"SMARTCAM"},
)
doobell_smartcam = parametrize(
"doorbell smartcam",
device_type_filter=[DeviceType.Doorbell],
protocol_filter={"SMARTCAM", "SMARTCAM.CHILD"},
)
chime_smart = parametrize(
"chime smart",
device_type_filter=[DeviceType.Chime],
protocol_filter={"SMART"},
)
vacuum = parametrize("vacuums", device_type_filter=[DeviceType.Vacuum])
def check_categories():
@@ -349,8 +373,11 @@ def check_categories():
+ hubs_smart.args[1]
+ sensors_smart.args[1]
+ thermostats_smart.args[1]
+ chime_smart.args[1]
+ camera_smartcam.args[1]
+ doobell_smartcam.args[1]
+ hub_smartcam.args[1]
+ vacuum.args[1]
)
diffs: set[FixtureInfo] = set(FIXTURE_DATA) - set(categorized_fixtures)
if diffs:
@@ -368,7 +395,7 @@ check_categories()
def device_for_fixture_name(model, protocol):
if protocol in {"SMART", "SMART.CHILD"}:
return SmartDevice
elif protocol == "SMARTCAM":
elif protocol in {"SMARTCAM", "SMARTCAM.CHILD"}:
return SmartCamDevice
else:
for d in STRIPS_IOT:
@@ -421,11 +448,20 @@ async def get_device_for_fixture(
d = device_for_fixture_name(fixture_data.name, fixture_data.protocol)(
host="127.0.0.123"
)
# smart child devices sometimes check _is_hub_child which needs a parent
# of DeviceType.Hub
class DummyParent:
device_type = DeviceType.Hub
if fixture_data.protocol in {"SMARTCAM.CHILD"}:
d._parent = DummyParent()
if fixture_data.protocol in {"SMART", "SMART.CHILD"}:
d.protocol = FakeSmartProtocol(
fixture_data.data, fixture_data.name, verbatim=verbatim
)
elif fixture_data.protocol == "SMARTCAM":
elif fixture_data.protocol in {"SMARTCAM", "SMARTCAM.CHILD"}:
d.protocol = FakeSmartCamProtocol(
fixture_data.data, fixture_data.name, verbatim=verbatim
)
@@ -434,7 +470,7 @@ async def get_device_for_fixture(
discovery_data = None
if "discovery_result" in fixture_data.data:
discovery_data = fixture_data.data["discovery_result"]
discovery_data = fixture_data.data["discovery_result"]["result"]
elif "system" in fixture_data.data:
discovery_data = {
"system": {"get_sysinfo": fixture_data.data["system"]["get_sysinfo"]}
@@ -472,8 +508,12 @@ def get_nearest_fixture_to_ip(dev):
assert protocol_fixtures, "Unknown device type"
# This will get the best fixture with a match on model region
if model_region_fixtures := filter_fixtures(
"", model_filter={dev._model_region}, fixture_list=protocol_fixtures
if (di := dev.device_info) and (
model_region_fixtures := filter_fixtures(
"",
model_filter={di.long_name + (f"({di.region})" if di.region else "")},
fixture_list=protocol_fixtures,
)
):
return next(iter(model_region_fixtures))

View File

@@ -1,6 +1,8 @@
from __future__ import annotations
import asyncio
import copy
from collections.abc import Coroutine
from dataclasses import dataclass
from json import dumps as json_dumps
from typing import Any, TypedDict
@@ -34,7 +36,7 @@ UNSUPPORTED_HOMEWIFISYSTEM = {
"group_id": "REDACTED_07d902da02fa9beab8a64",
"group_name": "I01BU0tFRF9TU0lEIw==", # '#MASKED_SSID#'
"hardware_version": "3.0",
"ip": "192.168.1.192",
"ip": "127.0.0.1",
"mac": "24:2F:D0:00:00:00",
"master_device_id": "REDACTED_51f72a752213a6c45203530",
"need_account_digest": True,
@@ -130,14 +132,19 @@ new_discovery = parametrize_discovery(
"new discovery", data_root_filter="discovery_result"
)
smart_discovery = parametrize_discovery("smart discovery", protocol_filter={"SMART"})
@pytest.fixture(
params=filter_fixtures("discoverable", protocol_filter={"SMART", "IOT"}),
params=filter_fixtures(
"discoverable", protocol_filter={"SMART", "SMARTCAM", "IOT"}
),
ids=idgenerator,
)
async def discovery_mock(request, mocker):
"""Mock discovery and patch protocol queries to use Fake protocols."""
fixture_info: FixtureInfo = request.param
fi: FixtureInfo = request.param
fixture_info = FixtureInfo(fi.name, fi.protocol, copy.deepcopy(fi.data))
return patch_discovery({DISCOVERY_MOCK_IP: fixture_info}, mocker)
@@ -156,6 +163,18 @@ def create_discovery_mock(ip: str, fixture_data: dict):
https: bool
login_version: int | None = None
port_override: int | None = None
http_port: int | None = None
@property
def model(self) -> str:
dd = self.discovery_data
model_region = (
dd["result"]["device_model"]
if self.discovery_port == 20002
else dd["system"]["get_sysinfo"]["model"]
)
model, _, _ = model_region.partition("(")
return model
@property
def _datagram(self) -> bytes:
@@ -168,18 +187,27 @@ def create_discovery_mock(ip: str, fixture_data: dict):
)
if "discovery_result" in fixture_data:
discovery_data = {"result": fixture_data["discovery_result"].copy()}
discovery_result = fixture_data["discovery_result"]
discovery_data = fixture_data["discovery_result"].copy()
discovery_result = fixture_data["discovery_result"]["result"]
device_type = discovery_result["device_type"]
encrypt_type = discovery_result["mgt_encrypt_schm"].get(
"encrypt_type", discovery_result.get("encrypt_info", {}).get("sym_schm")
)
login_version = discovery_result["mgt_encrypt_schm"].get("lv")
if not (login_version := discovery_result["mgt_encrypt_schm"].get("lv")) and (
et := discovery_result.get("encrypt_type")
):
login_version = max([int(i) for i in et])
https = discovery_result["mgt_encrypt_schm"]["is_support_https"]
http_port = discovery_result["mgt_encrypt_schm"].get("http_port")
if not http_port: # noqa: SIM108
# Not all discovery responses set the http port, i.e. smartcam.
default_port = 443 if https else 80
else:
default_port = http_port
dm = _DiscoveryMock(
ip,
80,
default_port,
20002,
discovery_data,
fixture_data,
@@ -187,6 +215,7 @@ def create_discovery_mock(ip: str, fixture_data: dict):
encrypt_type,
https,
login_version,
http_port=http_port,
)
else:
sys_info = fixture_data["system"]["get_sysinfo"]
@@ -226,12 +255,46 @@ def patch_discovery(fixture_infos: dict[str, FixtureInfo], mocker):
first_ip = list(fixture_infos.keys())[0]
first_host = None
# Mock _run_callback_task so the tasks complete in the order they started.
# Otherwise test output is non-deterministic which affects readme examples.
callback_queue: asyncio.Queue = asyncio.Queue()
exception_queue: asyncio.Queue = asyncio.Queue()
async def process_callback_queue(finished_event: asyncio.Event) -> None:
while (finished_event.is_set() is False) or callback_queue.qsize():
coro = await callback_queue.get()
try:
await coro
except Exception as ex:
await exception_queue.put(ex)
else:
await exception_queue.put(None)
callback_queue.task_done()
async def wait_for_coro():
await callback_queue.join()
if ex := exception_queue.get_nowait():
raise ex
def _run_callback_task(self, coro: Coroutine) -> None:
callback_queue.put_nowait(coro)
task = asyncio.create_task(wait_for_coro())
self.callback_tasks.append(task)
mocker.patch(
"kasa.discover._DiscoverProtocol._run_callback_task", _run_callback_task
)
# do_discover_mock
async def mock_discover(self):
"""Call datagram_received for all mock fixtures.
Handles test cases modifying the ip and hostname of the first fixture
for discover_single testing.
"""
finished_event = asyncio.Event()
asyncio.create_task(process_callback_queue(finished_event))
for ip, dm in discovery_mocks.items():
first_ip = list(discovery_mocks.values())[0].ip
fixture_info = fixture_infos[ip]
@@ -258,10 +321,18 @@ def patch_discovery(fixture_infos: dict[str, FixtureInfo], mocker):
dm._datagram,
(dm.ip, port),
)
# Setting this event will stop the processing of callbacks
finished_event.set()
mocker.patch("kasa.discover._DiscoverProtocol.do_discover", mock_discover)
# query_mock
async def _query(self, request, retry_count: int = 3):
return await protos[self._host].query(request)
mocker.patch("kasa.IotProtocol.query", _query)
mocker.patch("kasa.SmartProtocol.query", _query)
def _getaddrinfo(host, *_, **__):
nonlocal first_host, first_ip
first_host = host # Store the hostname used by discover single
@@ -270,20 +341,21 @@ def patch_discovery(fixture_infos: dict[str, FixtureInfo], mocker):
].ip # ip could have been overridden in test
return [(None, None, None, None, (first_ip, 0))]
mocker.patch("kasa.IotProtocol.query", _query)
mocker.patch("kasa.SmartProtocol.query", _query)
mocker.patch("kasa.discover._DiscoverProtocol.do_discover", mock_discover)
mocker.patch(
"socket.getaddrinfo",
# side_effect=lambda *_, **__: [(None, None, None, None, (first_ip, 0))],
side_effect=_getaddrinfo,
)
mocker.patch("socket.getaddrinfo", side_effect=_getaddrinfo)
# Mock decrypt so it doesn't error with unencryptable empty data in the
# fixtures. The discovery result will already contain the decrypted data
# deserialized from the fixture
mocker.patch("kasa.discover.Discover._decrypt_discovery_data")
# Only return the first discovery mock to be used for testing discover single
return discovery_mocks[first_ip]
@pytest.fixture(
params=filter_fixtures("discoverable", protocol_filter={"SMART", "IOT"}),
params=filter_fixtures(
"discoverable", protocol_filter={"SMART", "SMARTCAM", "IOT"}
),
ids=idgenerator,
)
def discovery_data(request, mocker):
@@ -303,7 +375,7 @@ def discovery_data(request, mocker):
mocker.patch("kasa.IotProtocol.query", return_value=fixture_data)
mocker.patch("kasa.SmartProtocol.query", return_value=fixture_data)
if "discovery_result" in fixture_data:
return {"result": fixture_data["discovery_result"]}
return fixture_data["discovery_result"].copy()
else:
return {"system": {"get_sysinfo": fixture_data["system"]["get_sysinfo"]}}

View File

@@ -308,10 +308,6 @@ class FakeIotTransport(BaseTransport):
child_ids = []
_LOGGER.debug("Setting relay state to %s", x["state"])
if not child_ids and "children" in self.proto["system"]["get_sysinfo"]:
for child in self.proto["system"]["get_sysinfo"]["children"]:
child_ids.append(child["id"])
_LOGGER.info("child_ids: %s", child_ids)
if child_ids:
for child in self.proto["system"]["get_sysinfo"]["children"]:

View File

@@ -7,6 +7,8 @@ import pytest
from kasa import Credentials, DeviceConfig, SmartProtocol
from kasa.exceptions import SmartErrorCode
from kasa.smart import SmartChildDevice
from kasa.smartcam import SmartCamChild
from kasa.smartcam.smartcamchild import CHILD_INFO_FROM_PARENT
from kasa.transports.basetransport import BaseTransport
@@ -48,13 +50,18 @@ class FakeSmartTransport(BaseTransport):
),
)
self.fixture_name = fixture_name
# When True verbatim will bypass any extra processing of missing
# methods and is used to test the fixture creation itself.
self.verbatim = verbatim
# Don't copy the dict if the device is a child so that updates on the
# child are then still reflected on the parent's lis of child device in
if not is_child:
self.info = copy.deepcopy(info)
if get_child_fixtures:
self.child_protocols = self._get_child_protocols(
self.info, self.fixture_name, "get_child_device_list"
self.info, self.fixture_name, "get_child_device_list", self.verbatim
)
else:
self.info = info
@@ -67,9 +74,6 @@ class FakeSmartTransport(BaseTransport):
self.warn_fixture_missing_methods = warn_fixture_missing_methods
self.fix_incomplete_fixture_lists = fix_incomplete_fixture_lists
# When True verbatim will bypass any extra processing of missing
# methods and is used to test the fixture creation itself.
self.verbatim = verbatim
if verbatim:
self.warn_fixture_missing_methods = False
self.fix_incomplete_fixture_lists = False
@@ -114,8 +118,17 @@ class FakeSmartTransport(BaseTransport):
"type": 0,
},
),
"get_homekit_info": (
"homekit",
{
"mfi_setup_code": "000-00-000",
"mfi_setup_id": "0000",
"mfi_token_token": "000000000000000000000000000000000",
"mfi_token_uuid": "00000000-0000-0000-0000-000000000000",
},
),
"get_auto_update_info": (
"firmware",
("firmware", 2),
{"enable": True, "random_range": 120, "time": 180},
),
"get_alarm_configure": (
@@ -159,8 +172,49 @@ class FakeSmartTransport(BaseTransport):
"power_protection",
{"max_power": 3904},
),
"get_matter_setup_info": (
"matter",
{
"setup_code": "00000000000",
"setup_payload": "00:0000000-0000.00.000",
},
),
# child setup
"get_support_child_device_category": (
"child_quick_setup",
{"device_category_list": [{"category": "subg.trv"}]},
),
# no devices found
"get_scan_child_device_list": (
"child_quick_setup",
{"child_device_list": [{"dummy": "response"}], "scan_status": "idle"},
),
}
def _missing_result(self, method):
"""Check the FIXTURE_MISSING_MAP for responses.
Fixtures generated prior to a query being supported by dump_devinfo
do not have the response so this method checks whether the component
is supported and fills in the missing response.
If the first value of the lookup value is a tuple it will also check
the version, i.e. (component_name, component_version).
"""
if not (missing := self.FIXTURE_MISSING_MAP.get(method)):
return None
condition = missing[0]
if (
isinstance(condition, tuple)
and (version := self.components.get(condition[0]))
and version >= condition[1]
):
return copy.deepcopy(missing[1])
if condition in self.components:
return copy.deepcopy(missing[1])
return None
async def send(self, request: str):
request_dict = json_loads(request)
method = request_dict["method"]
@@ -181,7 +235,7 @@ class FakeSmartTransport(BaseTransport):
@staticmethod
def _get_child_protocols(
parent_fixture_info, parent_fixture_name, child_devices_key
parent_fixture_info, parent_fixture_name, child_devices_key, verbatim
):
child_infos = parent_fixture_info.get(child_devices_key, {}).get(
"child_device_list", []
@@ -193,16 +247,20 @@ class FakeSmartTransport(BaseTransport):
# imported here to avoid circular import
from .conftest import filter_fixtures
def try_get_child_fixture_info(child_dev_info):
def try_get_child_fixture_info(child_dev_info, protocol):
hw_version = child_dev_info["hw_ver"]
sw_version = child_dev_info["fw_ver"]
sw_version = child_dev_info.get("sw_ver", child_dev_info.get("fw_ver"))
sw_version = sw_version.split(" ")[0]
model = child_dev_info["model"]
region = child_dev_info.get("specs", "XX")
child_fixture_name = f"{model}({region})_{hw_version}_{sw_version}"
model = child_dev_info.get("device_model", child_dev_info.get("model"))
assert sw_version
assert model
region = child_dev_info.get("specs", child_dev_info.get("region"))
region = f"({region})" if region else ""
child_fixture_name = f"{model}{region}_{hw_version}_{sw_version}"
child_fixtures = filter_fixtures(
"Child fixture",
protocol_filter={"SMART.CHILD"},
protocol_filter={protocol},
model_filter={child_fixture_name},
)
if child_fixtures:
@@ -215,12 +273,17 @@ class FakeSmartTransport(BaseTransport):
and (category := child_info.get("category"))
and category in SmartChildDevice.CHILD_DEVICE_TYPE_MAP
):
if fixture_info_tuple := try_get_child_fixture_info(child_info):
if fixture_info_tuple := try_get_child_fixture_info(
child_info, "SMART.CHILD"
):
child_fixture = copy.deepcopy(fixture_info_tuple.data)
child_fixture["get_device_info"]["device_id"] = device_id
found_child_fixture_infos.append(child_fixture["get_device_info"])
child_protocols[device_id] = FakeSmartProtocol(
child_fixture, fixture_info_tuple.name, is_child=True
child_fixture,
fixture_info_tuple.name,
is_child=True,
verbatim=verbatim,
)
# Look for fixture inline
elif (child_fixtures := parent_fixture_info.get("child_devices")) and (
@@ -231,19 +294,46 @@ class FakeSmartTransport(BaseTransport):
child_fixture,
f"{parent_fixture_name}-{device_id}",
is_child=True,
verbatim=verbatim,
)
else:
pytest.fixtures_missing_methods.setdefault( # type: ignore[attr-defined]
parent_fixture_name, set()
).add("child_devices")
elif (
(device_id := child_info.get("device_id"))
and (category := child_info.get("category"))
and category in SmartCamChild.CHILD_DEVICE_TYPE_MAP
and (
fixture_info_tuple := try_get_child_fixture_info(
child_info, "SMARTCAM.CHILD"
)
)
):
from .fakeprotocol_smartcam import FakeSmartCamProtocol
child_fixture = copy.deepcopy(fixture_info_tuple.data)
child_fixture["getDeviceInfo"]["device_info"]["basic_info"][
"dev_id"
] = device_id
child_fixture[CHILD_INFO_FROM_PARENT]["device_id"] = device_id
# We copy the child device info to the parent getChildDeviceInfo
# list for smartcam children in order for updates to work.
found_child_fixture_infos.append(child_fixture[CHILD_INFO_FROM_PARENT])
child_protocols[device_id] = FakeSmartCamProtocol(
child_fixture,
fixture_info_tuple.name,
is_child=True,
verbatim=verbatim,
)
else:
warn(
f"Child is a cameraprotocol which needs to be implemented {child_info}",
f"Child is a protocol which needs to be implemented {child_info}",
stacklevel=2,
)
# Replace parent child infos with the infos from the child fixtures so
# that updates update both
if child_infos and found_child_fixture_infos:
if not verbatim and child_infos and found_child_fixture_infos:
parent_fixture_info[child_devices_key]["child_device_list"] = (
found_child_fixture_infos
)
@@ -310,18 +400,16 @@ class FakeSmartTransport(BaseTransport):
elif child_method in child_device_calls:
result = copy.deepcopy(child_device_calls[child_method])
return {"result": result, "error_code": 0}
elif (
elif missing_result := self._missing_result(child_method):
# FIXTURE_MISSING is for service calls not in place when
# SMART fixtures started to be generated
missing_result := self.FIXTURE_MISSING_MAP.get(child_method)
) and missing_result[0] in self.components:
# Copy to info so it will work with update methods
child_device_calls[child_method] = copy.deepcopy(missing_result[1])
child_device_calls[child_method] = missing_result
result = copy.deepcopy(info[child_method])
retval = {"result": result, "error_code": 0}
return retval
elif child_method[:4] == "set_":
target_method = f"get_{child_method[4:]}"
elif child_method[:3] == "set":
target_method = f"get{child_method[3:]}"
if target_method not in child_device_calls:
raise RuntimeError(
f"No {target_method} in child info, calling set before get not supported."
@@ -478,6 +566,48 @@ class FakeSmartTransport(BaseTransport):
return {"error_code": 0}
def _hub_remove_device(self, info, params):
"""Remove hub device."""
items_to_remove = [dev["device_id"] for dev in params["child_device_list"]]
children = info["get_child_device_list"]["child_device_list"]
new_children = [
dev for dev in children if dev["device_id"] not in items_to_remove
]
info["get_child_device_list"]["child_device_list"] = new_children
return {"error_code": 0}
def get_child_device_queries(self, method, params):
return self._get_method_from_info(method, params)
def _get_method_from_info(self, method, params):
result = copy.deepcopy(self.info[method])
if result and "start_index" in result and "sum" in result:
list_key = next(
iter([key for key in result if isinstance(result[key], list)])
)
start_index = (
start_index
if (params and (start_index := params.get("start_index")))
else 0
)
# Fixtures generated before _handle_response_lists was implemented
# could have incomplete lists.
if (
len(result[list_key]) < result["sum"]
and self.fix_incomplete_fixture_lists
):
result["sum"] = len(result[list_key])
if self.warn_fixture_missing_methods:
pytest.fixtures_missing_methods.setdefault( # type: ignore[attr-defined]
self.fixture_name, set()
).add(f"{method} (incomplete '{list_key}' list)")
result[list_key] = result[list_key][
start_index : start_index + self.list_return_size
]
return {"result": result, "error_code": 0}
async def _send_request(self, request_dict: dict):
method = request_dict["method"]
@@ -486,34 +616,17 @@ class FakeSmartTransport(BaseTransport):
return await self._handle_control_child(request_dict["params"])
params = request_dict.get("params", {})
if method in {"component_nego", "qs_component_nego"} or method[:4] == "get_":
if method in info:
result = copy.deepcopy(info[method])
if result and "start_index" in result and "sum" in result:
list_key = next(
iter([key for key in result if isinstance(result[key], list)])
)
start_index = (
start_index
if (params and (start_index := params.get("start_index")))
else 0
)
# Fixtures generated before _handle_response_lists was implemented
# could have incomplete lists.
if (
len(result[list_key]) < result["sum"]
and self.fix_incomplete_fixture_lists
):
result["sum"] = len(result[list_key])
if self.warn_fixture_missing_methods:
pytest.fixtures_missing_methods.setdefault( # type: ignore[attr-defined]
self.fixture_name, set()
).add(f"{method} (incomplete '{list_key}' list)")
if method in {"component_nego", "qs_component_nego"} or method[:3] == "get":
# These methods are handled in get_child_device_query so it can be
# patched for tests to simulate dynamic devices.
if (
method in ("get_child_device_list", "get_child_device_component_list")
and method in info
):
return self.get_child_device_queries(method, params)
result[list_key] = result[list_key][
start_index : start_index + self.list_return_size
]
return {"result": result, "error_code": 0}
if method in info:
return self._get_method_from_info(method, params)
if self.verbatim:
return {
@@ -521,13 +634,11 @@ class FakeSmartTransport(BaseTransport):
"method": method,
}
if (
if missing_result := self._missing_result(method):
# FIXTURE_MISSING is for service calls not in place when
# SMART fixtures started to be generated
missing_result := self.FIXTURE_MISSING_MAP.get(method)
) and missing_result[0] in self.components:
# Copy to info so it will work with update methods
info[method] = copy.deepcopy(missing_result[1])
info[method] = missing_result
result = copy.deepcopy(info[method])
retval = {"result": result, "error_code": 0}
elif (
@@ -576,9 +687,30 @@ class FakeSmartTransport(BaseTransport):
return self._set_on_off_gradually_info(info, params)
elif method == "set_child_protection":
return self._update_sysinfo_key(info, "child_protection", params["enable"])
elif method[:4] == "set_":
target_method = f"get_{method[4:]}"
elif method == "remove_child_device_list":
return self._hub_remove_device(info, params)
# actions
elif method in [
"begin_scanning_child_device", # hub pairing
"add_child_device_list", # hub pairing
"remove_child_device_list", # hub pairing
"playSelectAudio", # vacuum special actions
"resetConsumablesTime", # vacuum special actions
]:
return {"error_code": 0}
elif method[:3] == "set":
target_method = f"get{method[3:]}"
# Some vacuum commands do not have a getter
if method in [
"setRobotPause",
"setSwitchClean",
"setSwitchCharge",
"setSwitchDustCollection",
]:
return {"error_code": 0}
info[target_method].update(params)
return {"error_code": 0}
async def close(self) -> None:

View File

@@ -6,6 +6,7 @@ from typing import Any
from kasa import Credentials, DeviceConfig, SmartProtocol
from kasa.protocols.smartcamprotocol import SmartCamProtocol
from kasa.smartcam.smartcamchild import CHILD_INFO_FROM_PARENT, SmartCamChild
from kasa.transports.basetransport import BaseTransport
from .fakeprotocol_smart import FakeSmartTransport
@@ -33,7 +34,9 @@ class FakeSmartCamTransport(BaseTransport):
*,
list_return_size=10,
is_child=False,
get_child_fixtures=True,
verbatim=False,
components_not_included=False,
):
super().__init__(
config=DeviceConfig(
@@ -44,20 +47,35 @@ class FakeSmartCamTransport(BaseTransport):
),
),
)
self.fixture_name = fixture_name
# When True verbatim will bypass any extra processing of missing
# methods and is used to test the fixture creation itself.
self.verbatim = verbatim
if not is_child:
self.info = copy.deepcopy(info)
self.child_protocols = FakeSmartTransport._get_child_protocols(
self.info, self.fixture_name, "getChildDeviceList"
)
# We don't need to get the child fixtures if testing things like
# lists
if get_child_fixtures:
self.child_protocols = FakeSmartTransport._get_child_protocols(
self.info, self.fixture_name, "getChildDeviceList", self.verbatim
)
else:
self.info = info
# self.child_protocols = self._get_child_protocols()
self.list_return_size = list_return_size
# Setting this flag allows tests to create dummy transports without
# full fixture info for testing specific cases like list handling etc
self.components_not_included = (components_not_included,)
if not components_not_included:
self.components = {
comp["name"]: comp["version"]
for comp in self.info["getAppComponentList"]["app_component"][
"app_component_list"
]
}
@property
def default_port(self):
"""Default port for the transport."""
@@ -108,10 +126,61 @@ class FakeSmartCamTransport(BaseTransport):
@staticmethod
def _get_param_set_value(info: dict, set_keys: list[str], value):
cifp = info.get(CHILD_INFO_FROM_PARENT)
for key in set_keys[:-1]:
info = info[key]
info[set_keys[-1]] = value
if (
cifp
and set_keys[0] == "getDeviceInfo"
and (
child_info_parent_key
:= FakeSmartCamTransport.CHILD_INFO_SETTER_MAP.get(set_keys[-1])
)
):
cifp[child_info_parent_key] = value
CHILD_INFO_SETTER_MAP = {
"device_alias": "alias",
}
FIXTURE_MISSING_MAP = {
"getMatterSetupInfo": (
"matter",
{
"setup_code": "00000000000",
"setup_payload": "00:0000000-0000.00.000",
},
),
"getSupportChildDeviceCategory": (
"childQuickSetup",
{
"device_category_list": [
{"category": "ipcamera"},
{"category": "subg.trv"},
{"category": "subg.trigger"},
{"category": "subg.plugswitch"},
]
},
),
"getScanChildDeviceList": (
"childQuickSetup",
{
"child_device_list": [
{
"device_id": "0000000000000000000000000000000000000000",
"category": "subg.trigger.button",
"device_model": "S200B",
"name": "I01BU0tFRF9OQU1FIw====",
}
],
"scan_wait_time": 55,
"scan_status": "scanning",
},
),
}
# Setters for when there's not a simple mapping of setters to getters
SETTERS = {
("system", "sys", "dev_alias"): [
@@ -136,6 +205,17 @@ class FakeSmartCamTransport(BaseTransport):
],
}
def _hub_remove_device(self, info, params):
"""Remove hub device."""
items_to_remove = [dev["device_id"] for dev in params["child_device_list"]]
children = info["getChildDeviceList"]["child_device_list"]
new_children = [
dev for dev in children if dev["device_id"] not in items_to_remove
]
info["getChildDeviceList"]["child_device_list"] = new_children
return {"result": {}, "error_code": 0}
@staticmethod
def _get_second_key(request_dict: dict[str, Any]) -> str:
assert (
@@ -145,6 +225,33 @@ class FakeSmartCamTransport(BaseTransport):
next(it, None)
return next(it)
def get_child_device_queries(self, method, params):
return self._get_method_from_info(method, params)
def _get_method_from_info(self, method, params):
result = copy.deepcopy(self.info[method])
if "start_index" in result and "sum" in result:
list_key = next(
iter([key for key in result if isinstance(result[key], list)])
)
assert isinstance(params, dict)
module_name = next(iter(params))
start_index = (
start_index
if (
params
and module_name
and (start_index := params[module_name].get("start_index"))
)
else 0
)
result[list_key] = result[list_key][
start_index : start_index + self.list_return_size
]
return {"result": result, "error_code": 0}
async def _send_request(self, request_dict: dict):
method = request_dict["method"]
@@ -199,26 +306,55 @@ class FakeSmartCamTransport(BaseTransport):
return {**result, "error_code": 0}
else:
return {"error_code": -1}
elif method[:3] == "get":
params = request_dict.get("params")
if method in info:
result = copy.deepcopy(info[method])
if "start_index" in result and "sum" in result:
list_key = next(
iter([key for key in result if isinstance(result[key], list)])
)
start_index = (
start_index
if (params and (start_index := params.get("start_index")))
else 0
)
elif method == "removeChildDeviceList":
return self._hub_remove_device(info, request_dict["params"]["childControl"])
# actions
elif method in [
"addScanChildDeviceList",
"startScanChildDevice",
]:
return {"result": {}, "error_code": 0}
# smartcam child devices do not make requests for getDeviceInfo as they
# get updated from the parent's query. If this is being called from a
# child it must be because the fixture has been created directly on the
# child device with a dummy parent. In this case return the child info
# from parent that's inside the fixture.
if (
not self.verbatim
and method == "getDeviceInfo"
and (cifp := info.get(CHILD_INFO_FROM_PARENT))
):
mapped = SmartCamChild._map_child_info_from_parent(cifp)
result = {"device_info": {"basic_info": mapped}}
return {"result": result, "error_code": 0}
# These methods are handled in get_child_device_query so it can be
# patched for tests to simulate dynamic devices.
if (
method in ("getChildDeviceList", "getChildDeviceComponentList")
and method in info
):
params = request_dict.get("params")
return self.get_child_device_queries(method, params)
if method in info:
params = request_dict.get("params")
return self._get_method_from_info(method, params)
if self.verbatim:
return {"error_code": -1}
if (
# FIXTURE_MISSING is for service calls not in place when
# SMART fixtures started to be generated
missing_result := self.FIXTURE_MISSING_MAP.get(method)
) and missing_result[0] in self.components:
# Copy to info so it will work with update methods
info[method] = copy.deepcopy(missing_result[1])
result = copy.deepcopy(info[method])
return {"result": result, "error_code": 0}
result[list_key] = result[list_key][
start_index : start_index + self.list_return_size
]
return {"result": result, "error_code": 0}
else:
return {"error_code": -1}
return {"error_code": -1}
async def close(self) -> None:

View File

@@ -60,11 +60,19 @@ SUPPORTED_SMARTCAM_DEVICES = [
)
]
SUPPORTED_SMARTCAM_CHILD_DEVICES = [
(device, "SMARTCAM.CHILD")
for device in glob.glob(
os.path.dirname(os.path.abspath(__file__)) + "/fixtures/smartcam/child/*.json"
)
]
SUPPORTED_DEVICES = (
SUPPORTED_IOT_DEVICES
+ SUPPORTED_SMART_DEVICES
+ SUPPORTED_SMART_CHILD_DEVICES
+ SUPPORTED_SMARTCAM_DEVICES
+ SUPPORTED_SMARTCAM_CHILD_DEVICES
)
@@ -77,19 +85,13 @@ def idgenerator(paramtuple: FixtureInfo):
return None
def get_fixture_info() -> list[FixtureInfo]:
def get_fixture_infos() -> list[FixtureInfo]:
"""Return raw discovery file contents as JSON. Used for discovery tests."""
fixture_data = []
for file, protocol in SUPPORTED_DEVICES:
p = Path(file)
folder = Path(__file__).parent / "fixtures"
if protocol == "SMART":
folder = folder / "smart"
if protocol == "SMART.CHILD":
folder = folder / "smart/child"
p = folder / file
with open(p) as f:
with open(file) as f:
data = json.load(f)
fixture_name = p.name
@@ -99,7 +101,7 @@ def get_fixture_info() -> list[FixtureInfo]:
return fixture_data
FIXTURE_DATA: list[FixtureInfo] = get_fixture_info()
FIXTURE_DATA: list[FixtureInfo] = get_fixture_infos()
def filter_fixtures(
@@ -145,12 +147,21 @@ def filter_fixtures(
def _component_match(
fixture_data: FixtureInfo, component_filter: str | ComponentFilter
):
if (component_nego := fixture_data.data.get("component_nego")) is None:
components = {}
if component_nego := fixture_data.data.get("component_nego"):
components = {
component["id"]: component["ver_code"]
for component in component_nego["component_list"]
}
if get_app_component_list := fixture_data.data.get("getAppComponentList"):
components = {
component["name"]: component["version"]
for component in get_app_component_list["app_component"][
"app_component_list"
]
}
if not components:
return False
components = {
component["id"]: component["ver_code"]
for component in component_nego["component_list"]
}
if isinstance(component_filter, str):
return component_filter in components
else:
@@ -179,7 +190,7 @@ def filter_fixtures(
IotDevice._get_device_type_from_sys_info(fixture_data.data)
in device_type
)
elif fixture_data.protocol == "SMARTCAM":
elif fixture_data.protocol in {"SMARTCAM", "SMARTCAM.CHILD"}:
info = fixture_data.data["getDeviceInfo"]["device_info"]["basic_info"]
return SmartCamDevice._get_device_type_from_sysinfo(info) in device_type
return False

View File

@@ -2,7 +2,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "167 lamp",
"alias": "#MASKED_NAME#",
"dev_name": "Smart Wi-Fi Plug Mini",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -1,12 +1,12 @@
{
"system": {
"get_sysinfo": {
"alias": "TP-LINK_Smart Plug_004F",
"alias": "#MASKED_NAME#",
"child_num": 2,
"children": [
{
"alias": "Zombie",
"id": "8006231E1499BAC4D4BC7EFCD4B075181E6393F200",
"alias": "#MASKED_NAME# 1",
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
"next_action": {
"type": -1
},
@@ -14,8 +14,8 @@
"state": 0
},
{
"alias": "Magic",
"id": "8006231E1499BAC4D4BC7EFCD4B075181E6393F201",
"alias": "#MASKED_NAME# 2",
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
"next_action": {
"type": -1
},

View File

@@ -11,7 +11,7 @@
"stopConnect": 0,
"tcspInfo": "",
"tcspStatus": 1,
"username": "#MASKED_NAME#"
"username": "user@example.com"
},
"get_intl_fw_list": {
"err_code": 0,

View File

@@ -78,7 +78,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Test ES20M",
"alias": "#MASKED_NAME#",
"brightness": 35,
"dev_name": "Wi-Fi Smart Dimmer with sensor",
"deviceId": "0000000000000000000000000000000000000000",

View File

@@ -1,18 +1,21 @@
{
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "HS100(UK)",
"device_type": "IOT.SMARTPLUGSWITCH",
"factory_default": true,
"hw_ver": "4.1",
"ip": "127.0.0.123",
"mac": "CC-32-E5-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false
},
"owner": "00000000000000000000000000000000"
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "HS100(UK)",
"device_type": "IOT.SMARTPLUGSWITCH",
"factory_default": true,
"hw_ver": "4.1",
"ip": "127.0.0.123",
"mac": "CC-32-E5-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false
},
"owner": "00000000000000000000000000000000"
}
},
"system": {
"get_sysinfo": {

View File

@@ -18,7 +18,7 @@
"system": {
"get_sysinfo": {
"active_mode": "schedule",
"alias": "Unused 3",
"alias": "#MASKED_NAME#",
"dev_name": "Wi-Fi Smart Plug",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -20,7 +20,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "3D Printer",
"alias": "#MASKED_NAME#",
"dev_name": "Smart Wi-Fi Plug",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -20,7 +20,7 @@
"system": {
"get_sysinfo": {
"active_mode": "schedule",
"alias": "Night lite",
"alias": "#MASKED_NAME#",
"dev_name": "Smart Wi-Fi Plug Lite",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -18,7 +18,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Corner",
"alias": "#MASKED_NAME#",
"dev_name": "Smart Wi-Fi Plug Lite",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -2,7 +2,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Plug",
"alias": "#MASKED_NAME#",
"dev_name": "Smart Wi-Fi Plug Lite",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -20,7 +20,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Unused 1",
"alias": "#MASKED_NAME#",
"dev_name": "Smart Wi-Fi Plug Mini",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -17,12 +17,12 @@
},
"system": {
"get_sysinfo": {
"alias": "TP-LINK_Smart Plug_D310",
"alias": "#MASKED_NAME#",
"child_num": 2,
"children": [
{
"alias": "Garage Charger 1",
"id": "00",
"alias": "#MASKED_NAME# 1",
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
"next_action": {
"type": -1
},
@@ -30,8 +30,8 @@
"state": 0
},
{
"alias": "Garage Charger 2",
"id": "01",
"alias": "#MASKED_NAME# 2",
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
"next_action": {
"type": -1
},
@@ -46,7 +46,7 @@
"hw_ver": "1.0",
"latitude_i": 0,
"led_off": 0,
"longitude_i": -0,
"longitude_i": 0,
"mac": "00:00:00:00:00:00",
"mic_type": "IOT.SMARTPLUGSWITCH",
"model": "HS107(US)",

View File

@@ -11,7 +11,7 @@
"system": {
"get_sysinfo": {
"active_mode": "schedule",
"alias": "Bedroom Lamp Plug",
"alias": "#MASKED_NAME#",
"dev_name": "Wi-Fi Smart Plug With Energy Monitoring",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -11,7 +11,7 @@
"system": {
"get_sysinfo": {
"active_mode": "schedule",
"alias": "Home Google WiFi HS110",
"alias": "#MASKED_NAME#",
"dev_name": "Wi-Fi Smart Plug With Energy Monitoring",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -20,7 +20,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Master Bedroom Fan",
"alias": "#MASKED_NAME#",
"dev_name": "Smart Wi-Fi Light Switch",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -2,7 +2,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "House Fan",
"alias": "#MASKED_NAME#",
"dev_name": "Smart Wi-Fi Light Switch",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -21,7 +21,7 @@
"get_sysinfo": {
"abnormal_detect": 1,
"active_mode": "none",
"alias": "Garage Light",
"alias": "#MASKED_NAME#",
"dev_name": "Smart Wi-Fi 3-Way Light Switch",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -0,0 +1,63 @@
{
"cnCloud": {
"get_info": {
"binded": 1,
"cld_connection": 1,
"err_code": 0,
"fwDlPage": "",
"fwNotifyType": -1,
"illegalType": 0,
"server": "n-devs.tplinkcloud.com",
"stopConnect": 0,
"tcspInfo": "",
"tcspStatus": 1,
"username": "user@example.com"
},
"get_intl_fw_list": {
"err_code": 0,
"fw_list": []
}
},
"schedule": {
"get_next_action": {
"err_code": 0,
"type": -1
},
"get_rules": {
"enable": 0,
"err_code": 0,
"rule_list": [],
"version": 2
}
},
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "#MASKED_NAME#",
"dev_name": "Smart Wi-Fi 3-Way Light Switch",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,
"feature": "TIM",
"hwId": "00000000000000000000000000000000",
"hw_ver": "3.0",
"icon_hash": "",
"latitude_i": 0,
"led_off": 0,
"longitude_i": 0,
"mac": "60:83:E7:00:00:00",
"mic_type": "IOT.SMARTPLUGSWITCH",
"model": "HS210(US)",
"next_action": {
"type": -1
},
"obd_src": "tplink",
"oemId": "00000000000000000000000000000000",
"on_time": 6525,
"relay_state": 1,
"rssi": -31,
"status": "new",
"sw_ver": "1.0.10 Build 240122 Rel.193635",
"updating": 0
}
}
}

View File

@@ -28,7 +28,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Living Room Dimmer Switch",
"alias": "#MASKED_NAME#",
"brightness": 25,
"dev_name": "Smart Wi-Fi Dimmer",
"deviceId": "000000000000000000000000000000000000000",
@@ -38,9 +38,9 @@
"hwId": "00000000000000000000000000000000",
"hw_ver": "1.0",
"icon_hash": "",
"latitude_i": 11.6210,
"latitude_i": 0,
"led_off": 0,
"longitude_i": 42.2074,
"longitude_i": 0,
"mac": "00:00:00:00:00:00",
"mic_type": "IOT.SMARTPLUGSWITCH",
"model": "HS220(US)",

View File

@@ -17,7 +17,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Living Room Dimmer Switch",
"alias": "#MASKED_NAME#",
"brightness": 100,
"dev_name": "Wi-Fi Smart Dimmer",
"deviceId": "0000000000000000000000000000000000000000",

View File

@@ -22,12 +22,12 @@
},
"system": {
"get_sysinfo": {
"alias": "TP-LINK_Power Strip_DAE1",
"alias": "#MASKED_NAME#",
"child_num": 6,
"children": [
{
"alias": "Office Monitor 1",
"id": "00",
"alias": "#MASKED_NAME# 1",
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
"next_action": {
"type": -1
},
@@ -35,8 +35,8 @@
"state": 0
},
{
"alias": "Office Monitor 2",
"id": "01",
"alias": "#MASKED_NAME# 2",
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
"next_action": {
"type": -1
},
@@ -44,8 +44,8 @@
"state": 0
},
{
"alias": "Office Monitor 3",
"id": "02",
"alias": "#MASKED_NAME# 3",
"id": "SCRUBBED_CHILD_DEVICE_ID_3",
"next_action": {
"type": -1
},
@@ -53,8 +53,8 @@
"state": 0
},
{
"alias": "Office Laptop Dock",
"id": "03",
"alias": "#MASKED_NAME# 4",
"id": "SCRUBBED_CHILD_DEVICE_ID_4",
"next_action": {
"type": -1
},
@@ -62,8 +62,8 @@
"state": 0
},
{
"alias": "Office Desk Light",
"id": "04",
"alias": "#MASKED_NAME# 5",
"id": "SCRUBBED_CHILD_DEVICE_ID_5",
"next_action": {
"type": -1
},
@@ -71,8 +71,8 @@
"state": 0
},
{
"alias": "Laptop",
"id": "05",
"alias": "#MASKED_NAME# 6",
"id": "SCRUBBED_CHILD_DEVICE_ID_6",
"next_action": {
"type": -1
},
@@ -87,7 +87,7 @@
"hw_ver": "1.0",
"latitude_i": 0,
"led_off": 0,
"longitude_i": -0,
"longitude_i": 0,
"mac": "00:00:00:00:00:00",
"mic_type": "IOT.SMARTPLUGSWITCH",
"model": "HS300(US)",

View File

@@ -10,12 +10,12 @@
},
"system": {
"get_sysinfo": {
"alias": "TP-LINK_Power Strip_2CA9",
"alias": "#MASKED_NAME#",
"child_num": 6,
"children": [
{
"alias": "Home CameraPC",
"id": "800623145DFF1AA096363EFD161C2E661A9D8DED00",
"alias": "#MASKED_NAME# 1",
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
"next_action": {
"type": -1
},
@@ -23,8 +23,8 @@
"state": 1
},
{
"alias": "Home Firewalla",
"id": "800623145DFF1AA096363EFD161C2E661A9D8DED01",
"alias": "#MASKED_NAME# 2",
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
"next_action": {
"type": -1
},
@@ -32,8 +32,8 @@
"state": 1
},
{
"alias": "Home Cox modem",
"id": "800623145DFF1AA096363EFD161C2E661A9D8DED02",
"alias": "#MASKED_NAME# 3",
"id": "SCRUBBED_CHILD_DEVICE_ID_3",
"next_action": {
"type": -1
},
@@ -41,8 +41,8 @@
"state": 1
},
{
"alias": "Home rpi3-2",
"id": "800623145DFF1AA096363EFD161C2E661A9D8DED03",
"alias": "#MASKED_NAME# 4",
"id": "SCRUBBED_CHILD_DEVICE_ID_4",
"next_action": {
"type": -1
},
@@ -50,8 +50,8 @@
"state": 1
},
{
"alias": "Home Camera Switch",
"id": "800623145DFF1AA096363EFD161C2E661A9D8DED05",
"alias": "#MASKED_NAME# 5",
"id": "SCRUBBED_CHILD_DEVICE_ID_5",
"next_action": {
"type": -1
},
@@ -59,8 +59,8 @@
"state": 1
},
{
"alias": "Home Network Switch",
"id": "800623145DFF1AA096363EFD161C2E661A9D8DED04",
"alias": "#MASKED_NAME# 6",
"id": "SCRUBBED_CHILD_DEVICE_ID_6",
"next_action": {
"type": -1
},

View File

@@ -15,8 +15,8 @@
"child_num": 6,
"children": [
{
"alias": "#MASKED_NAME#",
"id": "8006A0F1D01120C3F93794F7AACACDBE1EAD246D00",
"alias": "#MASKED_NAME# 1",
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
"next_action": {
"type": -1
},
@@ -24,8 +24,8 @@
"state": 1
},
{
"alias": "#MASKED_NAME#",
"id": "8006A0F1D01120C3F93794F7AACACDBE1EAD246D01",
"alias": "#MASKED_NAME# 2",
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
"next_action": {
"type": -1
},
@@ -33,8 +33,8 @@
"state": 1
},
{
"alias": "#MASKED_NAME#",
"id": "8006A0F1D01120C3F93794F7AACACDBE1EAD246D02",
"alias": "#MASKED_NAME# 3",
"id": "SCRUBBED_CHILD_DEVICE_ID_3",
"next_action": {
"type": -1
},
@@ -42,8 +42,8 @@
"state": 1
},
{
"alias": "#MASKED_NAME#",
"id": "8006A0F1D01120C3F93794F7AACACDBE1EAD246D03",
"alias": "#MASKED_NAME# 4",
"id": "SCRUBBED_CHILD_DEVICE_ID_4",
"next_action": {
"type": -1
},
@@ -51,8 +51,8 @@
"state": 1
},
{
"alias": "#MASKED_NAME#",
"id": "8006A0F1D01120C3F93794F7AACACDBE1EAD246D04",
"alias": "#MASKED_NAME# 5",
"id": "SCRUBBED_CHILD_DEVICE_ID_5",
"next_action": {
"type": -1
},
@@ -60,8 +60,8 @@
"state": 1
},
{
"alias": "#MASKED_NAME#",
"id": "8006A0F1D01120C3F93794F7AACACDBE1EAD246D05",
"alias": "#MASKED_NAME# 6",
"id": "SCRUBBED_CHILD_DEVICE_ID_6",
"next_action": {
"type": -1
},

View File

@@ -11,12 +11,12 @@
},
"system": {
"get_sysinfo": {
"alias": "TP-LINK_Power Strip_5C33",
"alias": "#MASKED_NAME#",
"child_num": 6,
"children": [
{
"alias": "Plug 1",
"id": "8006AF35494E7DB13DDE9B8F40BF2E001E77031900",
"alias": "#MASKED_NAME# 1",
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
"next_action": {
"type": -1
},
@@ -24,8 +24,8 @@
"state": 0
},
{
"alias": "Plug 2",
"id": "8006AF35494E7DB13DDE9B8F40BF2E001E77031901",
"alias": "#MASKED_NAME# 2",
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
"next_action": {
"type": -1
},
@@ -33,8 +33,8 @@
"state": 0
},
{
"alias": "Plug 3",
"id": "8006AF35494E7DB13DDE9B8F40BF2E001E77031902",
"alias": "#MASKED_NAME# 3",
"id": "SCRUBBED_CHILD_DEVICE_ID_3",
"next_action": {
"type": -1
},
@@ -42,8 +42,8 @@
"state": 0
},
{
"alias": "Plug 4",
"id": "8006AF35494E7DB13DDE9B8F40BF2E001E77031903",
"alias": "#MASKED_NAME# 4",
"id": "SCRUBBED_CHILD_DEVICE_ID_4",
"next_action": {
"type": -1
},
@@ -51,8 +51,8 @@
"state": 0
},
{
"alias": "Plug 5",
"id": "8006AF35494E7DB13DDE9B8F40BF2E001E77031904",
"alias": "#MASKED_NAME# 5",
"id": "SCRUBBED_CHILD_DEVICE_ID_5",
"next_action": {
"type": -1
},
@@ -60,8 +60,8 @@
"state": 0
},
{
"alias": "Plug 6",
"id": "8006AF35494E7DB13DDE9B8F40BF2E001E77031905",
"alias": "#MASKED_NAME# 6",
"id": "SCRUBBED_CHILD_DEVICE_ID_6",
"next_action": {
"type": -1
},

View File

@@ -21,7 +21,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Bulb3",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"

View File

@@ -19,7 +19,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Home Family Room Table",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"

View File

@@ -34,11 +34,11 @@
},
"description": "Smart Wi-Fi LED Bulb with Tunable White Light",
"dev_state": "normal",
"deviceId": "801200814AD69370AC59DE5501319C051AF409C3",
"deviceId": "0000000000000000000000000000000000000000",
"disco_ver": "1.0",
"err_code": 0,
"heapsize": 290784,
"hwId": "111E35908497A05512E259BB76801E10",
"hwId": "00000000000000000000000000000000",
"hw_ver": "1.0",
"is_color": 0,
"is_dimmable": 1,
@@ -52,10 +52,10 @@
"on_off": 1,
"saturation": 0
},
"mic_mac": "D80D17150474",
"mic_mac": "D80D17000000",
"mic_type": "IOT.SMARTBULB",
"model": "KL120(US)",
"oemId": "1210657CD7FBDC72895644388EEFAE8B",
"oemId": "00000000000000000000000000000000",
"preferred_state": [
{
"brightness": 100,

View File

@@ -20,7 +20,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "kasa-bc01",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"

View File

@@ -22,7 +22,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Test bulb 6",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"

View File

@@ -11,7 +11,7 @@
"stopConnect": 0,
"tcspInfo": "",
"tcspStatus": 1,
"username": "#MASKED_NAME#"
"username": "user@example.com"
},
"get_intl_fw_list": {
"err_code": 0,

View File

@@ -21,7 +21,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Bulb2",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"

View File

@@ -11,7 +11,7 @@
"stopConnect": 0,
"tcspInfo": "",
"tcspStatus": 1,
"username": "#MASKED_NAME#"
"username": "user@example.com"
},
"get_intl_fw_list": {
"err_code": 0,

View File

@@ -20,7 +20,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "KL135 Bulb",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"

View File

@@ -10,7 +10,7 @@
"get_sysinfo": {
"LEF": 0,
"active_mode": "none",
"alias": "Kl400",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"

View File

@@ -10,7 +10,7 @@
"get_sysinfo": {
"LEF": 0,
"active_mode": "none",
"alias": "Kl400",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"

View File

@@ -10,7 +10,7 @@
"get_sysinfo": {
"LEF": 1,
"active_mode": "none",
"alias": "Kl420 test",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"

View File

@@ -10,7 +10,7 @@
"get_sysinfo": {
"LEF": 1,
"active_mode": "none",
"alias": "Bedroom light strip",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"

View File

@@ -23,7 +23,7 @@
"system": {
"get_sysinfo": {
"active_mode": "schedule",
"alias": "Bedroom Lightstrip",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"

View File

@@ -11,7 +11,7 @@
"stopConnect": 0,
"tcspInfo": "",
"tcspStatus": 1,
"username": "#MASKED_NAME#"
"username": "user@example.com"
},
"get_intl_fw_list": {
"err_code": 0,

View File

@@ -10,7 +10,7 @@
"get_sysinfo": {
"LEF": 1,
"active_mode": "none",
"alias": "89 strip",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"

View File

@@ -10,7 +10,7 @@
"get_sysinfo": {
"LEF": 1,
"active_mode": "none",
"alias": "kl430 updated",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"

View File

@@ -22,7 +22,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Kl50",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"

View File

@@ -32,7 +32,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "TP-LINK_Smart Bulb_9179",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"
@@ -60,7 +60,7 @@
"on_off": 0
},
"longitude_i": 0,
"mic_mac": "74DA88C89179",
"mic_mac": "74DA88000000",
"mic_type": "IOT.SMARTBULB",
"model": "KL60(UN)",
"oemId": "00000000000000000000000000000000",

View File

@@ -22,7 +22,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Gold fil",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"

View File

@@ -2,7 +2,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Kasa",
"alias": "#MASKED_NAME#",
"dev_name": "Smart Wi-Fi Plug Mini",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -11,7 +11,7 @@
"stopConnect": 0,
"tcspInfo": "",
"tcspStatus": 1,
"username": "#MASKED_NAME#"
"username": "user@example.com"
},
"get_intl_fw_list": {
"err_code": -7,

View File

@@ -11,7 +11,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Test plug",
"alias": "#MASKED_NAME#",
"dev_name": "Smart Wi-Fi Plug Mini",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -11,7 +11,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Test plug",
"alias": "#MASKED_NAME#",
"dev_name": "Smart Wi-Fi Plug Mini",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -1,12 +1,12 @@
{
"system": {
"get_sysinfo": {
"alias": "TP-LINK_Smart Plug_C2D6",
"alias": "#MASKED_NAME#",
"child_num": 2,
"children": [
{
"alias": "One ",
"id": "80066788DFFFD572D9F2E4A5A6847669213E039F00",
"alias": "#MASKED_NAME# 1",
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
"next_action": {
"type": -1
},
@@ -14,8 +14,8 @@
"state": 1
},
{
"alias": "Two ",
"id": "80066788DFFFD572D9F2E4A5A6847669213E039F01",
"alias": "#MASKED_NAME# 2",
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
"next_action": {
"type": -1
},

View File

@@ -1,12 +1,12 @@
{
"system": {
"get_sysinfo": {
"alias": "Bedroom Power Strip",
"alias": "#MASKED_NAME#",
"child_num": 3,
"children": [
{
"alias": "Plug 1",
"id": "8006E9854025B67C3F9D99BA1E66223D1C9A8A7700",
"alias": "#MASKED_NAME# 1",
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
"next_action": {
"type": -1
},
@@ -14,8 +14,8 @@
"state": 1
},
{
"alias": "Plug 2",
"id": "8006E9854025B67C3F9D99BA1E66223D1C9A8A7701",
"alias": "#MASKED_NAME# 2",
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
"next_action": {
"type": -1
},
@@ -23,8 +23,8 @@
"state": 0
},
{
"alias": "Plug 3",
"id": "8006E9854025B67C3F9D99BA1E66223D1C9A8A7702",
"alias": "#MASKED_NAME# 3",
"id": "SCRUBBED_CHILD_DEVICE_ID_3",
"next_action": {
"type": -1
},

View File

@@ -1,12 +1,12 @@
{
"system": {
"get_sysinfo": {
"alias": "TP-LINK_Power Strip_BDF6",
"alias": "#MASKED_NAME#",
"child_num": 3,
"children": [
{
"alias": "Plug 1",
"id": "800681855E0E9AEF096F4891B3DC88C71E59F42E00",
"alias": "#MASKED_NAME# 1",
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
"next_action": {
"type": -1
},
@@ -14,8 +14,8 @@
"state": 0
},
{
"alias": "Plug 2",
"id": "800681855E0E9AEF096F4891B3DC88C71E59F42E01",
"alias": "#MASKED_NAME# 2",
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
"next_action": {
"type": -1
},
@@ -23,8 +23,8 @@
"state": 0
},
{
"alias": "Plug 3",
"id": "800681855E0E9AEF096F4891B3DC88C71E59F42E02",
"alias": "#MASKED_NAME# 3",
"id": "SCRUBBED_CHILD_DEVICE_ID_3",
"next_action": {
"type": -1
},

View File

@@ -5,8 +5,8 @@
"child_num": 3,
"children": [
{
"alias": "#MASKED_NAME#",
"id": "800639AA097730E58235162FCDA301CE1F038F9101",
"alias": "#MASKED_NAME# 1",
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
"next_action": {
"type": -1
},
@@ -14,8 +14,8 @@
"state": 1
},
{
"alias": "#MASKED_NAME#",
"id": "800639AA097730E58235162FCDA301CE1F038F9102",
"alias": "#MASKED_NAME# 2",
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
"next_action": {
"type": -1
},
@@ -23,8 +23,8 @@
"state": 0
},
{
"alias": "#MASKED_NAME#",
"id": "800639AA097730E58235162FCDA301CE1F038F9100",
"alias": "#MASKED_NAME# 3",
"id": "SCRUBBED_CHILD_DEVICE_ID_3",
"next_action": {
"type": -1
},

View File

@@ -17,12 +17,12 @@
},
"system": {
"get_sysinfo": {
"alias": "TP-LINK_Smart Plug_2ECE",
"alias": "#MASKED_NAME#",
"child_num": 2,
"children": [
{
"alias": "Rope",
"id": "00",
"alias": "#MASKED_NAME# 1",
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
"next_action": {
"action": 1,
"schd_sec": 69240,
@@ -32,8 +32,8 @@
"state": 0
},
{
"alias": "Plug 2",
"id": "01",
"alias": "#MASKED_NAME# 2",
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
"next_action": {
"type": -1
},

View File

@@ -1,12 +1,12 @@
{
"system": {
"get_sysinfo": {
"alias": "TP-LINK_Smart Plug_DC2A",
"alias": "#MASKED_NAME#",
"child_num": 2,
"children": [
{
"alias": "Anc ",
"id": "8006B8E953CC4149E2B13AA27E0D18EF1DCFBF3400",
"alias": "#MASKED_NAME# 1",
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
"next_action": {
"type": -1
},
@@ -14,8 +14,8 @@
"state": 1
},
{
"alias": "Plug 2",
"id": "8006B8E953CC4149E2B13AA27E0D18EF1DCFBF3401",
"alias": "#MASKED_NAME# 2",
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
"next_action": {
"type": -1
},

View File

@@ -5,8 +5,8 @@
"child_num": 2,
"children": [
{
"alias": "#MASKED_NAME#",
"id": "8006521377E30159055A751347B5A5E321A8D0A100",
"alias": "#MASKED_NAME# 1",
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
"next_action": {
"type": -1
},
@@ -14,8 +14,8 @@
"state": 1
},
{
"alias": "#MASKED_NAME#",
"id": "8006521377E30159055A751347B5A5E321A8D0A101",
"alias": "#MASKED_NAME# 2",
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
"next_action": {
"type": -1
},

View File

@@ -5,8 +5,8 @@
"child_num": 2,
"children": [
{
"alias": "#MASKED_NAME#",
"id": "8006521377E30159055A751347B5A5E321A8D0A100",
"alias": "#MASKED_NAME# 1",
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
"next_action": {
"type": -1
},
@@ -14,8 +14,8 @@
"state": 0
},
{
"alias": "#MASKED_NAME#",
"id": "8006521377E30159055A751347B5A5E321A8D0A101",
"alias": "#MASKED_NAME# 2",
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
"next_action": {
"type": -1
},

View File

@@ -2,7 +2,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Kp401",
"alias": "#MASKED_NAME#",
"dev_name": "Smart Outdoor Plug",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -15,7 +15,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Porch Lights",
"alias": "#MASKED_NAME#",
"brightness": 50,
"dev_name": "Kasa Smart Wi-Fi Outdoor Plug-In Dimmer",
"deviceId": "0000000000000000000000000000000000000000",

View File

@@ -0,0 +1,63 @@
{
"cnCloud": {
"get_info": {
"binded": 1,
"cld_connection": 1,
"err_code": 0,
"fwDlPage": "",
"fwNotifyType": -1,
"illegalType": 0,
"server": "n-devs.tplinkcloud.com",
"stopConnect": 0,
"tcspInfo": "",
"tcspStatus": 1,
"username": "user@example.com"
},
"get_intl_fw_list": {
"err_code": 0,
"fw_list": []
}
},
"schedule": {
"get_next_action": {
"err_code": 0,
"type": -1
},
"get_rules": {
"enable": 1,
"err_code": 0,
"rule_list": [],
"version": 2
}
},
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "#MASKED_NAME#",
"dev_name": "Smart Wi-Fi Light Switch",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,
"feature": "TIM",
"hwId": "00000000000000000000000000000000",
"hw_ver": "1.0",
"icon_hash": "",
"latitude_i": 0,
"led_off": 0,
"longitude_i": 0,
"mac": "A8:42:A1:00:00:00",
"mic_type": "IOT.SMARTPLUGSWITCH",
"model": "KS200(US)",
"next_action": {
"type": -1
},
"obd_src": "tplink",
"oemId": "00000000000000000000000000000000",
"on_time": 0,
"relay_state": 0,
"rssi": -46,
"status": "new",
"sw_ver": "1.0.8 Build 240424 Rel.101842",
"updating": 0
}
}
}

View File

@@ -11,7 +11,7 @@
"stopConnect": 0,
"tcspInfo": "",
"tcspStatus": 1,
"username": "#MASKED_NAME#"
"username": "user@example.com"
},
"get_intl_fw_list": {
"err_code": 0,

View File

@@ -66,7 +66,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Test KS200M",
"alias": "#MASKED_NAME#",
"dev_name": "Smart Light Switch with PIR",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,

View File

@@ -11,7 +11,7 @@
"stopConnect": 0,
"tcspInfo": "",
"tcspStatus": 1,
"username": "#MASKED_NAME#"
"username": "user@example.com"
},
"get_intl_fw_list": {
"err_code": 0,

View File

@@ -78,7 +78,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Garage Entryway Lights",
"alias": "#MASKED_NAME#",
"brightness": 100,
"dev_name": "Wi-Fi Smart Dimmer with sensor",
"deviceId": "0000000000000000000000000000000000000000",

View File

@@ -14,7 +14,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "Test KS230",
"alias": "#MASKED_NAME#",
"brightness": 60,
"dc_state": 0,
"dev_name": "Wi-Fi Smart 3-Way Dimmer",

View File

@@ -0,0 +1,112 @@
{
"cnCloud": {
"get_info": {
"binded": 1,
"cld_connection": 1,
"err_code": 0,
"fwDlPage": "",
"fwNotifyType": -1,
"illegalType": 0,
"server": "n-devs.tplinkcloud.com",
"stopConnect": 0,
"tcspInfo": "",
"tcspStatus": 1,
"username": "user@example.com"
},
"get_intl_fw_list": {
"err_code": 0,
"fw_list": []
}
},
"schedule": {
"get_next_action": {
"err_code": 0,
"type": -1
},
"get_rules": {
"enable": 1,
"err_code": 0,
"rule_list": [],
"version": 2
}
},
"smartlife.iot.dimmer": {
"get_default_behavior": {
"double_click": {
"mode": "none"
},
"err_code": 0,
"hard_on": {
"mode": "last_status"
},
"long_press": {
"mode": "instant_on_off"
},
"soft_on": {
"mode": "last_status"
}
},
"get_dimmer_parameters": {
"bulb_type": 1,
"calibration_type": 0,
"err_code": 0,
"fadeOffTime": 1000,
"fadeOnTime": 1000,
"gentleOffTime": 10000,
"gentleOnTime": 3000,
"minThreshold": 11,
"rampRate": 30
}
},
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "#MASKED_NAME#",
"brightness": 100,
"dc_state": 0,
"dev_name": "Wi-Fi Smart 3-Way Dimmer",
"deviceId": "0000000000000000000000000000000000000000",
"err_code": 0,
"feature": "TIM",
"hwId": "00000000000000000000000000000000",
"hw_ver": "2.0",
"icon_hash": "",
"latitude_i": 0,
"led_off": 0,
"longitude_i": 0,
"mac": "5C:E9:31:00:00:00",
"mic_type": "IOT.SMARTPLUGSWITCH",
"model": "KS230(US)",
"next_action": {
"type": -1
},
"ntc_state": 0,
"obd_src": "tplink",
"oemId": "00000000000000000000000000000000",
"on_time": 0,
"preferred_state": [
{
"brightness": 100,
"index": 0
},
{
"brightness": 75,
"index": 1
},
{
"brightness": 50,
"index": 2
},
{
"brightness": 25,
"index": 3
}
],
"relay_state": 0,
"rssi": -41,
"status": "new",
"sw_ver": "1.0.11 Build 240516 Rel.104458",
"updating": 0
}
}
}

View File

@@ -21,7 +21,7 @@
"system": {
"get_sysinfo": {
"active_mode": "none",
"alias": "TP-LINK_Smart Bulb_43EC",
"alias": "#MASKED_NAME#",
"ctrl_protocols": {
"name": "Linkie",
"version": "1.0"

View File

@@ -0,0 +1,86 @@
{
"emeter": {
"get_realtime": {
"err_code": -10008,
"err_msg": "Unsupported API call."
}
},
"smartlife.iot.LAS": {
"get_current_brt": {
"err_code": -10008,
"err_msg": "Unsupported API call."
}
},
"smartlife.iot.PIR": {
"get_config": {
"err_code": -10008,
"err_msg": "Unsupported API call."
}
},
"smartlife.iot.common.emeter": {
"get_realtime": {
"err_code": -10008,
"err_msg": "Unsupported API call."
}
},
"smartlife.iot.dimmer": {
"get_dimmer_parameters": {
"err_code": -10008,
"err_msg": "Unsupported API call."
}
},
"smartlife.iot.smartbulb.lightingservice": {
"get_light_state": {
"err_code": -10008,
"err_msg": "Unsupported API call."
}
},
"system": {
"get_sysinfo": {
"err_code": 0,
"system": {
"a_type": 2,
"alias": "#MASKED_NAME#",
"bind_status": false,
"c_opt": [
0,
1
],
"camera_switch": "on",
"dev_name": "Kasa Spot, 24/7 Recording",
"deviceId": "0000000000000000000000000000000000000000",
"f_list": [
1,
2
],
"hwId": "00000000000000000000000000000000",
"hw_ver": "4.0",
"is_cal": 1,
"last_activity_timestamp": 0,
"latitude": 0,
"led_status": "on",
"longitude": 0,
"mac": "74:FE:CE:00:00:00",
"mic_mac": "74FECE000000",
"model": "EC60(US)",
"new_feature": [
2,
3,
4,
5,
7,
9
],
"oemId": "00000000000000000000000000000000",
"resolution": "720P",
"rssi": -28,
"status": "new",
"stream_version": 2,
"sw_ver": "2.3.22 Build 20230731 rel.69808",
"system_time": 1690827820,
"type": "IOT.IPCAMERA",
"updating": false
}
}
}
}

View File

@@ -1,10 +1,9 @@
{
"host": "127.0.0.1",
"timeout": 5,
"connection_type": {
"device_family": "SMART.IPCAMERA",
"encryption_type": "AES",
"https": true
},
"uses_http": false
"host": "127.0.0.1",
"timeout": 5
}

View File

@@ -1,11 +1,10 @@
{
"host": "127.0.0.1",
"timeout": 5,
"connection_type": {
"device_family": "SMART.TAPOPLUG",
"encryption_type": "KLAP",
"https": false,
"login_version": 2
},
"uses_http": false
"host": "127.0.0.1",
"timeout": 5
}

View File

@@ -1,10 +1,9 @@
{
"host": "127.0.0.1",
"timeout": 5,
"connection_type": {
"device_family": "IOT.SMARTPLUGSWITCH",
"encryption_type": "XOR",
"https": false
},
"uses_http": false
"host": "127.0.0.1",
"timeout": 5
}

View File

@@ -0,0 +1,258 @@
{
"component_nego": {
"component_list": [
{
"id": "device",
"ver_code": 2
},
{
"id": "firmware",
"ver_code": 2
},
{
"id": "quick_setup",
"ver_code": 3
},
{
"id": "time",
"ver_code": 1
},
{
"id": "wireless",
"ver_code": 1
},
{
"id": "schedule",
"ver_code": 2
},
{
"id": "countdown",
"ver_code": 2
},
{
"id": "antitheft",
"ver_code": 1
},
{
"id": "account",
"ver_code": 1
},
{
"id": "synchronize",
"ver_code": 1
},
{
"id": "sunrise_sunset",
"ver_code": 1
},
{
"id": "led",
"ver_code": 1
},
{
"id": "cloud_connect",
"ver_code": 1
},
{
"id": "iot_cloud",
"ver_code": 1
},
{
"id": "device_local_time",
"ver_code": 1
},
{
"id": "default_states",
"ver_code": 1
}
]
},
"discovery_result": {
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "D100C(US)",
"device_type": "SMART.TAPOCHIME",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "40-AE-30-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
}
},
"get_auto_update_info": {
"enable": true,
"random_range": 120,
"time": 180
},
"get_connect_cloud_state": {
"status": 0
},
"get_device_info": {
"avatar": "",
"device_id": "0000000000000000000000000000000000000000",
"fw_id": "00000000000000000000000000000000",
"fw_ver": "1.1.3 Build 231221 Rel.154700",
"has_set_location_info": true,
"hw_id": "00000000000000000000000000000000",
"hw_ver": "1.0",
"ip": "127.0.0.123",
"lang": "en_US",
"latitude": 0,
"led_off": 0,
"longitude": 0,
"mac": "40-AE-30-00-00-00",
"model": "D100C",
"nickname": "I01BU0tFRF9OQU1FIw==",
"oem_id": "00000000000000000000000000000000",
"region": "America/Chicago",
"rssi": -24,
"signal_level": 3,
"specs": "",
"ssid": "I01BU0tFRF9TU0lEIw==",
"time_diff": -360,
"type": "SMART.TAPOCHIME"
},
"get_device_time": {
"region": "America/Chicago",
"time_diff": -360,
"timestamp": 1736433406
},
"get_device_usage": {},
"get_fw_download_state": {
"auto_upgrade": false,
"download_progress": 0,
"reboot_time": 5,
"status": 0,
"upgrade_time": 5
},
"get_latest_fw": {
"fw_size": 0,
"fw_ver": "1.1.3 Build 231221 Rel.154700",
"hw_id": "",
"need_to_upgrade": false,
"oem_id": "",
"release_date": "",
"release_note": "",
"type": 0
},
"get_wireless_scan_info": {
"ap_list": [
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 3,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 2,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
},
{
"bssid": "000000000000",
"channel": 0,
"cipher_type": 2,
"key_type": "wpa2_psk",
"signal_level": 1,
"ssid": "I01BU0tFRF9TU0lEIw=="
}
],
"start_index": 0,
"sum": 9,
"wep_supported": false
},
"qs_component_nego": {
"component_list": [
{
"id": "quick_setup",
"ver_code": 3
},
{
"id": "sunrise_sunset",
"ver_code": 1
},
{
"id": "ble_whole_setup",
"ver_code": 1
},
{
"id": "iot_cloud",
"ver_code": 1
},
{
"id": "inherit",
"ver_code": 1
},
{
"id": "firmware",
"ver_code": 2
}
],
"extra_info": {
"device_model": "D100C",
"device_type": "SMART.TAPOCHIME",
"is_klap": true
}
}
}

View File

@@ -84,21 +84,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "EP25(US)",
"device_type": "SMART.KASAPLUG",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "00-00-00-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "EP25(US)",
"device_type": "SMART.KASAPLUG",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "00-00-00-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
}
},
"get_antitheft_rules": {
"antitheft_rule_max_count": 1,

View File

@@ -88,21 +88,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "EP25(US)",
"device_type": "SMART.KASAPLUG",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "3C-52-A1-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "EP25(US)",
"device_type": "SMART.KASAPLUG",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "3C-52-A1-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
}
},
"get_antitheft_rules": {
"antitheft_rule_max_count": 1,

View File

@@ -379,21 +379,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "EP40M(US)",
"device_type": "SMART.KASAPLUG",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "F0-09-0D-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "matter",
"owner": "00000000000000000000000000000000"
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "EP40M(US)",
"device_type": "SMART.KASAPLUG",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "F0-09-0D-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "matter",
"owner": "00000000000000000000000000000000"
}
},
"get_auto_update_info": {
"enable": true,

View File

@@ -84,21 +84,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "H100(EU)",
"device_type": "SMART.TAPOHUB",
"factory_default": true,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "3C-52-A1-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": ""
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "H100(EU)",
"device_type": "SMART.TAPOHUB",
"factory_default": true,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "3C-52-A1-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": ""
}
},
"get_auto_update_info": {
"enable": true,

View File

@@ -96,21 +96,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "H100(EU)",
"device_type": "SMART.TAPOHUB",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "3C-52-A1-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "H100(EU)",
"device_type": "SMART.TAPOHUB",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "3C-52-A1-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
}
},
"get_alarm_configure": {
"duration": 10,
@@ -469,6 +472,24 @@
"setup_code": "00000000000",
"setup_payload": "00:0000000000000000000"
},
"get_scan_child_device_list": {
"child_device_list": [
{
"category": "subg.trigger.temp-hmdt-sensor",
"device_id": "REDACTED_1",
"device_model": "T315",
"name": "REDACTED_1"
},
{
"category": "subg.trigger.contact-sensor",
"device_id": "REDACTED_2",
"device_model": "T110",
"name": "REDACTED_2"
}
],
"scan_status": "scanning",
"scan_wait_time": 28
},
"get_support_alarm_type_list": {
"alarm_type_list": [
"Doorbell Ring 1",

View File

@@ -92,21 +92,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "H100(EU)",
"device_type": "SMART.TAPOHUB",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "3C-52-A1-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "H100(EU)",
"device_type": "SMART.TAPOHUB",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "3C-52-A1-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
}
},
"get_alarm_configure": {
"duration": 10,
@@ -195,7 +198,7 @@
"ver_code": 1
}
],
"device_id": "0000000000000000000000000000000000000000"
"device_id": "SCRUBBED_CHILD_DEVICE_ID_1"
}
],
"start_index": 0,
@@ -213,7 +216,7 @@
"current_humidity_exception": -34,
"current_temp": 22.2,
"current_temp_exception": 0,
"device_id": "0000000000000000000000000000000000000000",
"device_id": "SCRUBBED_CHILD_DEVICE_ID_1",
"fw_ver": "1.7.0 Build 230424 Rel.170332",
"hw_id": "00000000000000000000000000000000",
"hw_ver": "1.0",

View File

@@ -80,21 +80,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "HS200(US)",
"device_type": "SMART.KASASWITCH",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "74-FE-CE-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "HS200(US)",
"device_type": "SMART.KASASWITCH",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "74-FE-CE-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
}
},
"get_antitheft_rules": {
"antitheft_rule_max_count": 1,

View File

@@ -100,20 +100,23 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"owner": "00000000000000000000000000000000",
"device_type": "SMART.KASASWITCH",
"device_model": "HS220(US)",
"ip": "127.0.0.123",
"mac": "24-2F-D0-00-00-00",
"is_support_iot_cloud": true,
"obd_src": "tplink",
"factory_default": false,
"mgt_encrypt_schm": {
"is_support_https": false,
"encrypt_type": "AES",
"http_port": 80,
"lv": 2
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "HS220(US)",
"device_type": "SMART.KASASWITCH",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "24-2F-D0-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
}
},
"get_antitheft_rules": {

View File

@@ -84,21 +84,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KH100(EU)",
"device_type": "SMART.KASAHUB",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "A8-42-A1-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KH100(EU)",
"device_type": "SMART.KASAHUB",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "A8-42-A1-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
}
},
"get_alarm_configure": {
"duration": 300,

View File

@@ -88,21 +88,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KH100(EU)",
"device_type": "SMART.KASAHUB",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "A8-42-A1-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KH100(EU)",
"device_type": "SMART.KASAHUB",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "A8-42-A1-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
}
},
"get_alarm_configure": {
"duration": 300,

View File

@@ -1,4 +1,4 @@
{
{
"component_nego": {
"component_list": [
{
@@ -88,21 +88,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KH100(UK)",
"device_type": "SMART.KASAHUB",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "F0-A7-31-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KH100(UK)",
"device_type": "SMART.KASAHUB",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "F0-A7-31-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
}
},
"get_alarm_configure": {
"duration": 300,

View File

@@ -84,21 +84,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KP125M(US)",
"device_type": "SMART.KASAPLUG",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "00-00-00-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KP125M(US)",
"device_type": "SMART.KASAPLUG",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "00-00-00-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
}
},
"get_current_power": {
"current_power": 17
@@ -124,7 +127,7 @@
"longitude": 0,
"mac": "00-00-00-00-00-00",
"model": "KP125M",
"nickname": "IyNNQVNLRUROQU1FIyM=",
"nickname": "I01BU0tFRF9OQU1FIw==",
"oem_id": "00000000000000000000000000000000",
"on_time": 5332,
"overheated": false,
@@ -133,7 +136,7 @@
"rssi": -62,
"signal_level": 2,
"specs": "",
"ssid": "IyNNQVNLRUROQU1FIyM=",
"ssid": "I01BU0tFRF9TU0lEIw==",
"time_diff": -360,
"type": "SMART.KASAPLUG"
},

View File

@@ -88,21 +88,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KP125M(US)",
"device_type": "SMART.KASAPLUG",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "78-8C-B5-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KP125M(US)",
"device_type": "SMART.KASAPLUG",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "78-8C-B5-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
}
},
"get_antitheft_rules": {
"antitheft_rule_max_count": 1,

View File

@@ -80,21 +80,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KS205(US)",
"device_type": "SMART.KASASWITCH",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "00-00-00-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KS205(US)",
"device_type": "SMART.KASASWITCH",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "00-00-00-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
}
},
"get_antitheft_rules": {
"antitheft_rule_max_count": 1,

View File

@@ -76,21 +76,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KS205(US)",
"device_type": "SMART.KASASWITCH",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "40-ED-00-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": ""
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KS205(US)",
"device_type": "SMART.KASASWITCH",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "40-ED-00-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": ""
}
},
"get_antitheft_rules": {
"antitheft_rule_max_count": 1,

View File

@@ -96,21 +96,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KS225(US)",
"device_type": "SMART.KASASWITCH",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "00-00-00-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KS225(US)",
"device_type": "SMART.KASASWITCH",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "00-00-00-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
}
},
"get_antitheft_rules": {
"antitheft_rule_max_count": 1,

View File

@@ -96,21 +96,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KS225(US)",
"device_type": "SMART.KASASWITCH",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "3C-52-A1-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": ""
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KS225(US)",
"device_type": "SMART.KASASWITCH",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "3C-52-A1-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "KLAP",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": ""
}
},
"get_antitheft_rules": {
"antitheft_rule_max_count": 1,

View File

@@ -414,21 +414,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KS240(US)",
"device_type": "SMART.KASASWITCH",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "F0-A7-31-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KS240(US)",
"device_type": "SMART.KASASWITCH",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "F0-A7-31-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
}
},
"get_auto_update_info": {
"enable": false,

View File

@@ -104,21 +104,24 @@
]
},
"discovery_result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KS240(US)",
"device_type": "SMART.KASASWITCH",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "F0-A7-31-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
"error_code": 0,
"result": {
"device_id": "00000000000000000000000000000000",
"device_model": "KS240(US)",
"device_type": "SMART.KASASWITCH",
"factory_default": false,
"ip": "127.0.0.123",
"is_support_iot_cloud": true,
"mac": "F0-A7-31-00-00-00",
"mgt_encrypt_schm": {
"encrypt_type": "AES",
"http_port": 80,
"is_support_https": false,
"lv": 2
},
"obd_src": "tplink",
"owner": "00000000000000000000000000000000"
}
},
"get_auto_update_info": {
"enable": false,
@@ -206,7 +209,7 @@
"ver_code": 1
}
],
"device_id": "000000000000000000000000000000000000000001"
"device_id": "SCRUBBED_CHILD_DEVICE_ID_1"
},
{
"component_list": [
@@ -267,7 +270,7 @@
"ver_code": 1
}
],
"device_id": "000000000000000000000000000000000000000000"
"device_id": "SCRUBBED_CHILD_DEVICE_ID_2"
}
],
"start_index": 0,
@@ -279,7 +282,7 @@
"avatar": "switch_ks240",
"bind_count": 1,
"category": "kasa.switch.outlet.sub-fan",
"device_id": "000000000000000000000000000000000000000000",
"device_id": "SCRUBBED_CHILD_DEVICE_ID_2",
"device_on": true,
"fan_sleep_mode_on": false,
"fan_speed_level": 1,
@@ -317,7 +320,7 @@
],
"type": "last_states"
},
"device_id": "000000000000000000000000000000000000000001",
"device_id": "SCRUBBED_CHILD_DEVICE_ID_1",
"device_on": false,
"fade_off_time": 1,
"fade_on_time": 1,

Some files were not shown because too many files have changed in this diff Show More