mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-22 11:13:34 +00:00
Update dump_devinfo to include 20002 discovery results (#556)
* Fix dump_devinfo and add discovery_result to json * Update following review. Do not serialize aliases. * Delete kasa/tests/fixtures/HS100(UK)_1.0_1.2.6.json
This commit is contained in:
parent
9728866afb
commit
9de3f69033
@ -7,7 +7,6 @@ If you have new, yet unsupported device or a device with no devinfo file under
|
||||
Executing this script will several modules and methods one by one,
|
||||
and finally execute a query to query all of them at once.
|
||||
"""
|
||||
import asyncio
|
||||
import collections.abc
|
||||
import json
|
||||
import logging
|
||||
@ -15,9 +14,10 @@ import re
|
||||
from collections import defaultdict, namedtuple
|
||||
from pprint import pprint
|
||||
|
||||
import click
|
||||
import asyncclick as click
|
||||
|
||||
from kasa import TPLinkSmartHomeProtocol
|
||||
from kasa import Credentials, Discover
|
||||
from kasa.discover import DiscoveryResult
|
||||
|
||||
Call = namedtuple("Call", "module method")
|
||||
|
||||
@ -35,6 +35,13 @@ def scrub(res):
|
||||
"longitude_i",
|
||||
"latitude",
|
||||
"longitude",
|
||||
"owner",
|
||||
"device_id",
|
||||
"ip",
|
||||
"ssid",
|
||||
"hw_id",
|
||||
"fw_id",
|
||||
"oem_id",
|
||||
]
|
||||
|
||||
for k, v in res.items():
|
||||
@ -44,6 +51,8 @@ def scrub(res):
|
||||
if k in keys_to_scrub:
|
||||
if k in ["latitude", "latitude_i", "longitude", "longitude_i"]:
|
||||
v = 0
|
||||
elif k in ["ip"]:
|
||||
v = "127.0.0.123"
|
||||
else:
|
||||
v = re.sub(r"\w", "0", v)
|
||||
|
||||
@ -63,8 +72,22 @@ def default_to_regular(d):
|
||||
|
||||
@click.command()
|
||||
@click.argument("host")
|
||||
@click.option(
|
||||
"--username",
|
||||
default=None,
|
||||
required=False,
|
||||
envvar="TPLINK_CLOUD_USERNAME",
|
||||
help="Username/email address to authenticate to device.",
|
||||
)
|
||||
@click.option(
|
||||
"--password",
|
||||
default=None,
|
||||
required=False,
|
||||
envvar="TPLINK_CLOUD_PASSWORD",
|
||||
help="Password to use to authenticate to device.",
|
||||
)
|
||||
@click.option("-d", "--debug", is_flag=True)
|
||||
def cli(host, debug):
|
||||
async def cli(host, debug, username, password):
|
||||
"""Generate devinfo file for given device."""
|
||||
if debug:
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
@ -83,15 +106,15 @@ def cli(host, debug):
|
||||
|
||||
successes = []
|
||||
|
||||
credentials = Credentials(username=username, password=password)
|
||||
device = await Discover.discover_single(host, credentials=credentials)
|
||||
|
||||
for test_call in items:
|
||||
|
||||
async def _run_query(test_call):
|
||||
protocol = TPLinkSmartHomeProtocol(host)
|
||||
return await protocol.query({test_call.module: {test_call.method: None}})
|
||||
|
||||
try:
|
||||
click.echo(f"Testing {test_call}..", nl=False)
|
||||
info = asyncio.run(_run_query(test_call))
|
||||
info = await device.protocol.query(
|
||||
{test_call.module: {test_call.method: None}}
|
||||
)
|
||||
resp = info[test_call.module]
|
||||
except Exception as ex:
|
||||
click.echo(click.style(f"FAIL {ex}", fg="red"))
|
||||
@ -111,12 +134,8 @@ def cli(host, debug):
|
||||
|
||||
final = default_to_regular(final)
|
||||
|
||||
async def _run_final_query():
|
||||
protocol = TPLinkSmartHomeProtocol(host)
|
||||
return await protocol.query(final_query)
|
||||
|
||||
try:
|
||||
final = asyncio.run(_run_final_query())
|
||||
final = await device.protocol.query(final_query)
|
||||
except Exception as ex:
|
||||
click.echo(
|
||||
click.style(
|
||||
@ -124,6 +143,14 @@ def cli(host, debug):
|
||||
)
|
||||
)
|
||||
|
||||
if device._discovery_info:
|
||||
# Need to recreate a DiscoverResult here because we don't want the aliases
|
||||
# in the fixture, we want the actual field names as returned by the device.
|
||||
dr = DiscoveryResult(**device._discovery_info)
|
||||
final["discovery_result"] = dr.dict(
|
||||
by_alias=False, exclude_unset=True, exclude_none=True, exclude_defaults=True
|
||||
)
|
||||
|
||||
click.echo("Got %s successes" % len(successes))
|
||||
click.echo(click.style("## device info file ##", bold=True))
|
||||
|
||||
|
@ -423,7 +423,7 @@ class DiscoveryResult(BaseModel):
|
||||
mac: str
|
||||
mgt_encrypt_schm: EncryptionScheme
|
||||
|
||||
device_id: Optional[str] = Field(default=None, alias="device_type_hash")
|
||||
device_id: Optional[str] = Field(default=None, alias="device_id_hash")
|
||||
owner: Optional[str] = Field(default=None, alias="device_owner_hash")
|
||||
hw_ver: Optional[str] = None
|
||||
is_support_iot_cloud: Optional[bool] = None
|
||||
|
@ -211,6 +211,7 @@ class SmartDevice:
|
||||
# checks in accessors. the @updated_required decorator does not ensure
|
||||
# mypy that these are not accessed incorrectly.
|
||||
self._last_update: Any = None
|
||||
self._discovery_info: Optional[Dict[str, Any]] = None
|
||||
|
||||
self._sys_info: Any = None # TODO: this is here to avoid changing tests
|
||||
self._features: Set[str] = set()
|
||||
@ -371,6 +372,7 @@ class SmartDevice:
|
||||
# This allows setting of some info properties directly
|
||||
# from partial discovery info that will then be found
|
||||
# by the requires_update decorator
|
||||
self._discovery_info = info
|
||||
self._set_sys_info(info)
|
||||
|
||||
def _set_sys_info(self, sys_info: Dict[str, Any]) -> None:
|
||||
|
47
kasa/tests/fixtures/HS100(UK)_4.1_1.1.0.json
vendored
47
kasa/tests/fixtures/HS100(UK)_4.1_1.1.0.json
vendored
@ -1,43 +1,46 @@
|
||||
{
|
||||
"emeter": {
|
||||
"err_code": -1,
|
||||
"err_msg": "module not support"
|
||||
},
|
||||
"smartlife.iot.common.emeter": {
|
||||
"err_code": -1,
|
||||
"err_msg": "module not support"
|
||||
},
|
||||
"smartlife.iot.dimmer": {
|
||||
"err_code": -1,
|
||||
"err_msg": "module not support"
|
||||
},
|
||||
"smartlife.iot.smartbulb.lightingservice": {
|
||||
"err_code": -1,
|
||||
"err_msg": "module not support"
|
||||
"discovery_result": {
|
||||
"device_id": "00000000000000000000000000000000",
|
||||
"device_model": "HS100(UK)",
|
||||
"device_type": "IOT.SMARTPLUGSWITCH",
|
||||
"factory_default": true,
|
||||
"hw_ver": "4.1",
|
||||
"ip": "127.0.0.123",
|
||||
"mac": "00-00-00-00-00-00",
|
||||
"mgt_encrypt_schm": {
|
||||
"encrypt_type": "KLAP",
|
||||
"http_port": 80,
|
||||
"is_support_https": false
|
||||
},
|
||||
"owner": "00000000000000000000000000000000"
|
||||
},
|
||||
"system": {
|
||||
"get_sysinfo": {
|
||||
"active_mode": "schedule",
|
||||
"alias": "Unused 3",
|
||||
"active_mode": "none",
|
||||
"alias": "Bedroom Lamp 2",
|
||||
"dev_name": "Smart Wi-Fi Plug",
|
||||
"deviceId": "0000000000000000000000000000000000000000",
|
||||
"err_code": 0,
|
||||
"feature": "TIM",
|
||||
"fwId": "00000000000000000000000000000000",
|
||||
"hwId": "00000000000000000000000000000000",
|
||||
"hw_ver": "4.1",
|
||||
"icon_hash": "",
|
||||
"latitude": 0,
|
||||
"latitude_i": 0,
|
||||
"led_off": 0,
|
||||
"longitude": 0,
|
||||
"longitude_i": 0,
|
||||
"mac": "00:00:00:00:00:00",
|
||||
"mic_type": "IOT.SMARTPLUGSWITCH",
|
||||
"model": "HS100(UK)",
|
||||
"next_action": {
|
||||
"type": -1
|
||||
},
|
||||
"ntc_state": 0,
|
||||
"oemId": "00000000000000000000000000000000",
|
||||
"on_time": 0,
|
||||
"relay_state": 0,
|
||||
"rssi": -63,
|
||||
"rssi": -66,
|
||||
"status": "new",
|
||||
"sw_ver": "1.1.0 Build 201016 Rel.175121",
|
||||
"type": "IOT.SMARTPLUGSWITCH",
|
||||
"updating": 0
|
||||
}
|
||||
}
|
||||
|
@ -294,9 +294,10 @@ class FakeTransportProtocol(TPLinkSmartHomeProtocol):
|
||||
|
||||
for target in info:
|
||||
# print("target %s" % target)
|
||||
for cmd in info[target]:
|
||||
# print("initializing tgt %s cmd %s" % (target, cmd))
|
||||
proto[target][cmd] = info[target][cmd]
|
||||
if target != "discovery_result":
|
||||
for cmd in info[target]:
|
||||
# print("initializing tgt %s cmd %s" % (target, cmd))
|
||||
proto[target][cmd] = info[target][cmd]
|
||||
# if we have emeter support, we need to add the missing pieces
|
||||
for module in ["emeter", "smartlife.iot.common.emeter"]:
|
||||
if (
|
||||
|
Loading…
Reference in New Issue
Block a user