Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
93b9989cf2 | |||
8eaf2d75e6 | |||
57473349c3 | |||
dfd661cc7c | |||
f89e2361df | |||
075d34b5e2 | |||
88c76b8056 | |||
03a1e40b6e | |||
9d8b17b2cf |
17
.github/workflows/hacs_check.yml
vendored
Normal file
17
.github/workflows/hacs_check.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
name: HACS Action
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
jobs:
|
||||
hacs:
|
||||
name: HACS Action
|
||||
runs-on: "ubuntu-latest"
|
||||
steps:
|
||||
- name: HACS Action
|
||||
uses: "hacs/action@main"
|
||||
with:
|
||||
category: "integration"
|
14
.github/workflows/validate.yml
vendored
Normal file
14
.github/workflows/validate.yml
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
name: Validate with hassfest
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: "ubuntu-latest"
|
||||
steps:
|
||||
- uses: "actions/checkout@v3"
|
||||
- uses: "home-assistant/actions/hassfest@master"
|
56
README.md
56
README.md
@ -1,10 +1,13 @@
|
||||
# hOn
|
||||
Home Assistant component supporting hOn cloud.
|
||||
# Haier hOn
|
||||
[](https://github.com/hacs/integration)
|
||||
|
||||
Home Assistant component supporting devices of Haier's mobile app **hOn**.
|
||||
|
||||
## Installation
|
||||
1. Installing via HACS
|
||||
#### Installing via HACS
|
||||
1. You need to have installed [HACS](https://hacs.xyz/)
|
||||
2. Go to HACS->Integrations
|
||||
3. Add this repo into your HACS custom repositories
|
||||
3. Add this repo (`https://github.com/Andre0512/hon.git`) into your HACS custom repositories
|
||||
4. Search for Haier hOn and Download it
|
||||
5. Restart your HomeAssistant
|
||||
6. Go to Settings->Devices & Services
|
||||
@ -13,6 +16,51 @@ Home Assistant component supporting hOn cloud.
|
||||
9. Search for Haier hOn
|
||||
10. Type your username used in the hOn App and hit submit
|
||||
|
||||
## Contribute
|
||||
Any kind of contribution is welcome!
|
||||
#### Add appliances or additional attributes
|
||||
1. Install [pyhOn](https://github.com/Andre0512/pyhOn)
|
||||
```commandline
|
||||
$ pip install pyhOn
|
||||
```
|
||||
2. Use the commandline tool to read out all appliance data from your account
|
||||
```commandline
|
||||
$ pyhOn
|
||||
User for hOn account: user.name@example.com
|
||||
Password for hOn account: ********
|
||||
========== WM - Washing Machine ==========
|
||||
commands:
|
||||
pauseProgram: pauseProgram command
|
||||
resumeProgram: resumeProgram command
|
||||
startProgram: startProgram command
|
||||
stopProgram: stopProgram command
|
||||
data:
|
||||
actualWeight: 0
|
||||
airWashTempLevel: 0
|
||||
airWashTime: 0
|
||||
antiAllergyStatus: 0
|
||||
...
|
||||
```
|
||||
3. Fork this repository and clone it to your local machine
|
||||
4. Add the keys of the attributes you'd like to have as `EntityDescription` into this Repository
|
||||
_Example: Add pause button_
|
||||
```python
|
||||
BUTTONS: dict[str, tuple[ButtonEntityDescription, ...]] = {
|
||||
"WM": ( # WM is the applianceTypeName
|
||||
ButtonEntityDescription(
|
||||
key="pauseProgram", # key from pyhOn
|
||||
name="Pause Program", # name in home assistant
|
||||
icon="mdi:pause", # icon in home assistant
|
||||
...
|
||||
),
|
||||
...
|
||||
```
|
||||
5. Create a [pull request](https://github.com/Andre0512/hon/pulls)
|
||||
|
||||
#### Tips and Tricks
|
||||
- If you want to have some states humanreadable, have a look at the `translation_key` parameter of the `EntityDescription`
|
||||
- If you need to implement some more logic, create a pull request to the underlying library. There we collect special requirements in the `appliances` directory.
|
||||
|
||||
## Supported Appliances
|
||||
- Washing Machine
|
||||
|
||||
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"domain": "hon",
|
||||
"name": "hOn",
|
||||
"config_flow": true,
|
||||
"version": "0.1.0",
|
||||
"codeowners": ["@Andre0512"],
|
||||
"iot_class": "cloud_polling",
|
||||
"requirements": ["pyhOn==0.2.4"],
|
||||
"documentation": "https://github.com/Andre0512/hOn/"
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "hOn",
|
||||
"description": "Please enters your hOn credentials",
|
||||
"data": {
|
||||
"email": "Email Address",
|
||||
"password": "Password"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"mode": {
|
||||
"state": {
|
||||
"1": "Ready",
|
||||
"2": "Running",
|
||||
"5": "Scheduled",
|
||||
"6": "Error",
|
||||
"7": "Finished"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"state": {
|
||||
"00": "No error",
|
||||
"100000000000": "E2: Check if the door is closed",
|
||||
"8000000000000": "E4: Check the water supply"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -26,16 +26,16 @@ class HonBinarySensorEntityDescription(HonBinarySensorEntityDescriptionMixin, Bi
|
||||
BINARY_SENSORS: dict[str, tuple[HonBinarySensorEntityDescription, ...]] = {
|
||||
"WM": (
|
||||
HonBinarySensorEntityDescription(
|
||||
key="lastConnEvent.category",
|
||||
key="attributes.lastConnEvent.category",
|
||||
name="Connection",
|
||||
device_class=BinarySensorDeviceClass.CONNECTIVITY,
|
||||
on_value="CONNECTED",
|
||||
),
|
||||
HonBinarySensorEntityDescription(
|
||||
key="doorLockStatus",
|
||||
name="Door Locked",
|
||||
name="Door",
|
||||
device_class=BinarySensorDeviceClass.DOOR,
|
||||
on_value="1",
|
||||
on_value="0",
|
||||
),
|
||||
)
|
||||
}
|
||||
@ -53,9 +53,9 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non
|
||||
hass.data[DOMAIN]["coordinators"][device.mac_address] = coordinator
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
if descriptions := BINARY_SENSORS.get(device.appliance_type_name):
|
||||
if descriptions := BINARY_SENSORS.get(device.appliance_type):
|
||||
for description in descriptions:
|
||||
if not device.data.get(description.key):
|
||||
if not device.get(description.key):
|
||||
_LOGGER.info("Can't setup %s", description.key)
|
||||
continue
|
||||
appliances.extend([
|
||||
@ -78,9 +78,9 @@ class HonBinarySensorEntity(HonEntity, BinarySensorEntity):
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
return self._device.data.get(self.entity_description.key, "") == self.entity_description.on_value
|
||||
return self._device.get(self.entity_description.key, "") == self.entity_description.on_value
|
||||
|
||||
@callback
|
||||
def _handle_coordinator_update(self):
|
||||
self._attr_native_value = self._device.data.get(self.entity_description.key, "")
|
||||
self._attr_native_value = self._device.get(self.entity_description.key, "") == self.entity_description.on_value
|
||||
self.async_write_ha_state()
|
@ -9,16 +9,16 @@ from .hon import HonCoordinator, HonEntity
|
||||
|
||||
BUTTONS: dict[str, tuple[ButtonEntityDescription, ...]] = {
|
||||
"WM": (
|
||||
ButtonEntityDescription(
|
||||
key="pauseProgram",
|
||||
name="Pause Program",
|
||||
icon="mdi:pause",
|
||||
),
|
||||
ButtonEntityDescription(
|
||||
key="resumeProgram",
|
||||
name="Resume Program",
|
||||
icon="mdi:play-pause",
|
||||
),
|
||||
# ButtonEntityDescription(
|
||||
# key="pauseProgram",
|
||||
# name="Pause Program",
|
||||
# icon="mdi:pause",
|
||||
# ),
|
||||
# ButtonEntityDescription(
|
||||
# key="resumeProgram",
|
||||
# name="Resume Program",
|
||||
# icon="mdi:play-pause",
|
||||
# ),
|
||||
),
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non
|
||||
hass.data[DOMAIN]["coordinators"][device.mac_address] = coordinator
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
if descriptions := BUTTONS.get(device.appliance_type_name):
|
||||
if descriptions := BUTTONS.get(device.appliance_type):
|
||||
for description in descriptions:
|
||||
if not device.commands.get(description.key):
|
||||
continue
|
1
custom_components/hOn/config_flow.py → custom_components/hon/config_flow.py
Executable file → Normal file
1
custom_components/hOn/config_flow.py → custom_components/hon/config_flow.py
Executable file → Normal file
@ -11,7 +11,6 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HonFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
|
||||
VERSION = 1
|
||||
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL
|
||||
|
0
custom_components/hOn/const.py → custom_components/hon/const.py
Executable file → Normal file
0
custom_components/hOn/const.py → custom_components/hon/const.py
Executable file → Normal file
4
custom_components/hOn/hon.py → custom_components/hon/hon.py
Executable file → Normal file
4
custom_components/hOn/hon.py → custom_components/hon/hon.py
Executable file → Normal file
@ -28,10 +28,10 @@ class HonEntity(CoordinatorEntity):
|
||||
def device_info(self):
|
||||
return DeviceInfo(
|
||||
identifiers={(DOMAIN, self._device.mac_address)},
|
||||
manufacturer=self._device.brand,
|
||||
manufacturer=self._device.get("brand", ""),
|
||||
name=self._device.nick_name if self._device.nick_name else self._device.model_name,
|
||||
model=self._device.model_name,
|
||||
sw_version=self._device.fw_version,
|
||||
sw_version=self._device.get("fwVersion", ""),
|
||||
)
|
||||
|
||||
|
12
custom_components/hon/manifest.json
Normal file
12
custom_components/hon/manifest.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"domain": "hon",
|
||||
"name": "Haier hOn",
|
||||
"codeowners": ["@Andre0512"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://github.com/Andre0512/hon/",
|
||||
"iot_class": "cloud_polling",
|
||||
"issue_tracker": "https://github.com/Andre0512/hon/issues",
|
||||
"requirements": ["pyhOn==0.3.7"],
|
||||
"version": "0.2.4"
|
||||
}
|
||||
|
@ -20,19 +20,20 @@ NUMBERS: dict[str, tuple[NumberEntityDescription, ...]] = {
|
||||
NumberEntityDescription(
|
||||
key="startProgram.delayTime",
|
||||
name="Delay Time",
|
||||
icon="mdi:timer",
|
||||
icon="mdi:timer-plus",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
native_unit_of_measurement=UnitOfTime.MINUTES
|
||||
),
|
||||
NumberEntityDescription(
|
||||
key="startProgram.rinseIterations",
|
||||
name="Rinse Iterations",
|
||||
icon="mdi:rotate-right",
|
||||
entity_category=EntityCategory.CONFIG
|
||||
),
|
||||
NumberEntityDescription(
|
||||
key="startProgram.mainWashTime",
|
||||
name="Main Wash Time",
|
||||
icon="mdi:timer",
|
||||
icon="mdi:clock-start",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
native_unit_of_measurement=UnitOfTime.MINUTES
|
||||
),
|
||||
@ -52,7 +53,7 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non
|
||||
hass.data[DOMAIN]["coordinators"][device.mac_address] = coordinator
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
if descriptions := NUMBERS.get(device.appliance_type_name):
|
||||
if descriptions := NUMBERS.get(device.appliance_type):
|
||||
for description in descriptions:
|
||||
appliances.extend([
|
||||
HonNumberEntity(hass, coordinator, entry, device, description)]
|
||||
@ -66,6 +67,7 @@ class HonNumberEntity(HonEntity, NumberEntity):
|
||||
super().__init__(hass, entry, coordinator, device)
|
||||
|
||||
self._coordinator = coordinator
|
||||
self._device = device
|
||||
self._data = device.settings[description.key]
|
||||
self.entity_description = description
|
||||
self._attr_unique_id = f"{super().unique_id}{description.key}"
|
||||
@ -77,18 +79,18 @@ class HonNumberEntity(HonEntity, NumberEntity):
|
||||
|
||||
@property
|
||||
def native_value(self) -> float | None:
|
||||
return self._data.value
|
||||
return self._device.get(self.entity_description.key)
|
||||
|
||||
async def async_set_native_value(self, value: float) -> None:
|
||||
self._data.value = value
|
||||
self._device.settings[self.entity_description.key].value = value
|
||||
await self.coordinator.async_request_refresh()
|
||||
|
||||
@callback
|
||||
def _handle_coordinator_update(self):
|
||||
self._data = self._device.settings[self.entity_description.key]
|
||||
if isinstance(self._data, HonParameterRange):
|
||||
self._attr_native_max_value = self._data.max
|
||||
self._attr_native_min_value = self._data.min
|
||||
self._attr_native_step = self._data.step
|
||||
self._attr_native_value = self._data.value
|
||||
setting = self._device.settings[self.entity_description.key]
|
||||
if isinstance(setting, HonParameterRange):
|
||||
self._attr_native_max_value = setting.max
|
||||
self._attr_native_min_value = setting.min
|
||||
self._attr_native_step = setting.step
|
||||
self._attr_native_value = setting.value
|
||||
self.async_write_ha_state()
|
@ -1,4 +1,3 @@
|
||||
"""Support for Tuya select."""
|
||||
from __future__ import annotations
|
||||
|
||||
from pyhon import HonConnection
|
||||
@ -11,10 +10,9 @@ from homeassistant.const import UnitOfTemperature, REVOLUTIONS_PER_MINUTE
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
|
||||
from .const import DOMAIN
|
||||
from .hon import HonEntity, HonCoordinator
|
||||
|
||||
DOMAIN = "hon"
|
||||
|
||||
SELECTS = {
|
||||
"WM": (
|
||||
SelectEntityDescription(
|
||||
@ -33,8 +31,9 @@ SELECTS = {
|
||||
),
|
||||
SelectEntityDescription(
|
||||
key="startProgram.program",
|
||||
name="Programme",
|
||||
entity_category=EntityCategory.CONFIG
|
||||
name="Program",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
translation_key="programs"
|
||||
),
|
||||
)
|
||||
}
|
||||
@ -52,9 +51,9 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non
|
||||
hass.data[DOMAIN]["coordinators"][device.mac_address] = coordinator
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
if descriptions := SELECTS.get(device.appliance_type_name):
|
||||
if descriptions := SELECTS.get(device.appliance_type):
|
||||
for description in descriptions:
|
||||
if not device.data.get(description.key):
|
||||
if not device.get(description.key):
|
||||
continue
|
||||
appliances.extend([
|
||||
HonSelectEntity(hass, coordinator, entry, device, description)]
|
||||
@ -68,32 +67,31 @@ class HonSelectEntity(HonEntity, SelectEntity):
|
||||
|
||||
self._coordinator = coordinator
|
||||
self._device = device
|
||||
self._data = device.settings[description.key]
|
||||
self.entity_description = description
|
||||
self._attr_unique_id = f"{super().unique_id}{description.key}"
|
||||
|
||||
if not isinstance(self._data, HonParameterFixed):
|
||||
self._attr_options: list[str] = self._data.values
|
||||
if not isinstance(self._device.settings[description.key], HonParameterFixed):
|
||||
self._attr_options: list[str] = device.settings[description.key].values
|
||||
else:
|
||||
self._attr_options = [self._data.value]
|
||||
self._attr_options: list[str] = [device.settings[description.key].value]
|
||||
|
||||
@property
|
||||
def current_option(self) -> str | None:
|
||||
value = self._data.value
|
||||
value = self._device.settings[self.entity_description.key].value
|
||||
if value is None or value not in self._attr_options:
|
||||
return None
|
||||
return value
|
||||
|
||||
async def async_select_option(self, option: str) -> None:
|
||||
self._data.value = option
|
||||
self._device.settings[self.entity_description.key].value = option
|
||||
await self.coordinator.async_request_refresh()
|
||||
|
||||
@callback
|
||||
def _handle_coordinator_update(self):
|
||||
self._data = self._device.settings[self.entity_description.key]
|
||||
if not isinstance(self._data, HonParameterFixed):
|
||||
self._attr_options: list[str] = self._data.values
|
||||
setting = self._device.settings[self.entity_description.key]
|
||||
if not isinstance(self._device.settings[self.entity_description.key], HonParameterFixed):
|
||||
self._attr_options: list[str] = setting.values
|
||||
else:
|
||||
self._attr_options = [self._data.value]
|
||||
self._attr_native_value = self._data.value
|
||||
self._attr_options = [setting.value]
|
||||
self._attr_native_value = setting.value
|
||||
self.async_write_ha_state()
|
@ -9,7 +9,7 @@ from homeassistant.components.sensor import (
|
||||
SensorEntityDescription,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import UnitOfEnergy, UnitOfVolume, UnitOfMass, UnitOfPower
|
||||
from homeassistant.const import UnitOfEnergy, UnitOfVolume, UnitOfMass, UnitOfPower, UnitOfTime
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.typing import StateType
|
||||
@ -65,17 +65,30 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = {
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="machMode",
|
||||
name="Machine Last Status",
|
||||
name="Machine Status",
|
||||
icon="mdi:information",
|
||||
translation_key="mode"
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="errors",
|
||||
name="Last Error",
|
||||
name="Error",
|
||||
icon="mdi:math-log",
|
||||
translation_key="errors"
|
||||
),
|
||||
|
||||
SensorEntityDescription(
|
||||
key="remainingTimeMM",
|
||||
name="Remaining Time",
|
||||
icon="mdi:timer",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfTime.MINUTES,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="spinSpeed",
|
||||
name="Spin Speed",
|
||||
icon="mdi:timer",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfTime.MINUTES,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@ -92,9 +105,9 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non
|
||||
hass.data[DOMAIN]["coordinators"][device.mac_address] = coordinator
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
if descriptions := SENSORS.get(device.appliance_type_name):
|
||||
if descriptions := SENSORS.get(device.appliance_type):
|
||||
for description in descriptions:
|
||||
if not device.data.get(description.key):
|
||||
if not device.get(description.key):
|
||||
continue
|
||||
appliances.extend([
|
||||
HonSensorEntity(hass, coordinator, entry, device, description)]
|
||||
@ -114,9 +127,9 @@ class HonSensorEntity(HonEntity, SensorEntity):
|
||||
|
||||
@property
|
||||
def native_value(self) -> StateType:
|
||||
return self._device.data.get(self.entity_description.key, "")
|
||||
return self._device.get(self.entity_description.key, "")
|
||||
|
||||
@callback
|
||||
def _handle_coordinator_update(self):
|
||||
self._attr_native_value = self._device.data.get(self.entity_description.key, "")
|
||||
self._attr_native_value = self._device.get(self.entity_description.key, "")
|
||||
self.async_write_ha_state()
|
@ -1,13 +1,11 @@
|
||||
from collections.abc import Callable, Coroutine
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
from pyhon import HonConnection
|
||||
from pyhon.device import HonDevice
|
||||
|
||||
from homeassistant.components.switch import SwitchEntityDescription, SwitchEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import EntityCategory
|
||||
from pyhon import HonConnection
|
||||
from pyhon.device import HonDevice
|
||||
|
||||
from .const import DOMAIN
|
||||
from .hon import HonCoordinator, HonEntity
|
||||
@ -29,20 +27,29 @@ class HonSwitchEntityDescription(HonSwitchEntityDescriptionMixin,
|
||||
SWITCHES: dict[str, tuple[HonSwitchEntityDescription, ...]] = {
|
||||
"WM": (
|
||||
HonSwitchEntityDescription(
|
||||
key="startProgram",
|
||||
name="Start Program",
|
||||
icon="mdi:play",
|
||||
key="active",
|
||||
name="Washing Machine",
|
||||
icon="mdi:washing-machine",
|
||||
turn_on_key="startProgram",
|
||||
turn_off_key="stopProgram",
|
||||
),
|
||||
HonSwitchEntityDescription(
|
||||
key="pause",
|
||||
name="Pause Washing Machine",
|
||||
icon="mdi:pause",
|
||||
turn_on_key="pauseProgram",
|
||||
turn_off_key="resumeProgram",
|
||||
),
|
||||
HonSwitchEntityDescription(
|
||||
key="startProgram.delayStatus",
|
||||
name="Delay Status",
|
||||
icon="mdi:timer-check",
|
||||
entity_category=EntityCategory.CONFIG
|
||||
),
|
||||
HonSwitchEntityDescription(
|
||||
key="startProgram.haier_SoakPrewashSelection",
|
||||
name="Soak Prewash Selection",
|
||||
icon="mdi:tshirt-crew",
|
||||
entity_category=EntityCategory.CONFIG
|
||||
),
|
||||
),
|
||||
@ -61,9 +68,9 @@ async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> Non
|
||||
hass.data[DOMAIN]["coordinators"][device.mac_address] = coordinator
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
if descriptions := SWITCHES.get(device.appliance_type_name):
|
||||
if descriptions := SWITCHES.get(device.appliance_type):
|
||||
for description in descriptions:
|
||||
if device.data.get(description.key) is not None or device.commands.get(description.key) is not None:
|
||||
if device.get(description.key) is not None or device.commands.get(description.key) is not None:
|
||||
appliances.extend([
|
||||
HonSwitchEntity(hass, coordinator, entry, device, description)]
|
||||
)
|
||||
@ -83,7 +90,7 @@ class HonSwitchEntity(HonEntity, SwitchEntity):
|
||||
|
||||
def available(self) -> bool:
|
||||
if self.entity_category == EntityCategory.CONFIG:
|
||||
return self._device.settings[self.entity_description.key].typology == "fixed"
|
||||
return self._device.settings[self.entity_description.key].typology != "fixed"
|
||||
return True
|
||||
|
||||
@property
|
||||
@ -92,7 +99,7 @@ class HonSwitchEntity(HonEntity, SwitchEntity):
|
||||
if self.entity_category == EntityCategory.CONFIG:
|
||||
setting = self._device.settings[self.entity_description.key]
|
||||
return setting.value == "1" or hasattr(setting, "min") and setting.value != setting.min
|
||||
return self._device.data.get(self.entity_description.key, "")
|
||||
return self._device.get(self.entity_description.key, False)
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
if self.entity_category == EntityCategory.CONFIG:
|
322
custom_components/hon/translations/en.json
Normal file
322
custom_components/hon/translations/en.json
Normal file
@ -0,0 +1,322 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"description": "Please enters your hOn credentials",
|
||||
"data": {
|
||||
"email": "Email Address",
|
||||
"password": "Password"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"mode": {
|
||||
"state": {
|
||||
"0": "Disconnected",
|
||||
"1": "Ready",
|
||||
"2": "Running",
|
||||
"3": "Paused",
|
||||
"5": "Scheduled",
|
||||
"6": "Error",
|
||||
"7": "Finished"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"state": {
|
||||
"00": "No error",
|
||||
"100000000000": "E2: Check if the door is closed",
|
||||
"8000000000000": "E4: Check the water supply"
|
||||
}
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"programs": {
|
||||
"state": {
|
||||
"20_degrees_coloured_cottons": "20° Colored and Cottons",
|
||||
"20_degrees_new_energy_label": "20°C",
|
||||
"active_steam": "Steam",
|
||||
"active_wash": "Active Wash",
|
||||
"active_wash_steam": "Active Wash + Steam",
|
||||
"allergy_care": "Allergy Care",
|
||||
"allergy_care_pro": "Allergy Care Pro",
|
||||
"all_in_one_49": "All in One 49'",
|
||||
"all_in_one_59": "All in One 59'",
|
||||
"all_in_one_59_steam": "Active Wash + Steam",
|
||||
"autocare": "Autocare",
|
||||
"autoclean": "Drum Cleaning",
|
||||
"baby_60": "All Baby 60°C",
|
||||
"care_14": "Rapid Care 14'",
|
||||
"care_30": "Rapid Care 30'",
|
||||
"care_44": "Rapid Care 44'",
|
||||
"checkup": "Check-Up",
|
||||
"colour_59": "Colored 59'",
|
||||
"colour_59_steam": "Colored 59' + Steam",
|
||||
"cottons": "Cotton",
|
||||
"cottons_prewash": "Cottons + Prewash",
|
||||
"cottons_steam": "Cotton + Steam",
|
||||
"cotton_care_59": "Cotton Care 59'",
|
||||
"delicate_59": "Delicate 59'",
|
||||
"delicate_silk": "Delicate and Silk",
|
||||
"delicate_silk_steam": "Delicate and Silk + Steam",
|
||||
"delicati_59": "Delicate 59'",
|
||||
"delicati_59_steam": "Delicate 59' + Steam",
|
||||
"drain_spin": "Drain + Spin",
|
||||
"easy_iron": "Easy Iron",
|
||||
"eco_40_60_new_energy_label": "Eco 40-60",
|
||||
"extra_care": "Extra Care",
|
||||
"fitness": "Fitness Care",
|
||||
"fitness_care": "Fitness Care",
|
||||
"fresh_care": "Fresh Care",
|
||||
"fresh_care_steam": "Fresh Care + Steam",
|
||||
"handwash_wool": "Hand Wash + Wool",
|
||||
"high_dry": "High Heat Dry",
|
||||
"hqd_20_degrees": "Cotton 20℃",
|
||||
"hqd_allergy": "Allergy Care",
|
||||
"hqd_autoclean": "Drum Cleaning",
|
||||
"hqd_babycare": "Baby Care",
|
||||
"hqd_checkup": "Check-Up",
|
||||
"hqd_cottons": "Cotton",
|
||||
"hqd_delicate": "Delicate",
|
||||
"hqd_delicate_cradle": "Delicate",
|
||||
"hqd_dry": "Cotton Dry",
|
||||
"hqd_dry_synthetics": "Low Heat Dry",
|
||||
"hqd_duvet": "Duvet",
|
||||
"hqd_eco_40_60_degrees": "Eco 40-60",
|
||||
"hqd_handwash_wool": "Wool",
|
||||
"hqd_i_refresh": "i-Refresh",
|
||||
"hqd_mix": "Mix",
|
||||
"hqd_quick_15": "Quick 15'",
|
||||
"hqd_quick_wash_57": "Quick Wash 57'",
|
||||
"hqd_rapid_wash_and_dry": "Wash and dry",
|
||||
"hqd_refresh": "Refresh",
|
||||
"hqd_rinse": "Rinses",
|
||||
"hqd_shirts": "Shirts",
|
||||
"hqd_smart": "Smart A.I.",
|
||||
"hqd_spin": "Spin",
|
||||
"hqd_sport": "Sport",
|
||||
"hqd_super_fast": "Super Fast 39'",
|
||||
"hqd_synthetic_and_coloured": "Synthetics",
|
||||
"hygiene_59": "Hygiene Plus 59'",
|
||||
"hygiene_60": "Hygiene 60°C",
|
||||
"hygiene_plus_59": "Hygiene Plus 59'",
|
||||
"hygiene_plus_59_min": "Hygiene Plus 59'",
|
||||
"hygiene_pro_4_min": "Hygiene Pro 49'",
|
||||
"hygiene_pro_49_min": "Hygiene Pro 49'",
|
||||
"hygiene_pro_steam": "Hygiene Pro + Steam",
|
||||
"intensive_40": "Intensive 40°C",
|
||||
"intensive_40_steam": "Intensive 40°C + Steam",
|
||||
"iot_checkup": "Check-Up",
|
||||
"iot_dry_air_refresh": "Air Refresh",
|
||||
"iot_dry_anti_mites": "Anti-mite",
|
||||
"iot_dry_baby": "Baby",
|
||||
"iot_dry_backpacks": "Backpacks",
|
||||
"iot_dry_bathrobe": "Bathrobes",
|
||||
"iot_dry_bed_linen": "Bed Linen",
|
||||
"iot_dry_cotton_dry": "Cotton Dry",
|
||||
"iot_dry_cuddly_toys": "Cuddly Toys",
|
||||
"iot_dry_curtains": "Curtains",
|
||||
"iot_dry_dehumidifier": "Humidity Remover",
|
||||
"iot_dry_delicates_antiallergy": "Delicates Anti-allergy",
|
||||
"iot_dry_delicate_tablecloths": "Delicate Tablecloths",
|
||||
"iot_dry_denim_jeans": "Denim - Jeans",
|
||||
"iot_dry_easy_iron_cotton": "Easy Iron - Cotton",
|
||||
"iot_dry_easy_iron_synthetics": "Easy Iron - Synthetics",
|
||||
"iot_dry_gym_fit": "Gym fit - Fitness",
|
||||
"iot_dry_lingerie": "Lingerie",
|
||||
"iot_dry_mixed_dry": "Mixed Dry",
|
||||
"iot_dry_rapid_60_min_delicates": "Rapid 60' - Delicates",
|
||||
"iot_dry_shirts": "Shirts",
|
||||
"iot_dry_swimsuits_and_bikinis": "Swimsuits and Bikinis",
|
||||
"iot_dry_synthetics": "Synthetic Dry",
|
||||
"iot_dry_synthetic_dry": "Synthetic Dry",
|
||||
"iot_dry_tablecloths": "Tablecloths",
|
||||
"iot_dry_technical_fabrics": "Technical Fabrics",
|
||||
"iot_dry_warm_embrace": "Warm Embrace",
|
||||
"iot_dry_wool_dry": "Wool Dry",
|
||||
"iot_wash_and_dry": "Wash and dry",
|
||||
"iot_wash_anti_mites": "Anti-mites",
|
||||
"iot_wash_anti_odor": "Anti-odour",
|
||||
"iot_wash_ariel_clean_cycle": "Ariel Ultimate Clean",
|
||||
"iot_wash_ariel_cold_cycle": "Ariel Cold Clean",
|
||||
"iot_wash_ariel_fresh_cycle": "Ariel Fresh Clean",
|
||||
"iot_wash_baby_sanitizer": "Sanitizer",
|
||||
"iot_wash_baby_sanitizer_steam": "Sanitiser + Steam",
|
||||
"iot_wash_backpacks": "Backpacks",
|
||||
"iot_wash_backpacks_zelig": "Backpacks",
|
||||
"iot_wash_bathrobe": "Bathrobes and Towels",
|
||||
"iot_wash_bathrobe_steam": "Bathrobe and Towels + Steam",
|
||||
"iot_wash_bed_linen": "Bed Linen",
|
||||
"iot_wash_bed_linen_steam": "Bed Linen + Steam",
|
||||
"iot_wash_bed_linen_zelig": "Bed Linens",
|
||||
"iot_wash_big_single_load": "Big single load",
|
||||
"iot_wash_bleaching": "Bleaching",
|
||||
"iot_wash_blood_stains": "Bloodstains",
|
||||
"iot_wash_cashmere": "Cashmere",
|
||||
"iot_wash_chocolate_stains": "Chocolate stains",
|
||||
"iot_wash_cold_wash": "Cold Wash",
|
||||
"iot_wash_colored": "Colored",
|
||||
"iot_wash_colored_anti_stain": "Colored Anti-stain",
|
||||
"iot_wash_colored_delicate": "Colored Delicate",
|
||||
"iot_wash_coloured": "Colored",
|
||||
"iot_wash_coloured_bed_linen": "Colored Bed Linen",
|
||||
"iot_wash_coloured_bed_linen_steam": "Coloured Bed Linen + Steam",
|
||||
"iot_wash_coloured_curtains": "Colored Curtains",
|
||||
"iot_wash_coloured_shirts": "Colored Shirts",
|
||||
"iot_wash_coloured_shirts_steam": "Colored Shirts + Steam",
|
||||
"iot_wash_coloured_steam": "Colored + Steam",
|
||||
"iot_wash_coloured_tableclothes": "Colored Tableclothes",
|
||||
"iot_wash_coloured_tableclothes_steam": "Coloured Tablecloths + Steam",
|
||||
"iot_wash_cotton": "Cotton",
|
||||
"iot_wash_cotton_steam": "Cotton + Steam",
|
||||
"iot_wash_cuddly_toys": "Cuddly Toys",
|
||||
"iot_wash_curtains": "Curtains",
|
||||
"iot_wash_curtains_steam": "Curtains + Steam",
|
||||
"iot_wash_curtains_zelig": "Curtains",
|
||||
"iot_wash_dark": "Darks",
|
||||
"iot_wash_darks_and_coloured_44": "Darks and Colored 44'",
|
||||
"iot_wash_darks_and_coloured_59": "Darks and Colored 59'",
|
||||
"iot_wash_darks_and_coloured_xl": "Darks and Colored XL",
|
||||
"iot_wash_dark_steam": "Darks + Steam",
|
||||
"iot_wash_dash_clean_cycle": "Dash Ultimate Clean",
|
||||
"iot_wash_dash_cold_cycle": "Dash Cold Clean",
|
||||
"iot_wash_dash_fresh_cycle": "Dash Fresh Clean",
|
||||
"iot_wash_delicate": "Delicates",
|
||||
"iot_wash_delicate_antiallergy": "Delicate Anti-Allergy",
|
||||
"iot_wash_delicate_antiallergy_steam": "Delicate Anti-Allergy + Steam",
|
||||
"iot_wash_delicate_antiallergy_zelig": "Delicate Anti-Allergy",
|
||||
"iot_wash_delicate_colors": "Delicate Colors",
|
||||
"iot_wash_delicate_colors_steam": "Delicate Colors + Steam",
|
||||
"iot_wash_delicate_dark": "Delicate Darks",
|
||||
"iot_wash_delicate_steam": "Delicates + Steam",
|
||||
"iot_wash_delicate_tablecloths": "Delicate Tablecloths",
|
||||
"iot_wash_delicate_tablecloths_steam": "Delicate Tablecloths + Steam",
|
||||
"iot_wash_delicate_whites": "Delicate Whites",
|
||||
"iot_wash_denim_jeans": "Denim - Jeans",
|
||||
"iot_wash_diving_suits": "Diving Suits",
|
||||
"iot_wash_diving_suits_zelig": "Diving Suits",
|
||||
"iot_wash_down_jackets": "Down Jackets",
|
||||
"iot_wash_down_jackets_zelig": "Down Jackets",
|
||||
"iot_wash_duvet": "Duvet",
|
||||
"iot_wash_fruit_stains": "Fruit stains",
|
||||
"iot_wash_gym_fit": "Gym Fit - Fitness",
|
||||
"iot_wash_handwash": "Handwash",
|
||||
"iot_wash_handwash_colored": "Handwash Colored",
|
||||
"iot_wash_handwash_dark": "Handwash Darks",
|
||||
"iot_wash_lingerie": "Lingerie",
|
||||
"iot_wash_masks_refresh": "Masks Refresh",
|
||||
"iot_wash_masks_sanification": "Masks Sanitization",
|
||||
"iot_wash_masks_sanification_steam": "Mask Sanitisation + Steam",
|
||||
"iot_wash_mats": "Mats",
|
||||
"iot_wash_men_s_trousers": "Trousers",
|
||||
"iot_wash_mixed": "Mixed",
|
||||
"iot_wash_mixed_steam": "Mixed + Steam",
|
||||
"iot_wash_mix_and_coloured_44": "Mix and Colored 44'",
|
||||
"iot_wash_mix_and_coloured_59": "Mix and Colored 59'",
|
||||
"iot_wash_mix_and_coloured_xl": "Mix and colored XL",
|
||||
"iot_wash_new_clothes": "New Clothes",
|
||||
"iot_wash_perfect_white": "Perfect White",
|
||||
"iot_wash_perfect_white_steam": "Perfect White + Steam",
|
||||
"iot_wash_pets": "Pet Accessories",
|
||||
"iot_wash_pets_hair_removal": "Pets Hair Removal",
|
||||
"iot_wash_pets_odours_stains_removal": "Pets Odours and Stains Removal",
|
||||
"iot_wash_pets_steam": "Pet Accessories + Steam",
|
||||
"iot_wash_playsuits": "Playsuits",
|
||||
"iot_wash_playsuits_steam": "Playsuits + Steam",
|
||||
"iot_wash_quick_drum_cleaner": "Quick drum cleaner",
|
||||
"iot_wash_rapid_14": "Rapid 14’",
|
||||
"iot_wash_rapid_30": "Rapid 30’",
|
||||
"iot_wash_rapid_44": "Rapid 44'",
|
||||
"iot_wash_rapid_59": "Rapid 59'",
|
||||
"iot_wash_rapid_59_steam": "Rapid 59' + Steam",
|
||||
"iot_wash_refresh_14_min": "Refresh 14'",
|
||||
"iot_wash_resistant_colored": "Resistant Colored",
|
||||
"iot_wash_resistant_dark": "Resistant Darks",
|
||||
"iot_wash_resistant_whites": "Resistant Whites",
|
||||
"iot_wash_rinse": "Rinses",
|
||||
"iot_wash_shirts": "Shirts",
|
||||
"iot_wash_shirts_steam": "Shirts + Steam",
|
||||
"iot_wash_silk": "Silk",
|
||||
"iot_wash_ski_suit": "Ski Suit",
|
||||
"iot_wash_ski_suit_zelig": "Ski Suit",
|
||||
"iot_wash_spin": "Spin",
|
||||
"iot_wash_sport": "Sport",
|
||||
"iot_wash_sport_anti_odor": "Anti-odour Sportswear",
|
||||
"iot_wash_sport_anti_odor_zelig": "Anti-odour Sportswear",
|
||||
"iot_wash_stains_remover": "Stain Remover",
|
||||
"iot_wash_swimsuits_and_bikinis": "Swimsuits and Bikinis",
|
||||
"iot_wash_synthetic": "Synthetics",
|
||||
"iot_wash_synthetic_steam": "Synthetics + Steam",
|
||||
"iot_wash_tablecloths": "Tablecloths",
|
||||
"iot_wash_tablecloths_steam": "Tablecloths + Steam",
|
||||
"iot_wash_technical_fabrics": "Technical Fabrics",
|
||||
"iot_wash_technical_fabrics_zelig": "Technical Fabrics",
|
||||
"iot_wash_technical_jackets": "Technical Jackets",
|
||||
"iot_wash_technical_jackets_zelig": "Technical Jackets",
|
||||
"iot_wash_trainers": "Trainers",
|
||||
"iot_wash_whites": "Whites",
|
||||
"iot_wash_whites_44": "Whites 44'",
|
||||
"iot_wash_whites_59": "Whites 59'",
|
||||
"iot_wash_whites_xl": "Whites XL",
|
||||
"iot_wash_wine_stains": "Wine Stains",
|
||||
"iot_wash_wool": "Wool",
|
||||
"jeans": "Jeans",
|
||||
"jeans_60": "Jeans",
|
||||
"low_dry": "Low Heat Dry",
|
||||
"mixed": "Mixed",
|
||||
"mixed_and_colored_59": "Mixed and Colored 59'",
|
||||
"mixed_steam": "Mixed + Steam",
|
||||
"mix_and_colour_59": "Mixed and Colored 59'",
|
||||
"mix_and_colour_59_steam": "Mixed and Coloured 59' + Steam",
|
||||
"night_and_day": "Night and Day",
|
||||
"night_wash": "Night Wash",
|
||||
"perfect_59": "Perfect 59'",
|
||||
"perfect_cotton_59": "Perfect Cotton 59'",
|
||||
"perfect_cotton_59_steam": "Perfect Cotton 59' + Steam",
|
||||
"perfect_whites_59": "Perfect White 59'",
|
||||
"rapid_14_min": "Rapid 14'",
|
||||
"rapid_30_min": "Rapid 30'",
|
||||
"rapid_44_min": "Rapid 44'",
|
||||
"rapid_a_class_60": "Rapid 59' A Class",
|
||||
"rapid_a_class_60_steam": "Rapid 59' A Class + Steam",
|
||||
"rapid_wash_and_dry_59_min": "Wash and Dry 59'",
|
||||
"resistant_cotton": "Resistant Cotton",
|
||||
"resistant_cotton_steam": "Resistant Cotton + Steam",
|
||||
"rinse": "Rinse",
|
||||
"shirts_steam": "Shirts + Steam",
|
||||
"silent_night": "Silent Night",
|
||||
"single_item": "Single Item",
|
||||
"single_item_steam": "Single Item + Steam",
|
||||
"smart_wash": "Smart Wash",
|
||||
"soft_care": "Soft Care",
|
||||
"soft_care_steam_title": "Soft Care + Steam",
|
||||
"special_39": "Special 39'",
|
||||
"special_39_full_load": "Special 39'",
|
||||
"special_39_full_load_steam": "Special 39' + Steam",
|
||||
"special_49": "Special 49'",
|
||||
"sport_39": "Sport 39'",
|
||||
"sport_plus_29": "Sport Plus 29'",
|
||||
"sport_plus_39": "Sport Plus 39'",
|
||||
"steam_39": "Steam 39'",
|
||||
"steam_care_pro": "Steam Care Pro",
|
||||
"steam_care_pro_cotton": "Steam Care Pro - Cottons",
|
||||
"steam_care_pro_delicates": "Steam Care Pro - Delicates",
|
||||
"steam_care_pro_synthetic": "Steam Care Pro - Synthetics",
|
||||
"steam_hygiene_plus": "Hygiene Plus + Steam",
|
||||
"synthetics": "Synthetics",
|
||||
"synthetic_and_coloured": "Synthetic and Colored",
|
||||
"synthetic_and_coloured_steam": "Synthetic and Coloured + Steam",
|
||||
"tailored_resistant_cotton": "Tailored Resistant Cotton",
|
||||
"tailored_synthetic_and_coloured": "Tailored Synthetic Colored",
|
||||
"total_care": "Total Care",
|
||||
"tumbling": "Tumbling",
|
||||
"wool": "Wool",
|
||||
"wool_and_delicates_49": "Wool and Delicates 49'",
|
||||
"wool_dry": "Wool Dry",
|
||||
"wool_soft_care": "Wool and Soft Car"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user