pyhive-integration 1.0.8.dev4__tar.gz → 1.0.8.dev6__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.dev4/pyhive_integration.egg-info → pyhive_integration-1.0.8.dev6}/PKG-INFO +1 -1
  2. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6/pyhive_integration.egg-info}/PKG-INFO +1 -1
  3. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/setup.py +1 -1
  4. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/api/hive_async_api.py +11 -2
  5. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/heating.py +8 -7
  6. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/hotwater.py +8 -7
  7. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/light.py +8 -7
  8. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/plug.py +8 -7
  9. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/sensor.py +8 -7
  10. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/session.py +12 -0
  11. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/LICENSE +0 -0
  12. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/MANIFEST.in +0 -0
  13. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/README.md +0 -0
  14. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/pyhive_integration.egg-info/SOURCES.txt +0 -0
  15. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/pyhive_integration.egg-info/dependency_links.txt +0 -0
  16. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/pyhive_integration.egg-info/requires.txt +0 -0
  17. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/pyhive_integration.egg-info/top_level.txt +0 -0
  18. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/pyproject.toml +0 -0
  19. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/requirements.txt +0 -0
  20. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/requirements_test.txt +0 -0
  21. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/setup.cfg +0 -0
  22. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/__init__.py +0 -0
  23. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/action.py +0 -0
  24. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/alarm.py +0 -0
  25. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/api/__init__.py +0 -0
  26. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/api/hive_api.py +0 -0
  27. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/api/hive_auth.py +0 -0
  28. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/api/hive_auth_async.py +0 -0
  29. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/camera.py +0 -0
  30. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/device_attributes.py +0 -0
  31. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/helper/__init__.py +0 -0
  32. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/helper/const.py +0 -0
  33. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/helper/debugger.py +0 -0
  34. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/helper/hive_exceptions.py +0 -0
  35. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/helper/hive_helper.py +0 -0
  36. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/helper/hivedataclasses.py +0 -0
  37. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/helper/map.py +0 -0
  38. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/hive.py +0 -0
  39. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/hub.py +0 -0
  40. {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/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.dev4
3
+ Version: 1.0.8.dev6
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.dev4
3
+ Version: 1.0.8.dev6
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.dev4",
20
+ version="1.0.8.dev6",
21
21
  packages=["apyhiveapi", "apyhiveapi.api", "apyhiveapi.helper"],
22
22
  package_dir={"apyhiveapi": "src"},
23
23
  package_data={"data": ["*.json"]},
@@ -4,6 +4,7 @@
4
4
  import asyncio
5
5
  import json
6
6
  import logging
7
+ import time
7
8
  from typing import Optional
8
9
 
9
10
  import requests
@@ -42,7 +43,7 @@ class HiveApiAsync:
42
43
  "long_lived": "https://api.prod.bgchprod.info/omnia/accessTokens",
43
44
  "weather": "https://weather.prod.bgchprod.info/weather",
44
45
  }
45
- self.timeout = 10
46
+ self.timeout = 5
46
47
  self.json_return = {
47
48
  "original": "No response to Hive API request",
48
49
  "parsed": "No response to Hive API request",
@@ -84,12 +85,20 @@ class HiveApiAsync:
84
85
  )
85
86
 
86
87
  timeout = ClientTimeout(total=10)
88
+ req_start = time.monotonic()
87
89
  async with self.websession.request(
88
90
  method, url, headers=headers, data=data, timeout=timeout
89
91
  ) as resp:
90
92
  resp_body = await resp.text()
93
+ req_duration = time.monotonic() - req_start
94
+ _LOGGER.debug(
95
+ "API %s %s completed in %.2fs — HTTP %s",
96
+ method.upper(),
97
+ url,
98
+ req_duration,
99
+ resp.status,
100
+ )
91
101
  if str(resp.status).startswith("20"):
92
- _LOGGER.debug("API response %s from %s", resp.status, url)
93
102
  return resp
94
103
 
95
104
  if resp.status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN):
@@ -495,13 +495,14 @@ class Climate(HiveHeating):
495
495
  await self.session.helper.errorCheck(
496
496
  device["device_id"], "ERROR", device["deviceData"]["online"]
497
497
  )
498
- cached = self.session.devices.get(device["hiveID"])
499
- if cached is not None:
500
- _LOGGER.debug(
501
- "Returning cached state for offline climate %s.",
502
- device["haName"],
503
- )
504
- return cached
498
+ if self.session._lastPollSlow:
499
+ cached = self.session.devices.get(device["hiveID"])
500
+ if cached is not None:
501
+ _LOGGER.debug(
502
+ "Returning cached state for offline climate %s (slow poll).",
503
+ device["haName"],
504
+ )
505
+ return cached
505
506
  return device
506
507
 
507
508
  async def getScheduleNowNextLater(self, device: dict):
@@ -263,13 +263,14 @@ class WaterHeater(HiveHotwater):
263
263
  await self.session.helper.errorCheck(
264
264
  device["device_id"], "ERROR", device["deviceData"]["online"]
265
265
  )
