Merge pull request #68 from alexanv1/coffeemaker

Updates to Coffee Maker support
This commit is contained in:
simbaja 2022-02-18 23:47:31 -05:00 committed by GitHub
commit 54880b878b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 393 additions and 245 deletions

View File

@ -0,0 +1,33 @@
"""GE Home Button Entities"""
import async_timeout
import logging
from typing import Callable
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from .const import DOMAIN
from .entities import GeErdButton
from .update_coordinator import GeHomeUpdateCoordinator
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: Callable):
"""GE Home buttons."""
coordinator: GeHomeUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
# This should be a NOP, but let's be safe
with async_timeout.timeout(20):
await coordinator.initialization_future
apis = coordinator.appliance_apis.values()
_LOGGER.debug(f'Found {len(apis):d} appliance APIs')
entities = [
entity
for api in apis
for entity in api.entities
if isinstance(entity, GeErdButton)
]
_LOGGER.debug(f'Found {len(entities):d} buttons ')
async_add_entities(entities)

View File

@ -1,5 +1,4 @@
"""Constants for the gehome integration.""" """Constants for the gehome integration."""
from gehomesdk.clients.const import LOGIN_URL
DOMAIN = "ge_home" DOMAIN = "ge_home"
@ -13,4 +12,4 @@ RETRY_OFFLINE_COUNT = 5
SERVICE_SET_TIMER = "set_timer" SERVICE_SET_TIMER = "set_timer"
SERVICE_CLEAR_TIMER = "clear_timer" SERVICE_CLEAR_TIMER = "clear_timer"
SERVICE_SET_INT_VALUE = "set_int_value" SERVICE_SET_INT_VALUE = "set_int_value"

View File

@ -121,10 +121,10 @@ class ApplianceApi:
def build_entities_list(self) -> None: def build_entities_list(self) -> None:
"""Build the entities list, adding anything new.""" """Build the entities list, adding anything new."""
from ..entities import GeErdEntity from ..entities import GeErdEntity, GeErdButton
entities = [ entities = [
e for e in self.get_all_entities() e for e in self.get_all_entities()
if not isinstance(e, GeErdEntity) or e.erd_code in self.appliance.known_properties if not isinstance(e, GeErdEntity) or isinstance(e, GeErdButton) or e.erd_code in self.appliance.known_properties
] ]
for entity in entities: for entity in entities:

View File

