mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-04-27 00:56:23 +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,
|
Executing this script will several modules and methods one by one,
|
||||||
and finally execute a query to query all of them at once.
|
and finally execute a query to query all of them at once.
|
||||||
"""
|
"""
|
||||||
import asyncio
|
|
||||||
import collections.abc
|
import collections.abc
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
@ -15,9 +14,10 @@ import re
|
|||||||
from collections import defaultdict, namedtuple
|
from collections import defaultdict, namedtuple
|
||||||
from pprint import pprint
|
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")
|
Call = namedtuple("Call", "module method")
|
||||||
|
|
||||||
@ -35,6 +35,13 @@ def scrub(res):
|
|||||||
"longitude_i",
|
"longitude_i",
|
||||||
"latitude",
|
"latitude",
|
||||||
"longitude",
|
"longitude",
|
||||||
|
"owner",
|
||||||
|
"device_id",
|
||||||
|
"ip",
|
||||||
|
"ssid",
|
||||||
|
"hw_id",
|
||||||
|
"fw_id",
|
||||||
|
"oem_id",
|
||||||
]
|
]
|
||||||
|
|
||||||
for k, v in res.items():
|
for k, v in res.items():
|
||||||
@ -44,6 +51,8 @@ def scrub(res):
|
|||||||
if k in keys_to_scrub:
|
if k in keys_to_scrub:
|
||||||
if k in ["latitude", "latitude_i", "longitude", "longitude_i"]:
|
if k in ["latitude", "latitude_i", "longitude", "longitude_i"]:
|
||||||
v = 0
|
v = 0
|
||||||
|
elif k in ["ip"]:
|
||||||
|
v = "127.0.0.123"
|
||||||
else:
|
else:
|
||||||
v = re.sub(r"\w", "0", v)
|
v = re.sub(r"\w", "0", v)
|
||||||
|
|
||||||
@ -63,8 +72,22 @@ def default_to_regular(d):
|
|||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
@click.argument("host")
|
@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)
|
@click.option("-d", "--debug", is_flag=True)
|
||||||
def cli(host, debug):
|
async def cli(host, debug, username, password):
|
||||||
"""Generate devinfo file for given device."""
|
"""Generate devinfo file for given device."""
|
||||||
if debug:
|
if debug:
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
@ -83,15 +106,15 @@ def cli(host, debug):
|
|||||||
|
|
||||||
successes = []
|
successes = []
|
||||||
|
|
||||||
|
credentials = Credentials(username=username, password=password)
|
||||||
|
device = await Discover.discover_single(host, credentials=credentials)
|
||||||
|
|
||||||
for test_call in items:
|
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:
|
try:
|
||||||
click.echo(f"Testing {test_call}..", nl=False)
|
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]
|
resp = info[test_call.module]
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
click.echo(click.style(f"FAIL {ex}", fg="red"))
|
click.echo(click.style(f"FAIL {ex}", fg="red"))
|
||||||
@ -111,12 +134,8 @@ def cli(host, debug):
|
|||||||
|
|
||||||
final = default_to_regular(final)
|
final = default_to_regular(final)
|
||||||
|
|
||||||
async def _run_final_query():
|
|
||||||
protocol = TPLinkSmartHomeProtocol(host)
|
|
||||||
return await protocol.query(final_query)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
final = asyncio.run(_run_final_query())
|
final = await device.protocol.query(final_query)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
click.echo(
|
click.echo(
|
||||||
click.style(
|
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("Got %s successes" % len(successes))
|
||||||
click.echo(click.style("## device info file ##", bold=True))
|
click.echo(click.style("## device info file ##", bold=True))
|
||||||
|
|
||||||
|
@ -423,7 +423,7 @@ class DiscoveryResult(BaseModel):
|
|||||||
mac: str
|
mac: str
|
||||||
mgt_encrypt_schm: EncryptionScheme
|
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")
|
owner: Optional[str] = Field(default=None, alias="device_owner_hash")
|
||||||
hw_ver: Optional[str] = None
|
hw_ver: Optional[str] = None
|
||||||
is_support_iot_cloud: Optional[bool] = None
|
is_support_iot_cloud: Optional[bool] = None
|
||||||
|
@ -211,6 +211,7 @@ class SmartDevice:
|
|||||||
# checks in accessors. the @updated_required decorator does not ensure
|
# checks in accessors. the @updated_required decorator does not ensure
|
||||||
# mypy that these are not accessed incorrectly.
|
# mypy that these are not accessed incorrectly.
|
||||||
self._last_update: Any = None
|
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._sys_info: Any = None # TODO: this is here to avoid changing tests
|
||||||
self._features: Set[str] = set()
|
self._features: Set[str] = set()
|
||||||
@ -371,6 +372,7 @@ class SmartDevice:
|
|||||||
# This allows setting of some info properties directly
|
# This allows setting of some info properties directly
|
||||||
# from partial discovery info that will then be found
|
# from partial discovery info that will then be found
|
||||||
# by the requires_update decorator
|
# by the requires_update decorator
|
||||||
|
self._discovery_info = info
|
||||||
self._set_sys_info(info)
|
self._set_sys_info(info)
|
||||||
|
|
||||||
def _set_sys_info(self, sys_info: Dict[str, Any]) -> None:
|
def _set_sys_info(self, sys_info: Dict[str, Any]) -> None:
|
||||||
|
45
kasa/tests/fixtures/HS100(UK)_4.1_1.1.0.json
vendored
45
kasa/tests/fixtures/HS100(UK)_4.1_1.1.0.json
vendored
@ -1,43 +1,46 @@
|
|||||||
{
|
{
|
||||||
"emeter": {
|
"discovery_result": {
|
||||||
"err_code": -1,
|
"device_id": "00000000000000000000000000000000",
|
||||||
"err_msg": "module not support"
|
"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
|
||||||
},
|
},
|
||||||
"smartlife.iot.common.emeter": {
|
"owner": "00000000000000000000000000000000"
|
||||||
"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"
|
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"get_sysinfo": {
|
"get_sysinfo": {
|
||||||
"active_mode": "schedule",
|
"active_mode": "none",
|
||||||
"alias": "Unused 3",
|
"alias": "Bedroom Lamp 2",
|
||||||
"dev_name": "Smart Wi-Fi Plug",
|
"dev_name": "Smart Wi-Fi Plug",
|
||||||
"deviceId": "0000000000000000000000000000000000000000",
|
"deviceId": "0000000000000000000000000000000000000000",
|
||||||
"err_code": 0,
|
"err_code": 0,
|
||||||
"feature": "TIM",
|
"feature": "TIM",
|
||||||
"fwId": "00000000000000000000000000000000",
|
|
||||||
"hwId": "00000000000000000000000000000000",
|
"hwId": "00000000000000000000000000000000",
|
||||||
"hw_ver": "4.1",
|
"hw_ver": "4.1",
|
||||||
"icon_hash": "",
|
"icon_hash": "",
|
||||||
"latitude": 0,
|
"latitude_i": 0,
|
||||||
"led_off": 0,
|
"led_off": 0,
|
||||||
"longitude": 0,
|
"longitude_i": 0,
|
||||||
"mac": "00:00:00:00:00:00",
|
"mac": "00:00:00:00:00:00",
|
||||||
|
"mic_type": "IOT.SMARTPLUGSWITCH",
|
||||||
"model": "HS100(UK)",
|
"model": "HS100(UK)",
|
||||||
|
"next_action": {
|
||||||
|
"type": -1
|
||||||
|
},
|
||||||
|
"ntc_state": 0,
|
||||||
"oemId": "00000000000000000000000000000000",
|
"oemId": "00000000000000000000000000000000",
|
||||||
"on_time": 0,
|
"on_time": 0,
|
||||||
"relay_state": 0,
|
"relay_state": 0,
|
||||||
"rssi": -63,
|
"rssi": -66,
|
||||||
|
"status": "new",
|
||||||
"sw_ver": "1.1.0 Build 201016 Rel.175121",
|
"sw_ver": "1.1.0 Build 201016 Rel.175121",
|
||||||
"type": "IOT.SMARTPLUGSWITCH",
|
|
||||||
"updating": 0
|
"updating": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,6 +294,7 @@ class FakeTransportProtocol(TPLinkSmartHomeProtocol):
|
|||||||
|
|
||||||
for target in info:
|
for target in info:
|
||||||
# print("target %s" % target)
|
# print("target %s" % target)
|
||||||
|
if target != "discovery_result":
|
||||||
for cmd in info[target]:
|
for cmd in info[target]:
|
||||||
# print("initializing tgt %s cmd %s" % (target, cmd))
|
# print("initializing tgt %s cmd %s" % (target, cmd))
|
||||||
proto[target][cmd] = info[target][cmd]
|
proto[target][cmd] = info[target][cmd]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user