Skip to content

Commit

Permalink
Add support for PM1/2.5/10 device class (#459)
Browse files Browse the repository at this point in the history
  • Loading branch information
dext0r committed Oct 30, 2023
1 parent 77fcb66 commit 7916b62
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 19 deletions.
30 changes: 24 additions & 6 deletions custom_components/yandex_smart_home/property_float.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,8 +543,11 @@ class PM1DensitySensor(StateProperty, PM1DensityProperty):
@property
def supported(self) -> bool:
"""Test if the property is supported."""
if self.state.domain == air_quality.DOMAIN:
return air_quality.ATTR_PM_0_1 in self.state.attributes
match self.state.domain:
case sensor.DOMAIN:
return self.state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.PM1
case air_quality.DOMAIN:
return air_quality.ATTR_PM_0_1 in self.state.attributes

return False

Expand All @@ -555,6 +558,9 @@ def parameters(self) -> PM1DensityFloatPropertyParameters:

def _get_native_value(self) -> float | str | None:
"""Return the current property value without conversion."""
if self.state.domain == sensor.DOMAIN:
return self.state.state

return self.state.attributes.get(air_quality.ATTR_PM_0_1)


Expand All @@ -565,13 +571,19 @@ class PM25DensitySensor(StateProperty, PM25DensityProperty):
@property
def supported(self) -> bool:
"""Test if the property is supported."""
if self.state.domain == air_quality.DOMAIN:
return air_quality.ATTR_PM_2_5 in self.state.attributes
match self.state.domain:
case sensor.DOMAIN:
return self.state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.PM25
case air_quality.DOMAIN:
return air_quality.ATTR_PM_2_5 in self.state.attributes

return False

def _get_native_value(self) -> float | str | None:
"""Return the current property value without conversion."""
if self.state.domain == sensor.DOMAIN:
return self.state.state

return self.state.attributes.get(air_quality.ATTR_PM_2_5)


Expand All @@ -582,13 +594,19 @@ class PM10DensitySensor(StateProperty, PM10DensityProperty):
@property
def supported(self) -> bool:
"""Test if the property is supported."""
if self.state.domain == air_quality.DOMAIN:
return air_quality.ATTR_PM_10 in self.state.attributes
match self.state.domain:
case sensor.DOMAIN:
return self.state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.PM10
case air_quality.DOMAIN:
return air_quality.ATTR_PM_10 in self.state.attributes

return False

def _get_native_value(self) -> float | str | None:
"""Return the current property value without conversion."""
if self.state.domain == sensor.DOMAIN:
return self.state.state

return self.state.attributes.get(air_quality.ATTR_PM_10)


Expand Down
2 changes: 2 additions & 0 deletions docs/supported-devices.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
Или при наличии у объекта атрибута `carbon_dioxide`

### Уровни частиц PM1 / PM2.5 / PM10 { id=float-sensor-pm }
* `device_class`: `pm1` / `pm25` / `pm10`

При наличиии у объекта атрибутов `particulate_matter_0_1` / `particulate_matter_2_5` / `particulate_matter_10`

### Уровень TVOC { id=float-sensor-tvoc }
Expand Down
34 changes: 21 additions & 13 deletions tests/test_property_float.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,27 +371,35 @@ async def test_property_float_co2_level(hass, domain, device_class, attribute, s
assert prop.get_value() is None


@pytest.mark.parametrize("v,assert_v", [("300", 300), ("-5", 0), (None, None)])
@pytest.mark.parametrize(
"attribute,instance",
"domain,device_class,attribute,instance",
[
(air_quality.ATTR_PM_0_1, "pm1_density"),
(air_quality.ATTR_PM_2_5, "pm2.5_density"),
(air_quality.ATTR_PM_10, "pm10_density"),
(sensor.DOMAIN, SensorDeviceClass.PM1, None, "pm1_density"),
(sensor.DOMAIN, SensorDeviceClass.PM25, None, "pm2.5_density"),
(sensor.DOMAIN, SensorDeviceClass.PM10, None, "pm10_density"),
(air_quality.DOMAIN, None, air_quality.ATTR_PM_0_1, "pm1_density"),
(air_quality.DOMAIN, None, air_quality.ATTR_PM_2_5, "pm2.5_density"),
(air_quality.DOMAIN, None, air_quality.ATTR_PM_10, "pm10_density"),
],
)
async def test_property_float_pm_density(hass, attribute, instance):
state = State("air_quality.test", STATE_ON, {attribute: 300})
async def test_property_float_pm_density(hass, domain, v, assert_v, device_class, attribute, instance):
state = STATE_ON
attributes = {}
if device_class:
attributes[ATTR_DEVICE_CLASS] = device_class

if attribute:
attributes[attribute] = v
else:
state = v

state = State(f"{domain}.test", state, attributes)
prop = get_exact_one_property(hass, BASIC_ENTRY_DATA, state, PropertyType.FLOAT, FloatPropertyInstance(instance))

assert prop.retrievable is True
assert prop.parameters == {"instance": instance, "unit": "unit.density.mcg_m3"}
assert prop.get_value() == 300

prop.state = State("air_quality.test", STATE_ON, {attribute: -5})
assert prop.get_value() == 0

prop.state = State("air_quality.test", STATE_ON, {attribute: None})
assert prop.get_value() is None
assert prop.get_value() == assert_v


@pytest.mark.parametrize(
Expand Down

0 comments on commit 7916b62

Please sign in to comment.