From e4ed948487d8d156e022ed17103439c499405634 Mon Sep 17 00:00:00 2001 From: Khole Jones Date: Sun, 9 Nov 2025 23:44:31 +0000 Subject: [PATCH 1/6] refactor: replace dictionary access with attribute access for device objects - Changed from bracket notation (device["hiveID"]) to dot notation (device.hive_id) throughout action, alarm, camera, and heating modules - Updated AWS Cognito client initialization to use unsigned config instead of placeholder credentials - Replaced device.get() with getattr() for optional attributes --- src/action.py | 36 ++--- src/alarm.py | 27 ++-- src/api/hive_auth.py | 10 +- src/api/hive_auth_async.py | 10 +- src/camera.py | 38 ++--- src/heating.py | 124 +++++++------- src/helper/const.py | 294 +++++++++++++++++++++++++++------- src/helper/hive_helper.py | 18 ++- src/helper/hivedataclasses.py | 47 ++++-- src/hotwater.py | 58 +++---- src/hub.py | 6 +- src/light.py | 90 +++++------ src/plug.py | 48 +++--- src/sensor.py | 32 ++-- src/session.py | 119 +++++++------- 15 files changed, 589 insertions(+), 368 deletions(-) diff --git a/src/action.py b/src/action.py index bbd4788..7404a0e 100644 --- a/src/action.py +++ b/src/action.py @@ -31,21 +31,21 @@ async def getAction(self, device: dict): """ dev_data = {} - if device["hiveID"] in self.data["action"]: + if device.hive_id in self.data["action"]: dev_data = { - "hiveID": device["hiveID"], - "hiveName": device["hiveName"], - "hiveType": device["hiveType"], - "haName": device["haName"], - "haType": device["haType"], + "hiveID": device.hive_id, + "hiveName": device.hive_name, + "hiveType": device.hive_type, + "haName": device.ha_name, + "haType": device.ha_type, "status": {"state": await self.getState(device)}, "power_usage": None, "deviceData": {}, - "custom": device.get("custom", None), + "custom": getattr(device, "custom", None), } - self.session.devices.update({device["hiveID"]: dev_data}) - return self.session.devices[device["hiveID"]] + self.session.devices.update({device.hive_id: dev_data}) + return self.session.devices[device.hive_id] else: exists = self.session.data.actions.get("hiveID", False) if exists is False: @@ -64,7 +64,7 @@ async def getState(self, device: dict): final = None try: - data = self.session.data.actions[device["hiveID"]] + data = self.session.data.actions[device.hive_id] final = data["enabled"] except KeyError as e: await self.session.log.error(e) @@ -84,15 +84,15 @@ async def setStatusOn(self, device: dict): final = False - if device["hiveID"] in self.session.data.actions: + if device.hive_id in self.session.data.actions: await self.session.hiveRefreshTokens() - data = self.session.data.actions[device["hiveID"]] + data = self.session.data.actions[device.hive_id] data.update({"enabled": True}) send = json.dumps(data) - resp = await self.session.api.setAction(device["hiveID"], send) + resp = await self.session.api.setAction(device.hive_id, send) if resp["original"] == 200: final = True - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) return final @@ -109,14 +109,14 @@ async def setStatusOff(self, device: dict): final = False - if device["hiveID"] in self.session.data.actions: + if device.hive_id in self.session.data.actions: await self.session.hiveRefreshTokens() - data = self.session.data.actions[device["hiveID"]] + data = self.session.data.actions[device.hive_id] data.update({"enabled": False}) send = json.dumps(data) - resp = await self.session.api.setAction(device["hiveID"], send) + resp = await self.session.api.setAction(device.hive_id, send) if resp["original"] == 200: final = True - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) return final diff --git a/src/alarm.py b/src/alarm.py index 4e719ce..ca07f1b 100644 --- a/src/alarm.py +++ b/src/alarm.py @@ -37,7 +37,7 @@ async def getState(self, device: dict): state = None try: - data = self.session.data.devices[device["hiveID"]] + data = self.session.data.devices[device.hive_id] state = data["state"]["alarmActive"] except KeyError as e: await self.session.log.error(e) @@ -55,10 +55,7 @@ async def setMode(self, device: dict, mode: str): """ final = False - if ( - device["hiveID"] in self.session.data.devices - and device["deviceData"]["online"] - ): + if device.hive_id in self.session.data.devices and device.device_data["online"]: await self.session.hiveRefreshTokens() resp = await self.session.api.setAlarm(mode=mode) if resp["original"] == 200: @@ -92,19 +89,19 @@ async def getAlarm(self, device: dict): Returns: dict: Updated device. """ - device["deviceData"].update( + device.device_data.update( {"online": await self.session.attr.onlineOffline(device["device_id"])} ) dev_data = {} - if device["deviceData"]["online"]: + if device.device_data["online"]: self.session.helper.deviceRecovered(device["device_id"]) data = self.session.data.devices[device["device_id"]] dev_data = { - "hiveID": device["hiveID"], - "hiveName": device["hiveName"], - "hiveType": device["hiveType"], - "haName": device["haName"], + "hiveID": device.hive_id, + "hiveName": device.hive_name, + "hiveType": device.hive_type, + "haName": device.ha_name, "haType": device["haType"], "device_id": device["device_id"], "device_name": device["device_name"], @@ -116,14 +113,14 @@ async def getAlarm(self, device: dict): "parentDevice": data.get("parent", None), "custom": device.get("custom", None), "attributes": await self.session.attr.stateAttributes( - device["device_id"], device["hiveType"] + device["device_id"], device.hive_type ), } - self.session.devices.update({device["hiveID"]: dev_data}) - return self.session.devices[device["hiveID"]] + self.session.devices.update({device.hive_id: dev_data}) + return self.session.devices[device.hive_id] else: await self.session.log.errorCheck( - device["device_id"], "ERROR", device["deviceData"]["online"] + device["device_id"], "ERROR", device.device_data["online"] ) return device diff --git a/src/api/hive_auth.py b/src/api/hive_auth.py index b27788c..193ef8e 100644 --- a/src/api/hive_auth.py +++ b/src/api/hive_auth.py @@ -11,6 +11,8 @@ import boto3 import botocore +from botocore import UNSIGNED +from botocore.config import Config from ..helper.hive_exceptions import ( HiveApiError, @@ -117,12 +119,12 @@ def __init__( # pylint: disable=too-many-positional-arguments self.__pool_id = self.data.get("UPID") self.__client_id = self.data.get("CLIID") self.__region = self.data.get("REGION").split("_")[0] + # Use unsigned requests for Cognito public client (no AWS credentials needed) + config = Config(signature_version=UNSIGNED) self.client = boto3.client( "cognito-idp", - self.__region, - aws_access_key_id="ACCESS_KEY", - aws_secret_access_key="SECRET_KEY", - aws_session_token="SESSION_TOKEN", + region_name=self.__region, + config=config, ) def generate_random_small_a(self): diff --git a/src/api/hive_auth_async.py b/src/api/hive_auth_async.py index a1e03b8..484354b 100644 --- a/src/api/hive_auth_async.py +++ b/src/api/hive_auth_async.py @@ -14,6 +14,8 @@ import boto3 import botocore +from botocore import UNSIGNED +from botocore.config import Config from ..helper.hive_exceptions import ( HiveApiError, @@ -106,15 +108,15 @@ async def async_init(self): self.__pool_id = self.data.get("UPID") self.__client_id = self.data.get("CLIID") self.__region = self.data.get("REGION").split("_")[0] + # Use unsigned requests for Cognito public client (no AWS credentials needed) + config = Config(signature_version=UNSIGNED) self.client = await self.loop.run_in_executor( None, functools.partial( boto3.client, "cognito-idp", - self.__region, - aws_access_key_id="ACCESS_KEY", - aws_secret_access_key="SECRET_KEY", - aws_session_token="SESSION_TOKEN", + region_name=self.__region, + config=config, ), ) diff --git a/src/camera.py b/src/camera.py index 10c26a5..cf47f81 100644 --- a/src/camera.py +++ b/src/camera.py @@ -21,7 +21,7 @@ async def getCameraTemperature(self, device: dict): state = None try: - data = self.session.data.devices[device["hiveID"]] + data = self.session.data.devices[device.hive_id] state = data["props"]["temperature"] except KeyError as e: await self.session.log.error(e) @@ -37,7 +37,7 @@ async def getCameraState(self, device: dict): state = None try: - data = self.session.data.devices[device["hiveID"]] + data = self.session.data.devices[device.hive_id] state = True if data["state"]["mode"] == "ARMED" else False except KeyError as e: await self.session.log.error(e) @@ -53,7 +53,7 @@ async def getCameraImageURL(self, device: dict): state = None try: - state = self.session.data.camera[device["hiveID"]]["cameraImage"][ + state = self.session.data.camera[device.hive_id]["cameraImage"][ "thumbnailUrls" ][0] except KeyError as e: @@ -70,7 +70,7 @@ async def getCameraRecodringURL(self, device: dict): state = None try: - state = self.session.data.camera[device["hiveID"]]["cameraRecording"] + state = self.session.data.camera[device.hive_id]["cameraRecording"] except KeyError as e: await self.session.log.error(e) @@ -87,10 +87,7 @@ async def setCameraOn(self, device: dict, mode: str): """ final = False - if ( - device["hiveID"] in self.session.data.devices - and device["deviceData"]["online"] - ): + if device.hive_id in self.session.data.devices and device.device_data["online"]: await self.session.hiveRefreshTokens() resp = await self.session.api.setState(mode=mode) if resp["original"] == 200: @@ -110,10 +107,7 @@ async def setCameraOff(self, device: dict, mode: str): """ final = False - if ( - device["hiveID"] in self.session.data.devices - and device["deviceData"]["online"] - ): + if device.hive_id in self.session.data.devices and device.device_data["online"]: await self.session.hiveRefreshTokens() resp = await self.session.api.setState(mode=mode) if resp["original"] == 200: @@ -147,19 +141,19 @@ async def getCamera(self, device: dict): Returns: dict: Updated device. """ - device["deviceData"].update( + device.device_data.update( {"online": await self.session.attr.onlineOffline(device["device_id"])} ) dev_data = {} - if device["deviceData"]["online"]: + if device.device_data["online"]: self.session.helper.deviceRecovered(device["device_id"]) data = self.session.data.devices[device["device_id"]] dev_data = { - "hiveID": device["hiveID"], - "hiveName": device["hiveName"], - "hiveType": device["hiveType"], - "haName": device["haName"], + "hiveID": device.hive_id, + "hiveName": device.hive_name, + "hiveType": device.hive_type, + "haName": device.ha_name, "haType": device["haType"], "device_id": device["device_id"], "device_name": device["device_name"], @@ -173,14 +167,14 @@ async def getCamera(self, device: dict): "parentDevice": data.get("parent", None), "custom": device.get("custom", None), "attributes": await self.session.attr.stateAttributes( - device["device_id"], device["hiveType"] + device["device_id"], device.hive_type ), } - self.session.devices.update({device["hiveID"]: dev_data}) - return self.session.devices[device["hiveID"]] + self.session.devices.update({device.hive_id: dev_data}) + return self.session.devices[device.hive_id] else: await self.session.log.errorCheck( - device["device_id"], "ERROR", device["deviceData"]["online"] + device["device_id"], "ERROR", device.device_data["online"] ) return device diff --git a/src/heating.py b/src/heating.py index c7711f6..174ac43 100644 --- a/src/heating.py +++ b/src/heating.py @@ -22,8 +22,8 @@ async def getMinTemperature(self, device: dict): Returns: int: Minimum temperature """ - if device["hiveType"] == "nathermostat": - return self.session.data.products[device["hiveID"]]["props"]["minHeat"] + if device.hive_type == "nathermostat": + return self.session.data.products[device.hive_id]["props"]["minHeat"] return 5 async def getMaxTemperature(self, device: dict): @@ -35,8 +35,8 @@ async def getMaxTemperature(self, device: dict): Returns: int: Maximum temperature """ - if device["hiveType"] == "nathermostat": - return self.session.data.products[device["hiveID"]]["props"]["maxHeat"] + if device.hive_type == "nathermostat": + return self.session.data.products[device.hive_id]["props"]["maxHeat"] return 32 async def getCurrentTemperature(self, device: dict): @@ -55,31 +55,31 @@ async def getCurrentTemperature(self, device: dict): final = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["props"]["temperature"] - if device["hiveID"] in self.session.data.minMax: - if self.session.data.minMax[device["hiveID"]]["TodayDate"] == str( + if device.hive_id in self.session.data.minMax: + if self.session.data.minMax[device.hive_id]["TodayDate"] == str( datetime.date(datetime.now()) ): - if state < self.session.data.minMax[device["hiveID"]]["TodayMin"]: - self.session.data.minMax[device["hiveID"]]["TodayMin"] = state + if state < self.session.data.minMax[device.hive_id]["TodayMin"]: + self.session.data.minMax[device.hive_id]["TodayMin"] = state - if state > self.session.data.minMax[device["hiveID"]]["TodayMax"]: - self.session.data.minMax[device["hiveID"]]["TodayMax"] = state + if state > self.session.data.minMax[device.hive_id]["TodayMax"]: + self.session.data.minMax[device.hive_id]["TodayMax"] = state else: data = { "TodayMin": state, "TodayMax": state, "TodayDate": str(datetime.date(datetime.now())), } - self.session.data.minMax[device["hiveID"]].update(data) + self.session.data.minMax[device.hive_id].update(data) - if state < self.session.data.minMax[device["hiveID"]]["RestartMin"]: - self.session.data.minMax[device["hiveID"]]["RestartMin"] = state + if state < self.session.data.minMax[device.hive_id]["RestartMin"]: + self.session.data.minMax[device.hive_id]["RestartMin"] = state - if state > self.session.data.minMax[device["hiveID"]]["RestartMax"]: - self.session.data.minMax[device["hiveID"]]["RestartMax"] = state + if state > self.session.data.minMax[device.hive_id]["RestartMax"]: + self.session.data.minMax[device.hive_id]["RestartMax"] = state else: data = { "TodayMin": state, @@ -88,7 +88,7 @@ async def getCurrentTemperature(self, device: dict): "RestartMin": state, "RestartMax": state, } - self.session.data.minMax[device["hiveID"]] = data + self.session.data.minMax[device.hive_id] = data f_state = round(float(state), 1) final = f_state @@ -109,7 +109,7 @@ async def getTargetTemperature(self, device: dict): state = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = float(data["state"].get("target", None)) state = float(data["state"].get("heat", state)) except (KeyError, TypeError) as e: @@ -130,7 +130,7 @@ async def getMode(self, device: dict): final = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["state"]["mode"] if state == "BOOST": state = data["props"]["previous"]["mode"] @@ -177,7 +177,7 @@ async def getCurrentOperation(self, device: dict): state = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["props"]["working"] except KeyError as e: await self.session.log.error(e) @@ -196,7 +196,7 @@ async def getBoostStatus(self, device: dict): state = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = HIVETOHA["Boost"].get(data["state"].get("boost", False), "ON") except KeyError as e: await self.session.log.error(e) @@ -216,7 +216,7 @@ async def getBoostTime(self, device: dict): state = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["state"]["boost"] except KeyError as e: await self.session.log.error(e) @@ -236,7 +236,7 @@ async def getHeatOnDemand(self, device): state = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["props"]["autoBoost"]["active"] except KeyError as e: await self.session.log.error(e) @@ -266,17 +266,17 @@ async def setTargetTemperature(self, device: dict, new_temp: str): final = False if ( - device["hiveID"] in self.session.data.products - and device["deviceData"]["online"] + device.hive_id in self.session.data.products + and device.device_data["online"] ): await self.session.hiveRefreshTokens() - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] resp = await self.session.api.setState( - data["type"], device["hiveID"], target=new_temp + data["type"], device.hive_id, target=new_temp ) if resp["original"] == 200: - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) final = True return final @@ -295,16 +295,16 @@ async def setMode(self, device: dict, new_mode: str): final = False if ( - device["hiveID"] in self.session.data.products - and device["deviceData"]["online"] + device.hive_id in self.session.data.products + and device.device_data["online"] ): - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] resp = await self.session.api.setState( - data["type"], device["hiveID"], mode=new_mode + data["type"], device.hive_id, mode=new_mode ) if resp["original"] == 200: - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) final = True return final @@ -326,20 +326,20 @@ async def setBoostOn(self, device: dict, mins: str, temp: float): final = False if ( - device["hiveID"] in self.session.data.products - and device["deviceData"]["online"] + device.hive_id in self.session.data.products + and device.device_data["online"] ): - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] resp = await self.session.api.setState( data["type"], - device["hiveID"], + device.hive_id, mode="BOOST", boost=mins, target=temp, ) if resp["original"] == 200: - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) final = True return final @@ -357,28 +357,28 @@ async def setBoostOff(self, device: dict): final = False if ( - device["hiveID"] in self.session.data.products - and device["deviceData"]["online"] + device.hive_id in self.session.data.products + and device.device_data["online"] ): await self.session.hiveRefreshTokens() - data = self.session.data.products[device["hiveID"]] - await self.session.getDevices(device["hiveID"]) + data = self.session.data.products[device.hive_id] + await self.session.getDevices(device.hive_id) if await self.getBoostStatus(device) == "ON": prev_mode = data["props"]["previous"]["mode"] if prev_mode == "MANUAL" or prev_mode == "OFF": pre_temp = data["props"]["previous"].get("target", 7) resp = await self.session.api.setState( data["type"], - device["hiveID"], + device.hive_id, mode=prev_mode, target=pre_temp, ) else: resp = await self.session.api.setState( - data["type"], device["hiveID"], mode=prev_mode + data["type"], device.hive_id, mode=prev_mode ) if resp["original"] == 200: - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) final = True return final @@ -396,17 +396,17 @@ async def setHeatOnDemand(self, device: dict, state: str): final = False if ( - device["hiveID"] in self.session.data.products - and device["deviceData"]["online"] + device.hive_id in self.session.data.products + and device.device_data["online"] ): - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] await self.session.hiveRefreshTokens() resp = await self.session.api.setState( - data["type"], device["hiveID"], autoBoost=state + data["type"], device.hive_id, autoBoost=state ) if resp["original"] == 200: - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) final = True return final @@ -436,19 +436,19 @@ async def getClimate(self, device: dict): Returns: dict: Updated device. """ - device["deviceData"].update( + device.device_data.update( {"online": await self.session.attr.onlineOffline(device["device_id"])} ) - if device["deviceData"]["online"]: + if device.device_data["online"]: dev_data = {} self.session.helper.deviceRecovered(device["device_id"]) data = self.session.data.devices[device["device_id"]] dev_data = { - "hiveID": device["hiveID"], - "hiveName": device["hiveName"], - "hiveType": device["hiveType"], - "haName": device["haName"], + "hiveID": device.hive_id, + "hiveName": device.hive_name, + "hiveType": device.hive_type, + "haName": device.ha_name, "haType": device["haType"], "device_id": device["device_id"], "device_name": device["device_name"], @@ -466,14 +466,14 @@ async def getClimate(self, device: dict): "parentDevice": data.get("parent", None), "custom": device.get("custom", None), "attributes": await self.session.attr.stateAttributes( - device["device_id"], device["hiveType"] + device["device_id"], device.hive_type ), } - self.session.devices.update({device["hiveID"]: dev_data}) - return self.session.devices[device["hiveID"]] + self.session.devices.update({device.hive_id: dev_data}) + return self.session.devices[device.hive_id] else: await self.session.log.errorCheck( - device["device_id"], "ERROR", device["deviceData"]["online"] + device["device_id"], "ERROR", device.device_data["online"] ) return device @@ -492,7 +492,7 @@ async def getScheduleNowNextLater(self, device: dict): try: if online and current_mode == "SCHEDULE": - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = self.session.helper.getScheduleNNL(data["state"]["schedule"]) except KeyError as e: await self.session.log.error(e) @@ -512,7 +512,7 @@ async def minmaxTemperature(self, device: dict): final = None try: - state = self.session.data.minMax[device["hiveID"]] + state = self.session.data.minMax[device.hive_id] final = state except KeyError as e: await self.session.log.error(e) diff --git a/src/helper/const.py b/src/helper/const.py index 3fa5588..71fd5f0 100644 --- a/src/helper/const.py +++ b/src/helper/const.py @@ -1,5 +1,7 @@ """Constants for Pyhiveapi.""" +from .hivedataclasses import EntityConfig + # pylint: skip-file SYNC_PACKAGE_NAME = "pyhiveapi" SYNC_PACKAGE_DIR = "/pyhiveapi/" @@ -71,7 +73,7 @@ "Hotwater_Mode": "self.session.hotwater.getMode(device)", "Hotwater_Boost": "self.session.hotwater.getBoost(device)", "Battery": 'self.session.attr.getBattery(device["device_id"])', - "Mode": 'self.session.attr.getMode(device["hiveID"])', + "Mode": "self.session.attr.getMode(device.hive_id)", "Availability": "self.online(device)", "Connectivity": "self.online(device)", "Power": "self.session.switch.getPowerUsage(device)", @@ -79,93 +81,269 @@ PRODUCTS = { "sense": [ - 'addList("binary_sensor", p, haName="Glass Detection", hiveType="GLASS_BREAK")', - 'addList("binary_sensor", p, haName="Smoke Detection", hiveType="SMOKE_CO")', - 'addList("binary_sensor", p, haName="Dog Bark Detection", hiveType="DOG_BARK")', + EntityConfig( + entity_type="binary_sensor", + ha_name="Glass Detection", + hive_type="GLASS_BREAK", + ), + EntityConfig( + entity_type="binary_sensor", ha_name="Smoke Detection", hive_type="SMOKE_CO" + ), + EntityConfig( + entity_type="binary_sensor", + ha_name="Dog Bark Detection", + hive_type="DOG_BARK", + ), ], "heating": [ - 'addList("climate", p, temperatureunit=self.data["user"]["temperatureUnit"])', - 'addList("switch", p, haName=" Heat on Demand", hiveType="Heating_Heat_On_Demand", category="config")', - 'addList("sensor", p, haName=" Current Temperature", hiveType="Heating_Current_Temperature", category="diagnostic")', - 'addList("sensor", p, haName=" Target Temperature", hiveType="Heating_Target_Temperature", category="diagnostic")', - 'addList("sensor", p, haName=" State", hiveType="Heating_State", category="diagnostic")', - 'addList("sensor", p, haName=" Mode", hiveType="Heating_Mode", category="diagnostic")', - 'addList("sensor", p, haName=" Boost", hiveType="Heating_Boost", category="diagnostic")', + EntityConfig(entity_type="climate", temperature_unit="user.temperatureUnit"), + EntityConfig( + entity_type="switch", + ha_name="Heat on Demand", + hive_type="Heating_Heat_On_Demand", + category="config", + ), + EntityConfig( + entity_type="sensor", + ha_name="Current Temperature", + hive_type="Heating_Current_Temperature", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name="Target Temperature", + hive_type="Heating_Target_Temperature", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name="State", + hive_type="Heating_State", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name="Mode", + hive_type="Heating_Mode", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name="Boost", + hive_type="Heating_Boost", + category="diagnostic", + ), ], "trvcontrol": [ - 'addList("climate", p, temperatureunit=self.data["user"]["temperatureUnit"])', - 'addList("sensor", p, haName=" Current Temperature", hiveType="Heating_Current_Temperature", category="diagnostic")', - 'addList("sensor", p, haName=" Target Temperature", hiveType="Heating_Target_Temperature", category="diagnostic")', - 'addList("sensor", p, haName=" State", hiveType="Heating_State", category="diagnostic")', - 'addList("sensor", p, haName=" Mode", hiveType="Heating_Mode", category="diagnostic")', - 'addList("sensor", p, haName=" Boost", hiveType="Heating_Boost", category="diagnostic")', + EntityConfig(entity_type="climate", temperature_unit="user.temperatureUnit"), + EntityConfig( + entity_type="switch", + ha_name="Heat on Demand", + hive_type="Heating_Heat_On_Demand", + category="config", + ), + EntityConfig( + entity_type="sensor", + ha_name="Current Temperature", + hive_type="Heating_Current_Temperature", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name="Target Temperature", + hive_type="Heating_Target_Temperature", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name="State", + hive_type="Heating_State", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name="Mode", + hive_type="Heating_Mode", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name="Boost", + hive_type="Heating_Boost", + category="diagnostic", + ), ], "hotwater": [ - 'addList("water_heater", p,)', - 'addList("sensor", p, haName="Hotwater State", hiveType="Hotwater_State", category="diagnostic")', - 'addList("sensor", p, haName="Hotwater Mode", hiveType="Hotwater_Mode", category="diagnostic")', - 'addList("sensor", p, haName="Hotwater Boost", hiveType="Hotwater_Boost", category="diagnostic")', + EntityConfig( + entity_type="water_heater", + ha_name="Hotwater State", + hive_type="Hotwater_State", + ), + EntityConfig( + entity_type="sensor", + ha_name="Hotwater Mode", + hive_type="Hotwater_Mode", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name="Hotwater Boost", + hive_type="Hotwater_Boost", + category="diagnostic", + ), ], "activeplug": [ - 'addList("switch", p)', - 'addList("sensor", p, haName=" Mode", hiveType="Mode", category="diagnostic")', - 'addList("sensor", p, haName=" Availability", hiveType="Availability", category="diagnostic")', - 'addList("sensor", p, haName=" Power", hiveType="Power", category="diagnostic")', + EntityConfig(entity_type="switch"), + EntityConfig( + entity_type="sensor", + ha_name=" Mode", + hive_type="Mode", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name=" Availability", + hive_type="Availability", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name=" Power", + hive_type="Power", + category="diagnostic", + ), ], "warmwhitelight": [ - 'addList("light", p)', - 'addList("sensor", p, haName=" Mode", hiveType="Mode", category="diagnostic")', - 'addList("sensor", p, haName=" Availability", hiveType="Availability", category="diagnostic")', + EntityConfig(entity_type="light"), + EntityConfig( + entity_type="sensor", + ha_name=" Mode", + hive_type="Mode", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name=" Availability", + hive_type="Availability", + category="diagnostic", + ), ], "tuneablelight": [ - 'addList("light", p)', - 'addList("sensor", p, haName=" Mode", hiveType="Mode", category="diagnostic")', - 'addList("sensor", p, haName=" Availability", hiveType="Availability", category="diagnostic")', + EntityConfig(entity_type="light"), + EntityConfig( + entity_type="sensor", + ha_name=" Mode", + hive_type="Mode", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name=" Availability", + hive_type="Availability", + category="diagnostic", + ), ], "colourtuneablelight": [ - 'addList("light", p)', - 'addList("sensor", p, haName=" Mode", hiveType="Mode", category="diagnostic")', - 'addList("sensor", p, haName=" Availability", hiveType="Availability", category="diagnostic")', - ], - # "hivecamera": [ - # 'addList("camera", p)', - # 'addList("sensor", p, haName=" Mode", hiveType="Mode", category="diagnostic")', - # 'addList("sensor", p, haName=" Availability", hiveType="Availability", category="diagnostic")', - # 'addList("sensor", p, haName=" Temperature", hiveType="Camera_Temp", category="diagnostic")', - # ], + EntityConfig(entity_type="light"), + EntityConfig( + entity_type="sensor", + ha_name=" Mode", + hive_type="Mode", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name=" Availability", + hive_type="Availability", + category="diagnostic", + ), + ], "motionsensor": [ - 'addList("binary_sensor", p)', - 'addList("sensor", p, haName=" Current Temperature", hiveType="Current_Temperature", category="diagnostic")', + EntityConfig(entity_type="binary_sensor"), + EntityConfig( + entity_type="sensor", + ha_name=" Current Temperature", + hive_type="Current_Temperature", + category="diagnostic", + ), + ], + "contactsensor": [ + EntityConfig(entity_type="binary_sensor"), ], - "contactsensor": ['addList("binary_sensor", p)'], } DEVICES = { "contactsensor": [ - 'addList("sensor", d, haName=" Battery Level", hiveType="Battery", category="diagnostic")', - 'addList("sensor", d, haName=" Availability", hiveType="Availability", category="diagnostic")', + EntityConfig( + entity_type="sensor", + ha_name=" Battery Level", + hive_type="Battery", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name=" Availability", + hive_type="Availability", + category="diagnostic", + ), ], "hub": [ - 'addList("binary_sensor", d, haName="Hive Hub Status", hiveType="Connectivity", category="diagnostic")', + EntityConfig( + entity_type="binary_sensor", + ha_name="Hive Hub Status", + hive_type="Connectivity", + category="diagnostic", + ), ], "motionsensor": [ - 'addList("sensor", d, haName=" Battery Level", hiveType="Battery", category="diagnostic")', - 'addList("sensor", d, haName=" Availability", hiveType="Availability", category="diagnostic")', + EntityConfig( + entity_type="sensor", + ha_name=" Battery Level", + hive_type="Battery", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name=" Availability", + hive_type="Availability", + category="diagnostic", + ), ], "sense": [ - 'addList("binary_sensor", d, haName="Hive Hub Status", hiveType="Connectivity")', + EntityConfig( + entity_type="binary_sensor", + ha_name="Hive Hub Status", + hive_type="Connectivity", + ), ], - "siren": ['addList("alarm_control_panel", d)'], "thermostatui": [ - 'addList("sensor", d, haName=" Battery Level", hiveType="Battery", category="diagnostic")', - 'addList("sensor", d, haName=" Availability", hiveType="Availability", category="diagnostic")', + EntityConfig( + entity_type="sensor", + ha_name=" Battery Level", + hive_type="Battery", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name=" Availability", + hive_type="Availability", + category="diagnostic", + ), ], "trv": [ - 'addList("sensor", d, haName=" Battery Level", hiveType="Battery", category="diagnostic")', - 'addList("sensor", d, haName=" Availability", hiveType="Availability", category="diagnostic")', + EntityConfig( + entity_type="sensor", + ha_name=" Battery Level", + hive_type="Battery", + category="diagnostic", + ), + EntityConfig( + entity_type="sensor", + ha_name=" Availability", + hive_type="Availability", + category="diagnostic", + ), ], } -ACTIONS = ( - 'addList("switch", a, hiveName=a["name"], haName=a["name"], hiveType="action")' -) +ACTIONS = EntityConfig(entity_type="switch", ha_name="action.name", hive_type="action") diff --git a/src/helper/hive_helper.py b/src/helper/hive_helper.py index 051d9d5..18bed0b 100644 --- a/src/helper/hive_helper.py +++ b/src/helper/hive_helper.py @@ -5,6 +5,7 @@ import operator from .const import HIVE_TYPES +from .hivedataclasses import EntityConfig class HiveHelper: @@ -209,6 +210,21 @@ def getHeatOnDemandDevice(self, device: dict): Returns: [dictionary]: [Gets the thermostat device linked to TRV.] """ - trv = self.session.data.products.get(device["HiveID"]) + trv = self.session.data.products.get(device.hive_id) thermostat = self.session.data.products.get(trv["state"]["zone"]) return thermostat + + def _build_kwargs(self, config: EntityConfig) -> dict: + """Build kwargs dict from EntityConfig, excluding None values.""" + kwargs = {} + + if config.ha_name: + kwargs["haName"] = config.ha_name + if config.hive_type: + kwargs["hiveType"] = config.hive_type + if config.category: + kwargs["category"] = config.category + if config.temperature_unit: + kwargs["temperatureunit"] = self.session.data["user"]["temperatureUnit"] + + return kwargs diff --git a/src/helper/hivedataclasses.py b/src/helper/hivedataclasses.py index 184b3cb..6c0fb23 100644 --- a/src/helper/hivedataclasses.py +++ b/src/helper/hivedataclasses.py @@ -3,20 +3,45 @@ # pylint: skip-file from dataclasses import dataclass +from typing import Literal, Optional @dataclass class Device: - """Class for keeping track of an device.""" - - hiveID: str - hiveName: str - hiveType: str - haType: str - deviceData: dict - status: dict - data: dict - parentDevice: str - isGroup: bool + """Class for keeping track of a device.""" + + hive_id: str + hive_name: str + hive_type: str + ha_type: str device_id: str device_name: str + device_data: dict + parent_device: Optional[str] = None + is_group: bool = False + ha_name: str = "" + category: Optional[str] = None + temperature_unit: Optional[str] = None + # Add status and data as optional since not always populated at creation + status: Optional[dict] = None + data: Optional[dict] = None + + +@dataclass +class EntityConfig: + """Configuration for creating a device entity.""" + + entity_type: Literal[ + "sensor", + "binary_sensor", + "climate", + "light", + "switch", + "water_heater", + "alarm_control_panel", + "camera", + ] + ha_name: str = "" + hive_type: str = "" + category: Optional[str] = None + temperature_unit: Optional[str] = None diff --git a/src/hotwater.py b/src/hotwater.py index 1466205..4f03b83 100644 --- a/src/hotwater.py +++ b/src/hotwater.py @@ -27,7 +27,7 @@ async def getMode(self, device: dict): final = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["state"]["mode"] if state == "BOOST": state = data["props"]["previous"]["mode"] @@ -59,7 +59,7 @@ async def getBoost(self, device: dict): final = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["state"]["boost"] final = HIVETOHA["Boost"].get(state, "ON") except KeyError as e: @@ -79,7 +79,7 @@ async def getBoostTime(self, device: dict): state = None if await self.getBoost(device) == "ON": try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["state"]["boost"] except KeyError as e: await self.session.log.error(e) @@ -99,7 +99,7 @@ async def getState(self, device: dict): final = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["state"]["status"] mode_current = await self.getMode(device) if mode_current == "SCHEDULE": @@ -127,15 +127,15 @@ async def setMode(self, device: dict, new_mode: str): """ final = False - if device["hiveID"] in self.session.data.products: + if device.hive_id in self.session.data.products: await self.session.hiveRefreshTokens() - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] resp = await self.session.api.setState( - data["type"], device["hiveID"], mode=new_mode + data["type"], device.hive_id, mode=new_mode ) if resp["original"] == 200: final = True - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) return final @@ -153,17 +153,17 @@ async def setBoostOn(self, device: dict, mins: int): if ( int(mins) > 0 - and device["hiveID"] in self.session.data.products - and device["deviceData"]["online"] + and device.hive_id in self.session.data.products + and device.device_data["online"] ): await self.session.hiveRefreshTokens() - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] resp = await self.session.api.setState( - data["type"], device["hiveID"], mode="BOOST", boost=mins + data["type"], device.hive_id, mode="BOOST", boost=mins ) if resp["original"] == 200: final = True - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) return final @@ -179,18 +179,18 @@ async def setBoostOff(self, device: dict): final = False if ( - device["hiveID"] in self.session.data.products + device.hive_id in self.session.data.products and await self.getBoost(device) == "ON" - and device["deviceData"]["online"] + and device.device_data["online"] ): await self.session.hiveRefreshTokens() - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] prev_mode = data["props"]["previous"]["mode"] resp = await self.session.api.setState( - data["type"], device["hiveID"], mode=prev_mode + data["type"], device.hive_id, mode=prev_mode ) if resp["original"] == 200: - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) final = True return final @@ -220,20 +220,20 @@ async def getWaterHeater(self, device: dict): Returns: dict: Updated device. """ - device["deviceData"].update( + device.device_data.update( {"online": await self.session.attr.onlineOffline(device["device_id"])} ) - if device["deviceData"]["online"]: + if device.device_data["online"]: dev_data = {} self.session.helper.deviceRecovered(device["device_id"]) data = self.session.data.devices[device["device_id"]] dev_data = { - "hiveID": device["hiveID"], - "hiveName": device["hiveName"], - "hiveType": device["hiveType"], - "haName": device["haName"], + "hiveID": device.hive_id, + "hiveName": device.hive_name, + "hiveType": device.hive_type, + "haName": device.ha_name, "haType": device["haType"], "device_id": device["device_id"], "device_name": device["device_name"], @@ -242,15 +242,15 @@ async def getWaterHeater(self, device: dict): "parentDevice": data.get("parent", None), "custom": device.get("custom", None), "attributes": await self.session.attr.stateAttributes( - device["device_id"], device["hiveType"] + device["device_id"], device.hive_type ), } - self.session.devices.update({device["hiveID"]: dev_data}) - return self.session.devices[device["hiveID"]] + self.session.devices.update({device.hive_id: dev_data}) + return self.session.devices[device.hive_id] else: await self.session.log.errorCheck( - device["device_id"], "ERROR", device["deviceData"]["online"] + device["device_id"], "ERROR", device.device_data["online"] ) return device @@ -268,7 +268,7 @@ async def getScheduleNowNextLater(self, device: dict): try: mode_current = await self.getMode(device) if mode_current == "SCHEDULE": - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = self.session.helper.getScheduleNNL(data["state"]["schedule"]) except KeyError as e: await self.session.log.error(e) diff --git a/src/hub.py b/src/hub.py index de34fa2..94ea6e1 100644 --- a/src/hub.py +++ b/src/hub.py @@ -35,7 +35,7 @@ async def getSmokeStatus(self, device: dict): final = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["props"]["sensors"]["SMOKE_CO"]["active"] final = HIVETOHA[self.hubType]["Smoke"].get(state, state) except KeyError as e: @@ -56,7 +56,7 @@ async def getDogBarkStatus(self, device: dict): final = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["props"]["sensors"]["DOG_BARK"]["active"] final = HIVETOHA[self.hubType]["Dog"].get(state, state) except KeyError as e: @@ -77,7 +77,7 @@ async def getGlassBreakStatus(self, device: dict): final = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["props"]["sensors"]["GLASS_BREAK"]["active"] final = HIVETOHA[self.hubType]["Glass"].get(state, state) except KeyError as e: diff --git a/src/light.py b/src/light.py index abab4d7..e2d71b5 100644 --- a/src/light.py +++ b/src/light.py @@ -28,7 +28,7 @@ async def getState(self, device: dict): final = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["state"]["status"] final = HIVETOHA[self.lightType].get(state, state) except KeyError as e: @@ -49,7 +49,7 @@ async def getBrightness(self, device: dict): final = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["state"]["brightness"] final = (state / 100) * 255 except KeyError as e: @@ -70,7 +70,7 @@ async def getMinColorTemp(self, device: dict): final = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["props"]["colourTemperature"]["max"] final = round((1 / state) * 1000000) except KeyError as e: @@ -91,7 +91,7 @@ async def getMaxColorTemp(self, device: dict): final = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["props"]["colourTemperature"]["min"] final = round((1 / state) * 1000000) except KeyError as e: @@ -112,7 +112,7 @@ async def getColorTemp(self, device: dict): final = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["state"]["colourTemperature"] final = round((1 / state) * 1000000) except KeyError as e: @@ -133,7 +133,7 @@ async def getColor(self, device: dict): final = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = [ (data["state"]["hue"]) / 360, (data["state"]["saturation"]) / 100, @@ -159,7 +159,7 @@ async def getColorMode(self, device: dict): state = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["state"]["colourMode"] except KeyError as e: await self.session.log.error(e) @@ -178,18 +178,18 @@ async def setStatusOff(self, device: dict): final = False if ( - device["hiveID"] in self.session.data.products - and device["deviceData"]["online"] + device.hive_id in self.session.data.products + and device.device_data["online"] ): await self.session.hiveRefreshTokens() - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] resp = await self.session.api.setState( - data["type"], device["hiveID"], status="OFF" + data["type"], device.hive_id, status="OFF" ) if resp["original"] == 200: final = True - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) return final @@ -205,18 +205,18 @@ async def setStatusOn(self, device: dict): final = False if ( - device["hiveID"] in self.session.data.products - and device["deviceData"]["online"] + device.hive_id in self.session.data.products + and device.device_data["online"] ): await self.session.hiveRefreshTokens() - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] resp = await self.session.api.setState( - data["type"], device["hiveID"], status="ON" + data["type"], device.hive_id, status="ON" ) if resp["original"] == 200: final = True - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) return final @@ -233,20 +233,20 @@ async def setBrightness(self, device: dict, n_brightness: int): final = False if ( - device["hiveID"] in self.session.data.products - and device["deviceData"]["online"] + device.hive_id in self.session.data.products + and device.device_data["online"] ): await self.session.hiveRefreshTokens() - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] resp = await self.session.api.setState( data["type"], - device["hiveID"], + device.hive_id, status="ON", brightness=n_brightness, ) if resp["original"] == 200: final = True - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) return final @@ -263,29 +263,29 @@ async def setColorTemp(self, device: dict, color_temp: int): final = False if ( - device["hiveID"] in self.session.data.products - and device["deviceData"]["online"] + device.hive_id in self.session.data.products + and device.device_data["online"] ): await self.session.hiveRefreshTokens() - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] if data["type"] == "tuneablelight": resp = await self.session.api.setState( data["type"], - device["hiveID"], + device.hive_id, colourTemperature=color_temp, ) else: resp = await self.session.api.setState( data["type"], - device["hiveID"], + device.hive_id, colourMode="WHITE", colourTemperature=color_temp, ) if resp["original"] == 200: final = True - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) return final @@ -302,15 +302,15 @@ async def setColor(self, device: dict, new_color: list): final = False if ( - device["hiveID"] in self.session.data.products - and device["deviceData"]["online"] + device.hive_id in self.session.data.products + and device.device_data["online"] ): await self.session.hiveRefreshTokens() - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] resp = await self.session.api.setState( data["type"], - device["hiveID"], + device.hive_id, colourMode="COLOUR", hue=str(new_color[0]), saturation=str(new_color[1]), @@ -318,7 +318,7 @@ async def setColor(self, device: dict, new_color: list): ) if resp["original"] == 200: final = True - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) return final @@ -347,19 +347,19 @@ async def getLight(self, device: dict): Returns: dict: Updated device. """ - device["deviceData"].update( + device.device_data.update( {"online": await self.session.attr.onlineOffline(device["device_id"])} ) dev_data = {} - if device["deviceData"]["online"]: + if device.device_data["online"]: self.session.helper.deviceRecovered(device["device_id"]) data = self.session.data.devices[device["device_id"]] dev_data = { - "hiveID": device["hiveID"], - "hiveName": device["hiveName"], - "hiveType": device["hiveType"], - "haName": device["haName"], + "hiveID": device.hive_id, + "hiveName": device.hive_name, + "hiveType": device.hive_type, + "haName": device.ha_name, "haType": device["haType"], "device_id": device["device_id"], "device_name": device["device_name"], @@ -371,11 +371,11 @@ async def getLight(self, device: dict): "parentDevice": data.get("parent", None), "custom": device.get("custom", None), "attributes": await self.session.attr.stateAttributes( - device["device_id"], device["hiveType"] + device["device_id"], device.hive_type ), } - if device["hiveType"] in ("tuneablelight", "colourtuneablelight"): + if device.hive_type in ("tuneablelight", "colourtuneablelight"): dev_data.update( { "min_mireds": await self.getMinColorTemp(device), @@ -385,7 +385,7 @@ async def getLight(self, device: dict): dev_data["status"].update( {"color_temp": await self.getColorTemp(device)} ) - if device["hiveType"] == "colourtuneablelight": + if device.hive_type == "colourtuneablelight": mode = await self.getColorMode(device) if mode == "COLOUR": dev_data["status"].update( @@ -401,11 +401,11 @@ async def getLight(self, device: dict): } ) - self.session.devices.update({device["hiveID"]: dev_data}) - return self.session.devices[device["hiveID"]] + self.session.devices.update({device.hive_id: dev_data}) + return self.session.devices[device.hive_id] else: await self.session.log.errorCheck( - device["device_id"], "ERROR", device["deviceData"]["online"] + device["device_id"], "ERROR", device.device_data["online"] ) return device diff --git a/src/plug.py b/src/plug.py index 05e4b5e..ecf7a57 100644 --- a/src/plug.py +++ b/src/plug.py @@ -25,7 +25,7 @@ async def getState(self, device: dict): state = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["state"]["status"] state = HIVETOHA["Switch"].get(state, state) except KeyError as e: @@ -45,7 +45,7 @@ async def getPowerUsage(self, device: dict): state = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] state = data["props"]["powerConsumption"] except KeyError as e: await self.session.log.error(e) @@ -64,17 +64,17 @@ async def setStatusOn(self, device: dict): final = False if ( - device["hiveID"] in self.session.data.products - and device["deviceData"]["online"] + device.hive_id in self.session.data.products + and device.device_data["online"] ): await self.session.hiveRefreshTokens() - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] resp = await self.session.api.setState( data["type"], data["id"], status="ON" ) if resp["original"] == 200: final = True - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) return final @@ -90,17 +90,17 @@ async def setStatusOff(self, device: dict): final = False if ( - device["hiveID"] in self.session.data.products - and device["deviceData"]["online"] + device.hive_id in self.session.data.products + and device.device_data["online"] ): await self.session.hiveRefreshTokens() - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] resp = await self.session.api.setState( data["type"], data["id"], status="OFF" ) if resp["original"] == 200: final = True - await self.session.getDevices(device["hiveID"]) + await self.session.getDevices(device.hive_id) return final @@ -129,19 +129,19 @@ async def getSwitch(self, device: dict): Returns: dict: Return device after update is complete. """ - device["deviceData"].update( + device.device_data.update( {"online": await self.session.attr.onlineOffline(device["device_id"])} ) dev_data = {} - if device["deviceData"]["online"]: + if device.device_data["online"]: self.session.helper.deviceRecovered(device["device_id"]) data = self.session.data.devices[device["device_id"]] dev_data = { - "hiveID": device["hiveID"], - "hiveName": device["hiveName"], - "hiveType": device["hiveType"], - "haName": device["haName"], + "hiveID": device.hive_id, + "hiveName": device.hive_name, + "hiveType": device.hive_type, + "haName": device.ha_name, "haType": device["haType"], "device_id": device["device_id"], "device_name": device["device_name"], @@ -154,7 +154,7 @@ async def getSwitch(self, device: dict): "attributes": {}, } - if device["hiveType"] == "activeplug": + if device.hive_type == "activeplug": dev_data.update( { "status": { @@ -162,16 +162,16 @@ async def getSwitch(self, device: dict): "power_usage": await self.getPowerUsage(device), }, "attributes": await self.session.attr.stateAttributes( - device["device_id"], device["hiveType"] + device["device_id"], device.hive_type ), } ) - self.session.devices.update({device["hiveID"]: dev_data}) - return self.session.devices[device["hiveID"]] + self.session.devices.update({device.hive_id: dev_data}) + return self.session.devices[device.hive_id] else: await self.session.log.errorCheck( - device["device_id"], "ERROR", device["deviceData"]["online"] + device["device_id"], "ERROR", device.device_data["online"] ) return device @@ -184,7 +184,7 @@ async def getSwitchState(self, device: dict): Returns: boolean: Return True or False for the state. """ - if device["hiveType"] == "Heating_Heat_On_Demand": + if device.hive_type == "Heating_Heat_On_Demand": return await self.session.heating.getHeatOnDemand(device) else: return await self.getState(device) @@ -198,7 +198,7 @@ async def turnOn(self, device: dict): Returns: function: Calls relevant function. """ - if device["hiveType"] == "Heating_Heat_On_Demand": + if device.hive_type == "Heating_Heat_On_Demand": return await self.session.heating.setHeatOnDemand(device, "ENABLED") else: return await self.setStatusOn(device) @@ -212,7 +212,7 @@ async def turnOff(self, device: dict): Returns: function: Calls relevant function. """ - if device["hiveType"] == "Heating_Heat_On_Demand": + if device.hive_type == "Heating_Heat_On_Demand": return await self.session.heating.setHeatOnDemand(device, "DISABLED") else: return await self.setStatusOff(device) diff --git a/src/sensor.py b/src/sensor.py index 1fc6c63..20c78f5 100644 --- a/src/sensor.py +++ b/src/sensor.py @@ -22,7 +22,7 @@ async def getState(self, device: dict): final = None try: - data = self.session.data.products[device["hiveID"]] + data = self.session.data.products[device.hive_id] if data["type"] == "contactsensor": state = data["props"]["status"] final = HIVETOHA[self.sensorType].get(state, state) @@ -79,24 +79,24 @@ async def getSensor(self, device: dict): Returns: dict: Updated device. """ - device["deviceData"].update( + device.device_data.update( {"online": await self.session.attr.onlineOffline(device["device_id"])} ) data = {} - if device["deviceData"]["online"] or device["hiveType"] in ( + if device.device_data["online"] or device.hive_type in ( "Availability", "Connectivity", ): - if device["hiveType"] not in ("Availability", "Connectivity"): + if device.hive_type not in ("Availability", "Connectivity"): self.session.helper.deviceRecovered(device["device_id"]) dev_data = {} dev_data = { - "hiveID": device["hiveID"], - "hiveName": device["hiveName"], - "hiveType": device["hiveType"], - "haName": device["haName"], + "hiveID": device.hive_id, + "hiveName": device.hive_name, + "hiveType": device.hive_type, + "haName": device.ha_name, "haType": device["haType"], "device_id": device.get("device_id", None), "device_name": device.get("device_name", None), @@ -106,8 +106,8 @@ async def getSensor(self, device: dict): if device["device_id"] in self.session.data.devices: data = self.session.data.devices.get(device["device_id"], {}) - elif device["hiveID"] in self.session.data.products: - data = self.session.data.products.get(device["hiveID"], {}) + elif device.hive_id in self.session.data.products: + data = self.session.data.products.get(device.hive_id, {}) if ( dev_data["hiveType"] in sensor_commands @@ -124,23 +124,23 @@ async def getSensor(self, device: dict): "parentDevice": data.get("parent", None), } ) - elif device["hiveType"] in HIVE_TYPES["Sensor"]: - data = self.session.data.devices.get(device["hiveID"], {}) + elif device.hive_type in HIVE_TYPES["Sensor"]: + data = self.session.data.devices.get(device.hive_id, {}) dev_data.update( { "status": {"state": await self.getState(device)}, "deviceData": data.get("props", None), "parentDevice": data.get("parent", None), "attributes": await self.session.attr.stateAttributes( - device["device_id"], device["hiveType"] + device["device_id"], device.hive_type ), } ) - self.session.devices.update({device["hiveID"]: dev_data}) - return self.session.devices[device["hiveID"]] + self.session.devices.update({device.hive_id: dev_data}) + return self.session.devices[device.hive_id] else: await self.session.log.errorCheck( - device["device_id"], "ERROR", device["deviceData"]["online"] + device["device_id"], "ERROR", device.device_data["online"] ) return device diff --git a/src/session.py b/src/session.py index 2d9a64a..e696dbf 100644 --- a/src/session.py +++ b/src/session.py @@ -8,12 +8,13 @@ import os import time from datetime import datetime, timedelta +from typing import Optional from aiohttp.web import HTTPException from apyhiveapi import API, Auth from .device_attributes import HiveAttributes -from .helper.const import ACTIONS, DEVICES, HIVE_TYPES, PRODUCTS +from .helper.const import DEVICES, HIVE_TYPES, PRODUCTS from .helper.hive_exceptions import ( HiveApiError, HiveFailedToRefreshTokens, @@ -26,6 +27,7 @@ NoApiToken, ) from .helper.hive_helper import HiveHelper +from .helper.hivedataclasses import Device from .helper.logger import Logger from .helper.map import Map @@ -120,15 +122,16 @@ def openFile(self, file: str): return data - def addList(self, entityType: str, data: dict, **kwargs: dict): + def addList(self, entity_type: str, data: dict, **kwargs: dict) -> Optional[Device]: """Add entity to the list. Args: - type (str): Type of entity + entityType (str): Type of entity data (dict): Information to create entity. + **kwargs: Additional device attributes (ha_name, category, etc.) Returns: - dict: Entity. + Optional[Device]: Device dataclass instance, or None on error. """ try: device = self.helper.getDeviceData(data) @@ -137,34 +140,35 @@ def addList(self, entityType: str, data: dict, **kwargs: dict): if device["state"]["name"] != "Receiver" else "Heating" ) - formatted_data = {} - - formatted_data = { - "hiveID": data.get("id", ""), - "hiveName": device_name, - "hiveType": data.get("type", ""), - "haType": entityType, - "deviceData": device.get("props", data.get("props", {})), - "parentDevice": self.hub_id, - "isGroup": data.get("isGroup", False), - "device_id": device["id"], - "device_name": device_name, - } - - if kwargs.get("haName", "FALSE")[0] == " ": - kwargs["haName"] = device_name + kwargs["haName"] - else: - formatted_data["haName"] = device_name - formatted_data.update(kwargs) + # Handle ha_name logic + ha_name = kwargs.get("ha_name", device_name) + if ha_name and ha_name[0] == " ": + ha_name = device_name + ha_name + + # Create Device instance + device_obj = Device( + hive_id=data.get("id", ""), + hive_name=device_name, + hive_type=data.get("type", ""), + ha_type=entity_type, + device_id=device["id"], + device_name=device_name, + device_data=device.get("props", data.get("props", {})), + parent_device=self.hub_id, + is_group=data.get("isGroup", False), + ha_name=ha_name, + category=kwargs.get("category"), + temperature_unit=kwargs.get("temperatureunit"), + ) if data.get("type", "") == "hub": - self.deviceList["parent"].append(formatted_data) - self.deviceList[entityType].append(formatted_data) + self.deviceList["parent_device"].append(device_obj) + self.deviceList[entity_type].append(device_obj) else: - self.deviceList[entityType].append(formatted_data) + self.deviceList[entity_type].append(device_obj) - return formatted_data + return device_obj except KeyError as error: self.logger.error(error) return None @@ -338,7 +342,7 @@ async def updateData(self, device: dict): if datetime.now() >= ep and not self.updateLock.locked(): try: await self.updateLock.acquire() - await self.getDevices(device["hiveID"]) + await self.getDevices(device.hive_id) if len(self.deviceList["camera"]) > 0: for camera in self.data.camera: await self.getCamera(self.devices[camera]) @@ -532,7 +536,7 @@ async def createDevices(self): Returns: list: List of devices """ - self.deviceList["parent"] = [] + self.deviceList["parent_device"] = [] self.deviceList["alarm_control_panel"] = [] self.deviceList["binary_sensor"] = [] self.deviceList["camera"] = [] @@ -543,45 +547,48 @@ async def createDevices(self): self.deviceList["water_heater"] = [] hive_type = HIVE_TYPES["Thermo"] + HIVE_TYPES["Sensor"] - for aDevice in self.data["devices"]: - if self.data["devices"][aDevice]["type"] == "hub": - self.hub_id = aDevice + for device_id, device_data in self.data["devices"].items(): + if device_data["type"] == "hub": + self.hub_id = device_id break - for aDevice in self.data["devices"]: - d = self.data.devices[aDevice] - device_list = DEVICES.get(self.data.devices[aDevice]["type"], []) - for code in device_list: - eval("self." + code) - if self.data["devices"][aDevice]["type"] in hive_type: - self.config.battery.append(d["id"]) + for device_id, device_data in self.data["devices"].items(): + entity_configs = DEVICES.get(device_data["type"], []) + + for config in entity_configs: + kwargs = self.helper._build_kwargs(config) + self.addList(config.entity_type, device_data, **kwargs) - if "action" in HIVE_TYPES["Switch"]: - for action in self.data["actions"]: - a = self.data["actions"][action] # noqa: F841 - eval("self." + ACTIONS) + if device_data["type"] in hive_type: + self.config.battery.append(device_data["id"]) hive_type = HIVE_TYPES["Heating"] + HIVE_TYPES["Switch"] + HIVE_TYPES["Light"] - for aProduct in self.data.products: - p = self.data.products[aProduct] - if "error" in p: + for product_id, product_data in self.data.products.items(): + if "error" in product_data: continue - # Only consider single items or heating groups + + # Skip non-heating groups if ( - p.get("isGroup", False) - and self.data.products[aProduct]["type"] not in HIVE_TYPES["Heating"] + product_data.get("isGroup", False) + and product_data["type"] not in HIVE_TYPES["Heating"] ): continue - product_list = PRODUCTS.get(self.data.products[aProduct]["type"], []) - product_name = self.data.products[aProduct]["state"].get("name", "Unknown") - for code in product_list: + + entity_configs = PRODUCTS.get(product_data["type"], []) + + for config in entity_configs: + kwargs = self.helper._build_kwargs(config) + try: - eval("self." + code) + self.addList(config.entity_type, product_data, **kwargs) except (NameError, AttributeError) as e: - self.logger.warning(f"Device {product_name} cannot be setup - {e}") + product_name = product_data["state"].get("name", "Unknown") + self.logger.warning( + f"Device {product_id}-{product_name} cannot be setup - {e}" + ) - if self.data.products[aProduct]["type"] in hive_type: - self.config.mode.append(p["id"]) + if product_data["type"] in hive_type: + self.config.mode.append(product_data["id"]) return self.deviceList From f4aaa090ab9b1796d8945ef103d1f74b87c66122 Mon Sep 17 00:00:00 2001 From: Khole Jones Date: Sun, 9 Nov 2025 23:52:41 +0000 Subject: [PATCH 2/6] refactor: improve debugger code quality and fix trace functionality - Fixed sys.settrace implementation to properly enable/disable tracing - Renamed variables to follow Python naming conventions (snake_case) - Added proper return values to trace functions and __exit__ method --- src/helper/debugger.py | 38 +++++++++++++++++++++----------------- src/helper/map.py | 2 -- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/helper/debugger.py b/src/helper/debugger.py index f3a3102..14934a7 100644 --- a/src/helper/debugger.py +++ b/src/helper/debugger.py @@ -1,7 +1,7 @@ """Debugger file.""" -# pylint: skip-file import logging +import sys class DebugContext: @@ -12,43 +12,47 @@ def __init__(self, name, enabled): self.name = name self.enabled = enabled self.logging = logging.getLogger(__name__) - self.debugOutFolder = "" - self.debugOutFile = "" - self.debugEnabled = False - self.debugList = [] + self.debug_out_folder = "" + self.debug_out_file = "" + self.debug_enabled = False + self.debug_list = [] def __enter__(self): """Set trace calls on entering debugger.""" print("Entering Debug Decorated func") # Set the trace function to the trace_calls function # So all events are now traced - self.traceCalls + sys.settrace(self.trace_calls) + return self - def traceCalls(self, frame, event, arg): + def __exit__(self, exc_type, exc_val, exc_tb): + """Clean up trace on exiting debugger.""" + print("Exiting Debug Decorated func") + sys.settrace(None) + return False + + def trace_calls(self, frame, event, _arg): """Trace calls be made.""" # We want to only trace our call to the decorated function if event != "call": - return - elif frame.f_code.co_name != self.name: - return + return None + if frame.f_code.co_name != self.name: + return None # return the trace function to use when you go into that # function call - return self.traceLines + return self.trace_lines - def traceLines(self, frame, event, arg): + def trace_lines(self, frame, event, _arg): """Print out lines for function.""" - # If you want to print local variables each line - # keep the check for the event 'line' - # If you want to print local variables only on return - # check only for the 'return' event if event not in ["line", "return"]: - return + return None co = frame.f_code func_name = co.co_name line_no = frame.f_lineno local_vars = frame.f_locals text = f" {func_name} {event} {line_no} locals: {local_vars}" self.logging.debug(text) + return self.trace_lines def debug(enabled=False): diff --git a/src/helper/map.py b/src/helper/map.py index b4bd8ea..8014b10 100644 --- a/src/helper/map.py +++ b/src/helper/map.py @@ -1,7 +1,5 @@ """Dot notation for dictionary.""" -# pylint: skip-file - class Map(dict): """dot.notation access to dictionary attributes. From 43021210d5b8d9213e20da55f31370413e674a42 Mon Sep 17 00:00:00 2001 From: Khole Jones Date: Sun, 9 Nov 2025 23:53:27 +0000 Subject: [PATCH 3/6] refactor: remove unnecessary pylint skip-file comments --- src/helper/const.py | 1 - src/helper/hivedataclasses.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/helper/const.py b/src/helper/const.py index 71fd5f0..42cb01b 100644 --- a/src/helper/const.py +++ b/src/helper/const.py @@ -2,7 +2,6 @@ from .hivedataclasses import EntityConfig -# pylint: skip-file SYNC_PACKAGE_NAME = "pyhiveapi" SYNC_PACKAGE_DIR = "/pyhiveapi/" ASYNC_PACKAGE_NAME = "apyhiveapi" diff --git a/src/helper/hivedataclasses.py b/src/helper/hivedataclasses.py index 6c0fb23..1f2e00d 100644 --- a/src/helper/hivedataclasses.py +++ b/src/helper/hivedataclasses.py @@ -1,7 +1,5 @@ """Device data class.""" -# pylint: skip-file - from dataclasses import dataclass from typing import Literal, Optional From d366085a8fcbbf7527b84c849a0ae5c34aad5609 Mon Sep 17 00:00:00 2001 From: Khole Jones Date: Sun, 9 Nov 2025 23:57:56 +0000 Subject: [PATCH 4/6] refactor: standardize attribute naming to snake_case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Renamed token attributes from camelCase to snake_case (tokenData → token_data, tokenCreated → token_created, tokenExpiry → token_expiry) - Renamed config attributes to snake_case (homeID → home_id, lastUpdated → last_updated, scanInterval → scan_interval, userID → user_id) --- src/session.py | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/session.py b/src/session.py index e696dbf..c2d6554 100644 --- a/src/session.py +++ b/src/session.py @@ -71,9 +71,9 @@ def __init__( self.updateLock = asyncio.Lock() self.tokens = Map( { - "tokenData": {}, - "tokenCreated": datetime.now() - timedelta(seconds=4000), - "tokenExpiry": timedelta(seconds=3600), + "token_data": {}, + "token_created": datetime.now() - timedelta(seconds=4000), + "token_expiry": timedelta(seconds=3600), } ) self.config = Map( @@ -83,11 +83,11 @@ def __init__( "camera": False, "errorList": {}, "file": False, - "homeID": None, - "lastUpdated": datetime.now(), + "home_id": None, + "last_updated": datetime.now(), "mode": [], - "scanInterval": timedelta(seconds=120), - "userID": None, + "scan_interval": timedelta(seconds=120), + "user_id": None, "username": username, } ) @@ -185,7 +185,7 @@ async def updateInterval(self, new_interval: timedelta): interval = new_interval if interval < timedelta(seconds=15): interval = timedelta(seconds=15) - self.config.scanInterval = interval + self.config.scan_interval = interval async def useFile(self, username: str = None): """Update to check if file is being used. @@ -210,20 +210,20 @@ async def updateTokens(self, tokens: dict, update_expiry_time: bool = True): data = {} if "AuthenticationResult" in tokens: data = tokens.get("AuthenticationResult") - self.tokens.tokenData.update({"token": data["IdToken"]}) + self.tokens.token_data.update({"token": data["IdToken"]}) if "RefreshToken" in data: - self.tokens.tokenData.update({"refreshToken": data["RefreshToken"]}) - self.tokens.tokenData.update({"accessToken": data["AccessToken"]}) + self.tokens.token_data.update({"refreshToken": data["RefreshToken"]}) + self.tokens.token_data.update({"accessToken": data["AccessToken"]}) if update_expiry_time: - self.tokens.tokenCreated = datetime.now() + self.tokens.token_created = datetime.now() elif "token" in tokens: data = tokens - self.tokens.tokenData.update({"token": data["token"]}) - self.tokens.tokenData.update({"refreshToken": data["refreshToken"]}) - self.tokens.tokenData.update({"accessToken": data["accessToken"]}) + self.tokens.token_data.update({"token": data["token"]}) + self.tokens.token_data.update({"refreshToken": data["refreshToken"]}) + self.tokens.token_data.update({"accessToken": data["accessToken"]}) if "ExpiresIn" in data: - self.tokens.tokenExpiry = timedelta(seconds=data["ExpiresIn"]) + self.tokens.token_expiry = timedelta(seconds=data["ExpiresIn"]) return self.tokens @@ -298,7 +298,7 @@ async def deviceLogin(self): if "AuthenticationResult" in result: await self.updateTokens(result) - self.tokens.tokenExpiry = timedelta(seconds=0) + self.tokens.token_expiry = timedelta(seconds=0) return result async def hiveRefreshTokens(self): @@ -312,11 +312,11 @@ async def hiveRefreshTokens(self): if self.config.file: return None else: - expiry_time = self.tokens.tokenCreated + self.tokens.tokenExpiry + expiry_time = self.tokens.token_created + self.tokens.token_expiry if datetime.now() >= expiry_time: try: result = await self.auth.refresh_token( - self.tokens.tokenData["refreshToken"] + self.tokens.token_data["refreshToken"] ) if "AuthenticationResult" in result: @@ -338,7 +338,7 @@ async def updateData(self, device: dict): boolean: True/False if update was successful """ updated = False - ep = self.config.lastUpdate + self.config.scanInterval + ep = self.config.last_updated + self.config.scan_interval if datetime.now() >= ep and not self.updateLock.locked(): try: await self.updateLock.acquire() @@ -453,7 +453,7 @@ async def getDevices(self, n_id: str): for hiveType in api_resp_p: if hiveType == "user": self.data.user = api_resp_p[hiveType] - self.config.userID = api_resp_p[hiveType]["id"] + self.config.user_id = api_resp_p[hiveType]["id"] if hiveType == "products": for aProduct in api_resp_p[hiveType]: tmpProducts.update({aProduct["id"]: aProduct}) @@ -468,7 +468,7 @@ async def getDevices(self, n_id: str): for aAction in api_resp_p[hiveType]: tmpActions.update({aAction["id"]: aAction}) if hiveType == "homes": - self.config.homeID = api_resp_p[hiveType]["homes"][0]["id"] + self.config.home_id = api_resp_p[hiveType]["homes"][0]["id"] if len(tmpProducts) > 0: self.data.products = copy.deepcopy(tmpProducts) @@ -477,7 +477,7 @@ async def getDevices(self, n_id: str): self.data.actions = copy.deepcopy(tmpActions) if self.config.alarm: await self.getAlarm() - self.config.lastUpdate = datetime.now() + self.config.last_updated = datetime.now() get_nodes_successful = True except (OSError, RuntimeError, HiveApiError, ConnectionError, HTTPException): get_nodes_successful = False @@ -499,7 +499,7 @@ async def startSession(self, config: dict = {}): """ await self.useFile(config.get("username", self.config.username)) await self.updateInterval( - config.get("options", {}).get("scan_interval", self.config.scanInterval) + config.get("options", {}).get("scan_interval", self.config.scan_interval) ) if config != {}: From 31c01279ca5afe9bd60082074a1b703ca93889ad Mon Sep 17 00:00:00 2001 From: Khole Jones <29937485+KJonline@users.noreply.github.com> Date: Fri, 20 Feb 2026 22:10:12 +0000 Subject: [PATCH 5/6] Remove alarm and camera modules with associated API endpoints and functionality Deleted alarm.py and camera.py modules containing HiveHomeShield/Alarm and HiveCamera/Camera classes. Removed alarm and camera-related API endpoints from both hive_api.py and hive_async_api.py including security-lite, camera images, and camera recordings URLs. Removed camera-specific request handling with Bearer token authentication and x-jwt-token headers. Cleaned up cameraBaseUrl and cameraPlatform references from --- src/alarm.py | 138 ---- src/api/hive_api.py | 85 +-- src/api/hive_async_api.py | 85 +-- src/api/hive_auth_async.py | 6 +- src/camera.py | 197 ------ src/data/alarm.json | 53 -- src/data/camera.json | 17 - src/data/data.json | 1223 +++++---------------------------- src/helper/const.py | 2 - src/helper/hivedataclasses.py | 2 - src/hive.py | 4 - src/session.py | 83 --- 12 files changed, 202 insertions(+), 1693 deletions(-) delete mode 100644 src/alarm.py delete mode 100644 src/camera.py delete mode 100644 src/data/alarm.json delete mode 100644 src/data/camera.json diff --git a/src/alarm.py b/src/alarm.py deleted file mode 100644 index 970b8a5..0000000 --- a/src/alarm.py +++ /dev/null @@ -1,138 +0,0 @@ -"""Hive Alarm Module.""" - -# pylint: skip-file -import logging - -_LOGGER = logging.getLogger(__name__) - - -class HiveHomeShield: - """Hive homeshield alarm. - - Returns: - object: Hive homeshield - """ - - alarmType = "Alarm" - - async def getMode(self): - """Get current mode of the alarm. - - Returns: - str: Mode if the alarm [armed_home, armed_away, armed_night] - """ - state = None - - try: - data = self.session.data.alarm - state = data["mode"] - except KeyError as e: - _LOGGER.error(e) - - return state - - async def getState(self, device: dict): - """Get the alarm triggered state. - - Returns: - boolean: True/False if alarm is triggered. - """ - state = None - - try: - data = self.session.data.devices[device.hive_id] - state = data["state"]["alarmActive"] - except KeyError as e: - _LOGGER.error(e) - - return state - - async def setMode(self, device: dict, mode: str): - """Set the alarm mode. - - Args: - device (dict): Alarm device. - - Returns: - boolean: True/False if successful. - """ - final = False - - if device.hive_id in self.session.data.devices and device.device_data["online"]: - if ( - device["hiveID"] in self.session.data.devices - and device["deviceData"]["online"] - ): - _LOGGER.debug("Setting alarm mode to %s.", mode) - await self.session.hiveRefreshTokens() - resp = await self.session.api.setAlarm(mode=mode) - if resp["original"] == 200: - final = True - await self.session.getAlarm() - - return final - - -class Alarm(HiveHomeShield): - """Home assistant alarm. - - Args: - HiveHomeShield (object): Class object. - """ - - def __init__(self, session: object = None): - """Initialise alarm. - - Args: - session (object, optional): Used to interact with the hive account. Defaults to None. - """ - self.session = session - - async def getAlarm(self, device: dict): - """Get alarm data. - - Args: - device (dict): Device to update. - - Returns: - dict: Updated device. - """ - device.device_data.update( - {"online": await self.session.attr.onlineOffline(device["device_id"])} - ) - dev_data = {} - - if device.device_data["online"]: - self.session.helper.deviceRecovered(device["device_id"]) - _LOGGER.debug("Updating alarm data for %s.", device["haName"]) - data = self.session.data.devices[device["device_id"]] - dev_data = { - "hiveID": device.hive_id, - "hiveName": device.hive_name, - "hiveType": device.hive_type, - "haName": device.ha_name, - "haType": device["haType"], - "device_id": device["device_id"], - "device_name": device["device_name"], - "status": { - "state": await self.getState(device), - "mode": await self.getMode(), - }, - "deviceData": data.get("props", None), - "parentDevice": data.get("parent", None), - "custom": device.get("custom", None), - "attributes": await self.session.attr.stateAttributes( - device["device_id"], device.hive_type - ), - } - - self.session.devices.update({device.hive_id: dev_data}) - return self.session.devices[device.hive_id] - else: - await self.session.log.errorCheck( - device["device_id"], "ERROR", device.device_data["online"] - await self.session.helper.errorCheck( - device["device_id"], "ERROR", device["deviceData"]["online"] - ) - device.setdefault("status", {"state": None, "mode": None}) - return device diff --git a/src/api/hive_api.py b/src/api/hive_api.py index a2f0c44..6971055 100644 --- a/src/api/hive_api.py +++ b/src/api/hive_api.py @@ -15,7 +15,6 @@ class HiveApi: def __init__(self, hiveSession=None, websession=None, token=None): """Hive API initialisation.""" - self.cameraBaseUrl = "prod.hcam.bgchtest.info" self.urls = { "properties": "https://sso.hivehome.com/", "login": "https://beekeeper.hivehome.com/1.0/cognito/login", @@ -25,9 +24,6 @@ def __init__(self, hiveSession=None, websession=None, token=None): "weather": "https://weather.prod.bgchprod.info/weather", "holiday_mode": "/holiday-mode", "all": "/nodes/all?products=true&devices=true&actions=true", - "alarm": "/security-lite?homeId=", - "cameraImages": f"https://event-history-service.{self.cameraBaseUrl}/v1/events/cameras?latest=true&cameraId={{0}}", - "cameraRecordings": f"https://event-history-service.{self.cameraBaseUrl}/v1/playlist/cameras/{{0}}/events/{{1}}.m3u8", "devices": "/devices", "products": "/products", "actions": "/actions", @@ -41,36 +37,20 @@ def __init__(self, hiveSession=None, websession=None, token=None): self.session = hiveSession self.token = token - def request(self, type, url, jsc=None, camera=False): + def request(self, type, url, jsc=None): """Make API request.""" if self.session is not None: - if camera: - self.headers = { - "content-type": "application/json", - "Accept": "*/*", - "Authorization": f"Bearer {self.session.tokens.tokenData['token']}", - "x-jwt-token": self.session.tokens.tokenData["token"], - } - else: - self.headers = { - "content-type": "application/json", - "Accept": "*/*", - "authorization": self.session.tokens.tokenData["token"], - } + self.headers = { + "content-type": "application/json", + "Accept": "*/*", + "authorization": self.session.tokens.token_data["token"], + } else: - if camera: - self.headers = { - "content-type": "application/json", - "Accept": "*/*", - "Authorization": f"Bearer {self.token}", - "x-jwt-token": self.token, - } - else: - self.headers = { - "content-type": "application/json", - "Accept": "*/*", - "authorization": self.token, - } + self.headers = { + "content-type": "application/json", + "Accept": "*/*", + "authorization": self.token, + } if type == "GET": return requests.get( @@ -99,7 +79,6 @@ def refreshTokens(self, tokens={}): if "token" in data and self.session: self.session.updateTokens(data) self.urls.update({"base": data["platform"]["endpoint"]}) - self.urls.update({"camera": data["platform"]["cameraPlatform"]}) self.json_return.update({"original": info.status_code}) self.json_return.update({"parsed": info.json()}) except (OSError, RuntimeError, ZeroDivisionError): @@ -143,48 +122,6 @@ def getAll(self): return json_return - def getAlarm(self, homeID=None): - """Build and query alarm endpoint.""" - if self.session is not None: - homeID = self.session.config.homeID - url = self.urls["base"] + self.urls["alarm"] + homeID - try: - info = self.request("GET", url) - self.json_return.update({"original": info.status_code}) - self.json_return.update({"parsed": info.json()}) - except (OSError, RuntimeError, ZeroDivisionError): - self.error() - - return self.json_return - - def getCameraImage(self, device=None, accessToken=None): - """Build and query camera endpoint.""" - json_return = {} - url = self.urls["cameraImages"].format(device["props"]["hardwareIdentifier"]) - try: - info = self.request("GET", url, camera=True) - json_return.update({"original": info.status_code}) - json_return.update({"parsed": info.json()}) - except (OSError, RuntimeError, ZeroDivisionError): - self.error() - - return json_return - - def getCameraRecording(self, device=None, eventId=None): - """Build and query camera endpoint.""" - json_return = {} - url = self.urls["cameraRecordings"].format( - device["props"]["hardwareIdentifier"], eventId - ) - try: - info = self.request("GET", url, camera=True) - json_return.update({"original": info.status_code}) - json_return.update({"parsed": info.text.split("\n")[3]}) - except (OSError, RuntimeError, ZeroDivisionError): - self.error() - - return json_return - def getDevices(self): """Call the get devices endpoint.""" url = self.urls["base"] + self.urls["devices"] diff --git a/src/api/hive_async_api.py b/src/api/hive_async_api.py index 8a29a2e..cd6292a 100644 --- a/src/api/hive_async_api.py +++ b/src/api/hive_async_api.py @@ -26,16 +26,12 @@ class HiveApiAsync: def __init__(self, hiveSession=None, websession: Optional[ClientSession] = None): """Hive API initialisation.""" self.baseUrl = "https://beekeeper.hivehome.com/1.0" - self.cameraBaseUrl = "prod.hcam.bgchtest.info" self.urls = { "properties": "https://sso.hivehome.com/", "login": f"{self.baseUrl}/cognito/login", "refresh": f"{self.baseUrl}/cognito/refresh-token", "holiday_mode": f"{self.baseUrl}/holiday-mode", "all": f"{self.baseUrl}/nodes/all?products=true&devices=true&actions=true", - "alarm": f"{self.baseUrl}/security-lite?homeId=", - "cameraImages": f"https://event-history-service.{self.cameraBaseUrl}/v1/events/cameras?latest=true&cameraId={{0}}", - "cameraRecordings": f"https://event-history-service.{self.cameraBaseUrl}/v1/playlist/cameras/{{0}}/events/{{1}}.m3u8", "devices": f"{self.baseUrl}/devices", "products": f"{self.baseUrl}/products", "actions": f"{self.baseUrl}/actions", @@ -51,9 +47,7 @@ def __init__(self, hiveSession=None, websession: Optional[ClientSession] = None) self.session = hiveSession self.websession = ClientSession() if websession is None else websession - async def request( - self, method: str, url: str, camera: bool = False, **kwargs - ) -> ClientResponse: + async def request(self, method: str, url: str, **kwargs) -> ClientResponse: """Make a request.""" _LOGGER.debug("API %s request to %s", method.upper(), url) data = kwargs.get("data", None) @@ -64,13 +58,7 @@ async def request( "User-Agent": "Hive/12.04.0 iOS/18.3.1 Apple", } try: - if camera: - headers["Authorization"] = ( - f"Bearer {self.session.tokens.tokenData['token']}" - ) - headers["x-jwt-token"] = self.session.tokens.tokenData["token"] - else: - headers["Authorization"] = self.session.tokens.tokenData["token"] + headers["Authorization"] = self.session.tokens.tokenData["token"] except KeyError: if "sso" in url: pass @@ -158,7 +146,6 @@ async def refreshTokens(self): if "token" in info: await self.session.updateTokens(info) self.baseUrl = info["platform"]["endpoint"] - self.cameraBaseUrl = info["platform"]["cameraPlatform"] return True except (ConnectionError, OSError, RuntimeError, ZeroDivisionError): await self.error() @@ -182,48 +169,6 @@ async def getAll(self): return json_return - async def getAlarm(self): - """Build and query alarm endpoint.""" - json_return = {} - url = self.urls["alarm"] + self.session.config.homeID - try: - resp = await self.request("get", url) - json_return.update({"original": resp.status}) - json_return.update({"parsed": await resp.json(content_type=None)}) - except (OSError, RuntimeError, ZeroDivisionError): - await self.error() - - return json_return - - async def getCameraImage(self, device): - """Build and query alarm endpoint.""" - json_return = {} - url = self.urls["cameraImages"].format(device["props"]["hardwareIdentifier"]) - try: - resp = await self.request("get", url, True) - json_return.update({"original": resp.status}) - json_return.update({"parsed": await resp.json(content_type=None)}) - except (OSError, RuntimeError, ZeroDivisionError): - await self.error() - - return json_return - - async def getCameraRecording(self, device, eventId): - """Build and query alarm endpoint.""" - json_return = {} - url = self.urls["cameraRecordings"].format( - device["props"]["hardwareIdentifier"], eventId - ) - try: - resp = await self.request("get", url, True) - recUrl = await resp.text() - json_return.update({"original": resp.status}) - json_return.update({"parsed": recUrl.split("\n")[3]}) - except (OSError, RuntimeError, ZeroDivisionError): - await self.error() - - return json_return - async def getDevices(self): """Call the get devices endpoint.""" json_return = {} @@ -327,32 +272,6 @@ async def setState(self, n_type, n_id, **kwargs): return json_return - async def setAlarm(self, **kwargs): - """Set the state of the alarm.""" - _LOGGER.debug("Setting alarm state: %s", kwargs) - json_return = {} - jsc = ( - "{" - + ",".join( - ('"' + str(i) + '": ' '"' + str(t) + '" ' for i, t in kwargs.items()) - ) - + "}" - ) - - url = f"{self.urls['alarm']}{self.session.config.homeID}" - try: - await self.isFileBeingUsed() - resp = await self.request("post", url, data=jsc) - json_return["original"] = resp.status - json_return["parsed"] = await resp.json(content_type=None) - except (FileInUse, OSError, RuntimeError, ConnectionError) as e: - if e.__class__.__name__ == "FileInUse": - return {"original": "file"} - else: - await self.error() - - return json_return - async def setAction(self, n_id, data): """Set the state of a Action.""" _LOGGER.debug("Setting action %s", n_id) diff --git a/src/api/hive_auth_async.py b/src/api/hive_auth_async.py index 466dbe3..eb3c80d 100644 --- a/src/api/hive_auth_async.py +++ b/src/api/hive_auth_async.py @@ -427,9 +427,9 @@ async def login(self): self.device_group_key = result["AuthenticationResult"][ "NewDeviceMetadata" ]["DeviceGroupKey"] - self.device_key = result["AuthenticationResult"][ - "NewDeviceMetadata" - ]["DeviceKey"] + self.device_key = result["AuthenticationResult"]["NewDeviceMetadata"][ + "DeviceKey" + ] _LOGGER.debug("SRP auth challenge completed successfully.") return result diff --git a/src/camera.py b/src/camera.py deleted file mode 100644 index d5deace..0000000 --- a/src/camera.py +++ /dev/null @@ -1,197 +0,0 @@ -"""Hive Camera Module.""" - -# pylint: skip-file -import logging - -_LOGGER = logging.getLogger(__name__) - - -class HiveCamera: - """Hive camera. - - Returns: - object: Hive camera - """ - - cameraType = "Camera" - - async def getCameraTemperature(self, device: dict): - """Get the camera state. - - Returns: - boolean: True/False if camera is on. - """ - state = None - - try: - data = self.session.data.devices[device.hive_id] - state = data["props"]["temperature"] - except KeyError as e: - _LOGGER.error(e) - - return state - - async def getCameraState(self, device: dict): - """Get the camera state. - - Returns: - boolean: True/False if camera is on. - """ - state = None - - try: - data = self.session.data.devices[device.hive_id] - state = True if data["state"]["mode"] == "ARMED" else False - except KeyError as e: - _LOGGER.error(e) - - return state - - async def getCameraImageURL(self, device: dict): - """Get the camera image url. - - Returns: - str: image url. - """ - state = None - - try: - state = self.session.data.camera[device.hive_id]["cameraImage"][ - "thumbnailUrls" - ][0] - except KeyError as e: - _LOGGER.error(e) - - return state - - async def getCameraRecodringURL(self, device: dict): - """Get the camera recording url. - - Returns: - str: image url. - """ - state = None - - try: - state = self.session.data.camera[device.hive_id]["cameraRecording"] - except KeyError as e: - _LOGGER.error(e) - - return state - - async def setCameraOn(self, device: dict, mode: str): - """Set the camera state to on. - - Args: - device (dict): Camera device. - - Returns: - boolean: True/False if successful. - """ - final = False - - if device.hive_id in self.session.data.devices and device.device_data["online"]: - if ( - device["hiveID"] in self.session.data.devices - and device["deviceData"]["online"] - ): - _LOGGER.debug("Setting camera ON for %s.", device["haName"]) - await self.session.hiveRefreshTokens() - resp = await self.session.api.setState(mode=mode) - if resp["original"] == 200: - final = True - await self.session.getCamera() - - return final - - async def setCameraOff(self, device: dict, mode: str): - """Set the camera state to on. - - Args: - device (dict): Camera device. - - Returns: - boolean: True/False if successful. - """ - final = False - - if device.hive_id in self.session.data.devices and device.device_data["online"]: - if ( - device["hiveID"] in self.session.data.devices - and device["deviceData"]["online"] - ): - _LOGGER.debug("Setting camera OFF for %s.", device["haName"]) - await self.session.hiveRefreshTokens() - resp = await self.session.api.setState(mode=mode) - if resp["original"] == 200: - final = True - await self.session.getCamera() - - return final - - -class Camera(HiveCamera): - """Home assistant camera. - - Args: - HiveCamera (object): Class object. - """ - - def __init__(self, session: object = None): - """Initialise camera. - - Args: - session (object, optional): Used to interact with the hive account. Defaults to None. - """ - self.session = session - - async def getCamera(self, device: dict): - """Get camera data. - - Args: - device (dict): Device to update. - - Returns: - dict: Updated device. - """ - device.device_data.update( - {"online": await self.session.attr.onlineOffline(device["device_id"])} - ) - dev_data = {} - - if device.device_data["online"]: - self.session.helper.deviceRecovered(device["device_id"]) - _LOGGER.debug("Updating camera data for %s.", device["haName"]) - data = self.session.data.devices[device["device_id"]] - dev_data = { - "hiveID": device.hive_id, - "hiveName": device.hive_name, - "hiveType": device.hive_type, - "haName": device.ha_name, - "haType": device["haType"], - "device_id": device["device_id"], - "device_name": device["device_name"], - "status": { - "temperature": await self.getCameraTemperature(device), - "state": await self.getCameraState(device), - "imageURL": await self.getCameraImageURL(device), - "recordingURL": await self.getCameraRecodringURL(device), - }, - "deviceData": data.get("props", None), - "parentDevice": data.get("parent", None), - "custom": device.get("custom", None), - "attributes": await self.session.attr.stateAttributes( - device["device_id"], device.hive_type - ), - } - - self.session.devices.update({device.hive_id: dev_data}) - return self.session.devices[device.hive_id] - else: - await self.session.log.errorCheck( - device["device_id"], "ERROR", device.device_data["online"] - await self.session.helper.errorCheck( - device["device_id"], "ERROR", device["deviceData"]["online"] - ) - device.setdefault("status", {"state": None}) - return device diff --git a/src/data/alarm.json b/src/data/alarm.json deleted file mode 100644 index 5392dec..0000000 --- a/src/data/alarm.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "mode": "home", - "securitySystemState": "ARMED", - "armingGracePeriod": 60, - "alarmingGracePeriod": 60, - "devices": [ - "keypad-0000-0000-000000000001", - "contact-sensor-0000-0000-000000000001", - "siren-0000-0000-000000000001", - "contact-sensor-0000-0000-000000000002" - ], - "triggers": { - "home": [], - "away": [ - "contact-sensor-0000-0000-000000000001", - "contact-sensor-0000-0000-000000000002" - ], - "asleep": [ - "contact-sensor-0000-0000-000000000002", - "contact-sensor-0000-0000-000000000001" - ] - }, - "actions": { - "away": [ - "keypad-0000-0000-000000000001" - ], - "asleep": [ - "keypad-0000-0000-000000000001" - ], - "sos": [ - "keypad-0000-0000-000000000001" - ] - }, - "monitoringCameras": { - "home": [], - "away": [], - "asleep": [] - }, - "alarmingGraceChirp": { - "away": "ON_GRACE_START", - "asleep": "ON_GRACE_START" - }, - "numberOfTriggersToAlarm": { - "away": 1, - "asleep": 1 - }, - "modeValid": { - "home": true, - "away": true, - "asleep": true - }, - "pinSchedules": {} -} \ No newline at end of file diff --git a/src/data/camera.json b/src/data/camera.json deleted file mode 100644 index 604ffbe..0000000 --- a/src/data/camera.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "cameraImage": { - "parsed": { - "events": [ - { - "thumbnailUrls": [ - "https://test.com/image" - ], - "hasRecording": true - } - ] - } - }, - "camaeraRecording": { - "parsed": "https://test.com/video" - } -} \ No newline at end of file diff --git a/src/data/data.json b/src/data/data.json index 246abf4..b030123 100644 --- a/src/data/data.json +++ b/src/data/data.json @@ -700,267 +700,216 @@ } }, { - "id": "camera-0000-0000-0000-000000000001", - "type": "hivecamera", + "id": "plug-0000-0000-0000-000000000001", + "type": "activeplug", "sortOrder": 0, - "created": 1243477586508, - "lastSeen": 1553324607010, + "created": 1295844392614, + "lastSeen": 1549431134911, + "parent": "parent-0000-0000-0000-000000000001", "props": { "online": true, - "model": "HCI001", - "version": "V0_0_00_093_svn825", - "manufacturer": "Hive", - "hardwareIdentifier": "51385FC1F5024E748A446456449E9601", - "ipAddress": "000.168.0.00", - "macAddress": "00:0A:11:BB:22:CC", - "temperature": "40", - "hardwareVersion": "H4", - "capabilities": [ - "CAMERA_VIDEO", - "CAMERA_DETECTION", - "CAMERA_DEVICE", - "NOTIFICATIONS", - "INFORMATION", - "CHANGE_WIFI", - "RENAME", - "DELETE" - ] + "model": "SLP2b", + "version": "01045700", + "manufacturer": "Computime", + "powerConsumption": 0, + "onSince": 1550266428863, + "inUse": false, + "deviceClass": "UNKNOWN", + "capabilities": ["INFORMATION", "RENAME", "DELETE"] }, "state": { - "name": "Camera 1", - "resolution": "1080P", - "motionDetection": "ALL", - "audioDetection": "ALL", - "ledDot": false, - "ledRing": true, - "soundAlert": true, - "nightVision": "AUTO", - "invertImage": false, - "cameraAudio": true, - "motionSensitivity": "LOW", - "audioSensitivity": "LOW", - "timeZone": "Europe/London", - "notificationScheduleEnabled": false, - "notificationsMode": "DISABLED", - "frameRate": "30", - "cameraZoom": "1X", - "storage": "CLOUD", - "activityZone": "ALL", - "scheduleEnabled": false, - "mode": "ARMED", - "systemNotificationSettings": { - "connectionStatus": true, - "batteryLevel": true, - "overheating": true - }, + "name": "Plug 1", + "status": "OFF", + "mode": "MANUAL", "schedule": { "monday": [ { - "start": 390, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 510, + "start": 480, "value": { - "mode": "ARMED" + "status": "OFF" } }, { - "start": 960, + "start": 1320, "value": { - "mode": "PRIVACY" + "status": "ON" } }, { - "start": 1290, + "start": 1380, "value": { - "mode": "ARMED" + "status": "OFF" } } ], "tuesday": [ { - "start": 390, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 510, + "start": 480, "value": { - "mode": "ARMED" + "status": "OFF" } }, { - "start": 960, + "start": 1320, "value": { - "mode": "PRIVACY" + "status": "ON" } }, { - "start": 1290, + "start": 1380, "value": { - "mode": "ARMED" + "status": "OFF" } } ], "wednesday": [ { - "start": 390, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 510, + "start": 480, "value": { - "mode": "ARMED" + "status": "OFF" } }, { - "start": 960, + "start": 1320, "value": { - "mode": "PRIVACY" + "status": "ON" } }, { - "start": 1290, + "start": 1380, "value": { - "mode": "ARMED" + "status": "OFF" } } ], "thursday": [ { - "start": 390, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 510, + "start": 480, "value": { - "mode": "ARMED" + "status": "OFF" } }, { - "start": 960, + "start": 1320, "value": { - "mode": "PRIVACY" + "status": "ON" } }, { - "start": 1290, + "start": 1380, "value": { - "mode": "ARMED" + "status": "OFF" } } ], "friday": [ { - "start": 390, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 510, + "start": 480, "value": { - "mode": "ARMED" + "status": "OFF" } }, { - "start": 960, + "start": 1320, "value": { - "mode": "PRIVACY" + "status": "ON" } }, { - "start": 1290, + "start": 1380, "value": { - "mode": "ARMED" + "status": "OFF" } } ], "saturday": [ { - "start": 390, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 510, + "start": 480, "value": { - "mode": "ARMED" + "status": "OFF" } }, { - "start": 960, + "start": 1320, "value": { - "mode": "PRIVACY" + "status": "ON" } }, { - "start": 1290, + "start": 1380, "value": { - "mode": "ARMED" + "status": "OFF" } } ], "sunday": [ { - "start": 390, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 510, + "start": 480, "value": { - "mode": "ARMED" + "status": "OFF" } }, { - "start": 960, + "start": 1320, "value": { - "mode": "PRIVACY" + "status": "ON" } }, { - "start": 1290, + "start": 1380, "value": { - "mode": "ARMED" + "status": "OFF" } } ] - }, - "notificationSchedule": { + } + } + }, + { + "id": "plug-0000-0000-0000-000000000002", + "type": "activeplug", + "sortOrder": 0, + "created": 1523679665643, + "parent": "parent-0000-0000-0000-000000000001", + "props": { + "online": true, + "model": "SLP2b", + "version": "01035700", + "manufacturer": "Computime", + "powerConsumption": 0, + "onSince": 1553134057795, + "inUse": false, + "deviceClass": "UNKNOWN", + "capabilities": ["INFORMATION", "RENAME", "DELETE"] + }, + "state": { + "name": "Plug 2", + "status": "OFF", + "mode": "MANUAL", + "schedule": { "monday": [ { "start": 390, "value": { - "state": "DISABLE" + "status": "ON" } }, { "start": 510, "value": { - "state": "ENABLE" + "status": "OFF" } }, { "start": 960, "value": { - "state": "DISABLE" + "status": "ON" } }, { "start": 1290, "value": { - "state": "ENABLE" + "status": "OFF" } } ], @@ -968,25 +917,25 @@ { "start": 390, "value": { - "state": "DISABLE" + "status": "ON" } }, { "start": 510, "value": { - "state": "ENABLE" + "status": "OFF" } }, { "start": 960, "value": { - "state": "DISABLE" + "status": "ON" } }, { "start": 1290, "value": { - "state": "ENABLE" + "status": "OFF" } } ], @@ -994,25 +943,25 @@ { "start": 390, "value": { - "state": "DISABLE" + "status": "ON" } }, { "start": 510, "value": { - "state": "ENABLE" + "status": "OFF" } }, { "start": 960, "value": { - "state": "DISABLE" + "status": "ON" } }, { "start": 1290, "value": { - "state": "ENABLE" + "status": "OFF" } } ], @@ -1020,25 +969,25 @@ { "start": 390, "value": { - "state": "DISABLE" + "status": "ON" } }, { "start": 510, "value": { - "state": "ENABLE" + "status": "OFF" } }, { "start": 960, "value": { - "state": "DISABLE" + "status": "ON" } }, { "start": 1290, "value": { - "state": "ENABLE" + "status": "OFF" } } ], @@ -1046,25 +995,25 @@ { "start": 390, "value": { - "state": "DISABLE" + "status": "ON" } }, { "start": 510, "value": { - "state": "ENABLE" + "status": "OFF" } }, { "start": 960, "value": { - "state": "DISABLE" + "status": "ON" } }, { "start": 1290, "value": { - "state": "ENABLE" + "status": "OFF" } } ], @@ -1072,25 +1021,25 @@ { "start": 390, "value": { - "state": "DISABLE" + "status": "ON" } }, { "start": 510, "value": { - "state": "ENABLE" + "status": "OFF" } }, { "start": 960, "value": { - "state": "DISABLE" + "status": "ON" } }, { "start": 1290, "value": { - "state": "ENABLE" + "status": "OFF" } } ], @@ -1098,25 +1047,25 @@ { "start": 390, "value": { - "state": "DISABLE" + "status": "ON" } }, { "start": 510, "value": { - "state": "ENABLE" + "status": "OFF" } }, { "start": 960, "value": { - "state": "DISABLE" + "status": "ON" } }, { "start": 1290, "value": { - "state": "ENABLE" + "status": "OFF" } } ] @@ -1124,35 +1073,29 @@ } }, { - "id": "plug-0000-0000-0000-000000000001", + "id": "plug-0000-0000-0000-000000000003", "type": "activeplug", "sortOrder": 0, - "created": 1295844392614, - "lastSeen": 1549431134911, + "created": 1512759057107, + "lastSeen": 1549431076054, "parent": "parent-0000-0000-0000-000000000001", "props": { "online": true, "model": "SLP2b", - "version": "01045700", + "version": "01035700", "manufacturer": "Computime", "powerConsumption": 0, - "onSince": 1550266428863, + "onSince": 1550266371454, "inUse": false, "deviceClass": "UNKNOWN", "capabilities": ["INFORMATION", "RENAME", "DELETE"] }, "state": { - "name": "Plug 1", + "name": "Plug 3", "status": "OFF", "mode": "MANUAL", "schedule": { "monday": [ - { - "start": 480, - "value": { - "status": "OFF" - } - }, { "start": 1320, "value": { @@ -1167,12 +1110,6 @@ } ], "tuesday": [ - { - "start": 480, - "value": { - "status": "OFF" - } - }, { "start": 1320, "value": { @@ -1187,12 +1124,6 @@ } ], "wednesday": [ - { - "start": 480, - "value": { - "status": "OFF" - } - }, { "start": 1320, "value": { @@ -1207,12 +1138,6 @@ } ], "thursday": [ - { - "start": 480, - "value": { - "status": "OFF" - } - }, { "start": 1320, "value": { @@ -1227,12 +1152,6 @@ } ], "friday": [ - { - "start": 480, - "value": { - "status": "OFF" - } - }, { "start": 1320, "value": { @@ -1247,12 +1166,6 @@ } ], "saturday": [ - { - "start": 480, - "value": { - "status": "OFF" - } - }, { "start": 1320, "value": { @@ -1267,12 +1180,6 @@ } ], "sunday": [ - { - "start": 480, - "value": { - "status": "OFF" - } - }, { "start": 1320, "value": { @@ -1290,31 +1197,38 @@ } }, { - "id": "plug-0000-0000-0000-000000000002", - "type": "activeplug", + "id": "light-0000-0000-0000-000000000003", + "type": "warmwhitelight", "sortOrder": 0, - "created": 1523679665643, + "created": 1995324452543, + "lastSeen": 1147535994599, "parent": "parent-0000-0000-0000-000000000001", "props": { "online": true, - "model": "SLP2b", - "version": "01035700", - "manufacturer": "Computime", - "powerConsumption": 0, - "onSince": 1553134057795, - "inUse": false, - "deviceClass": "UNKNOWN", - "capabilities": ["INFORMATION", "RENAME", "DELETE"] + "model": "FWBulb01", + "version": "11480002", + "manufacturer": "Aurora", + "capabilities": [ + "INFORMATION", + "RENAME", + "DELETE", + "GROUPABLE", + "MIMIC_MODE", + "SCHEDULE", + "IDENTIFY_DEVICE" + ] }, "state": { - "name": "Plug 2", + "name": "Light 3", "status": "OFF", + "brightness": 100, "mode": "MANUAL", "schedule": { "monday": [ { "start": 390, "value": { + "brightness": 100, "status": "ON" } }, @@ -1327,6 +1241,7 @@ { "start": 960, "value": { + "brightness": 100, "status": "ON" } }, @@ -1341,6 +1256,7 @@ { "start": 390, "value": { + "brightness": 100, "status": "ON" } }, @@ -1353,6 +1269,7 @@ { "start": 960, "value": { + "brightness": 100, "status": "ON" } }, @@ -1367,6 +1284,7 @@ { "start": 390, "value": { + "brightness": 100, "status": "ON" } }, @@ -1379,6 +1297,7 @@ { "start": 960, "value": { + "brightness": 100, "status": "ON" } }, @@ -1393,6 +1312,7 @@ { "start": 390, "value": { + "brightness": 100, "status": "ON" } }, @@ -1405,6 +1325,7 @@ { "start": 960, "value": { + "brightness": 100, "status": "ON" } }, @@ -1419,6 +1340,7 @@ { "start": 390, "value": { + "brightness": 100, "status": "ON" } }, @@ -1431,6 +1353,7 @@ { "start": 960, "value": { + "brightness": 100, "status": "ON" } }, @@ -1445,6 +1368,7 @@ { "start": 390, "value": { + "brightness": 100, "status": "ON" } }, @@ -1457,6 +1381,7 @@ { "start": 960, "value": { + "brightness": 100, "status": "ON" } }, @@ -1471,6 +1396,7 @@ { "start": 390, "value": { + "brightness": 100, "status": "ON" } }, @@ -1483,6 +1409,7 @@ { "start": 960, "value": { + "brightness": 100, "status": "ON" } }, @@ -1497,135 +1424,11 @@ } }, { - "id": "plug-0000-0000-0000-000000000003", - "type": "activeplug", - "sortOrder": 0, - "created": 1512759057107, - "lastSeen": 1549431076054, - "parent": "parent-0000-0000-0000-000000000001", - "props": { - "online": true, - "model": "SLP2b", - "version": "01035700", - "manufacturer": "Computime", - "powerConsumption": 0, - "onSince": 1550266371454, - "inUse": false, - "deviceClass": "UNKNOWN", - "capabilities": ["INFORMATION", "RENAME", "DELETE"] - }, - "state": { - "name": "Plug 3", - "status": "OFF", - "mode": "MANUAL", - "schedule": { - "monday": [ - { - "start": 1320, - "value": { - "status": "ON" - } - }, - { - "start": 1380, - "value": { - "status": "OFF" - } - } - ], - "tuesday": [ - { - "start": 1320, - "value": { - "status": "ON" - } - }, - { - "start": 1380, - "value": { - "status": "OFF" - } - } - ], - "wednesday": [ - { - "start": 1320, - "value": { - "status": "ON" - } - }, - { - "start": 1380, - "value": { - "status": "OFF" - } - } - ], - "thursday": [ - { - "start": 1320, - "value": { - "status": "ON" - } - }, - { - "start": 1380, - "value": { - "status": "OFF" - } - } - ], - "friday": [ - { - "start": 1320, - "value": { - "status": "ON" - } - }, - { - "start": 1380, - "value": { - "status": "OFF" - } - } - ], - "saturday": [ - { - "start": 1320, - "value": { - "status": "ON" - } - }, - { - "start": 1380, - "value": { - "status": "OFF" - } - } - ], - "sunday": [ - { - "start": 1320, - "value": { - "status": "ON" - } - }, - { - "start": 1380, - "value": { - "status": "OFF" - } - } - ] - } - } - }, - { - "id": "light-0000-0000-0000-000000000003", + "id": "light-0000-0000-0000-000000000004", "type": "warmwhitelight", "sortOrder": 0, - "created": 1995324452543, - "lastSeen": 1147535994599, + "created": 1495819606370, + "lastSeen": 1549742852622, "parent": "parent-0000-0000-0000-000000000001", "props": { "online": true, @@ -1643,7 +1446,7 @@ ] }, "state": { - "name": "Light 3", + "name": "Light 4", "status": "OFF", "brightness": 100, "mode": "MANUAL", @@ -1848,11 +1651,11 @@ } }, { - "id": "light-0000-0000-0000-000000000004", + "id": "light-0000-0000-0000-000000000002", "type": "warmwhitelight", "sortOrder": 0, - "created": 1495819606370, - "lastSeen": 1549742852622, + "created": 1470158558350, + "lastSeen": 1543686750227, "parent": "parent-0000-0000-0000-000000000001", "props": { "online": true, @@ -1870,34 +1673,21 @@ ] }, "state": { - "name": "Light 4", - "status": "OFF", + "name": "Light 2", + "status": "ON", "brightness": 100, "mode": "MANUAL", "schedule": { "monday": [ { - "start": 390, - "value": { - "brightness": 100, - "status": "ON" - } - }, - { - "start": 510, - "value": { - "status": "OFF" - } - }, - { - "start": 960, + "start": 1095, "value": { - "brightness": 100, + "brightness": 5, "status": "ON" } }, { - "start": 1290, + "start": 1350, "value": { "status": "OFF" } @@ -1905,27 +1695,14 @@ ], "tuesday": [ { - "start": 390, - "value": { - "brightness": 100, - "status": "ON" - } - }, - { - "start": 510, - "value": { - "status": "OFF" - } - }, - { - "start": 960, + "start": 1095, "value": { - "brightness": 100, + "brightness": 5, "status": "ON" } }, { - "start": 1290, + "start": 1350, "value": { "status": "OFF" } @@ -1933,27 +1710,14 @@ ], "wednesday": [ { - "start": 390, - "value": { - "brightness": 100, - "status": "ON" - } - }, - { - "start": 510, - "value": { - "status": "OFF" - } - }, - { - "start": 960, + "start": 1095, "value": { - "brightness": 100, + "brightness": 5, "status": "ON" } }, { - "start": 1290, + "start": 1350, "value": { "status": "OFF" } @@ -1961,247 +1725,59 @@ ], "thursday": [ { - "start": 390, + "start": 1095, "value": { - "brightness": 100, + "brightness": 5, "status": "ON" } }, { - "start": 510, + "start": 1350, "value": { "status": "OFF" } - }, + } + ], + "friday": [ { - "start": 960, + "start": 1095, "value": { - "brightness": 100, + "brightness": 5, "status": "ON" } }, { - "start": 1290, + "start": 1350, "value": { "status": "OFF" } } ], - "friday": [ + "saturday": [ { - "start": 390, + "start": 1095, "value": { - "brightness": 100, + "brightness": 5, "status": "ON" } }, { - "start": 510, + "start": 1350, "value": { "status": "OFF" } - }, + } + ], + "sunday": [ { - "start": 960, + "start": 1095, "value": { - "brightness": 100, + "brightness": 5, "status": "ON" } }, { - "start": 1290, - "value": { - "status": "OFF" - } - } - ], - "saturday": [ - { - "start": 390, - "value": { - "brightness": 100, - "status": "ON" - } - }, - { - "start": 510, - "value": { - "status": "OFF" - } - }, - { - "start": 960, - "value": { - "brightness": 100, - "status": "ON" - } - }, - { - "start": 1290, - "value": { - "status": "OFF" - } - } - ], - "sunday": [ - { - "start": 390, - "value": { - "brightness": 100, - "status": "ON" - } - }, - { - "start": 510, - "value": { - "status": "OFF" - } - }, - { - "start": 960, - "value": { - "brightness": 100, - "status": "ON" - } - }, - { - "start": 1290, - "value": { - "status": "OFF" - } - } - ] - } - } - }, - { - "id": "light-0000-0000-0000-000000000002", - "type": "warmwhitelight", - "sortOrder": 0, - "created": 1470158558350, - "lastSeen": 1543686750227, - "parent": "parent-0000-0000-0000-000000000001", - "props": { - "online": true, - "model": "FWBulb01", - "version": "11480002", - "manufacturer": "Aurora", - "capabilities": [ - "INFORMATION", - "RENAME", - "DELETE", - "GROUPABLE", - "MIMIC_MODE", - "SCHEDULE", - "IDENTIFY_DEVICE" - ] - }, - "state": { - "name": "Light 2", - "status": "ON", - "brightness": 100, - "mode": "MANUAL", - "schedule": { - "monday": [ - { - "start": 1095, - "value": { - "brightness": 5, - "status": "ON" - } - }, - { - "start": 1350, - "value": { - "status": "OFF" - } - } - ], - "tuesday": [ - { - "start": 1095, - "value": { - "brightness": 5, - "status": "ON" - } - }, - { - "start": 1350, - "value": { - "status": "OFF" - } - } - ], - "wednesday": [ - { - "start": 1095, - "value": { - "brightness": 5, - "status": "ON" - } - }, - { - "start": 1350, - "value": { - "status": "OFF" - } - } - ], - "thursday": [ - { - "start": 1095, - "value": { - "brightness": 5, - "status": "ON" - } - }, - { - "start": 1350, - "value": { - "status": "OFF" - } - } - ], - "friday": [ - { - "start": 1095, - "value": { - "brightness": 5, - "status": "ON" - } - }, - { - "start": 1350, - "value": { - "status": "OFF" - } - } - ], - "saturday": [ - { - "start": 1095, - "value": { - "brightness": 5, - "status": "ON" - } - }, - { - "start": 1350, - "value": { - "status": "OFF" - } - } - ], - "sunday": [ - { - "start": 1095, - "value": { - "brightness": 5, - "status": "ON" - } - }, - { - "start": 1350, + "start": 1350, "value": { "status": "OFF" } @@ -3551,433 +3127,6 @@ "calibrationStatus": "CALIBRATED" } }, - { - "id": "camera-0000-0000-0000-000000000001", - "type": "hivecamera", - "sortOrder": 0, - "created": 1543677886208, - "lastSeen": 1550320722000, - "props": { - "online": true, - "model": "HCI001", - "version": "V0_0_00_093_svn825", - "manufacturer": "Hive", - "hardwareIdentifier": "51385FC1F5024E748A446456449E9601", - "power": "mains", - "signal": 37, - "battery": 100, - "ipAddress": "000.168.0.00", - "macAddress": "00:0A:11:BB:22:CC", - "temperature": "40", - "hardwareVersion": "H4", - "capabilities": [ - "CAMERA_VIDEO", - "CAMERA_DETECTION", - "CAMERA_DEVICE", - "NOTIFICATIONS", - "INFORMATION", - "CHANGE_WIFI", - "RENAME", - "DELETE" - ] - }, - "state": { - "name": "Camera 1", - "resolution": "1080P", - "motionDetection": "ALL", - "audioDetection": "ALL", - "ledDot": false, - "ledRing": true, - "soundAlert": true, - "nightVision": "AUTO", - "invertImage": false, - "cameraAudio": true, - "motionSensitivity": "LOW", - "audioSensitivity": "LOW", - "timeZone": "Europe/London", - "notificationScheduleEnabled": false, - "notificationsMode": "DISABLED", - "frameRate": "30", - "cameraZoom": "1X", - "storage": "CLOUD", - "activityZone": "ALL", - "scheduleEnabled": false, - "mode": "ARMED", - "systemNotificationSettings": { - "connectionStatus": true, - "batteryLevel": true, - "overheating": true - }, - "schedule": { - "monday": [ - { - "start": 390, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 510, - "value": { - "mode": "ARMED" - } - }, - { - "start": 960, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 1290, - "value": { - "mode": "ARMED" - } - } - ], - "tuesday": [ - { - "start": 390, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 510, - "value": { - "mode": "ARMED" - } - }, - { - "start": 960, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 1290, - "value": { - "mode": "ARMED" - } - } - ], - "wednesday": [ - { - "start": 390, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 510, - "value": { - "mode": "ARMED" - } - }, - { - "start": 960, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 1290, - "value": { - "mode": "ARMED" - } - } - ], - "thursday": [ - { - "start": 390, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 510, - "value": { - "mode": "ARMED" - } - }, - { - "start": 960, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 1290, - "value": { - "mode": "ARMED" - } - } - ], - "friday": [ - { - "start": 390, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 510, - "value": { - "mode": "ARMED" - } - }, - { - "start": 960, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 1290, - "value": { - "mode": "ARMED" - } - } - ], - "saturday": [ - { - "start": 390, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 510, - "value": { - "mode": "ARMED" - } - }, - { - "start": 960, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 1290, - "value": { - "mode": "ARMED" - } - } - ], - "sunday": [ - { - "start": 390, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 510, - "value": { - "mode": "ARMED" - } - }, - { - "start": 960, - "value": { - "mode": "PRIVACY" - } - }, - { - "start": 1290, - "value": { - "mode": "ARMED" - } - } - ] - }, - "notificationSchedule": { - "monday": [ - { - "start": 390, - "value": { - "state": "DISABLE" - } - }, - { - "start": 510, - "value": { - "state": "ENABLE" - } - }, - { - "start": 960, - "value": { - "state": "DISABLE" - } - }, - { - "start": 1290, - "value": { - "state": "ENABLE" - } - } - ], - "tuesday": [ - { - "start": 390, - "value": { - "state": "DISABLE" - } - }, - { - "start": 510, - "value": { - "state": "ENABLE" - } - }, - { - "start": 960, - "value": { - "state": "DISABLE" - } - }, - { - "start": 1290, - "value": { - "state": "ENABLE" - } - } - ], - "wednesday": [ - { - "start": 390, - "value": { - "state": "DISABLE" - } - }, - { - "start": 510, - "value": { - "state": "ENABLE" - } - }, - { - "start": 960, - "value": { - "state": "DISABLE" - } - }, - { - "start": 1290, - "value": { - "state": "ENABLE" - } - } - ], - "thursday": [ - { - "start": 390, - "value": { - "state": "DISABLE" - } - }, - { - "start": 510, - "value": { - "state": "ENABLE" - } - }, - { - "start": 960, - "value": { - "state": "DISABLE" - } - }, - { - "start": 1290, - "value": { - "state": "ENABLE" - } - } - ], - "friday": [ - { - "start": 390, - "value": { - "state": "DISABLE" - } - }, - { - "start": 510, - "value": { - "state": "ENABLE" - } - }, - { - "start": 960, - "value": { - "state": "DISABLE" - } - }, - { - "start": 1290, - "value": { - "state": "ENABLE" - } - } - ], - "saturday": [ - { - "start": 390, - "value": { - "state": "DISABLE" - } - }, - { - "start": 510, - "value": { - "state": "ENABLE" - } - }, - { - "start": 960, - "value": { - "state": "DISABLE" - } - }, - { - "start": 1290, - "value": { - "state": "ENABLE" - } - } - ], - "sunday": [ - { - "start": 390, - "value": { - "state": "DISABLE" - } - }, - { - "start": 510, - "value": { - "state": "ENABLE" - } - }, - { - "start": 960, - "value": { - "state": "DISABLE" - } - }, - { - "start": 1290, - "value": { - "state": "ENABLE" - } - } - ] - } - } - }, { "id": "plug-0000-0000-0000-000000000001", "type": "activeplug", diff --git a/src/helper/const.py b/src/helper/const.py index 42cb01b..b0322e8 100644 --- a/src/helper/const.py +++ b/src/helper/const.py @@ -27,7 +27,6 @@ HIVETOHA = { - "Alarm": {"home": "armed_home", "away": "armed_away", "asleep": "armed_night"}, "Attribute": {True: "Online", False: "Offline"}, "Boost": {None: "OFF", False: "OFF"}, "Heating": {False: "OFF", "ENABLED": True, "DISABLED": False}, @@ -61,7 +60,6 @@ "SMOKE_CO": "self.session.hub.getSmokeStatus(device)", "DOG_BARK": "self.session.hub.getDogBarkStatus(device)", "GLASS_BREAK": "self.session.hub.getGlassBreakStatus(device)", - "Camera_Temp": "self.session.camera.getCameraTemperature(device)", "Current_Temperature": "self.session.heating.getCurrentTemperature(device)", "Heating_Current_Temperature": "self.session.heating.getCurrentTemperature(device)", "Heating_Target_Temperature": "self.session.heating.getTargetTemperature(device)", diff --git a/src/helper/hivedataclasses.py b/src/helper/hivedataclasses.py index 1f2e00d..78b57da 100644 --- a/src/helper/hivedataclasses.py +++ b/src/helper/hivedataclasses.py @@ -36,8 +36,6 @@ class EntityConfig: "light", "switch", "water_heater", - "alarm_control_panel", - "camera", ] ha_name: str = "" hive_type: str = "" diff --git a/src/hive.py b/src/hive.py index 29f2edd..75558bb 100644 --- a/src/hive.py +++ b/src/hive.py @@ -10,8 +10,6 @@ from aiohttp import ClientSession from .action import HiveAction -from .alarm import Alarm -from .camera import Camera from .heating import Climate from .hotwater import WaterHeater from .hub import HiveHub @@ -105,8 +103,6 @@ def __init__( super().__init__(username, password, websession) self.session = self self.action = HiveAction(self.session) - self.alarm = Alarm(self.session) - self.camera = Camera(self.session) self.heating = Climate(self.session) self.hotwater = WaterHeater(self.session) self.hub = HiveHub(self.session) diff --git a/src/session.py b/src/session.py index 3462a53..7316b18 100644 --- a/src/session.py +++ b/src/session.py @@ -28,11 +28,9 @@ HiveReauthRequired, HiveRefreshTokenExpired, HiveUnknownConfiguration, - NoApiToken, ) from .helper.hive_helper import HiveHelper from .helper.hivedataclasses import Device -from .helper.logger import Logger from .helper.map import Map _LOGGER = logging.getLogger(__name__) @@ -84,9 +82,7 @@ def __init__( ) self.config = Map( { - "alarm": False, "battery": [], - "camera": False, "errorList": {}, "file": False, "home_id": None, @@ -104,8 +100,6 @@ def __init__( "actions": {}, "user": {}, "minMax": {}, - "alarm": {}, - "camera": {}, } ) self.devices = {} @@ -482,9 +476,6 @@ async def updateData(self, device: dict): return updated _LOGGER.debug("Polling Hive API for device updates.") updated = await self.getDevices(device["hiveID"]) - if updated and len(self.deviceList["camera"]) > 0: - for camera in self.data.camera: - await self.getCamera(self.devices[camera]) if updated: _LOGGER.debug("Device update completed successfully.") else: @@ -494,72 +485,6 @@ async def updateData(self, device: dict): return updated - async def getAlarm(self): - """Get alarm data. - - Raises: - HTTPException: HTTP error has occurred updating the devices. - HiveApiError: An API error code has been returned. - """ - if self.config.file: - api_resp_d = self.openFile("alarm.json") - elif self.tokens is not None: - api_resp_d = await self.api.getAlarm() - if operator.contains(str(api_resp_d["original"]), "20") is False: - raise HTTPException - elif api_resp_d["parsed"] is None: - raise HiveApiError - - self.data.alarm = api_resp_d["parsed"] - - async def getCamera(self, device): - """Get camera data. - - Raises: - HTTPException: HTTP error has occurred updating the devices. - HiveApiError: An API error code has been returned. - """ - cameraImage = None - cameraRecording = None - hasCameraImage = False - hasCameraRecording = False - - if self.config.file: - cameraImage = self.openFile("camera.json") - cameraRecording = self.openFile("camera.json") - elif self.tokens is not None: - cameraImage = await self.api.getCameraImage(device) - hasCameraRecording = bool( - cameraImage["parsed"]["events"][0]["hasRecording"] - ) - if hasCameraRecording: - cameraRecording = await self.api.getCameraRecording( - device, cameraImage["parsed"]["events"][0]["eventId"] - ) - - if operator.contains(str(cameraImage["original"]), "20") is False: - raise HTTPException - elif cameraImage["parsed"] is None: - raise HiveApiError - else: - raise NoApiToken - - hasCameraImage = bool(cameraImage["parsed"]["events"][0]) - - self.data.camera[device["id"]] = {} - self.data.camera[device["id"]]["cameraImage"] = None - self.data.camera[device["id"]]["cameraRecording"] = None - - if cameraImage is not None and hasCameraImage: - self.data.camera[device["id"]] = {} - self.data.camera[device["id"]]["cameraImage"] = cameraImage["parsed"][ - "events" - ][0] - if cameraRecording is not None and hasCameraRecording: - self.data.camera[device["id"]]["cameraRecording"] = cameraRecording[ - "parsed" - ] - async def getDevices(self, n_id: str): """Get latest data for Hive nodes. @@ -641,10 +566,6 @@ async def getDevices(self, n_id: str): if hiveType == "devices": for aDevice in api_resp_p[hiveType]: tmpDevices.update({aDevice["id"]: aDevice}) - if aDevice["type"] == "siren": - self.config.alarm = True - # if aDevice["type"] == "hivecamera": - # await self.getCamera(aDevice) if hiveType == "actions": for aAction in api_resp_p[hiveType]: tmpActions.update({aAction["id"]: aAction}) @@ -662,8 +583,6 @@ async def getDevices(self, n_id: str): if len(tmpDevices) > 0: self.data.devices = copy.deepcopy(tmpDevices) self.data.actions = copy.deepcopy(tmpActions) - if self.config.alarm: - await self.getAlarm() self.config.last_updated = datetime.now() get_nodes_successful = True except HiveReauthRequired: @@ -751,9 +670,7 @@ async def createDevices(self): list: List of devices """ self.deviceList["parent_device"] = [] - self.deviceList["alarm_control_panel"] = [] self.deviceList["binary_sensor"] = [] - self.deviceList["camera"] = [] self.deviceList["climate"] = [] self.deviceList["light"] = [] self.deviceList["sensor"] = [] From 160ba165898ada502b091951c59e7d6dd8dca878 Mon Sep 17 00:00:00 2001 From: Khole Jones <29937485+KJonline@users.noreply.github.com> Date: Fri, 20 Feb 2026 22:24:28 +0000 Subject: [PATCH 6/6] Standardize attribute naming to snake_case convention Renamed camelCase attributes to snake_case: tokenData to token_data, deviceList to device_list, tokenCreated to token_created, and tokenExpiry to token_expiry. Updated all references throughout hive_async_api.py and session.py to maintain consistency with Python naming conventions. --- src/api/hive_async_api.py | 2 +- src/session.py | 58 +++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/api/hive_async_api.py b/src/api/hive_async_api.py index cd6292a..979cd32 100644 --- a/src/api/hive_async_api.py +++ b/src/api/hive_async_api.py @@ -58,7 +58,7 @@ async def request(self, method: str, url: str, **kwargs) -> ClientResponse: "User-Agent": "Hive/12.04.0 iOS/18.3.1 Apple", } try: - headers["Authorization"] = self.session.tokens.tokenData["token"] + headers["Authorization"] = self.session.tokens.token_data["token"] except KeyError: if "sso" in url: pass diff --git a/src/session.py b/src/session.py index 7316b18..9ef076c 100644 --- a/src/session.py +++ b/src/session.py @@ -103,7 +103,7 @@ def __init__( } ) self.devices = {} - self.deviceList = {} + self.device_list = {} self.hub_id = None self._lastPollSlow = False self._slowPollThreshold = 3 @@ -166,10 +166,10 @@ def addList(self, entity_type: str, data: dict, **kwargs: dict) -> Optional[Devi ) if data.get("type", "") == "hub": - self.deviceList["parent_device"].append(device_obj) - self.deviceList[entity_type].append(device_obj) + self.device_list["parent_device"].append(device_obj) + self.device_list[entity_type].append(device_obj) else: - self.deviceList[entity_type].append(device_obj) + self.device_list[entity_type].append(device_obj) return device_obj except KeyError as error: @@ -233,22 +233,22 @@ async def updateTokens(self, tokens: dict, update_expiry_time: bool = True): "AccessToken: len=%d tail=…%s | " "RefreshToken: %s | " "ExpiresIn: %s | tokenCreated: %s | tokenExpiry: %s", - len(self.tokens.tokenData.get("token", "")), - self.tokens.tokenData.get("token", "")[-4:], - len(self.tokens.tokenData.get("accessToken", "")), - self.tokens.tokenData.get("accessToken", "")[-4:], + len(self.tokens.token_data.get("token", "")), + self.tokens.token_data.get("token", "")[-4:], + len(self.tokens.token_data.get("accessToken", "")), + self.tokens.token_data.get("accessToken", "")[-4:], ( "present (len=%d tail=…%s)" % ( - len(self.tokens.tokenData.get("refreshToken", "")), - self.tokens.tokenData.get("refreshToken", "")[-4:], + len(self.tokens.token_data.get("refreshToken", "")), + self.tokens.token_data.get("refreshToken", "")[-4:], ) - if self.tokens.tokenData.get("refreshToken") + if self.tokens.token_data.get("refreshToken") else "not present" ), data.get("ExpiresIn", "N/A"), - self.tokens.tokenCreated, - self.tokens.tokenExpiry, + self.tokens.token_created, + self.tokens.token_expiry, ) return self.tokens @@ -669,13 +669,13 @@ async def createDevices(self): Returns: list: List of devices """ - self.deviceList["parent_device"] = [] - self.deviceList["binary_sensor"] = [] - self.deviceList["climate"] = [] - self.deviceList["light"] = [] - self.deviceList["sensor"] = [] - self.deviceList["switch"] = [] - self.deviceList["water_heater"] = [] + self.device_list["parent_device"] = [] + self.device_list["binary_sensor"] = [] + self.device_list["climate"] = [] + self.device_list["light"] = [] + self.device_list["sensor"] = [] + self.device_list["switch"] = [] + self.device_list["water_heater"] = [] hive_type = HIVE_TYPES["Thermo"] + HIVE_TYPES["Sensor"] for device_id, device_data in self.data["devices"].items(): @@ -720,17 +720,17 @@ async def createDevices(self): self.config.mode.append(product_data["id"]) _LOGGER.debug( - "Device discovery found: %d parent, %d binary_sensor, %d climate, %d light, %d sensor, %d switch, %d water_heater", - len(self.deviceList.get("parent", [])), - len(self.deviceList.get("binary_sensor", [])), - len(self.deviceList.get("climate", [])), - len(self.deviceList.get("light", [])), - len(self.deviceList.get("sensor", [])), - len(self.deviceList.get("switch", [])), - len(self.deviceList.get("water_heater", [])), + "Device discovery found: %d parent_device, %d binary_sensor, %d climate, %d light, %d sensor, %d switch, %d water_heater", + len(self.device_list.get("parent_device", [])), + len(self.device_list.get("binary_sensor", [])), + len(self.device_list.get("climate", [])), + len(self.device_list.get("light", [])), + len(self.device_list.get("sensor", [])), + len(self.device_list.get("switch", [])), + len(self.device_list.get("water_heater", [])), ) - return self.deviceList + return self.device_list @staticmethod def epochTime(date_time: any, pattern: str, action: str):