266
- cached = self.session.devices.get(device["hiveID"])
267
- if cached is not None:
268
- _LOGGER.debug(
269
- "Returning cached state for offline water heater %s.",
270
- device["haName"],
271
- )
272
- return cached
266
+ if self.session._lastPollSlow:
267
+ cached = self.session.devices.get(device["hiveID"])
268
+ if cached is not None:
269
+ _LOGGER.debug(
270
+ "Returning cached state for offline water heater %s (slow poll).",
271
+ device["haName"],
272
+ )
273
+ return cached
273
274
  return device
274
275
 
275
276
  async def getScheduleNowNextLater(self, device: dict):
@@ -420,13 +420,14 @@ class Light(HiveLight):
420
420
  await self.session.helper.errorCheck(
421
421
  device["device_id"], "ERROR", device["deviceData"]["online"]
422
422
  )
423
- cached = self.session.devices.get(device["hiveID"])
424
- if cached is not None:
425
- _LOGGER.debug(
426
- "Returning cached state for offline light %s.",
427
- device["haName"],
428
- )
429
- return cached
423
+ if self.session._lastPollSlow:
424
+ cached = self.session.devices.get(device["hiveID"])
425
+ if cached is not None:
426
+ _LOGGER.debug(
427
+ "Returning cached state for light %s (slow poll).",
428
+ device["haName"],
429
+ )
430
+ return cached
430
431
  return device
431
432
 
432
433
  async def turnOn(self, device: dict, brightness: int, color_temp: int, color: list):
@@ -180,13 +180,14 @@ class Switch(HiveSmartPlug):
180
180
  await self.session.helper.errorCheck(
181
181
  device["device_id"], "ERROR", device["deviceData"]["online"]
182
182
  )
183
- cached = self.session.devices.get(device["hiveID"])
184
- if cached is not None:
185
- _LOGGER.debug(
186
- "Returning cached state for offline switch %s.",
187
- device["haName"],
188
- )
189
- return cached
183
+ if self.session._lastPollSlow:
184
+ cached = self.session.devices.get(device["hiveID"])
185
+ if cached is not None:
186
+ _LOGGER.debug(
187
+ "Returning cached state for offline switch %s (slow poll).",
188
+ device["haName"],
189
+ )
190
+ return cached
190
191
  return device
191
192
 
192
193
  async def getSwitchState(self, device: dict):
@@ -152,11 +152,12 @@ class Sensor(HiveSensor):
152
152
  await self.session.helper.errorCheck(
153
153
  device["device_id"], "ERROR", device["deviceData"]["online"]
154
154
  )
155
- cached = self.session.devices.get(device["hiveID"])
156
- if cached is not None:
157
- _LOGGER.debug(
158
- "Returning cached state for offline sensor %s.",
159
- device["haName"],
160
- )
161
- return cached
155
+ if self.session._lastPollSlow:
156
+ cached = self.session.devices.get(device["hiveID"])
157
+ if cached is not None:
158
+ _LOGGER.debug(
159
+ "Returning cached state for offline sensor %s (slow poll).",
160
+ device["haName"],
161
+ )
162
+ return cached
162
163
  return device
@@ -107,6 +107,7 @@ class HiveSession:
107
107
  self.devices = {}
108
108
  self.deviceList = {}
109
109
  self.hub_id = None
110
+ self._lastPollSlow = False
110
111
 
111
112
  def openFile(self, file: str):
112
113
  """Open a file.
@@ -525,6 +526,7 @@ class HiveSession:
525
526
  elif self.tokens is not None:
526
527
  await self.hiveRefreshTokens()
527
528
  _LOGGER.debug("Fetching all devices from Hive API.")
529
+ api_call_start = time.monotonic()
528
530
  try:
529
531
  api_resp_d = await self.api.getAll()
530
532
  except HiveAuthError:
@@ -537,6 +539,15 @@ class HiveSession:
537
539
  api_resp_d = await self.api.getAll()
538
540
  except HiveAuthError as retry_err:
539
541
  raise HiveReauthRequired from retry_err
542
+ api_call_duration = time.monotonic() - api_call_start
543
+ if api_call_duration > 3:
544
+ _LOGGER.warning(
545
+ "Hive API response took %.1fs — marking poll as slow.",
546
+ api_call_duration,
547
+ )
548
+ self._lastPollSlow = True
549
+ else:
550
+ self._lastPollSlow = False
540
551
  if operator.contains(str(api_resp_d["original"]), "20") is False:
541
552
  raise HTTPException
542
553
  elif api_resp_d["parsed"] is None:
@@ -588,6 +599,7 @@ class HiveSession:
588
599
  raise
589
600
  except asyncio.TimeoutError:
590
601
  _LOGGER.warning("Hive API request timed out — keeping cached device data.")
602
+ self._lastPollSlow = True
591
603
  self.config.lastUpdate = (
592
604
  datetime.now() - self.config.scanInterval + timedelta(seconds=30)
593
605
  )