mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-22 19:23:34 +00:00
Merge branch 'master' into feat/smartcam_passthrough
This commit is contained in:
commit
9f10cd10cb
@ -283,9 +283,12 @@ git rebase upstream/master
|
|||||||
git checkout -b janitor/merge_patch
|
git checkout -b janitor/merge_patch
|
||||||
git fetch upstream patch
|
git fetch upstream patch
|
||||||
git merge upstream/patch --no-commit
|
git merge upstream/patch --no-commit
|
||||||
|
# If there are any merge conflicts run the following command which will simply make master win
|
||||||
|
# Do not run it if there are no conflicts as it will end up checking out upstream/master
|
||||||
git diff --name-only --diff-filter=U | xargs git checkout upstream/master
|
git diff --name-only --diff-filter=U | xargs git checkout upstream/master
|
||||||
|
# Check the diff is as expected
|
||||||
git diff --staged
|
git diff --staged
|
||||||
# The only diff should be the version in pyproject.toml and CHANGELOG.md
|
# The only diff should be the version in pyproject.toml and uv.lock, and CHANGELOG.md
|
||||||
# unless a change made on patch that was not part of a cherry-pick commit
|
# unless a change made on patch that was not part of a cherry-pick commit
|
||||||
# If there are any other unexpected diffs `git checkout upstream/master [thefilename]`
|
# If there are any other unexpected diffs `git checkout upstream/master [thefilename]`
|
||||||
git commit -m "Merge patch into local master" -S
|
git commit -m "Merge patch into local master" -S
|
||||||
|
@ -10,8 +10,6 @@ and finally execute a query to query all of them at once.
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import base64
|
|
||||||
import collections.abc
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
@ -19,6 +17,7 @@ import re
|
|||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
from collections import defaultdict, namedtuple
|
from collections import defaultdict, namedtuple
|
||||||
|
from collections.abc import Callable
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@ -39,13 +38,20 @@ from kasa import (
|
|||||||
)
|
)
|
||||||
from kasa.device_factory import get_protocol
|
from kasa.device_factory import get_protocol
|
||||||
from kasa.deviceconfig import DeviceEncryptionType, DeviceFamily
|
from kasa.deviceconfig import DeviceEncryptionType, DeviceFamily
|
||||||
from kasa.discover import DiscoveryResult
|
from kasa.discover import (
|
||||||
|
NEW_DISCOVERY_REDACTORS,
|
||||||
|
DiscoveredRaw,
|
||||||
|
DiscoveryResult,
|
||||||
|
)
|
||||||
from kasa.exceptions import SmartErrorCode
|
from kasa.exceptions import SmartErrorCode
|
||||||
from kasa.protocols import IotProtocol
|
from kasa.protocols import IotProtocol
|
||||||
|
from kasa.protocols.iotprotocol import REDACTORS as IOT_REDACTORS
|
||||||
|
from kasa.protocols.protocol import redact_data
|
||||||
from kasa.protocols.smartcamprotocol import (
|
from kasa.protocols.smartcamprotocol import (
|
||||||
SmartCamProtocol,
|
SmartCamProtocol,
|
||||||
_ChildCameraProtocolWrapper,
|
_ChildCameraProtocolWrapper,
|
||||||
)
|
)
|
||||||
|
from kasa.protocols.smartprotocol import REDACTORS as SMART_REDACTORS
|
||||||
from kasa.protocols.smartprotocol import SmartProtocol, _ChildProtocolWrapper
|
from kasa.protocols.smartprotocol import SmartProtocol, _ChildProtocolWrapper
|
||||||
from kasa.smart import SmartChildDevice, SmartDevice
|
from kasa.smart import SmartChildDevice, SmartDevice
|
||||||
from kasa.smartcam import SmartCamDevice
|
from kasa.smartcam import SmartCamDevice
|
||||||
@ -63,6 +69,42 @@ ENCRYPT_TYPES = [encrypt_type.value for encrypt_type in DeviceEncryptionType]
|
|||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def _wrap_redactors(redactors: dict[str, Callable[[Any], Any] | None]):
|
||||||
|
"""Wrap the redactors for dump_devinfo.
|
||||||
|
|
||||||
|
Will replace all partial REDACT_ values with zeros.
|
||||||
|
If the data item is already scrubbed by dump_devinfo will leave as-is.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _wrap(key: str) -> Any:
|
||||||
|
def _wrapped(redactor: Callable[[Any], Any] | None) -> Any | None:
|
||||||
|
if redactor is None:
|
||||||
|
return lambda x: "**SCRUBBED**"
|
||||||
|
|
||||||
|
def _redact_to_zeros(x: Any) -> Any:
|
||||||
|
if isinstance(x, str) and "REDACT" in x:
|
||||||
|
return re.sub(r"\w", "0", x)
|
||||||
|
if isinstance(x, dict):
|
||||||
|
for k, v in x.items():
|
||||||
|
x[k] = _redact_to_zeros(v)
|
||||||
|
return x
|
||||||
|
|
||||||
|
def _scrub(x: Any) -> Any:
|
||||||
|
if key in {"ip", "local_ip"}:
|
||||||
|
return "127.0.0.123"
|
||||||
|
# Already scrubbed by dump_devinfo
|
||||||
|
if isinstance(x, str) and "SCRUBBED" in x:
|
||||||
|
return x
|
||||||
|
default = redactor(x)
|
||||||
|
return _redact_to_zeros(default)
|
||||||
|
|
||||||
|
return _scrub
|
||||||
|
|
||||||
|
return _wrapped(redactors[key])
|
||||||
|
|
||||||
|
return {key: _wrap(key) for key in redactors}
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
class SmartCall:
|
class SmartCall:
|
||||||
"""Class for smart and smartcam calls."""
|
"""Class for smart and smartcam calls."""
|
||||||
@ -74,115 +116,6 @@ class SmartCall:
|
|||||||
supports_multiple: bool = True
|
supports_multiple: bool = True
|
||||||
|
|
||||||
|
|
||||||
def scrub(res):
|
|
||||||
"""Remove identifiers from the given dict."""
|
|
||||||
keys_to_scrub = [
|
|
||||||
"deviceId",
|
|
||||||
"fwId",
|
|
||||||
"hwId",
|
|
||||||
"oemId",
|
|
||||||
"mac",
|
|
||||||
"mic_mac",
|
|
||||||
"latitude_i",
|
|
||||||
"longitude_i",
|
|
||||||
"latitude",
|
|
||||||
"longitude",
|
|
||||||
"la", # lat on ks240
|
|
||||||
"lo", # lon on ks240
|
|
||||||
"owner",
|
|
||||||
"device_id",
|
|
||||||
"ip",
|
|
||||||
"ssid",
|
|
||||||
"hw_id",
|
|
||||||
"fw_id",
|
|
||||||
"oem_id",
|
|
||||||
"nickname",
|
|
||||||
"alias",
|
|
||||||
"bssid",
|
|
||||||
"channel",
|
|
||||||
"original_device_id", # for child devices on strips
|
|
||||||
"parent_device_id", # for hub children
|
|
||||||
"setup_code", # matter
|
|
||||||
"setup_payload", # matter
|
|
||||||
"mfi_setup_code", # mfi_ for homekit
|
|
||||||
"mfi_setup_id",
|
|
||||||
"mfi_token_token",
|
|
||||||
"mfi_token_uuid",
|
|
||||||
"dev_id",
|
|
||||||
"device_name",
|
|
||||||
"device_alias",
|
|
||||||
"connect_ssid",
|
|
||||||
"encrypt_info",
|
|
||||||
"local_ip",
|
|
||||||
"username",
|
|
||||||
# vacuum
|
|
||||||
"board_sn",
|
|
||||||
"custom_sn",
|
|
||||||
"location",
|
|
||||||
]
|
|
||||||
|
|
||||||
for k, v in res.items():
|
|
||||||
if isinstance(v, collections.abc.Mapping):
|
|
||||||
if k == "encrypt_info":
|
|
||||||
if "data" in v:
|
|
||||||
v["data"] = ""
|
|
||||||
if "key" in v:
|
|
||||||
v["key"] = ""
|
|
||||||
else:
|
|
||||||
res[k] = scrub(res.get(k))
|
|
||||||
elif (
|
|
||||||
isinstance(v, list)
|
|
||||||
and len(v) > 0
|
|
||||||
and isinstance(v[0], collections.abc.Mapping)
|
|
||||||
):
|
|
||||||
res[k] = [scrub(vi) for vi in v]
|
|
||||||
else:
|
|
||||||
if k in keys_to_scrub:
|
|
||||||
if k in ["mac", "mic_mac"]:
|
|
||||||
# Some macs have : or - as a separator and others do not
|
|
||||||
if len(v) == 12:
|
|
||||||
v = f"{v[:6]}000000"
|
|
||||||
else:
|
|
||||||
delim = ":" if ":" in v else "-"
|
|
||||||
rest = delim.join(
|
|
||||||
format(s, "02x") for s in bytes.fromhex("000000")
|
|
||||||
)
|
|
||||||
v = f"{v[:8]}{delim}{rest}"
|
|
||||||
elif k in ["latitude", "latitude_i", "longitude", "longitude_i"]:
|
|
||||||
v = 0
|
|
||||||
elif k in ["ip", "local_ip"]:
|
|
||||||
v = "127.0.0.123"
|
|
||||||
elif k in ["ssid"]:
|
|
||||||
# Need a valid base64 value here
|
|
||||||
v = base64.b64encode(b"#MASKED_SSID#").decode()
|
|
||||||
elif k in ["nickname"]:
|
|
||||||
v = base64.b64encode(b"#MASKED_NAME#").decode()
|
|
||||||
elif k in [
|
|
||||||
"alias",
|
|
||||||
"device_alias",
|
|
||||||
"device_name",
|
|
||||||
"username",
|
|
||||||
"location",
|
|
||||||
]:
|
|
||||||
v = "#MASKED_NAME#"
|
|
||||||
elif isinstance(res[k], int):
|
|
||||||
v = 0
|
|
||||||
elif k in ["map_data"]: #
|
|
||||||
v = "#SCRUBBED_MAPDATA#"
|
|
||||||
elif k in ["device_id", "dev_id"] and "SCRUBBED" in v:
|
|
||||||
pass # already scrubbed
|
|
||||||
elif k == ["device_id", "dev_id"] and len(v) > 40:
|
|
||||||
# retain the last two chars when scrubbing child ids
|
|
||||||
end = v[-2:]
|
|
||||||
v = re.sub(r"\w", "0", v)
|
|
||||||
v = v[:40] + end
|
|
||||||
else:
|
|
||||||
v = re.sub(r"\w", "0", v)
|
|
||||||
|
|
||||||
res[k] = v
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
def default_to_regular(d):
|
def default_to_regular(d):
|
||||||
"""Convert nested defaultdicts to regular ones.
|
"""Convert nested defaultdicts to regular ones.
|
||||||
|
|
||||||
@ -209,7 +142,7 @@ async def handle_device(
|
|||||||
for fixture_result in fixture_results:
|
for fixture_result in fixture_results:
|
||||||
save_filename = Path(basedir) / fixture_result.folder / fixture_result.filename
|
save_filename = Path(basedir) / fixture_result.folder / fixture_result.filename
|
||||||
|
|
||||||
pprint(scrub(fixture_result.data))
|
pprint(fixture_result.data)
|
||||||
if autosave:
|
if autosave:
|
||||||
save = "y"
|
save = "y"
|
||||||
else:
|
else:
|
||||||
@ -325,6 +258,11 @@ async def cli(
|
|||||||
if debug:
|
if debug:
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
|
raw_discovery = {}
|
||||||
|
|
||||||
|
def capture_raw(discovered: DiscoveredRaw):
|
||||||
|
raw_discovery[discovered["meta"]["ip"]] = discovered["discovery_response"]
|
||||||
|
|
||||||
credentials = Credentials(username=username, password=password)
|
credentials = Credentials(username=username, password=password)
|
||||||
if host is not None:
|
if host is not None:
|
||||||
if discovery_info:
|
if discovery_info:
|
||||||
@ -377,12 +315,16 @@ async def cli(
|
|||||||
credentials=credentials,
|
credentials=credentials,
|
||||||
port=port,
|
port=port,
|
||||||
discovery_timeout=discovery_timeout,
|
discovery_timeout=discovery_timeout,
|
||||||
|
on_discovered_raw=capture_raw,
|
||||||
)
|
)
|
||||||
|
discovery_info = raw_discovery[device.host]
|
||||||
|
if decrypted_data := device._discovery_info.get("decrypted_data"):
|
||||||
|
discovery_info["decrypted_data"] = decrypted_data
|
||||||
await handle_device(
|
await handle_device(
|
||||||
basedir,
|
basedir,
|
||||||
autosave,
|
autosave,
|
||||||
device.protocol,
|
device.protocol,
|
||||||
discovery_info=device._discovery_info,
|
discovery_info=discovery_info,
|
||||||
batch_size=batch_size,
|
batch_size=batch_size,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -391,21 +333,28 @@ async def cli(
|
|||||||
f" {target}. Use --target to override."
|
f" {target}. Use --target to override."
|
||||||
)
|
)
|
||||||
devices = await Discover.discover(
|
devices = await Discover.discover(
|
||||||
target=target, credentials=credentials, discovery_timeout=discovery_timeout
|
target=target,
|
||||||
|
credentials=credentials,
|
||||||
|
discovery_timeout=discovery_timeout,
|
||||||
|
on_discovered_raw=capture_raw,
|
||||||
)
|
)
|
||||||
click.echo(f"Detected {len(devices)} devices")
|
click.echo(f"Detected {len(devices)} devices")
|
||||||
for dev in devices.values():
|
for dev in devices.values():
|
||||||
|
discovery_info = raw_discovery[dev.host]
|
||||||
|
if decrypted_data := dev._discovery_info.get("decrypted_data"):
|
||||||
|
discovery_info["decrypted_data"] = decrypted_data
|
||||||
|
|
||||||
await handle_device(
|
await handle_device(
|
||||||
basedir,
|
basedir,
|
||||||
autosave,
|
autosave,
|
||||||
dev.protocol,
|
dev.protocol,
|
||||||
discovery_info=dev._discovery_info,
|
discovery_info=discovery_info,
|
||||||
batch_size=batch_size,
|
batch_size=batch_size,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def get_legacy_fixture(
|
async def get_legacy_fixture(
|
||||||
protocol: IotProtocol, *, discovery_info: dict[str, Any] | None
|
protocol: IotProtocol, *, discovery_info: dict[str, dict[str, Any]] | None
|
||||||
) -> FixtureResult:
|
) -> FixtureResult:
|
||||||
"""Get fixture for legacy IOT style protocol."""
|
"""Get fixture for legacy IOT style protocol."""
|
||||||
items = [
|
items = [
|
||||||
@ -475,11 +424,21 @@ async def get_legacy_fixture(
|
|||||||
_echo_error(f"Unable to query all successes at once: {ex}")
|
_echo_error(f"Unable to query all successes at once: {ex}")
|
||||||
finally:
|
finally:
|
||||||
await protocol.close()
|
await protocol.close()
|
||||||
|
|
||||||
|
final = redact_data(final, _wrap_redactors(IOT_REDACTORS))
|
||||||
|
|
||||||
|
# Scrub the child device ids
|
||||||
|
if children := final.get("system", {}).get("get_sysinfo", {}).get("children"):
|
||||||
|
for index, child in enumerate(children):
|
||||||
|
if "id" not in child:
|
||||||
|
_LOGGER.error("Could not find a device for the child device: %s", child)
|
||||||
|
else:
|
||||||
|
child["id"] = f"SCRUBBED_CHILD_DEVICE_ID_{index + 1}"
|
||||||
|
|
||||||
if discovery_info and not discovery_info.get("system"):
|
if discovery_info and not discovery_info.get("system"):
|
||||||
# Need to recreate a DiscoverResult here because we don't want the aliases
|
final["discovery_result"] = redact_data(
|
||||||
# in the fixture, we want the actual field names as returned by the device.
|
discovery_info, _wrap_redactors(NEW_DISCOVERY_REDACTORS)
|
||||||
dr = DiscoveryResult.from_dict(discovery_info)
|
)
|
||||||
final["discovery_result"] = dr.to_dict()
|
|
||||||
|
|
||||||
click.echo(f"Got {len(successes)} successes")
|
click.echo(f"Got {len(successes)} successes")
|
||||||
click.echo(click.style("## device info file ##", bold=True))
|
click.echo(click.style("## device info file ##", bold=True))
|
||||||
@ -867,7 +826,10 @@ def get_smart_child_fixture(response):
|
|||||||
|
|
||||||
|
|
||||||
async def get_smart_fixtures(
|
async def get_smart_fixtures(
|
||||||
protocol: SmartProtocol, *, discovery_info: dict[str, Any] | None, batch_size: int
|
protocol: SmartProtocol,
|
||||||
|
*,
|
||||||
|
discovery_info: dict[str, dict[str, Any]] | None,
|
||||||
|
batch_size: int,
|
||||||
) -> list[FixtureResult]:
|
) -> list[FixtureResult]:
|
||||||
"""Get fixture for new TAPO style protocol."""
|
"""Get fixture for new TAPO style protocol."""
|
||||||
if isinstance(protocol, SmartCamProtocol):
|
if isinstance(protocol, SmartCamProtocol):
|
||||||
@ -988,22 +950,24 @@ async def get_smart_fixtures(
|
|||||||
continue
|
continue
|
||||||
_LOGGER.error("Could not find a device for the child device: %s", child)
|
_LOGGER.error("Could not find a device for the child device: %s", child)
|
||||||
|
|
||||||
# Need to recreate a DiscoverResult here because we don't want the aliases
|
final = redact_data(final, _wrap_redactors(SMART_REDACTORS))
|
||||||
# in the fixture, we want the actual field names as returned by the device.
|
discovery_result = None
|
||||||
if discovery_info:
|
if discovery_info:
|
||||||
dr = DiscoveryResult.from_dict(discovery_info) # type: ignore
|
final["discovery_result"] = redact_data(
|
||||||
final["discovery_result"] = dr.to_dict()
|
discovery_info, _wrap_redactors(NEW_DISCOVERY_REDACTORS)
|
||||||
|
)
|
||||||
|
discovery_result = discovery_info["result"]
|
||||||
|
|
||||||
click.echo(f"Got {len(successes)} successes")
|
click.echo(f"Got {len(successes)} successes")
|
||||||
click.echo(click.style("## device info file ##", bold=True))
|
click.echo(click.style("## device info file ##", bold=True))
|
||||||
|
|
||||||
if "get_device_info" in final:
|
if "get_device_info" in final:
|
||||||
# smart protocol
|
# smart protocol
|
||||||
model_info = SmartDevice._get_device_info(final, discovery_info)
|
model_info = SmartDevice._get_device_info(final, discovery_result)
|
||||||
copy_folder = SMART_FOLDER
|
copy_folder = SMART_FOLDER
|
||||||
else:
|
else:
|
||||||
# smart camera protocol
|
# smart camera protocol
|
||||||
model_info = SmartCamDevice._get_device_info(final, discovery_info)
|
model_info = SmartCamDevice._get_device_info(final, discovery_result)
|
||||||
copy_folder = SMARTCAM_FOLDER
|
copy_folder = SMARTCAM_FOLDER
|
||||||
hw_version = model_info.hardware_version
|
hw_version = model_info.hardware_version
|
||||||
sw_version = model_info.firmware_version
|
sw_version = model_info.firmware_version
|
||||||
|
@ -205,7 +205,7 @@ def _get_supported_devices(
|
|||||||
fixture_data = json.load(f)
|
fixture_data = json.load(f)
|
||||||
|
|
||||||
model_info = device_cls._get_device_info(
|
model_info = device_cls._get_device_info(
|
||||||
fixture_data, fixture_data.get("discovery_result")
|
fixture_data, fixture_data.get("discovery_result", {}).get("result")
|
||||||
)
|
)
|
||||||
|
|
||||||
supported_type = DEVICE_TYPE_TO_PRODUCT_GROUP[model_info.device_type]
|
supported_type = DEVICE_TYPE_TO_PRODUCT_GROUP[model_info.device_type]
|
||||||
|
128
devtools/update_fixtures.py
Normal file
128
devtools/update_fixtures.py
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
"""Module to mass update fixture files."""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
from collections.abc import Callable
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import asyncclick as click
|
||||||
|
|
||||||
|
from devtools.dump_devinfo import _wrap_redactors
|
||||||
|
from kasa.discover import NEW_DISCOVERY_REDACTORS, redact_data
|
||||||
|
from kasa.protocols.iotprotocol import REDACTORS as IOT_REDACTORS
|
||||||
|
from kasa.protocols.smartprotocol import REDACTORS as SMART_REDACTORS
|
||||||
|
|
||||||
|
FIXTURE_FOLDER = "tests/fixtures/"
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def update_fixtures(update_func: Callable[[dict], bool], *, dry_run: bool) -> None:
|
||||||
|
"""Run the update function against the fixtures."""
|
||||||
|
for file in Path(FIXTURE_FOLDER).glob("**/*.json"):
|
||||||
|
with file.open("r") as f:
|
||||||
|
fixture_data = json.load(f)
|
||||||
|
|
||||||
|
if file.parent.name == "serialization":
|
||||||
|
continue
|
||||||
|
changed = update_func(fixture_data)
|
||||||
|
if changed:
|
||||||
|
click.echo(f"Will update {file.name}\n")
|
||||||
|
if changed and not dry_run:
|
||||||
|
with file.open("w") as f:
|
||||||
|
json.dump(fixture_data, f, sort_keys=True, indent=4)
|
||||||
|
f.write("\n")
|
||||||
|
|
||||||
|
|
||||||
|
def _discovery_result_update(info) -> bool:
|
||||||
|
"""Update discovery_result to be the raw result and error_code."""
|
||||||
|
if (disco_result := info.get("discovery_result")) and "result" not in disco_result:
|
||||||
|
info["discovery_result"] = {
|
||||||
|
"result": disco_result,
|
||||||
|
"error_code": 0,
|
||||||
|
}
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _child_device_id_update(info) -> bool:
|
||||||
|
"""Update child device ids to be the scrubbed ids from dump_devinfo."""
|
||||||
|
changed = False
|
||||||
|
if get_child_device_list := info.get("get_child_device_list"):
|
||||||
|
child_device_list = get_child_device_list["child_device_list"]
|
||||||
|
child_component_list = info["get_child_device_component_list"][
|
||||||
|
"child_component_list"
|
||||||
|
]
|
||||||
|
for index, child_device in enumerate(child_device_list):
|
||||||
|
child_component = child_component_list[index]
|
||||||
|
if "SCRUBBED" not in child_device["device_id"]:
|
||||||
|
dev_id = f"SCRUBBED_CHILD_DEVICE_ID_{index + 1}"
|
||||||
|
click.echo(
|
||||||
|
f"child_device_id{index}: {child_device['device_id']} -> {dev_id}"
|
||||||
|
)
|
||||||
|
child_device["device_id"] = dev_id
|
||||||
|
child_component["device_id"] = dev_id
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
if children := info.get("system", {}).get("get_sysinfo", {}).get("children"):
|
||||||
|
for index, child_device in enumerate(children):
|
||||||
|
if "SCRUBBED" not in child_device["id"]:
|
||||||
|
dev_id = f"SCRUBBED_CHILD_DEVICE_ID_{index + 1}"
|
||||||
|
click.echo(f"child_device_id{index}: {child_device['id']} -> {dev_id}")
|
||||||
|
child_device["id"] = dev_id
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
return changed
|
||||||
|
|
||||||
|
|
||||||
|
def _diff_data(fullkey, data1, data2, diffs):
|
||||||
|
if isinstance(data1, dict):
|
||||||
|
for k, v in data1.items():
|
||||||
|
_diff_data(fullkey + "/" + k, v, data2[k], diffs)
|
||||||
|
elif isinstance(data1, list):
|
||||||
|
for index, item in enumerate(data1):
|
||||||
|
_diff_data(fullkey + "/" + str(index), item, data2[index], diffs)
|
||||||
|
elif data1 != data2:
|
||||||
|
diffs[fullkey] = (data1, data2)
|
||||||
|
|
||||||
|
|
||||||
|
def _redactor_result_update(info) -> bool:
|
||||||
|
"""Update fixtures with the output using the common redactors."""
|
||||||
|
changed = False
|
||||||
|
|
||||||
|
redactors = IOT_REDACTORS if "system" in info else SMART_REDACTORS
|
||||||
|
|
||||||
|
for key, val in info.items():
|
||||||
|
if not isinstance(val, dict):
|
||||||
|
continue
|
||||||
|
if key == "discovery_result":
|
||||||
|
info[key] = redact_data(val, _wrap_redactors(NEW_DISCOVERY_REDACTORS))
|
||||||
|
else:
|
||||||
|
info[key] = redact_data(val, _wrap_redactors(redactors))
|
||||||
|
diffs: dict[str, tuple[str, str]] = {}
|
||||||
|
_diff_data(key, val, info[key], diffs)
|
||||||
|
if diffs:
|
||||||
|
for k, v in diffs.items():
|
||||||
|
click.echo(f"{k}: {v[0]} -> {v[1]}")
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
return changed
|
||||||
|
|
||||||
|
|
||||||
|
@click.option(
|
||||||
|
"--dry-run/--no-dry-run",
|
||||||
|
default=False,
|
||||||
|
is_flag=True,
|
||||||
|
type=bool,
|
||||||
|
help="Perform a dry run without saving.",
|
||||||
|
)
|
||||||
|
@click.command()
|
||||||
|
async def cli(dry_run: bool) -> None:
|
||||||
|
"""Cli method fo rupdating fixtures."""
|
||||||
|
update_fixtures(_discovery_result_update, dry_run=dry_run)
|
||||||
|
update_fixtures(_child_device_id_update, dry_run=dry_run)
|
||||||
|
update_fixtures(_redactor_result_update, dry_run=dry_run)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
cli()
|
@ -91,5 +91,5 @@ False
|
|||||||
True
|
True
|
||||||
>>> for feat in dev.features.values():
|
>>> for feat in dev.features.values():
|
||||||
>>> print(f"{feat.name}: {feat.value}")
|
>>> print(f"{feat.name}: {feat.value}")
|
||||||
Device ID: 0000000000000000000000000000000000000000\nState: True\nSignal Level: 2\nRSSI: -52\nSSID: #MASKED_SSID#\nOverheated: False\nReboot: <Action>\nBrightness: 50\nCloud connection: True\nHSV: HSV(hue=0, saturation=100, value=50)\nColor temperature: 2700\nAuto update enabled: True\nUpdate available: None\nCurrent firmware version: 1.1.6 Build 240130 Rel.173828\nAvailable firmware version: None\nCheck latest firmware: <Action>\nLight effect: Party\nLight preset: Light preset 1\nSmooth transition on: 2\nSmooth transition off: 2\nDevice time: 2024-02-23 02:40:15+01:00
|
Device ID: 0000000000000000000000000000000000000000\nState: True\nSignal Level: 2\nRSSI: -52\nSSID: #MASKED_SSID#\nReboot: <Action>\nBrightness: 50\nCloud connection: True\nHSV: HSV(hue=0, saturation=100, value=50)\nColor temperature: 2700\nAuto update enabled: True\nUpdate available: None\nCurrent firmware version: 1.1.6 Build 240130 Rel.173828\nAvailable firmware version: None\nCheck latest firmware: <Action>\nLight effect: Party\nLight preset: Light preset 1\nSmooth transition on: 2\nSmooth transition off: 2\nOverheated: False\nDevice time: 2024-02-23 02:40:15+01:00
|
||||||
"""
|
"""
|
||||||
|
@ -14,9 +14,17 @@ from kasa import (
|
|||||||
Discover,
|
Discover,
|
||||||
UnsupportedDeviceError,
|
UnsupportedDeviceError,
|
||||||
)
|
)
|
||||||
from kasa.discover import ConnectAttempt, DiscoveryResult
|
from kasa.discover import (
|
||||||
|
NEW_DISCOVERY_REDACTORS,
|
||||||
|
ConnectAttempt,
|
||||||
|
DiscoveredRaw,
|
||||||
|
DiscoveryResult,
|
||||||
|
)
|
||||||
from kasa.iot.iotdevice import _extract_sys_info
|
from kasa.iot.iotdevice import _extract_sys_info
|
||||||
|
from kasa.protocols.iotprotocol import REDACTORS as IOT_REDACTORS
|
||||||
|
from kasa.protocols.protocol import redact_data
|
||||||
|
|
||||||
|
from ..json import dumps as json_dumps
|
||||||
from .common import echo, error
|
from .common import echo, error
|
||||||
|
|
||||||
|
|
||||||
@ -64,7 +72,9 @@ async def detail(ctx):
|
|||||||
await ctx.parent.invoke(state)
|
await ctx.parent.invoke(state)
|
||||||
echo()
|
echo()
|
||||||
|
|
||||||
discovered = await _discover(ctx, print_discovered, print_unsupported)
|
discovered = await _discover(
|
||||||
|
ctx, print_discovered=print_discovered, print_unsupported=print_unsupported
|
||||||
|
)
|
||||||
if ctx.parent.parent.params["host"]:
|
if ctx.parent.parent.params["host"]:
|
||||||
return discovered
|
return discovered
|
||||||
|
|
||||||
@ -77,6 +87,33 @@ async def detail(ctx):
|
|||||||
return discovered
|
return discovered
|
||||||
|
|
||||||
|
|
||||||
|
@discover.command()
|
||||||
|
@click.option(
|
||||||
|
"--redact/--no-redact",
|
||||||
|
default=False,
|
||||||
|
is_flag=True,
|
||||||
|
type=bool,
|
||||||
|
help="Set flag to redact sensitive data from raw output.",
|
||||||
|
)
|
||||||
|
@click.pass_context
|
||||||
|
async def raw(ctx, redact: bool):
|
||||||
|
"""Return raw discovery data returned from devices."""
|
||||||
|
|
||||||
|
def print_raw(discovered: DiscoveredRaw):
|
||||||
|
if redact:
|
||||||
|
redactors = (
|
||||||
|
NEW_DISCOVERY_REDACTORS
|
||||||
|
if discovered["meta"]["port"] == Discover.DISCOVERY_PORT_2
|
||||||
|
else IOT_REDACTORS
|
||||||
|
)
|
||||||
|
discovered["discovery_response"] = redact_data(
|
||||||
|
discovered["discovery_response"], redactors
|
||||||
|
)
|
||||||
|
echo(json_dumps(discovered, indent=True))
|
||||||
|
|
||||||
|
return await _discover(ctx, print_raw=print_raw, do_echo=False)
|
||||||
|
|
||||||
|
|
||||||
@discover.command()
|
@discover.command()
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
async def list(ctx):
|
async def list(ctx):
|
||||||
@ -102,10 +139,17 @@ async def list(ctx):
|
|||||||
echo(f"{host:<15} UNSUPPORTED DEVICE")
|
echo(f"{host:<15} UNSUPPORTED DEVICE")
|
||||||
|
|
||||||
echo(f"{'HOST':<15} {'DEVICE FAMILY':<20} {'ENCRYPT':<7} {'ALIAS'}")
|
echo(f"{'HOST':<15} {'DEVICE FAMILY':<20} {'ENCRYPT':<7} {'ALIAS'}")
|
||||||
return await _discover(ctx, print_discovered, print_unsupported, do_echo=False)
|
return await _discover(
|
||||||
|
ctx,
|
||||||
|
print_discovered=print_discovered,
|
||||||
|
print_unsupported=print_unsupported,
|
||||||
|
do_echo=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def _discover(ctx, print_discovered, print_unsupported, *, do_echo=True):
|
async def _discover(
|
||||||
|
ctx, *, print_discovered=None, print_unsupported=None, print_raw=None, do_echo=True
|
||||||
|
):
|
||||||
params = ctx.parent.parent.params
|
params = ctx.parent.parent.params
|
||||||
target = params["target"]
|
target = params["target"]
|
||||||
username = params["username"]
|
username = params["username"]
|
||||||
@ -126,6 +170,7 @@ async def _discover(ctx, print_discovered, print_unsupported, *, do_echo=True):
|
|||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
discovery_timeout=discovery_timeout,
|
discovery_timeout=discovery_timeout,
|
||||||
on_unsupported=print_unsupported,
|
on_unsupported=print_unsupported,
|
||||||
|
on_discovered_raw=print_raw,
|
||||||
)
|
)
|
||||||
if do_echo:
|
if do_echo:
|
||||||
echo(f"Discovering devices on {target} for {discovery_timeout} seconds")
|
echo(f"Discovering devices on {target} for {discovery_timeout} seconds")
|
||||||
@ -137,6 +182,7 @@ async def _discover(ctx, print_discovered, print_unsupported, *, do_echo=True):
|
|||||||
port=port,
|
port=port,
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
credentials=credentials,
|
credentials=credentials,
|
||||||
|
on_discovered_raw=print_raw,
|
||||||
)
|
)
|
||||||
|
|
||||||
for device in discovered_devices.values():
|
for device in discovered_devices.values():
|
||||||
|
102
kasa/discover.py
102
kasa/discover.py
@ -99,6 +99,7 @@ from typing import (
|
|||||||
Annotated,
|
Annotated,
|
||||||
Any,
|
Any,
|
||||||
NamedTuple,
|
NamedTuple,
|
||||||
|
TypedDict,
|
||||||
cast,
|
cast,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -147,18 +148,43 @@ class ConnectAttempt(NamedTuple):
|
|||||||
device: type
|
device: type
|
||||||
|
|
||||||
|
|
||||||
|
class DiscoveredMeta(TypedDict):
|
||||||
|
"""Meta info about discovery response."""
|
||||||
|
|
||||||
|
ip: str
|
||||||
|
port: int
|
||||||
|
|
||||||
|
|
||||||
|
class DiscoveredRaw(TypedDict):
|
||||||
|
"""Try to connect attempt."""
|
||||||
|
|
||||||
|
meta: DiscoveredMeta
|
||||||
|
discovery_response: dict
|
||||||
|
|
||||||
|
|
||||||
OnDiscoveredCallable = Callable[[Device], Coroutine]
|
OnDiscoveredCallable = Callable[[Device], Coroutine]
|
||||||
|
OnDiscoveredRawCallable = Callable[[DiscoveredRaw], None]
|
||||||
OnUnsupportedCallable = Callable[[UnsupportedDeviceError], Coroutine]
|
OnUnsupportedCallable = Callable[[UnsupportedDeviceError], Coroutine]
|
||||||
OnConnectAttemptCallable = Callable[[ConnectAttempt, bool], None]
|
OnConnectAttemptCallable = Callable[[ConnectAttempt, bool], None]
|
||||||
DeviceDict = dict[str, Device]
|
DeviceDict = dict[str, Device]
|
||||||
|
|
||||||
|
DECRYPTED_REDACTORS: dict[str, Callable[[Any], Any] | None] = {
|
||||||
|
"connect_ssid": lambda x: "#MASKED_SSID#" if x else "",
|
||||||
|
"device_id": lambda x: "REDACTED_" + x[9::],
|
||||||
|
"owner": lambda x: "REDACTED_" + x[9::],
|
||||||
|
}
|
||||||
|
|
||||||
NEW_DISCOVERY_REDACTORS: dict[str, Callable[[Any], Any] | None] = {
|
NEW_DISCOVERY_REDACTORS: dict[str, Callable[[Any], Any] | None] = {
|
||||||
"device_id": lambda x: "REDACTED_" + x[9::],
|
"device_id": lambda x: "REDACTED_" + x[9::],
|
||||||
|
"device_name": lambda x: "#MASKED_NAME#" if x else "",
|
||||||
"owner": lambda x: "REDACTED_" + x[9::],
|
"owner": lambda x: "REDACTED_" + x[9::],
|
||||||
"mac": mask_mac,
|
"mac": mask_mac,
|
||||||
"master_device_id": lambda x: "REDACTED_" + x[9::],
|
"master_device_id": lambda x: "REDACTED_" + x[9::],
|
||||||
"group_id": lambda x: "REDACTED_" + x[9::],
|
"group_id": lambda x: "REDACTED_" + x[9::],
|
||||||
"group_name": lambda x: "I01BU0tFRF9TU0lEIw==",
|
"group_name": lambda x: "I01BU0tFRF9TU0lEIw==",
|
||||||
|
"encrypt_info": lambda x: {**x, "key": "", "data": ""},
|
||||||
|
"ip": lambda x: x, # don't redact but keep listed here for dump_devinfo
|
||||||
|
"decrypted_data": lambda x: redact_data(x, DECRYPTED_REDACTORS),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -216,6 +242,7 @@ class _DiscoverProtocol(asyncio.DatagramProtocol):
|
|||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
on_discovered: OnDiscoveredCallable | None = None,
|
on_discovered: OnDiscoveredCallable | None = None,
|
||||||
|
on_discovered_raw: OnDiscoveredRawCallable | None = None,
|
||||||
target: str = "255.255.255.255",
|
target: str = "255.255.255.255",
|
||||||
discovery_packets: int = 3,
|
discovery_packets: int = 3,
|
||||||
discovery_timeout: int = 5,
|
discovery_timeout: int = 5,
|
||||||
@ -240,6 +267,7 @@ class _DiscoverProtocol(asyncio.DatagramProtocol):
|
|||||||
self.unsupported_device_exceptions: dict = {}
|
self.unsupported_device_exceptions: dict = {}
|
||||||
self.invalid_device_exceptions: dict = {}
|
self.invalid_device_exceptions: dict = {}
|
||||||
self.on_unsupported = on_unsupported
|
self.on_unsupported = on_unsupported
|
||||||
|
self.on_discovered_raw = on_discovered_raw
|
||||||
self.credentials = credentials
|
self.credentials = credentials
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
self.discovery_timeout = discovery_timeout
|
self.discovery_timeout = discovery_timeout
|
||||||
@ -329,12 +357,23 @@ class _DiscoverProtocol(asyncio.DatagramProtocol):
|
|||||||
config.timeout = self.timeout
|
config.timeout = self.timeout
|
||||||
try:
|
try:
|
||||||
if port == self.discovery_port:
|
if port == self.discovery_port:
|
||||||
device = Discover._get_device_instance_legacy(data, config)
|
json_func = Discover._get_discovery_json_legacy
|
||||||
|
device_func = Discover._get_device_instance_legacy
|
||||||
elif port == Discover.DISCOVERY_PORT_2:
|
elif port == Discover.DISCOVERY_PORT_2:
|
||||||
config.uses_http = True
|
config.uses_http = True
|
||||||
device = Discover._get_device_instance(data, config)
|
json_func = Discover._get_discovery_json
|
||||||
|
device_func = Discover._get_device_instance
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
info = json_func(data, ip)
|
||||||
|
if self.on_discovered_raw is not None:
|
||||||
|
self.on_discovered_raw(
|
||||||
|
{
|
||||||
|
"discovery_response": info,
|
||||||
|
"meta": {"ip": ip, "port": port},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
device = device_func(info, config)
|
||||||
except UnsupportedDeviceError as udex:
|
except UnsupportedDeviceError as udex:
|
||||||
_LOGGER.debug("Unsupported device found at %s << %s", ip, udex)
|
_LOGGER.debug("Unsupported device found at %s << %s", ip, udex)
|
||||||
self.unsupported_device_exceptions[ip] = udex
|
self.unsupported_device_exceptions[ip] = udex
|
||||||
@ -391,6 +430,7 @@ class Discover:
|
|||||||
*,
|
*,
|
||||||
target: str = "255.255.255.255",
|
target: str = "255.255.255.255",
|
||||||
on_discovered: OnDiscoveredCallable | None = None,
|
on_discovered: OnDiscoveredCallable | None = None,
|
||||||
|
on_discovered_raw: OnDiscoveredRawCallable | None = None,
|
||||||
discovery_timeout: int = 5,
|
discovery_timeout: int = 5,
|
||||||
discovery_packets: int = 3,
|
discovery_packets: int = 3,
|
||||||
interface: str | None = None,
|
interface: str | None = None,
|
||||||
@ -421,6 +461,8 @@ class Discover:
|
|||||||
:param target: The target address where to send the broadcast discovery
|
:param target: The target address where to send the broadcast discovery
|
||||||
queries if multi-homing (e.g. 192.168.xxx.255).
|
queries if multi-homing (e.g. 192.168.xxx.255).
|
||||||
:param on_discovered: coroutine to execute on discovery
|
:param on_discovered: coroutine to execute on discovery
|
||||||
|
:param on_discovered_raw: Optional callback once discovered json is loaded
|
||||||
|
before any attempt to deserialize it and create devices
|
||||||
:param discovery_timeout: Seconds to wait for responses, defaults to 5
|
:param discovery_timeout: Seconds to wait for responses, defaults to 5
|
||||||
:param discovery_packets: Number of discovery packets to broadcast
|
:param discovery_packets: Number of discovery packets to broadcast
|
||||||
:param interface: Bind to specific interface
|
:param interface: Bind to specific interface
|
||||||
@ -443,6 +485,7 @@ class Discover:
|
|||||||
discovery_packets=discovery_packets,
|
discovery_packets=discovery_packets,
|
||||||
interface=interface,
|
interface=interface,
|
||||||
on_unsupported=on_unsupported,
|
on_unsupported=on_unsupported,
|
||||||
|
on_discovered_raw=on_discovered_raw,
|
||||||
credentials=credentials,
|
credentials=credentials,
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
discovery_timeout=discovery_timeout,
|
discovery_timeout=discovery_timeout,
|
||||||
@ -476,6 +519,7 @@ class Discover:
|
|||||||
credentials: Credentials | None = None,
|
credentials: Credentials | None = None,
|
||||||
username: str | None = None,
|
username: str | None = None,
|
||||||
password: str | None = None,
|
password: str | None = None,
|
||||||
|
on_discovered_raw: OnDiscoveredRawCallable | None = None,
|
||||||
on_unsupported: OnUnsupportedCallable | None = None,
|
on_unsupported: OnUnsupportedCallable | None = None,
|
||||||
) -> Device | None:
|
) -> Device | None:
|
||||||
"""Discover a single device by the given IP address.
|
"""Discover a single device by the given IP address.
|
||||||
@ -493,6 +537,9 @@ class Discover:
|
|||||||
username and password are ignored if provided.
|
username and password are ignored if provided.
|
||||||
:param username: Username for devices that require authentication
|
:param username: Username for devices that require authentication
|
||||||
:param password: Password for devices that require authentication
|
:param password: Password for devices that require authentication
|
||||||
|
:param on_discovered_raw: Optional callback once discovered json is loaded
|
||||||
|
before any attempt to deserialize it and create devices
|
||||||
|
:param on_unsupported: Optional callback when unsupported devices are discovered
|
||||||
:rtype: SmartDevice
|
:rtype: SmartDevice
|
||||||
:return: Object for querying/controlling found device.
|
:return: Object for querying/controlling found device.
|
||||||
"""
|
"""
|
||||||
@ -529,6 +576,7 @@ class Discover:
|
|||||||
credentials=credentials,
|
credentials=credentials,
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
discovery_timeout=discovery_timeout,
|
discovery_timeout=discovery_timeout,
|
||||||
|
on_discovered_raw=on_discovered_raw,
|
||||||
),
|
),
|
||||||
local_addr=("0.0.0.0", 0), # noqa: S104
|
local_addr=("0.0.0.0", 0), # noqa: S104
|
||||||
)
|
)
|
||||||
@ -666,15 +714,19 @@ class Discover:
|
|||||||
return get_device_class_from_sys_info(info)
|
return get_device_class_from_sys_info(info)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_device_instance_legacy(data: bytes, config: DeviceConfig) -> IotDevice:
|
def _get_discovery_json_legacy(data: bytes, ip: str) -> dict:
|
||||||
"""Get SmartDevice from legacy 9999 response."""
|
"""Get discovery json from legacy 9999 response."""
|
||||||
try:
|
try:
|
||||||
info = json_loads(XorEncryption.decrypt(data))
|
info = json_loads(XorEncryption.decrypt(data))
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
raise KasaException(
|
raise KasaException(
|
||||||
f"Unable to read response from device: {config.host}: {ex}"
|
f"Unable to read response from device: {ip}: {ex}"
|
||||||
) from ex
|
) from ex
|
||||||
|
return info
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_device_instance_legacy(info: dict, config: DeviceConfig) -> Device:
|
||||||
|
"""Get IotDevice from legacy 9999 response."""
|
||||||
if _LOGGER.isEnabledFor(logging.DEBUG):
|
if _LOGGER.isEnabledFor(logging.DEBUG):
|
||||||
data = redact_data(info, IOT_REDACTORS) if Discover._redact_data else info
|
data = redact_data(info, IOT_REDACTORS) if Discover._redact_data else info
|
||||||
_LOGGER.debug("[DISCOVERY] %s << %s", config.host, pf(data))
|
_LOGGER.debug("[DISCOVERY] %s << %s", config.host, pf(data))
|
||||||
@ -698,6 +750,7 @@ class Discover:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _decrypt_discovery_data(discovery_result: DiscoveryResult) -> None:
|
def _decrypt_discovery_data(discovery_result: DiscoveryResult) -> None:
|
||||||
|
debug_enabled = _LOGGER.isEnabledFor(logging.DEBUG)
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
assert discovery_result.encrypt_info
|
assert discovery_result.encrypt_info
|
||||||
assert _AesDiscoveryQuery.keypair
|
assert _AesDiscoveryQuery.keypair
|
||||||
@ -713,22 +766,39 @@ class Discover:
|
|||||||
session = AesEncyptionSession(key, iv)
|
session = AesEncyptionSession(key, iv)
|
||||||
decrypted_data = session.decrypt(encrypted_data)
|
decrypted_data = session.decrypt(encrypted_data)
|
||||||
|
|
||||||
discovery_result.decrypted_data = json_loads(decrypted_data)
|
result = json_loads(decrypted_data)
|
||||||
|
if debug_enabled:
|
||||||
|
data = (
|
||||||
|
redact_data(result, DECRYPTED_REDACTORS)
|
||||||
|
if Discover._redact_data
|
||||||
|
else result
|
||||||
|
)
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Decrypted encrypt_info for %s: %s",
|
||||||
|
discovery_result.ip,
|
||||||
|
pf(data),
|
||||||
|
)
|
||||||
|
discovery_result.decrypted_data = result
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_discovery_json(data: bytes, ip: str) -> dict:
|
||||||
|
"""Get discovery json from the new 20002 response."""
|
||||||
|
try:
|
||||||
|
info = json_loads(data[16:])
|
||||||
|
except Exception as ex:
|
||||||
|
_LOGGER.debug("Got invalid response from device %s: %s", ip, data)
|
||||||
|
raise KasaException(
|
||||||
|
f"Unable to read response from device: {ip}: {ex}"
|
||||||
|
) from ex
|
||||||
|
return info
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_device_instance(
|
def _get_device_instance(
|
||||||
data: bytes,
|
info: dict,
|
||||||
config: DeviceConfig,
|
config: DeviceConfig,
|
||||||
) -> Device:
|
) -> Device:
|
||||||
"""Get SmartDevice from the new 20002 response."""
|
"""Get SmartDevice from the new 20002 response."""
|
||||||
debug_enabled = _LOGGER.isEnabledFor(logging.DEBUG)
|
debug_enabled = _LOGGER.isEnabledFor(logging.DEBUG)
|
||||||
try:
|
|
||||||
info = json_loads(data[16:])
|
|
||||||
except Exception as ex:
|
|
||||||
_LOGGER.debug("Got invalid response from device %s: %s", config.host, data)
|
|
||||||
raise KasaException(
|
|
||||||
f"Unable to read response from device: {config.host}: {ex}"
|
|
||||||
) from ex
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
discovery_result = DiscoveryResult.from_dict(info["result"])
|
discovery_result = DiscoveryResult.from_dict(info["result"])
|
||||||
@ -757,7 +827,9 @@ class Discover:
|
|||||||
Discover._decrypt_discovery_data(discovery_result)
|
Discover._decrypt_discovery_data(discovery_result)
|
||||||
except Exception:
|
except Exception:
|
||||||
_LOGGER.exception(
|
_LOGGER.exception(
|
||||||
"Unable to decrypt discovery data %s: %s", config.host, data
|
"Unable to decrypt discovery data %s: %s",
|
||||||
|
config.host,
|
||||||
|
redact_data(info, NEW_DISCOVERY_REDACTORS),
|
||||||
)
|
)
|
||||||
|
|
||||||
type_ = discovery_result.device_type
|
type_ = discovery_result.device_type
|
||||||
|
@ -24,7 +24,6 @@ State (state): True
|
|||||||
Signal Level (signal_level): 2
|
Signal Level (signal_level): 2
|
||||||
RSSI (rssi): -52
|
RSSI (rssi): -52
|
||||||
SSID (ssid): #MASKED_SSID#
|
SSID (ssid): #MASKED_SSID#
|
||||||
Overheated (overheated): False
|
|
||||||
Reboot (reboot): <Action>
|
Reboot (reboot): <Action>
|
||||||
Brightness (brightness): 100
|
Brightness (brightness): 100
|
||||||
Cloud connection (cloud_connection): True
|
Cloud connection (cloud_connection): True
|
||||||
@ -39,6 +38,7 @@ Light effect (light_effect): Off
|
|||||||
Light preset (light_preset): Not set
|
Light preset (light_preset): Not set
|
||||||
Smooth transition on (smooth_transition_on): 2
|
Smooth transition on (smooth_transition_on): 2
|
||||||
Smooth transition off (smooth_transition_off): 2
|
Smooth transition off (smooth_transition_off): 2
|
||||||
|
Overheated (overheated): False
|
||||||
Device time (device_time): 2024-02-23 02:40:15+01:00
|
Device time (device_time): 2024-02-23 02:40:15+01:00
|
||||||
|
|
||||||
To see whether a device supports a feature, check for the existence of it:
|
To see whether a device supports a feature, check for the existence of it:
|
||||||
|
14
kasa/json.py
14
kasa/json.py
@ -8,18 +8,24 @@ from typing import Any
|
|||||||
try:
|
try:
|
||||||
import orjson
|
import orjson
|
||||||
|
|
||||||
def dumps(obj: Any, *, default: Callable | None = None) -> str:
|
def dumps(
|
||||||
|
obj: Any, *, default: Callable | None = None, indent: bool = False
|
||||||
|
) -> str:
|
||||||
"""Dump JSON."""
|
"""Dump JSON."""
|
||||||
return orjson.dumps(obj).decode()
|
return orjson.dumps(
|
||||||
|
obj, option=orjson.OPT_INDENT_2 if indent else None
|
||||||
|
).decode()
|
||||||
|
|
||||||
loads = orjson.loads
|
loads = orjson.loads
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import json
|
import json
|
||||||
|
|
||||||
def dumps(obj: Any, *, default: Callable | None = None) -> str:
|
def dumps(
|
||||||
|
obj: Any, *, default: Callable | None = None, indent: bool = False
|
||||||
|
) -> str:
|
||||||
"""Dump JSON."""
|
"""Dump JSON."""
|
||||||
# Separators specified for consistency with orjson
|
# Separators specified for consistency with orjson
|
||||||
return json.dumps(obj, separators=(",", ":"))
|
return json.dumps(obj, separators=(",", ":"), indent=2 if indent else None)
|
||||||
|
|
||||||
loads = json.loads
|
loads = json.loads
|
||||||
|
|
||||||
|
@ -25,19 +25,35 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def _mask_children(children: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||||
|
def mask_child(child: dict[str, Any], index: int) -> dict[str, Any]:
|
||||||
|
result = {
|
||||||
|
**child,
|
||||||
|
"id": f"SCRUBBED_CHILD_DEVICE_ID_{index+1}",
|
||||||
|
}
|
||||||
|
# Will leave empty aliases as blank
|
||||||
|
if child.get("alias"):
|
||||||
|
result["alias"] = f"#MASKED_NAME# {index + 1}"
|
||||||
|
return result
|
||||||
|
|
||||||
|
return [mask_child(child, index) for index, child in enumerate(children)]
|
||||||
|
|
||||||
|
|
||||||
REDACTORS: dict[str, Callable[[Any], Any] | None] = {
|
REDACTORS: dict[str, Callable[[Any], Any] | None] = {
|
||||||
"latitude": lambda x: 0,
|
"latitude": lambda x: 0,
|
||||||
"longitude": lambda x: 0,
|
"longitude": lambda x: 0,
|
||||||
"latitude_i": lambda x: 0,
|
"latitude_i": lambda x: 0,
|
||||||
"longitude_i": lambda x: 0,
|
"longitude_i": lambda x: 0,
|
||||||
"deviceId": lambda x: "REDACTED_" + x[9::],
|
"deviceId": lambda x: "REDACTED_" + x[9::],
|
||||||
"id": lambda x: "REDACTED_" + x[9::],
|
"children": _mask_children,
|
||||||
"alias": lambda x: "#MASKED_NAME#" if x else "",
|
"alias": lambda x: "#MASKED_NAME#" if x else "",
|
||||||
"mac": mask_mac,
|
"mac": mask_mac,
|
||||||
"mic_mac": mask_mac,
|
"mic_mac": mask_mac,
|
||||||
"ssid": lambda x: "#MASKED_SSID#" if x else "",
|
"ssid": lambda x: "#MASKED_SSID#" if x else "",
|
||||||
"oemId": lambda x: "REDACTED_" + x[9::],
|
"oemId": lambda x: "REDACTED_" + x[9::],
|
||||||
"username": lambda _: "user@example.com", # cnCloud
|
"username": lambda _: "user@example.com", # cnCloud
|
||||||
|
"hwId": lambda x: "REDACTED_" + x[9::],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,6 +66,8 @@ def redact_data(data: _T, redactors: dict[str, Callable[[Any], Any] | None]) ->
|
|||||||
|
|
||||||
def mask_mac(mac: str) -> str:
|
def mask_mac(mac: str) -> str:
|
||||||
"""Return mac address with last two octects blanked."""
|
"""Return mac address with last two octects blanked."""
|
||||||
|
if len(mac) == 12:
|
||||||
|
return f"{mac[:6]}000000"
|
||||||
delim = ":" if ":" in mac else "-"
|
delim = ":" if ":" in mac else "-"
|
||||||
rest = delim.join(format(s, "02x") for s in bytes.fromhex("000000"))
|
rest = delim.join(format(s, "02x") for s in bytes.fromhex("000000"))
|
||||||
return f"{mac[:8]}{delim}{rest}"
|
return f"{mac[:8]}{delim}{rest}"
|
||||||
|
@ -9,6 +9,7 @@ from __future__ import annotations
|
|||||||
import asyncio
|
import asyncio
|
||||||
import base64
|
import base64
|
||||||
import logging
|
import logging
|
||||||
|
import re
|
||||||
import time
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
@ -45,15 +46,27 @@ REDACTORS: dict[str, Callable[[Any], Any] | None] = {
|
|||||||
"original_device_id": lambda x: "REDACTED_" + x[9::], # Strip children
|
"original_device_id": lambda x: "REDACTED_" + x[9::], # Strip children
|
||||||
"nickname": lambda x: "I01BU0tFRF9OQU1FIw==" if x else "",
|
"nickname": lambda x: "I01BU0tFRF9OQU1FIw==" if x else "",
|
||||||
"mac": mask_mac,
|
"mac": mask_mac,
|
||||||
"ssid": lambda x: "I01BU0tFRF9TU0lEIw=" if x else "",
|
"ssid": lambda x: "I01BU0tFRF9TU0lEIw==" if x else "",
|
||||||
"bssid": lambda _: "000000000000",
|
"bssid": lambda _: "000000000000",
|
||||||
|
"channel": lambda _: 0,
|
||||||
"oem_id": lambda x: "REDACTED_" + x[9::],
|
"oem_id": lambda x: "REDACTED_" + x[9::],
|
||||||
"setup_code": None, # matter
|
"setup_code": lambda x: re.sub(r"\w", "0", x), # matter
|
||||||
"setup_payload": None, # matter
|
"setup_payload": lambda x: re.sub(r"\w", "0", x), # matter
|
||||||
"mfi_setup_code": None, # mfi_ for homekit
|
"mfi_setup_code": lambda x: re.sub(r"\w", "0", x), # mfi_ for homekit
|
||||||
"mfi_setup_id": None,
|
"mfi_setup_id": lambda x: re.sub(r"\w", "0", x),
|
||||||
"mfi_token_token": None,
|
"mfi_token_token": lambda x: re.sub(r"\w", "0", x),
|
||||||
"mfi_token_uuid": None,
|
"mfi_token_uuid": lambda x: re.sub(r"\w", "0", x),
|
||||||
|
"ip": lambda x: x, # don't redact but keep listed here for dump_devinfo
|
||||||
|
# smartcam
|
||||||
|
"dev_id": lambda x: "REDACTED_" + x[9::],
|
||||||
|
"device_name": lambda x: "#MASKED_NAME#" if x else "",
|
||||||
|
"device_alias": lambda x: "#MASKED_NAME#" if x else "",
|
||||||
|
"local_ip": lambda x: x, # don't redact but keep listed here for dump_devinfo
|
||||||
|
# robovac
|
||||||
|
"board_sn": lambda _: "000000000000",
|
||||||
|
"custom_sn": lambda _: "000000000000",
|
||||||
|
"location": lambda x: "#MASKED_NAME#" if x else "",
|
||||||
|
"map_data": lambda x: "#SCRUBBED_MAPDATA#" if x else "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ from .lightpreset import LightPreset
|
|||||||
from .lightstripeffect import LightStripEffect
|
from .lightstripeffect import LightStripEffect
|
||||||
from .lighttransition import LightTransition
|
from .lighttransition import LightTransition
|
||||||
from .motionsensor import MotionSensor
|
from .motionsensor import MotionSensor
|
||||||
|
from .overheatprotection import OverheatProtection
|
||||||
from .reportmode import ReportMode
|
from .reportmode import ReportMode
|
||||||
from .temperaturecontrol import TemperatureControl
|
from .temperaturecontrol import TemperatureControl
|
||||||
from .temperaturesensor import TemperatureSensor
|
from .temperaturesensor import TemperatureSensor
|
||||||
@ -64,4 +65,5 @@ __all__ = [
|
|||||||
"FrostProtection",
|
"FrostProtection",
|
||||||
"Thermostat",
|
"Thermostat",
|
||||||
"SmartLightEffect",
|
"SmartLightEffect",
|
||||||
|
"OverheatProtection",
|
||||||
]
|
]
|
||||||
|
@ -10,7 +10,7 @@ class ContactSensor(SmartModule):
|
|||||||
"""Implementation of contact sensor module."""
|
"""Implementation of contact sensor module."""
|
||||||
|
|
||||||
REQUIRED_COMPONENT = None # we depend on availability of key
|
REQUIRED_COMPONENT = None # we depend on availability of key
|
||||||
REQUIRED_KEY_ON_PARENT = "open"
|
SYSINFO_LOOKUP_KEYS = ["open"]
|
||||||
|
|
||||||
def _initialize_features(self) -> None:
|
def _initialize_features(self) -> None:
|
||||||
"""Initialize features after the initial update."""
|
"""Initialize features after the initial update."""
|
||||||
|
41
kasa/smart/modules/overheatprotection.py
Normal file
41
kasa/smart/modules/overheatprotection.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
"""Overheat module."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from ...feature import Feature
|
||||||
|
from ..smartmodule import SmartModule
|
||||||
|
|
||||||
|
|
||||||
|
class OverheatProtection(SmartModule):
|
||||||
|
"""Implementation for overheat_protection."""
|
||||||
|
|
||||||
|
SYSINFO_LOOKUP_KEYS = ["overheated", "overheat_status"]
|
||||||
|
|
||||||
|
def _initialize_features(self) -> None:
|
||||||
|
"""Initialize features after the initial update."""
|
||||||
|
self._add_feature(
|
||||||
|
Feature(
|
||||||
|
self._device,
|
||||||
|
container=self,
|
||||||
|
id="overheated",
|
||||||
|
name="Overheated",
|
||||||
|
attribute_getter="overheated",
|
||||||
|
icon="mdi:heat-wave",
|
||||||
|
type=Feature.Type.BinarySensor,
|
||||||
|
category=Feature.Category.Info,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def overheated(self) -> bool:
|
||||||
|
"""Return True if device reports overheating."""
|
||||||
|
if (value := self._device.sys_info.get("overheat_status")) is not None:
|
||||||
|
# Value can be normal, cooldown, or overheated.
|
||||||
|
# We report all but normal as overheated.
|
||||||
|
return value != "normal"
|
||||||
|
|
||||||
|
return self._device.sys_info["overheated"]
|
||||||
|
|
||||||
|
def query(self) -> dict:
|
||||||
|
"""Query to execute during the update cycle."""
|
||||||
|
return {}
|
@ -9,7 +9,7 @@ from typing import Any
|
|||||||
from ..device_type import DeviceType
|
from ..device_type import DeviceType
|
||||||
from ..deviceconfig import DeviceConfig
|
from ..deviceconfig import DeviceConfig
|
||||||
from ..protocols.smartprotocol import SmartProtocol, _ChildProtocolWrapper
|
from ..protocols.smartprotocol import SmartProtocol, _ChildProtocolWrapper
|
||||||
from .smartdevice import SmartDevice
|
from .smartdevice import ComponentsRaw, SmartDevice
|
||||||
from .smartmodule import SmartModule
|
from .smartmodule import SmartModule
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -37,7 +37,7 @@ class SmartChildDevice(SmartDevice):
|
|||||||
self,
|
self,
|
||||||
parent: SmartDevice,
|
parent: SmartDevice,
|
||||||
info: dict,
|
info: dict,
|
||||||
component_info: dict,
|
component_info_raw: ComponentsRaw,
|
||||||
*,
|
*,
|
||||||
config: DeviceConfig | None = None,
|
config: DeviceConfig | None = None,
|
||||||
protocol: SmartProtocol | None = None,
|
protocol: SmartProtocol | None = None,
|
||||||
@ -47,7 +47,8 @@ class SmartChildDevice(SmartDevice):
|
|||||||
super().__init__(parent.host, config=parent.config, protocol=_protocol)
|
super().__init__(parent.host, config=parent.config, protocol=_protocol)
|
||||||
self._parent = parent
|
self._parent = parent
|
||||||
self._update_internal_state(info)
|
self._update_internal_state(info)
|
||||||
self._components = component_info
|
self._components_raw = component_info_raw
|
||||||
|
self._components = self._parse_components(self._components_raw)
|
||||||
|
|
||||||
async def update(self, update_children: bool = True) -> None:
|
async def update(self, update_children: bool = True) -> None:
|
||||||
"""Update child module info.
|
"""Update child module info.
|
||||||
@ -84,7 +85,7 @@ class SmartChildDevice(SmartDevice):
|
|||||||
cls,
|
cls,
|
||||||
parent: SmartDevice,
|
parent: SmartDevice,
|
||||||
child_info: dict,
|
child_info: dict,
|
||||||
child_components: dict,
|
child_components_raw: ComponentsRaw,
|
||||||
protocol: SmartProtocol | None = None,
|
protocol: SmartProtocol | None = None,
|
||||||
*,
|
*,
|
||||||
last_update: dict | None = None,
|
last_update: dict | None = None,
|
||||||
@ -97,7 +98,7 @@ class SmartChildDevice(SmartDevice):
|
|||||||
derived from the parent.
|
derived from the parent.
|
||||||
"""
|
"""
|
||||||
child: SmartChildDevice = cls(
|
child: SmartChildDevice = cls(
|
||||||
parent, child_info, child_components, protocol=protocol
|
parent, child_info, child_components_raw, protocol=protocol
|
||||||
)
|
)
|
||||||
if last_update:
|
if last_update:
|
||||||
child._last_update = last_update
|
child._last_update = last_update
|
||||||
|
@ -7,7 +7,7 @@ import logging
|
|||||||
import time
|
import time
|
||||||
from collections.abc import Mapping, Sequence
|
from collections.abc import Mapping, Sequence
|
||||||
from datetime import UTC, datetime, timedelta, tzinfo
|
from datetime import UTC, datetime, timedelta, tzinfo
|
||||||
from typing import TYPE_CHECKING, Any, cast
|
from typing import TYPE_CHECKING, Any, TypeAlias, cast
|
||||||
|
|
||||||
from ..device import Device, WifiNetwork, _DeviceInfo
|
from ..device import Device, WifiNetwork, _DeviceInfo
|
||||||
from ..device_type import DeviceType
|
from ..device_type import DeviceType
|
||||||
@ -40,6 +40,8 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
# same issue, homekit perhaps?
|
# same issue, homekit perhaps?
|
||||||
NON_HUB_PARENT_ONLY_MODULES = [DeviceModule, Time, Firmware, Cloud]
|
NON_HUB_PARENT_ONLY_MODULES = [DeviceModule, Time, Firmware, Cloud]
|
||||||
|
|
||||||
|
ComponentsRaw: TypeAlias = dict[str, list[dict[str, int | str]]]
|
||||||
|
|
||||||
|
|
||||||
# Device must go last as the other interfaces also inherit Device
|
# Device must go last as the other interfaces also inherit Device
|
||||||
# and python needs a consistent method resolution order.
|
# and python needs a consistent method resolution order.
|
||||||
@ -61,7 +63,7 @@ class SmartDevice(Device):
|
|||||||
)
|
)
|
||||||
super().__init__(host=host, config=config, protocol=_protocol)
|
super().__init__(host=host, config=config, protocol=_protocol)
|
||||||
self.protocol: SmartProtocol
|
self.protocol: SmartProtocol
|
||||||
self._components_raw: dict[str, Any] | None = None
|
self._components_raw: ComponentsRaw | None = None
|
||||||
self._components: dict[str, int] = {}
|
self._components: dict[str, int] = {}
|
||||||
self._state_information: dict[str, Any] = {}
|
self._state_information: dict[str, Any] = {}
|
||||||
self._modules: dict[str | ModuleName[Module], SmartModule] = {}
|
self._modules: dict[str | ModuleName[Module], SmartModule] = {}
|
||||||
@ -82,10 +84,8 @@ class SmartDevice(Device):
|
|||||||
self.internal_state.update(resp)
|
self.internal_state.update(resp)
|
||||||
|
|
||||||
children = self.internal_state["get_child_device_list"]["child_device_list"]
|
children = self.internal_state["get_child_device_list"]["child_device_list"]
|
||||||
children_components = {
|
children_components_raw = {
|
||||||
child["device_id"]: {
|
child["device_id"]: child
|
||||||
comp["id"]: int(comp["ver_code"]) for comp in child["component_list"]
|
|
||||||
}
|
|
||||||
for child in self.internal_state["get_child_device_component_list"][
|
for child in self.internal_state["get_child_device_component_list"][
|
||||||
"child_component_list"
|
"child_component_list"
|
||||||
]
|
]
|
||||||
@ -96,7 +96,7 @@ class SmartDevice(Device):
|
|||||||
child_info["device_id"]: await SmartChildDevice.create(
|
child_info["device_id"]: await SmartChildDevice.create(
|
||||||
parent=self,
|
parent=self,
|
||||||
child_info=child_info,
|
child_info=child_info,
|
||||||
child_components=children_components[child_info["device_id"]],
|
child_components_raw=children_components_raw[child_info["device_id"]],
|
||||||
)
|
)
|
||||||
for child_info in children
|
for child_info in children
|
||||||
}
|
}
|
||||||
@ -131,6 +131,13 @@ class SmartDevice(Device):
|
|||||||
f"{request} not found in {responses} for device {self.host}"
|
f"{request} not found in {responses} for device {self.host}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _parse_components(components_raw: ComponentsRaw) -> dict[str, int]:
|
||||||
|
return {
|
||||||
|
str(comp["id"]): int(comp["ver_code"])
|
||||||
|
for comp in components_raw["component_list"]
|
||||||
|
}
|
||||||
|
|
||||||
async def _negotiate(self) -> None:
|
async def _negotiate(self) -> None:
|
||||||
"""Perform initialization.
|
"""Perform initialization.
|
||||||
|
|
||||||
@ -151,12 +158,9 @@ class SmartDevice(Device):
|
|||||||
self._info = self._try_get_response(resp, "get_device_info")
|
self._info = self._try_get_response(resp, "get_device_info")
|
||||||
|
|
||||||
# Create our internal presentation of available components
|
# Create our internal presentation of available components
|
||||||
self._components_raw = cast(dict, resp["component_nego"])
|
self._components_raw = cast(ComponentsRaw, resp["component_nego"])
|
||||||
|
|
||||||
self._components = {
|
self._components = self._parse_components(self._components_raw)
|
||||||
comp["id"]: int(comp["ver_code"])
|
|
||||||
for comp in self._components_raw["component_list"]
|
|
||||||
}
|
|
||||||
|
|
||||||
if "child_device" in self._components and not self.children:
|
if "child_device" in self._components and not self.children:
|
||||||
await self._initialize_children()
|
await self._initialize_children()
|
||||||
@ -349,9 +353,8 @@ class SmartDevice(Device):
|
|||||||
) or mod.__name__ in child_modules_to_skip:
|
) or mod.__name__ in child_modules_to_skip:
|
||||||
continue
|
continue
|
||||||
required_component = cast(str, mod.REQUIRED_COMPONENT)
|
required_component = cast(str, mod.REQUIRED_COMPONENT)
|
||||||
if required_component in self._components or (
|
if required_component in self._components or any(
|
||||||
mod.REQUIRED_KEY_ON_PARENT
|
self.sys_info.get(key) is not None for key in mod.SYSINFO_LOOKUP_KEYS
|
||||||
and self.sys_info.get(mod.REQUIRED_KEY_ON_PARENT) is not None
|
|
||||||
):
|
):
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Device %s, found required %s, adding %s to modules.",
|
"Device %s, found required %s, adding %s to modules.",
|
||||||
@ -440,19 +443,6 @@ class SmartDevice(Device):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if "overheated" in self._info:
|
|
||||||
self._add_feature(
|
|
||||||
Feature(
|
|
||||||
self,
|
|
||||||
id="overheated",
|
|
||||||
name="Overheated",
|
|
||||||
attribute_getter=lambda x: x._info["overheated"],
|
|
||||||
icon="mdi:heat-wave",
|
|
||||||
type=Feature.Type.BinarySensor,
|
|
||||||
category=Feature.Category.Info,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# We check for the key available, and not for the property truthiness,
|
# We check for the key available, and not for the property truthiness,
|
||||||
# as the value is falsy when the device is off.
|
# as the value is falsy when the device is off.
|
||||||
if "on_time" in self._info:
|
if "on_time" in self._info:
|
||||||
|
@ -54,8 +54,8 @@ class SmartModule(Module):
|
|||||||
NAME: str
|
NAME: str
|
||||||
#: Module is initialized, if the given component is available
|
#: Module is initialized, if the given component is available
|
||||||
REQUIRED_COMPONENT: str | None = None
|
REQUIRED_COMPONENT: str | None = None
|
||||||
#: Module is initialized, if the given key available in the main sysinfo
|
#: Module is initialized, if any of the given keys exists in the sysinfo
|
||||||
REQUIRED_KEY_ON_PARENT: str | None = None
|
SYSINFO_LOOKUP_KEYS: list[str] = []
|
||||||
#: Query to execute during the main update cycle
|
#: Query to execute during the main update cycle
|
||||||
QUERY_GETTER_NAME: str
|
QUERY_GETTER_NAME: str
|
||||||
|
|
||||||
|
@ -3,13 +3,14 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any, cast
|
||||||
|
|
||||||
from ..device import _DeviceInfo
|
from ..device import _DeviceInfo
|
||||||
from ..device_type import DeviceType
|
from ..device_type import DeviceType
|
||||||
from ..module import Module
|
from ..module import Module
|
||||||
from ..protocols.smartcamprotocol import _ChildCameraProtocolWrapper
|
from ..protocols.smartcamprotocol import _ChildCameraProtocolWrapper
|
||||||
from ..smart import SmartChildDevice, SmartDevice
|
from ..smart import SmartChildDevice, SmartDevice
|
||||||
|
from ..smart.smartdevice import ComponentsRaw
|
||||||
from .modules import ChildDevice, DeviceModule
|
from .modules import ChildDevice, DeviceModule
|
||||||
from .smartcammodule import SmartCamModule
|
from .smartcammodule import SmartCamModule
|
||||||
|
|
||||||
@ -78,7 +79,7 @@ class SmartCamDevice(SmartDevice):
|
|||||||
self._children[child_id]._update_internal_state(info)
|
self._children[child_id]._update_internal_state(info)
|
||||||
|
|
||||||
async def _initialize_smart_child(
|
async def _initialize_smart_child(
|
||||||
self, info: dict, child_components: dict
|
self, info: dict, child_components_raw: ComponentsRaw
|
||||||
) -> SmartDevice:
|
) -> SmartDevice:
|
||||||
"""Initialize a smart child device attached to a smartcam device."""
|
"""Initialize a smart child device attached to a smartcam device."""
|
||||||
child_id = info["device_id"]
|
child_id = info["device_id"]
|
||||||
@ -93,7 +94,7 @@ class SmartCamDevice(SmartDevice):
|
|||||||
return await SmartChildDevice.create(
|
return await SmartChildDevice.create(
|
||||||
parent=self,
|
parent=self,
|
||||||
child_info=info,
|
child_info=info,
|
||||||
child_components=child_components,
|
child_components_raw=child_components_raw,
|
||||||
protocol=child_protocol,
|
protocol=child_protocol,
|
||||||
last_update=initial_response,
|
last_update=initial_response,
|
||||||
)
|
)
|
||||||
@ -108,17 +109,8 @@ class SmartCamDevice(SmartDevice):
|
|||||||
self.internal_state.update(resp)
|
self.internal_state.update(resp)
|
||||||
|
|
||||||
smart_children_components = {
|
smart_children_components = {
|
||||||
child["device_id"]: {
|
child["device_id"]: child
|
||||||
comp["id"]: int(comp["ver_code"]) for comp in component_list
|
|
||||||
}
|
|
||||||
for child in resp["getChildDeviceComponentList"]["child_component_list"]
|
for child in resp["getChildDeviceComponentList"]["child_component_list"]
|
||||||
if (component_list := child.get("component_list"))
|
|
||||||
# Child camera devices will have a different component schema so only
|
|
||||||
# extract smart values.
|
|
||||||
and (first_comp := next(iter(component_list), None))
|
|
||||||
and isinstance(first_comp, dict)
|
|
||||||
and "id" in first_comp
|
|
||||||
and "ver_code" in first_comp
|
|
||||||
}
|
}
|
||||||
children = {}
|
children = {}
|
||||||
for info in resp["getChildDeviceList"]["child_device_list"]:
|
for info in resp["getChildDeviceList"]["child_device_list"]:
|
||||||
@ -172,6 +164,13 @@ class SmartCamDevice(SmartDevice):
|
|||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _parse_components(components_raw: ComponentsRaw) -> dict[str, int]:
|
||||||
|
return {
|
||||||
|
str(comp["name"]): int(comp["version"])
|
||||||
|
for comp in components_raw["app_component_list"]
|
||||||
|
}
|
||||||
|
|
||||||
async def _negotiate(self) -> None:
|
async def _negotiate(self) -> None:
|
||||||
"""Perform initialization.
|
"""Perform initialization.
|
||||||
|
|
||||||
@ -186,12 +185,10 @@ class SmartCamDevice(SmartDevice):
|
|||||||
self._last_update.update(resp)
|
self._last_update.update(resp)
|
||||||
self._update_internal_info(resp)
|
self._update_internal_info(resp)
|
||||||
|
|
||||||
self._components = {
|
self._components_raw = cast(
|
||||||
comp["name"]: int(comp["version"])
|
ComponentsRaw, resp["getAppComponentList"]["app_component"]
|
||||||
for comp in resp["getAppComponentList"]["app_component"][
|
)
|
||||||
"app_component_list"
|
self._components = self._parse_components(self._components_raw)
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
if "childControl" in self._components and not self.children:
|
if "childControl" in self._components and not self.children:
|
||||||
await self._initialize_children()
|
await self._initialize_children()
|
||||||
|
@ -435,7 +435,7 @@ async def get_device_for_fixture(
|
|||||||
|
|
||||||
discovery_data = None
|
discovery_data = None
|
||||||
if "discovery_result" in fixture_data.data:
|
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:
|
elif "system" in fixture_data.data:
|
||||||
discovery_data = {
|
discovery_data = {
|
||||||
"system": {"get_sysinfo": fixture_data.data["system"]["get_sysinfo"]}
|
"system": {"get_sysinfo": fixture_data.data["system"]["get_sysinfo"]}
|
||||||
|
@ -139,7 +139,8 @@ smart_discovery = parametrize_discovery("smart discovery", protocol_filter={"SMA
|
|||||||
)
|
)
|
||||||
async def discovery_mock(request, mocker):
|
async def discovery_mock(request, mocker):
|
||||||
"""Mock discovery and patch protocol queries to use Fake protocols."""
|
"""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)
|
return patch_discovery({DISCOVERY_MOCK_IP: fixture_info}, mocker)
|
||||||
|
|
||||||
|
|
||||||
@ -170,8 +171,8 @@ def create_discovery_mock(ip: str, fixture_data: dict):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if "discovery_result" in fixture_data:
|
if "discovery_result" in fixture_data:
|
||||||
discovery_data = {"result": fixture_data["discovery_result"].copy()}
|
discovery_data = fixture_data["discovery_result"].copy()
|
||||||
discovery_result = fixture_data["discovery_result"]
|
discovery_result = fixture_data["discovery_result"]["result"]
|
||||||
device_type = discovery_result["device_type"]
|
device_type = discovery_result["device_type"]
|
||||||
encrypt_type = discovery_result["mgt_encrypt_schm"].get(
|
encrypt_type = discovery_result["mgt_encrypt_schm"].get(
|
||||||
"encrypt_type", discovery_result.get("encrypt_info", {}).get("sym_schm")
|
"encrypt_type", discovery_result.get("encrypt_info", {}).get("sym_schm")
|
||||||
@ -305,7 +306,7 @@ def discovery_data(request, mocker):
|
|||||||
mocker.patch("kasa.IotProtocol.query", return_value=fixture_data)
|
mocker.patch("kasa.IotProtocol.query", return_value=fixture_data)
|
||||||
mocker.patch("kasa.SmartProtocol.query", return_value=fixture_data)
|
mocker.patch("kasa.SmartProtocol.query", return_value=fixture_data)
|
||||||
if "discovery_result" in fixture_data:
|
if "discovery_result" in fixture_data:
|
||||||
return {"result": fixture_data["discovery_result"]}
|
return fixture_data["discovery_result"].copy()
|
||||||
else:
|
else:
|
||||||
return {"system": {"get_sysinfo": fixture_data["system"]["get_sysinfo"]}}
|
return {"system": {"get_sysinfo": fixture_data["system"]["get_sysinfo"]}}
|
||||||
|
|
||||||
|
2
tests/fixtures/iot/EP10(US)_1.0_1.0.2.json
vendored
2
tests/fixtures/iot/EP10(US)_1.0_1.0.2.json
vendored
@ -2,7 +2,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "167 lamp",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Smart Wi-Fi Plug Mini",
|
"dev_name": "Smart Wi-Fi Plug Mini",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
10
tests/fixtures/iot/EP40(US)_1.0_1.0.2.json
vendored
10
tests/fixtures/iot/EP40(US)_1.0_1.0.2.json
vendored
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"alias": "TP-LINK_Smart Plug_004F",
|
"alias": "#MASKED_NAME#",
|
||||||
"child_num": 2,
|
"child_num": 2,
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"alias": "Zombie",
|
"alias": "#MASKED_NAME# 1",
|
||||||
"id": "8006231E1499BAC4D4BC7EFCD4B075181E6393F200",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -14,8 +14,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Magic",
|
"alias": "#MASKED_NAME# 2",
|
||||||
"id": "8006231E1499BAC4D4BC7EFCD4B075181E6393F201",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
|
2
tests/fixtures/iot/ES20M(US)_1.0_1.0.11.json
vendored
2
tests/fixtures/iot/ES20M(US)_1.0_1.0.11.json
vendored
@ -11,7 +11,7 @@
|
|||||||
"stopConnect": 0,
|
"stopConnect": 0,
|
||||||
"tcspInfo": "",
|
"tcspInfo": "",
|
||||||
"tcspStatus": 1,
|
"tcspStatus": 1,
|
||||||
"username": "#MASKED_NAME#"
|
"username": "user@example.com"
|
||||||
},
|
},
|
||||||
"get_intl_fw_list": {
|
"get_intl_fw_list": {
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/ES20M(US)_1.0_1.0.8.json
vendored
2
tests/fixtures/iot/ES20M(US)_1.0_1.0.8.json
vendored
@ -78,7 +78,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Test ES20M",
|
"alias": "#MASKED_NAME#",
|
||||||
"brightness": 35,
|
"brightness": 35,
|
||||||
"dev_name": "Wi-Fi Smart Dimmer with sensor",
|
"dev_name": "Wi-Fi Smart Dimmer with sensor",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
|
29
tests/fixtures/iot/HS100(UK)_4.1_1.1.0.json
vendored
29
tests/fixtures/iot/HS100(UK)_4.1_1.1.0.json
vendored
@ -1,18 +1,21 @@
|
|||||||
{
|
{
|
||||||
"discovery_result": {
|
"discovery_result": {
|
||||||
"device_id": "00000000000000000000000000000000",
|
"error_code": 0,
|
||||||
"device_model": "HS100(UK)",
|
"result": {
|
||||||
"device_type": "IOT.SMARTPLUGSWITCH",
|
"device_id": "00000000000000000000000000000000",
|
||||||
"factory_default": true,
|
"device_model": "HS100(UK)",
|
||||||
"hw_ver": "4.1",
|
"device_type": "IOT.SMARTPLUGSWITCH",
|
||||||
"ip": "127.0.0.123",
|
"factory_default": true,
|
||||||
"mac": "CC-32-E5-00-00-00",
|
"hw_ver": "4.1",
|
||||||
"mgt_encrypt_schm": {
|
"ip": "127.0.0.123",
|
||||||
"encrypt_type": "KLAP",
|
"mac": "CC-32-E5-00-00-00",
|
||||||
"http_port": 80,
|
"mgt_encrypt_schm": {
|
||||||
"is_support_https": false
|
"encrypt_type": "KLAP",
|
||||||
},
|
"http_port": 80,
|
||||||
"owner": "00000000000000000000000000000000"
|
"is_support_https": false
|
||||||
|
},
|
||||||
|
"owner": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
|
2
tests/fixtures/iot/HS100(US)_1.0_1.2.5.json
vendored
2
tests/fixtures/iot/HS100(US)_1.0_1.2.5.json
vendored
@ -18,7 +18,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "schedule",
|
"active_mode": "schedule",
|
||||||
"alias": "Unused 3",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Wi-Fi Smart Plug",
|
"dev_name": "Wi-Fi Smart Plug",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/HS100(US)_2.0_1.5.6.json
vendored
2
tests/fixtures/iot/HS100(US)_2.0_1.5.6.json
vendored
@ -20,7 +20,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "3D Printer",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Smart Wi-Fi Plug",
|
"dev_name": "Smart Wi-Fi Plug",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/HS103(US)_1.0_1.5.7.json
vendored
2
tests/fixtures/iot/HS103(US)_1.0_1.5.7.json
vendored
@ -20,7 +20,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "schedule",
|
"active_mode": "schedule",
|
||||||
"alias": "Night lite",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Smart Wi-Fi Plug Lite",
|
"dev_name": "Smart Wi-Fi Plug Lite",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/HS103(US)_2.1_1.1.2.json
vendored
2
tests/fixtures/iot/HS103(US)_2.1_1.1.2.json
vendored
@ -18,7 +18,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Corner",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Smart Wi-Fi Plug Lite",
|
"dev_name": "Smart Wi-Fi Plug Lite",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/HS103(US)_2.1_1.1.4.json
vendored
2
tests/fixtures/iot/HS103(US)_2.1_1.1.4.json
vendored
@ -2,7 +2,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Plug",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Smart Wi-Fi Plug Lite",
|
"dev_name": "Smart Wi-Fi Plug Lite",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/HS105(US)_1.0_1.5.6.json
vendored
2
tests/fixtures/iot/HS105(US)_1.0_1.5.6.json
vendored
@ -20,7 +20,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Unused 1",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Smart Wi-Fi Plug Mini",
|
"dev_name": "Smart Wi-Fi Plug Mini",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
12
tests/fixtures/iot/HS107(US)_1.0_1.0.8.json
vendored
12
tests/fixtures/iot/HS107(US)_1.0_1.0.8.json
vendored
@ -17,12 +17,12 @@
|
|||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"alias": "TP-LINK_Smart Plug_D310",
|
"alias": "#MASKED_NAME#",
|
||||||
"child_num": 2,
|
"child_num": 2,
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"alias": "Garage Charger 1",
|
"alias": "#MASKED_NAME# 1",
|
||||||
"id": "00",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -30,8 +30,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Garage Charger 2",
|
"alias": "#MASKED_NAME# 2",
|
||||||
"id": "01",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -46,7 +46,7 @@
|
|||||||
"hw_ver": "1.0",
|
"hw_ver": "1.0",
|
||||||
"latitude_i": 0,
|
"latitude_i": 0,
|
||||||
"led_off": 0,
|
"led_off": 0,
|
||||||
"longitude_i": -0,
|
"longitude_i": 0,
|
||||||
"mac": "00:00:00:00:00:00",
|
"mac": "00:00:00:00:00:00",
|
||||||
"mic_type": "IOT.SMARTPLUGSWITCH",
|
"mic_type": "IOT.SMARTPLUGSWITCH",
|
||||||
"model": "HS107(US)",
|
"model": "HS107(US)",
|
||||||
|
2
tests/fixtures/iot/HS110(EU)_1.0_1.2.5.json
vendored
2
tests/fixtures/iot/HS110(EU)_1.0_1.2.5.json
vendored
@ -11,7 +11,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "schedule",
|
"active_mode": "schedule",
|
||||||
"alias": "Bedroom Lamp Plug",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Wi-Fi Smart Plug With Energy Monitoring",
|
"dev_name": "Wi-Fi Smart Plug With Energy Monitoring",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/HS110(US)_1.0_1.2.6.json
vendored
2
tests/fixtures/iot/HS110(US)_1.0_1.2.6.json
vendored
@ -11,7 +11,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "schedule",
|
"active_mode": "schedule",
|
||||||
"alias": "Home Google WiFi HS110",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Wi-Fi Smart Plug With Energy Monitoring",
|
"dev_name": "Wi-Fi Smart Plug With Energy Monitoring",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/HS200(US)_2.0_1.5.7.json
vendored
2
tests/fixtures/iot/HS200(US)_2.0_1.5.7.json
vendored
@ -20,7 +20,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Master Bedroom Fan",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Smart Wi-Fi Light Switch",
|
"dev_name": "Smart Wi-Fi Light Switch",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/HS200(US)_5.0_1.0.2.json
vendored
2
tests/fixtures/iot/HS200(US)_5.0_1.0.2.json
vendored
@ -2,7 +2,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "House Fan",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Smart Wi-Fi Light Switch",
|
"dev_name": "Smart Wi-Fi Light Switch",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/HS210(US)_1.0_1.5.8.json
vendored
2
tests/fixtures/iot/HS210(US)_1.0_1.5.8.json
vendored
@ -21,7 +21,7 @@
|
|||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"abnormal_detect": 1,
|
"abnormal_detect": 1,
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Garage Light",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Smart Wi-Fi 3-Way Light Switch",
|
"dev_name": "Smart Wi-Fi 3-Way Light Switch",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
6
tests/fixtures/iot/HS220(US)_1.0_1.5.7.json
vendored
6
tests/fixtures/iot/HS220(US)_1.0_1.5.7.json
vendored
@ -28,7 +28,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Living Room Dimmer Switch",
|
"alias": "#MASKED_NAME#",
|
||||||
"brightness": 25,
|
"brightness": 25,
|
||||||
"dev_name": "Smart Wi-Fi Dimmer",
|
"dev_name": "Smart Wi-Fi Dimmer",
|
||||||
"deviceId": "000000000000000000000000000000000000000",
|
"deviceId": "000000000000000000000000000000000000000",
|
||||||
@ -38,9 +38,9 @@
|
|||||||
"hwId": "00000000000000000000000000000000",
|
"hwId": "00000000000000000000000000000000",
|
||||||
"hw_ver": "1.0",
|
"hw_ver": "1.0",
|
||||||
"icon_hash": "",
|
"icon_hash": "",
|
||||||
"latitude_i": 11.6210,
|
"latitude_i": 0,
|
||||||
"led_off": 0,
|
"led_off": 0,
|
||||||
"longitude_i": 42.2074,
|
"longitude_i": 0,
|
||||||
"mac": "00:00:00:00:00:00",
|
"mac": "00:00:00:00:00:00",
|
||||||
"mic_type": "IOT.SMARTPLUGSWITCH",
|
"mic_type": "IOT.SMARTPLUGSWITCH",
|
||||||
"model": "HS220(US)",
|
"model": "HS220(US)",
|
||||||
|
2
tests/fixtures/iot/HS220(US)_2.0_1.0.3.json
vendored
2
tests/fixtures/iot/HS220(US)_2.0_1.0.3.json
vendored
@ -17,7 +17,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Living Room Dimmer Switch",
|
"alias": "#MASKED_NAME#",
|
||||||
"brightness": 100,
|
"brightness": 100,
|
||||||
"dev_name": "Wi-Fi Smart Dimmer",
|
"dev_name": "Wi-Fi Smart Dimmer",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
|
28
tests/fixtures/iot/HS300(US)_1.0_1.0.10.json
vendored
28
tests/fixtures/iot/HS300(US)_1.0_1.0.10.json
vendored
@ -22,12 +22,12 @@
|
|||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"alias": "TP-LINK_Power Strip_DAE1",
|
"alias": "#MASKED_NAME#",
|
||||||
"child_num": 6,
|
"child_num": 6,
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"alias": "Office Monitor 1",
|
"alias": "#MASKED_NAME# 1",
|
||||||
"id": "00",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -35,8 +35,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Office Monitor 2",
|
"alias": "#MASKED_NAME# 2",
|
||||||
"id": "01",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -44,8 +44,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Office Monitor 3",
|
"alias": "#MASKED_NAME# 3",
|
||||||
"id": "02",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_3",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -53,8 +53,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Office Laptop Dock",
|
"alias": "#MASKED_NAME# 4",
|
||||||
"id": "03",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_4",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -62,8 +62,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Office Desk Light",
|
"alias": "#MASKED_NAME# 5",
|
||||||
"id": "04",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_5",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -71,8 +71,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Laptop",
|
"alias": "#MASKED_NAME# 6",
|
||||||
"id": "05",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_6",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -87,7 +87,7 @@
|
|||||||
"hw_ver": "1.0",
|
"hw_ver": "1.0",
|
||||||
"latitude_i": 0,
|
"latitude_i": 0,
|
||||||
"led_off": 0,
|
"led_off": 0,
|
||||||
"longitude_i": -0,
|
"longitude_i": 0,
|
||||||
"mac": "00:00:00:00:00:00",
|
"mac": "00:00:00:00:00:00",
|
||||||
"mic_type": "IOT.SMARTPLUGSWITCH",
|
"mic_type": "IOT.SMARTPLUGSWITCH",
|
||||||
"model": "HS300(US)",
|
"model": "HS300(US)",
|
||||||
|
26
tests/fixtures/iot/HS300(US)_1.0_1.0.21.json
vendored
26
tests/fixtures/iot/HS300(US)_1.0_1.0.21.json
vendored
@ -10,12 +10,12 @@
|
|||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"alias": "TP-LINK_Power Strip_2CA9",
|
"alias": "#MASKED_NAME#",
|
||||||
"child_num": 6,
|
"child_num": 6,
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"alias": "Home CameraPC",
|
"alias": "#MASKED_NAME# 1",
|
||||||
"id": "800623145DFF1AA096363EFD161C2E661A9D8DED00",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -23,8 +23,8 @@
|
|||||||
"state": 1
|
"state": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Home Firewalla",
|
"alias": "#MASKED_NAME# 2",
|
||||||
"id": "800623145DFF1AA096363EFD161C2E661A9D8DED01",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -32,8 +32,8 @@
|
|||||||
"state": 1
|
"state": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Home Cox modem",
|
"alias": "#MASKED_NAME# 3",
|
||||||
"id": "800623145DFF1AA096363EFD161C2E661A9D8DED02",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_3",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -41,8 +41,8 @@
|
|||||||
"state": 1
|
"state": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Home rpi3-2",
|
"alias": "#MASKED_NAME# 4",
|
||||||
"id": "800623145DFF1AA096363EFD161C2E661A9D8DED03",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_4",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -50,8 +50,8 @@
|
|||||||
"state": 1
|
"state": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Home Camera Switch",
|
"alias": "#MASKED_NAME# 5",
|
||||||
"id": "800623145DFF1AA096363EFD161C2E661A9D8DED05",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_5",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -59,8 +59,8 @@
|
|||||||
"state": 1
|
"state": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Home Network Switch",
|
"alias": "#MASKED_NAME# 6",
|
||||||
"id": "800623145DFF1AA096363EFD161C2E661A9D8DED04",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_6",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
|
24
tests/fixtures/iot/HS300(US)_2.0_1.0.12.json
vendored
24
tests/fixtures/iot/HS300(US)_2.0_1.0.12.json
vendored
@ -15,8 +15,8 @@
|
|||||||
"child_num": 6,
|
"child_num": 6,
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"alias": "#MASKED_NAME#",
|
"alias": "#MASKED_NAME# 1",
|
||||||
"id": "8006A0F1D01120C3F93794F7AACACDBE1EAD246D00",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -24,8 +24,8 @@
|
|||||||
"state": 1
|
"state": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "#MASKED_NAME#",
|
"alias": "#MASKED_NAME# 2",
|
||||||
"id": "8006A0F1D01120C3F93794F7AACACDBE1EAD246D01",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -33,8 +33,8 @@
|
|||||||
"state": 1
|
"state": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "#MASKED_NAME#",
|
"alias": "#MASKED_NAME# 3",
|
||||||
"id": "8006A0F1D01120C3F93794F7AACACDBE1EAD246D02",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_3",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -42,8 +42,8 @@
|
|||||||
"state": 1
|
"state": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "#MASKED_NAME#",
|
"alias": "#MASKED_NAME# 4",
|
||||||
"id": "8006A0F1D01120C3F93794F7AACACDBE1EAD246D03",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_4",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -51,8 +51,8 @@
|
|||||||
"state": 1
|
"state": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "#MASKED_NAME#",
|
"alias": "#MASKED_NAME# 5",
|
||||||
"id": "8006A0F1D01120C3F93794F7AACACDBE1EAD246D04",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_5",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -60,8 +60,8 @@
|
|||||||
"state": 1
|
"state": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "#MASKED_NAME#",
|
"alias": "#MASKED_NAME# 6",
|
||||||
"id": "8006A0F1D01120C3F93794F7AACACDBE1EAD246D05",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_6",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
|
26
tests/fixtures/iot/HS300(US)_2.0_1.0.3.json
vendored
26
tests/fixtures/iot/HS300(US)_2.0_1.0.3.json
vendored
@ -11,12 +11,12 @@
|
|||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"alias": "TP-LINK_Power Strip_5C33",
|
"alias": "#MASKED_NAME#",
|
||||||
"child_num": 6,
|
"child_num": 6,
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"alias": "Plug 1",
|
"alias": "#MASKED_NAME# 1",
|
||||||
"id": "8006AF35494E7DB13DDE9B8F40BF2E001E77031900",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -24,8 +24,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Plug 2",
|
"alias": "#MASKED_NAME# 2",
|
||||||
"id": "8006AF35494E7DB13DDE9B8F40BF2E001E77031901",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -33,8 +33,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Plug 3",
|
"alias": "#MASKED_NAME# 3",
|
||||||
"id": "8006AF35494E7DB13DDE9B8F40BF2E001E77031902",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_3",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -42,8 +42,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Plug 4",
|
"alias": "#MASKED_NAME# 4",
|
||||||
"id": "8006AF35494E7DB13DDE9B8F40BF2E001E77031903",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_4",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -51,8 +51,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Plug 5",
|
"alias": "#MASKED_NAME# 5",
|
||||||
"id": "8006AF35494E7DB13DDE9B8F40BF2E001E77031904",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_5",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -60,8 +60,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Plug 6",
|
"alias": "#MASKED_NAME# 6",
|
||||||
"id": "8006AF35494E7DB13DDE9B8F40BF2E001E77031905",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_6",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
|
2
tests/fixtures/iot/KL110(US)_1.0_1.8.11.json
vendored
2
tests/fixtures/iot/KL110(US)_1.0_1.8.11.json
vendored
@ -21,7 +21,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Bulb3",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
2
tests/fixtures/iot/KL120(US)_1.0_1.8.11.json
vendored
2
tests/fixtures/iot/KL120(US)_1.0_1.8.11.json
vendored
@ -19,7 +19,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Home Family Room Table",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
8
tests/fixtures/iot/KL120(US)_1.0_1.8.6.json
vendored
8
tests/fixtures/iot/KL120(US)_1.0_1.8.6.json
vendored
@ -34,11 +34,11 @@
|
|||||||
},
|
},
|
||||||
"description": "Smart Wi-Fi LED Bulb with Tunable White Light",
|
"description": "Smart Wi-Fi LED Bulb with Tunable White Light",
|
||||||
"dev_state": "normal",
|
"dev_state": "normal",
|
||||||
"deviceId": "801200814AD69370AC59DE5501319C051AF409C3",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"disco_ver": "1.0",
|
"disco_ver": "1.0",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
"heapsize": 290784,
|
"heapsize": 290784,
|
||||||
"hwId": "111E35908497A05512E259BB76801E10",
|
"hwId": "00000000000000000000000000000000",
|
||||||
"hw_ver": "1.0",
|
"hw_ver": "1.0",
|
||||||
"is_color": 0,
|
"is_color": 0,
|
||||||
"is_dimmable": 1,
|
"is_dimmable": 1,
|
||||||
@ -52,10 +52,10 @@
|
|||||||
"on_off": 1,
|
"on_off": 1,
|
||||||
"saturation": 0
|
"saturation": 0
|
||||||
},
|
},
|
||||||
"mic_mac": "D80D17150474",
|
"mic_mac": "D80D17000000",
|
||||||
"mic_type": "IOT.SMARTBULB",
|
"mic_type": "IOT.SMARTBULB",
|
||||||
"model": "KL120(US)",
|
"model": "KL120(US)",
|
||||||
"oemId": "1210657CD7FBDC72895644388EEFAE8B",
|
"oemId": "00000000000000000000000000000000",
|
||||||
"preferred_state": [
|
"preferred_state": [
|
||||||
{
|
{
|
||||||
"brightness": 100,
|
"brightness": 100,
|
||||||
|
2
tests/fixtures/iot/KL125(US)_1.20_1.0.5.json
vendored
2
tests/fixtures/iot/KL125(US)_1.20_1.0.5.json
vendored
@ -20,7 +20,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "kasa-bc01",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
2
tests/fixtures/iot/KL125(US)_2.0_1.0.7.json
vendored
2
tests/fixtures/iot/KL125(US)_2.0_1.0.7.json
vendored
@ -22,7 +22,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Test bulb 6",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
2
tests/fixtures/iot/KL130(EU)_1.0_1.8.8.json
vendored
2
tests/fixtures/iot/KL130(EU)_1.0_1.8.8.json
vendored
@ -11,7 +11,7 @@
|
|||||||
"stopConnect": 0,
|
"stopConnect": 0,
|
||||||
"tcspInfo": "",
|
"tcspInfo": "",
|
||||||
"tcspStatus": 1,
|
"tcspStatus": 1,
|
||||||
"username": "#MASKED_NAME#"
|
"username": "user@example.com"
|
||||||
},
|
},
|
||||||
"get_intl_fw_list": {
|
"get_intl_fw_list": {
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/KL130(US)_1.0_1.8.11.json
vendored
2
tests/fixtures/iot/KL130(US)_1.0_1.8.11.json
vendored
@ -21,7 +21,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Bulb2",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
2
tests/fixtures/iot/KL135(US)_1.0_1.0.15.json
vendored
2
tests/fixtures/iot/KL135(US)_1.0_1.0.15.json
vendored
@ -11,7 +11,7 @@
|
|||||||
"stopConnect": 0,
|
"stopConnect": 0,
|
||||||
"tcspInfo": "",
|
"tcspInfo": "",
|
||||||
"tcspStatus": 1,
|
"tcspStatus": 1,
|
||||||
"username": "#MASKED_NAME#"
|
"username": "user@example.com"
|
||||||
},
|
},
|
||||||
"get_intl_fw_list": {
|
"get_intl_fw_list": {
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/KL135(US)_1.0_1.0.6.json
vendored
2
tests/fixtures/iot/KL135(US)_1.0_1.0.6.json
vendored
@ -20,7 +20,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "KL135 Bulb",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"LEF": 0,
|
"LEF": 0,
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Kl400",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"LEF": 0,
|
"LEF": 0,
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Kl400",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"LEF": 1,
|
"LEF": 1,
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Kl420 test",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
2
tests/fixtures/iot/KL430(UN)_2.0_1.0.8.json
vendored
2
tests/fixtures/iot/KL430(UN)_2.0_1.0.8.json
vendored
@ -10,7 +10,7 @@
|
|||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"LEF": 1,
|
"LEF": 1,
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Bedroom light strip",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
2
tests/fixtures/iot/KL430(US)_1.0_1.0.10.json
vendored
2
tests/fixtures/iot/KL430(US)_1.0_1.0.10.json
vendored
@ -23,7 +23,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "schedule",
|
"active_mode": "schedule",
|
||||||
"alias": "Bedroom Lightstrip",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
2
tests/fixtures/iot/KL430(US)_2.0_1.0.11.json
vendored
2
tests/fixtures/iot/KL430(US)_2.0_1.0.11.json
vendored
@ -11,7 +11,7 @@
|
|||||||
"stopConnect": 0,
|
"stopConnect": 0,
|
||||||
"tcspInfo": "",
|
"tcspInfo": "",
|
||||||
"tcspStatus": 1,
|
"tcspStatus": 1,
|
||||||
"username": "#MASKED_NAME#"
|
"username": "user@example.com"
|
||||||
},
|
},
|
||||||
"get_intl_fw_list": {
|
"get_intl_fw_list": {
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/KL430(US)_2.0_1.0.8.json
vendored
2
tests/fixtures/iot/KL430(US)_2.0_1.0.8.json
vendored
@ -10,7 +10,7 @@
|
|||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"LEF": 1,
|
"LEF": 1,
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "89 strip",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
2
tests/fixtures/iot/KL430(US)_2.0_1.0.9.json
vendored
2
tests/fixtures/iot/KL430(US)_2.0_1.0.9.json
vendored
@ -10,7 +10,7 @@
|
|||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"LEF": 1,
|
"LEF": 1,
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "kl430 updated",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
2
tests/fixtures/iot/KL50(US)_1.0_1.1.13.json
vendored
2
tests/fixtures/iot/KL50(US)_1.0_1.1.13.json
vendored
@ -22,7 +22,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Kl50",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
4
tests/fixtures/iot/KL60(UN)_1.0_1.1.4.json
vendored
4
tests/fixtures/iot/KL60(UN)_1.0_1.1.4.json
vendored
@ -32,7 +32,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "TP-LINK_Smart Bulb_9179",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
@ -60,7 +60,7 @@
|
|||||||
"on_off": 0
|
"on_off": 0
|
||||||
},
|
},
|
||||||
"longitude_i": 0,
|
"longitude_i": 0,
|
||||||
"mic_mac": "74DA88C89179",
|
"mic_mac": "74DA88000000",
|
||||||
"mic_type": "IOT.SMARTBULB",
|
"mic_type": "IOT.SMARTBULB",
|
||||||
"model": "KL60(UN)",
|
"model": "KL60(UN)",
|
||||||
"oemId": "00000000000000000000000000000000",
|
"oemId": "00000000000000000000000000000000",
|
||||||
|
2
tests/fixtures/iot/KL60(US)_1.0_1.1.13.json
vendored
2
tests/fixtures/iot/KL60(US)_1.0_1.1.13.json
vendored
@ -22,7 +22,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Gold fil",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
2
tests/fixtures/iot/KP100(US)_3.0_1.0.1.json
vendored
2
tests/fixtures/iot/KP100(US)_3.0_1.0.1.json
vendored
@ -2,7 +2,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Kasa",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Smart Wi-Fi Plug Mini",
|
"dev_name": "Smart Wi-Fi Plug Mini",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/KP105(UK)_1.0_1.0.5.json
vendored
2
tests/fixtures/iot/KP105(UK)_1.0_1.0.5.json
vendored
@ -11,7 +11,7 @@
|
|||||||
"stopConnect": 0,
|
"stopConnect": 0,
|
||||||
"tcspInfo": "",
|
"tcspInfo": "",
|
||||||
"tcspStatus": 1,
|
"tcspStatus": 1,
|
||||||
"username": "#MASKED_NAME#"
|
"username": "user@example.com"
|
||||||
},
|
},
|
||||||
"get_intl_fw_list": {
|
"get_intl_fw_list": {
|
||||||
"err_code": -7,
|
"err_code": -7,
|
||||||
|
2
tests/fixtures/iot/KP115(US)_1.0_1.0.17.json
vendored
2
tests/fixtures/iot/KP115(US)_1.0_1.0.17.json
vendored
@ -11,7 +11,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Test plug",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Smart Wi-Fi Plug Mini",
|
"dev_name": "Smart Wi-Fi Plug Mini",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/KP125(US)_1.0_1.0.6.json
vendored
2
tests/fixtures/iot/KP125(US)_1.0_1.0.6.json
vendored
@ -11,7 +11,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Test plug",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Smart Wi-Fi Plug Mini",
|
"dev_name": "Smart Wi-Fi Plug Mini",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
10
tests/fixtures/iot/KP200(US)_3.0_1.0.3.json
vendored
10
tests/fixtures/iot/KP200(US)_3.0_1.0.3.json
vendored
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"alias": "TP-LINK_Smart Plug_C2D6",
|
"alias": "#MASKED_NAME#",
|
||||||
"child_num": 2,
|
"child_num": 2,
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"alias": "One ",
|
"alias": "#MASKED_NAME# 1",
|
||||||
"id": "80066788DFFFD572D9F2E4A5A6847669213E039F00",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -14,8 +14,8 @@
|
|||||||
"state": 1
|
"state": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Two ",
|
"alias": "#MASKED_NAME# 2",
|
||||||
"id": "80066788DFFFD572D9F2E4A5A6847669213E039F01",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
|
14
tests/fixtures/iot/KP303(UK)_1.0_1.0.3.json
vendored
14
tests/fixtures/iot/KP303(UK)_1.0_1.0.3.json
vendored
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"alias": "Bedroom Power Strip",
|
"alias": "#MASKED_NAME#",
|
||||||
"child_num": 3,
|
"child_num": 3,
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"alias": "Plug 1",
|
"alias": "#MASKED_NAME# 1",
|
||||||
"id": "8006E9854025B67C3F9D99BA1E66223D1C9A8A7700",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -14,8 +14,8 @@
|
|||||||
"state": 1
|
"state": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Plug 2",
|
"alias": "#MASKED_NAME# 2",
|
||||||
"id": "8006E9854025B67C3F9D99BA1E66223D1C9A8A7701",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -23,8 +23,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Plug 3",
|
"alias": "#MASKED_NAME# 3",
|
||||||
"id": "8006E9854025B67C3F9D99BA1E66223D1C9A8A7702",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_3",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
|
14
tests/fixtures/iot/KP303(US)_2.0_1.0.3.json
vendored
14
tests/fixtures/iot/KP303(US)_2.0_1.0.3.json
vendored
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"alias": "TP-LINK_Power Strip_BDF6",
|
"alias": "#MASKED_NAME#",
|
||||||
"child_num": 3,
|
"child_num": 3,
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"alias": "Plug 1",
|
"alias": "#MASKED_NAME# 1",
|
||||||
"id": "800681855E0E9AEF096F4891B3DC88C71E59F42E00",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -14,8 +14,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Plug 2",
|
"alias": "#MASKED_NAME# 2",
|
||||||
"id": "800681855E0E9AEF096F4891B3DC88C71E59F42E01",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -23,8 +23,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Plug 3",
|
"alias": "#MASKED_NAME# 3",
|
||||||
"id": "800681855E0E9AEF096F4891B3DC88C71E59F42E02",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_3",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
|
12
tests/fixtures/iot/KP303(US)_2.0_1.0.9.json
vendored
12
tests/fixtures/iot/KP303(US)_2.0_1.0.9.json
vendored
@ -5,8 +5,8 @@
|
|||||||
"child_num": 3,
|
"child_num": 3,
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"alias": "#MASKED_NAME#",
|
"alias": "#MASKED_NAME# 1",
|
||||||
"id": "800639AA097730E58235162FCDA301CE1F038F9101",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -14,8 +14,8 @@
|
|||||||
"state": 1
|
"state": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "#MASKED_NAME#",
|
"alias": "#MASKED_NAME# 2",
|
||||||
"id": "800639AA097730E58235162FCDA301CE1F038F9102",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -23,8 +23,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "#MASKED_NAME#",
|
"alias": "#MASKED_NAME# 3",
|
||||||
"id": "800639AA097730E58235162FCDA301CE1F038F9100",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_3",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
|
10
tests/fixtures/iot/KP400(US)_1.0_1.0.10.json
vendored
10
tests/fixtures/iot/KP400(US)_1.0_1.0.10.json
vendored
@ -17,12 +17,12 @@
|
|||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"alias": "TP-LINK_Smart Plug_2ECE",
|
"alias": "#MASKED_NAME#",
|
||||||
"child_num": 2,
|
"child_num": 2,
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"alias": "Rope",
|
"alias": "#MASKED_NAME# 1",
|
||||||
"id": "00",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"action": 1,
|
"action": 1,
|
||||||
"schd_sec": 69240,
|
"schd_sec": 69240,
|
||||||
@ -32,8 +32,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Plug 2",
|
"alias": "#MASKED_NAME# 2",
|
||||||
"id": "01",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
|
10
tests/fixtures/iot/KP400(US)_2.0_1.0.6.json
vendored
10
tests/fixtures/iot/KP400(US)_2.0_1.0.6.json
vendored
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"alias": "TP-LINK_Smart Plug_DC2A",
|
"alias": "#MASKED_NAME#",
|
||||||
"child_num": 2,
|
"child_num": 2,
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"alias": "Anc ",
|
"alias": "#MASKED_NAME# 1",
|
||||||
"id": "8006B8E953CC4149E2B13AA27E0D18EF1DCFBF3400",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -14,8 +14,8 @@
|
|||||||
"state": 1
|
"state": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "Plug 2",
|
"alias": "#MASKED_NAME# 2",
|
||||||
"id": "8006B8E953CC4149E2B13AA27E0D18EF1DCFBF3401",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
|
8
tests/fixtures/iot/KP400(US)_3.0_1.0.3.json
vendored
8
tests/fixtures/iot/KP400(US)_3.0_1.0.3.json
vendored
@ -5,8 +5,8 @@
|
|||||||
"child_num": 2,
|
"child_num": 2,
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"alias": "#MASKED_NAME#",
|
"alias": "#MASKED_NAME# 1",
|
||||||
"id": "8006521377E30159055A751347B5A5E321A8D0A100",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -14,8 +14,8 @@
|
|||||||
"state": 1
|
"state": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "#MASKED_NAME#",
|
"alias": "#MASKED_NAME# 2",
|
||||||
"id": "8006521377E30159055A751347B5A5E321A8D0A101",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
|
8
tests/fixtures/iot/KP400(US)_3.0_1.0.4.json
vendored
8
tests/fixtures/iot/KP400(US)_3.0_1.0.4.json
vendored
@ -5,8 +5,8 @@
|
|||||||
"child_num": 2,
|
"child_num": 2,
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"alias": "#MASKED_NAME#",
|
"alias": "#MASKED_NAME# 1",
|
||||||
"id": "8006521377E30159055A751347B5A5E321A8D0A100",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_1",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
@ -14,8 +14,8 @@
|
|||||||
"state": 0
|
"state": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": "#MASKED_NAME#",
|
"alias": "#MASKED_NAME# 2",
|
||||||
"id": "8006521377E30159055A751347B5A5E321A8D0A101",
|
"id": "SCRUBBED_CHILD_DEVICE_ID_2",
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"type": -1
|
"type": -1
|
||||||
},
|
},
|
||||||
|
2
tests/fixtures/iot/KP401(US)_1.0_1.0.0.json
vendored
2
tests/fixtures/iot/KP401(US)_1.0_1.0.0.json
vendored
@ -2,7 +2,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Kp401",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Smart Outdoor Plug",
|
"dev_name": "Smart Outdoor Plug",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/KP405(US)_1.0_1.0.5.json
vendored
2
tests/fixtures/iot/KP405(US)_1.0_1.0.5.json
vendored
@ -15,7 +15,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Porch Lights",
|
"alias": "#MASKED_NAME#",
|
||||||
"brightness": 50,
|
"brightness": 50,
|
||||||
"dev_name": "Kasa Smart Wi-Fi Outdoor Plug-In Dimmer",
|
"dev_name": "Kasa Smart Wi-Fi Outdoor Plug-In Dimmer",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
|
2
tests/fixtures/iot/KS200(US)_1.0_1.0.8.json
vendored
2
tests/fixtures/iot/KS200(US)_1.0_1.0.8.json
vendored
@ -11,7 +11,7 @@
|
|||||||
"stopConnect": 0,
|
"stopConnect": 0,
|
||||||
"tcspInfo": "",
|
"tcspInfo": "",
|
||||||
"tcspStatus": 1,
|
"tcspStatus": 1,
|
||||||
"username": "#MASKED_NAME#"
|
"username": "user@example.com"
|
||||||
},
|
},
|
||||||
"get_intl_fw_list": {
|
"get_intl_fw_list": {
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
"stopConnect": 0,
|
"stopConnect": 0,
|
||||||
"tcspInfo": "",
|
"tcspInfo": "",
|
||||||
"tcspStatus": 1,
|
"tcspStatus": 1,
|
||||||
"username": "#MASKED_NAME#"
|
"username": "user@example.com"
|
||||||
},
|
},
|
||||||
"get_intl_fw_list": {
|
"get_intl_fw_list": {
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/KS200M(US)_1.0_1.0.8.json
vendored
2
tests/fixtures/iot/KS200M(US)_1.0_1.0.8.json
vendored
@ -66,7 +66,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Test KS200M",
|
"alias": "#MASKED_NAME#",
|
||||||
"dev_name": "Smart Light Switch with PIR",
|
"dev_name": "Smart Light Switch with PIR",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/KS220(US)_1.0_1.0.13.json
vendored
2
tests/fixtures/iot/KS220(US)_1.0_1.0.13.json
vendored
@ -11,7 +11,7 @@
|
|||||||
"stopConnect": 0,
|
"stopConnect": 0,
|
||||||
"tcspInfo": "",
|
"tcspInfo": "",
|
||||||
"tcspStatus": 1,
|
"tcspStatus": 1,
|
||||||
"username": "#MASKED_NAME#"
|
"username": "user@example.com"
|
||||||
},
|
},
|
||||||
"get_intl_fw_list": {
|
"get_intl_fw_list": {
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
|
2
tests/fixtures/iot/KS220M(US)_1.0_1.0.4.json
vendored
2
tests/fixtures/iot/KS220M(US)_1.0_1.0.4.json
vendored
@ -78,7 +78,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Garage Entryway Lights",
|
"alias": "#MASKED_NAME#",
|
||||||
"brightness": 100,
|
"brightness": 100,
|
||||||
"dev_name": "Wi-Fi Smart Dimmer with sensor",
|
"dev_name": "Wi-Fi Smart Dimmer with sensor",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
|
2
tests/fixtures/iot/KS230(US)_1.0_1.0.14.json
vendored
2
tests/fixtures/iot/KS230(US)_1.0_1.0.14.json
vendored
@ -14,7 +14,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "Test KS230",
|
"alias": "#MASKED_NAME#",
|
||||||
"brightness": 60,
|
"brightness": 60,
|
||||||
"dc_state": 0,
|
"dc_state": 0,
|
||||||
"dev_name": "Wi-Fi Smart 3-Way Dimmer",
|
"dev_name": "Wi-Fi Smart 3-Way Dimmer",
|
||||||
|
2
tests/fixtures/iot/LB110(US)_1.0_1.8.11.json
vendored
2
tests/fixtures/iot/LB110(US)_1.0_1.8.11.json
vendored
@ -21,7 +21,7 @@
|
|||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "none",
|
"active_mode": "none",
|
||||||
"alias": "TP-LINK_Smart Bulb_43EC",
|
"alias": "#MASKED_NAME#",
|
||||||
"ctrl_protocols": {
|
"ctrl_protocols": {
|
||||||
"name": "Linkie",
|
"name": "Linkie",
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
|
33
tests/fixtures/smart/EP25(US)_2.6_1.0.1.json
vendored
33
tests/fixtures/smart/EP25(US)_2.6_1.0.1.json
vendored
@ -84,21 +84,24 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"discovery_result": {
|
"discovery_result": {
|
||||||
"device_id": "00000000000000000000000000000000",
|
"error_code": 0,
|
||||||
"device_model": "EP25(US)",
|
"result": {
|
||||||
"device_type": "SMART.KASAPLUG",
|
"device_id": "00000000000000000000000000000000",
|
||||||
"factory_default": false,
|
"device_model": "EP25(US)",
|
||||||
"ip": "127.0.0.123",
|
"device_type": "SMART.KASAPLUG",
|
||||||
"is_support_iot_cloud": true,
|
"factory_default": false,
|
||||||
"mac": "00-00-00-00-00-00",
|
"ip": "127.0.0.123",
|
||||||
"mgt_encrypt_schm": {
|
"is_support_iot_cloud": true,
|
||||||
"encrypt_type": "AES",
|
"mac": "00-00-00-00-00-00",
|
||||||
"http_port": 80,
|
"mgt_encrypt_schm": {
|
||||||
"is_support_https": false,
|
"encrypt_type": "AES",
|
||||||
"lv": 2
|
"http_port": 80,
|
||||||
},
|
"is_support_https": false,
|
||||||
"obd_src": "tplink",
|
"lv": 2
|
||||||
"owner": "00000000000000000000000000000000"
|
},
|
||||||
|
"obd_src": "tplink",
|
||||||
|
"owner": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"get_antitheft_rules": {
|
"get_antitheft_rules": {
|
||||||
"antitheft_rule_max_count": 1,
|
"antitheft_rule_max_count": 1,
|
||||||
|
33
tests/fixtures/smart/EP25(US)_2.6_1.0.2.json
vendored
33
tests/fixtures/smart/EP25(US)_2.6_1.0.2.json
vendored
@ -88,21 +88,24 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"discovery_result": {
|
"discovery_result": {
|
||||||
"device_id": "00000000000000000000000000000000",
|
"error_code": 0,
|
||||||
"device_model": "EP25(US)",
|
"result": {
|
||||||
"device_type": "SMART.KASAPLUG",
|
"device_id": "00000000000000000000000000000000",
|
||||||
"factory_default": false,
|
"device_model": "EP25(US)",
|
||||||
"ip": "127.0.0.123",
|
"device_type": "SMART.KASAPLUG",
|
||||||
"is_support_iot_cloud": true,
|
"factory_default": false,
|
||||||
"mac": "3C-52-A1-00-00-00",
|
"ip": "127.0.0.123",
|
||||||
"mgt_encrypt_schm": {
|
"is_support_iot_cloud": true,
|
||||||
"encrypt_type": "AES",
|
"mac": "3C-52-A1-00-00-00",
|
||||||
"http_port": 80,
|
"mgt_encrypt_schm": {
|
||||||
"is_support_https": false,
|
"encrypt_type": "AES",
|
||||||
"lv": 2
|
"http_port": 80,
|
||||||
},
|
"is_support_https": false,
|
||||||
"obd_src": "tplink",
|
"lv": 2
|
||||||
"owner": "00000000000000000000000000000000"
|
},
|
||||||
|
"obd_src": "tplink",
|
||||||
|
"owner": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"get_antitheft_rules": {
|
"get_antitheft_rules": {
|
||||||
"antitheft_rule_max_count": 1,
|
"antitheft_rule_max_count": 1,
|
||||||
|
33
tests/fixtures/smart/EP40M(US)_1.0_1.1.0.json
vendored
33
tests/fixtures/smart/EP40M(US)_1.0_1.1.0.json
vendored
@ -379,21 +379,24 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"discovery_result": {
|
"discovery_result": {
|
||||||
"device_id": "00000000000000000000000000000000",
|
"error_code": 0,
|
||||||
"device_model": "EP40M(US)",
|
"result": {
|
||||||
"device_type": "SMART.KASAPLUG",
|
"device_id": "00000000000000000000000000000000",
|
||||||
"factory_default": false,
|
"device_model": "EP40M(US)",
|
||||||
"ip": "127.0.0.123",
|
"device_type": "SMART.KASAPLUG",
|
||||||
"is_support_iot_cloud": true,
|
"factory_default": false,
|
||||||
"mac": "F0-09-0D-00-00-00",
|
"ip": "127.0.0.123",
|
||||||
"mgt_encrypt_schm": {
|
"is_support_iot_cloud": true,
|
||||||
"encrypt_type": "KLAP",
|
"mac": "F0-09-0D-00-00-00",
|
||||||
"http_port": 80,
|
"mgt_encrypt_schm": {
|
||||||
"is_support_https": false,
|
"encrypt_type": "KLAP",
|
||||||
"lv": 2
|
"http_port": 80,
|
||||||
},
|
"is_support_https": false,
|
||||||
"obd_src": "matter",
|
"lv": 2
|
||||||
"owner": "00000000000000000000000000000000"
|
},
|
||||||
|
"obd_src": "matter",
|
||||||
|
"owner": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"get_auto_update_info": {
|
"get_auto_update_info": {
|
||||||
"enable": true,
|
"enable": true,
|
||||||
|
33
tests/fixtures/smart/H100(EU)_1.0_1.2.3.json
vendored
33
tests/fixtures/smart/H100(EU)_1.0_1.2.3.json
vendored
@ -84,21 +84,24 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"discovery_result": {
|
"discovery_result": {
|
||||||
"device_id": "00000000000000000000000000000000",
|
"error_code": 0,
|
||||||
"device_model": "H100(EU)",
|
"result": {
|
||||||
"device_type": "SMART.TAPOHUB",
|
"device_id": "00000000000000000000000000000000",
|
||||||
"factory_default": true,
|
"device_model": "H100(EU)",
|
||||||
"ip": "127.0.0.123",
|
"device_type": "SMART.TAPOHUB",
|
||||||
"is_support_iot_cloud": true,
|
"factory_default": true,
|
||||||
"mac": "3C-52-A1-00-00-00",
|
"ip": "127.0.0.123",
|
||||||
"mgt_encrypt_schm": {
|
"is_support_iot_cloud": true,
|
||||||
"encrypt_type": "AES",
|
"mac": "3C-52-A1-00-00-00",
|
||||||
"http_port": 80,
|
"mgt_encrypt_schm": {
|
||||||
"is_support_https": false,
|
"encrypt_type": "AES",
|
||||||
"lv": 2
|
"http_port": 80,
|
||||||
},
|
"is_support_https": false,
|
||||||
"obd_src": "tplink",
|
"lv": 2
|
||||||
"owner": ""
|
},
|
||||||
|
"obd_src": "tplink",
|
||||||
|
"owner": ""
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"get_auto_update_info": {
|
"get_auto_update_info": {
|
||||||
"enable": true,
|
"enable": true,
|
||||||
|
33
tests/fixtures/smart/H100(EU)_1.0_1.5.10.json
vendored
33
tests/fixtures/smart/H100(EU)_1.0_1.5.10.json
vendored
@ -96,21 +96,24 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"discovery_result": {
|
"discovery_result": {
|
||||||
"device_id": "00000000000000000000000000000000",
|
"error_code": 0,
|
||||||
"device_model": "H100(EU)",
|
"result": {
|
||||||
"device_type": "SMART.TAPOHUB",
|
"device_id": "00000000000000000000000000000000",
|
||||||
"factory_default": false,
|
"device_model": "H100(EU)",
|
||||||
"ip": "127.0.0.123",
|
"device_type": "SMART.TAPOHUB",
|
||||||
"is_support_iot_cloud": true,
|
"factory_default": false,
|
||||||
"mac": "3C-52-A1-00-00-00",
|
"ip": "127.0.0.123",
|
||||||
"mgt_encrypt_schm": {
|
"is_support_iot_cloud": true,
|
||||||
"encrypt_type": "AES",
|
"mac": "3C-52-A1-00-00-00",
|
||||||
"http_port": 80,
|
"mgt_encrypt_schm": {
|
||||||
"is_support_https": false,
|
"encrypt_type": "AES",
|
||||||
"lv": 2
|
"http_port": 80,
|
||||||
},
|
"is_support_https": false,
|
||||||
"obd_src": "tplink",
|
"lv": 2
|
||||||
"owner": "00000000000000000000000000000000"
|
},
|
||||||
|
"obd_src": "tplink",
|
||||||
|
"owner": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"get_alarm_configure": {
|
"get_alarm_configure": {
|
||||||
"duration": 10,
|
"duration": 10,
|
||||||
|
37
tests/fixtures/smart/H100(EU)_1.0_1.5.5.json
vendored
37
tests/fixtures/smart/H100(EU)_1.0_1.5.5.json
vendored
@ -92,21 +92,24 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"discovery_result": {
|
"discovery_result": {
|
||||||
"device_id": "00000000000000000000000000000000",
|
"error_code": 0,
|
||||||
"device_model": "H100(EU)",
|
"result": {
|
||||||
"device_type": "SMART.TAPOHUB",
|
"device_id": "00000000000000000000000000000000",
|
||||||
"factory_default": false,
|
"device_model": "H100(EU)",
|
||||||
"ip": "127.0.0.123",
|
"device_type": "SMART.TAPOHUB",
|
||||||
"is_support_iot_cloud": true,
|
"factory_default": false,
|
||||||
"mac": "3C-52-A1-00-00-00",
|
"ip": "127.0.0.123",
|
||||||
"mgt_encrypt_schm": {
|
"is_support_iot_cloud": true,
|
||||||
"encrypt_type": "AES",
|
"mac": "3C-52-A1-00-00-00",
|
||||||
"http_port": 80,
|
"mgt_encrypt_schm": {
|
||||||
"is_support_https": false,
|
"encrypt_type": "AES",
|
||||||
"lv": 2
|
"http_port": 80,
|
||||||
},
|
"is_support_https": false,
|
||||||
"obd_src": "tplink",
|
"lv": 2
|
||||||
"owner": "00000000000000000000000000000000"
|
},
|
||||||
|
"obd_src": "tplink",
|
||||||
|
"owner": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"get_alarm_configure": {
|
"get_alarm_configure": {
|
||||||
"duration": 10,
|
"duration": 10,
|
||||||
@ -195,7 +198,7 @@
|
|||||||
"ver_code": 1
|
"ver_code": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"device_id": "0000000000000000000000000000000000000000"
|
"device_id": "SCRUBBED_CHILD_DEVICE_ID_1"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"start_index": 0,
|
"start_index": 0,
|
||||||
@ -213,7 +216,7 @@
|
|||||||
"current_humidity_exception": -34,
|
"current_humidity_exception": -34,
|
||||||
"current_temp": 22.2,
|
"current_temp": 22.2,
|
||||||
"current_temp_exception": 0,
|
"current_temp_exception": 0,
|
||||||
"device_id": "0000000000000000000000000000000000000000",
|
"device_id": "SCRUBBED_CHILD_DEVICE_ID_1",
|
||||||
"fw_ver": "1.7.0 Build 230424 Rel.170332",
|
"fw_ver": "1.7.0 Build 230424 Rel.170332",
|
||||||
"hw_id": "00000000000000000000000000000000",
|
"hw_id": "00000000000000000000000000000000",
|
||||||
"hw_ver": "1.0",
|
"hw_ver": "1.0",
|
||||||
|
33
tests/fixtures/smart/HS200(US)_5.26_1.0.3.json
vendored
33
tests/fixtures/smart/HS200(US)_5.26_1.0.3.json
vendored
@ -80,21 +80,24 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"discovery_result": {
|
"discovery_result": {
|
||||||
"device_id": "00000000000000000000000000000000",
|
"error_code": 0,
|
||||||
"device_model": "HS200(US)",
|
"result": {
|
||||||
"device_type": "SMART.KASASWITCH",
|
"device_id": "00000000000000000000000000000000",
|
||||||
"factory_default": false,
|
"device_model": "HS200(US)",
|
||||||
"ip": "127.0.0.123",
|
"device_type": "SMART.KASASWITCH",
|
||||||
"is_support_iot_cloud": true,
|
"factory_default": false,
|
||||||
"mac": "74-FE-CE-00-00-00",
|
"ip": "127.0.0.123",
|
||||||
"mgt_encrypt_schm": {
|
"is_support_iot_cloud": true,
|
||||||
"encrypt_type": "KLAP",
|
"mac": "74-FE-CE-00-00-00",
|
||||||
"http_port": 80,
|
"mgt_encrypt_schm": {
|
||||||
"is_support_https": false,
|
"encrypt_type": "KLAP",
|
||||||
"lv": 2
|
"http_port": 80,
|
||||||
},
|
"is_support_https": false,
|
||||||
"obd_src": "tplink",
|
"lv": 2
|
||||||
"owner": "00000000000000000000000000000000"
|
},
|
||||||
|
"obd_src": "tplink",
|
||||||
|
"owner": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"get_antitheft_rules": {
|
"get_antitheft_rules": {
|
||||||
"antitheft_rule_max_count": 1,
|
"antitheft_rule_max_count": 1,
|
||||||
|
31
tests/fixtures/smart/HS220(US)_3.26_1.0.1.json
vendored
31
tests/fixtures/smart/HS220(US)_3.26_1.0.1.json
vendored
@ -100,20 +100,23 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"discovery_result": {
|
"discovery_result": {
|
||||||
"device_id": "00000000000000000000000000000000",
|
"error_code": 0,
|
||||||
"owner": "00000000000000000000000000000000",
|
"result": {
|
||||||
"device_type": "SMART.KASASWITCH",
|
"device_id": "00000000000000000000000000000000",
|
||||||
"device_model": "HS220(US)",
|
"device_model": "HS220(US)",
|
||||||
"ip": "127.0.0.123",
|
"device_type": "SMART.KASASWITCH",
|
||||||
"mac": "24-2F-D0-00-00-00",
|
"factory_default": false,
|
||||||
"is_support_iot_cloud": true,
|
"ip": "127.0.0.123",
|
||||||
"obd_src": "tplink",
|
"is_support_iot_cloud": true,
|
||||||
"factory_default": false,
|
"mac": "24-2F-D0-00-00-00",
|
||||||
"mgt_encrypt_schm": {
|
"mgt_encrypt_schm": {
|
||||||
"is_support_https": false,
|
"encrypt_type": "AES",
|
||||||
"encrypt_type": "AES",
|
"http_port": 80,
|
||||||
"http_port": 80,
|
"is_support_https": false,
|
||||||
"lv": 2
|
"lv": 2
|
||||||
|
},
|
||||||
|
"obd_src": "tplink",
|
||||||
|
"owner": "00000000000000000000000000000000"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"get_antitheft_rules": {
|
"get_antitheft_rules": {
|
||||||
|
33
tests/fixtures/smart/KH100(EU)_1.0_1.2.3.json
vendored
33
tests/fixtures/smart/KH100(EU)_1.0_1.2.3.json
vendored
@ -84,21 +84,24 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"discovery_result": {
|
"discovery_result": {
|
||||||
"device_id": "00000000000000000000000000000000",
|
"error_code": 0,
|
||||||
"device_model": "KH100(EU)",
|
"result": {
|
||||||
"device_type": "SMART.KASAHUB",
|
"device_id": "00000000000000000000000000000000",
|
||||||
"factory_default": false,
|
"device_model": "KH100(EU)",
|
||||||
"ip": "127.0.0.123",
|
"device_type": "SMART.KASAHUB",
|
||||||
"is_support_iot_cloud": true,
|
"factory_default": false,
|
||||||
"mac": "A8-42-A1-00-00-00",
|
"ip": "127.0.0.123",
|
||||||
"mgt_encrypt_schm": {
|
"is_support_iot_cloud": true,
|
||||||
"encrypt_type": "AES",
|
"mac": "A8-42-A1-00-00-00",
|
||||||
"http_port": 80,
|
"mgt_encrypt_schm": {
|
||||||
"is_support_https": false,
|
"encrypt_type": "AES",
|
||||||
"lv": 2
|
"http_port": 80,
|
||||||
},
|
"is_support_https": false,
|
||||||
"obd_src": "tplink",
|
"lv": 2
|
||||||
"owner": "00000000000000000000000000000000"
|
},
|
||||||
|
"obd_src": "tplink",
|
||||||
|
"owner": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"get_alarm_configure": {
|
"get_alarm_configure": {
|
||||||
"duration": 300,
|
"duration": 300,
|
||||||
|
33
tests/fixtures/smart/KH100(EU)_1.0_1.5.12.json
vendored
33
tests/fixtures/smart/KH100(EU)_1.0_1.5.12.json
vendored
@ -88,21 +88,24 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"discovery_result": {
|
"discovery_result": {
|
||||||
"device_id": "00000000000000000000000000000000",
|
"error_code": 0,
|
||||||
"device_model": "KH100(EU)",
|
"result": {
|
||||||
"device_type": "SMART.KASAHUB",
|
"device_id": "00000000000000000000000000000000",
|
||||||
"factory_default": false,
|
"device_model": "KH100(EU)",
|
||||||
"ip": "127.0.0.123",
|
"device_type": "SMART.KASAHUB",
|
||||||
"is_support_iot_cloud": true,
|
"factory_default": false,
|
||||||
"mac": "A8-42-A1-00-00-00",
|
"ip": "127.0.0.123",
|
||||||
"mgt_encrypt_schm": {
|
"is_support_iot_cloud": true,
|
||||||
"encrypt_type": "KLAP",
|
"mac": "A8-42-A1-00-00-00",
|
||||||
"http_port": 80,
|
"mgt_encrypt_schm": {
|
||||||
"is_support_https": false,
|
"encrypt_type": "KLAP",
|
||||||
"lv": 2
|
"http_port": 80,
|
||||||
},
|
"is_support_https": false,
|
||||||
"obd_src": "tplink",
|
"lv": 2
|
||||||
"owner": "00000000000000000000000000000000"
|
},
|
||||||
|
"obd_src": "tplink",
|
||||||
|
"owner": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"get_alarm_configure": {
|
"get_alarm_configure": {
|
||||||
"duration": 300,
|
"duration": 300,
|
||||||
|
35
tests/fixtures/smart/KH100(UK)_1.0_1.5.6.json
vendored
35
tests/fixtures/smart/KH100(UK)_1.0_1.5.6.json
vendored
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"component_nego": {
|
"component_nego": {
|
||||||
"component_list": [
|
"component_list": [
|
||||||
{
|
{
|
||||||
@ -88,21 +88,24 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"discovery_result": {
|
"discovery_result": {
|
||||||
"device_id": "00000000000000000000000000000000",
|
"error_code": 0,
|
||||||
"device_model": "KH100(UK)",
|
"result": {
|
||||||
"device_type": "SMART.KASAHUB",
|
"device_id": "00000000000000000000000000000000",
|
||||||
"factory_default": false,
|
"device_model": "KH100(UK)",
|
||||||
"ip": "127.0.0.123",
|
"device_type": "SMART.KASAHUB",
|
||||||
"is_support_iot_cloud": true,
|
"factory_default": false,
|
||||||
"mac": "F0-A7-31-00-00-00",
|
"ip": "127.0.0.123",
|
||||||
"mgt_encrypt_schm": {
|
"is_support_iot_cloud": true,
|
||||||
"encrypt_type": "AES",
|
"mac": "F0-A7-31-00-00-00",
|
||||||
"http_port": 80,
|
"mgt_encrypt_schm": {
|
||||||
"is_support_https": false,
|
"encrypt_type": "AES",
|
||||||
"lv": 2
|
"http_port": 80,
|
||||||
},
|
"is_support_https": false,
|
||||||
"obd_src": "tplink",
|
"lv": 2
|
||||||
"owner": "00000000000000000000000000000000"
|
},
|
||||||
|
"obd_src": "tplink",
|
||||||
|
"owner": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"get_alarm_configure": {
|
"get_alarm_configure": {
|
||||||
"duration": 300,
|
"duration": 300,
|
||||||
|
37
tests/fixtures/smart/KP125M(US)_1.0_1.1.3.json
vendored
37
tests/fixtures/smart/KP125M(US)_1.0_1.1.3.json
vendored
@ -84,21 +84,24 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"discovery_result": {
|
"discovery_result": {
|
||||||
"device_id": "00000000000000000000000000000000",
|
"error_code": 0,
|
||||||
"device_model": "KP125M(US)",
|
"result": {
|
||||||
"device_type": "SMART.KASAPLUG",
|
"device_id": "00000000000000000000000000000000",
|
||||||
"factory_default": false,
|
"device_model": "KP125M(US)",
|
||||||
"ip": "127.0.0.123",
|
"device_type": "SMART.KASAPLUG",
|
||||||
"is_support_iot_cloud": true,
|
"factory_default": false,
|
||||||
"mac": "00-00-00-00-00-00",
|
"ip": "127.0.0.123",
|
||||||
"mgt_encrypt_schm": {
|
"is_support_iot_cloud": true,
|
||||||
"encrypt_type": "AES",
|
"mac": "00-00-00-00-00-00",
|
||||||
"http_port": 80,
|
"mgt_encrypt_schm": {
|
||||||
"is_support_https": false,
|
"encrypt_type": "AES",
|
||||||
"lv": 2
|
"http_port": 80,
|
||||||
},
|
"is_support_https": false,
|
||||||
"obd_src": "tplink",
|
"lv": 2
|
||||||
"owner": "00000000000000000000000000000000"
|
},
|
||||||
|
"obd_src": "tplink",
|
||||||
|
"owner": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"get_current_power": {
|
"get_current_power": {
|
||||||
"current_power": 17
|
"current_power": 17
|
||||||
@ -124,7 +127,7 @@
|
|||||||
"longitude": 0,
|
"longitude": 0,
|
||||||
"mac": "00-00-00-00-00-00",
|
"mac": "00-00-00-00-00-00",
|
||||||
"model": "KP125M",
|
"model": "KP125M",
|
||||||
"nickname": "IyNNQVNLRUROQU1FIyM=",
|
"nickname": "I01BU0tFRF9OQU1FIw==",
|
||||||
"oem_id": "00000000000000000000000000000000",
|
"oem_id": "00000000000000000000000000000000",
|
||||||
"on_time": 5332,
|
"on_time": 5332,
|
||||||
"overheated": false,
|
"overheated": false,
|
||||||
@ -133,7 +136,7 @@
|
|||||||
"rssi": -62,
|
"rssi": -62,
|
||||||
"signal_level": 2,
|
"signal_level": 2,
|
||||||
"specs": "",
|
"specs": "",
|
||||||
"ssid": "IyNNQVNLRUROQU1FIyM=",
|
"ssid": "I01BU0tFRF9TU0lEIw==",
|
||||||
"time_diff": -360,
|
"time_diff": -360,
|
||||||
"type": "SMART.KASAPLUG"
|
"type": "SMART.KASAPLUG"
|
||||||
},
|
},
|
||||||
|
33
tests/fixtures/smart/KP125M(US)_1.0_1.2.3.json
vendored
33
tests/fixtures/smart/KP125M(US)_1.0_1.2.3.json
vendored
@ -88,21 +88,24 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"discovery_result": {
|
"discovery_result": {
|
||||||
"device_id": "00000000000000000000000000000000",
|
"error_code": 0,
|
||||||
"device_model": "KP125M(US)",
|
"result": {
|
||||||
"device_type": "SMART.KASAPLUG",
|
"device_id": "00000000000000000000000000000000",
|
||||||
"factory_default": false,
|
"device_model": "KP125M(US)",
|
||||||
"ip": "127.0.0.123",
|
"device_type": "SMART.KASAPLUG",
|
||||||
"is_support_iot_cloud": true,
|
"factory_default": false,
|
||||||
"mac": "78-8C-B5-00-00-00",
|
"ip": "127.0.0.123",
|
||||||
"mgt_encrypt_schm": {
|
"is_support_iot_cloud": true,
|
||||||
"encrypt_type": "KLAP",
|
"mac": "78-8C-B5-00-00-00",
|
||||||
"http_port": 80,
|
"mgt_encrypt_schm": {
|
||||||
"is_support_https": false,
|
"encrypt_type": "KLAP",
|
||||||
"lv": 2
|
"http_port": 80,
|
||||||
},
|
"is_support_https": false,
|
||||||
"obd_src": "tplink",
|
"lv": 2
|
||||||
"owner": "00000000000000000000000000000000"
|
},
|
||||||
|
"obd_src": "tplink",
|
||||||
|
"owner": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"get_antitheft_rules": {
|
"get_antitheft_rules": {
|
||||||
"antitheft_rule_max_count": 1,
|
"antitheft_rule_max_count": 1,
|
||||||
|
33
tests/fixtures/smart/KS205(US)_1.0_1.0.2.json
vendored
33
tests/fixtures/smart/KS205(US)_1.0_1.0.2.json
vendored
@ -80,21 +80,24 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"discovery_result": {
|
"discovery_result": {
|
||||||
"device_id": "00000000000000000000000000000000",
|
"error_code": 0,
|
||||||
"device_model": "KS205(US)",
|
"result": {
|
||||||
"device_type": "SMART.KASASWITCH",
|
"device_id": "00000000000000000000000000000000",
|
||||||
"factory_default": false,
|
"device_model": "KS205(US)",
|
||||||
"ip": "127.0.0.123",
|
"device_type": "SMART.KASASWITCH",
|
||||||
"is_support_iot_cloud": true,
|
"factory_default": false,
|
||||||
"mac": "00-00-00-00-00-00",
|
"ip": "127.0.0.123",
|
||||||
"mgt_encrypt_schm": {
|
"is_support_iot_cloud": true,
|
||||||
"encrypt_type": "AES",
|
"mac": "00-00-00-00-00-00",
|
||||||
"http_port": 80,
|
"mgt_encrypt_schm": {
|
||||||
"is_support_https": false,
|
"encrypt_type": "AES",
|
||||||
"lv": 2
|
"http_port": 80,
|
||||||
},
|
"is_support_https": false,
|
||||||
"obd_src": "tplink",
|
"lv": 2
|
||||||
"owner": "00000000000000000000000000000000"
|
},
|
||||||
|
"obd_src": "tplink",
|
||||||
|
"owner": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"get_antitheft_rules": {
|
"get_antitheft_rules": {
|
||||||
"antitheft_rule_max_count": 1,
|
"antitheft_rule_max_count": 1,
|
||||||
|
33
tests/fixtures/smart/KS205(US)_1.0_1.1.0.json
vendored
33
tests/fixtures/smart/KS205(US)_1.0_1.1.0.json
vendored
@ -76,21 +76,24 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"discovery_result": {
|
"discovery_result": {
|
||||||
"device_id": "00000000000000000000000000000000",
|
"error_code": 0,
|
||||||
"device_model": "KS205(US)",
|
"result": {
|
||||||
"device_type": "SMART.KASASWITCH",
|
"device_id": "00000000000000000000000000000000",
|
||||||
"factory_default": false,
|
"device_model": "KS205(US)",
|
||||||
"ip": "127.0.0.123",
|
"device_type": "SMART.KASASWITCH",
|
||||||
"is_support_iot_cloud": true,
|
"factory_default": false,
|
||||||
"mac": "40-ED-00-00-00-00",
|
"ip": "127.0.0.123",
|
||||||
"mgt_encrypt_schm": {
|
"is_support_iot_cloud": true,
|
||||||
"encrypt_type": "KLAP",
|
"mac": "40-ED-00-00-00-00",
|
||||||
"http_port": 80,
|
"mgt_encrypt_schm": {
|
||||||
"is_support_https": false,
|
"encrypt_type": "KLAP",
|
||||||
"lv": 2
|
"http_port": 80,
|
||||||
},
|
"is_support_https": false,
|
||||||
"obd_src": "tplink",
|
"lv": 2
|
||||||
"owner": ""
|
},
|
||||||
|
"obd_src": "tplink",
|
||||||
|
"owner": ""
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"get_antitheft_rules": {
|
"get_antitheft_rules": {
|
||||||
"antitheft_rule_max_count": 1,
|
"antitheft_rule_max_count": 1,
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user