pyhive-integration 1.0.8.dev8__tar.gz → 1.0.8.dev10__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 (40) hide show
  1. {pyhive_integration-1.0.8.dev8/pyhive_integration.egg-info → pyhive_integration-1.0.8.dev10}/PKG-INFO +1 -1
  2. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10/pyhive_integration.egg-info}/PKG-INFO +1 -1
  3. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/setup.py +1 -1
  4. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/heating.py +15 -3
  5. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/session.py +28 -14
  6. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/LICENSE +0 -0
  7. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/MANIFEST.in +0 -0
  8. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/README.md +0 -0
  9. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/pyhive_integration.egg-info/SOURCES.txt +0 -0
  10. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/pyhive_integration.egg-info/dependency_links.txt +0 -0
  11. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/pyhive_integration.egg-info/requires.txt +0 -0
  12. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/pyhive_integration.egg-info/top_level.txt +0 -0
  13. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/pyproject.toml +0 -0
  14. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/requirements.txt +0 -0
  15. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/requirements_test.txt +0 -0
  16. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/setup.cfg +0 -0
  17. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/__init__.py +0 -0
  18. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/action.py +0 -0
  19. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/alarm.py +0 -0
  20. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/api/__init__.py +0 -0
  21. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/api/hive_api.py +0 -0
  22. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/api/hive_async_api.py +0 -0
  23. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/api/hive_auth.py +0 -0
  24. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/api/hive_auth_async.py +0 -0
  25. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/camera.py +0 -0
  26. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/device_attributes.py +0 -0
  27. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/helper/__init__.py +0 -0
  28. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/helper/const.py +0 -0
  29. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/helper/debugger.py +0 -0
  30. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/helper/hive_exceptions.py +0 -0
  31. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/helper/hive_helper.py +0 -0
  32. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/helper/hivedataclasses.py +0 -0
  33. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/helper/map.py +0 -0
  34. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/hive.py +0 -0
  35. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/hotwater.py +0 -0
  36. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/hub.py +0 -0
  37. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/light.py +0 -0
  38. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/plug.py +0 -0
  39. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/src/sensor.py +0 -0
  40. {pyhive_integration-1.0.8.dev8 → pyhive_integration-1.0.8.dev10}/tests/test_hub.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyhive-integration
3
- Version: 1.0.8.dev8
3
+ Version: 1.0.8.dev10
4
4
  Summary: A Python library to interface with the Hive API
5
5
  Home-page: https://github.com/Pyhive/pyhiveapi
6
6
  Author: KJonline24
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyhive-integration
3
- Version: 1.0.8.dev8
3
+ Version: 1.0.8.dev10
4
4
  Summary: A Python library to interface with the Hive API
5
5
  Home-page: https://github.com/Pyhive/pyhiveapi
6
6
  Author: KJonline24
@@ -17,7 +17,7 @@ def requirements_from_file(filename="requirements.txt"):
17
17
 
18
18
 
