Compare commits

...

6 Commits

11 changed files with 130 additions and 86 deletions

View File

@ -40,6 +40,7 @@ Support was confirmed for these models. If a supported model is missing, please
- Candy CIS633SCTTWIFI - Candy CIS633SCTTWIFI
- Haier XIB 3B2SFS-80 - Haier XIB 3B2SFS-80
- Haier XIB 6B2D3FB - Haier XIB 6B2D3FB
- Hoover HSOT3161WG
## Supported Languages ## Supported Languages
Translation of internal names like programs are available for all languages which are official supported by the hOn app: Translation of internal names like programs are available for all languages which are official supported by the hOn app:
@ -138,19 +139,19 @@ I moved the api related stuff into the package [pyhOn](https://github.com/Andre0
#### Configs #### Configs
| Name | Icon | Entity | Key | | Name | Icon | Entity | Key |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| 10° Heating | | `switch` | `startProgram.10degreeHeatingStatus` | | 10° Heating | `heat-wave` | `switch` | `settings.10degreeHeatingStatus` |
| Echo | | `switch` | `startProgram.echoStatus` | | Echo | `account-voice` | `switch` | `settings.echoStatus` |
| Eco Mode | | `switch` | `startProgram.ecoMode` | | Eco Mode | | `switch` | `settings.ecoMode` |
| Eco Pilot | | `select` | `startProgram.humanSensingStatus` | | Eco Pilot | `run` | `select` | `settings.humanSensingStatus` |
| Health Mode | | `switch` | `startProgram.healthMode` | | Health Mode | `medication-outline` | `switch` | `settings.healthMode` |
| Mute | | `switch` | `startProgram.muteStatus` | | Mute | `volume-off` | `switch` | `settings.muteStatus` |
| Program | | `select` | `startProgram.program` | | Program | | `select` | `startProgram.program` |
| Rapid Mode | | `switch` | `startProgram.rapidMode` | | Rapid Mode | `run-fast` | `switch` | `settings.rapidMode` |
| Screen Display | | `switch` | `startProgram.screenDisplayStatus` | | Screen Display | `monitor-small` | `switch` | `settings.screenDisplayStatus` |
| Self Cleaning | | `switch` | `startProgram.selfCleaningStatus` | | Self Cleaning | `air-filter` | `switch` | `settings.selfCleaningStatus` |
| Self Cleaning 56 | | `switch` | `startProgram.selfCleaning56Status` | | Self Cleaning 56 | `air-filter` | `switch` | `settings.selfCleaning56Status` |
| Silent Sleep | | `switch` | `startProgram.silentSleepStatus` | | Silent Sleep | `bed` | `switch` | `settings.silentSleepStatus` |
| Target Temperature | `thermometer` | `number` | `startProgram.tempSel` | | Target Temperature | `thermometer` | `number` | `settings.tempSel` |
### Dish washer ### Dish washer
#### Controls #### Controls
@ -209,7 +210,6 @@ I moved the api related stuff into the package [pyhOn](https://github.com/Andre0
| Pan Status | `pot-mix` | `binary_sensor` | `panStatus` | | Pan Status | `pot-mix` | `binary_sensor` | `panStatus` |
| Power | `lightning-bolt` | `sensor` | `power` | | Power | `lightning-bolt` | `sensor` | `power` |
| Remaining Time | `timer` | `sensor` | `remainingTimeMM` | | Remaining Time | `timer` | `sensor` | `remainingTimeMM` |
| Remote Control | `remote` | `binary_sensor` | `attributes.parameters.remoteCtrValid` |
| Temperature | `thermometer` | `sensor` | `temp` | | Temperature | `thermometer` | `sensor` | `temp` |
### Oven ### Oven
@ -231,7 +231,6 @@ I moved the api related stuff into the package [pyhOn](https://github.com/Andre0
| Connection | `wifi` | `binary_sensor` | `attributes.lastConnEvent.category` | | Connection | `wifi` | `binary_sensor` | `attributes.lastConnEvent.category` |
| On | `power-cycle` | `binary_sensor` | `attributes.parameters.onOffStatus` | | On | `power-cycle` | `binary_sensor` | `attributes.parameters.onOffStatus` |
| Remaining Time | `timer` | `sensor` | `remainingTimeMM` | | Remaining Time | `timer` | `sensor` | `remainingTimeMM` |
| Remote Control | `remote` | `binary_sensor` | `attributes.parameters.remoteCtrValid` |
| Start Time | `clock-start` | `sensor` | `delayTime` | | Start Time | `clock-start` | `sensor` | `delayTime` |
| Temperature | `thermometer` | `sensor` | `temp` | | Temperature | `thermometer` | `sensor` | `temp` |
| Temperature Selected | `thermometer` | `sensor` | `tempSel` | | Temperature Selected | `thermometer` | `sensor` | `tempSel` |
@ -293,10 +292,10 @@ I moved the api related stuff into the package [pyhOn](https://github.com/Andre0
| Dry Time | `timer` | `select` | `startProgram.dryTimeMM` | | Dry Time | `timer` | `select` | `startProgram.dryTimeMM` |
| Dry level | `hair-dryer` | `select` | `startProgram.dryLevel` | | Dry level | `hair-dryer` | `select` | `startProgram.dryLevel` |
| Energy Label | `lightning-bolt-circle` | `sensor` | `startProgram.energyLabel` | | Energy Label | `lightning-bolt-circle` | `sensor` | `startProgram.energyLabel` |
| Extra Rinse 1 | `numeric-1-box-multiple-outline` | `switch` | `extraRinse1` | | Extra Rinse 1 | `numeric-1-box-multiple-outline` | `switch` | `startProgram.extraRinse1` |
| Extra Rinse 2 | `numeric-2-box-multiple-outline` | `switch` | `extraRinse2` | | Extra Rinse 2 | `numeric-2-box-multiple-outline` | `switch` | `startProgram.extraRinse2` |
| Extra Rinse 3 | `numeric-3-box-multiple-outline` | `switch` | `extraRinse3` | | Extra Rinse 3 | `numeric-3-box-multiple-outline` | `switch` | `startProgram.extraRinse3` |
| Good Night | `weather-night` | `switch` | `goodNight` | | Good Night | `weather-night` | `switch` | `startProgram.goodNight` |
| Keep Fresh | `refresh-circle` | `switch` | `startProgram.autoSoftenerStatus` | | Keep Fresh | `refresh-circle` | `switch` | `startProgram.autoSoftenerStatus` |
| Liquid Detergent Dose | `cup-water` | `sensor` | `startProgram.liquidDetergentDose` | | Liquid Detergent Dose | `cup-water` | `sensor` | `startProgram.liquidDetergentDose` |
| Main Wash Time | `clock-start` | `number` | `startProgram.mainWashTime` | | Main Wash Time | `clock-start` | `number` | `startProgram.mainWashTime` |
@ -323,6 +322,7 @@ I moved the api related stuff into the package [pyhOn](https://github.com/Andre0
| Acqua Plus | | `binary_sensor` | `acquaplus` | | Acqua Plus | | `binary_sensor` | `acquaplus` |
| Anti-Crease | | `binary_sensor` | `anticrease` | | Anti-Crease | | `binary_sensor` | `anticrease` |
| Current Electricity Used | `lightning-bolt` | `sensor` | `currentElectricityUsed` | | Current Electricity Used | `lightning-bolt` | `sensor` | `currentElectricityUsed` |
| Current Temperature | `thermometer` | `sensor` | `temp` |
| Current Water Used | `water` | `sensor` | `currentWaterUsed` | | Current Water Used | `water` | `sensor` | `currentWaterUsed` |
| Dirt level | `liquid-spot` | `sensor` | `dirtyLevel` | | Dirt level | `liquid-spot` | `sensor` | `dirtyLevel` |
| Door | | `binary_sensor` | `doorStatus` | | Door | | `binary_sensor` | `doorStatus` |
@ -361,10 +361,10 @@ I moved the api related stuff into the package [pyhOn](https://github.com/Andre0
| Delay Status | `timer-check` | `switch` | `startProgram.delayStatus` | | Delay Status | `timer-check` | `switch` | `startProgram.delayStatus` |
| Delay Time | `timer-plus` | `number` | `startProgram.delayTime` | | Delay Time | `timer-plus` | `number` | `startProgram.delayTime` |
| Energy Label | `lightning-bolt-circle` | `sensor` | `startProgram.energyLabel` | | Energy Label | `lightning-bolt-circle` | `sensor` | `startProgram.energyLabel` |
| Extra Rinse 1 | `numeric-1-box-multiple-outline` | `switch` | `extraRinse1` | | Extra Rinse 1 | `numeric-1-box-multiple-outline` | `switch` | `startProgram.extraRinse1` |
| Extra Rinse 2 | `numeric-2-box-multiple-outline` | `switch` | `extraRinse2` | | Extra Rinse 2 | `numeric-2-box-multiple-outline` | `switch` | `startProgram.extraRinse2` |
| Extra Rinse 3 | `numeric-3-box-multiple-outline` | `switch` | `extraRinse3` | | Extra Rinse 3 | `numeric-3-box-multiple-outline` | `switch` | `startProgram.extraRinse3` |
| Good Night | `weather-night` | `switch` | `goodNight` | | Good Night | `weather-night` | `switch` | `startProgram.goodNight` |
| Keep Fresh | `refresh-circle` | `switch` | `startProgram.autoSoftenerStatus` | | Keep Fresh | `refresh-circle` | `switch` | `startProgram.autoSoftenerStatus` |
| Liquid Detergent Dose | `cup-water` | `sensor` | `startProgram.liquidDetergentDose` | | Liquid Detergent Dose | `cup-water` | `sensor` | `startProgram.liquidDetergentDose` |
| Main Wash Time | `clock-start` | `number` | `startProgram.mainWashTime` | | Main Wash Time | `clock-start` | `number` | `startProgram.mainWashTime` |
@ -385,6 +385,7 @@ I moved the api related stuff into the package [pyhOn](https://github.com/Andre0
| --- | --- | --- | --- | | --- | --- | --- | --- |
| Acqua Plus | | `binary_sensor` | `acquaplus` | | Acqua Plus | | `binary_sensor` | `acquaplus` |
| Current Electricity Used | `lightning-bolt` | `sensor` | `currentElectricityUsed` | | Current Electricity Used | `lightning-bolt` | `sensor` | `currentElectricityUsed` |
| Current Temperature | `thermometer` | `sensor` | `temp` |
| Current Water Used | `water` | `sensor` | `currentWaterUsed` | | Current Water Used | `water` | `sensor` | `currentWaterUsed` |
| Dirt level | `liquid-spot` | `sensor` | `dirtyLevel` | | Dirt level | `liquid-spot` | `sensor` | `dirtyLevel` |
| Door | | `binary_sensor` | `doorStatus` | | Door | | `binary_sensor` | `doorStatus` |

View File

@ -99,14 +99,6 @@ BINARY_SENSORS: dict[str, tuple[HonBinarySensorEntityDescription, ...]] = {
icon="mdi:wifi", icon="mdi:wifi",
translation_key="connection", translation_key="connection",
), ),
HonBinarySensorEntityDescription(
key="attributes.parameters.remoteCtrValid",
name="Remote Control",
device_class=BinarySensorDeviceClass.CONNECTIVITY,
on_value="1",
icon="mdi:remote",
translation_key="remote_control",
),
HonBinarySensorEntityDescription( HonBinarySensorEntityDescription(
key="attributes.parameters.onOffStatus", key="attributes.parameters.onOffStatus",
name="On", name="On",
@ -125,14 +117,6 @@ BINARY_SENSORS: dict[str, tuple[HonBinarySensorEntityDescription, ...]] = {
icon="mdi:wifi", icon="mdi:wifi",
translation_key="connection", translation_key="connection",
), ),
HonBinarySensorEntityDescription(
key="attributes.parameters.remoteCtrValid",
name="Remote Control",
device_class=BinarySensorDeviceClass.CONNECTIVITY,
on_value="1",
icon="mdi:remote",
translation_key="remote_control",
),
HonBinarySensorEntityDescription( HonBinarySensorEntityDescription(
key="attributes.parameters.onOffStatus", key="attributes.parameters.onOffStatus",
name="On", name="On",

View File

@ -64,6 +64,11 @@ class HonButtonEntity(HonEntity, ButtonEntity):
async def async_press(self) -> None: async def async_press(self) -> None:
await self._device.commands[self.entity_description.key].send() await self._device.commands[self.entity_description.key].send()
@property
def available(self) -> bool:
"""Return True if entity is available."""
return super().available and self._device.get("remoteCtrValid") == "1"
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:

View File

@ -29,7 +29,7 @@ from .hon import HonEntity, HonCoordinator
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
CLIMATES = { CLIMATES = {
"AC": (ClimateEntityDescription(key="startProgram"),), "AC": (ClimateEntityDescription(key="startProgram", icon="mdi:air-conditioner"),),
} }
@ -47,7 +47,7 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non
if descriptions := CLIMATES.get(device.appliance_type): if descriptions := CLIMATES.get(device.appliance_type):
for description in descriptions: for description in descriptions:
if description.key not in device.available_settings: if description.key not in list(device.commands):
continue continue
appliances.extend( appliances.extend(
[HonClimateEntity(hass, coordinator, entry, device, description)] [HonClimateEntity(hass, coordinator, entry, device, description)]
@ -61,21 +61,21 @@ class HonClimateEntity(HonEntity, ClimateEntity):
) -> None: ) -> None:
super().__init__(hass, entry, coordinator, device) super().__init__(hass, entry, coordinator, device)
self._coordinator = coordinator self._coordinator = coordinator
self._device = coordinator.device self._device = device
self.entity_description = description self.entity_description = description
self._hass = hass 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
self._attr_target_temperature_step = PRECISION_WHOLE self._attr_target_temperature_step = PRECISION_WHOLE
self._attr_max_temp = device.settings["tempSel"].max self._attr_max_temp = device.settings["settings.tempSel"].max
self._attr_min_temp = device.settings["tempSel"].min self._attr_min_temp = device.settings["settings.tempSel"].min
self._attr_hvac_modes = [HVACMode.OFF] + [ self._attr_hvac_modes = [HVACMode.OFF] + [
HON_HVAC_MODE[mode] for mode in device.settings["machMode"].values HON_HVAC_MODE[mode] for mode in device.settings["settings.machMode"].values
] ]
self._attr_fan_modes = [FAN_OFF] + [ self._attr_fan_modes = [FAN_OFF] + [
HON_FAN[mode] for mode in device.settings["windSpeed"].values HON_FAN[mode] for mode in device.settings["settings.windSpeed"].values
] ]
self._attr_swing_modes = [ self._attr_swing_modes = [
SWING_OFF, SWING_OFF,
@ -89,22 +89,28 @@ class HonClimateEntity(HonEntity, ClimateEntity):
| ClimateEntityFeature.SWING_MODE | ClimateEntityFeature.SWING_MODE
) )
self._handle_coordinator_update()
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:
self._device.commands["stopProgram"].send() await self._device.commands["stopProgram"].send()
else: else:
self._device.settings["program"].value = HON_HVAC_PROGRAM[hvac_mode] self._device.settings["startProgram.program"].value = HON_HVAC_PROGRAM[
self._device.commands["startProgram"].send() hvac_mode
]
await self._device.commands["startProgram"].send()
self._attr_hvac_mode = hvac_mode self._attr_hvac_mode = hvac_mode
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)
self._device.settings["windSpeed"].value = list(HON_FAN.keys())[mode_number] self._device.settings["settings.windSpeed"].value = list(HON_FAN.keys())[
self._device.commands["startProgram"].send() mode_number
]
await self._device.commands["settings"].send()
async def async_set_swing_mode(self, swing_mode): async def async_set_swing_mode(self, swing_mode):
horizontal = self._device.settings["windDirectionHorizontal"] horizontal = self._device.settings["settings.windDirectionHorizontal"]
vertical = self._device.settings["windDirectionVertical"] vertical = self._device.settings["settings.windDirectionVertical"]
if swing_mode in [SWING_BOTH, SWING_HORIZONTAL]: if swing_mode in [SWING_BOTH, SWING_HORIZONTAL]:
horizontal.value = "7" horizontal.value = "7"
if swing_mode in [SWING_BOTH, SWING_VERTICAL]: if swing_mode in [SWING_BOTH, SWING_VERTICAL]:
@ -114,30 +120,30 @@ class HonClimateEntity(HonEntity, ClimateEntity):
if swing_mode in [SWING_OFF, SWING_VERTICAL] and horizontal.value == "7": if swing_mode in [SWING_OFF, SWING_VERTICAL] and horizontal.value == "7":
horizontal.value = "0" horizontal.value = "0"
self._attr_swing_mode = swing_mode self._attr_swing_mode = swing_mode
self._device.commands["startProgram"].send() await self._device.commands["settings"].send()
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["selTemp"].value = temperature self._device.settings["settings.selTemp"].value = temperature
self._device.commands["startProgram"].send() await self._device.commands["settings"].send()
@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["tempSel"].max self._attr_max_temp = self._device.settings["settings.tempSel"].max
self._attr_min_temp = self._device.settings["tempSel"].min 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")] self._attr_hvac_mode = HON_HVAC_MODE[self._device.get("machMode") or "0"]
self._attr_fan_mode = HON_FAN[self._device.settings["windSpeed"].value] self._attr_fan_mode = HON_FAN[self._device.settings["settings.windSpeed"].value]
horizontal = self._device.settings["windDirectionHorizontal"] horizontal = self._device.settings["settings.windDirectionHorizontal"]
vertical = self._device.settings["windDirectionVertical"] vertical = self._device.settings["settings.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":

View File

@ -120,6 +120,19 @@ TUMBLE_DRYER_PR_PHASE = {
"19": "WASHING_CMD&CTRL.PHASE_DRYING.TITLE", "19": "WASHING_CMD&CTRL.PHASE_DRYING.TITLE",
"20": "WASHING_CMD&CTRL.PHASE_DRYING.TITLE", "20": "WASHING_CMD&CTRL.PHASE_DRYING.TITLE",
} }
DIRTY_LEVEL = {
"1": "WASHING_CMD&CTRL.PROGRAM_CYCLE_DETAIL_OPTIONS_VALUES_DESCRIPTION.LITTLE",
"2": "WASHING_CMD&CTRL.PROGRAM_CYCLE_DETAIL_OPTIONS_VALUES_DESCRIPTION.NORMAL",
"3": "WASHING_CMD&CTRL.PROGRAM_CYCLE_DETAIL_OPTIONS_VALUES_DESCRIPTION.VERY",
}
STEAM_LEVEL = {
"0": "WASHING_CMD&CTRL.PROGRAM_CYCLE_DETAIL_OPTIONS_VALUES_DESCRIPTION.NO_STEAM",
"1": "WASHING_CMD&CTRL.GUIDED_WASHING_SYMBOLS_FABRICS.COTTON_TITLE",
"2": "WASHING_CMD&CTRL.GUIDED_WASHING_SYMBOLS_FABRICS.DELICATE_TITLE",
"3": "WASHING_CMD&CTRL.GUIDED_WASHING_SYMBOLS_FABRICS.SYNTHETIC_TITLE",
}
DISHWASHER_PR_PHASE = { DISHWASHER_PR_PHASE = {
"0": "WASHING_CMD&CTRL.PHASE_READY.TITLE", "0": "WASHING_CMD&CTRL.PHASE_READY.TITLE",
"1": "WASHING_CMD&CTRL.PHASE_PREWASH.TITLE", "1": "WASHING_CMD&CTRL.PHASE_PREWASH.TITLE",

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.4"], "requirements": ["pyhOn==0.10.6"],
"version": "0.7.1" "version": "0.7.3-beta.2"
} }

View File

@ -146,7 +146,7 @@ NUMBERS: dict[str, tuple[NumberEntityDescription, ...]] = {
), ),
"AC": ( "AC": (
NumberEntityDescription( NumberEntityDescription(
key="startProgram.tempSel", key="settings.tempSel",
name="Target Temperature", name="Target Temperature",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
icon="mdi:thermometer", icon="mdi:thermometer",

View File

@ -98,8 +98,9 @@ SELECTS = {
translation_key="programs_ac", translation_key="programs_ac",
), ),
SelectEntityDescription( SelectEntityDescription(
key="startProgram.humanSensingStatus", key="settings.humanSensingStatus",
name="Eco Pilot", name="Eco Pilot",
icon="mdi:run",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
translation_key="eco_pilot", translation_key="eco_pilot",
), ),

View File

@ -161,6 +161,14 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = {
native_unit_of_measurement=UnitOfMass.KILOGRAMS, native_unit_of_measurement=UnitOfMass.KILOGRAMS,
translation_key="suggested_load", translation_key="suggested_load",
), ),
SensorEntityDescription(
key="temp",
name="Current Temperature",
icon="mdi:thermometer",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
translation_key="temperature",
),
), ),
"TD": ( "TD": (
SensorEntityDescription( SensorEntityDescription(

View File

@ -82,28 +82,28 @@ SWITCHES: dict[str, tuple[HonSwitchEntityDescription, ...]] = {
translation_key="acqua_plus", translation_key="acqua_plus",
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="extraRinse1", key="startProgram.extraRinse1",
name="Extra Rinse 1", name="Extra Rinse 1",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
icon="mdi:numeric-1-box-multiple-outline", icon="mdi:numeric-1-box-multiple-outline",
translation_key="extra_rinse_1", translation_key="extra_rinse_1",
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="extraRinse2", key="startProgram.extraRinse2",
name="Extra Rinse 2", name="Extra Rinse 2",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
icon="mdi:numeric-2-box-multiple-outline", icon="mdi:numeric-2-box-multiple-outline",
translation_key="extra_rinse_2", translation_key="extra_rinse_2",
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="extraRinse3", key="startProgram.extraRinse3",
name="Extra Rinse 3", name="Extra Rinse 3",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
icon="mdi:numeric-3-box-multiple-outline", icon="mdi:numeric-3-box-multiple-outline",
translation_key="extra_rinse_3", translation_key="extra_rinse_3",
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="goodNight", key="startProgram.goodNight",
name="Good Night", name="Good Night",
icon="mdi:weather-night", icon="mdi:weather-night",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
@ -237,59 +237,68 @@ SWITCHES: dict[str, tuple[HonSwitchEntityDescription, ...]] = {
), ),
"AC": ( "AC": (
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="startProgram.10degreeHeatingStatus", key="settings.10degreeHeatingStatus",
name="10° Heating", name="10° Heating",
icon="mdi:heat-wave",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
translation_key="10_degree_heating", translation_key="10_degree_heating",
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="startProgram.echoStatus", key="settings.echoStatus",
name="Echo", name="Echo",
icon="mdi:account-voice",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="startProgram.ecoMode", key="settings.ecoMode",
name="Eco Mode", name="Eco Mode",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
translation_key="eco_mode", translation_key="eco_mode",
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="startProgram.healthMode", key="settings.healthMode",
name="Health Mode", name="Health Mode",
icon="mdi:medication-outline",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="startProgram.muteStatus", key="settings.muteStatus",
name="Mute", name="Mute",
icon="mdi:volume-off",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
translation_key="mute_mode", translation_key="mute_mode",
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="startProgram.rapidMode", key="settings.rapidMode",
name="Rapid Mode", name="Rapid Mode",
icon="mdi:run-fast",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
translation_key="rapid_mode", translation_key="rapid_mode",
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="startProgram.screenDisplayStatus", key="settings.screenDisplayStatus",
name="Screen Display", name="Screen Display",
icon="mdi:monitor-small",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="startProgram.selfCleaning56Status", key="settings.selfCleaning56Status",
name="Self Cleaning 56", name="Self Cleaning 56",
icon="mdi:air-filter",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
translation_key="self_clean_56", translation_key="self_clean_56",
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="startProgram.selfCleaningStatus", key="settings.selfCleaningStatus",
name="Self Cleaning", name="Self Cleaning",
icon="mdi:air-filter",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
translation_key="self_clean", translation_key="self_clean",
), ),
HonSwitchEntityDescription( HonSwitchEntityDescription(
key="startProgram.silentSleepStatus", key="settings.silentSleepStatus",
name="Silent Sleep", name="Silent Sleep",
icon="mdi:bed",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
translation_key="silent_mode", translation_key="silent_mode",
), ),
@ -314,10 +323,18 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non
if descriptions := SWITCHES.get(device.appliance_type): if descriptions := SWITCHES.get(device.appliance_type):
for description in descriptions: for description in descriptions:
if ( if description.entity_category == EntityCategory.CONFIG:
device.get(description.key) is not None if description.key not in device.available_settings:
or description.key in device.available_settings continue
else:
if not any(
[
device.get(description.key) is not None,
description.turn_on_key in list(device.commands),
description.turn_off_key in list(device.commands),
]
): ):
continue
appliances.extend( appliances.extend(
[HonSwitchEntity(hass, coordinator, entry, device, description)] [HonSwitchEntity(hass, coordinator, entry, device, description)]
) )
@ -379,3 +396,11 @@ class HonSwitchEntity(HonEntity, SwitchEntity):
await self.coordinator.async_refresh() await self.coordinator.async_refresh()
else: else:
await self._device.commands[self.entity_description.turn_off_key].send() await self._device.commands[self.entity_description.turn_off_key].send()
@property
def available(self) -> bool:
"""Return True if entity is available."""
if self.entity_category == EntityCategory.CONFIG:
return super().available
else:
return super().available and self._device.get("remoteCtrValid") == "1"

View File

@ -29,6 +29,7 @@ Support was confirmed for these models. If a supported model is missing, please
- Candy CIS633SCTTWIFI - Candy CIS633SCTTWIFI
- Haier XIB 3B2SFS-80 - Haier XIB 3B2SFS-80
- Haier XIB 6B2D3FB - Haier XIB 6B2D3FB
- Hoover HSOT3161WG
## Supported Languages ## Supported Languages
Translation of internal names like programs are available for all languages which are official supported by the hOn app: Translation of internal names like programs are available for all languages which are official supported by the hOn app: