Skip to content

Commit

Permalink
feat: add Humidifier platform support (#170)
Browse files Browse the repository at this point in the history
feat: Add support for humidifier platform

* Support for target humidity / aka auto regulated humidity

* Add support for humidifier platform

* Address feedback

* Revert manifest.json change

* Add not implemented abstract methods for consistency

* Fix missing localisation

* change  target_humidity / auto_regulated_humidity naming

* chore: remove should poll as it is already provided by BaseCoordinatorEntity

* fix: int_cast aware of None and NotImplemented (#173)

This change intends to fix #169.

* chore: bumping version to 1.17.10

* linting
address feedback
move static properties to init

* Revert "chore: remove should poll as it is already provided by BaseCoordinatorEntity"

This reverts commit ed54237.

* Change 'normal mode' to 'fan speed mode'

* Remove wonky Dry Wick mode

---------

Co-authored-by: zim514 <krisyoung@gmail.com>
Co-authored-by: Brendan Dahl <dahl.brendan@gmail.com>
Co-authored-by: Yu Feng <rainwoodman@gmail.com>
Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
5 people authored Dec 21, 2024
1 parent d920ed5 commit 866baf1
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 1 deletion.
9 changes: 9 additions & 0 deletions custom_components/ha_blueair/blueair_update_coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ def filter_expired(self) -> bool | None:
"""Return the current filter status."""
pass

@property
@abstractmethod
def auto_regulated_humidity(self) -> bool | None | NotImplemented:
pass

async def set_fan_speed(self, new_speed) -> None:
await self.blueair_api_device.set_fan_speed(new_speed)
await self.async_request_refresh()
Expand Down Expand Up @@ -177,3 +182,7 @@ async def set_fan_auto_mode(self, value) -> None:
@abstractmethod
async def set_wick_dry_mode(self, value) -> None:
pass

@abstractmethod
async def set_auto_regulated_humidity(self, value) -> None:
pass
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ def wick_dry_mode(self) -> bool | None | NotImplemented:
def water_shortage(self) -> bool | None | NotImplemented:
return NotImplemented

@property
def auto_regulated_humidity(self) -> bool | None | NotImplemented:
return NotImplemented

async def set_brightness(self, brightness) -> None:
# Convert Home Assistant brightness (0-255) to brightness (0-4)
await self.blueair_api_device.set_brightness(round(brightness * 4 / 255.0))
Expand All @@ -117,3 +121,6 @@ async def set_fan_auto_mode(self, value) -> None:

async def set_wick_dry_mode(self, value) -> None:
raise NotImplementedError

async def set_auto_regulated_humidity(self, value) -> None:
raise NotImplementedError
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ def temperature(self) -> int | None | NotImplemented:
def humidity(self) -> int | None | NotImplemented:
return self.blueair_api_device.humidity

@property
def auto_regulated_humidity(self) -> int | None | NotImplemented:
return self.blueair_api_device.auto_regulated_humidity

@property
def voc(self) -> int | None | NotImplemented:
return self.blueair_api_device.tVOC
Expand Down Expand Up @@ -135,3 +139,7 @@ async def set_fan_auto_mode(self, value) -> None:
async def set_wick_dry_mode(self, value) -> None:
await self.blueair_api_device.set_wick_dry_mode(value)
await self.async_request_refresh()

async def set_auto_regulated_humidity(self, value) -> None:
await self.blueair_api_device.set_auto_regulated_humidity(value)
await self.async_request_refresh()
5 changes: 4 additions & 1 deletion custom_components/ha_blueair/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

# Integration Setting Constants
CONFIG_FLOW_VERSION: int = 2
PLATFORMS = ["binary_sensor", "fan", "sensor", "light", "switch"]
PLATFORMS = ["binary_sensor", "fan", "humidifier", "light", "sensor", "switch"]

# Home Assistant Data Storage Constants
DATA_DEVICES: str = "api_devices"
Expand All @@ -15,3 +15,6 @@

DEFAULT_FAN_SPEED_PERCENTAGE = 50
FILTER_EXPIRED_THRESHOLD = 95

# Custom Mode Constants
MODE_FAN_SPEED = "fan_speed"
122 changes: 122 additions & 0 deletions custom_components/ha_blueair/humidifier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
"""Support for Blueair humidifiers."""

from __future__ import annotations

import logging

from homeassistant.components.humidifier import (
MODE_AUTO,
MODE_SLEEP,
HumidifierDeviceClass,
HumidifierEntity,
HumidifierEntityFeature,
)

from .blueair_update_coordinator_device_aws import BlueairUpdateCoordinator
from .const import MODE_FAN_SPEED
from .entity import BlueairEntity, async_setup_entry_helper

_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the Blueair humidifier from config entry"""

async_setup_entry_helper(
hass,
config_entry,
async_add_entities,
entity_classes=[
BlueairAwsHumidifier,
],
)


class BlueairAwsHumidifier(BlueairEntity, HumidifierEntity):
"""Controls Humidifier."""

@classmethod
def is_implemented(kls, coordinator):
return coordinator.auto_regulated_humidity is not NotImplemented

def __init__(self, coordinator: BlueairUpdateCoordinator):
"""Initialize the humidifer."""
self._attr_device_class = HumidifierDeviceClass.HUMIDIFIER
self._attr_supported_features = HumidifierEntityFeature.MODES
self._attr_translation_key = "ha_blueair"
self._attr_available_modes = [
MODE_AUTO,
MODE_SLEEP,
MODE_FAN_SPEED,
]
super().__init__("Humidifier", coordinator)

@property
def available(self) -> bool:
"""Return if entity is available."""
return self.coordinator.last_update_success and self.coordinator.online

@property
def mode(self):
if self.coordinator.night_mode:
return MODE_SLEEP
elif self.coordinator.fan_auto_mode:
return MODE_AUTO
elif self.is_on:
return MODE_FAN_SPEED
else:
return

@property
def is_on(self) -> int:
return self.coordinator.is_on

@property
def target_humidity(self):
return self.coordinator.auto_regulated_humidity

@property
def current_humidity(self):
return self.coordinator.humidity

async def async_turn_off(self, **kwargs: any) -> None:
await self.coordinator.set_running(False)
self.async_write_ha_state()

async def async_turn_on(
self,
percentage: int | None = None,
preset_mode: str | None = None,
**kwargs: any,
) -> None:
await self.coordinator.set_running(True)
self.async_write_ha_state()

async def async_set_mode(self, mode):
if mode == MODE_AUTO:
# This mode doesn't apply when off
await self.coordinator.set_fan_auto_mode(True)
await self.coordinator.set_running(True)
self.async_write_ha_state()
elif mode == MODE_SLEEP:
# This mode doesn't apply when off
await self.coordinator.set_night_mode(True)
await self.coordinator.set_fan_auto_mode(False)
await self.coordinator.set_running(False)
self.async_write_ha_state()
elif mode == MODE_FAN_SPEED:
# This mode doesn't apply when off
await self.coordinator.set_fan_auto_mode(False)
await self.coordinator.set_night_mode(False)
await self.coordinator.set_running(True)

self.async_write_ha_state()
else:
raise ValueError(f"Invalid mode: {mode}")

async def async_set_humidity(self, humidity):
"""Set the humidity level. Sets Humidifier to 'On' to comply with hass requirements, and sets mode to Auto since this is the only mode in which the target humidity is used."""

await self.coordinator.set_auto_regulated_humidity(humidity)
await self.coordinator.set_fan_auto_mode(True)
await self.async_turn_on()
13 changes: 13 additions & 0 deletions custom_components/ha_blueair/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,18 @@
"error": {
"auth": "Login failed. Please use official app to logout and log back in and try again."
}
},
"entity": {
"humidifier": {
"ha_blueair": {
"state_attributes": {
"mode": {
"state": {
"fan_speed": "Fan Speed"
}
}
}
}
}
}
}
13 changes: 13 additions & 0 deletions custom_components/ha_blueair/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,18 @@
"error": {
"auth": "Login failed. Please use official app to logout and log back in and try again."
}
},
"entity": {
"humidifier": {
"ha_blueair": {
"state_attributes": {
"mode": {
"state": {
"fan_speed": "Fan Speed"
}
}
}
}
}
}
}

0 comments on commit 866baf1

Please sign in to comment.