@ -3,16 +3,23 @@ from typing import List
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from gehomesdk import ( from gehomesdk import (
GeAppliance,
ErdCode, ErdCode,
ErdApplianceType ErdApplianceType,
ErdCcmBrewSettings
) )
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from .base import ApplianceApi from .base import ApplianceApi
from ..entities import ( from ..entities import (
GeCcmPotNotPresentBinarySensor, GeCcmPotNotPresentBinarySensor,
GeErdSensor, GeErdSensor,
GeErdBinarySensor, GeErdBinarySensor,
GeCcm GeErdButton,
GeCcmBrewStrengthSelect,
GeCcmBrewTemperatureNumber,
GeCcmBrewCupsNumber,
GeCcmBrewSettingsButton
) )
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -22,23 +29,38 @@ class CcmApi(ApplianceApi):
"""API class for Cafe Coffee Maker objects""" """API class for Cafe Coffee Maker objects"""
APPLIANCE_TYPE = ErdApplianceType.CAFE_COFFEE_MAKER APPLIANCE_TYPE = ErdApplianceType.CAFE_COFFEE_MAKER
def __init__(self, coordinator: DataUpdateCoordinator, appliance: GeAppliance):
super().__init__(coordinator, appliance)
self._brew_strengh_entity = GeCcmBrewStrengthSelect(self)
self._brew_temperature_entity = GeCcmBrewTemperatureNumber(self)
self._brew_cups_entity = GeCcmBrewCupsNumber(self)
def get_all_entities(self) -> List[Entity]: def get_all_entities(self) -> List[Entity]:
base_entities = super().get_all_entities() base_entities = super().get_all_entities()
units = self.hass.config.units
ccm_entities = [ ccm_entities = [
GeErdBinarySensor(self, ErdCode.CCM_IS_BREWING, device_class_override="heat"), GeErdBinarySensor(self, ErdCode.CCM_IS_BREWING),
GeErdBinarySensor(self, ErdCode.CCM_IS_DESCALING), GeErdBinarySensor(self, ErdCode.CCM_IS_DESCALING),
GeErdSensor(self, ErdCode.CCM_BREW_STRENGTH), GeCcmBrewSettingsButton(self),
GeErdSensor(self, ErdCode.CCM_BREW_CUPS), GeErdButton(self, ErdCode.CCM_CANCEL_DESCALING),
GeErdSensor(self, ErdCode.CCM_BREW_TEMPERATURE), GeErdButton(self, ErdCode.CCM_START_DESCALING),
GeErdButton(self, ErdCode.CCM_CANCEL_BREWING),
self._brew_strengh_entity,
self._brew_temperature_entity,
self._brew_cups_entity,
GeErdSensor(self, ErdCode.CCM_CURRENT_WATER_TEMPERATURE), GeErdSensor(self, ErdCode.CCM_CURRENT_WATER_TEMPERATURE),
GeErdBinarySensor(self, ErdCode.CCM_OUT_OF_WATER, device_class_override="problem"), GeErdBinarySensor(self, ErdCode.CCM_OUT_OF_WATER, device_class_override="problem"),
GeCcmPotNotPresentBinarySensor(self, ErdCode.CCM_POT_PRESENT, device_class_override="problem"), GeCcmPotNotPresentBinarySensor(self, ErdCode.CCM_POT_PRESENT, device_class_override="problem")
GeCcm(self, units)
] ]
entities = base_entities + ccm_entities entities = base_entities + ccm_entities
return entities return entities
async def start_brewing(self) -> None:
"""Aggregate brew settings and start brewing."""
new_mode = ErdCcmBrewSettings(self._brew_cups_entity.value,
self._brew_strengh_entity.brew_strength,
self._brew_temperature_entity.brew_temperature)
await self.appliance.async_set_erd_value(ErdCode.CCM_BREW_SETTINGS, new_mode)

View File

@ -1,2 +1,5 @@
from .ge_ccm_pot_not_present_binary_sensor import GeCcmPotNotPresentBinarySensor from .ge_ccm_pot_not_present_binary_sensor import GeCcmPotNotPresentBinarySensor
from .ge_ccm import GeCcm from .ge_ccm_brew_strength import GeCcmBrewStrengthSelect
from .ge_ccm_brew_temperature import GeCcmBrewTemperatureNumber
from .ge_ccm_brew_cups import GeCcmBrewCupsNumber
from .ge_ccm_brew_settings import GeCcmBrewSettingsButton

View File

@ -1,8 +0,0 @@
from homeassistant.components.water_heater import (
SUPPORT_OPERATION_MODE,
SUPPORT_TARGET_TEMPERATURE
)
GE_CCM = SUPPORT_OPERATION_MODE | SUPPORT_TARGET_TEMPERATURE
MAX_CUPS = 10
MIN_CUPS = 2

View File