19
19
  setup(
20
- version="1.0.8.dev8",
20
+ version="1.0.8.dev10",
21
21
  packages=["apyhiveapi", "apyhiveapi.api", "apyhiveapi.helper"],
22
22
  package_dir={"apyhiveapi": "src"},
23
23
  package_data={"data": ["*.json"]},
@@ -116,14 +116,26 @@ class HiveHeating:
116
116
  device (dict): Device to get target temperature for.
117
117
 
118
118
  Returns:
119
- str: Target temperature.
119
+ float: Target temperature or None if invalid
120
120
  """
121
121
  state = None
122
122
 
123
123
  try:
124
124
  data = self.session.data.products[device["hiveID"]]
125
- state = float(data["state"].get("target", None))
126
- state = float(data["state"].get("heat", state))
125
+ state = data["state"].get("target", None)
126
+ if state is None:
127
+ state = data["state"].get("heat", None)
128
+
129
+ if state is not None:
130
+ try:
131
+ state = float(state)
132
+ except (ValueError, TypeError):
133
+ _LOGGER.debug(
134
+ "Non-numeric target temperature value '%s' for %s.",
135
+ state,
136
+ device.get("haName", device.get("hiveID")),
137
+ )
138
+ return None
127
139
  except (KeyError, TypeError) as e:
128
140
  _LOGGER.error(e)
129
141
 
@@ -108,7 +108,8 @@ class HiveSession:
108
108
  self.deviceList = {}
109
109
  self.hub_id = None
110
110
  self._lastPollSlow = False
111
- self._slowPollThreshold = timedelta(seconds=3)
111
+ self._slowPollThreshold = 3
112
+ self._refreshThreshold = 0.90
112
113
 
113
114
  def openFile(self, file: str):
114
115
  """Open a file.
@@ -353,7 +354,7 @@ class HiveSession:
353
354
  HiveReauthRequired: All retry attempts have been exhausted.
354
355
  """
355
356
  last_err = None
356
- for delay_s in (0, 5, 15):
357
+ for delay_s in (0, 5, 10):
357
358
  try:
358
359
  if delay_s:
359
360
  _LOGGER.debug("Retrying device login in %s seconds.", delay_s)
@@ -375,9 +376,14 @@ class HiveSession:
375
376
  )
376
377
  raise HiveReauthRequired from last_err
377
378
 
378
- async def hiveRefreshTokens(self):
379
+ await self.hiveRefreshTokens(force_refresh=True)
380
+
381
+ async def hiveRefreshTokens(self, force_refresh: bool = False):
379
382
  """Refresh Hive tokens.
380
383
 
384
+ Args:
385
+ force_refresh (bool): Whether to force a token refresh regardless of expiry.
386
+
381
387
  Returns:
382
388
  boolean: True/False if update was successful
383
389
  """
@@ -386,29 +392,33 @@ class HiveSession:
386
392
  if self.config.file:
387
393
  return None
388
394
  else:
389
- expiry_time = self.tokens.tokenCreated + (self.tokens.tokenExpiry * 0.95)
390
- # Refresh at 95% of token lifetime to prevent expiration during API calls
395
+ expiry_time = self.tokens.tokenCreated + (
396
+ self.tokens.tokenExpiry * self._refreshThreshold
397
+ )
398
+ # Refresh at 90% of token lifetime to prevent expiration during API calls
391
399
  _LOGGER.debug(
392
400
  "Session token expiry time ( Current: %s | Expiry: %s)",
393
401
  datetime.now(),
394
402
  expiry_time,
395
403
  )
396
- if datetime.now() >= expiry_time:
404
+ if datetime.now() >= expiry_time or force_refresh:
397
405
  async with self._refreshLock:
398
406
  # Re-check after acquiring lock — another caller may have already refreshed
399
407
  expiry_time = self.tokens.tokenCreated + (
400
- self.tokens.tokenExpiry * 0.95
408
+ self.tokens.tokenExpiry * self._refreshThreshold
401
409
  )
402
- if datetime.now() < expiry_time:
410
+ if datetime.now() < expiry_time and not force_refresh:
403
411
  return result
404
412
  actual_expiry = self.tokens.tokenCreated + self.tokens.tokenExpiry
405
413
  _LOGGER.debug(
406
414
  "Session Token created: %s | Actual expiry: %s | "
407
- "Early refresh (×0.95): %s | Now: %s",
415
+ "Early refresh (×%s): %s | Now: %s | Force refresh: %s",
408
416
  self.tokens.tokenCreated,
409
417
  actual_expiry,
418
+ self._refreshThreshold,
410
419
  expiry_time,
411
420
  datetime.now(),
421
+ force_refresh,
412
422
  )
413
423
  try:
414
424
  result = await self.auth.refresh_token(
@@ -434,7 +444,13 @@ class HiveSession:
434
444
  "Session Token refresh failed (%s), falling back to device login.",
435
445
  type(exc).__name__,
436
446
  )
437
- await self._retryDeviceLogin()
447
+ if not force_refresh:
448
+ await self._retryDeviceLogin()
449
+ else:
450
+ _LOGGER.error(
451
+ "Token refresh failed during retry attempt, giving up."
452
+ )
453
+ raise HiveReauthRequired from exc
438
454
  except HiveApiError:
439
455
  _LOGGER.error("API error during token refresh.")
440
456
  raise
@@ -571,7 +587,7 @@ class HiveSession:
571
587
  )
572
588
  await self._retryDeviceLogin()
573
589
  last_auth_err = None
574
- for api_retry_delay in (0, 2, 5):
590
+ for api_retry_delay in (0, 5, 10):
575
591
  try:
576
592
  if api_retry_delay:
577
593
  _LOGGER.debug(
@@ -646,9 +662,7 @@ class HiveSession:
646
662
  get_nodes_successful = True
647
663
  except HiveReauthRequired:
648
664
  _LOGGER.error("Reauthentication required, propagating to caller.")
649
- self.config.lastUpdate = (
650
- datetime.now() - self.config.scanInterval + timedelta(seconds=30)
651
- )
665
+ self.config.lastUpdate = datetime.now()
652
666
  raise
653
667
  except asyncio.TimeoutError:
654
668
  _LOGGER.warning("Hive API request timed out — keeping cached device data.")