wyzeapy 0.5.21__tar.gz → 0.5.22.post1__tar.gz

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.
Files changed (22) hide show
  1. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/PKG-INFO +1 -1
  2. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/pyproject.toml +1 -1
  3. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/__init__.py +2 -3
  4. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/services/base_service.py +18 -18
  5. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/utils.py +19 -10
  6. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/wyze_auth_lib.py +7 -5
  7. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/LICENSES/GPL-3.0-only.txt +0 -0
  8. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/const.py +0 -0
  9. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/crypto.py +0 -0
  10. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/exceptions.py +0 -0
  11. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/payload_factory.py +0 -0
  12. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/services/__init__.py +0 -0
  13. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/services/bulb_service.py +0 -0
  14. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/services/camera_service.py +0 -0
  15. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/services/hms_service.py +0 -0
  16. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/services/lock_service.py +0 -0
  17. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/services/sensor_service.py +0 -0
  18. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/services/switch_service.py +0 -0
  19. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/services/thermostat_service.py +0 -0
  20. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/services/update_manager.py +0 -0
  21. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/services/wall_switch_service.py +0 -0
  22. {wyzeapy-0.5.21 → wyzeapy-0.5.22.post1}/src/wyzeapy/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wyzeapy
3
- Version: 0.5.21
3
+ Version: 0.5.22.post1
4
4
  Summary: A library for interacting with Wyze devices
5
5
  License: GPL-3.0-only
6
6
  Author: Katie Mulliken
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "wyzeapy"
3
- version = "0.5.21"
3
+ version = "0.5.22-1"
4
4
  description = "A library for interacting with Wyze devices"
5
5
  authors = ["Katie Mulliken <katie@mulliken.net>"]
6
6
  license = "GPL-3.0-only"
@@ -20,7 +20,6 @@ from .services.sensor_service import SensorService
20
20
  from .services.switch_service import SwitchService, SwitchUsageService
21
21
  from .services.thermostat_service import ThermostatService
22
22
  from .services.wall_switch_service import WallSwitchService
23
- from .utils import check_for_errors_standard
24
23
  from .wyze_auth_lib import WyzeAuthLib, Token
25
24
 
26
25
  _LOGGER = logging.getLogger(__name__)
@@ -84,8 +83,8 @@ class Wyzeapy:
84
83
  email, password, key_id, api_key, token, self.execute_token_callbacks
85
84
  )
86
85
  if token:
87
- # User token supplied, lets go ahead and use it and refresh the access token if needed.
88
- await self._auth_lib.refresh_if_should()
86
+ # User token supplied, refresh on startup
87
+ await self._auth_lib.refresh()
89
88
  else:
90
89
  await self._auth_lib.get_token_with_username_password(
91
90
  email, password, key_id, api_key
@@ -73,7 +73,7 @@ class BaseService:
73
73
 
74
74
  response_json = await self._auth_lib.post(url, json=payload)
75
75
 
76
- check_for_errors_standard(response_json)
76
+ check_for_errors_standard(self, response_json)
77
77
 
78
78
  async def get_user_profile(self) -> Dict[Any, Any]:
79
79
  await self._auth_lib.refresh_if_should()
@@ -119,7 +119,7 @@ class BaseService:
119
119
  response_json = await self._auth_lib.post("https://api.wyzecam.com/app/v2/home_page/get_object_list",
120
120
  json=payload)
121
121
 
122
- check_for_errors_standard(response_json)
122
+ check_for_errors_standard(self, response_json)
123
123
 
124
124
  # Cache the devices so that update calls can pull more recent device_params
125
125
  BaseService._devices = [Device(device) for device in response_json['data']['device_list']]
@@ -164,7 +164,7 @@ class BaseService:
164
164
  response_json = await self._auth_lib.post("https://api.wyzecam.com/app/v2/device/get_property_list",
165
165
  json=payload)
166
166
 
167
- check_for_errors_standard(response_json)
167
+ check_for_errors_standard(self, response_json)
168
168
  properties = response_json['data']['property_list']
169
169
 
170
170
  property_list = []
@@ -209,7 +209,7 @@ class BaseService:
209
209
  response_json = await self._auth_lib.post("https://api.wyzecam.com/app/v2/device/set_property_list",
210
210
  json=payload)
211
211
 
212
- check_for_errors_standard(response_json)
212
+ check_for_errors_standard(self, response_json)
213
213
 
214
214
  async def _run_action_list(self, device: Device, plist: List[Dict[Any, Any]]) -> None:
215
215
  """
@@ -250,7 +250,7 @@ class BaseService:
250
250
  response_json = await self._auth_lib.post("https://api.wyzecam.com/app/v2/auto/run_action_list",
251
251
  json=payload)
252
252
 
253
- check_for_errors_standard(response_json)
253
+ check_for_errors_standard(self, response_json)
254
254
 
255
255
  async def _get_event_list(self, count: int) -> Dict[Any, Any]:
256
256
  """
@@ -291,7 +291,7 @@ class BaseService:
291
291
  response_json = await self._auth_lib.post("https://api.wyzecam.com/app/v2/device/get_event_list",
292
292
  json=payload)
293
293
 
294
- check_for_errors_standard(response_json)
294
+ check_for_errors_standard(self, response_json)
295
295
  return response_json
296
296
 
297
297
  async def _run_action(self, device: Device, action: str) -> None:
@@ -325,7 +325,7 @@ class BaseService:
325
325
  response_json = await self._auth_lib.post("https://api.wyzecam.com/app/v2/auto/run_action",
326
326
  json=payload)
327
327
 
328
- check_for_errors_standard(response_json)
328
+ check_for_errors_standard(self, response_json)
329
329
 
330
330
  async def _set_property(self, device: Device, pid: str, pvalue: str) -> None:
331
331
  """
@@ -356,7 +356,7 @@ class BaseService:
356
356
  response_json = await self._auth_lib.post("https://api.wyzecam.com/app/v2/device/set_property",
357
357
  json=payload)
358
358
 
359
- check_for_errors_standard(response_json)
359
+ check_for_errors_standard(self, response_json)
360
360
 
361
361
  async def _monitoring_profile_active(self, hms_id: str, home: int, away: int) -> None:
362
362
  """
@@ -393,7 +393,7 @@ class BaseService:
393
393
  }
394
394
  ]
395
395
  response_json = await self._auth_lib.patch(url, headers=headers, params=query, json=payload)
396
- check_for_errors_hms(response_json)
396
+ check_for_errors_hms(self, response_json)
397
397
 
398
398
  async def _get_plan_binding_list_by_user(self) -> Dict[Any, Any]:
399
399
  """
@@ -419,7 +419,7 @@ class BaseService:
419
419
  }
420
420
 
421
421
  response_json = await self._auth_lib.get(url, headers=headers, params=payload)
422
- check_for_errors_hms(response_json)
422
+ check_for_errors_hms(self, response_json)
423
423
  return response_json
424
424
 
425
425
  async def _disable_reme_alarm(self, hms_id: str) -> None:
@@ -441,7 +441,7 @@ class BaseService:
441
441
 
442
442
  response_json = await self._auth_lib.delete(url, headers=headers, json=payload)
443
443
 
444
- check_for_errors_hms(response_json)
444
+ check_for_errors_hms(self, response_json)
445
445
 
446
446
  async def _monitoring_profile_state_status(self, hms_id: str) -> Dict[Any, Any]:
447
447
  """
@@ -469,7 +469,7 @@ class BaseService:
469
469
 
470
470
  response_json = await self._auth_lib.get(url, headers=headers, params=query)
471
471
 
472
- check_for_errors_hms(response_json)
472
+ check_for_errors_hms(self, response_json)
473
473
  return response_json
474
474
 
475
475
  async def _lock_control(self, device: Device, action: str) -> None:
@@ -489,7 +489,7 @@ class BaseService:
489
489
 
490
490
  response_json = await self._auth_lib.post(url, json=payload)
491
491
 
492
- check_for_errors_lock(response_json)
492
+ check_for_errors_lock(self, response_json)
493
493
 
494
494
  async def _get_lock_info(self, device: Device) -> Dict[str, Optional[Any]]:
495
495
  await self._auth_lib.refresh_if_should()
@@ -509,7 +509,7 @@ class BaseService:
509
509
 
510
510
  response_json = await self._auth_lib.get(url, params=payload)
511
511
 
512
- check_for_errors_lock(response_json)
512
+ check_for_errors_lock(self, response_json)
513
513
 
514
514
  return response_json
515
515
 
@@ -533,7 +533,7 @@ class BaseService:
533
533
  response_json = await self._auth_lib.post("https://api.wyzecam.com/app/v2/device/get_device_Info",
534
534
  json=payload)
535
535
 
536
- check_for_errors_standard(response_json)
536
+ check_for_errors_standard(self, response_json)
537
537
 
538
538
  return response_json
539
539
 
@@ -554,7 +554,7 @@ class BaseService:
554
554
 
555
555
  response_json = await self._auth_lib.get(url, headers=headers, params=payload)
556
556
 
557
- check_for_errors_iot(response_json)
557
+ check_for_errors_iot(self, response_json)
558
558
 
559
559
  return response_json
560
560
 
@@ -579,7 +579,7 @@ class BaseService:
579
579
 
580
580
  response_json = await self._auth_lib.post(url, headers=headers, data=payload_str)
581
581
 
582
- check_for_errors_iot(response_json)
582
+ check_for_errors_iot(self, response_json)
583
583
 
584
584
  async def _local_bulb_command(self, bulb, plist):
585
585
  # await self._auth_lib.refresh_if_should()
@@ -640,6 +640,6 @@ class BaseService:
640
640
  "https://api.wyzecam.com/app/v2/plug/usage_record_list", json=payload
641
641
  )
642
642
 
643
- check_for_errors_standard(response_json)
643
+ check_for_errors_standard(self, response_json)
644
644
 
645
645
  return response_json["data"]["usage_record_list"]