@ -1,150 +0,0 @@
"""GE Home Sensor Entities - Advantium"""
import logging
from typing import Any, Dict, List, Mapping, Optional, Set
from random import randrange
from gehomesdk import (
ErdCode,
ErdUnitType,
ErdCcmBrewSettings,
ErdCcmBrewStrength
)
from homeassistant.const import ATTR_TEMPERATURE
from homeassistant.util.unit_system import UnitSystem
from ...const import DOMAIN
from ...devices import ApplianceApi
from ..common import GeWaterHeater
from .const import *
from .ge_ccm_options import CcmBrewOptionsConverter
_LOGGER = logging.getLogger(__name__)
class GeCcm(GeWaterHeater):
"""GE Appliance Cafe Coffee Maker"""
icon = "mdi:coffee-maker"
def __init__(self, api: ApplianceApi, units: UnitSystem):
super().__init__(api)
self._options = CcmBrewOptionsConverter(units)
@property
def supported_features(self):
return GE_CCM
@property
def unique_id(self) -> str:
return f"{DOMAIN}_{self.serial_number}"
@property
def name(self) -> Optional[str]:
return f"{self.serial_number} Coffee Maker"
@property
def unit_type(self) -> Optional[ErdUnitType]:
try:
return self.appliance.get_erd_value(ErdCode.UNIT_TYPE)
except:
return None
@property
def current_temperature(self) -> Optional[int]:
return self.appliance.get_erd_value(ErdCode.CCM_CURRENT_WATER_TEMPERATURE)
@property
def is_brewing(self) -> bool:
return self.appliance.get_erd_value(ErdCode.CCM_IS_BREWING)
@property
def is_descaling(self) -> bool:
return self.appliance.get_erd_value(ErdCode.CCM_IS_DESCALING)
@property
def current_operation(self) -> Optional[str]:
try:
settings: ErdCcmBrewSettings = self.appliance.get_erd_value(ErdCode.CCM_BREW_SETTINGS)
if self.is_descaling:
return "Descale"
if not self.is_brewing:
return "Off"
return self._options.to_option_string(settings)
except:
return None
@property
def operation_list(self) -> List[str]:
return self._options.options
@property
def current_brew_setting(self) -> ErdCcmBrewSettings:
"""Get the current brew setting."""
return self.appliance.get_erd_value(ErdCode.CCM_BREW_SETTINGS)
@property
def target_temperature(self) -> Optional[int]:
"""Return the temperature we try to reach."""
try:
return self.appliance.get_erd_value(ErdCode.CCM_BREW_TEMPERATURE)
except:
pass
return None
@property
def min_temp(self) -> int:
"""Return the minimum temperature."""
min_temp, _, _ = self.appliance.get_erd_value(ErdCode.CCM_BREW_TEMPERATURE_RANGE)
return min_temp
@property
def max_temp(self) -> int:
"""Return the maximum temperature."""
_, max_temp, _ = self.appliance.get_erd_value(ErdCode.CCM_BREW_TEMPERATURE_RANGE)
return max_temp
@property
def extra_state_attributes(self) -> Optional[Mapping[str, Any]]:
data = {}
data["unit_type"] = self._stringify(self.unit_type)
return data
@property
def can_set_temperature(self) -> bool:
"""Indicates whether we can set the temperature based on the current mode"""
return not self.is_descaling
async def async_set_operation_mode(self, operation_mode: str):
"""Set the operation mode."""
#try to get the mode/setting for the selection
try:
if operation_mode not in ["Off","Descale"]:
new_mode = self._options.from_option_string(operation_mode)
new_mode = ErdCcmBrewSettings(new_mode.number_of_cups, new_mode.brew_strength, self.target_temperature)
await self.appliance.async_set_erd_value(ErdCode.CCM_BREW_SETTINGS, new_mode)
elif operation_mode == "Off":
await self.appliance.async_set_erd_value(ErdCode.CCM_CANCEL_BREWING, True)
await self.appliance.async_set_erd_value(ErdCode.CCM_CANCEL_DESCALING, True)
elif operation_mode == "Descale":
await self.appliance.async_set_erd_value(ErdCode.CCM_START_DESCALING, True)
except:
_LOGGER.error(f"Error Attempting to set mode to {operation_mode}.", exc_info=True)
async def async_set_temperature(self, **kwargs):
"""Set the brew temperature"""
target_temp = kwargs.get(ATTR_TEMPERATURE)
if target_temp is None:
return
# get the current strength/cups
strength: ErdCcmBrewStrength = self.appliance.get_erd_value(ErdCode.CCM_BREW_STRENGTH)
cups: int = self.appliance.get_erd_value(ErdCode.CCM_BREW_CUPS)
new_mode = ErdCcmBrewSettings(cups, strength, target_temp)
await self.appliance.async_set_erd_value(ErdCode.CCM_BREW_SETTINGS, new_mode)

View File

@ -0,0 +1,19 @@
from gehomesdk import ErdCode
from ...devices import ApplianceApi
from ..common import GeErdNumber
from .ge_ccm_cached_value import GeCcmCachedValue
class GeCcmBrewCupsNumber(GeErdNumber, GeCcmCachedValue):
def __init__(self, api: ApplianceApi):
GeErdNumber.__init__(self, api = api, erd_code = ErdCode.CCM_BREW_CUPS, min_value=1, max_value=10, mode="box")
GeCcmCachedValue.__init__(self)
self._set_value = None
async def async_set_value(self, value):
GeCcmCachedValue.set_value(self, value)
self.schedule_update_ha_state()
@property
def value(self):
return self.get_value(device_value = super().value)

View File

@ -0,0 +1,13 @@
from gehomesdk import ErdCode
from ...devices import ApplianceApi
from ..common import GeErdButton
class GeCcmBrewSettingsButton(GeErdButton):
def __init__(self, api: ApplianceApi):
super().__init__(api, erd_code=ErdCode.CCM_BREW_SETTINGS)
async def async_press(self) -> None:
"""Handle the button press."""
# Forward the call up to the Coffee Maker device to handle
await self.api.start_brewing()

View File

@ -0,0 +1,47 @@
import logging
from typing import List, Any, Optional
from gehomesdk import ErdCode, ErdCcmBrewStrength
from ...devices import ApplianceApi
from ..common import GeErdSelect, OptionsConverter
from .ge_ccm_cached_value import GeCcmCachedValue
_LOGGER = logging.getLogger(__name__)
class GeCcmBrewStrengthOptionsConverter(OptionsConverter):
def __init__(self):
self._default = ErdCcmBrewStrength.MEDIUM
@property
def options(self) -> List[str]:
return [i.stringify() for i in [ErdCcmBrewStrength.LIGHT, ErdCcmBrewStrength.MEDIUM, ErdCcmBrewStrength.BOLD, ErdCcmBrewStrength.GOLD]]
def from_option_string(self, value: str) -> Any:
try:
return ErdCcmBrewStrength[value.upper()]
except:
_LOGGER.warn(f"Could not set brew strength to {value.upper()}")
return self._default
def to_option_string(self, value: ErdCcmBrewStrength) -> Optional[str]:
try:
return value.stringify()
except:
return self._default.stringify()
class GeCcmBrewStrengthSelect(GeErdSelect, GeCcmCachedValue):
def __init__(self, api: ApplianceApi):
GeErdSelect.__init__(self, api = api, erd_code = ErdCode.CCM_BREW_STRENGTH, converter = GeCcmBrewStrengthOptionsConverter())
GeCcmCachedValue.__init__(self)
@property
def brew_strength(self) -> ErdCcmBrewStrength:
return self._converter.from_option_string(self.current_option)
async def async_select_option(self, value):
GeCcmCachedValue.set_value(self, value)
self.schedule_update_ha_state()
@property
def current_option(self):
return self.get_value(device_value = super().current_option)

View File

@ -0,0 +1,22 @@
from gehomesdk import ErdCode
from ...devices import ApplianceApi
from ..common import GeErdNumber
from .ge_ccm_cached_value import GeCcmCachedValue
class GeCcmBrewTemperatureNumber(GeErdNumber, GeCcmCachedValue):
def __init__(self, api: ApplianceApi):
min_temp, max_temp, _ = api.appliance.get_erd_value(ErdCode.CCM_BREW_TEMPERATURE_RANGE)
GeErdNumber.__init__(self, api = api, erd_code = ErdCode.CCM_BREW_TEMPERATURE, min_value=min_temp, max_value=max_temp, mode="slider")
GeCcmCachedValue.__init__(self)
async def async_set_value(self, value):
GeCcmCachedValue.set_value(self, value)
self.schedule_update_ha_state()
@property
def value(self):
return int(self.get_value(device_value = super().value))
@property
def brew_temperature(self) -> int:
return self.value

View File

@ -0,0 +1,20 @@
class GeCcmCachedValue():
def __init__(self):
self._set_value = None
self._last_device_value = None
def get_value(self, device_value):
# If the last device value is different from the current one, return the device value which overrides the set value
if self._last_device_value != device_value:
self._last_device_value = device_value
self._set_value = None
return device_value
if self._set_value is not None:
return self._set_value
return device_value
def set_value(self, set_value):
self._set_value = set_value

View File

@ -1,61 +0,0 @@
import logging
from typing import List, Any, NamedTuple, Optional
from gehomesdk import ErdCcmBrewStrength, ErdCcmBrewSettings
from homeassistant.const import TEMP_FAHRENHEIT
from homeassistant.util.unit_system import UnitSystem
from custom_components.ge_home.entities.ccm.const import MAX_CUPS, MIN_CUPS
from ..common import OptionsConverter
_LOGGER = logging.getLogger(__name__)
class CcmBrewOption(NamedTuple):
strength: ErdCcmBrewStrength
cups: int
def stringify(self):
return f"{self.strength.stringify()} -- {self.cups} cups"
class CcmBrewOptionsConverter(OptionsConverter):
def __init__(self, units: UnitSystem):
super().__init__()
self._units = units
self._options = self._build_options()
@property
def options(self) -> List[str]:
options = ["Off"]
options.extend([i.stringify() for i in self._options])
options.extend(["Descale"])
return options
def from_option_string(self, value: str) -> Optional[ErdCcmBrewSettings]:
try:
if value in ["Off","Descale"]:
return None
s = value.split(" -- ")[0].upper()
c = value.split(" -- ")[1].replace(" cups","")
return ErdCcmBrewSettings(int(c), ErdCcmBrewStrength[s], 200)
except:
_LOGGER.error(f"Could not convert brew options '{value}'", exc_info=True)
#return a default if we can't interpret it
return ErdCcmBrewSettings(4, ErdCcmBrewStrength.MEDIUM, 200)
def to_option_string(self, value: ErdCcmBrewSettings) -> Optional[str]:
try:
o = CcmBrewOption(value.brew_strength, value.number_of_cups)
return o.stringify()
except:
#return a default if we can't interpret it
return CcmBrewOption(ErdCcmBrewStrength.MEDIUM, 4)
def _build_options(self) -> List[CcmBrewOption]:
options = []
for s in filter(lambda x: x != ErdCcmBrewStrength.UNKNOWN, ErdCcmBrewStrength):
for c in range(MIN_CUPS, MAX_CUPS, 2):
options.append(CcmBrewOption(s, c))
return options

View File

@ -9,6 +9,8 @@ from .ge_erd_light import GeErdLight
from .ge_erd_timer_sensor import GeErdTimerSensor from .ge_erd_timer_sensor import GeErdTimerSensor
from .ge_erd_property_sensor import GeErdPropertySensor from .ge_erd_property_sensor import GeErdPropertySensor
from .ge_erd_switch import GeErdSwitch from .ge_erd_switch import GeErdSwitch
from .ge_erd_button import GeErdButton
from .ge_erd_number import GeErdNumber
from .ge_water_heater import GeWaterHeater from .ge_water_heater import GeWaterHeater
from .ge_erd_select import GeErdSelect from .ge_erd_select import GeErdSelect
from .ge_climate import GeClimate from .ge_climate import GeClimate

View File

@ -0,0 +1,17 @@
from typing import Optional
from homeassistant.components.button import ButtonEntity
from gehomesdk import ErdCodeType
from ...devices import ApplianceApi
from .ge_erd_entity import GeErdEntity
class GeErdButton(GeErdEntity, ButtonEntity):
def __init__(self, api: ApplianceApi, erd_code: ErdCodeType, erd_override: str = None):
super().__init__(api, erd_code, erd_override=erd_override)
"""GE Entity for buttons"""
async def async_press(self) -> None:
"""Handle the button press."""
await self.appliance.async_set_erd_value(self.erd_code, True)

View File

@ -83,7 +83,7 @@ class GeErdEntity(GeEntity):
try: try:
value = self.appliance.get_erd_value(ErdCode.TEMPERATURE_UNIT) value = self.appliance.get_erd_value(ErdCode.TEMPERATURE_UNIT)
except KeyError: except KeyError:
return None return ErdMeasurementUnits.Imperial
return value return value
def _get_icon(self): def _get_icon(self):
@ -142,6 +142,8 @@ class GeErdEntity(GeEntity):
if self.erd_code_class == ErdCodeClass.OIM_SENSOR: if self.erd_code_class == ErdCodeClass.OIM_SENSOR:
return "mdi:snowflake" return "mdi:snowflake"
if self.erd_code_class == ErdCodeClass.WATERSOFTENER_SENSOR: if self.erd_code_class == ErdCodeClass.WATERSOFTENER_SENSOR:
return "mdi:water" return "mdi:water"
if self.erd_code_class == ErdCodeClass.CCM_SENSOR:
return "mdi:coffee-maker"
return None return None

View File

@ -0,0 +1,128 @@
import logging
from typing import Optional
from gehomesdk.erd.erd_data_type import ErdDataType
from homeassistant.components.number import NumberEntity
from homeassistant.const import (
DEVICE_CLASS_TEMPERATURE,
TEMP_FAHRENHEIT,
)
from gehomesdk import ErdCodeType, ErdCodeClass
from .ge_erd_entity import GeErdEntity
from ...devices import ApplianceApi
_LOGGER = logging.getLogger(__name__)
class GeErdNumber(GeErdEntity, NumberEntity):
"""GE Entity for numbers"""
def __init__(
self,
api: ApplianceApi,
erd_code: ErdCodeType,
erd_override: str = None,
icon_override: str = None,
device_class_override: str = None,
uom_override: str = None,
data_type_override: ErdDataType = None,
min_value: float = 1,
max_value: float = 100,
step_value: float = 1,
mode: str = "auto"
):
super().__init__(api, erd_code, erd_override, icon_override, device_class_override)
self._uom_override = uom_override
self._data_type_override = data_type_override
self._min_value = min_value
self._max_value = max_value
self._step_value = step_value
self._mode = mode
@property
def value(self):
try:
value = self.appliance.get_erd_value(self.erd_code)
return self._convert_value_from_device(value)
except KeyError:
return None
@property
def unit_of_measurement(self) -> Optional[str]:
return self._get_uom()
@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 min_value(self) -> float:
return self._convert_value_from_device(self._min_value)
@property
def max_value(self) -> float:
return self._convert_value_from_device(self._max_value)
@property
def step(self) -> float:
return self._step_value
@property
def mode(self) -> float:
return self._mode
def _convert_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.device_class == DEVICE_CLASS_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 TEMP_FAHRENHEIT
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 DEVICE_CLASS_TEMPERATURE
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 async_set_value(self, value):
"""Sets the ERD value, assumes that the data type is correct"""
if self._data_type == ErdDataType.INT:
value = int(round(value))
try:
await self.appliance.async_set_erd_value(self.erd_code, value)
except:
_LOGGER.warning(f"Could not set {self.name} to {value}")

View File

@ -9,11 +9,9 @@ from homeassistant.const import (
DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_TEMPERATURE,
DEVICE_CLASS_BATTERY, DEVICE_CLASS_BATTERY,
DEVICE_CLASS_POWER_FACTOR, DEVICE_CLASS_POWER_FACTOR,
DEVICE_CLASS_TIMESTAMP,
TEMP_CELSIUS,
TEMP_FAHRENHEIT, TEMP_FAHRENHEIT,
) )
from gehomesdk import ErdCode, ErdCodeType, ErdCodeClass, ErdMeasurementUnits from gehomesdk import ErdCodeType, ErdCodeClass
from .ge_erd_entity import GeErdEntity from .ge_erd_entity import GeErdEntity
from ...devices import ApplianceApi from ...devices import ApplianceApi
@ -45,7 +43,7 @@ class GeErdSensor(GeErdEntity, SensorEntity):
# if it's a numeric data type, return it directly # if it's a numeric data type, return it directly
if self._data_type in [ErdDataType.INT, ErdDataType.FLOAT]: if self._data_type in [ErdDataType.INT, ErdDataType.FLOAT]:
return value return self._convert_numeric_value_from_device(value)
# otherwise, return a stringified version # otherwise, return a stringified version
# TODO: perhaps enhance so that there's a list of variables available # TODO: perhaps enhance so that there's a list of variables available
@ -80,6 +78,14 @@ class GeErdSensor(GeErdEntity, SensorEntity):
# return TEMP_CELSIUS # return TEMP_CELSIUS
#return TEMP_FAHRENHEIT #return TEMP_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): def _get_uom(self):
"""Select appropriate units""" """Select appropriate units"""

View File

@ -3,7 +3,7 @@
"name": "GE Home (SmartHQ)", "name": "GE Home (SmartHQ)",
"config_flow": true, "config_flow": true,
"documentation": "https://github.com/simbaja/ha_gehome", "documentation": "https://github.com/simbaja/ha_gehome",
"requirements": ["gehomesdk==0.4.21","magicattr==0.1.5"], "requirements": ["gehomesdk==0.4.22","magicattr==0.1.5","slixmpp==1.7.1"],
"codeowners": ["@simbaja"], "codeowners": ["@simbaja"],
"version": "0.6.0" "version": "0.6.0"
} }

View File

@ -0,0 +1,33 @@
"""GE Home Number Entities"""
import async_timeout
import logging
from typing import Callable
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from .const import DOMAIN
from .entities import GeErdNumber
from .update_coordinator import GeHomeUpdateCoordinator
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: Callable):
"""GE Home numbers."""
coordinator: GeHomeUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
# This should be a NOP, but let's be safe
with async_timeout.timeout(20):
await coordinator.initialization_future
apis = coordinator.appliance_apis.values()
_LOGGER.debug(f'Found {len(apis):d} appliance APIs')
entities = [
entity
for api in apis
for entity in api.entities
if isinstance(entity, GeErdNumber)
]
_LOGGER.debug(f'Found {len(entities):d} numbers ')
async_add_entities(entities)

View File

@ -34,7 +34,7 @@ from .const import (
) )
from .devices import ApplianceApi, get_appliance_api_type from .devices import ApplianceApi, get_appliance_api_type
PLATFORMS = ["binary_sensor", "sensor", "switch", "water_heater", "select", "climate", "light"] PLATFORMS = ["binary_sensor", "sensor", "switch", "water_heater", "select", "climate", "light", "button", "number"]
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -261,6 +261,7 @@ class GeHomeUpdateCoordinator(DataUpdateCoordinator):
api = self.appliance_apis[appliance.mac_addr] api = self.appliance_apis[appliance.mac_addr]
except KeyError: except KeyError:
return return
for entity in api.entities: for entity in api.entities:
if entity.enabled: if entity.enabled:
_LOGGER.debug(f"Updating {entity} ({entity.unique_id}, {entity.entity_id})") _LOGGER.debug(f"Updating {entity} ({entity.unique_id}, {entity.entity_id})")