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.
- {pyhive_integration-1.0.8.dev4/pyhive_integration.egg-info → pyhive_integration-1.0.8.dev6}/PKG-INFO +1 -1
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6/pyhive_integration.egg-info}/PKG-INFO +1 -1
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/setup.py +1 -1
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/api/hive_async_api.py +11 -2
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/heating.py +8 -7
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/hotwater.py +8 -7
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/light.py +8 -7
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/plug.py +8 -7
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/sensor.py +8 -7
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/session.py +12 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/LICENSE +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/MANIFEST.in +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/README.md +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/pyhive_integration.egg-info/SOURCES.txt +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/pyhive_integration.egg-info/dependency_links.txt +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/pyhive_integration.egg-info/requires.txt +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/pyhive_integration.egg-info/top_level.txt +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/pyproject.toml +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/requirements.txt +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/requirements_test.txt +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/setup.cfg +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/__init__.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/action.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/alarm.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/api/__init__.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/api/hive_api.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/api/hive_auth.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/api/hive_auth_async.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/camera.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/device_attributes.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/helper/__init__.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/helper/const.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/helper/debugger.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/helper/hive_exceptions.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/helper/hive_helper.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/helper/hivedataclasses.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/helper/map.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/hive.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/hub.py +0 -0
- {pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/tests/test_hub.py +0 -0
|
@@ -17,7 +17,7 @@ def requirements_from_file(filename="requirements.txt"):
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
setup(
|
|
20
|
-
version="1.0.8.
|
|
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 =
|
|
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
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
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
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
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
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/helper/hive_exceptions.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyhive_integration-1.0.8.dev4 → pyhive_integration-1.0.8.dev6}/src/helper/hivedataclasses.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|