mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Add support for air purifiers to HomeKit Device (#109880)
This commit is contained in:
parent
aea81a180c
commit
1ea9b1a158
@ -55,6 +55,7 @@ HOMEKIT_ACCESSORY_DISPATCH = {
|
|||||||
ServicesTypes.DOORBELL: "event",
|
ServicesTypes.DOORBELL: "event",
|
||||||
ServicesTypes.STATELESS_PROGRAMMABLE_SWITCH: "event",
|
ServicesTypes.STATELESS_PROGRAMMABLE_SWITCH: "event",
|
||||||
ServicesTypes.SERVICE_LABEL: "event",
|
ServicesTypes.SERVICE_LABEL: "event",
|
||||||
|
ServicesTypes.AIR_PURIFIER: "fan",
|
||||||
}
|
}
|
||||||
|
|
||||||
CHARACTERISTIC_PLATFORMS = {
|
CHARACTERISTIC_PLATFORMS = {
|
||||||
@ -104,6 +105,8 @@ CHARACTERISTIC_PLATFORMS = {
|
|||||||
CharacteristicsTypes.FILTER_LIFE_LEVEL: "sensor",
|
CharacteristicsTypes.FILTER_LIFE_LEVEL: "sensor",
|
||||||
CharacteristicsTypes.VENDOR_AIRVERSA_SLEEP_MODE: "switch",
|
CharacteristicsTypes.VENDOR_AIRVERSA_SLEEP_MODE: "switch",
|
||||||
CharacteristicsTypes.TEMPERATURE_UNITS: "select",
|
CharacteristicsTypes.TEMPERATURE_UNITS: "select",
|
||||||
|
CharacteristicsTypes.AIR_PURIFIER_STATE_CURRENT: "sensor",
|
||||||
|
CharacteristicsTypes.AIR_PURIFIER_STATE_TARGET: "select",
|
||||||
}
|
}
|
||||||
|
|
||||||
STARTUP_EXCEPTIONS = (
|
STARTUP_EXCEPTIONS = (
|
||||||
|
@ -206,6 +206,7 @@ class HomeKitFanV2(BaseHomeKitFan):
|
|||||||
ENTITY_TYPES = {
|
ENTITY_TYPES = {
|
||||||
ServicesTypes.FAN: HomeKitFanV1,
|
ServicesTypes.FAN: HomeKitFanV1,
|
||||||
ServicesTypes.FAN_V2: HomeKitFanV2,
|
ServicesTypes.FAN_V2: HomeKitFanV2,
|
||||||
|
ServicesTypes.AIR_PURIFIER: HomeKitFanV2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,7 +5,10 @@ from dataclasses import dataclass
|
|||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
|
|
||||||
from aiohomekit.model.characteristics import Characteristic, CharacteristicsTypes
|
from aiohomekit.model.characteristics import Characteristic, CharacteristicsTypes
|
||||||
from aiohomekit.model.characteristics.const import TemperatureDisplayUnits
|
from aiohomekit.model.characteristics.const import (
|
||||||
|
TargetAirPurifierStateValues,
|
||||||
|
TemperatureDisplayUnits,
|
||||||
|
)
|
||||||
|
|
||||||
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
|
||||||
@ -47,6 +50,16 @@ SELECT_ENTITIES: dict[str, HomeKitSelectEntityDescription] = {
|
|||||||
"fahrenheit": TemperatureDisplayUnits.FAHRENHEIT,
|
"fahrenheit": TemperatureDisplayUnits.FAHRENHEIT,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
CharacteristicsTypes.AIR_PURIFIER_STATE_TARGET: HomeKitSelectEntityDescription(
|
||||||
|
key="air_purifier_state_target",
|
||||||
|
translation_key="air_purifier_state_target",
|
||||||
|
name="Air Purifier Mode",
|
||||||
|
entity_category=EntityCategory.CONFIG,
|
||||||
|
choices={
|
||||||
|
"automatic": TargetAirPurifierStateValues.AUTOMATIC,
|
||||||
|
"manual": TargetAirPurifierStateValues.MANUAL,
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
_ECOBEE_MODE_TO_TEXT = {
|
_ECOBEE_MODE_TO_TEXT = {
|
||||||
|
@ -3,10 +3,15 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from enum import IntEnum
|
||||||
|
|
||||||
from aiohomekit.model import Accessory, Transport
|
from aiohomekit.model import Accessory, Transport
|
||||||
from aiohomekit.model.characteristics import Characteristic, CharacteristicsTypes
|
from aiohomekit.model.characteristics import Characteristic, CharacteristicsTypes
|
||||||
from aiohomekit.model.characteristics.const import ThreadNodeCapabilities, ThreadStatus
|
from aiohomekit.model.characteristics.const import (
|
||||||
|
CurrentAirPurifierStateValues,
|
||||||
|
ThreadNodeCapabilities,
|
||||||
|
ThreadStatus,
|
||||||
|
)
|
||||||
from aiohomekit.model.services import Service, ServicesTypes
|
from aiohomekit.model.services import Service, ServicesTypes
|
||||||
|
|
||||||
from homeassistant.components.bluetooth import (
|
from homeassistant.components.bluetooth import (
|
||||||
@ -52,6 +57,7 @@ class HomeKitSensorEntityDescription(SensorEntityDescription):
|
|||||||
|
|
||||||
probe: Callable[[Characteristic], bool] | None = None
|
probe: Callable[[Characteristic], bool] | None = None
|
||||||
format: Callable[[Characteristic], str] | None = None
|
format: Callable[[Characteristic], str] | None = None
|
||||||
|
enum: dict[IntEnum, str] | None = None
|
||||||
|
|
||||||
|
|
||||||
def thread_node_capability_to_str(char: Characteristic) -> str:
|
def thread_node_capability_to_str(char: Characteristic) -> str:
|
||||||
@ -324,6 +330,18 @@ SIMPLE_SENSOR: dict[str, HomeKitSensorEntityDescription] = {
|
|||||||
],
|
],
|
||||||
translation_key="thread_status",
|
translation_key="thread_status",
|
||||||
),
|
),
|
||||||
|
CharacteristicsTypes.AIR_PURIFIER_STATE_CURRENT: HomeKitSensorEntityDescription(
|
||||||
|
key=CharacteristicsTypes.AIR_PURIFIER_STATE_CURRENT,
|
||||||
|
name="Air Purifier Status",
|
||||||
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
device_class=SensorDeviceClass.ENUM,
|
||||||
|
enum={
|
||||||
|
CurrentAirPurifierStateValues.INACTIVE: "inactive",
|
||||||
|
CurrentAirPurifierStateValues.IDLE: "idle",
|
||||||
|
CurrentAirPurifierStateValues.ACTIVE: "purifying",
|
||||||
|
},
|
||||||
|
translation_key="air_purifier_state_current",
|
||||||
|
),
|
||||||
CharacteristicsTypes.VENDOR_NETATMO_NOISE: HomeKitSensorEntityDescription(
|
CharacteristicsTypes.VENDOR_NETATMO_NOISE: HomeKitSensorEntityDescription(
|
||||||
key=CharacteristicsTypes.VENDOR_NETATMO_NOISE,
|
key=CharacteristicsTypes.VENDOR_NETATMO_NOISE,
|
||||||
name="Noise",
|
name="Noise",
|
||||||
@ -535,6 +553,8 @@ class SimpleSensor(CharacteristicEntity, SensorEntity):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialise a secondary HomeKit characteristic sensor."""
|
"""Initialise a secondary HomeKit characteristic sensor."""
|
||||||
self.entity_description = description
|
self.entity_description = description
|
||||||
|
if self.entity_description.enum:
|
||||||
|
self._attr_options = list(self.entity_description.enum.values())
|
||||||
super().__init__(conn, info, char)
|
super().__init__(conn, info, char)
|
||||||
|
|
||||||
def get_characteristic_types(self) -> list[str]:
|
def get_characteristic_types(self) -> list[str]:
|
||||||
@ -551,10 +571,11 @@ class SimpleSensor(CharacteristicEntity, SensorEntity):
|
|||||||
@property
|
@property
|
||||||
def native_value(self) -> str | int | float:
|
def native_value(self) -> str | int | float:
|
||||||
"""Return the current sensor value."""
|
"""Return the current sensor value."""
|
||||||
val = self._char.value
|
if self.entity_description.enum:
|
||||||
|
return self.entity_description.enum[self._char.value]
|
||||||
if self.entity_description.format:
|
if self.entity_description.format:
|
||||||
return self.entity_description.format(val)
|
return self.entity_description.format(self._char)
|
||||||
return val
|
return self._char.value
|
||||||
|
|
||||||
|
|
||||||
ENTITY_TYPES = {
|
ENTITY_TYPES = {
|
||||||
|
@ -108,6 +108,12 @@
|
|||||||
"celsius": "Celsius",
|
"celsius": "Celsius",
|
||||||
"fahrenheit": "Fahrenheit"
|
"fahrenheit": "Fahrenheit"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"air_purifier_state_target": {
|
||||||
|
"state": {
|
||||||
|
"automatic": "Automatic",
|
||||||
|
"manual": "Manual"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sensor": {
|
"sensor": {
|
||||||
@ -131,6 +137,13 @@
|
|||||||
"leader": "Leader",
|
"leader": "Leader",
|
||||||
"router": "Router"
|
"router": "Router"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"air_purifier_state_current": {
|
||||||
|
"state": {
|
||||||
|
"inactive": "Inactive",
|
||||||
|
"idle": "Idle",
|
||||||
|
"purifying": "Purifying"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,142 @@
|
|||||||
'state': 'unknown',
|
'state': 'unknown',
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
dict({
|
||||||
|
'entry': dict({
|
||||||
|
'aliases': list([
|
||||||
|
]),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'preset_modes': None,
|
||||||
|
}),
|
||||||
|
'config_entry_id': 'TestData',
|
||||||
|
'device_class': None,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'fan',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'fan.airversa_ap2_1808_airpurifier',
|
||||||
|
'has_entity_name': False,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': None,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Airversa AP2 1808 AirPurifier',
|
||||||
|
'platform': 'homekit_controller',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': <FanEntityFeature: 1>,
|
||||||
|
'translation_key': None,
|
||||||
|
'unique_id': '00:00:00:00:00:00_1_32832',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
}),
|
||||||
|
'state': dict({
|
||||||
|
'attributes': dict({
|
||||||
|
'friendly_name': 'Airversa AP2 1808 AirPurifier',
|
||||||
|
'percentage': 0,
|
||||||
|
'percentage_step': 20.0,
|
||||||
|
'preset_mode': None,
|
||||||
|
'preset_modes': None,
|
||||||
|
'supported_features': <FanEntityFeature: 1>,
|
||||||
|
}),
|
||||||
|
'entity_id': 'fan.airversa_ap2_1808_airpurifier',
|
||||||
|
'state': 'off',
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'entry': dict({
|
||||||
|
'aliases': list([
|
||||||
|
]),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'options': list([
|
||||||
|
'automatic',
|
||||||
|
'manual',
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
'config_entry_id': 'TestData',
|
||||||
|
'device_class': None,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'select',
|
||||||
|
'entity_category': <EntityCategory.CONFIG: 'config'>,
|
||||||
|
'entity_id': 'select.airversa_ap2_1808_air_purifier_mode',
|
||||||
|
'has_entity_name': False,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': None,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Airversa AP2 1808 Air Purifier Mode',
|
||||||
|
'platform': 'homekit_controller',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'air_purifier_state_target',
|
||||||
|
'unique_id': '00:00:00:00:00:00_1_32832_32837',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
}),
|
||||||
|
'state': dict({
|
||||||
|
'attributes': dict({
|
||||||
|
'friendly_name': 'Airversa AP2 1808 Air Purifier Mode',
|
||||||
|
'options': list([
|
||||||
|
'automatic',
|
||||||
|
'manual',
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
'entity_id': 'select.airversa_ap2_1808_air_purifier_mode',
|
||||||
|
'state': 'automatic',
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'entry': dict({
|
||||||
|
'aliases': list([
|
||||||
|
]),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'options': list([
|
||||||
|
'inactive',
|
||||||
|
'idle',
|
||||||
|
'purifying',
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
'config_entry_id': 'TestData',
|
||||||
|
'device_class': None,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'sensor',
|
||||||
|
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||||
|
'entity_id': 'sensor.airversa_ap2_1808_air_purifier_status',
|
||||||
|
'has_entity_name': False,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Airversa AP2 1808 Air Purifier Status',
|
||||||
|
'platform': 'homekit_controller',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'air_purifier_state_current',
|
||||||
|
'unique_id': '00:00:00:00:00:00_1_32832_32836',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
}),
|
||||||
|
'state': dict({
|
||||||
|
'attributes': dict({
|
||||||
|
'device_class': 'enum',
|
||||||
|
'friendly_name': 'Airversa AP2 1808 Air Purifier Status',
|
||||||
|
'options': list([
|
||||||
|
'inactive',
|
||||||
|
'idle',
|
||||||
|
'purifying',
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
'entity_id': 'sensor.airversa_ap2_1808_air_purifier_status',
|
||||||
|
'state': 'inactive',
|
||||||
|
}),
|
||||||
|
}),
|
||||||
dict({
|
dict({
|
||||||
'entry': dict({
|
'entry': dict({
|
||||||
'aliases': list([
|
'aliases': list([
|
||||||
|
Loading…
x
Reference in New Issue
Block a user