Skip to content

Commit

Permalink
Seems to build
Browse files Browse the repository at this point in the history
  • Loading branch information
benjamin-dcs committed Dec 23, 2024
1 parent 8f32b13 commit 075b8b7
Show file tree
Hide file tree
Showing 26 changed files with 3,534 additions and 834 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
README.md
.DS_Store
custom_components/ithodaalderop/__pycache__
*.pyc
112 changes: 112 additions & 0 deletions custom_components/ithodaalderop/_sensor_autotemp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
"""Sensor class for handling Autotemp sensors."""

import json

from homeassistant.components import mqtt
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import callback
from homeassistant.helpers.device_registry import DeviceInfo

from ._sensor_base import IthoBaseSensor
from .const import (
ADDON_TYPES,
AUTOTEMP_ERROR,
AUTOTEMP_MODE,
CONF_ADDON_TYPE,
DOMAIN,
MANUFACTURER,
)
from .definitions.base import IthoSensorEntityDescription


class IthoSensorAutotemp(IthoBaseSensor):
"""Representation of Itho add-on sensor for Autotemp data that is updated via MQTT."""

def __init__(
self,
description: IthoSensorEntityDescription,
config_entry: ConfigEntry,
) -> None:
"""Construct sensor for Autotemp."""
super().__init__(description, config_entry)

async def async_added_to_hass(self) -> None:
"""Subscribe to MQTT events."""

@callback
def message_received(message):
"""Handle new MQTT messages."""
payload = json.loads(message.payload)
json_field = self.entity_description.json_field
if json_field not in payload:
value = None
else:
value = payload[json_field]
if json_field == "Error":
self._extra_state_attributes = {
"Code": value,
}
value = AUTOTEMP_ERROR.get(value, "Unknown error")

if json_field == "Mode":
self._extra_state_attributes = {
"Code": value,
}
value = AUTOTEMP_MODE.get(value, "Unknown mode")

if json_field == "State off":
if value == 1:
value = "Off"
if payload["State cool"] == 1:
value = "Cooling"
if payload["State heating"] == 1:
value = "Heating"
if payload["state hand"] == 1:
value = "Hand"

self._attr_native_value = value
self.async_write_ha_state()

await mqtt.async_subscribe(
self.hass, self.entity_description.key, message_received, 1
)


class IthoSensorAutotempRoom(IthoBaseSensor):
"""Representation of Itho add-on room sensor for Autotemp data that is updated via MQTT."""

def __init__(
self, description: IthoSensorEntityDescription, config_entry: ConfigEntry
) -> None:
"""Construct sensor for Autotemp."""

self._attr_device_info = DeviceInfo(
identifiers={
(
DOMAIN,
f"{config_entry.data[CONF_ADDON_TYPE]}_room_{description.room.lower()}",
)
},
manufacturer=MANUFACTURER,
model=f"{ADDON_TYPES[config_entry.data[CONF_ADDON_TYPE]]} Spider",
name=f"Spider {description.room.capitalize()}",
via_device=(DOMAIN, config_entry.data[CONF_ADDON_TYPE]),
)

super().__init__(description, config_entry, use_base_sensor_device=False)

async def async_added_to_hass(self) -> None:
"""Subscribe to MQTT events."""

@callback
def message_received(message):
"""Handle new MQTT messages."""
payload = json.loads(message.payload)
value = payload.get(self.entity_description.json_field, None)

self._attr_native_value = value
self.async_write_ha_state()

await mqtt.async_subscribe(
self.hass, self.entity_description.key, message_received, 1
)
64 changes: 64 additions & 0 deletions custom_components/ithodaalderop/_sensor_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""Sensor base class."""

from homeassistant.components.sensor import SensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers.device_registry import DeviceInfo

from .const import (
ADDON_TYPES,
CONF_ADDON_TYPE,
CONF_NONCVE_MODEL,
DOMAIN,
MANUFACTURER,
NONCVE_DEVICES,
UNITTYPE_ICONS,
)
from .definitions.base import IthoSensorEntityDescription


class IthoBaseSensor(SensorEntity):
"""Base class sharing foundation for WPU, remotes and Fans."""

_attr_has_entity_name = True
entity_description: IthoSensorEntityDescription

_extra_state_attributes = None

def __init__(
self,
description: IthoSensorEntityDescription,
config_entry: ConfigEntry,
use_base_sensor_device: bool = True,
) -> None:
"""Initialize the sensor."""
self.entity_description = description

if use_base_sensor_device:
model = ADDON_TYPES[config_entry.data[CONF_ADDON_TYPE]]
if config_entry.data[CONF_ADDON_TYPE] == "noncve":
model = (
model + " - " + NONCVE_DEVICES[config_entry.data[CONF_NONCVE_MODEL]]
)

self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, config_entry.data[CONF_ADDON_TYPE])},
manufacturer=MANUFACTURER,
model=model,
name=ADDON_TYPES[config_entry.data[CONF_ADDON_TYPE]],
)

if description.unique_id is not None:
self._attr_unique_id = f"itho_{ADDON_TYPES[config_entry.data[CONF_ADDON_TYPE]]}_{description.unique_id.lower()}"
else:
self._attr_unique_id = f"itho_{ADDON_TYPES[config_entry.data[CONF_ADDON_TYPE]]}_{description.translation_key}"
self.entity_id = f"sensor.{self._attr_unique_id}"

@property
def icon(self) -> str | None:
"""Pick the right icon."""

if self.entity_description.icon is not None:
return self.entity_description.icon
if self.entity_description.native_unit_of_measurement in UNITTYPE_ICONS:
return UNITTYPE_ICONS[self.entity_description.native_unit_of_measurement]
return None
43 changes: 43 additions & 0 deletions custom_components/ithodaalderop/_sensor_co2_remote.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Sensor class for handling CO2 Remote sensors."""

import json

from homeassistant.components import mqtt
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import callback

from ._sensor_base import IthoBaseSensor
from .const import ADDON_TYPES, CONF_ADDON_TYPE

Check failure on line 10 in custom_components/ithodaalderop/_sensor_co2_remote.py

View workflow job for this annotation

GitHub Actions / build

Ruff (F401)

custom_components/ithodaalderop/_sensor_co2_remote.py:10:20: F401 `.const.ADDON_TYPES` imported but unused

Check failure on line 10 in custom_components/ithodaalderop/_sensor_co2_remote.py

View workflow job for this annotation

GitHub Actions / build

Ruff (F401)

custom_components/ithodaalderop/_sensor_co2_remote.py:10:33: F401 `.const.CONF_ADDON_TYPE` imported but unused
from .definitions.base import IthoSensorEntityDescription


class IthoSensorCO2Remote(IthoBaseSensor):
"""Representation of Itho add-on sensor for a Remote that is updated via MQTT."""

def __init__(
self,
description: IthoSensorEntityDescription,
config_entry: ConfigEntry,
) -> None:
"""Construct sensor for Remote."""
super().__init__(description, config_entry)

async def async_added_to_hass(self) -> None:
"""Subscribe to MQTT events."""

@callback
def message_received(message):
"""Handle new MQTT messages."""
payload = json.loads(message.payload)
json_field = self.entity_description.json_field
if json_field not in payload:
value = None
else:
value = payload[json_field]["co2"]

self._attr_native_value = value
self.async_write_ha_state()

await mqtt.async_subscribe(
self.hass, self.entity_description.key, message_received, 1
)
142 changes: 142 additions & 0 deletions custom_components/ithodaalderop/_sensor_fan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
"""Sensor class for handling Fan sensors."""

from datetime import datetime, timedelta
import json

from homeassistant.components import mqtt
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import callback

from ._sensor_base import IthoBaseSensor
from .const import (
HRU_ECO_250_300_ERROR_CODE,
HRU_ECO_350_ACTUAL_MODE,
HRU_ECO_350_GLOBAL_FAULT_CODE,
HRU_ECO_350_RH_ERROR_CODE,
HRU_ECO_STATUS,
)
from .definitions.base import IthoSensorEntityDescription


class IthoSensorFan(IthoBaseSensor):
"""Representation of a Itho add-on sensor that is updated via MQTT."""

_attr_has_entity_name = True
entity_description: IthoSensorEntityDescription

_extra_state_attributes = None

def __init__(
self,
description: IthoSensorEntityDescription,
config_entry: ConfigEntry,
) -> None:
"""Initialize the sensor."""
super().__init__(description, config_entry)

@property
def extra_state_attributes(self) -> list[str] | None:
"""Return the state attributes."""
return self._extra_state_attributes

async def async_added_to_hass(self) -> None:
"""Subscribe to MQTT events."""

@callback
def message_received(message):
"""Handle new MQTT messages."""
payload = json.loads(message.payload)
json_field = self.entity_description.json_field
if json_field not in payload:
value = None
else:
value = payload[json_field]
# HRU ECO 350
if json_field == "Actual Mode":
self._extra_state_attributes = {"Code": value}
value = HRU_ECO_350_ACTUAL_MODE.get(value, "Unknown mode")

# HRU ECO 350
if json_field == "Air Quality (%)":
_error_description = "Unknown error code"
if isinstance(value, (int, float)) and float(value) > 100:
_error_description = "Unknown error"
value = None

self._extra_state_attributes = {
"Error Description": _error_description,
}

# HRU ECO 350 / HRU ECO
if json_field in ["Airfilter counter", "Air filter counter"]:
_last_maintenance = ""
_next_maintenance_estimate = ""
if str(value).isnumeric():
_last_maintenance = (
datetime.now() - timedelta(hours=int(value))
).date()
_next_maintenance_estimate = (
datetime.now() + timedelta(days=180, hours=-int(value))
).date()
else:
_last_maintenance = "Invalid value"

self._extra_state_attributes = {
"Last Maintenance": _last_maintenance,
"Next Maintenance Estimate": _next_maintenance_estimate,
}

# HRU ECO 250/300
if json_field == "Error number":
_description = ""
if str(value).isnumeric():
_error_description = HRU_ECO_250_300_ERROR_CODE.get(
int(value), _description
)

self._extra_state_attributes = {
"Description": _description,
}

# HRU ECO 350
if json_field == "Global fault code":
_description = "Unknown fault code"
if str(value).isnumeric():
_description = HRU_ECO_350_GLOBAL_FAULT_CODE.get(
int(value), _description
)

self._extra_state_attributes = {
"Description": _description,
}

# HRU ECO 350
if json_field == "Highest received RH value (%RH)":
_error_description = ""
if isinstance(value, (int, float)) and float(value) > 100:
_error_description = HRU_ECO_350_RH_ERROR_CODE.get(
int(value), "Unknown error"
)
value = None

self._extra_state_attributes = {
"Error Description": _error_description,
}

# HRU ECO
if json_field == "Status":
self._extra_state_attributes = {
"Code": value,
}

_description = "Unknown status"
if str(value).isnumeric():
_description = HRU_ECO_STATUS.get(int(value), _description)
value = _description

self._attr_native_value = value
self.async_write_ha_state()

await mqtt.async_subscribe(
self.hass, self.entity_description.key, message_received, 1
)
Loading

0 comments on commit 075b8b7

Please sign in to comment.