More functions
This commit is contained in:
parent
31c30b1670
commit
136a1810fc
12 changed files with 140 additions and 46 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
__pycache__/
|
__pycache__/
|
||||||
test.py
|
test.py
|
||||||
|
.idea/
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
import logging
|
import logging
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from pyhon import HonConnection
|
from pyhon import HonConnection
|
||||||
from pyhon.device import HonDevice
|
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
|
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
|
||||||
from homeassistant.helpers import config_validation as cv, aiohttp_client
|
from homeassistant.helpers import config_validation as cv, aiohttp_client
|
||||||
from homeassistant.helpers.typing import HomeAssistantType
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
|
||||||
from custom_components.hon.const import DOMAIN, PLATFORMS
|
from .const import DOMAIN, PLATFORMS
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -40,13 +38,3 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry):
|
||||||
hass.async_create_task(
|
hass.async_create_task(
|
||||||
hass.config_entries.async_forward_entry_setup(entry, platform)
|
hass.config_entries.async_forward_entry_setup(entry, platform)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class HonCoordinator(DataUpdateCoordinator):
|
|
||||||
def __init__(self, hass, device: HonDevice):
|
|
||||||
"""Initialize my coordinator."""
|
|
||||||
super().__init__(hass, _LOGGER, name=device.mac_address, update_interval=timedelta(seconds=30))
|
|
||||||
self._device = device
|
|
||||||
|
|
||||||
async def _async_update_data(self):
|
|
||||||
await self._device.load_attributes()
|
|
67
custom_components/hOn/button.py
Normal file
67
custom_components/hOn/button.py
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
from pyhon import HonConnection
|
||||||
|
from pyhon.device import HonDevice
|
||||||
|
|
||||||
|
from homeassistant.components.button import ButtonEntityDescription, ButtonEntity
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
from .hon import HonCoordinator, HonEntity
|
||||||
|
|
||||||
|
BUTTONS: dict[str, tuple[ButtonEntityDescription, ...]] = {
|
||||||
|
"WM": (
|
||||||
|
ButtonEntityDescription(
|
||||||
|
key="startProgram",
|
||||||
|
name="Start Program",
|
||||||
|
icon="mdi:play",
|
||||||
|
),
|
||||||
|
ButtonEntityDescription(
|
||||||
|
key="stopProgram",
|
||||||
|
name="Stop Program",
|
||||||
|
icon="mdi:stop",
|
||||||
|
),
|
||||||
|
ButtonEntityDescription(
|
||||||
|
key="pauseProgram",
|
||||||
|
name="Pause Program",
|
||||||
|
icon="mdi:pause",
|
||||||
|
),
|
||||||
|
ButtonEntityDescription(
|
||||||
|
key="resumeProgram",
|
||||||
|
name="Resume Program",
|
||||||
|
icon="mdi:play-pause",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(hass, entry: ConfigEntry, async_add_entities) -> None:
|
||||||
|
hon: HonConnection = hass.data[DOMAIN][entry.unique_id]
|
||||||
|
coordinators = hass.data[DOMAIN]["coordinators"]
|
||||||
|
appliances = []
|
||||||
|
for device in hon.devices:
|
||||||
|
if device.mac_address in coordinators:
|
||||||
|
coordinator = hass.data[DOMAIN]["coordinators"][device.mac_address]
|
||||||
|
else:
|
||||||
|
coordinator = HonCoordinator(hass, device)
|
||||||
|
hass.data[DOMAIN]["coordinators"][device.mac_address] = coordinator
|
||||||
|
await coordinator.async_config_entry_first_refresh()
|
||||||
|
|
||||||
|
if descriptions := BUTTONS.get(device.appliance_type_name):
|
||||||
|
for description in descriptions:
|
||||||
|
appliances.extend([
|
||||||
|
HonButtonEntity(hass, coordinator, entry, device, description)]
|
||||||
|
)
|
||||||
|
|
||||||
|
async_add_entities(appliances)
|
||||||
|
|
||||||
|
|
||||||
|
class HonButtonEntity(HonEntity, ButtonEntity):
|
||||||
|
def __init__(self, hass, coordinator, entry, device: HonDevice, description) -> None:
|
||||||
|
super().__init__(hass, entry, coordinator, device)
|
||||||
|
|
||||||
|
self._coordinator = coordinator
|
||||||
|
self._device = device
|
||||||
|
self.entity_description = description
|
||||||
|
self._attr_unique_id = f"{super().unique_id}{description.key}"
|
||||||
|
|
||||||
|
async def async_press(self) -> None:
|
||||||
|
await self._device.commands[self.entity_description.key].send()
|
|
@ -4,6 +4,7 @@ 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__)
|
|
@ -3,5 +3,6 @@ DOMAIN = "hon"
|
||||||
PLATFORMS = [
|
PLATFORMS = [
|
||||||
"sensor",
|
"sensor",
|
||||||
"select",
|
"select",
|
||||||
"number"
|
"number",
|
||||||
|
"button"
|
||||||
]
|
]
|
|
@ -1,8 +1,15 @@
|
||||||
|
import logging
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
from pyhon.device import HonDevice
|
from pyhon.device import HonDevice
|
||||||
|
|
||||||
from .const import DOMAIN
|
|
||||||
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 .const import DOMAIN
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class HonEntity(CoordinatorEntity):
|
class HonEntity(CoordinatorEntity):
|
||||||
|
@ -19,7 +26,6 @@ class HonEntity(CoordinatorEntity):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self):
|
def device_info(self):
|
||||||
"""Return a device description for device registry."""
|
|
||||||
return DeviceInfo(
|
return DeviceInfo(
|
||||||
identifiers={(DOMAIN, self._device.mac_address)},
|
identifiers={(DOMAIN, self._device.mac_address)},
|
||||||
manufacturer=self._device.brand,
|
manufacturer=self._device.brand,
|
||||||
|
@ -27,3 +33,13 @@ class HonEntity(CoordinatorEntity):
|
||||||
model=self._device.model_name,
|
model=self._device.model_name,
|
||||||
sw_version=self._device.fw_version,
|
sw_version=self._device.fw_version,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class HonCoordinator(DataUpdateCoordinator):
|
||||||
|
def __init__(self, hass, device: HonDevice):
|
||||||
|
"""Initialize my coordinator."""
|
||||||
|
super().__init__(hass, _LOGGER, name=device.mac_address, update_interval=timedelta(seconds=30))
|
||||||
|
self._device = device
|
||||||
|
|
||||||
|
async def _async_update_data(self):
|
||||||
|
await self._device.update()
|
|
@ -4,5 +4,7 @@
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"codeowners": ["@Andre0512"],
|
"codeowners": ["@Andre0512"],
|
||||||
"iot_class": "cloud_polling"
|
"iot_class": "cloud_polling",
|
||||||
|
"requirements": ["pyhon"],
|
||||||
|
"documentation": "https://github.com/Andre0512/hOn/"
|
||||||
}
|
}
|
|
@ -8,39 +8,43 @@ from homeassistant.components.number import (
|
||||||
NumberEntityDescription,
|
NumberEntityDescription,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import UnitOfTime
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers.entity import EntityCategory
|
from homeassistant.helpers.entity import EntityCategory
|
||||||
from custom_components import DOMAIN, HonCoordinator
|
|
||||||
from custom_components.hon import HonEntity
|
from .const import DOMAIN
|
||||||
|
from .hon import HonEntity, HonCoordinator
|
||||||
|
|
||||||
NUMBERS: dict[str, tuple[NumberEntityDescription, ...]] = {
|
NUMBERS: dict[str, tuple[NumberEntityDescription, ...]] = {
|
||||||
"WM": (
|
"WM": (
|
||||||
NumberEntityDescription(
|
NumberEntityDescription(
|
||||||
key="delayStatus",
|
key="startProgram.delayStatus",
|
||||||
name="delayStatus",
|
name="Delay Status",
|
||||||
entity_category=EntityCategory.CONFIG
|
entity_category=EntityCategory.CONFIG
|
||||||
),
|
),
|
||||||
NumberEntityDescription(
|
NumberEntityDescription(
|
||||||
key="delayTime",
|
key="startProgram.delayTime",
|
||||||
name="delayTime",
|
name="Delay Time",
|
||||||
icon="mdi:timer",
|
icon="mdi:timer",
|
||||||
|
entity_category=EntityCategory.CONFIG,
|
||||||
|
native_unit_of_measurement=UnitOfTime.MINUTES
|
||||||
|
),
|
||||||
|
NumberEntityDescription(
|
||||||
|
key="startProgram.haier_SoakPrewashSelection",
|
||||||
|
name="Soak Prewash Selection",
|
||||||
entity_category=EntityCategory.CONFIG
|
entity_category=EntityCategory.CONFIG
|
||||||
),
|
),
|
||||||
NumberEntityDescription(
|
NumberEntityDescription(
|
||||||
key="haier_SoakPrewashSelection",
|
key="startProgram.rinseIterations",
|
||||||
name="haier_SoakPrewashSelection",
|
name="Rinse Iterations",
|
||||||
entity_category=EntityCategory.CONFIG
|
entity_category=EntityCategory.CONFIG
|
||||||
),
|
),
|
||||||
NumberEntityDescription(
|
NumberEntityDescription(
|
||||||
key="rinseIterations",
|
key="startProgram.mainWashTime",
|
||||||
name="rinseIterations",
|
name="Main Wash Time",
|
||||||
entity_category=EntityCategory.CONFIG
|
|
||||||
),
|
|
||||||
NumberEntityDescription(
|
|
||||||
key="mainWashTime",
|
|
||||||
name="mainWashTime",
|
|
||||||
icon="mdi:timer",
|
icon="mdi:timer",
|
||||||
entity_category=EntityCategory.CONFIG
|
entity_category=EntityCategory.CONFIG,
|
||||||
|
native_unit_of_measurement=UnitOfTime.MINUTES
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
|
@ -5,31 +5,34 @@ from pyhon import HonConnection
|
||||||
from pyhon.device import HonDevice
|
from pyhon.device import HonDevice
|
||||||
from pyhon.parameter import HonParameterFixed
|
from pyhon.parameter import HonParameterFixed
|
||||||
|
|
||||||
from config.custom_components.hon import HonCoordinator
|
|
||||||
from config.custom_components.hon.hon import HonEntity
|
|
||||||
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import UnitOfTemperature, REVOLUTIONS_PER_MINUTE
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers.entity import EntityCategory
|
from homeassistant.helpers.entity import EntityCategory
|
||||||
|
|
||||||
|
from .hon import HonEntity, HonCoordinator
|
||||||
|
|
||||||
DOMAIN = "hon"
|
DOMAIN = "hon"
|
||||||
|
|
||||||
SELECTS = {
|
SELECTS = {
|
||||||
"WM": (
|
"WM": (
|
||||||
SelectEntityDescription(
|
SelectEntityDescription(
|
||||||
key="spinSpeed",
|
key="startProgram.spinSpeed",
|
||||||
name="Spin speed",
|
name="Spin speed",
|
||||||
entity_category=EntityCategory.CONFIG,
|
entity_category=EntityCategory.CONFIG,
|
||||||
icon="mdi:numeric"
|
icon="mdi:numeric",
|
||||||
|
unit_of_measurement=REVOLUTIONS_PER_MINUTE
|
||||||
),
|
),
|
||||||
SelectEntityDescription(
|
SelectEntityDescription(
|
||||||
key="temp",
|
key="startProgram.temp",
|
||||||
name="Temperature",
|
name="Temperature",
|
||||||
entity_category=EntityCategory.CONFIG,
|
entity_category=EntityCategory.CONFIG,
|
||||||
icon="mdi:thermometer"
|
icon="mdi:thermometer",
|
||||||
|
unit_of_measurement=UnitOfTemperature.CELSIUS
|
||||||
),
|
),
|
||||||
SelectEntityDescription(
|
SelectEntityDescription(
|
||||||
key="program",
|
key="startProgram.program",
|
||||||
name="Programme",
|
name="Programme",
|
||||||
entity_category=EntityCategory.CONFIG
|
entity_category=EntityCategory.CONFIG
|
||||||
),
|
),
|
|
@ -9,11 +9,13 @@ from homeassistant.components.sensor import (
|
||||||
SensorEntityDescription,
|
SensorEntityDescription,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import UnitOfEnergy, UnitOfVolume, UnitOfMass
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
|
from homeassistant.helpers.entity import EntityCategory
|
||||||
from homeassistant.helpers.typing import StateType
|
from homeassistant.helpers.typing import StateType
|
||||||
from custom_components import HonCoordinator
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
from custom_components.hon import HonEntity
|
from .hon import HonCoordinator, HonEntity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -24,12 +26,14 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = {
|
||||||
name="Total Power",
|
name="Total Power",
|
||||||
device_class=SensorDeviceClass.ENERGY,
|
device_class=SensorDeviceClass.ENERGY,
|
||||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
|
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key="totalWaterUsed",
|
key="totalWaterUsed",
|
||||||
name="Total Water",
|
name="Total Water",
|
||||||
device_class=SensorDeviceClass.WATER,
|
device_class=SensorDeviceClass.WATER,
|
||||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
|
native_unit_of_measurement=UnitOfVolume.LITERS
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key="totalWashCycle",
|
key="totalWashCycle",
|
||||||
|
@ -49,6 +53,14 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = {
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
icon="mdi:water"
|
icon="mdi:water"
|
||||||
),
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="startProgram.weight",
|
||||||
|
name="Weight",
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
|
entity_category=EntityCategory.CONFIG,
|
||||||
|
native_unit_of_measurement=UnitOfMass.KILOGRAMS,
|
||||||
|
icon="mdi:weight-kilogram"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,9 +97,9 @@ class HonSensorEntity(HonEntity, SensorEntity):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def native_value(self) -> StateType:
|
def native_value(self) -> StateType:
|
||||||
return self._device.attributes.get(self.entity_description.key, "")
|
return self._device.data.get(self.entity_description.key, "")
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _handle_coordinator_update(self):
|
def _handle_coordinator_update(self):
|
||||||
self._attr_native_value = self._device.attributes.get(self.entity_description.key, "")
|
self._attr_native_value = self._device.data.get(self.entity_description.key, "")
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
|
@ -1,6 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "Haier hOn",
|
"name": "Haier hOn",
|
||||||
"content_in_root": true,
|
|
||||||
"render_readme": false,
|
"render_readme": false,
|
||||||
"homeassistant": "2023.2.0"
|
"homeassistant": "2023.2.0"
|
||||||
}
|
}
|
Loading…
Reference in a new issue