mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-01-08 22:07:06 +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
|
* KP105
|
||||||
* KP115
|
* KP115
|
||||||
* KP125
|
* KP125
|
||||||
* KP125M
|
* KP125M [See note below](#tapo-and-newer-kasa-branded-devices)
|
||||||
* KP401
|
* KP401
|
||||||
* EP10
|
* EP10
|
||||||
|
* EP25 [See note below](#tapo-and-newer-kasa-branded-devices)
|
||||||
|
|
||||||
### Power Strips
|
### Power Strips
|
||||||
|
|
||||||
@ -268,18 +269,25 @@ The following lists the devices that have been manually verified to work.
|
|||||||
|
|
||||||
### Light strips
|
### Light strips
|
||||||
|
|
||||||
* KL400
|
* KL400L5
|
||||||
* KL420
|
* KL420L5
|
||||||
* KL430
|
* 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:
|
At the moment, the following devices have been confirmed to work:
|
||||||
|
|
||||||
* Tapo P110 (plug)
|
* 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).**
|
**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
|
### 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)
|
* [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)
|
* [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)
|
* [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
|
SUPPORTED_DEVICES = SUPPORTED_IOT_DEVICES + SUPPORTED_SMART_DEVICES
|
||||||
|
|
||||||
# Tapo bulbs
|
# Tapo bulbs
|
||||||
BULBS_SMART_VARIABLE_TEMP = {"L530"}
|
BULBS_SMART_VARIABLE_TEMP = {"L530E"}
|
||||||
BULBS_SMART_COLOR = {"L530"}
|
BULBS_SMART_COLOR = {"L530E"}
|
||||||
BULBS_SMART_LIGHT_STRIP: Set[str] = set()
|
BULBS_SMART_LIGHT_STRIP: Set[str] = set()
|
||||||
BULBS_SMART_DIMMABLE: Set[str] = set()
|
BULBS_SMART_DIMMABLE: Set[str] = set()
|
||||||
BULBS_SMART = (
|
BULBS_SMART = (
|
||||||
@ -54,7 +54,7 @@ BULBS_SMART = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Kasa (IOT-prefixed) bulbs
|
# Kasa (IOT-prefixed) bulbs
|
||||||
BULBS_IOT_LIGHT_STRIP = {"KL400", "KL430", "KL420"}
|
BULBS_IOT_LIGHT_STRIP = {"KL400L5", "KL430", "KL420L5"}
|
||||||
BULBS_IOT_VARIABLE_TEMP = {
|
BULBS_IOT_VARIABLE_TEMP = {
|
||||||
"LB120",
|
"LB120",
|
||||||
"LB130",
|
"LB130",
|
||||||
@ -83,7 +83,7 @@ BULBS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PLUGS = {
|
PLUGS_IOT = {
|
||||||
"HS100",
|
"HS100",
|
||||||
"HS103",
|
"HS103",
|
||||||
"HS105",
|
"HS105",
|
||||||
@ -95,22 +95,35 @@ PLUGS = {
|
|||||||
"KP105",
|
"KP105",
|
||||||
"KP115",
|
"KP115",
|
||||||
"KP125",
|
"KP125",
|
||||||
"KP125M",
|
|
||||||
"KP401",
|
"KP401",
|
||||||
"KS200M",
|
"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_IOT = {"ES20M", "HS220", "KS220M", "KS230", "KP405"}
|
||||||
DIMMERS = {"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}
|
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)
|
ALL_DEVICES = ALL_DEVICES_IOT.union(ALL_DEVICES_SMART)
|
||||||
|
|
||||||
IP_MODEL_CACHE: Dict[str, str] = {}
|
IP_MODEL_CACHE: Dict[str, str] = {}
|
||||||
@ -126,14 +139,15 @@ def idgenerator(paramtuple):
|
|||||||
|
|
||||||
|
|
||||||
def filter_model(desc, model_filter, protocol_filter=None):
|
def filter_model(desc, model_filter, protocol_filter=None):
|
||||||
if not protocol_filter:
|
if protocol_filter is None:
|
||||||
protocol_filter = {"IOT"}
|
protocol_filter = {"IOT", "SMART"}
|
||||||
filtered = list()
|
filtered = list()
|
||||||
for file, protocol in SUPPORTED_DEVICES:
|
for file, protocol in SUPPORTED_DEVICES:
|
||||||
if protocol in protocol_filter:
|
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:
|
for model in model_filter:
|
||||||
if model in file_model:
|
if model == file_model:
|
||||||
filtered.append((file, protocol))
|
filtered.append((file, protocol))
|
||||||
|
|
||||||
filtered_basenames = [basename(f) + "-" + p for f, p in filtered]
|
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)
|
has_emeter = parametrize("has emeter", WITH_EMETER_IOT, protocol_filter={"IOT"})
|
||||||
no_emeter = parametrize("no emeter", ALL_DEVICES_IOT - WITH_EMETER)
|
no_emeter = parametrize(
|
||||||
|
"no emeter", ALL_DEVICES_IOT - WITH_EMETER_IOT, protocol_filter={"SMART", "IOT"}
|
||||||
|
)
|
||||||
|
|
||||||
bulb = parametrize("bulbs", BULBS, protocol_filter={"SMART", "IOT"})
|
bulb = parametrize("bulbs", BULBS, protocol_filter={"SMART", "IOT"})
|
||||||
plug = parametrize("plugs", PLUGS)
|
plug = parametrize("plugs", PLUGS, protocol_filter={"IOT"})
|
||||||
strip = parametrize("strips", STRIPS)
|
strip = parametrize("strips", STRIPS, protocol_filter={"IOT"})
|
||||||
dimmer = parametrize("dimmers", DIMMERS)
|
dimmer = parametrize("dimmers", DIMMERS, protocol_filter={"IOT"})
|
||||||
lightstrip = parametrize("lightstrips", LIGHT_STRIPS)
|
lightstrip = parametrize("lightstrips", LIGHT_STRIPS, protocol_filter={"IOT"})
|
||||||
|
|
||||||
# bulb types
|
# bulb types
|
||||||
dimmable = parametrize("dimmable", DIMMABLE)
|
dimmable = parametrize("dimmable", DIMMABLE, protocol_filter={"IOT"})
|
||||||
non_dimmable = parametrize("non-dimmable", BULBS - DIMMABLE)
|
non_dimmable = parametrize("non-dimmable", BULBS - DIMMABLE, protocol_filter={"IOT"})
|
||||||
variable_temp = parametrize(
|
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_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"})
|
color_bulb_iot = parametrize(
|
||||||
variable_temp_iot = parametrize("variable color temp iot", BULBS_VARIABLE_TEMP, {"IOT"})
|
"color bulbs iot", BULBS_IOT_COLOR, protocol_filter={"IOT"}
|
||||||
bulb_iot = parametrize("bulb devices iot", BULBS_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"})
|
plug_smart = parametrize("plug devices smart", PLUGS_SMART, protocol_filter={"SMART"})
|
||||||
bulb_smart = parametrize("bulb devices smart", BULBS_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:
|
if root_filter in val:
|
||||||
filtered[key] = val
|
filtered[key] = val
|
||||||
|
|
||||||
print(f"{desc}: {filtered.keys()}")
|
print(f"# {desc}")
|
||||||
|
for key in filtered:
|
||||||
|
print(f"\t{key}")
|
||||||
return filtered
|
return filtered
|
||||||
|
|
||||||
|
|
||||||
@ -268,11 +294,11 @@ def device_for_file(model, protocol):
|
|||||||
if d in model:
|
if d in model:
|
||||||
return TapoBulb
|
return TapoBulb
|
||||||
else:
|
else:
|
||||||
for d in STRIPS:
|
for d in STRIPS_IOT:
|
||||||
if d in model:
|
if d in model:
|
||||||
return SmartStrip
|
return SmartStrip
|
||||||
|
|
||||||
for d in PLUGS:
|
for d in PLUGS_IOT:
|
||||||
if d in model:
|
if d in model:
|
||||||
return SmartPlug
|
return SmartPlug
|
||||||
|
|
||||||
@ -281,11 +307,11 @@ def device_for_file(model, protocol):
|
|||||||
if d in model:
|
if d in model:
|
||||||
return SmartLightStrip
|
return SmartLightStrip
|
||||||
|
|
||||||
for d in BULBS:
|
for d in BULBS_IOT:
|
||||||
if d in model:
|
if d in model:
|
||||||
return SmartBulb
|
return SmartBulb
|
||||||
|
|
||||||
for d in DIMMERS:
|
for d in DIMMERS_IOT:
|
||||||
if d in model:
|
if d in model:
|
||||||
return SmartDimmer
|
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