Compare commits

...

3 Commits

Author SHA1 Message Date
d963086dbf Fix climate not available #52 2023-05-19 01:27:44 +02:00
29238d3d08 Add supported devices 2023-05-18 23:48:19 +02:00
a4ec3290ba Many air conditioner fixes for #52 2023-05-17 00:01:33 +02:00
34 changed files with 217 additions and 54 deletions

View File

@ -60,7 +60,10 @@ Translation of internal names like programs are available for all languages whic
## Supported Models ## Supported Models
Support has been confirmed for these models, but many more will work. Please add already supported devices [with this form to complete the list](https://forms.gle/bTSD8qFotdZFytbf8). Support has been confirmed for these models, but many more will work. Please add already supported devices [with this form to complete the list](https://forms.gle/bTSD8qFotdZFytbf8).
- Haier AD105S2SM3FA
- Haier AS25PBAHRA - Haier AS25PBAHRA
- Haier AS25TADHRA-2
- Haier AS35TADHRA-2
- Haier EG9012B19SU1JD - Haier EG9012B19SU1JD
- Haier HD80-A3959 - Haier HD80-A3959
- Haier HW90-B14TEAM5 - Haier HW90-B14TEAM5
@ -155,6 +158,7 @@ For every device exists a hidden button which can be used to log all infos of yo
| Air Conditioner | `air-conditioner` | `climate` | `settings` | | Air Conditioner | `air-conditioner` | `climate` | `settings` |
| Echo | `account-voice` | `switch` | `settings.echoStatus` | | Echo | `account-voice` | `switch` | `settings.echoStatus` |
| Eco Mode | | `switch` | `settings.ecoMode` | | Eco Mode | | `switch` | `settings.ecoMode` |
| Eco Pilot | `run` | `select` | `settings.humanSensingStatus` |
| Health Mode | `medication-outline` | `switch` | `settings.healthMode` | | Health Mode | `medication-outline` | `switch` | `settings.healthMode` |
| Mute | `volume-off` | `switch` | `settings.muteStatus` | | Mute | `volume-off` | `switch` | `settings.muteStatus` |
| Rapid Mode | `run-fast` | `switch` | `settings.rapidMode` | | Rapid Mode | `run-fast` | `switch` | `settings.rapidMode` |
@ -162,15 +166,21 @@ For every device exists a hidden button which can be used to log all infos of yo
| Self Cleaning | `air-filter` | `switch` | `settings.selfCleaningStatus` | | Self Cleaning | `air-filter` | `switch` | `settings.selfCleaningStatus` |
| Self Cleaning 56 | `air-filter` | `switch` | `settings.selfCleaning56Status` | | Self Cleaning 56 | `air-filter` | `switch` | `settings.selfCleaning56Status` |
| Silent Sleep | `bed` | `switch` | `settings.silentSleepStatus` | | Silent Sleep | `bed` | `switch` | `settings.silentSleepStatus` |
#### Configs | Target Temperature | `thermometer` | `number` | `settings.tempSel` |
| Name | Icon | Entity | Key |
| --- | --- | --- | --- |
| Program | | `select` | `startProgram.program` |
#### Sensors #### Sensors
| Name | Icon | Entity | Key | | Name | Icon | Entity | Key |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| Eco Pilot | `run` | `select` | `settings.humanSensingStatus` | | Air Temperature Outdoor | `thermometer` | `sensor` | `tempAirOutdoor` |
| Target Temperature | `thermometer` | `number` | `settings.tempSel` | | Ch2O Cleaning | | `binary_sensor` | `ch2oCleaningStatus` |
| Coiler Temperature Indoor | `thermometer` | `sensor` | `tempCoilerIndoor` |
| Coiler Temperature Outside | `thermometer` | `sensor` | `tempCoilerOutdoor` |
| Defrost Temperature Outdoor | `thermometer` | `sensor` | `tempDefrostOutdoor` |
| Filter Replacement | | `binary_sensor` | `filterChangeStatusLocal` |
| In Air Temperature Outdoor | `thermometer` | `sensor` | `tempInAirOutdoor` |
| Indoor Temperature | `thermometer` | `sensor` | `tempIndoor` |
| Outdoor Temperature | `thermometer` | `sensor` | `tempOutdoor` |
| Program | | `select` | `startProgram.program` |
| Selected Temperature | `thermometer` | `sensor` | `tempSel` |
### Dish washer ### Dish washer
#### Controls #### Controls
@ -262,6 +272,8 @@ For every device exists a hidden button which can be used to log all infos of yo
| Name | Icon | Entity | Key | | Name | Icon | Entity | Key |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| Auto-Set Mode | `thermometer-auto` | `switch` | `settings.intelligenceMode` | | Auto-Set Mode | `thermometer-auto` | `switch` | `settings.intelligenceMode` |
| Freezer Temperature | `thermometer` | `number` | `settings.tempSelZ2` |
| Fridge Temperature | `thermometer` | `number` | `settings.tempSelZ1` |
| Super Cool | `snowflake` | `switch` | `settings.quickModeZ2` | | Super Cool | `snowflake` | `switch` | `settings.quickModeZ2` |
| Super Freeze | `snowflake-variant` | `switch` | `settings.quickModeZ1` | | Super Freeze | `snowflake-variant` | `switch` | `settings.quickModeZ1` |
#### Configs #### Configs
@ -274,8 +286,6 @@ For every device exists a hidden button which can be used to log all infos of yo
| Auto-Set Mode | `thermometer-auto` | `binary_sensor` | `intelligenceMode` | | Auto-Set Mode | `thermometer-auto` | `binary_sensor` | `intelligenceMode` |
| Door Status Freezer | `fridge-top` | `binary_sensor` | `doorStatusZ1` | | Door Status Freezer | `fridge-top` | `binary_sensor` | `doorStatusZ1` |
| Door Status Fridge | `fridge-bottom` | `binary_sensor` | `door2StatusZ1` | | Door Status Fridge | `fridge-bottom` | `binary_sensor` | `door2StatusZ1` |
| Freezer Temperature | `thermometer` | `number` | `settings.tempSelZ2` |
| Fridge Temperature | `thermometer` | `number` | `settings.tempSelZ1` |
| Holiday Mode | `palm-tree` | `binary_sensor` | `holidayMode` | | Holiday Mode | `palm-tree` | `binary_sensor` | `holidayMode` |
| Room Humidity | `water-percent` | `sensor` | `humidityEnv` | | Room Humidity | `water-percent` | `sensor` | `humidityEnv` |
| Room Temperature | `home-thermometer-outline` | `sensor` | `tempEnv` | | Room Temperature | `home-thermometer-outline` | `sensor` | `tempEnv` |

View File

@ -1,6 +1,8 @@
import logging import logging
from dataclasses import dataclass from dataclasses import dataclass
from pyhon import Hon
from homeassistant.components.binary_sensor import ( from homeassistant.components.binary_sensor import (
BinarySensorEntityDescription, BinarySensorEntityDescription,
BinarySensorDeviceClass, BinarySensorDeviceClass,
@ -8,8 +10,6 @@ from homeassistant.components.binary_sensor import (
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import callback from homeassistant.core import callback
from pyhon import Hon
from .const import DOMAIN from .const import DOMAIN
from .hon import HonCoordinator, HonEntity, unique_entities from .hon import HonCoordinator, HonEntity, unique_entities
@ -179,6 +179,20 @@ BINARY_SENSORS: dict[str, tuple[HonBinarySensorEntityDescription, ...]] = {
translation_key="door_open", translation_key="door_open",
), ),
), ),
"AC": (
HonBinarySensorEntityDescription(
key="filterChangeStatusLocal",
name="Filter Replacement",
device_class=BinarySensorDeviceClass.PROBLEM,
on_value="1",
translation_key="filter_replacement",
),
HonBinarySensorEntityDescription(
key="ch2oCleaningStatus",
name="Ch2O Cleaning",
on_value="1",
),
),
"REF": ( "REF": (
HonBinarySensorEntityDescription( HonBinarySensorEntityDescription(
key="quickModeZ2", key="quickModeZ2",
@ -264,8 +278,6 @@ class HonBinarySensorEntity(HonEntity, BinarySensorEntity):
def __init__(self, hass, coordinator, entry, device, description) -> None: def __init__(self, hass, coordinator, entry, device, description) -> None:
super().__init__(hass, entry, coordinator, device) super().__init__(hass, entry, coordinator, device)
self._coordinator = coordinator
self.entity_description = description self.entity_description = description
self._attr_unique_id = f"{super().unique_id}{description.key}" self._attr_unique_id = f"{super().unique_id}{description.key}"

View File

@ -56,8 +56,6 @@ class HonButtonEntity(HonEntity, ButtonEntity):
) -> None: ) -> None:
super().__init__(hass, entry, coordinator, device) super().__init__(hass, entry, coordinator, device)
self._coordinator = coordinator
self._device = device
self.entity_description = description self.entity_description = description
self._attr_unique_id = f"{super().unique_id}{description.key}" self._attr_unique_id = f"{super().unique_id}{description.key}"
@ -77,9 +75,7 @@ class HonButtonEntity(HonEntity, ButtonEntity):
class HonFeatureRequestButton(HonEntity, ButtonEntity): class HonFeatureRequestButton(HonEntity, ButtonEntity):
def __init__(self, hass, coordinator, entry, device: HonAppliance) -> None: def __init__(self, hass, coordinator, entry, device: HonAppliance) -> None:
super().__init__(hass, entry, coordinator, device) super().__init__(hass, entry, coordinator, device)
self._hass = hass
self._device = device
self._attr_unique_id = f"{super().unique_id}_log_device_info" self._attr_unique_id = f"{super().unique_id}_log_device_info"
self._attr_icon = "mdi:information" self._attr_icon = "mdi:information"
self._attr_name = "Show Device Info" self._attr_name = "Show Device Info"
@ -88,7 +84,9 @@ class HonFeatureRequestButton(HonEntity, ButtonEntity):
async def async_press(self) -> None: async def async_press(self) -> None:
pyhon_version = pkg_resources.get_distribution("pyhon").version pyhon_version = pkg_resources.get_distribution("pyhon").version
info = f"Device Info:\n{self._device.diagnose()}pyhOnVersion: {pyhon_version}" info = f"{self._device.diagnose()}pyhOnVersion: {pyhon_version}"
title = f"{self._device.nick_name} Device Info" title = f"{self._device.nick_name} Device Info"
persistent_notification.create(self._hass, f"```\n```{info}```\n```", title) persistent_notification.create(
self._hass, f"````\n```\n{info}\n```\n````", title
)
_LOGGER.info(info.replace(" ", "\u200B ")) _LOGGER.info(info.replace(" ", "\u200B "))

View File

@ -1,5 +1,8 @@
import logging import logging
from pyhon import Hon
from pyhon.appliance import HonAppliance
from homeassistant.components.climate import ( from homeassistant.components.climate import (
ClimateEntity, ClimateEntity,
ClimateEntityDescription, ClimateEntityDescription,
@ -20,9 +23,6 @@ from homeassistant.const import (
TEMP_CELSIUS, TEMP_CELSIUS,
) )
from homeassistant.core import callback from homeassistant.core import callback
from pyhon import Hon
from pyhon.appliance import HonAppliance
from .const import HON_HVAC_MODE, HON_FAN, HON_HVAC_PROGRAM, DOMAIN from .const import HON_HVAC_MODE, HON_FAN, HON_HVAC_PROGRAM, DOMAIN
from .hon import HonEntity, HonCoordinator from .hon import HonEntity, HonCoordinator
@ -56,8 +56,8 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non
for description in descriptions: for description in descriptions:
if description.key not in list(device.commands): if description.key not in list(device.commands):
continue continue
appliances.extend( appliances.append(
[HonClimateEntity(hass, coordinator, entry, device, description)] HonClimateEntity(hass, coordinator, entry, device, description)
) )
async_add_entities(appliances) async_add_entities(appliances)
@ -67,10 +67,7 @@ class HonClimateEntity(HonEntity, ClimateEntity):
self, hass, coordinator, entry, device: HonAppliance, description self, hass, coordinator, entry, device: HonAppliance, description
) -> None: ) -> None:
super().__init__(hass, entry, coordinator, device) super().__init__(hass, entry, coordinator, device)
self._coordinator = coordinator
self._device = device
self.entity_description = description self.entity_description = description
self._hass = hass
self._attr_unique_id = f"{super().unique_id}climate" self._attr_unique_id = f"{super().unique_id}climate"
self._attr_temperature_unit = TEMP_CELSIUS self._attr_temperature_unit = TEMP_CELSIUS
@ -96,7 +93,7 @@ class HonClimateEntity(HonEntity, ClimateEntity):
| ClimateEntityFeature.SWING_MODE | ClimateEntityFeature.SWING_MODE
) )
self._handle_coordinator_update() self._handle_coordinator_update(update=False)
async def async_set_hvac_mode(self, hvac_mode): async def async_set_hvac_mode(self, hvac_mode):
if hvac_mode == HVACMode.OFF: if hvac_mode == HVACMode.OFF:
@ -107,6 +104,7 @@ class HonClimateEntity(HonEntity, ClimateEntity):
] ]
await self._device.commands["startProgram"].send() await self._device.commands["startProgram"].send()
self._attr_hvac_mode = hvac_mode self._attr_hvac_mode = hvac_mode
self.async_write_ha_state()
async def async_set_fan_mode(self, fan_mode): async def async_set_fan_mode(self, fan_mode):
mode_number = list(HON_FAN.values()).index(fan_mode) mode_number = list(HON_FAN.values()).index(fan_mode)
@ -114,6 +112,7 @@ class HonClimateEntity(HonEntity, ClimateEntity):
mode_number mode_number
] ]
await self._device.commands["settings"].send() await self._device.commands["settings"].send()
self.async_write_ha_state()
async def async_set_swing_mode(self, swing_mode): async def async_set_swing_mode(self, swing_mode):
horizontal = self._device.settings["settings.windDirectionHorizontal"] horizontal = self._device.settings["settings.windDirectionHorizontal"]
@ -128,29 +127,29 @@ class HonClimateEntity(HonEntity, ClimateEntity):
horizontal.value = "0" horizontal.value = "0"
self._attr_swing_mode = swing_mode self._attr_swing_mode = swing_mode
await self._device.commands["settings"].send() await self._device.commands["settings"].send()
self.async_write_ha_state()
async def async_set_temperature(self, **kwargs): async def async_set_temperature(self, **kwargs):
if (temperature := kwargs.get(ATTR_TEMPERATURE)) is None: if (temperature := kwargs.get(ATTR_TEMPERATURE)) is None:
return False return False
self._device.settings["settings.tempSel"].value = int(temperature) self._device.settings["settings.tempSel"].value = str(int(temperature))
await self._device.commands["settings"].send() await self._device.commands["settings"].send()
self.async_write_ha_state()
@callback @callback
def _handle_coordinator_update(self, update=True) -> None: def _handle_coordinator_update(self, update=True) -> None:
self._attr_target_temperature = int(float(self._device.get("tempSel"))) self._attr_target_temperature = int(float(self._device.get("tempSel")))
self._attr_current_temperature = float(self._device.get("tempIndoor")) self._attr_current_temperature = float(self._device.get("tempIndoor"))
self._attr_max_temp = self._device.settings["settings.tempSel"].max
self._attr_min_temp = self._device.settings["settings.tempSel"].min
if self._device.get("onOffStatus") == "0": if self._device.get("onOffStatus") == "0":
self._attr_hvac_mode = HVACMode.OFF self._attr_hvac_mode = HVACMode.OFF
else: else:
self._attr_hvac_mode = HON_HVAC_MODE[self._device.get("machMode") or "0"] self._attr_hvac_mode = HON_HVAC_MODE[self._device.get("machMode") or "0"]
self._attr_fan_mode = HON_FAN[self._device.settings["settings.windSpeed"].value] self._attr_fan_mode = HON_FAN[self._device.get("windSpeed")]
horizontal = self._device.settings["settings.windDirectionHorizontal"] horizontal = self._device.get("windDirectionHorizontal")
vertical = self._device.settings["settings.windDirectionVertical"] vertical = self._device.get("windDirectionVertical")
if horizontal == "7" and vertical == "8": if horizontal == "7" and vertical == "8":
self._attr_swing_mode = SWING_BOTH self._attr_swing_mode = SWING_BOTH
elif horizontal == "7": elif horizontal == "7":
@ -159,3 +158,5 @@ class HonClimateEntity(HonEntity, ClimateEntity):
self._attr_swing_mode = SWING_VERTICAL self._attr_swing_mode = SWING_VERTICAL
else: else:
self._attr_swing_mode = SWING_OFF self._attr_swing_mode = SWING_OFF
if update:
self.async_write_ha_state()

View File

@ -1,9 +1,9 @@
import logging import logging
import voluptuous as vol import voluptuous as vol
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
from .const import DOMAIN from .const import DOMAIN
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)

View File

@ -21,7 +21,7 @@ PLATFORMS = [
HON_HVAC_MODE = { HON_HVAC_MODE = {
"0": HVACMode.AUTO, "0": HVACMode.AUTO,
"1": HVACMode.COOL, "1": HVACMode.COOL,
"2": HVACMode.COOL, "2": HVACMode.DRY,
"3": HVACMode.DRY, "3": HVACMode.DRY,
"4": HVACMode.HEAT, "4": HVACMode.HEAT,
"5": HVACMode.FAN_ONLY, "5": HVACMode.FAN_ONLY,

View File

@ -1,11 +1,11 @@
import logging import logging
from datetime import timedelta from datetime import timedelta
from pyhon.appliance import HonAppliance
from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from pyhon.appliance import HonAppliance
from .const import DOMAIN from .const import DOMAIN
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -19,6 +19,7 @@ class HonEntity(CoordinatorEntity):
self._hon = hass.data[DOMAIN][entry.unique_id] self._hon = hass.data[DOMAIN][entry.unique_id]
self._hass = hass self._hass = hass
self._coordinator = coordinator
self._device = device self._device = device
self._attr_unique_id = self._device.unique_id self._attr_unique_id = self._device.unique_id

View File

@ -6,6 +6,6 @@
"documentation": "https://github.com/Andre0512/hon/", "documentation": "https://github.com/Andre0512/hon/",
"iot_class": "cloud_polling", "iot_class": "cloud_polling",
"issue_tracker": "https://github.com/Andre0512/hon/issues", "issue_tracker": "https://github.com/Andre0512/hon/issues",
"requirements": ["pyhOn==0.10.7"], "requirements": ["pyhOn==0.10.9"],
"version": "0.8.0-beta.2" "version": "0.8.0-beta.4"
} }

View File

@ -200,8 +200,6 @@ class HonNumberEntity(HonEntity, NumberEntity):
def __init__(self, hass, coordinator, entry, device, description) -> None: def __init__(self, hass, coordinator, entry, device, description) -> None:
super().__init__(hass, entry, coordinator, device) super().__init__(hass, entry, coordinator, device)
self._coordinator = coordinator
self._device = device
self._data = device.settings[description.key] self._data = device.settings[description.key]
self.entity_description = description self.entity_description = description
self._attr_unique_id = f"{super().unique_id}{description.key}" self._attr_unique_id = f"{super().unique_id}{description.key}"

View File

@ -108,7 +108,6 @@ SELECTS = {
SelectEntityDescription( SelectEntityDescription(
key="startProgram.program", key="startProgram.program",
name="Program", name="Program",
entity_category=EntityCategory.CONFIG,
translation_key="programs_ac", translation_key="programs_ac",
), ),
SelectEntityDescription( SelectEntityDescription(
@ -159,8 +158,6 @@ class HonSelectEntity(HonEntity, SelectEntity):
) -> None: ) -> None:
super().__init__(hass, entry, coordinator, device) super().__init__(hass, entry, coordinator, device)
self._coordinator = coordinator
self._device = device
self.entity_description = description self.entity_description = description
self._attr_unique_id = f"{super().unique_id}{description.key}" self._attr_unique_id = f"{super().unique_id}{description.key}"

View File

@ -1,5 +1,7 @@
import logging import logging
from pyhon import Hon
from homeassistant.components.sensor import ( from homeassistant.components.sensor import (
SensorEntity, SensorEntity,
SensorDeviceClass, SensorDeviceClass,
@ -20,8 +22,6 @@ from homeassistant.const import (
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers.entity import EntityCategory from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.typing import StateType from homeassistant.helpers.typing import StateType
from pyhon import Hon
from . import const from . import const
from .const import DOMAIN from .const import DOMAIN
from .hon import HonCoordinator, HonEntity, unique_entities from .hon import HonCoordinator, HonEntity, unique_entities
@ -399,6 +399,72 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = {
options=list(const.DISHWASHER_PR_PHASE), options=list(const.DISHWASHER_PR_PHASE),
), ),
), ),
"AC": (
SensorEntityDescription(
key="tempAirOutdoor",
name="Air Temperature Outdoor",
icon="mdi:thermometer",
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
),
SensorEntityDescription(
key="tempCoilerIndoor",
name="Coiler Temperature Indoor",
icon="mdi:thermometer",
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
),
SensorEntityDescription(
key="tempCoilerOutdoor",
name="Coiler Temperature Outside",
icon="mdi:thermometer",
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
),
SensorEntityDescription(
key="tempDefrostOutdoor",
name="Defrost Temperature Outdoor",
icon="mdi:thermometer",
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
),
SensorEntityDescription(
key="tempInAirOutdoor",
name="In Air Temperature Outdoor",
icon="mdi:thermometer",
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
),
SensorEntityDescription(
key="tempIndoor",
name="Indoor Temperature",
icon="mdi:thermometer",
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
),
SensorEntityDescription(
key="tempOutdoor",
name="Outdoor Temperature",
icon="mdi:thermometer",
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
),
SensorEntityDescription(
key="tempSel",
name="Selected Temperature",
icon="mdi:thermometer",
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
),
),
"REF": ( "REF": (
SensorEntityDescription( SensorEntityDescription(
key="humidityEnv", key="humidityEnv",
@ -470,8 +536,6 @@ class HonSensorEntity(HonEntity, SensorEntity):
def __init__(self, hass, coordinator, entry, device, description) -> None: def __init__(self, hass, coordinator, entry, device, description) -> None:
super().__init__(hass, entry, coordinator, device) super().__init__(hass, entry, coordinator, device)
self._coordinator = coordinator
self.entity_description = description self.entity_description = description
self._attr_unique_id = f"{super().unique_id}{description.key}" self._attr_unique_id = f"{super().unique_id}{description.key}"

View File

@ -2,13 +2,14 @@ import logging
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any from typing import Any
from homeassistant.components.switch import SwitchEntityDescription, SwitchEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
from pyhon import Hon from pyhon import Hon
from pyhon.appliance import HonAppliance from pyhon.appliance import HonAppliance
from pyhon.parameter.range import HonParameterRange from pyhon.parameter.range import HonParameterRange
from homeassistant.components.switch import SwitchEntityDescription, SwitchEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
from homeassistant.core import callback
from .const import DOMAIN from .const import DOMAIN
from .hon import HonCoordinator, HonEntity, unique_entities from .hon import HonCoordinator, HonEntity, unique_entities
@ -19,6 +20,7 @@ _LOGGER = logging.getLogger(__name__)
class HonSwitchEntityDescriptionMixin: class HonSwitchEntityDescriptionMixin:
turn_on_key: str = "" turn_on_key: str = ""
turn_off_key: str = "" turn_off_key: str = ""
status_key: str = ""
@dataclass @dataclass
@ -251,12 +253,14 @@ SWITCHES: dict[str, tuple[HonSwitchEntityDescription, ...]] = {
"AC": ( "AC": (
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="settings.10degreeHeatingStatus", key="settings.10degreeHeatingStatus",
status_key="10degreeHeatingStatus",
name="10° Heating", name="10° Heating",
icon="mdi:heat-wave", icon="mdi:heat-wave",
translation_key="10_degree_heating", translation_key="10_degree_heating",
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="settings.echoStatus", key="settings.echoStatus",
status_key="echoStatus",
name="Echo", name="Echo",
icon="mdi:account-voice", icon="mdi:account-voice",
), ),
@ -267,23 +271,27 @@ SWITCHES: dict[str, tuple[HonSwitchEntityDescription, ...]] = {
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="settings.healthMode", key="settings.healthMode",
status_key="healthMode",
name="Health Mode", name="Health Mode",
icon="mdi:medication-outline", icon="mdi:medication-outline",
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="settings.muteStatus", key="settings.muteStatus",
status_key="muteStatus",
name="Mute", name="Mute",
icon="mdi:volume-off", icon="mdi:volume-off",
translation_key="mute_mode", translation_key="mute_mode",
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="settings.rapidMode", key="settings.rapidMode",
status_key="rapidMode",
name="Rapid Mode", name="Rapid Mode",
icon="mdi:run-fast", icon="mdi:run-fast",
translation_key="rapid_mode", translation_key="rapid_mode",
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="settings.screenDisplayStatus", key="settings.screenDisplayStatus",
status_key="screenDisplayStatus",
name="Screen Display", name="Screen Display",
icon="mdi:monitor-small", icon="mdi:monitor-small",
), ),
@ -295,12 +303,14 @@ SWITCHES: dict[str, tuple[HonSwitchEntityDescription, ...]] = {
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="settings.selfCleaningStatus", key="settings.selfCleaningStatus",
status_key="selfCleaningStatus",
name="Self Cleaning", name="Self Cleaning",
icon="mdi:air-filter", icon="mdi:air-filter",
translation_key="self_clean", translation_key="self_clean",
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="settings.silentSleepStatus", key="settings.silentSleepStatus",
status_key="silentSleepStatus",
name="Silent Sleep", name="Silent Sleep",
icon="mdi:bed", icon="mdi:bed",
translation_key="silent_mode", translation_key="silent_mode",
@ -377,8 +387,7 @@ class HonSwitchEntity(HonEntity, SwitchEntity):
description: HonSwitchEntityDescription, description: HonSwitchEntityDescription,
) -> None: ) -> None:
super().__init__(hass, entry, coordinator, device) super().__init__(hass, entry, coordinator, device)
self._coordinator = coordinator
self._device = device
self.entity_description = description self.entity_description = description
self._attr_unique_id = f"{super().unique_id}{description.key}" self._attr_unique_id = f"{super().unique_id}{description.key}"
@ -392,6 +401,8 @@ class HonSwitchEntity(HonEntity, SwitchEntity):
or hasattr(setting, "min") or hasattr(setting, "min")
and setting.value != setting.min and setting.value != setting.min
) )
elif self.entity_description.status_key:
return self._device.get(self.entity_description.status_key, "0") == "1"
return self._device.get(self.entity_description.key, False) return self._device.get(self.entity_description.key, False)
async def async_turn_on(self, **kwargs: Any) -> None: async def async_turn_on(self, **kwargs: Any) -> None:
@ -438,3 +449,11 @@ class HonSwitchEntity(HonEntity, SwitchEntity):
and self._device.get("attributes.lastConnEvent.category") and self._device.get("attributes.lastConnEvent.category")
!= "DISCONNECTED" != "DISCONNECTED"
) )
@callback
def _handle_coordinator_update(self):
if not self.entity_description.status_key:
return
value = self._device.get(self.entity_description.status_key, "0")
self._attr_state = value == "1"
self.async_write_ha_state()

View File

@ -1255,6 +1255,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Otevřená dvířka Chladnička" "name": "Otevřená dvířka Chladnička"
},
"filter_replacement": {
"name": "Výměna filtru"
} }
}, },
"number": { "number": {

View File

@ -1255,6 +1255,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Tür offen Kühlschrank" "name": "Tür offen Kühlschrank"
},
"filter_replacement": {
"name": "Filteraustausch"
} }
}, },
"number": { "number": {

View File

@ -1255,6 +1255,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Πόρτα ανοιχτή Ψυγείο" "name": "Πόρτα ανοιχτή Ψυγείο"
},
"filter_replacement": {
"name": "Αντικατάσταση φίλτρου"
} }
}, },
"number": { "number": {

View File

@ -1323,6 +1323,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Door open Fridge" "name": "Door open Fridge"
},
"filter_replacement": {
"name": "Filter replacement"
} }
}, },
"number": { "number": {

View File

@ -1255,6 +1255,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Puerta abierta Frigorífico" "name": "Puerta abierta Frigorífico"
},
"filter_replacement": {
"name": "Sustitución del filtro"
} }
}, },
"number": { "number": {

View File

@ -1255,6 +1255,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Porte ouverte Réfrigérateur" "name": "Porte ouverte Réfrigérateur"
},
"filter_replacement": {
"name": "Remplacement du filtre"
} }
}, },
"number": { "number": {

View File

@ -708,6 +708,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Door open Fridge" "name": "Door open Fridge"
},
"filter_replacement": {
"name": "Filter replacement"
} }
}, },
"number": { "number": {

View File

@ -1255,6 +1255,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Otvorena vrata Hladnjak" "name": "Otvorena vrata Hladnjak"
},
"filter_replacement": {
"name": "Zamjena filtra"
} }
}, },
"number": { "number": {

View File

@ -1307,6 +1307,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Porta aperta Frigorifero" "name": "Porta aperta Frigorifero"
},
"filter_replacement": {
"name": "Sostituzione filtro"
} }
}, },
"number": { "number": {

View File

@ -1255,6 +1255,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Deur open Koelkast" "name": "Deur open Koelkast"
},
"filter_replacement": {
"name": "Filter vervangen"
} }
}, },
"number": { "number": {

View File

@ -1255,6 +1255,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Drzwi otwarte Lodówka" "name": "Drzwi otwarte Lodówka"
},
"filter_replacement": {
"name": "Wymiana filtra"
} }
}, },
"number": { "number": {

View File

@ -1255,6 +1255,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Porta aberta Frigorífico" "name": "Porta aberta Frigorífico"
},
"filter_replacement": {
"name": "Substituição do filtro"
} }
}, },
"number": { "number": {

View File

@ -1255,6 +1255,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Ușă deschisă Frigider" "name": "Ușă deschisă Frigider"
},
"filter_replacement": {
"name": "Înlocuirea filtrului"
} }
}, },
"number": { "number": {

View File

@ -1255,6 +1255,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Дверца открыта Холодильник" "name": "Дверца открыта Холодильник"
},
"filter_replacement": {
"name": "Замена фильтра"
} }
}, },
"number": { "number": {

View File

@ -1255,6 +1255,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Otvorené dvere Chladnička" "name": "Otvorené dvere Chladnička"
},
"filter_replacement": {
"name": "Výmena filtra"
} }
}, },
"number": { "number": {

View File

@ -1255,6 +1255,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Door open Hladilnik" "name": "Door open Hladilnik"
},
"filter_replacement": {
"name": "Menjava filtra"
} }
}, },
"number": { "number": {

View File

@ -1255,6 +1255,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Vrata su otvorena Frižider" "name": "Vrata su otvorena Frižider"
},
"filter_replacement": {
"name": "Zamena filtera"
} }
}, },
"number": { "number": {

View File

@ -1255,6 +1255,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "Kapıık Buzdolabı" "name": "Kapıık Buzdolabı"
},
"filter_replacement": {
"name": "Filtre değişimi"
} }
}, },
"number": { "number": {

View File

@ -1255,6 +1255,9 @@
}, },
"fridge_door": { "fridge_door": {
"name": "门打开 冰箱" "name": "门打开 冰箱"
},
"filter_replacement": {
"name": "更换过滤器"
} }
}, },
"number": { "number": {

View File

@ -49,7 +49,10 @@ Translation of internal names like programs are available for all languages whic
## Supported Models ## Supported Models
Support has been confirmed for these models, but many more will work. Please add already supported devices [with this form to complete the list](https://forms.gle/bTSD8qFotdZFytbf8). Support has been confirmed for these models, but many more will work. Please add already supported devices [with this form to complete the list](https://forms.gle/bTSD8qFotdZFytbf8).
- Haier AD105S2SM3FA
- Haier AS25PBAHRA - Haier AS25PBAHRA
- Haier AS25TADHRA-2
- Haier AS35TADHRA-2
- Haier EG9012B19SU1JD - Haier EG9012B19SU1JD
- Haier HD80-A3959 - Haier HD80-A3959
- Haier HW90-B14TEAM5 - Haier HW90-B14TEAM5

View File

@ -112,6 +112,7 @@ NAMES = {
"super_freeze": "REF_CMD&CTRL.MODALITIES.SUPER_FREEZE", "super_freeze": "REF_CMD&CTRL.MODALITIES.SUPER_FREEZE",
"freezer_door": ["GLOBALS.APPLIANCE_STATUS.DOOR_OPEN", "REF.ZONES.FREEZER"], "freezer_door": ["GLOBALS.APPLIANCE_STATUS.DOOR_OPEN", "REF.ZONES.FREEZER"],
"fridge_door": ["GLOBALS.APPLIANCE_STATUS.DOOR_OPEN", "REF.ZONES.FRIDGE"], "fridge_door": ["GLOBALS.APPLIANCE_STATUS.DOOR_OPEN", "REF.ZONES.FRIDGE"],
"filter_replacement": "AP.MAINTENANCE.FILTER_REPLACEMENT",
}, },
"button": { "button": {
"induction_hob": "GLOBALS.APPLIANCES_NAME.IH", "induction_hob": "GLOBALS.APPLIANCES_NAME.IH",

View File

@ -61,7 +61,9 @@ for entity_type, appliances in entities.items():
attributes = (key, entity.name, entity.icon, entity_type) attributes = (key, entity.name, entity.icon, entity_type)
category = ( category = (
"control" "control"
if entity_type in ["switch", "button", "climate"] if entity.key.startswith("settings")
or hasattr(entity, "turn_on_key")
or entity_type in ["button", "climate"]
else "sensor" else "sensor"
) )
result.setdefault(appliance, {}).setdefault( result.setdefault(appliance, {}).setdefault(