Skip to content

Commit 492db2a

Browse files
Khole JonesKhole Jones
authored andcommitted
Bump version to 1.0.8.dev7 and add defensive null state handling with temperature validation
Added setdefault() calls to ensure device status dictionaries exist with None values when devices are offline or slow polls occur, preventing KeyError exceptions. Implemented temperature value validation in getCurrentTemperature() to catch and log non-numeric values before processing. Added None checks in getState() before comparing temperatures. Reduced API timeout from 10s to 5s and fixed timeout parameter
1 parent 9f96ee5 commit 492db2a

10 files changed

Lines changed: 38 additions & 12 deletions

File tree

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def requirements_from_file(filename="requirements.txt"):
1717

1818

1919
setup(
20-
version="1.0.8.dev6",
20+
version="1.0.8.dev7",
2121
packages=["apyhiveapi", "apyhiveapi.api", "apyhiveapi.helper"],
2222
package_dir={"apyhiveapi": "src"},
2323
package_data={"data": ["*.json"]},

src/alarm.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,5 @@ async def getAlarm(self, device: dict):
131131
await self.session.helper.errorCheck(
132132
device["device_id"], "ERROR", device["deviceData"]["online"]
133133
)
134+
device.setdefault("status", {"state": None, "mode": None})
134135
return device

src/api/hive_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def __init__(self, hiveSession=None, websession=None, token=None):
3333
"actions": "/actions",
3434
"nodes": "/nodes/{0}/{1}",
3535
}
36-
self.timeout = 10
36+
self.timeout = 5
3737
self.json_return = {
3838
"original": "No response to Hive API request",
3939
"parsed": "No response to Hive API request",

src/api/hive_async_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ async def request(
8484
auth_token[-4:] if len(auth_token) >= 4 else auth_token,
8585
)
8686

87-
timeout = ClientTimeout(total=10)
87+
timeout = ClientTimeout(total=self.timeout)
8888
req_start = time.monotonic()
8989
async with self.websession.request(
9090
method, url, headers=headers, data=data, timeout=timeout

src/camera.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,4 +189,5 @@ async def getCamera(self, device: dict):
189189
await self.session.helper.errorCheck(
190190
device["device_id"], "ERROR", device["deviceData"]["online"]
191191
)
192+
device.setdefault("status", {"state": None})
192193
return device

src/heating.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,23 @@ async def getCurrentTemperature(self, device: dict):
5454
"""
5555
from datetime import datetime
5656

57-
f_state = None
5857
state = None
5958
final = None
6059

6160
try:
6261
data = self.session.data.products[device["hiveID"]]
6362
state = data["props"]["temperature"]
6463

64+
try:
65+
state = float(state)
66+
except (ValueError, TypeError):
67+
_LOGGER.debug(
68+
"Non-numeric temperature value '%s' for %s.",
69+
state,
70+
device.get("haName", device.get("hiveID")),
71+
)
72+
return None
73+
6574
if device["hiveID"] in self.session.data.minMax:
6675
if self.session.data.minMax[device["hiveID"]]["TodayDate"] == str(
6776
datetime.date(datetime.now())
@@ -94,8 +103,7 @@ async def getCurrentTemperature(self, device: dict):
94103
}
95104
self.session.data.minMax[device["hiveID"]] = data
96105

97-
f_state = round(float(state), 1)
98-
final = f_state
106+
final = round(state, 1)
99107
except KeyError as e:
100108
_LOGGER.error(e)
101109

@@ -159,12 +167,13 @@ async def getState(self, device: dict):
159167
try:
160168
current_temp = await self.getCurrentTemperature(device)
161169
target_temp = await self.getTargetTemperature(device)
162-
if current_temp < target_temp:
163-
state = "ON"
164-
else:
165-
state = "OFF"
166-
final = HIVETOHA[self.heatingType].get(state, state)
167-
except KeyError as e:
170+
if current_temp is not None and target_temp is not None:
171+
if current_temp < target_temp:
172+
state = "ON"
173+
else:
174+
state = "OFF"
175+
final = HIVETOHA[self.heatingType].get(state, state)
176+
except (KeyError, TypeError) as e:
168177
_LOGGER.error(e)
169178

170179
return final
@@ -503,6 +512,17 @@ async def getClimate(self, device: dict):
503512
device["haName"],
504513
)
505514
return cached
515+
device.setdefault(
516+
"status",
517+
{
518+
"current_temperature": None,
519+
"target_temperature": None,
520+
"action": None,
521+
"mode": None,
522+
"boost": None,
523+
"state": None,
524+
},
525+
)
506526
return device
507527

508528
async def getScheduleNowNextLater(self, device: dict):

src/hotwater.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ async def getWaterHeater(self, device: dict):
271271
device["haName"],
272272
)
273273
return cached
274+
device.setdefault("status", {"current_operation": None})
274275
return device
275276

276277
async def getScheduleNowNextLater(self, device: dict):

src/light.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ async def getLight(self, device: dict):
428428
device["haName"],
429429
)
430430
return cached
431+
device.setdefault("status", {"state": None})
431432
return device
432433

433434
async def turnOn(self, device: dict, brightness: int, color_temp: int, color: list):

src/plug.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ async def getSwitch(self, device: dict):
188188
device["haName"],
189189
)
190190
return cached
191+
device.setdefault("status", {"state": None})
191192
return device
192193

193194
async def getSwitchState(self, device: dict):

src/sensor.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,5 @@ async def getSensor(self, device: dict):
160160
device["haName"],
161161
)
162162
return cached
163+
device.setdefault("status", {"state": None})
163164
return device

0 commit comments

Comments
 (0)