8000 Update dump_devinfo to include 20002 discovery results by sdb9696 · Pull Request #556 · python-kasa/python-kasa · GitHub
[go: up one dir, main page]

Skip to content

Update dump_devinfo to include 20002 discovery results #556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 42 additions & 15 deletions devtools/dump_devinfo.py
< 8000 td id="diff-942f6b87f2ce42051a8565e3d27362e8cc929b749d886d8ffb69686018ab7446R120" data-line-number="120" class="blob-num blob-num-context js-linkable-line-number js-blob-rnum">
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@
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
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")

Expand All @@ -35,6 +35,13 @@ def scrub(res):
"longitude_i",
"latitude",
"longitude",
"owner",
"device_id",
"ip",
"ssid",
"hw_id",
"fw_id",
"oem_id",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me for now, but we will probably want to move the list of keys to scrub (including the ones below) into the library itself. This will allow removing the hardcoded list from homeassistant integration: https://github.com/home-assistant/core/blob/b36ddaa15c5975fbae36e2b4eef9721ef45f1a35/homeassistant/components/tplink/diagnostics.py#L14

]

for k, v in res.items():
Expand All @@ -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)

Expand All @@ -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)
Expand All @@ -83,15 +106,15 @@ def cli(host, debug):

successes = []

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}})
credentials = Credentials(username=username, password=password)
device = await Discover.discover_single(host, credentials=credentials)

for test_call in items:
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"))
Expand All @@ -111,19 +134,23 @@ async def _run_query(test_call):

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(
f"Unable to query all successes at once: {ex}", bold=True, fg="red"
)
)

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))

Expand Down
2 changes: 1 addition & 1 deletion kasa/discover.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ class EncryptionScheme(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
Expand Down
2 changes: 2 additions & 0 deletions kasa/smartdevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ def __init__(
# 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()
Expand Down Expand Up @@ -371,6 +372,7 @@ def update_from_discover_info(self, info: Dict[str, Any]) -> None:
# 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:
Expand Down
47 changes: 25 additions & 22 deletions kasa/tests/fixtures/HS100(UK)_4.1_1.1.0.json
Original file line number Diff line number Diff line change
@@ -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.SMART 9E88 PLUGSWITCH",
"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
}
}
Expand Down
7 changes: 4 additions & 3 deletions kasa/tests/newfakes.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,10 @@ def __init__(self, info):

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 (
Expand Down
0