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.
@@ -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, Dict[str, Any]] = {}
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] = device_info["device_config"]
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
- device_config = device_configs.get(host)
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"Action failed: {e}, reconnecting...")
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
- device_config = device_configs.get(host)
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: Dict[str, Any]) -> Device:
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=Device.Config.from_dict(device_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: Dict[str, Any]) -> Device:
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=Device.Config.from_dict(device_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.22",
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",