From 207a82937a51c7db9e9ab0561caea78217136f40 Mon Sep 17 00:00:00 2001 From: Rob Schmidt Date: Sun, 10 Jul 2022 16:36:26 -0700 Subject: [PATCH] Add support for Built-In AC Unit Built-In AC unit operation and function is similar to a WAC. `gehomesdk` version bumped from 0.4.25 to 0.4.27 to include latest ErdApplianceType enum. --- custom_components/ge_home/climate.py | 2 +- custom_components/ge_home/devices/__init__.py | 3 ++ custom_components/ge_home/devices/biac.py | 33 ++++++++++++++ .../ge_home/entities/ac/__init__.py | 3 +- .../ge_home/entities/ac/ge_biac_climate.py | 45 +++++++++++++++++++ .../ge_home/entities/common/ge_climate.py | 2 +- custom_components/ge_home/manifest.json | 2 +- 7 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 custom_components/ge_home/devices/biac.py create mode 100644 custom_components/ge_home/entities/ac/ge_biac_climate.py diff --git a/custom_components/ge_home/climate.py b/custom_components/ge_home/climate.py index 3694a09..fbdb94d 100644 --- a/custom_components/ge_home/climate.py +++ b/custom_components/ge_home/climate.py @@ -14,7 +14,7 @@ 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 Water Heaters.""" + """GE Climate Devices.""" _LOGGER.debug('Adding GE Climate Entities') coordinator: GeHomeUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id] diff --git a/custom_components/ge_home/devices/__init__.py b/custom_components/ge_home/devices/__init__.py index 1acc228..5c8332f 100644 --- a/custom_components/ge_home/devices/__init__.py +++ b/custom_components/ge_home/devices/__init__.py @@ -15,6 +15,7 @@ from .advantium import AdvantiumApi from .wac import WacApi from .sac import SacApi from .pac import PacApi +from .biac import BiacApi from .hood import HoodApi from .microwave import MicrowaveApi from .water_softener import WaterSoftenerApi @@ -51,6 +52,8 @@ def get_appliance_api_type(appliance_type: ErdApplianceType) -> Type: return SacApi if appliance_type == ErdApplianceType.PORTABLE_AIR_CONDITIONER: return PacApi + if appliance_type == ErdApplianceType.BUILT_IN_AIR_CONDITIONER: + return BiacApi if appliance_type == ErdApplianceType.HOOD: return HoodApi if appliance_type == ErdApplianceType.MICROWAVE: diff --git a/custom_components/ge_home/devices/biac.py b/custom_components/ge_home/devices/biac.py new file mode 100644 index 0000000..d22eb17 --- /dev/null +++ b/custom_components/ge_home/devices/biac.py @@ -0,0 +1,33 @@ +import logging +from typing import List + +from homeassistant.helpers.entity import Entity +from gehomesdk.erd import ErdCode, ErdApplianceType + +from .base import ApplianceApi +from ..entities import GeBiacClimate, GeErdSensor, GeErdBinarySensor, GeErdSwitch, ErdOnOffBoolConverter + +_LOGGER = logging.getLogger(__name__) + + +class BiacApi(ApplianceApi): + """API class for Built-In AC objects""" + APPLIANCE_TYPE = ErdApplianceType.BUILT_IN_AIR_CONDITIONER + + def get_all_entities(self) -> List[Entity]: + base_entities = super().get_all_entities() + + biac_entities = [ + GeBiacClimate(self), + GeErdSensor(self, ErdCode.AC_TARGET_TEMPERATURE), + GeErdSensor(self, ErdCode.AC_AMBIENT_TEMPERATURE), + GeErdSensor(self, ErdCode.AC_FAN_SETTING, icon_override="mdi:fan"), + GeErdSensor(self, ErdCode.AC_OPERATION_MODE), + GeErdSwitch(self, ErdCode.AC_POWER_STATUS, bool_converter=ErdOnOffBoolConverter(), icon_on_override="mdi:power-on", icon_off_override="mdi:power-off"), + GeErdBinarySensor(self, ErdCode.AC_FILTER_STATUS, device_class_override="problem"), + GeErdSensor(self, ErdCode.WAC_DEMAND_RESPONSE_STATE), + GeErdSensor(self, ErdCode.WAC_DEMAND_RESPONSE_POWER, uom_override="kW"), + ] + entities = base_entities + biac_entities + return entities + diff --git a/custom_components/ge_home/entities/ac/__init__.py b/custom_components/ge_home/entities/ac/__init__.py index 0f2e6ad..aefb995 100644 --- a/custom_components/ge_home/entities/ac/__init__.py +++ b/custom_components/ge_home/entities/ac/__init__.py @@ -1,3 +1,4 @@ from .ge_wac_climate import GeWacClimate from .ge_sac_climate import GeSacClimate -from .ge_pac_climate import GePacClimate \ No newline at end of file +from .ge_pac_climate import GePacClimate +from .ge_biac_climate import GeBiacClimate diff --git a/custom_components/ge_home/entities/ac/ge_biac_climate.py b/custom_components/ge_home/entities/ac/ge_biac_climate.py new file mode 100644 index 0000000..f3b7453 --- /dev/null +++ b/custom_components/ge_home/entities/ac/ge_biac_climate.py @@ -0,0 +1,45 @@ +import logging +from typing import Any, List, Optional + +from homeassistant.components.climate.const import ( + HVAC_MODE_AUTO, + HVAC_MODE_COOL, + HVAC_MODE_FAN_ONLY, +) +from gehomesdk import ErdAcOperationMode +from ...devices import ApplianceApi +from ..common import GeClimate, OptionsConverter +from .fan_mode_options import AcFanModeOptionsConverter, AcFanOnlyFanModeOptionsConverter + +_LOGGER = logging.getLogger(__name__) + +class BiacHvacModeOptionsConverter(OptionsConverter): + @property + def options(self) -> List[str]: + return [HVAC_MODE_AUTO, HVAC_MODE_COOL, HVAC_MODE_FAN_ONLY] + def from_option_string(self, value: str) -> Any: + try: + return { + HVAC_MODE_AUTO: ErdAcOperationMode.ENERGY_SAVER, + HVAC_MODE_COOL: ErdAcOperationMode.COOL, + HVAC_MODE_FAN_ONLY: ErdAcOperationMode.FAN_ONLY + }.get(value) + except: + _LOGGER.warn(f"Could not set HVAC mode to {value.upper()}") + return ErdAcOperationMode.COOL + def to_option_string(self, value: Any) -> Optional[str]: + try: + return { + ErdAcOperationMode.ENERGY_SAVER: HVAC_MODE_AUTO, + ErdAcOperationMode.AUTO: HVAC_MODE_AUTO, + ErdAcOperationMode.COOL: HVAC_MODE_COOL, + ErdAcOperationMode.FAN_ONLY: HVAC_MODE_FAN_ONLY + }.get(value) + except: + _LOGGER.warn(f"Could not determine operation mode mapping for {value}") + return HVAC_MODE_COOL + +class GeBiacClimate(GeClimate): + """Class for Built-In AC units""" + def __init__(self, api: ApplianceApi): + super().__init__(api, BiacHvacModeOptionsConverter(), AcFanModeOptionsConverter(), AcFanOnlyFanModeOptionsConverter()) diff --git a/custom_components/ge_home/entities/common/ge_climate.py b/custom_components/ge_home/entities/common/ge_climate.py index fc48f93..7f44edb 100644 --- a/custom_components/ge_home/entities/common/ge_climate.py +++ b/custom_components/ge_home/entities/common/ge_climate.py @@ -191,4 +191,4 @@ class GeClimate(GeEntity, ClimateEntity): return (temperature_f - 32.0) * (5/9) def _get_icon(self) -> Optional[str]: - return "mdi:air-conditioner" \ No newline at end of file + return "mdi:air-conditioner" diff --git a/custom_components/ge_home/manifest.json b/custom_components/ge_home/manifest.json index 048a3cc..330faec 100644 --- a/custom_components/ge_home/manifest.json +++ b/custom_components/ge_home/manifest.json @@ -3,7 +3,7 @@ "name": "GE Home (SmartHQ)", "config_flow": true, "documentation": "https://github.com/simbaja/ha_gehome", - "requirements": ["gehomesdk==0.4.25","magicattr==0.1.5","slixmpp==1.7.1"], + "requirements": ["gehomesdk==0.4.27","magicattr==0.1.6","slixmpp==1.8.2"], "codeowners": ["@simbaja"], "version": "0.6.1" }