From 0065bbc56d285c1c6e40462a59adcb5bd286f5cc Mon Sep 17 00:00:00 2001 From: Jc2k Date: Mon, 23 Aug 2021 19:47:09 +0100 Subject: [PATCH] Add volatile organic compounds to homekit_controller (#55093) --- .../components/homekit_controller/const.py | 23 ++++++++-- .../components/homekit_controller/sensor.py | 7 +++ .../homekit_controller/test_air_quality.py | 45 +++++++++++++++++++ 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/homekit_controller/const.py b/homeassistant/components/homekit_controller/const.py index 9e2ac1ce75b..fa28bab7606 100644 --- a/homeassistant/components/homekit_controller/const.py +++ b/homeassistant/components/homekit_controller/const.py @@ -50,8 +50,23 @@ CHARACTERISTIC_PLATFORMS = { CharacteristicsTypes.Vendor.KOOGEEK_REALTIME_ENERGY: "sensor", CharacteristicsTypes.Vendor.KOOGEEK_REALTIME_ENERGY_2: "sensor", CharacteristicsTypes.Vendor.VOCOLINC_HUMIDIFIER_SPRAY_LEVEL: "number", - CharacteristicsTypes.get_uuid(CharacteristicsTypes.TEMPERATURE_CURRENT): "sensor", - CharacteristicsTypes.get_uuid( - CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT - ): "sensor", + CharacteristicsTypes.TEMPERATURE_CURRENT: "sensor", + CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT: "sensor", + CharacteristicsTypes.AIR_QUALITY: "sensor", + CharacteristicsTypes.DENSITY_PM25: "sensor", + CharacteristicsTypes.DENSITY_PM10: "sensor", + CharacteristicsTypes.DENSITY_OZONE: "sensor", + CharacteristicsTypes.DENSITY_NO2: "sensor", + CharacteristicsTypes.DENSITY_SO2: "sensor", + CharacteristicsTypes.DENSITY_VOC: "sensor", } + +# For legacy reasons, "built-in" characteristic types are in their short form +# And vendor types don't have a short form +# This means long and short forms get mixed up in this dict, and comparisons +# don't work! +# We call get_uuid on *every* type to normalise them to the long form +# Eventually aiohomekit will use the long form exclusively amd this can be removed. +for k, v in list(CHARACTERISTIC_PLATFORMS.items()): + value = CHARACTERISTIC_PLATFORMS.pop(k) + CHARACTERISTIC_PLATFORMS[CharacteristicsTypes.get_uuid(k)] = value diff --git a/homeassistant/components/homekit_controller/sensor.py b/homeassistant/components/homekit_controller/sensor.py index ac4f19dadb4..cac61d59ac4 100644 --- a/homeassistant/components/homekit_controller/sensor.py +++ b/homeassistant/components/homekit_controller/sensor.py @@ -18,6 +18,7 @@ from homeassistant.const import ( DEVICE_CLASS_PRESSURE, DEVICE_CLASS_SULPHUR_DIOXIDE, DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, LIGHT_LUX, PERCENTAGE, POWER_WATT, @@ -114,6 +115,12 @@ SIMPLE_SENSOR = { "state_class": STATE_CLASS_MEASUREMENT, "unit": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, }, + CharacteristicsTypes.DENSITY_VOC: { + "name": "Volatile Organic Compound Density", + "device_class": DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, + "state_class": STATE_CLASS_MEASUREMENT, + "unit": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + }, } # For legacy reasons, "built-in" characteristic types are in their short form diff --git a/tests/components/homekit_controller/test_air_quality.py b/tests/components/homekit_controller/test_air_quality.py index f75335ca357..2477c6bacfd 100644 --- a/tests/components/homekit_controller/test_air_quality.py +++ b/tests/components/homekit_controller/test_air_quality.py @@ -2,6 +2,7 @@ from aiohomekit.model.characteristics import CharacteristicsTypes from aiohomekit.model.services import ServicesTypes +from homeassistant.const import CONCENTRATION_MICROGRAMS_PER_CUBIC_METER from homeassistant.helpers import entity_registry as er from tests.components.homekit_controller.common import setup_test_component @@ -53,3 +54,47 @@ async def test_air_quality_sensor_read_state(hass, utcnow): assert state.attributes["particulate_matter_2_5"] == 4444 assert state.attributes["particulate_matter_10"] == 5555 assert state.attributes["volatile_organic_compounds"] == 6666 + + +async def test_air_quality_sensor_read_state_even_if_air_quality_off(hass, utcnow): + """The air quality entity is disabled by default, the replacement sensors should always be available.""" + await setup_test_component(hass, create_air_quality_sensor_service) + + entity_registry = er.async_get(hass) + + sensors = [ + {"entity_id": "sensor.testdevice_air_quality"}, + { + "entity_id": "sensor.testdevice_pm10_density", + "units": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + }, + { + "entity_id": "sensor.testdevice_pm2_5_density", + "units": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + }, + { + "entity_id": "sensor.testdevice_pm10_density", + "units": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + }, + { + "entity_id": "sensor.testdevice_ozone_density", + "units": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + }, + { + "entity_id": "sensor.testdevice_sulphur_dioxide_density", + "units": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + }, + { + "entity_id": "sensor.testdevice_nitrogen_dioxide_density", + "units": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + }, + { + "entity_id": "sensor.testdevice_volatile_organic_compound_density", + "units": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + }, + ] + + for sensor in sensors: + entry = entity_registry.async_get(sensor["entity_id"]) + assert entry is not None + assert entry.unit_of_measurement == sensor.get("units")