@@ -72,36 +72,45 @@ def create_password(password: str) -> str:
72
72
  return hashlib.md5(hex2.encode()).hexdigest()
73
73
 
74
74
 
75
- def check_for_errors_standard(response_json: Dict[str, Any]) -> None:
75
+ def check_for_errors_standard(service, response_json: Dict[str, Any]) -> None:
76
76
  if response_json['code'] != ResponseCodes.SUCCESS.value:
77
77
  if response_json['code'] == ResponseCodes.PARAMETER_ERROR.value:
78
78
  raise ParameterError(response_json)
79
79
  elif response_json['code'] == ResponseCodes.ACCESS_TOKEN_ERROR.value:
80
- raise AccessTokenError
80
+ service._auth_lib.token.expired = True
81
+ raise AccessTokenError("Access Token expired, attempting to refresh")
81
82
  elif response_json['code'] == ResponseCodes.DEVICE_OFFLINE.value:
82
83
  return
83
84
  else:
84
85
  raise UnknownApiError(response_json)
85
86
 
86
87
 
87
- def check_for_errors_lock(response_json: Dict[str, Any]) -> None:
88
+ def check_for_errors_lock(service, response_json: Dict[str, Any]) -> None:
88
89
  if response_json['ErrNo'] != 0:
89
90
  if response_json.get('code') == ResponseCodes.PARAMETER_ERROR.value:
90
91
  raise ParameterError
91
92
  elif response_json.get('code') == ResponseCodes.ACCESS_TOKEN_ERROR.value:
92
- raise AccessTokenError
93
+ service._auth_lib.token.expired = True
94
+ raise AccessTokenError("Access Token expired, attempting to refresh")
93
95
  else:
94
96
  raise UnknownApiError(response_json)
95
97
 
96
98
 
97
- def check_for_errors_iot(response_json: Dict[Any, Any]) -> None:
99
+ def check_for_errors_iot(service, response_json: Dict[Any, Any]) -> None:
98
100
  if response_json['code'] != 1:
99
- raise UnknownApiError(response_json)
100
-
101
+ if str(response_json['code']) == ResponseCodes.ACCESS_TOKEN_ERROR.value:
102
+ service._auth_lib.token.expired = True
103
+ raise AccessTokenError("Access Token expired, attempting to refresh")
104
+ else:
105
+ raise UnknownApiError(response_json)
101
106
 
102
- def check_for_errors_hms(response_json: Dict[Any, Any]) -> None:
103
- if response_json['message'] is None:
104
- raise AccessTokenError
107
+ def check_for_errors_hms(service, response_json: Dict[Any, Any]) -> None:
108
+ if response_json['code'] != 1:
109
+ if str(response_json['code']) == ResponseCodes.ACCESS_TOKEN_ERROR.value:
110
+ service._auth_lib.token.expired = True
111
+ raise AccessTokenError("Access Token expired, attempting to refresh")
112
+ else:
113
+ raise UnknownApiError(response_json)
105
114
 
106
115
 
107
116
  def return_event_for_device(device: Device, events: List[Event]) -> Optional[Event]:
@@ -22,12 +22,13 @@ _LOGGER = logging.getLogger(__name__)
22
22
 
23
23
 
24
24
  class Token:
25
- # Token is good for 216,000 seconds (60 hours) but 48 hours seems like a reasonable refresh interval
26
- REFRESH_INTERVAL = 172800
25
+ # Token is apparently good for 24 hours, so refresh after 23
26
+ REFRESH_INTERVAL = 82800
27
27
 
28
28
  def __init__(self, access_token, refresh_token, refresh_time: float = None):
29
29
  self._access_token: str = access_token
30
30
  self._refresh_token: str = refresh_token
31
+ self.expired = False
31
32
  if refresh_time:
32
33
  self._refresh_time: float = refresh_time
33
34
  else:
@@ -206,9 +207,9 @@ class WyzeAuthLib:
206
207
  return time.time() >= self.token.refresh_time
207
208
 
208
209
  async def refresh_if_should(self):
209
- if self.should_refresh:
210
+ if self.should_refresh or self.token.expired:
210
211
  async with self.refresh_lock:
211
- if self.should_refresh:
212
+ if self.should_refresh or self.token.expired:
212
213
  _LOGGER.debug("Should refresh. Refreshing...")
213
214
  await self.refresh()
214
215
 
@@ -233,11 +234,12 @@ class WyzeAuthLib:
233
234
  response = await _session.post("https://api.wyzecam.com/app/user/refresh_token", headers=headers,
234
235
  json=payload)
235
236
  response_json = await response.json()
236
- check_for_errors_standard(response_json)
237
+ check_for_errors_standard(self, response_json)
237
238
 
238
239
  self.token.access_token = response_json['data']['access_token']
239
240
  self.token.refresh_token = response_json['data']['refresh_token']
240
241
  await self.token_callback(self.token)
242
+ self.token.expired = False
241
243
 
242
244
  def sanitize(self, data):
243
245
  if data and type(data) is dict: