From 136a1810fc551c18b2fddd840130b11d57f2e756 Mon Sep 17 00:00:00 2001 From: Andre Basche Date: Fri, 3 Mar 2023 18:23:30 +0100 Subject: [PATCH] More functions --- .gitignore | 1 + custom_components/{hon => hOn}/__init__.py | 16 +---- custom_components/hOn/button.py | 67 +++++++++++++++++++ custom_components/{hon => hOn}/config_flow.py | 1 + custom_components/{hon => hOn}/const.py | 3 +- custom_components/{hon => hOn}/hon.py | 20 +++++- custom_components/{hon => hOn}/manifest.json | 4 +- custom_components/{hon => hOn}/number.py | 36 +++++----- custom_components/{hon => hOn}/select.py | 17 +++-- custom_components/{hon => hOn}/sensor.py | 20 ++++-- .../{hon => hOn}/translations/en.json | 0 hacs.json | 1 - 12 files changed, 140 insertions(+), 46 deletions(-) rename custom_components/{hon => hOn}/__init__.py (66%) create mode 100644 custom_components/hOn/button.py rename custom_components/{hon => hOn}/config_flow.py (99%) rename custom_components/{hon => hOn}/const.py (68%) rename custom_components/{hon => hOn}/hon.py (64%) rename custom_components/{hon => hOn}/manifest.json (50%) rename custom_components/{hon => hOn}/number.py (80%) rename custom_components/{hon => hOn}/select.py (88%) rename custom_components/{hon => hOn}/sensor.py (79%) rename custom_components/{hon => hOn}/translations/en.json (100%) diff --git a/.gitignore b/.gitignore index e1f7009..6024b17 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ __pycache__/ test.py +.idea/ diff --git a/custom_components/hon/__init__.py b/custom_components/hOn/__init__.py similarity index 66% rename from custom_components/hon/__init__.py rename to custom_components/hOn/__init__.py index 66c60b7..7d0800e 100644 --- a/custom_components/hon/__init__.py +++ b/custom_components/hOn/__init__.py @@ -1,16 +1,14 @@ import logging -from datetime import timedelta import voluptuous as vol from pyhon import HonConnection -from pyhon.device import HonDevice from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_EMAIL, CONF_PASSWORD from homeassistant.helpers import config_validation as cv, aiohttp_client 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__) @@ -40,13 +38,3 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): hass.async_create_task( 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() diff --git a/custom_components/hOn/button.py b/custom_components/hOn/button.py new file mode 100644 index 0000000..410d6ab --- /dev/null +++ b/custom_components/hOn/button.py @@ -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() diff --git a/custom_components/hon/config_flow.py b/custom_components/hOn/config_flow.py similarity index 99% rename from custom_components/hon/config_flow.py rename to custom_components/hOn/config_flow.py index 1a286c8..ea30fbc 100755 --- a/custom_components/hon/config_flow.py +++ b/custom_components/hOn/config_flow.py @@ -4,6 +4,7 @@ import voluptuous as vol from homeassistant import config_entries from homeassistant.const import CONF_EMAIL, CONF_PASSWORD + from .const import DOMAIN _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/hon/const.py b/custom_components/hOn/const.py similarity index 68% rename from custom_components/hon/const.py rename to custom_components/hOn/const.py index 09d08f6..f6fdb4d 100755 --- a/custom_components/hon/const.py +++ b/custom_components/hOn/const.py @@ -3,5 +3,6 @@ DOMAIN = "hon" PLATFORMS = [ "sensor", "select", - "number" + "number", + "button" ] diff --git a/custom_components/hon/hon.py b/custom_components/hOn/hon.py similarity index 64% rename from custom_components/hon/hon.py rename to custom_components/hOn/hon.py index 91b83ea..3c2b548 100755 --- a/custom_components/hon/hon.py +++ b/custom_components/hOn/hon.py @@ -1,8 +1,15 @@ +import logging +from datetime import timedelta + from pyhon.device import HonDevice -from .const import DOMAIN from homeassistant.helpers.entity import DeviceInfo 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): @@ -19,7 +26,6 @@ class HonEntity(CoordinatorEntity): @property def device_info(self): - """Return a device description for device registry.""" return DeviceInfo( identifiers={(DOMAIN, self._device.mac_address)}, manufacturer=self._device.brand, @@ -27,3 +33,13 @@ class HonEntity(CoordinatorEntity): model=self._device.model_name, 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() diff --git a/custom_components/hon/manifest.json b/custom_components/hOn/manifest.json similarity index 50% rename from custom_components/hon/manifest.json rename to custom_components/hOn/manifest.json index 11e4887..d01bfc4 100755 --- a/custom_components/hon/manifest.json +++ b/custom_components/hOn/manifest.json @@ -4,5 +4,7 @@ "config_flow": true, "version": "0.0.1", "codeowners": ["@Andre0512"], - "iot_class": "cloud_polling" + "iot_class": "cloud_polling", + "requirements": ["pyhon"], + "documentation": "https://github.com/Andre0512/hOn/" } diff --git a/custom_components/hon/number.py b/custom_components/hOn/number.py similarity index 80% rename from custom_components/hon/number.py rename to custom_components/hOn/number.py index 8172bea..c206a26 100644 --- a/custom_components/hon/number.py +++ b/custom_components/hOn/number.py @@ -8,39 +8,43 @@ from homeassistant.components.number import ( NumberEntityDescription, ) from homeassistant.config_entries import ConfigEntry +from homeassistant.const import UnitOfTime from homeassistant.core import callback 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, ...]] = { "WM": ( NumberEntityDescription( - key="delayStatus", - name="delayStatus", + key="startProgram.delayStatus", + name="Delay Status", entity_category=EntityCategory.CONFIG ), NumberEntityDescription( - key="delayTime", - name="delayTime", + key="startProgram.delayTime", + name="Delay Time", 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 ), NumberEntityDescription( - key="haier_SoakPrewashSelection", - name="haier_SoakPrewashSelection", + key="startProgram.rinseIterations", + name="Rinse Iterations", entity_category=EntityCategory.CONFIG ), NumberEntityDescription( - key="rinseIterations", - name="rinseIterations", - entity_category=EntityCategory.CONFIG - ), - NumberEntityDescription( - key="mainWashTime", - name="mainWashTime", + key="startProgram.mainWashTime", + name="Main Wash Time", icon="mdi:timer", - entity_category=EntityCategory.CONFIG + entity_category=EntityCategory.CONFIG, + native_unit_of_measurement=UnitOfTime.MINUTES ), ), } diff --git a/custom_components/hon/select.py b/custom_components/hOn/select.py similarity index 88% rename from custom_components/hon/select.py rename to custom_components/hOn/select.py index abf54c2..6ba29e8 100644 --- a/custom_components/hon/select.py +++ b/custom_components/hOn/select.py @@ -5,31 +5,34 @@ from pyhon import HonConnection from pyhon.device import HonDevice 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.config_entries import ConfigEntry +from homeassistant.const import UnitOfTemperature, REVOLUTIONS_PER_MINUTE from homeassistant.core import callback from homeassistant.helpers.entity import EntityCategory +from .hon import HonEntity, HonCoordinator + DOMAIN = "hon" SELECTS = { "WM": ( SelectEntityDescription( - key="spinSpeed", + key="startProgram.spinSpeed", name="Spin speed", entity_category=EntityCategory.CONFIG, - icon="mdi:numeric" + icon="mdi:numeric", + unit_of_measurement=REVOLUTIONS_PER_MINUTE ), SelectEntityDescription( - key="temp", + key="startProgram.temp", name="Temperature", entity_category=EntityCategory.CONFIG, - icon="mdi:thermometer" + icon="mdi:thermometer", + unit_of_measurement=UnitOfTemperature.CELSIUS ), SelectEntityDescription( - key="program", + key="startProgram.program", name="Programme", entity_category=EntityCategory.CONFIG ), diff --git a/custom_components/hon/sensor.py b/custom_components/hOn/sensor.py similarity index 79% rename from custom_components/hon/sensor.py rename to custom_components/hOn/sensor.py index cc6224a..6e21f5e 100644 --- a/custom_components/hon/sensor.py +++ b/custom_components/hOn/sensor.py @@ -9,11 +9,13 @@ from homeassistant.components.sensor import ( SensorEntityDescription, ) from homeassistant.config_entries import ConfigEntry +from homeassistant.const import UnitOfEnergy, UnitOfVolume, UnitOfMass from homeassistant.core import callback +from homeassistant.helpers.entity import EntityCategory from homeassistant.helpers.typing import StateType -from custom_components import HonCoordinator + from .const import DOMAIN -from custom_components.hon import HonEntity +from .hon import HonCoordinator, HonEntity _LOGGER = logging.getLogger(__name__) @@ -24,12 +26,14 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { name="Total Power", device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, + native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR ), SensorEntityDescription( key="totalWaterUsed", name="Total Water", device_class=SensorDeviceClass.WATER, state_class=SensorStateClass.TOTAL_INCREASING, + native_unit_of_measurement=UnitOfVolume.LITERS ), SensorEntityDescription( key="totalWashCycle", @@ -49,6 +53,14 @@ SENSORS: dict[str, tuple[SensorEntityDescription, ...]] = { state_class=SensorStateClass.MEASUREMENT, 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 def native_value(self) -> StateType: - return self._device.attributes.get(self.entity_description.key, "") + return self._device.data.get(self.entity_description.key, "") @callback 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() diff --git a/custom_components/hon/translations/en.json b/custom_components/hOn/translations/en.json similarity index 100% rename from custom_components/hon/translations/en.json rename to custom_components/hOn/translations/en.json diff --git a/hacs.json b/hacs.json index 458c86d..2cf5be6 100644 --- a/hacs.json +++ b/hacs.json @@ -1,6 +1,5 @@ { "name": "Haier hOn", - "content_in_root": true, "render_readme": false, "homeassistant": "2023.2.0" } \ No newline at end of file