Skip to content

Commit

Permalink
Add support for homekit air quality sensors (#30510)
Browse files Browse the repository at this point in the history
* Add air quality sensor

* Fix comment from review

* Fix comment from review

* Lint fix
  • Loading branch information
Jc2k authored and MartinHjelmare committed Jan 6, 2020
1 parent 1fffa21 commit a58c796
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 0 deletions.
10 changes: 10 additions & 0 deletions homeassistant/components/homekit_controller/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,16 @@ def _setup_characteristic(self, char):
return
setup_fn(char)

def get_hk_char_value(self, characteristic_type):
"""Return the value for a given characteristic type enum."""
state = self._accessory.current_state.get(self._aid)
if not state:
return None
char = self._chars.get(CharacteristicsTypes.get_short(characteristic_type))
if not char:
return None
return state.get(char, {}).get("value")

@callback
def async_state_changed(self):
"""Collect new data from bridge and update the entity state in hass."""
Expand Down
98 changes: 98 additions & 0 deletions homeassistant/components/homekit_controller/air_quality.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
"""Support for HomeKit Controller air quality sensors."""
from homekit.model.characteristics import CharacteristicsTypes

from homeassistant.components.air_quality import AirQualityEntity

from . import KNOWN_DEVICES, HomeKitEntity

AIR_QUALITY_TEXT = {
0: "unknown",
1: "excellent",
2: "good",
3: "fair",
4: "inferior",
5: "poor",
}


class HomeAirQualitySensor(HomeKitEntity, AirQualityEntity):
"""Representation of a HomeKit Controller Air Quality sensor."""

def get_characteristic_types(self):
"""Define the homekit characteristics the entity cares about."""
return [
CharacteristicsTypes.AIR_QUALITY,
CharacteristicsTypes.DENSITY_PM25,
CharacteristicsTypes.DENSITY_PM10,
CharacteristicsTypes.DENSITY_OZONE,
CharacteristicsTypes.DENSITY_NO2,
CharacteristicsTypes.DENSITY_SO2,
CharacteristicsTypes.DENSITY_VOC,
]

@property
def particulate_matter_2_5(self):
"""Return the particulate matter 2.5 level."""
return self.get_hk_char_value(CharacteristicsTypes.DENSITY_PM25)

@property
def particulate_matter_10(self):
"""Return the particulate matter 10 level."""
return self.get_hk_char_value(CharacteristicsTypes.DENSITY_PM10)

@property
def ozone(self):
"""Return the O3 (ozone) level."""
return self.get_hk_char_value(CharacteristicsTypes.DENSITY_OZONE)

@property
def sulphur_dioxide(self):
"""Return the SO2 (sulphur dioxide) level."""
return self.get_hk_char_value(CharacteristicsTypes.DENSITY_SO2)

@property
def nitrogen_dioxide(self):
"""Return the NO2 (nitrogen dioxide) level."""
return self.get_hk_char_value(CharacteristicsTypes.DENSITY_NO2)

@property
def air_quality_text(self):
"""Return the Air Quality Index (AQI)."""
air_quality = self.get_hk_char_value(CharacteristicsTypes.AIR_QUALITY)
return AIR_QUALITY_TEXT.get(air_quality, "unknown")

@property
def volatile_organic_compounds(self):
"""Return the volatile organic compounds (VOC) level."""
return self.get_hk_char_value(CharacteristicsTypes.DENSITY_VOC)

@property
def device_state_attributes(self):
"""Return the device state attributes."""
data = {"air_quality_text": self.air_quality_text}

voc = self.volatile_organic_compounds
if voc:
data["volatile_organic_compounds"] = voc

return data


async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Legacy set up platform."""
pass


async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up Homekit air quality sensor."""
hkid = config_entry.data["AccessoryPairingID"]
conn = hass.data[KNOWN_DEVICES][hkid]

def async_add_service(aid, service):
if service["stype"] != "air-quality":
return False
info = {"aid": aid, "iid": service["iid"]}
async_add_entities([HomeAirQualitySensor(conn, info)], True)
return True

conn.add_listener(async_add_service)
1 change: 1 addition & 0 deletions homeassistant/components/homekit_controller/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@
"smoke": "binary_sensor",
"fan": "fan",
"fanv2": "fan",
"air-quality": "air_quality",
}
47 changes: 47 additions & 0 deletions tests/components/homekit_controller/test_air_quality.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""Basic checks for HomeKit air quality sensor."""
from tests.components.homekit_controller.common import FakeService, setup_test_component


def create_air_quality_sensor_service():
"""Define temperature characteristics."""
service = FakeService("public.hap.service.sensor.air-quality")

cur_state = service.add_characteristic("air-quality")
cur_state.value = 5

cur_state = service.add_characteristic("density.ozone")
cur_state.value = 1111

cur_state = service.add_characteristic("density.no2")
cur_state.value = 2222

cur_state = service.add_characteristic("density.so2")
cur_state.value = 3333

cur_state = service.add_characteristic("density.pm25")
cur_state.value = 4444

cur_state = service.add_characteristic("density.pm10")
cur_state.value = 5555

cur_state = service.add_characteristic("density.voc")
cur_state.value = 6666

return service


async def test_air_quality_sensor_read_state(hass, utcnow):
"""Test reading the state of a HomeKit temperature sensor accessory."""
sensor = create_air_quality_sensor_service()
helper = await setup_test_component(hass, [sensor])

state = await helper.poll_and_get_state()
assert state.state == "4444"

assert state.attributes["air_quality_text"] == "poor"
assert state.attributes["ozone"] == 1111
assert state.attributes["nitrogen_dioxide"] == 2222
assert state.attributes["sulphur_dioxide"] == 3333
assert state.attributes["particulate_matter_2_5"] == 4444
assert state.attributes["particulate_matter_10"] == 5555
assert state.attributes["volatile_organic_compounds"] == 6666

0 comments on commit a58c796

Please sign in to comment.