diff --git a/README.md b/README.md index 7e4db6e..c18f85b 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Configuration is done through the `Add Integrations` rather than configuration.y Some devices may not work after moving the configuration to the integration. Please review the docs on how to gather the device data to send to the developer. -No longer supports services. Many often used services are incorperated into the device types. Hopefully will be added back +No longer supports services. Many often used services are incorperated into the device types. Hopefully will be added back Thanks to @dloveall and now @Expl0dingBanana this release will automatically discover most devices. Post an issue, if your device is no longer found. diff --git a/custom_components/hubspace/anonomyize_data.py b/custom_components/hubspace/anonomyize_data.py index f8f90e7..e8abd61 100644 --- a/custom_components/hubspace/anonomyize_data.py +++ b/custom_components/hubspace/anonomyize_data.py @@ -110,6 +110,8 @@ def anonymize_state(state: HubSpaceState): fake_state["lastUpdateTime"] = 0 if fake_state["functionClass"] == "wifi-ssid": fake_state["value"] = str(uuid4()) + elif fake_state["functionClass"] == "geo-coordinates": + fake_state["value"] = {"geo-coordinates": {"latitude": "0", "longitude": "0"}} elif isinstance(state.value, str): if "mac" in state.functionClass: fake_state["value"] = str(uuid4()) diff --git a/custom_components/hubspace/coordinator.py b/custom_components/hubspace/coordinator.py index 3b61bd3..8059429 100644 --- a/custom_components/hubspace/coordinator.py +++ b/custom_components/hubspace/coordinator.py @@ -158,3 +158,26 @@ async def get_sensors( ) required_sensors.append(sensor) return required_sensors + + +async def create_devices_from_data( + file_name: str, +) -> list[hubspace_async.HubSpaceDevice]: + """Generate devices from a data dump + + :param file_name: Name of the file to load + """ + current_path: str = os.path.dirname(os.path.realpath(__file__)) + async with aiofiles.open(os.path.join(current_path, file_name), "r") as fh: + data = await fh.read() + devices = json.loads(data) + processed = [] + for device in devices: + processed_states = [] + for state in device["states"]: + processed_states.append(hubspace_async.HubSpaceState(**state)) + device["states"] = processed_states + if "children" not in device: + device["children"] = [] + processed.append(hubspace_async.HubSpaceDevice(**device)) + return processed diff --git a/custom_components/hubspace/fan.py b/custom_components/hubspace/fan.py index 0aaa4f8..b25fdc9 100644 --- a/custom_components/hubspace/fan.py +++ b/custom_components/hubspace/fan.py @@ -156,6 +156,8 @@ def update_states(self) -> None: self._current_direction = state.value elif state.functionClass == "power": self._state = state.value + elif state.functionClass == "available": + self._availability = state.value elif state.functionClass in additional_attrs: self._bonus_attrs[state.functionClass] = state.value diff --git a/tests/test_fan.py b/tests/test_fan.py index eacf741..057f6cc 100644 --- a/tests/test_fan.py +++ b/tests/test_fan.py @@ -82,6 +82,7 @@ def test_process_functions(self, functions, expected_attrs, empty_fan): "_fan_speed": "fan-speed-6-050", "_current_direction": "reverse", "_state": "on", + "_availability": True, }, { "model": None, diff --git a/tests/test_light.py b/tests/test_light.py index c4e15bc..52fe444 100644 --- a/tests/test_light.py +++ b/tests/test_light.py @@ -103,6 +103,7 @@ def test_process_functions(functions, expected_attrs, empty_light): "_state": "on", "_color_temp": 3000, "_brightness": 114, + "_availability": True, }, { "Child ID": None, diff --git a/tests/test_lock.py b/tests/test_lock.py index 24851c5..0e26589 100644 --- a/tests/test_lock.py +++ b/tests/test_lock.py @@ -21,6 +21,7 @@ def empty_lock(mocked_coordinator): lock_tbd_instance.states, { "_current_position": "locked", + "_availability": True, }, { "Child ID": None, diff --git a/tests/test_valve.py b/tests/test_valve.py index 52a951a..99a3c18 100644 --- a/tests/test_valve.py +++ b/tests/test_valve.py @@ -18,8 +18,8 @@ def empty_valve(mocked_coordinator): @pytest.mark.parametrize( "instance,states,expected_attrs", [ - ("spigot-1", spigot.states, {"_state": "off"}), - ("spigot-2", spigot.states, {"_state": "on"}), + ("spigot-1", spigot.states, {"_state": "off", "_availability": True}), + ("spigot-2", spigot.states, {"_state": "on", "_availability": True}), ], ) async def test_update_states(instance, states, expected_attrs, empty_valve): diff --git a/tests/utils.py b/tests/utils.py index 8ce2021..f7543a7 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,8 +1,11 @@ +import asyncio import json import os from typing import Any -from hubspace_async import HubSpaceDevice, HubSpaceState +from hubspace_async import HubSpaceConnection, HubSpaceDevice, HubSpaceState + +from custom_components.hubspace import anonomyize_data current_path: str = os.path.dirname(os.path.realpath(__file__)) @@ -32,3 +35,14 @@ def create_devices_from_data(file_name: str) -> list[HubSpaceDevice]: device["children"] = [] processed.append(HubSpaceDevice(**device)) return processed + + +def convert_hs_raw(data): + """Used for converting old data-dumps to new data dumps""" + loop = asyncio.get_event_loop() + conn = HubSpaceConnection(None, None) + loop.run_until_complete(conn._process_api_results(data)) + devs = loop.run_until_complete(anonomyize_data.generate_anon_data(conn)) + with open("converted.json", "w") as fh: + json.dump(devs, fh, indent=4) + return devs