From d081cdad1f7e2c9a6a9db3e445971e055126c40b Mon Sep 17 00:00:00 2001 From: PocketMiner82 Date: Sun, 23 Jun 2024 19:40:14 +0200 Subject: [PATCH 1/4] fix: retry setup when iDRAC is unreachable during HA boot --- custom_components/idrac_power/__init__.py | 15 +---- .../idrac_power/binary_sensor.py | 38 +++++++------ custom_components/idrac_power/button.py | 37 ++++++------ custom_components/idrac_power/config_flow.py | 0 custom_components/idrac_power/const.py | 0 custom_components/idrac_power/idrac_rest.py | 30 +++++----- custom_components/idrac_power/manifest.json | 0 custom_components/idrac_power/sensor.py | 56 ++++++++++--------- custom_components/idrac_power/strings.json | 0 9 files changed, 88 insertions(+), 88 deletions(-) mode change 100644 => 100755 custom_components/idrac_power/__init__.py mode change 100644 => 100755 custom_components/idrac_power/binary_sensor.py mode change 100644 => 100755 custom_components/idrac_power/button.py mode change 100644 => 100755 custom_components/idrac_power/config_flow.py mode change 100644 => 100755 custom_components/idrac_power/const.py mode change 100644 => 100755 custom_components/idrac_power/idrac_rest.py mode change 100644 => 100755 custom_components/idrac_power/manifest.json mode change 100644 => 100755 custom_components/idrac_power/sensor.py mode change 100644 => 100755 custom_components/idrac_power/strings.json diff --git a/custom_components/idrac_power/__init__.py b/custom_components/idrac_power/__init__.py old mode 100644 new mode 100755 index 1bada69..8bbd92f --- a/custom_components/idrac_power/__init__.py +++ b/custom_components/idrac_power/__init__.py @@ -31,19 +31,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: } hass.async_create_task( - hass.config_entries.async_forward_entry_setup( - entry, Platform.SENSOR - ) - ) - hass.async_create_task( - hass.config_entries.async_forward_entry_setup( - entry, Platform.BINARY_SENSOR - ) - ) - - hass.async_create_task( - hass.config_entries.async_forward_entry_setup( - entry, Platform.BUTTON + hass.config_entries.async_forward_entry_setups( + entry, [Platform.SENSOR, Platform.BINARY_SENSOR, Platform.BUTTON] ) ) return True diff --git a/custom_components/idrac_power/binary_sensor.py b/custom_components/idrac_power/binary_sensor.py old mode 100644 new mode 100755 index 16e23cf..3492d42 --- a/custom_components/idrac_power/binary_sensor.py +++ b/custom_components/idrac_power/binary_sensor.py @@ -8,10 +8,11 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import DeviceInfo +from homeassistant.exceptions import PlatformNotReady from .const import (DOMAIN, DATA_IDRAC_REST_CLIENT, JSON_MODEL, JSON_MANUFACTURER, JSON_SERIAL_NUMBER, DATA_IDRAC_FIRMWARE, DATA_IDRAC_INFO) -from .idrac_rest import IdracRest +from .idrac_rest import IdracRest, CannotConnect, RedfishConfig _LOGGER = logging.getLogger(__name__) @@ -25,22 +26,25 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_e """Add iDrac power sensor entry""" rest_client = hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_REST_CLIENT] - if DATA_IDRAC_INFO not in hass.data[DOMAIN][entry.entry_id]: - info = await hass.async_add_executor_job(target=rest_client.get_device_info) - if not info: - _LOGGER.error(f"Could not set up: couldn't reach device.") - return - - hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] = info - else: - info = hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] - - firmware_version = await hass.async_add_executor_job(target=rest_client.get_firmware_version) - if not firmware_version: - if DATA_IDRAC_FIRMWARE in hass.data[DOMAIN][entry.entry_id]: - firmware_version = hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_FIRMWARE] - else: - hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] = firmware_version + try: + if DATA_IDRAC_INFO not in hass.data[DOMAIN][entry.entry_id]: + info = await hass.async_add_executor_job(target=rest_client.get_device_info) + if not info: + raise PlatformNotReady(f"Could not set up: device didn't return anything.") + + hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] = info + else: + info = hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] + + firmware_version = await hass.async_add_executor_job(target=rest_client.get_firmware_version) + if not firmware_version: + if DATA_IDRAC_FIRMWARE in hass.data[DOMAIN][entry.entry_id]: + firmware_version = hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_FIRMWARE] + else: + hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] = firmware_version + except (CannotConnect, RedfishConfig) as e: + raise PlatformNotReady(str(e)) from e + model = info[JSON_MODEL] name = model diff --git a/custom_components/idrac_power/button.py b/custom_components/idrac_power/button.py old mode 100644 new mode 100755 index 77e990d..215f0d2 --- a/custom_components/idrac_power/button.py +++ b/custom_components/idrac_power/button.py @@ -7,10 +7,11 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import DeviceInfo +from homeassistant.exceptions import PlatformNotReady from .const import (DOMAIN, DATA_IDRAC_REST_CLIENT, JSON_MODEL, JSON_MANUFACTURER, JSON_SERIAL_NUMBER, DATA_IDRAC_INFO, DATA_IDRAC_FIRMWARE) -from .idrac_rest import IdracRest +from .idrac_rest import IdracRest, CannotConnect, RedfishConfig _LOGGER = logging.getLogger(__name__) @@ -19,22 +20,24 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_e """Add iDrac power sensor entry""" rest_client = hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_REST_CLIENT] - if DATA_IDRAC_INFO not in hass.data[DOMAIN][entry.entry_id]: - info = await hass.async_add_executor_job(target=rest_client.get_device_info) - if not info: - _LOGGER.error(f"Could not set up: couldn't reach device.") - return - - hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] = info - else: - info = hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] - - firmware_version = await hass.async_add_executor_job(target=rest_client.get_firmware_version) - if not firmware_version: - if DATA_IDRAC_FIRMWARE in hass.data[DOMAIN][entry.entry_id]: - firmware_version = hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_FIRMWARE] - else: - hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] = firmware_version + try: + if DATA_IDRAC_INFO not in hass.data[DOMAIN][entry.entry_id]: + info = await hass.async_add_executor_job(target=rest_client.get_device_info) + if not info: + raise PlatformNotReady(f"Could not set up: device didn't return anything.") + + hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] = info + else: + info = hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] + + firmware_version = await hass.async_add_executor_job(target=rest_client.get_firmware_version) + if not firmware_version: + if DATA_IDRAC_FIRMWARE in hass.data[DOMAIN][entry.entry_id]: + firmware_version = hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_FIRMWARE] + else: + hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] = firmware_version + except (CannotConnect, RedfishConfig) as e: + raise PlatformNotReady(str(e)) from e model = info[JSON_MODEL] name = model diff --git a/custom_components/idrac_power/config_flow.py b/custom_components/idrac_power/config_flow.py old mode 100644 new mode 100755 diff --git a/custom_components/idrac_power/const.py b/custom_components/idrac_power/const.py old mode 100644 new mode 100755 diff --git a/custom_components/idrac_power/idrac_rest.py b/custom_components/idrac_power/idrac_rest.py old mode 100644 new mode 100755 index 48a5541..e26b37c --- a/custom_components/idrac_power/idrac_rest.py +++ b/custom_components/idrac_power/idrac_rest.py @@ -5,6 +5,7 @@ import urllib3 from homeassistant.exceptions import HomeAssistantError from requests import Response +from requests.exceptions import ConnectionError, JSONDecodeError urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) @@ -28,7 +29,11 @@ def handle_error(result): raise InvalidAuth() if result.status_code == 404: - error = result.json()['error'] + try: + error = result.json()['error'] + except JSONDecodeError: + # start of iDRAC can cause 404 error, ignore it + raise CannotConnect(f"iDRAC responed with 404, but no JSON present:\n{result.text}") if error['code'] == 'Base.1.0.GeneralError' and 'RedFish attribute is disabled' in \ error['@Message.ExtendedInfo'][0]['Message']: raise RedfishConfig() @@ -55,8 +60,7 @@ def get_device_info(self) -> dict | None: try: result = self.get_path(drac_chassis_path) except ConnectionError: - _LOGGER.warning(f"Could not get device info from {self.host}") - return None + raise CannotConnect(f"Cannot connect to {self.host}") handle_error(result) @@ -72,8 +76,7 @@ def get_firmware_version(self) -> str | None: try: result = self.get_path(drac_managers_path) except ConnectionError: - _LOGGER.warning(f"Could not get firmware version of {self.host}") - return None + raise CannotConnect(f"Could not get firmware version of {self.host}") handle_error(result) @@ -88,8 +91,7 @@ def power_on(self) -> Response | None: result = requests.post(protocol + self.host + drac_powerON_path, auth=self.auth, verify=False, json={"ResetType": "On"}) except ConnectionError as e: - _LOGGER.error(f"Could power on {self.host}: {e}") - return None + raise CannotConnect(f"Could not power on {self.host}: {e}") json = result.json() if result.status_code == 401: @@ -101,7 +103,7 @@ def power_on(self) -> Response | None: error['@Message.ExtendedInfo'][0]['Message']: raise RedfishConfig() if "error" in json: - _LOGGER.error("Idrac power on failed: %s", json["error"]["@Message.ExtendedInfo"][0]["Message"]) + _LOGGER.error("iDRAC power on failed: %s", json["error"]["@Message.ExtendedInfo"][0]["Message"]) return result @@ -120,8 +122,8 @@ def update_thermals(self) -> dict: handle_error(req) new_thermals = req.json() - except ConnectionError as e: - _LOGGER.warning(f"Couldn't update {self.host} thermals: {e}") + except (ConnectionError, RedfishConfig, CannotConnect) as e: + _LOGGER.debug(f"Couldn't update {self.host} thermals: {e}") new_thermals = None if new_thermals != self.thermal_values: @@ -141,8 +143,8 @@ def update_status(self): except: new_status = None - except ConnectionError as e: - _LOGGER.warning(f"Couldn't update {self.host} status: {e}") + except (ConnectionError, RedfishConfig, CannotConnect) as e: + _LOGGER.debug(f"Couldn't update {self.host} status: {e}") new_status = False if new_status != self.status: @@ -155,8 +157,8 @@ def update_power_usage(self): result = self.get_path(drac_powercontrol_path) handle_error(result) power_values = result.json() - except ConnectionError as e: - _LOGGER.warning(f"Couldn't update {self.host} thermals: {e}") + except (ConnectionError, RedfishConfig, CannotConnect) as e: + _LOGGER.debug(f"Couldn't update {self.host} power usage: {e}") for callback in self.callback_power_usage: callback(None) return diff --git a/custom_components/idrac_power/manifest.json b/custom_components/idrac_power/manifest.json old mode 100644 new mode 100755 diff --git a/custom_components/idrac_power/sensor.py b/custom_components/idrac_power/sensor.py old mode 100644 new mode 100755 index e1bc6b4..29bc6c6 --- a/custom_components/idrac_power/sensor.py +++ b/custom_components/idrac_power/sensor.py @@ -8,10 +8,11 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import DeviceInfo +from homeassistant.exceptions import PlatformNotReady from .const import (DOMAIN, DATA_IDRAC_REST_CLIENT, JSON_MODEL, JSON_MANUFACTURER, JSON_SERIAL_NUMBER, DATA_IDRAC_INFO, DATA_IDRAC_FIRMWARE, DATA_IDRAC_THERMAL) -from .idrac_rest import IdracRest +from .idrac_rest import IdracRest, CannotConnect, RedfishConfig _LOGGER = logging.getLogger(__name__) @@ -27,30 +28,31 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_e _LOGGER.debug(f"Getting the REST client for {entry.entry_id}") - if DATA_IDRAC_INFO not in hass.data[DOMAIN][entry.entry_id]: - info = await hass.async_add_executor_job(target=rest_client.get_device_info) - if not info: - _LOGGER.error(f"Could not set up: couldn't reach device.") - return - - hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] = info - else: - info = hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] - - firmware_version = await hass.async_add_executor_job(target=rest_client.get_firmware_version) - if not firmware_version: - if DATA_IDRAC_FIRMWARE in hass.data[DOMAIN][entry.entry_id]: - firmware_version = hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_FIRMWARE] - else: - hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] = firmware_version - - thermal_info = await hass.async_add_executor_job(target=rest_client.update_thermals) - if not thermal_info: - if DATA_IDRAC_THERMAL in hass.data[DOMAIN][entry.entry_id]: - thermal_info = hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_THERMAL] + try: + if DATA_IDRAC_INFO not in hass.data[DOMAIN][entry.entry_id]: + info = await hass.async_add_executor_job(target=rest_client.get_device_info) + if not info: + raise PlatformNotReady(f"Could not set up: device didn't return anything.") + + hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] = info + else: + info = hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] + + firmware_version = await hass.async_add_executor_job(target=rest_client.get_firmware_version) + if not firmware_version: + if DATA_IDRAC_FIRMWARE in hass.data[DOMAIN][entry.entry_id]: + firmware_version = hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_FIRMWARE] else: - _LOGGER.error(f"Could not set up: couldn't get thermal info.") - return + hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_INFO] = firmware_version + + thermal_info = await hass.async_add_executor_job(target=rest_client.update_thermals) + if not thermal_info: + if DATA_IDRAC_THERMAL in hass.data[DOMAIN][entry.entry_id]: + thermal_info = hass.data[DOMAIN][entry.entry_id][DATA_IDRAC_THERMAL] + else: + raise PlatformNotReady(f"Could not set up: couldn't get thermal info.") + except (CannotConnect, RedfishConfig) as e: + raise PlatformNotReady(str(e)) from e model = info[JSON_MODEL] name = model @@ -68,17 +70,17 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_e _LOGGER.debug(f"Adding new devices to device info {('serial', serial)}") - entities = [IdracCurrentPowerSensor(hass, rest_client, device_info, f"{serial}_{name}_current", name)] + entities = [IdracCurrentPowerSensor(hass, rest_client, device_info, f"{serial}_{name}_power", name)] for i, fan in enumerate(thermal_info['Fans']): _LOGGER.info("Adding fan %s : %s", i, fan["FanName"]) - entities.append(IdracFanSensor(hass, rest_client, device_info, f"{serial}_{name}_fan_{i}", + entities.append(IdracFanSensor(hass, rest_client, device_info, f"{serial}_{name}_fan_{fan['FanName'].lower().replace(" ", "_")}", f"{name} {fan['FanName']}", i )) for i, temp in enumerate(thermal_info['Temperatures']): _LOGGER.info("Adding temp %s : %s", i, temp["Name"]) - entities.append(IdracTempSensor(hass, rest_client, device_info, f"{serial}_{name}_temp_{i}", + entities.append(IdracTempSensor(hass, rest_client, device_info, f"{serial}_{name}_temp_{temp['Name'].lower().replace(" ", "_")}", f"{name} {temp['Name']}", i )) diff --git a/custom_components/idrac_power/strings.json b/custom_components/idrac_power/strings.json old mode 100644 new mode 100755 From 07b38f1fa502433ed146a118bfb124ca9baf19c8 Mon Sep 17 00:00:00 2001 From: PocketMiner82 Date: Mon, 24 Jun 2024 19:54:22 +0200 Subject: [PATCH 2/4] fix: add timeout to request to allow entities to become unavailable (and available if device becomes reachable again) --- custom_components/idrac_power/idrac_rest.py | 20 ++++++++++---------- custom_components/idrac_power/sensor.py | 20 +++++++++++++++++--- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/custom_components/idrac_power/idrac_rest.py b/custom_components/idrac_power/idrac_rest.py index e26b37c..1ab8004 100755 --- a/custom_components/idrac_power/idrac_rest.py +++ b/custom_components/idrac_power/idrac_rest.py @@ -5,7 +5,7 @@ import urllib3 from homeassistant.exceptions import HomeAssistantError from requests import Response -from requests.exceptions import ConnectionError, JSONDecodeError +from requests.exceptions import RequestException, JSONDecodeError urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) @@ -59,7 +59,7 @@ def __init__(self, host, username, password, interval): def get_device_info(self) -> dict | None: try: result = self.get_path(drac_chassis_path) - except ConnectionError: + except RequestException: raise CannotConnect(f"Cannot connect to {self.host}") handle_error(result) @@ -75,7 +75,7 @@ def get_device_info(self) -> dict | None: def get_firmware_version(self) -> str | None: try: result = self.get_path(drac_managers_path) - except ConnectionError: + except RequestException: raise CannotConnect(f"Could not get firmware version of {self.host}") handle_error(result) @@ -84,13 +84,13 @@ def get_firmware_version(self) -> str | None: return manager_results[JSON_FIRMWARE_VERSION] def get_path(self, path): - return requests.get(protocol + self.host + path, auth=self.auth, verify=False) + return requests.get(protocol + self.host + path, auth=self.auth, verify=False, timeout=300) def power_on(self) -> Response | None: try: result = requests.post(protocol + self.host + drac_powerON_path, auth=self.auth, verify=False, - json={"ResetType": "On"}) - except ConnectionError as e: + json={"ResetType": "On"}, timeout=300) + except RequestException as e: raise CannotConnect(f"Could not power on {self.host}: {e}") json = result.json() @@ -122,7 +122,7 @@ def update_thermals(self) -> dict: handle_error(req) new_thermals = req.json() - except (ConnectionError, RedfishConfig, CannotConnect) as e: + except (RequestException, RedfishConfig, CannotConnect) as e: _LOGGER.debug(f"Couldn't update {self.host} thermals: {e}") new_thermals = None @@ -143,9 +143,9 @@ def update_status(self): except: new_status = None - except (ConnectionError, RedfishConfig, CannotConnect) as e: + except (RequestException, RedfishConfig, CannotConnect) as e: _LOGGER.debug(f"Couldn't update {self.host} status: {e}") - new_status = False + new_status = None if new_status != self.status: self.status = new_status @@ -157,7 +157,7 @@ def update_power_usage(self): result = self.get_path(drac_powercontrol_path) handle_error(result) power_values = result.json() - except (ConnectionError, RedfishConfig, CannotConnect) as e: + except (RequestException, RedfishConfig, CannotConnect) as e: _LOGGER.debug(f"Couldn't update {self.host} power usage: {e}") for callback in self.callback_power_usage: callback(None) diff --git a/custom_components/idrac_power/sensor.py b/custom_components/idrac_power/sensor.py index 29bc6c6..0c1f258 100755 --- a/custom_components/idrac_power/sensor.py +++ b/custom_components/idrac_power/sensor.py @@ -93,9 +93,23 @@ async def refresh_sensors_task(): await asyncio.sleep(rest_client.interval) async def update_all(): - await hass.async_add_executor_job(rest_client.update_thermals) - await hass.async_add_executor_job(rest_client.update_status) - await hass.async_add_executor_job(rest_client.update_power_usage) + try: + await hass.async_add_executor_job(rest_client.update_thermals) + except Exception as e: + # ignore exceptions, just log the error + _LOGGER.warning(f"Updating {name} thermals sensors failed:\n{e}") + + try: + await hass.async_add_executor_job(rest_client.update_status) + except Exception as e: + # ignore exceptions, just log the error + _LOGGER.warning(f"Updating {name} status sensor failed:\n{e}") + + try: + await hass.async_add_executor_job(rest_client.update_power_usage) + except Exception as e: + # ignore exceptions, just log the error + _LOGGER.warning(f"Updating {name} power usage failed:\n{e}") await update_all() From e757d6e7f79d91dc482353ec7cc329e16272380b Mon Sep 17 00:00:00 2001 From: PocketMiner82 Date: Mon, 24 Jun 2024 20:35:37 +0200 Subject: [PATCH 3/4] fix: sensors getting mixed up after reconnecting --- custom_components/idrac_power/idrac_rest.py | 2 ++ custom_components/idrac_power/sensor.py | 28 +++++++++++++-------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/custom_components/idrac_power/idrac_rest.py b/custom_components/idrac_power/idrac_rest.py index 1ab8004..142b592 100755 --- a/custom_components/idrac_power/idrac_rest.py +++ b/custom_components/idrac_power/idrac_rest.py @@ -126,6 +126,8 @@ def update_thermals(self) -> dict: _LOGGER.debug(f"Couldn't update {self.host} thermals: {e}") new_thermals = None + _LOGGER.warning(new_thermals) + if new_thermals != self.thermal_values: self.thermal_values = new_thermals for callback in self.callback_thermals: diff --git a/custom_components/idrac_power/sensor.py b/custom_components/idrac_power/sensor.py index 0c1f258..6522b77 100755 --- a/custom_components/idrac_power/sensor.py +++ b/custom_components/idrac_power/sensor.py @@ -73,15 +73,17 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_e entities = [IdracCurrentPowerSensor(hass, rest_client, device_info, f"{serial}_{name}_power", name)] for i, fan in enumerate(thermal_info['Fans']): + member_id = fan['MemberId'] _LOGGER.info("Adding fan %s : %s", i, fan["FanName"]) - entities.append(IdracFanSensor(hass, rest_client, device_info, f"{serial}_{name}_fan_{fan['FanName'].lower().replace(" ", "_")}", - f"{name} {fan['FanName']}", i + entities.append(IdracFanSensor(hass, rest_client, device_info, f"{serial}_{name}_fan_{member_id}", + f"{name} {fan['FanName']}", member_id )) for i, temp in enumerate(thermal_info['Temperatures']): + member_id = temp['MemberId'] _LOGGER.info("Adding temp %s : %s", i, temp["Name"]) - entities.append(IdracTempSensor(hass, rest_client, device_info, f"{serial}_{name}_temp_{temp['Name'].lower().replace(" ", "_")}", - f"{name} {temp['Name']}", i + entities.append(IdracTempSensor(hass, rest_client, device_info, f"{serial}_{name}_temp_{member_id}", + f"{name} {temp['Name']}", member_id )) async_add_entities(entities) @@ -150,7 +152,7 @@ def update_value(self, new_value: int | None): class IdracFanSensor(SensorEntity): - def __init__(self, hass, rest: IdracRest, device_info, unique_id, name, index): + def __init__(self, hass, rest: IdracRest, device_info, unique_id, name, member_id): self.hass = hass self.rest = rest @@ -167,13 +169,16 @@ def __init__(self, hass, rest: IdracRest, device_info, unique_id, name, index): self._attr_has_entity_name = True self._attr_native_value = None - self.index = index + self.member_id = member_id self.rest.register_callback_thermals(self.update_value) def update_value(self, thermal: dict | None): if thermal: - self._attr_native_value = thermal['Fans'][self.index]['Reading'] + for fan in thermal['Fans']: + if fan['MemberId'] == self.member_id: + self._attr_native_value = fan['Reading'] + break self._attr_available = True else: self._attr_available = False @@ -181,7 +186,7 @@ def update_value(self, thermal: dict | None): class IdracTempSensor(SensorEntity): - def __init__(self, hass, rest: IdracRest, device_info, unique_id, name, index): + def __init__(self, hass, rest: IdracRest, device_info, unique_id, name, member_id): self.hass = hass self.rest = rest @@ -198,13 +203,16 @@ def __init__(self, hass, rest: IdracRest, device_info, unique_id, name, index): self._attr_unique_id = unique_id self._attr_has_entity_name = True self._attr_native_value = None - self.index = index + self.member_id = member_id self.rest.register_callback_thermals(self.update_value) def update_value(self, thermal: dict | None): if thermal: - self._attr_native_value = thermal['Temperatures'][self.index]['ReadingCelsius'] + for temp in thermal['Temperatures']: + if temp['MemberId'] == self.member_id: + self._attr_native_value = temp['ReadingCelsius'] + break self._attr_available = True else: self._attr_available = False From 4ce917f02ff776285acbf77ba0cbbe334ea1b2ff Mon Sep 17 00:00:00 2001 From: PocketMiner82 <73847326+PocketMiner82@users.noreply.github.com> Date: Mon, 24 Jun 2024 20:43:09 +0200 Subject: [PATCH 4/4] chore: remove debugging log message --- custom_components/idrac_power/idrac_rest.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/custom_components/idrac_power/idrac_rest.py b/custom_components/idrac_power/idrac_rest.py index 142b592..1ab8004 100755 --- a/custom_components/idrac_power/idrac_rest.py +++ b/custom_components/idrac_power/idrac_rest.py @@ -126,8 +126,6 @@ def update_thermals(self) -> dict: _LOGGER.debug(f"Couldn't update {self.host} thermals: {e}") new_thermals = None - _LOGGER.warning(new_thermals) - if new_thermals != self.thermal_values: self.thermal_values = new_thermals for callback in self.callback_thermals: