ha_gehome/entities/common/ge_erd_sensor.py

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}")