mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-22 19:23:34 +00:00
Add EP25 smart fixture and improve test framework for SMART devices (#572)
This commit is contained in:
parent
b27a31a8a9
commit
16ba87378d
26
README.md
26
README.md
@ -228,9 +228,10 @@ The following lists the devices that have been manually verified to work.
|
||||
* KP105
|
||||
* KP115
|
||||
* KP125
|
||||
* KP125M
|
||||
* KP125M [See note below](#tapo-and-newer-kasa-branded-devices)
|
||||
* KP401
|
||||
* EP10
|
||||
* EP25 [See note below](#tapo-and-newer-kasa-branded-devices)
|
||||
|
||||
### Power Strips
|
||||
|
||||
@ -268,18 +269,25 @@ The following lists the devices that have been manually verified to work.
|
||||
|
||||
### Light strips
|
||||
|
||||
* KL400
|
||||
* KL420
|
||||
* KL400L5
|
||||
* KL420L5
|
||||
* KL430
|
||||
|
||||
### Tapo-branded devices
|
||||
### Tapo and newer Kasa branded devices
|
||||
|
||||
The library has recently added a limited supported for devices that carry tapo branding.
|
||||
The library has recently added a limited supported for devices that carry Tapo branding.
|
||||
|
||||
At the moment, the following devices have been confirmed to work:
|
||||
|
||||
* Tapo P110 (plug)
|
||||
* Tapo L530 (bulb)
|
||||
* Tapo L530E (bulb)
|
||||
|
||||
Some newer hardware versions of Kasa branded devices are now using the same protocol as
|
||||
Tapo branded devices. Support for these devices is currently limited as per TAPO branded
|
||||
devices:
|
||||
|
||||
* Kasa EP25 (plug) hw_version 2.6
|
||||
* Kasa KP125M (plug)
|
||||
|
||||
**If your device is unlisted but working, please open a pull request to update the list and add a fixture file (use `devtools/dump_devinfo.py` to generate one).**
|
||||
|
||||
@ -301,6 +309,12 @@ At the moment, the following devices have been confirmed to work:
|
||||
|
||||
### TP-Link Tapo support
|
||||
|
||||
This library has recently added a limited supported for devices that carry Tapo branding.
|
||||
That support is currently limited to the cli. The package `kasa.tapo` is in flux and if you
|
||||
use it directly you should expect it could break in future releases until this statement is removed.
|
||||
|
||||
Other TAPO libraries are:
|
||||
|
||||
* [PyTapo - Python library for communication with Tapo Cameras](https://github.com/JurajNyiri/pytapo)
|
||||
* [Tapo P100 (Tapo P105/P100 plugs, Tapo L510E bulbs)](https://github.com/fishbigger/TapoP100)
|
||||
* [Home Assistant integration](https://github.com/fishbigger/HomeAssistant-Tapo-P100-Control)
|
||||
|
@ -43,8 +43,8 @@ SUPPORTED_SMART_DEVICES = [
|
||||
SUPPORTED_DEVICES = SUPPORTED_IOT_DEVICES + SUPPORTED_SMART_DEVICES
|
||||
|
||||
# Tapo bulbs
|
||||
BULBS_SMART_VARIABLE_TEMP = {"L530"}
|
||||
BULBS_SMART_COLOR = {"L530"}
|
||||
BULBS_SMART_VARIABLE_TEMP = {"L530E"}
|
||||
BULBS_SMART_COLOR = {"L530E"}
|
||||
BULBS_SMART_LIGHT_STRIP: Set[str] = set()
|
||||
BULBS_SMART_DIMMABLE: Set[str] = set()
|
||||
BULBS_SMART = (
|
||||
@ -54,7 +54,7 @@ BULBS_SMART = (
|
||||
)
|
||||
|
||||
# Kasa (IOT-prefixed) bulbs
|
||||
BULBS_IOT_LIGHT_STRIP = {"KL400", "KL430", "KL420"}
|
||||
BULBS_IOT_LIGHT_STRIP = {"KL400L5", "KL430", "KL420L5"}
|
||||
BULBS_IOT_VARIABLE_TEMP = {
|
||||
"LB120",
|
||||
"LB130",
|
||||
@ -83,7 +83,7 @@ BULBS = {
|
||||
}
|
||||
|
||||
|
||||
PLUGS = {
|
||||
PLUGS_IOT = {
|
||||
"HS100",
|
||||
"HS103",
|
||||
"HS105",
|
||||
@ -95,22 +95,35 @@ PLUGS = {
|
||||
"KP105",
|
||||
"KP115",
|
||||
"KP125",
|
||||
"KP125M",
|
||||
"KP401",
|
||||
"KS200M",
|
||||
}
|
||||
PLUGS_SMART = {"P110", "KP125M", "EP25"}
|
||||
PLUGS = {
|
||||
*PLUGS_IOT,
|
||||
*PLUGS_SMART,
|
||||
}
|
||||
STRIPS_IOT = {"HS107", "HS300", "KP303", "KP200", "KP400", "EP40"}
|
||||
STRIPS_SMART = {} # type: ignore[var-annotated]
|
||||
STRIPS = {*STRIPS_IOT, *STRIPS_SMART}
|
||||
|
||||
STRIPS = {"HS107", "HS300", "KP303", "KP200", "KP400", "EP40"}
|
||||
DIMMERS = {"ES20M", "HS220", "KS220M", "KS230", "KP405"}
|
||||
DIMMERS_IOT = {"ES20M", "HS220", "KS220M", "KS230", "KP405"}
|
||||
DIMMERS_SMART = {} # type: ignore[var-annotated]
|
||||
DIMMERS = {
|
||||
*DIMMERS_IOT,
|
||||
*DIMMERS_SMART,
|
||||
}
|
||||
|
||||
WITH_EMETER_IOT = {"HS110", "HS300", "KP115", "KP125", *BULBS_IOT}
|
||||
WITH_EMETER_SMART = {*PLUGS_SMART}
|
||||
WITH_EMETER = {*WITH_EMETER_IOT, *WITH_EMETER_SMART}
|
||||
|
||||
DIMMABLE = {*BULBS, *DIMMERS}
|
||||
WITH_EMETER = {"HS110", "HS300", "KP115", "KP125", "KP125M", *BULBS}
|
||||
|
||||
ALL_DEVICES_IOT = BULBS.union(PLUGS).union(STRIPS).union(DIMMERS)
|
||||
|
||||
PLUGS_SMART = {"P110", "KP125M"}
|
||||
ALL_DEVICES_SMART = BULBS_SMART.union(PLUGS_SMART)
|
||||
|
||||
ALL_DEVICES_IOT = BULBS_IOT.union(PLUGS_IOT).union(STRIPS_IOT).union(DIMMERS_IOT)
|
||||
ALL_DEVICES_SMART = (
|
||||
BULBS_SMART.union(PLUGS_SMART).union(STRIPS_SMART).union(DIMMERS_SMART)
|
||||
)
|
||||
ALL_DEVICES = ALL_DEVICES_IOT.union(ALL_DEVICES_SMART)
|
||||
|
||||
IP_MODEL_CACHE: Dict[str, str] = {}
|
||||
@ -126,14 +139,15 @@ def idgenerator(paramtuple):
|
||||
|
||||
|
||||
def filter_model(desc, model_filter, protocol_filter=None):
|
||||
if not protocol_filter:
|
||||
protocol_filter = {"IOT"}
|
||||
if protocol_filter is None:
|
||||
protocol_filter = {"IOT", "SMART"}
|
||||
filtered = list()
|
||||
for file, protocol in SUPPORTED_DEVICES:
|
||||
if protocol in protocol_filter:
|
||||
file_model = basename(file).split("_")[0]
|
||||
file_model_region = basename(file).split("_")[0]
|
||||
file_model = file_model_region.split("(")[0]
|
||||
for model in model_filter:
|
||||
if model in file_model:
|
||||
if model == file_model:
|
||||
filtered.append((file, protocol))
|
||||
|
||||
filtered_basenames = [basename(f) + "-" + p for f, p in filtered]
|
||||
@ -151,30 +165,40 @@ def parametrize(desc, devices, protocol_filter=None, ids=None):
|
||||
)
|
||||
|
||||
|
||||
has_emeter = parametrize("has emeter", WITH_EMETER)
|
||||
no_emeter = parametrize("no emeter", ALL_DEVICES_IOT - WITH_EMETER)
|
||||
has_emeter = parametrize("has emeter", WITH_EMETER_IOT, protocol_filter={"IOT"})
|
||||
no_emeter = parametrize(
|
||||
"no emeter", ALL_DEVICES_IOT - WITH_EMETER_IOT, protocol_filter={"SMART", "IOT"}
|
||||
)
|
||||
|
||||
bulb = parametrize("bulbs", BULBS, protocol_filter={"SMART", "IOT"})
|
||||
plug = parametrize("plugs", PLUGS)
|
||||
strip = parametrize("strips", STRIPS)
|
||||
dimmer = parametrize("dimmers", DIMMERS)
|
||||
lightstrip = parametrize("lightstrips", LIGHT_STRIPS)
|
||||
plug = parametrize("plugs", PLUGS, protocol_filter={"IOT"})
|
||||
strip = parametrize("strips", STRIPS, protocol_filter={"IOT"})
|
||||
dimmer = parametrize("dimmers", DIMMERS, protocol_filter={"IOT"})
|
||||
lightstrip = parametrize("lightstrips", LIGHT_STRIPS, protocol_filter={"IOT"})
|
||||
|
||||
# bulb types
|
||||
dimmable = parametrize("dimmable", DIMMABLE)
|
||||
non_dimmable = parametrize("non-dimmable", BULBS - DIMMABLE)
|
||||
dimmable = parametrize("dimmable", DIMMABLE, protocol_filter={"IOT"})
|
||||
non_dimmable = parametrize("non-dimmable", BULBS - DIMMABLE, protocol_filter={"IOT"})
|
||||
variable_temp = parametrize(
|
||||
"variable color temp", BULBS_VARIABLE_TEMP, {"SMART", "IOT"}
|
||||
"variable color temp", BULBS_VARIABLE_TEMP, protocol_filter={"SMART", "IOT"}
|
||||
)
|
||||
non_variable_temp = parametrize(
|
||||
"non-variable color temp", BULBS - BULBS_VARIABLE_TEMP, {"SMART", "IOT"}
|
||||
"non-variable color temp",
|
||||
BULBS - BULBS_VARIABLE_TEMP,
|
||||
protocol_filter={"SMART", "IOT"},
|
||||
)
|
||||
color_bulb = parametrize("color bulbs", BULBS_COLOR, protocol_filter={"SMART", "IOT"})
|
||||
non_color_bulb = parametrize(
|
||||
"non-color bulbs", BULBS - BULBS_COLOR, protocol_filter={"SMART", "IOT"}
|
||||
)
|
||||
color_bulb = parametrize("color bulbs", BULBS_COLOR, {"SMART", "IOT"})
|
||||
non_color_bulb = parametrize("non-color bulbs", BULBS - BULBS_COLOR, {"SMART", "IOT"})
|
||||
|
||||
color_bulb_iot = parametrize("color bulbs iot", BULBS_COLOR, {"IOT"})
|
||||
variable_temp_iot = parametrize("variable color temp iot", BULBS_VARIABLE_TEMP, {"IOT"})
|
||||
bulb_iot = parametrize("bulb devices iot", BULBS_IOT)
|
||||
color_bulb_iot = parametrize(
|
||||
"color bulbs iot", BULBS_IOT_COLOR, protocol_filter={"IOT"}
|
||||
)
|
||||
variable_temp_iot = parametrize(
|
||||
"variable color temp iot", BULBS_IOT_VARIABLE_TEMP, protocol_filter={"IOT"}
|
||||
)
|
||||
bulb_iot = parametrize("bulb devices iot", BULBS_IOT, protocol_filter={"IOT"})
|
||||
|
||||
plug_smart = parametrize("plug devices smart", PLUGS_SMART, protocol_filter={"SMART"})
|
||||
bulb_smart = parametrize("bulb devices smart", BULBS_SMART, protocol_filter={"SMART"})
|
||||
@ -209,7 +233,9 @@ def filter_fixtures(desc, root_filter):
|
||||
if root_filter in val:
|
||||
filtered[key] = val
|
||||
|
||||
print(f"{desc}: {filtered.keys()}")
|
||||
print(f"# {desc}")
|
||||
for key in filtered:
|
||||
print(f"\t{key}")
|
||||
return filtered
|
||||
|
||||
|
||||
@ -268,11 +294,11 @@ def device_for_file(model, protocol):
|
||||
if d in model:
|
||||
return TapoBulb
|
||||
else:
|
||||
for d in STRIPS:
|
||||
for d in STRIPS_IOT:
|
||||
if d in model:
|
||||
return SmartStrip
|
||||
|
||||
for d in PLUGS:
|
||||
for d in PLUGS_IOT:
|
||||
if d in model:
|
||||
return SmartPlug
|
||||
|
||||
@ -281,11 +307,11 @@ def device_for_file(model, protocol):
|
||||
if d in model:
|
||||
return SmartLightStrip
|
||||
|
||||
for d in BULBS:
|
||||
for d in BULBS_IOT:
|
||||
if d in model:
|
||||
return SmartBulb
|
||||
|
||||
for d in DIMMERS:
|
||||
for d in DIMMERS_IOT:
|
||||
if d in model:
|
||||
return SmartDimmer
|
||||
|
||||
|
175
kasa/tests/fixtures/smart/EP25(US)_2.6_1.0.1.json
vendored
Normal file
175
kasa/tests/fixtures/smart/EP25(US)_2.6_1.0.1.json
vendored
Normal file
@ -0,0 +1,175 @@
|
||||
{
|
||||
"component_nego": {
|
||||
"component_list": [
|
||||
{
|
||||
"id": "device",
|
||||
"ver_code": 2
|
||||
},
|
||||
{
|
||||
"id": "firmware",
|
||||
"ver_code": 2
|
||||
},
|
||||
{
|
||||
"id": "quick_setup",
|
||||
"ver_code": 3
|
||||
},
|
||||
{
|
||||
"id": "time",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "wireless",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "schedule",
|
||||
"ver_code": 2
|
||||
},
|
||||
{
|
||||
"id": "countdown",
|
||||
"ver_code": 2
|
||||
},
|
||||
{
|
||||
"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
|
||||
},
|
||||
{
|
||||
"id": "iot_cloud",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "device_local_time",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "default_states",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "auto_off",
|
||||
"ver_code": 2
|
||||
},
|
||||
{
|
||||
"id": "energy_monitoring",
|
||||
"ver_code": 2
|
||||
},
|
||||
{
|
||||
"id": "power_protection",
|
||||
"ver_code": 1
|
||||
},
|
||||
{
|
||||
"id": "homekit",
|
||||
"ver_code": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
"discovery_result": {
|
||||
"device_id": "00000000000000000000000000000000",
|
||||
"device_model": "EP25(US)",
|
||||
"device_type": "SMART.KASAPLUG",
|
||||
"factory_default": false,
|
||||
"ip": "127.0.0.123",
|
||||
"is_support_iot_cloud": true,
|
||||
"mac": "00-00-00-00-00-00",
|
||||
"mgt_encrypt_schm": {
|
||||
"encrypt_type": "AES",
|
||||
"http_port": 80,
|
||||
"is_support_https": false,
|
||||
"lv": 2
|
||||
},
|
||||
"obd_src": "apple",
|
||||
"owner": "00000000000000000000000000000000"
|
||||
},
|
||||
"get_current_power": {
|
||||
"current_power": 715
|
||||
},
|
||||
"get_device_info": {
|
||||
"auto_off_remain_time": 0,
|
||||
"auto_off_status": "off",
|
||||
"avatar": "plug",
|
||||
"default_states": {
|
||||
"state": {},
|
||||
"type": "last_states"
|
||||
},
|
||||
"device_id": "0000000000000000000000000000000000000000",
|
||||
"device_on": true,
|
||||
"fw_id": "00000000000000000000000000000000",
|
||||
"fw_ver": "1.0.1 Build 230614 Rel.150219",
|
||||
"has_set_location_info": false,
|
||||
"hw_id": "00000000000000000000000000000000",
|
||||
"hw_ver": "2.6",
|
||||
"ip": "127.0.0.123",
|
||||
"lang": "en_US",
|
||||
"latitude": 0,
|
||||
"longitude": 0,
|
||||
"mac": "00-00-00-00-00-00",
|
||||
"model": "EP25",
|
||||
"nickname": "emVlaw==",
|
||||
"oem_id": "00000000000000000000000000000000",
|
||||
"on_time": 177938,
|
||||
"overheated": false,
|
||||
"power_protection_status": "normal",
|
||||
"region": "America/Los_Angeles",
|
||||
"rssi": -58,
|
||||
"signal_level": 2,
|
||||
"specs": "",
|
||||
"ssid": "IyNNQVNLRUROQU1FIyM=",
|
||||
"time_diff": -480,
|
||||
"type": "SMART.KASAPLUG"
|
||||
},
|
||||
"get_device_time": {
|
||||
"region": "America/Los_Angeles",
|
||||
"time_diff": -480,
|
||||
"timestamp": 1701455103
|
||||
},
|
||||
"get_device_usage": {
|
||||
"power_usage": {
|
||||
"past30": 100856,
|
||||
"past7": 56030,
|
||||
"today": 3965
|
||||
},
|
||||
"saved_power": {
|
||||
"past30": 0,
|
||||
"past7": 0,
|
||||
"today": 0
|
||||
},
|
||||
"time_usage": {
|
||||
"past30": 19678,
|
||||
"past7": 9265,
|
||||
"today": 625
|
||||
}
|
||||
},
|
||||
"get_energy_usage": {
|
||||
"current_power": 715092,
|
||||
"electricity_charge": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"local_time": "2023-12-01 10:25:03",
|
||||
"month_energy": 3965,
|
||||
"month_runtime": 625,
|
||||
"today_energy": 3965,
|
||||
"today_runtime": 625
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user