Skip to content

Commit

Permalink
Task/support disabled sensors (#37)
Browse files Browse the repository at this point in the history
* fix sensor errors when device off or failed

---------

Co-authored-by: Nils Hulsch <[email protected]>
  • Loading branch information
dotvezz and nhulsch authored Jul 3, 2023
1 parent 8729c8e commit 67fb01f
Showing 1 changed file with 90 additions and 38 deletions.
128 changes: 90 additions & 38 deletions custom_components/dyson_local/sensor.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Sensor platform for dyson."""

from typing import Callable, Union
from typing import Callable, Union, Optional

from .vendor.libdyson import (
Dyson360Eye,
Expand Down Expand Up @@ -85,8 +85,8 @@ class DysonSensor(SensorEntity, DysonEntity):
"""Base class for a Dyson sensor."""

_MESSAGE_TYPE = MessageType.STATE
_SENSOR_TYPE = None
_SENSOR_NAME = None
_SENSOR_TYPE: Optional[str] = None
_SENSOR_NAME: Optional[str] = None

def __init__(self, device: DysonDevice, name: str):
"""Initialize the sensor."""
Expand All @@ -110,7 +110,7 @@ class DysonSensorEnvironmental(CoordinatorEntity, DysonSensor):

def __init__(
self, coordinator: DataUpdateCoordinator, device: DysonDevice, name: str
):
) -> None:
"""Initialize the environmental sensor."""
CoordinatorEntity.__init__(self, coordinator)
DysonSensor.__init__(self, device, name)
Expand Down Expand Up @@ -200,10 +200,16 @@ class DysonNextDeepCleanSensor(DysonSensor):
_attr_native_unit_of_measurement = TIME_HOURS

@property
def native_value(self) -> int:
def native_value(self) -> Optional[int]:
"""Return the state of the sensor."""
return self._device.time_until_next_clean
if (value := self._device.time_until_next_clean) >= 0:
return value
return None

@property
def available(self) -> bool:
"""Return available only if device not in off, init or failed states."""
return isinstance(self._device.time_until_next_clean, (int, float))

class DysonHumiditySensor(DysonSensorEnvironmental):
"""Dyson humidity sensor."""
Expand All @@ -214,10 +220,17 @@ class DysonHumiditySensor(DysonSensorEnvironmental):
_attr_native_unit_of_measurement = PERCENTAGE
_attr_state_class = SensorStateClass.MEASUREMENT

@environmental_property
def native_value(self) -> int:
@property
def native_value(self) -> Optional[int]:
"""Return the state of the sensor."""
return self._device.humidity
if (value := self._device.humidity) >= 0:
return value
return None

@property
def available(self) -> bool:
"""Return available only if device not in off, init or failed states."""
return isinstance(self._device.humidity, (int, float))


class DysonTemperatureSensor(DysonSensorEnvironmental):
Expand All @@ -229,24 +242,21 @@ class DysonTemperatureSensor(DysonSensorEnvironmental):
_attr_native_unit_of_measurement = TEMP_CELSIUS
_attr_state_class = SensorStateClass.MEASUREMENT

@environmental_property
def temperature_kelvin(self) -> int:
"""Return the temperature in kelvin."""
return self._device.temperature

@property
def native_value(self) -> Union[str, float]:
def native_value(self) -> Optional[float]:
"""Return the "native" value for this sensor.
Note that as of 2021-10-28, Home Assistant does not support converting
from Kelvin native unit to Celsius/Fahrenheit. So we return the Celsius
value as it's the easiest to calculate.
"""
temperature_kelvin = self.temperature_kelvin
if isinstance(temperature_kelvin, str):
return temperature_kelvin
if (value := self._device.temperature) >= 0:
return value - 273.15
return None

return temperature_kelvin - 273.15
@property
def available(self) -> bool:
"""Return available only if device not in off, init or failed states."""
return isinstance(self._device.temperature, (int, float))


class DysonPM25Sensor(DysonSensorEnvironmental):
Expand All @@ -258,10 +268,17 @@ class DysonPM25Sensor(DysonSensorEnvironmental):
_attr_native_unit_of_measurement = CONCENTRATION_MICROGRAMS_PER_CUBIC_METER
_attr_state_class = SensorStateClass.MEASUREMENT

@environmental_property
def native_value(self) -> int:
@property
def native_value(self) -> Optional[float]:
"""Return the state of the sensor."""
return self._device.particulate_matter_2_5
if (value := self._device.particulate_matter_2_5) >= 0:
return value
return None

@property
def available(self) -> bool:
"""Return available only if device not in off, init or failed states."""
return isinstance(self._device.particulate_matter_2_5, (int, float))


class DysonPM10Sensor(DysonSensorEnvironmental):
Expand All @@ -273,10 +290,17 @@ class DysonPM10Sensor(DysonSensorEnvironmental):
_attr_native_unit_of_measurement = CONCENTRATION_MICROGRAMS_PER_CUBIC_METER
_attr_state_class = SensorStateClass.MEASUREMENT

@environmental_property
def native_value(self) -> int:
@property
def native_value(self) -> Optional[int]:
"""Return the state of the sensor."""
return self._device.particulate_matter_10
if (value := self._device.particulate_matter_10) >= 0:
return value
return None

@property
def available(self) -> bool:
"""Return available only if device not in off, init or failed states."""
return isinstance(self._device.particulate_matter_10, (int, float))


class DysonParticulatesSensor(DysonSensorEnvironmental):
Expand All @@ -286,10 +310,17 @@ class DysonParticulatesSensor(DysonSensorEnvironmental):
_attr_device_class = SensorDeviceClass.AQI
_attr_state_class = SensorStateClass.MEASUREMENT

@environmental_property
def native_value(self) -> int:
@property
def native_value(self) -> Optional[int]:
"""Return the state of the sensor."""
return self._device.particulates
if (value := self._device.particulates) >= 0:
return value
return None

@property
def available(self) -> bool:
"""Return available only if device not in off, init or failed states."""
return isinstance(self._device.particulates, (int, float))


class DysonVOCSensor(DysonSensorEnvironmental):
Expand All @@ -300,10 +331,17 @@ class DysonVOCSensor(DysonSensorEnvironmental):
_attr_device_class = SensorDeviceClass.AQI
_attr_state_class = SensorStateClass.MEASUREMENT

@environmental_property
def native_value(self) -> float:
@property
def native_value(self) -> Optional[int]:
"""Return the state of the sensor."""
return self._device.volatile_organic_compounds
if (value := self._device.volatile_organic_compounds) >= 0:
return value
return None

@property
def available(self) -> bool:
"""Return available only if device not in off, init or failed states."""
return isinstance(self._device.volatile_organic_compounds, (int, float))


class DysonNO2Sensor(DysonSensorEnvironmental):
Expand All @@ -314,10 +352,17 @@ class DysonNO2Sensor(DysonSensorEnvironmental):
_attr_device_class = SensorDeviceClass.AQI
_attr_state_class = SensorStateClass.MEASUREMENT

@environmental_property
def native_value(self) -> int:
@property
def native_value(self) -> Optional[int]:
"""Return the state of the sensor."""
return self._device.nitrogen_dioxide
if (value := self._device.nitrogen_dioxide) >= 0:
return value
return None

@property
def available(self) -> bool:
"""Return available only if device not in off, init or failed states."""
return isinstance(self._device.nitrogen_dioxide, (int, float))


class DysonHCHOSensor(DysonSensorEnvironmental):
Expand All @@ -329,7 +374,14 @@ class DysonHCHOSensor(DysonSensorEnvironmental):
_attr_device_class = SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS
_attr_state_class = SensorStateClass.MEASUREMENT

@environmental_property
def native_value(self) -> float:
@property
def native_value(self) -> Optional[int]:
"""Return the state of the sensor."""
return self._device.formaldehyde
if (value := self._device.formaldehyde) >= 0:
return value
return None

@property
def available(self) -> bool:
"""Return available only if device not in off, init or failed states."""
return isinstance(self._device.formaldehyde, (int, float))

0 comments on commit 67fb01f

Please sign in to comment.