164 lines
6.0 KiB
Python
164 lines
6.0 KiB
Python
import logging
|
|
from typing import Optional
|
|
from gehomesdk.erd.erd_data_type import ErdDataType
|
|
from homeassistant.components.sensor import SensorDeviceClass, SensorEntity, SensorStateClass
|
|
|
|
from homeassistant.const import UnitOfTemperature
|
|
from gehomesdk import ErdCodeType, ErdCodeClass
|
|
from .ge_erd_entity import GeErdEntity
|
|
from ...devices import ApplianceApi
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
class GeErdSensor(GeErdEntity, SensorEntity):
|
|
"""GE Entity for sensors"""
|
|
|
|
def __init__(
|
|
self,
|
|
api: ApplianceApi,
|
|
erd_code: ErdCodeType,
|
|
erd_override: str = None,
|
|
icon_override: str = None,
|
|
device_class_override: str = None,
|
|
state_class_override: str = None,
|
|
uom_override: str = None,
|
|
data_type_override: ErdDataType = None
|
|
):
|
|
super().__init__(api, erd_code, erd_override, icon_override, device_class_override)
|
|
self._uom_override = uom_override
|
|
self._state_class_override = state_class_override
|
|
self._data_type_override = data_type_override
|
|
|
|
@property
|
|
def native_value(self):
|
|
try:
|
|
value = self.appliance.get_erd_value(self.erd_code)
|
|
|
|
# if it's a numeric data type, return it directly
|
|
if self._data_type in [ErdDataType.INT, ErdDataType.FLOAT]:
|
|
return self._convert_numeric_value_from_device(value)
|
|
|
|
# otherwise, return a stringified version
|
|
# TODO: perhaps enhance so that there's a list of variables available
|
|
# for the stringify function to consume...
|
|
return self._stringify(value, temp_units=self._temp_units)
|
|
except KeyError:
|
|
return None
|
|
|
|
@property
|
|
def native_unit_of_measurement(self) -> Optional[str]:
|
|
return self._get_uom()
|
|
|
|
@property
|
|
def state_class(self) -> Optional[str]:
|
|
return self._get_state_class()
|
|
|
|
@property
|
|
def _data_type(self) -> ErdDataType:
|
|
if self._data_type_override is not None:
|
|
return self._data_type_override
|
|
|
|
return self.appliance.get_erd_code_data_type(self.erd_code)
|
|
|
|
@property
|
|
def _temp_units(self) -> Optional[str]:
|
|
#based on testing, all API values are in Fahrenheit, so we'll redefine
|
|
#this property to be the configured temperature unit and set the native
|
|
#unit differently
|
|
return self.api.hass.config.units.temperature_unit
|
|
|
|
#if self._measurement_system == ErdMeasurementUnits.METRIC:
|
|
# return UnitOfTemperature.CELSIUS
|
|
#return UnitOfTemperature.FAHRENHEIT
|
|
|
|
def _convert_numeric_value_from_device(self, value):
|
|
"""Convert to expected data type"""
|
|
|
|
if self._data_type == ErdDataType.INT:
|
|
return int(round(value))
|
|
else:
|
|
return value
|
|
|
|
def _get_uom(self):
|
|
"""Select appropriate units"""
|
|
|
|
#if we have an override, just use it
|
|
if self._uom_override:
|
|
return self._uom_override
|
|
|
|
if (
|
|
self.erd_code_class
|
|
in [ErdCodeClass.RAW_TEMPERATURE, ErdCodeClass.NON_ZERO_TEMPERATURE]
|
|
or self.device_class == SensorDeviceClass.TEMPERATURE
|
|
):
|
|
#NOTE: it appears that the API only sets temperature in Fahrenheit,
|
|
#so we'll hard code this UOM instead of using the device configured
|
|
#settings
|
|
return UnitOfTemperature.FAHRENHEIT
|
|
if (
|
|
self.erd_code_class == ErdCodeClass.BATTERY
|
|
or self.device_class == SensorDeviceClass.BATTERY
|
|
):
|
|
return "%"
|
|
if self.erd_code_class == ErdCodeClass.PERCENTAGE:
|
|
return "%"
|
|
if self.device_class == SensorDeviceClass.POWER_FACTOR:
|
|
return "%"
|
|
if self.erd_code_class == ErdCodeClass.HUMIDITY:
|
|
return "%"
|
|
if self.erd_code_class == ErdCodeClass.FLOW_RATE:
|
|
#if self._measurement_system == ErdMeasurementUnits.METRIC:
|
|
# return "lpm"
|
|
return "gpm"
|
|
if self.erd_code_class == ErdCodeClass.LIQUID_VOLUME:
|
|
#if self._measurement_system == ErdMeasurementUnits.METRIC:
|
|
# return "l"
|
|
return "gal"
|
|
return None
|
|
|
|
def _get_device_class(self) -> Optional[str]:
|
|
if self._device_class_override:
|
|
return self._device_class_override
|
|
if self.erd_code_class in [
|
|
ErdCodeClass.RAW_TEMPERATURE,
|
|
ErdCodeClass.NON_ZERO_TEMPERATURE,
|
|
]:
|
|
return SensorDeviceClass.TEMPERATURE
|
|
if self.erd_code_class == ErdCodeClass.BATTERY:
|
|
return SensorDeviceClass.BATTERY
|
|
if self.erd_code_class == ErdCodeClass.POWER:
|
|
return SensorDeviceClass.POWER
|
|
if self.erd_code_class == ErdCodeClass.ENERGY:
|
|
return SensorDeviceClass.ENERGY
|
|
if self.erd_code_class == ErdCodeClass.HUMIDITY:
|
|
return SensorDeviceClass.HUMIDITY
|
|
|
|
return None
|
|
|
|
def _get_state_class(self) -> Optional[str]:
|
|
if self._state_class_override:
|
|
return self._state_class_override
|
|
|
|
if self.device_class in [SensorDeviceClass.TEMPERATURE, SensorDeviceClass.ENERGY]:
|
|
return SensorStateClass.MEASUREMENT
|
|
if self.erd_code_class in [ErdCodeClass.FLOW_RATE, ErdCodeClass.PERCENTAGE, ErdCodeClass.HUMIDITY]:
|
|
return SensorStateClass.MEASUREMENT
|
|
if self.erd_code_class in [ErdCodeClass.LIQUID_VOLUME]:
|
|
return SensorStateClass.TOTAL_INCREASING
|
|
|
|
return None
|
|
|
|
def _get_icon(self):
|
|
if self.erd_code_class == ErdCodeClass.DOOR:
|
|
if self.state.lower().endswith("open"):
|
|
return "mdi:door-open"
|
|
if self.state.lower().endswith("closed"):
|
|
return "mdi:door-closed"
|
|
return super()._get_icon()
|
|
|
|
async def set_value(self, value):
|
|
"""Sets the ERD value, assumes that the data type is correct"""
|
|
try:
|
|
await self.appliance.async_set_erd_value(self.erd_code, value)
|
|
except:
|
|
_LOGGER.warning(f"Could not set {self.name} to {value}") |