homebridge-kasa-python 2.7.0-beta.22 → 2.7.0-beta.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/python/kasaApi.py +40 -27
- package/package.json +1 -1
package/dist/python/kasaApi.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import asyncio, sys
|
|
2
2
|
from typing import Any, Dict, List, Optional
|
|
3
3
|
|
|
4
|
-
from kasa import AuthenticationError, Credentials, Device, DeviceType, Discover, Module, UnsupportedDeviceError
|
|
4
|
+
from kasa import AuthenticationError, Credentials, Device, DeviceType, DeviceConfig, Discover, Module, UnsupportedDeviceError
|
|
5
5
|
from quart import Quart, jsonify, request
|
|
6
6
|
|
|
7
7
|
app = Quart(__name__)
|
|
@@ -16,9 +16,10 @@ UNSUPPORTED_TYPES = {
|
|
|
16
16
|
DeviceType.Unknown.value,
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
credentials: Optional[Credentials] = None
|
|
19
20
|
device_cache: Dict[str, Device] = {}
|
|
20
21
|
device_locks: Dict[str, asyncio.Lock] = {}
|
|
21
|
-
device_configs: Dict[str,
|
|
22
|
+
device_configs: Dict[str, dict[Any, Any]] = {}
|
|
22
23
|
|
|
23
24
|
def serialize_child(child: Device) -> Dict[str, Any]:
|
|
24
25
|
print(f"Serializing child device {child.alias}")
|
|
@@ -81,25 +82,9 @@ def custom_serializer(device: Device) -> Dict[str, Any]:
|
|
|
81
82
|
else:
|
|
82
83
|
feature_info = {}
|
|
83
84
|
|
|
84
|
-
device_config = {
|
|
85
|
-
"host": device.config.host,
|
|
86
|
-
"timeout": device.config.timeout,
|
|
87
|
-
"uses_http": device.config.uses_http,
|
|
88
|
-
**({"credentials": {
|
|
89
|
-
"username": device.config.credentials.username,
|
|
90
|
-
"password": device.config.credentials.password
|
|
91
|
-
}} if device.config.credentials else {}),
|
|
92
|
-
"connection_type": {
|
|
93
|
-
"device_family": device.config.connection_type.device_family.value,
|
|
94
|
-
"encryption_type": device.config.connection_type.encryption_type.value,
|
|
95
|
-
"https": device.config.connection_type.https
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
85
|
return {
|
|
100
86
|
"sys_info": sys_info,
|
|
101
|
-
"feature_info": feature_info
|
|
102
|
-
"device_config": device_config
|
|
87
|
+
"feature_info": feature_info
|
|
103
88
|
}
|
|
104
89
|
|
|
105
90
|
async def discover_devices(
|
|
@@ -108,6 +93,7 @@ async def discover_devices(
|
|
|
108
93
|
additional_broadcasts: Optional[List[str]] = None,
|
|
109
94
|
manual_devices: Optional[List[str]] = None
|
|
110
95
|
) -> Dict[str, Any]:
|
|
96
|
+
global credentials
|
|
111
97
|
devices = {}
|
|
112
98
|
devices_to_remove = []
|
|
113
99
|
broadcasts = ["255.255.255.255"] + (additional_broadcasts or [])
|
|
@@ -217,7 +203,9 @@ async def close_all_connections():
|
|
|
217
203
|
async def create_device_info(host: str, device: Device):
|
|
218
204
|
print("Creating device info for host: ", host)
|
|
219
205
|
device_info = custom_serializer(device)
|
|
220
|
-
device_configs[host] =
|
|
206
|
+
device_configs[host] = device.config.to_dict()
|
|
207
|
+
if not device_configs.get(host):
|
|
208
|
+
device_configs[host] = device.config.to_dict()
|
|
221
209
|
all_device_info = {
|
|
222
210
|
"sys_info": device_info["sys_info"],
|
|
223
211
|
"feature_info": device_info["feature_info"],
|
|
@@ -226,14 +214,20 @@ async def create_device_info(host: str, device: Device):
|
|
|
226
214
|
|
|
227
215
|
async def get_sys_info(host: str) -> Dict[str, Any]:
|
|
228
216
|
print("Getting sys_info for host: ", host)
|
|
229
|
-
|
|
217
|
+
device_config_dict = device_configs.get(host)
|
|
218
|
+
if device_config_dict:
|
|
219
|
+
print("Device config found in cache")
|
|
220
|
+
device_config = DeviceConfig.from_dict(device_config_dict)
|
|
221
|
+
else:
|
|
222
|
+
print("Device config not found in cache, recreating...")
|
|
223
|
+
device_config = await recreate_device_config(host)
|
|
230
224
|
lock = device_locks.get(host, asyncio.Lock())
|
|
231
225
|
async with lock:
|
|
232
226
|
device = await get_or_connect_device(host, device_config)
|
|
233
227
|
try:
|
|
234
228
|
await device.update()
|
|
235
229
|
except Exception as e:
|
|
236
|
-
print(f"
|
|
230
|
+
print(f"GetSysInfo failed: {e}, reconnecting...")
|
|
237
231
|
device = await reconnect_device(host, device_config)
|
|
238
232
|
device_info = custom_serializer(device)
|
|
239
233
|
return {"sys_info": device_info["sys_info"]}
|
|
@@ -246,7 +240,13 @@ async def control_device(
|
|
|
246
240
|
child_num: Optional[int] = None
|
|
247
241
|
) -> Dict[str, Any]:
|
|
248
242
|
print(f"Controlling device at host: {host}")
|
|
249
|
-
|
|
243
|
+
device_config_dict = device_configs.get(host)
|
|
244
|
+
if device_config_dict:
|
|
245
|
+
print("Device config found in cache")
|
|
246
|
+
device_config = DeviceConfig.from_dict(device_config_dict)
|
|
247
|
+
else:
|
|
248
|
+
print("Device config not found in cache, recreating...")
|
|
249
|
+
device_config = await recreate_device_config(host)
|
|
250
250
|
lock = device_locks.get(host, asyncio.Lock())
|
|
251
251
|
async with lock:
|
|
252
252
|
device = await get_or_connect_device(host, device_config)
|
|
@@ -257,22 +257,35 @@ async def control_device(
|
|
|
257
257
|
device = await reconnect_device(host, device_config)
|
|
258
258
|
return await perform_device_action(device, feature, action, value, child_num)
|
|
259
259
|
|
|
260
|
-
async def get_or_connect_device(host: str, device_config:
|
|
260
|
+
async def get_or_connect_device(host: str, device_config: DeviceConfig) -> Device:
|
|
261
261
|
device = device_cache.get(host)
|
|
262
262
|
if not device:
|
|
263
263
|
print(f"Device not in cache, connecting to device at host: {host}")
|
|
264
|
-
device = await Device.connect(config=
|
|
264
|
+
device = await Device.connect(config=device_config)
|
|
265
265
|
device_cache[host] = device
|
|
266
|
+
else:
|
|
267
|
+
print(f"Device found in cache: {device.alias}")
|
|
266
268
|
return device
|
|
267
269
|
|
|
268
|
-
async def reconnect_device(host: str, device_config:
|
|
270
|
+
async def reconnect_device(host: str, device_config: DeviceConfig) -> Device:
|
|
269
271
|
device = device_cache.pop(host, None)
|
|
270
272
|
if device:
|
|
271
273
|
await device.disconnect()
|
|
272
|
-
device = await Device.connect(config=
|
|
274
|
+
device = await Device.connect(config=device_config)
|
|
273
275
|
device_cache[host] = device
|
|
274
276
|
return device
|
|
275
277
|
|
|
278
|
+
async def recreate_device_config(host: str) -> DeviceConfig:
|
|
279
|
+
global credentials
|
|
280
|
+
device = await Discover.discover_single(host=host, credentials=credentials)
|
|
281
|
+
await device.update()
|
|
282
|
+
device_configs[host] = device.config.to_dict()
|
|
283
|
+
if not device_configs.get(host):
|
|
284
|
+
device_configs[host] = device.config.to_dict()
|
|
285
|
+
device_config = DeviceConfig.from_dict(device_configs[host])
|
|
286
|
+
await device.disconnect()
|
|
287
|
+
return device_config
|
|
288
|
+
|
|
276
289
|
async def perform_device_action(device: Device, feature: str, action: str, value: Any, child_num: Optional[int] = None) -> Dict[str, Any]:
|
|
277
290
|
target = device.children[child_num] if child_num is not None else device
|
|
278
291
|
light = target.modules.get(Module.Light)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"displayName": "Homebridge Kasa Python",
|
|
3
3
|
"name": "homebridge-kasa-python",
|
|
4
|
-
"version": "2.7.0-beta.
|
|
4
|
+
"version": "2.7.0-beta.24",
|
|
5
5
|
"description": "Plugin that uses Python-Kasa API to communicate with Kasa Devices.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|