mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-22 19:23:34 +00:00
Fix devtools for P100 and add fixture (#753)
This commit is contained in:
parent
13d8d94bd5
commit
57835276e3
@ -12,6 +12,7 @@ import collections.abc
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
import traceback
|
||||
from collections import defaultdict, namedtuple
|
||||
from pathlib import Path
|
||||
from pprint import pprint
|
||||
@ -19,7 +20,7 @@ from typing import Dict, List, Union
|
||||
|
||||
import asyncclick as click
|
||||
|
||||
from devtools.helpers.smartrequests import COMPONENT_REQUESTS, SmartRequest
|
||||
from devtools.helpers.smartrequests import SmartRequest, get_component_requests
|
||||
from kasa import (
|
||||
AuthenticationException,
|
||||
Credentials,
|
||||
@ -35,6 +36,8 @@ from kasa.smart import SmartDevice
|
||||
Call = namedtuple("Call", "module method")
|
||||
SmartCall = namedtuple("SmartCall", "module request should_succeed")
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def scrub(res):
|
||||
"""Remove identifiers from the given dict."""
|
||||
@ -228,6 +231,8 @@ async def get_legacy_fixture(device):
|
||||
else:
|
||||
click.echo(click.style("OK", fg="green"))
|
||||
successes.append((test_call, info))
|
||||
finally:
|
||||
await device.protocol.close()
|
||||
|
||||
final_query = defaultdict(defaultdict)
|
||||
final = defaultdict(defaultdict)
|
||||
@ -241,7 +246,8 @@ async def get_legacy_fixture(device):
|
||||
final = await device.protocol.query(final_query)
|
||||
except Exception as ex:
|
||||
_echo_error(f"Unable to query all successes at once: {ex}", bold=True, fg="red")
|
||||
|
||||
finally:
|
||||
await device.protocol.close()
|
||||
if device._discovery_info and not device._discovery_info.get("system"):
|
||||
# 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.
|
||||
@ -316,7 +322,11 @@ async def _make_requests_or_exit(
|
||||
_echo_error(
|
||||
f"Unexpected exception querying {name} at once: {ex}",
|
||||
)
|
||||
if _LOGGER.isEnabledFor(logging.DEBUG):
|
||||
traceback.print_stack()
|
||||
exit(1)
|
||||
finally:
|
||||
await device.protocol.close()
|
||||
|
||||
|
||||
async def get_smart_fixture(device: SmartDevice, batch_size: int):
|
||||
@ -367,14 +377,15 @@ async def get_smart_fixture(device: SmartDevice, batch_size: int):
|
||||
|
||||
for item in component_info_response["component_list"]:
|
||||
component_id = item["id"]
|
||||
if requests := COMPONENT_REQUESTS.get(component_id):
|
||||
ver_code = item["ver_code"]
|
||||
if (requests := get_component_requests(component_id, ver_code)) is not None:
|
||||
component_test_calls = [
|
||||
SmartCall(module=component_id, request=request, should_succeed=True)
|
||||
for request in requests
|
||||
]
|
||||
test_calls.extend(component_test_calls)
|
||||
should_succeed.extend(component_test_calls)
|
||||
elif component_id not in COMPONENT_REQUESTS:
|
||||
else:
|
||||
click.echo(f"Skipping {component_id}..", nl=False)
|
||||
click.echo(click.style("UNSUPPORTED", fg="yellow"))
|
||||
|
||||
@ -396,7 +407,11 @@ async def get_smart_fixture(device: SmartDevice, batch_size: int):
|
||||
if (
|
||||
not test_call.should_succeed
|
||||
and hasattr(ex, "error_code")
|
||||
and ex.error_code == SmartErrorCode.UNKNOWN_METHOD_ERROR
|
||||
and ex.error_code
|
||||
in [
|
||||
SmartErrorCode.UNKNOWN_METHOD_ERROR,
|
||||
SmartErrorCode.TRANSPORT_NOT_AVAILABLE_ERROR,
|
||||
]
|
||||
):
|
||||
click.echo(click.style("FAIL - EXPECTED", fg="green"))
|
||||
else:
|
||||
@ -410,6 +425,8 @@ async def get_smart_fixture(device: SmartDevice, batch_size: int):
|
||||
else:
|
||||
click.echo(click.style("OK", fg="green"))
|
||||
successes.append(test_call)
|
||||
finally:
|
||||
await device.protocol.close()
|
||||
|
||||
requests = []
|
||||
for succ in successes:
|
||||
|
@ -133,11 +133,14 @@ class SmartRequest:
|
||||
return SmartRequest("get_device_usage")
|
||||
|
||||
@staticmethod
|
||||
def device_info_list() -> List["SmartRequest"]:
|
||||
def device_info_list(ver_code) -> List["SmartRequest"]:
|
||||
"""Get device info list."""
|
||||
if ver_code == 1:
|
||||
return [SmartRequest.get_device_info()]
|
||||
return [
|
||||
SmartRequest.get_device_info(),
|
||||
SmartRequest.get_device_usage(),
|
||||
SmartRequest.get_auto_update_info(),
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
@ -149,7 +152,6 @@ class SmartRequest:
|
||||
def firmware_info_list() -> List["SmartRequest"]:
|
||||
"""Get info list."""
|
||||
return [
|
||||
SmartRequest.get_auto_update_info(),
|
||||
SmartRequest.get_raw_request("get_fw_download_state"),
|
||||
SmartRequest.get_raw_request("get_latest_fw"),
|
||||
]
|
||||
@ -165,9 +167,13 @@ class SmartRequest:
|
||||
return SmartRequest("get_device_time")
|
||||
|
||||
@staticmethod
|
||||
def get_wireless_scan_info() -> "SmartRequest":
|
||||
def get_wireless_scan_info(
|
||||
params: Optional[GetRulesParams] = None
|
||||
) -> "SmartRequest":
|
||||
"""Get wireless scan info."""
|
||||
return SmartRequest("get_wireless_scan_info")
|
||||
return SmartRequest(
|
||||
"get_wireless_scan_info", params or SmartRequest.GetRulesParams()
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_schedule_rules(params: Optional[GetRulesParams] = None) -> "SmartRequest":
|
||||
@ -294,9 +300,13 @@ class SmartRequest:
|
||||
@staticmethod
|
||||
def get_component_info_requests(component_nego_response) -> List["SmartRequest"]:
|
||||
"""Get a list of requests based on the component info response."""
|
||||
request_list = []
|
||||
request_list: List["SmartRequest"] = []
|
||||
for component in component_nego_response["component_list"]:
|
||||
if requests := COMPONENT_REQUESTS.get(component["id"]):
|
||||
if (
|
||||
requests := get_component_requests(
|
||||
component["id"], int(component["ver_code"])
|
||||
)
|
||||
) is not None:
|
||||
request_list.extend(requests)
|
||||
return request_list
|
||||
|
||||
@ -314,8 +324,17 @@ class SmartRequest:
|
||||
return request
|
||||
|
||||
|
||||
def get_component_requests(component_id, ver_code):
|
||||
"""Get the requests supported by the component and version."""
|
||||
if (cr := COMPONENT_REQUESTS.get(component_id)) is None:
|
||||
return None
|
||||
if callable(cr):
|
||||
return cr(ver_code)
|
||||
return cr
|
||||
|
||||
|
||||
COMPONENT_REQUESTS = {
|
||||
"device": SmartRequest.device_info_list(),
|
||||
"device": SmartRequest.device_info_list,
|
||||
"firmware": SmartRequest.firmware_info_list(),
|
||||
"quick_setup": [SmartRequest.qs_component_nego()],
|
||||
"inherit": [SmartRequest.get_raw_request("get_inherit_info")],
|
||||
@ -324,33 +343,33 @@ COMPONENT_REQUESTS = {
|
||||
"schedule": SmartRequest.schedule_info_list(),
|
||||
"countdown": [SmartRequest.get_countdown_rules()],
|
||||
"antitheft": [SmartRequest.get_antitheft_rules()],
|
||||
"account": None,
|
||||
"synchronize": None, # sync_env
|
||||
"sunrise_sunset": None, # for schedules
|
||||
"account": [],
|
||||
"synchronize": [], # sync_env
|
||||
"sunrise_sunset": [], # for schedules
|
||||
"led": [SmartRequest.get_led_info()],
|
||||
"cloud_connect": [SmartRequest.get_raw_request("get_connect_cloud_state")],
|
||||
"iot_cloud": None,
|
||||
"device_local_time": None,
|
||||
"default_states": None, # in device_info
|
||||
"iot_cloud": [],
|
||||
"device_local_time": [],
|
||||
"default_states": [], # in device_info
|
||||
"auto_off": [SmartRequest.get_auto_off_config()],
|
||||
"localSmart": None,
|
||||
"localSmart": [],
|
||||
"energy_monitoring": SmartRequest.energy_monitoring_list(),
|
||||
"power_protection": SmartRequest.power_protection_list(),
|
||||
"current_protection": None, # overcurrent in device_info
|
||||
"matter": None,
|
||||
"current_protection": [], # overcurrent in device_info
|
||||
"matter": [],
|
||||
"preset": [SmartRequest.get_preset_rules()],
|
||||
"brightness": None, # in device_info
|
||||
"color": None, # in device_info
|
||||
"color_temperature": None, # in device_info
|
||||
"brightness": [], # in device_info
|
||||
"color": [], # in device_info
|
||||
"color_temperature": [], # in device_info
|
||||
"auto_light": [SmartRequest.get_auto_light_info()],
|
||||
"light_effect": [SmartRequest.get_dynamic_light_effect_rules()],
|
||||
"bulb_quick_control": None,
|
||||
"bulb_quick_control": [],
|
||||
"on_off_gradually": [SmartRequest.get_raw_request("get_on_off_gradually_info")],
|
||||
"light_strip": None,
|
||||
"light_strip": [],
|
||||
"light_strip_lighting_effect": [
|
||||
SmartRequest.get_raw_request("get_lighting_effect")
|
||||
],
|
||||
"music_rhythm": None, # music_rhythm_enable in device_info
|
||||
"music_rhythm": [], # music_rhythm_enable in device_info
|
||||
"segment": [SmartRequest.get_raw_request("get_device_segment")],
|
||||
"segment_effect": [SmartRequest.get_raw_request("get_segment_effect_rule")],
|
||||
}
|
||||
|
173
kasa/tests/fixtures/smart/P100_1.0.0_1.1.3.json
vendored
Normal file
173
kasa/tests/fixtures/smart/P100_1.0.0_1.1.3.json
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
{
|
||||
"component_nego": {
|
||||
"component_list": [
|
||||
{
|
||||
"id": "device",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "firmware",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "quick_setup",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "time",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "wireless",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "schedule",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "countdown",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "antitheft",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "account",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "synchronize",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "sunrise_sunset",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "led",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "cloud_connect",
|
||||
"ver_code": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"discovery_result": {
|
||||
"device_id": "00000000000000000000000000000000",
|
||||
"device_model": "P100",
|
||||
"device_type": "SMART.TAPOPLUG",
|
||||
"factory_default": false,
|
||||
"ip": "127.0.0.123",
|
||||
"mac": "1C-3B-F3-00-00-00",
|
||||
"mgt_encrypt_schm": {
|
||||
"encrypt_type": "AES",
|
||||
"http_port": 80,
|
||||
"is_support_https": false
|
||||
},
|
||||
"owner": "00000000000000000000000000000000"
|
||||
},
|
||||
"get_antitheft_rules": {
|
||||
"antitheft_rule_max_count": 1,
|
||||
"enable": false,
|
||||
"rule_list": []
|
||||
},
|
||||
"get_connect_cloud_state": {
|
||||
"status": -1001
|
||||
},
|
||||
"get_countdown_rules": {
|
||||
"countdown_rule_max_count": 1,
|
||||
"enable": false,
|
||||
"rule_list": []
|
||||
},
|
||||
"get_device_info": {
|
||||
"avatar": "plug",
|
||||
"device_id": "0000000000000000000000000000000000000000",
|
||||
"device_on": true,
|
||||
"fw_id": "00000000000000000000000000000000",
|
||||
"fw_ver": "1.1.3 Build 20191017 Rel. 57937",
|
||||
"has_set_location_info": true,
|
||||
"hw_id": "00000000000000000000000000000000",
|
||||
"hw_ver": "1.0.0",
|
||||
"ip": "127.0.0.123",
|
||||
"latitude": 0,
|
||||
"location": "hallway",
|
||||
"longitude": 0,
|
||||
"mac": "1C-3B-F3-00-00-00",
|
||||
"model": "P100",
|
||||
"nickname": "I01BU0tFRF9OQU1FIw==",
|
||||
"oem_id": "00000000000000000000000000000000",
|
||||
"on_time": 6868,
|
||||
"overheated": false,
|
||||
"signal_level": 2,
|
||||
"specs": "US",
|
||||
"ssid": "I01BU0tFRF9TU0lEIw==",
|
||||
"time_usage_past30": 114,
|
||||
"time_usage_past7": 114,
|
||||
"time_usage_today": 114,
|
||||
"type": "SMART.TAPOPLUG"
|
||||
},
|
||||
"get_device_time": {
|
||||
"region": "Europe/London",
|
||||
"time_diff": 0,
|
||||
"timestamp": 1707905077
|
||||
},
|
||||
"get_fw_download_state": {
|
||||
"download_progress": 0,
|
||||
"reboot_time": 10,
|
||||
"status": 0,
|
||||
"upgrade_time": 0
|
||||
},
|
||||
"get_latest_fw": {
|
||||
"fw_size": 786432,
|
||||
"fw_ver": "1.3.7 Build 20230711 Rel.61904",
|
||||
"hw_id": "00000000000000000000000000000000",
|
||||
"need_to_upgrade": true,
|
||||
"oem_id": "00000000000000000000000000000000",
|
||||
"release_date": "2023-07-26",
|
||||
"release_note": "Modifications and Bug fixes:\nEnhanced device security.",
|
||||
"type": 3
|
||||
},
|
||||
"get_led_info": {
|
||||
"led_rule": "always",
|
||||
"led_status": true
|
||||
},
|
||||
"get_next_event": {
|
||||
"action": -1,
|
||||
"e_time": 0,
|
||||
"id": "0",
|
||||
"s_time": 0,
|
||||
"type": 0
|
||||
},
|
||||
"get_schedule_rules": {
|
||||
"enable": false,
|
||||
"rule_list": [],
|
||||
"schedule_rule_max_count": 20,
|
||||
"start_index": 0,
|
||||
"sum": 0
|
||||
},
|
||||
"get_wireless_scan_info": {
|
||||
"ap_list": [],
|
||||
"start_index": 0,
|
||||
"sum": 0,
|
||||
"wep_supported": false
|
||||
},
|
||||
"qs_component_nego": {
|
||||
"component_list": [
|
||||
{
|
||||
"id": "quick_setup",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "sunrise_sunset",
|
||||
"ver_code": 1
|
||||
}
|
||||
],
|
||||
"extra_info": {
|
||||
"device_model": "P100",
|
||||
"device_type": "SMART.TAPOPLUG"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user