Initial commit to new repo
This commit is contained in:
commit
1173160cfd
81
__init__.py
Normal file
81
__init__.py
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
"""The ge_home integration."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.const import CONF_REGION
|
||||||
|
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
||||||
|
from .const import DOMAIN
|
||||||
|
from .exceptions import HaAuthError, HaCannotConnect
|
||||||
|
from .update_coordinator import GeHomeUpdateCoordinator
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({})}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup(hass: HomeAssistant, config: dict):
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry):
|
||||||
|
"""Migrate old entry."""
|
||||||
|
_LOGGER.debug("Migrating from version %s", config_entry.version)
|
||||||
|
|
||||||
|
if config_entry.version == 1:
|
||||||
|
|
||||||
|
new = {**config_entry.data}
|
||||||
|
new[CONF_REGION] = "US"
|
||||||
|
|
||||||
|
config_entry.version = 2
|
||||||
|
hass.config_entries.async_update_entry(config_entry, data=new)
|
||||||
|
|
||||||
|
_LOGGER.info("Migration to version %s successful", config_entry.version)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
|
"""Set up ge_home from a config entry."""
|
||||||
|
hass.data.setdefault(DOMAIN, {})
|
||||||
|
|
||||||
|
#try to get existing coordinator
|
||||||
|
existing: GeHomeUpdateCoordinator = dict.get(hass.data[DOMAIN],entry.entry_id)
|
||||||
|
|
||||||
|
coordinator = GeHomeUpdateCoordinator(hass, entry)
|
||||||
|
hass.data[DOMAIN][entry.entry_id] = coordinator
|
||||||
|
|
||||||
|
# try to unload the existing coordinator
|
||||||
|
try:
|
||||||
|
if existing:
|
||||||
|
await coordinator.async_reset()
|
||||||
|
except:
|
||||||
|
_LOGGER.warning("Could not reset existing coordinator.")
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not await coordinator.async_setup():
|
||||||
|
return False
|
||||||
|
except HaCannotConnect:
|
||||||
|
raise ConfigEntryNotReady("Could not connect to SmartHQ")
|
||||||
|
except HaAuthError:
|
||||||
|
raise ConfigEntryAuthFailed("Could not authenticate to SmartHQ")
|
||||||
|
|
||||||
|
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, coordinator.shutdown)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
|
"""Unload a config entry."""
|
||||||
|
coordinator: GeHomeUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
ok = await coordinator.async_reset()
|
||||||
|
if ok:
|
||||||
|
hass.data[DOMAIN].pop(entry.entry_id)
|
||||||
|
|
||||||
|
return ok
|
||||||
|
|
||||||
|
|
||||||
|
async def async_update_options(hass, config_entry):
|
||||||
|
"""Update options."""
|
||||||
|
await hass.config_entries.async_reload(config_entry.entry_id)
|
||||||
BIN
__pycache__/__init__.cpython-313.pyc
Normal file
BIN
__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/binary_sensor.cpython-313.pyc
Normal file
BIN
__pycache__/binary_sensor.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/button.cpython-313.pyc
Normal file
BIN
__pycache__/button.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/climate.cpython-313.pyc
Normal file
BIN
__pycache__/climate.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/config_flow.cpython-313.pyc
Normal file
BIN
__pycache__/config_flow.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/const.cpython-313.pyc
Normal file
BIN
__pycache__/const.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/exceptions.cpython-313.pyc
Normal file
BIN
__pycache__/exceptions.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/humidifier.cpython-313.pyc
Normal file
BIN
__pycache__/humidifier.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/light.cpython-313.pyc
Normal file
BIN
__pycache__/light.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/number.cpython-313.pyc
Normal file
BIN
__pycache__/number.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/select.cpython-313.pyc
Normal file
BIN
__pycache__/select.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/sensor.cpython-313.pyc
Normal file
BIN
__pycache__/sensor.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/switch.cpython-313.pyc
Normal file
BIN
__pycache__/switch.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/update_coordinator.cpython-313.pyc
Normal file
BIN
__pycache__/update_coordinator.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/water_heater.cpython-313.pyc
Normal file
BIN
__pycache__/water_heater.cpython-313.pyc
Normal file
Binary file not shown.
47
binary_sensor.py
Normal file
47
binary_sensor.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
"""GE Home Sensor Entities"""
|
||||||
|
import logging
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
from homeassistant.components.switch import SwitchEntity
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
from .devices import ApplianceApi
|
||||||
|
from .entities import GeErdBinarySensor
|
||||||
|
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 binary sensors."""
|
||||||
|
|
||||||
|
_LOGGER.debug('Adding GE Binary Sensor Entities')
|
||||||
|
coordinator: GeHomeUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
||||||
|
registry = er.async_get(hass)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_devices_discovered(apis: list[ApplianceApi]):
|
||||||
|
_LOGGER.debug(f'Found {len(apis):d} appliance APIs')
|
||||||
|
|
||||||
|
entities = [
|
||||||
|
entity
|
||||||
|
for api in apis
|
||||||
|
for entity in api.entities
|
||||||
|
if isinstance(entity, GeErdBinarySensor) and not isinstance(entity, SwitchEntity)
|
||||||
|
if not registry.async_is_registered(entity.entity_id)
|
||||||
|
]
|
||||||
|
_LOGGER.debug(f'Found {len(entities):d} unregistered binary sensors')
|
||||||
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
#if we're already initialized at this point, call device
|
||||||
|
#discovery directly, otherwise add a callback based on the
|
||||||
|
#ready signal
|
||||||
|
if coordinator.initialized:
|
||||||
|
async_devices_discovered(coordinator.appliance_apis.values())
|
||||||
|
else:
|
||||||
|
# add the ready signal and register the remove callback
|
||||||
|
coordinator.add_signal_remove_callback(
|
||||||
|
async_dispatcher_connect(hass, coordinator.signal_ready, async_devices_discovered))
|
||||||
45
button.py
Normal file
45
button.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
"""GE Home Button Entities"""
|
||||||
|
import logging
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
from .devices import ApplianceApi
|
||||||
|
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."""
|
||||||
|
|
||||||
|
_LOGGER.debug('Adding GE Button Entities')
|
||||||
|
coordinator: GeHomeUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
||||||
|
registry = er.async_get(hass)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_devices_discovered(apis: list[ApplianceApi]):
|
||||||
|
_LOGGER.debug(f'Found {len(apis):d} appliance APIs')
|
||||||
|
entities = [
|
||||||
|
entity
|
||||||
|
for api in apis
|
||||||
|
for entity in api.entities
|
||||||
|
if isinstance(entity, GeErdButton)
|
||||||
|
if not registry.async_is_registered(entity.entity_id)
|
||||||
|
]
|
||||||
|
_LOGGER.debug(f'Found {len(entities):d} unregistered buttons ')
|
||||||
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
#if we're already initialized at this point, call device
|
||||||
|
#discovery directly, otherwise add a callback based on the
|
||||||
|
#ready signal
|
||||||
|
if coordinator.initialized:
|
||||||
|
async_devices_discovered(coordinator.appliance_apis.values())
|
||||||
|
else:
|
||||||
|
# add the ready signal and register the remove callback
|
||||||
|
coordinator.add_signal_remove_callback(
|
||||||
|
async_dispatcher_connect(hass, coordinator.signal_ready, async_devices_discovered))
|
||||||
47
climate.py
Normal file
47
climate.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
"""GE Home Climate Entities"""
|
||||||
|
import logging
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
from homeassistant.components.climate import ClimateEntity
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
|
||||||
|
from .entities import GeClimate
|
||||||
|
from .const import DOMAIN
|
||||||
|
from .devices import ApplianceApi
|
||||||
|
from .update_coordinator import GeHomeUpdateCoordinator
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: Callable):
|
||||||
|
"""GE Climate Devices."""
|
||||||
|
|
||||||
|
_LOGGER.debug('Adding GE Climate Entities')
|
||||||
|
coordinator: GeHomeUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
||||||
|
registry = er.async_get(hass)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_devices_discovered(apis: list[ApplianceApi]):
|
||||||
|
_LOGGER.debug(f'Found {len(apis):d} appliance APIs')
|
||||||
|
|
||||||
|
entities = [
|
||||||
|
entity
|
||||||
|
for api in apis
|
||||||
|
for entity in api.entities
|
||||||
|
if isinstance(entity, GeClimate)
|
||||||
|
if not registry.async_is_registered(entity.entity_id)
|
||||||
|
]
|
||||||
|
_LOGGER.debug(f'Found {len(entities):d} unregistered climate entities')
|
||||||
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
#if we're already initialized at this point, call device
|
||||||
|
#discovery directly, otherwise add a callback based on the
|
||||||
|
#ready signal
|
||||||
|
if coordinator.initialized:
|
||||||
|
async_devices_discovered(coordinator.appliance_apis.values())
|
||||||
|
else:
|
||||||
|
# add the ready signal and register the remove callback
|
||||||
|
coordinator.add_signal_remove_callback(
|
||||||
|
async_dispatcher_connect(hass, coordinator.signal_ready, async_devices_discovered))
|
||||||
129
config_flow.py
Normal file
129
config_flow.py
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
"""Config flow for GE Home integration."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from typing import Dict, Optional
|
||||||
|
|
||||||
|
import aiohttp
|
||||||
|
import asyncio
|
||||||
|
import async_timeout
|
||||||
|
|
||||||
|
from gehomesdk import (
|
||||||
|
GeAuthFailedError,
|
||||||
|
GeNotAuthenticatedError,
|
||||||
|
GeGeneralServerError,
|
||||||
|
async_get_oauth2_token,
|
||||||
|
LOGIN_REGIONS
|
||||||
|
)
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant import config_entries, core
|
||||||
|
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, CONF_REGION
|
||||||
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
|
|
||||||
|
from .const import DOMAIN # pylint:disable=unused-import
|
||||||
|
from .exceptions import HaAuthError, HaCannotConnect, HaAlreadyConfigured
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
GEHOME_SCHEMA = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(CONF_USERNAME): str,
|
||||||
|
vol.Required(CONF_PASSWORD): str,
|
||||||
|
vol.Required(CONF_REGION): vol.In(LOGIN_REGIONS.keys())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
async def validate_input(hass: core.HomeAssistant, data):
|
||||||
|
"""Validate the user input allows us to connect."""
|
||||||
|
|
||||||
|
session = async_get_clientsession(hass)
|
||||||
|
|
||||||
|
# noinspection PyBroadException
|
||||||
|
try:
|
||||||
|
async with async_timeout.timeout(10):
|
||||||
|
_ = await async_get_oauth2_token(session, data[CONF_USERNAME], data[CONF_PASSWORD], data[CONF_REGION])
|
||||||
|
except (asyncio.TimeoutError, aiohttp.ClientError):
|
||||||
|
raise HaCannotConnect('Connection failure')
|
||||||
|
except (GeAuthFailedError, GeNotAuthenticatedError):
|
||||||
|
raise HaAuthError('Authentication failure')
|
||||||
|
except GeGeneralServerError:
|
||||||
|
raise HaCannotConnect('Cannot connect (server error)')
|
||||||
|
except Exception as exc:
|
||||||
|
_LOGGER.exception("Unknown connection failure", exc_info=exc)
|
||||||
|
raise HaCannotConnect('Unknown connection failure')
|
||||||
|
|
||||||
|
# Return info that you want to store in the config entry.
|
||||||
|
return {"title": f"{data[CONF_USERNAME]:s}"}
|
||||||
|
|
||||||
|
class GeHomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
|
"""Handle a config flow for GE Home."""
|
||||||
|
|
||||||
|
VERSION = 2
|
||||||
|
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_PUSH
|
||||||
|
|
||||||
|
async def _async_validate_input(self, user_input):
|
||||||
|
"""Validate form input."""
|
||||||
|
errors = {}
|
||||||
|
info = None
|
||||||
|
|
||||||
|
if user_input is not None:
|
||||||
|
# noinspection PyBroadException
|
||||||
|
try:
|
||||||
|
info = await validate_input(self.hass, user_input)
|
||||||
|
except HaCannotConnect:
|
||||||
|
errors["base"] = "cannot_connect"
|
||||||
|
except HaAuthError:
|
||||||
|
errors["base"] = "invalid_auth"
|
||||||
|
except Exception: # pylint: disable=broad-except
|
||||||
|
_LOGGER.exception("Unexpected exception")
|
||||||
|
errors["base"] = "unknown"
|
||||||
|
return info, errors
|
||||||
|
|
||||||
|
def _ensure_not_configured(self, username: str):
|
||||||
|
"""Ensure that we haven't configured this account"""
|
||||||
|
existing_accounts = {
|
||||||
|
entry.data[CONF_USERNAME] for entry in self._async_current_entries()
|
||||||
|
}
|
||||||
|
_LOGGER.debug(f"Existing accounts: {existing_accounts}")
|
||||||
|
if username in existing_accounts:
|
||||||
|
raise HaAlreadyConfigured
|
||||||
|
|
||||||
|
async def async_step_user(self, user_input: Optional[Dict] = None):
|
||||||
|
"""Handle the initial step."""
|
||||||
|
errors = {}
|
||||||
|
if user_input is not None:
|
||||||
|
try:
|
||||||
|
self._ensure_not_configured(user_input[CONF_USERNAME])
|
||||||
|
info, errors = await self._async_validate_input(user_input)
|
||||||
|
if info:
|
||||||
|
return self.async_create_entry(title=info["title"], data=user_input)
|
||||||
|
except HaAlreadyConfigured:
|
||||||
|
return self.async_abort(reason="already_configured_account")
|
||||||
|
|
||||||
|
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id="user", data_schema=GEHOME_SCHEMA, errors=errors
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_step_reauth(self, user_input: Optional[dict] = None):
|
||||||
|
"""Handle re-auth if login is invalid."""
|
||||||
|
errors = {}
|
||||||
|
|
||||||
|
if user_input is not None:
|
||||||
|
_, errors = await self._async_validate_input(user_input)
|
||||||
|
|
||||||
|
if not errors:
|
||||||
|
for entry in self._async_current_entries():
|
||||||
|
if entry.unique_id == self.unique_id:
|
||||||
|
self.hass.config_entries.async_update_entry(
|
||||||
|
entry, data=user_input
|
||||||
|
)
|
||||||
|
await self.hass.config_entries.async_reload(entry.entry_id)
|
||||||
|
return self.async_abort(reason="reauth_successful")
|
||||||
|
|
||||||
|
if errors["base"] != "invalid_auth":
|
||||||
|
return self.async_abort(reason=errors["base"])
|
||||||
|
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id="reauth", data_schema=GEHOME_SCHEMA, errors=errors,
|
||||||
|
)
|
||||||
15
const.py
Normal file
15
const.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
"""Constants for the gehome integration."""
|
||||||
|
|
||||||
|
DOMAIN = "ge_home"
|
||||||
|
|
||||||
|
EVENT_ALL_APPLIANCES_READY = 'all_appliances_ready'
|
||||||
|
|
||||||
|
UPDATE_INTERVAL = 30
|
||||||
|
ASYNC_TIMEOUT = 30
|
||||||
|
MIN_RETRY_DELAY = 15
|
||||||
|
MAX_RETRY_DELAY = 1800
|
||||||
|
RETRY_OFFLINE_COUNT = 5
|
||||||
|
|
||||||
|
SERVICE_SET_TIMER = "set_timer"
|
||||||
|
SERVICE_CLEAR_TIMER = "clear_timer"
|
||||||
|
SERVICE_SET_INT_VALUE = "set_int_value"
|
||||||
66
devices/__init__.py
Normal file
66
devices/__init__.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import logging
|
||||||
|
from typing import Type
|
||||||
|
|
||||||
|
from gehomesdk.erd import ErdApplianceType
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from .oven import OvenApi
|
||||||
|
from .cooktop import CooktopApi
|
||||||
|
from .fridge import FridgeApi
|
||||||
|
from .dishwasher import DishwasherApi
|
||||||
|
from .washer import WasherApi
|
||||||
|
from .dryer import DryerApi
|
||||||
|
from .washer_dryer import WasherDryerApi
|
||||||
|
from .water_filter import WaterFilterApi
|
||||||
|
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
|
||||||
|
from .water_heater import WaterHeaterApi
|
||||||
|
from .oim import OimApi
|
||||||
|
from .ucim import UcimApi
|
||||||
|
from .coffee_maker import CcmApi
|
||||||
|
from .dual_dishwasher import DualDishwasherApi
|
||||||
|
from .espresso_maker import EspressoMakerApi
|
||||||
|
from .dehumidifier import DehumidifierApi
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def get_appliance_api_type(appliance_type: ErdApplianceType) -> Type:
|
||||||
|
"""Get the appropriate appliance type"""
|
||||||
|
_LOGGER.debug(f"Found device type: {appliance_type}")
|
||||||
|
known_types = {
|
||||||
|
ErdApplianceType.OVEN: OvenApi,
|
||||||
|
ErdApplianceType.COOKTOP: CooktopApi,
|
||||||
|
ErdApplianceType.ELECTRIC_COOKTOP: CooktopApi,
|
||||||
|
ErdApplianceType.FRIDGE: FridgeApi,
|
||||||
|
ErdApplianceType.BEVERAGE_CENTER: FridgeApi,
|
||||||
|
ErdApplianceType.DISH_WASHER: DishwasherApi,
|
||||||
|
ErdApplianceType.DUAL_DISH_WASHER: DualDishwasherApi,
|
||||||
|
ErdApplianceType.WASHER: WasherApi,
|
||||||
|
ErdApplianceType.DRYER: DryerApi,
|
||||||
|
ErdApplianceType.COMBINATION_WASHER_DRYER: WasherDryerApi,
|
||||||
|
ErdApplianceType.POE_WATER_FILTER: WaterFilterApi,
|
||||||
|
ErdApplianceType.WATER_SOFTENER: WaterSoftenerApi,
|
||||||
|
ErdApplianceType.WATER_HEATER: WaterHeaterApi,
|
||||||
|
ErdApplianceType.ADVANTIUM: AdvantiumApi,
|
||||||
|
ErdApplianceType.AIR_CONDITIONER: WacApi,
|
||||||
|
ErdApplianceType.SPLIT_AIR_CONDITIONER: SacApi,
|
||||||
|
ErdApplianceType.PORTABLE_AIR_CONDITIONER: PacApi,
|
||||||
|
ErdApplianceType.BUILT_IN_AIR_CONDITIONER: BiacApi,
|
||||||
|
ErdApplianceType.HOOD: HoodApi,
|
||||||
|
ErdApplianceType.MICROWAVE: MicrowaveApi,
|
||||||
|
ErdApplianceType.OPAL_ICE_MAKER: OimApi,
|
||||||
|
ErdApplianceType.UNDER_COUNTER_ICE_MAKER: UcimApi,
|
||||||
|
ErdApplianceType.CAFE_COFFEE_MAKER: CcmApi,
|
||||||
|
ErdApplianceType.ESPRESSO_MAKER: EspressoMakerApi,
|
||||||
|
ErdApplianceType.DEHUMIDIFIER: DehumidifierApi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the appliance type
|
||||||
|
return known_types.get(appliance_type, ApplianceApi)
|
||||||
BIN
devices/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
devices/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/advantium.cpython-313.pyc
Normal file
BIN
devices/__pycache__/advantium.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/base.cpython-313.pyc
Normal file
BIN
devices/__pycache__/base.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/biac.cpython-313.pyc
Normal file
BIN
devices/__pycache__/biac.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/coffee_maker.cpython-313.pyc
Normal file
BIN
devices/__pycache__/coffee_maker.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/cooktop.cpython-313.pyc
Normal file
BIN
devices/__pycache__/cooktop.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/dehumidifier.cpython-313.pyc
Normal file
BIN
devices/__pycache__/dehumidifier.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/dishwasher.cpython-313.pyc
Normal file
BIN
devices/__pycache__/dishwasher.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/dryer.cpython-313.pyc
Normal file
BIN
devices/__pycache__/dryer.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/dual_dishwasher.cpython-313.pyc
Normal file
BIN
devices/__pycache__/dual_dishwasher.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/espresso_maker.cpython-313.pyc
Normal file
BIN
devices/__pycache__/espresso_maker.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/fridge.cpython-313.pyc
Normal file
BIN
devices/__pycache__/fridge.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/hood.cpython-313.pyc
Normal file
BIN
devices/__pycache__/hood.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/microwave.cpython-313.pyc
Normal file
BIN
devices/__pycache__/microwave.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/oim.cpython-313.pyc
Normal file
BIN
devices/__pycache__/oim.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/oven.cpython-313.pyc
Normal file
BIN
devices/__pycache__/oven.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/pac.cpython-313.pyc
Normal file
BIN
devices/__pycache__/pac.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/sac.cpython-313.pyc
Normal file
BIN
devices/__pycache__/sac.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/ucim.cpython-313.pyc
Normal file
BIN
devices/__pycache__/ucim.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/wac.cpython-313.pyc
Normal file
BIN
devices/__pycache__/wac.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/washer.cpython-313.pyc
Normal file
BIN
devices/__pycache__/washer.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/washer_dryer.cpython-313.pyc
Normal file
BIN
devices/__pycache__/washer_dryer.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/water_filter.cpython-313.pyc
Normal file
BIN
devices/__pycache__/water_filter.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/water_heater.cpython-313.pyc
Normal file
BIN
devices/__pycache__/water_heater.cpython-313.pyc
Normal file
Binary file not shown.
BIN
devices/__pycache__/water_softener.cpython-313.pyc
Normal file
BIN
devices/__pycache__/water_softener.cpython-313.pyc
Normal file
Binary file not shown.
45
devices/advantium.py
Normal file
45
devices/advantium.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk.erd import ErdCode, ErdApplianceType, ErdDataType
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from ..entities import GeAdvantium, GeErdSensor, GeErdBinarySensor, GeErdPropertySensor, GeErdPropertyBinarySensor, UPPER_OVEN
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class AdvantiumApi(ApplianceApi):
|
||||||
|
"""API class for Advantium objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.ADVANTIUM
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
advantium_entities = [
|
||||||
|
GeErdSensor(self, ErdCode.PERSONALITY),
|
||||||
|
GeErdBinarySensor(self, ErdCode.UPPER_OVEN_REMOTE_ENABLED, self._single_name(ErdCode.UPPER_OVEN_REMOTE_ENABLED)),
|
||||||
|
GeErdBinarySensor(self, ErdCode.MICROWAVE_REMOTE_ENABLE),
|
||||||
|
GeErdSensor(self, ErdCode.UPPER_OVEN_DISPLAY_TEMPERATURE, self._single_name(ErdCode.UPPER_OVEN_DISPLAY_TEMPERATURE)),
|
||||||
|
GeErdSensor(self, ErdCode.ADVANTIUM_KITCHEN_TIME_REMAINING),
|
||||||
|
GeErdSensor(self, ErdCode.ADVANTIUM_COOK_TIME_REMAINING),
|
||||||
|
GeAdvantium(self),
|
||||||
|
|
||||||
|
#Cook Status
|
||||||
|
GeErdPropertySensor(self, ErdCode.ADVANTIUM_COOK_STATUS, "cook_mode"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.ADVANTIUM_COOK_STATUS, "termination_reason", icon_override="mdi:information-outline"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.ADVANTIUM_COOK_STATUS, "preheat_status", icon_override="mdi:fire"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.ADVANTIUM_COOK_STATUS, "temperature", icon_override="mdi:thermometer", data_type_override=ErdDataType.INT),
|
||||||
|
GeErdPropertySensor(self, ErdCode.ADVANTIUM_COOK_STATUS, "power_level", icon_override="mdi:gauge", data_type_override=ErdDataType.INT),
|
||||||
|
GeErdPropertySensor(self, ErdCode.ADVANTIUM_COOK_STATUS, "warm_status", icon_override="mdi:radiator"),
|
||||||
|
GeErdPropertyBinarySensor(self, ErdCode.ADVANTIUM_COOK_STATUS, "door_status", device_class_override="door"),
|
||||||
|
GeErdPropertyBinarySensor(self, ErdCode.ADVANTIUM_COOK_STATUS, "sensing_active", icon_on_override="mdi:flash-auto", icon_off_override="mdi:flash-off"),
|
||||||
|
GeErdPropertyBinarySensor(self, ErdCode.ADVANTIUM_COOK_STATUS, "cooling_fan_status", icon_on_override="mdi:fan", icon_off_override="mdi:fan-off"),
|
||||||
|
GeErdPropertyBinarySensor(self, ErdCode.ADVANTIUM_COOK_STATUS, "oven_light_status", icon_on_override="mdi:lightbulb-on", icon_off_override="mdi:lightbulb-off"),
|
||||||
|
]
|
||||||
|
entities = base_entities + advantium_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
|
def _single_name(self, erd_code: ErdCode):
|
||||||
|
return erd_code.name.replace(UPPER_OVEN+"_","").replace("_", " ").title()
|
||||||
|
|
||||||
154
devices/base.py
Normal file
154
devices/base.py
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
import asyncio
|
||||||
|
import logging
|
||||||
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
|
from gehomesdk import GeAppliance
|
||||||
|
from gehomesdk.erd import ErdCode, ErdCodeType, ErdApplianceType
|
||||||
|
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
|
|
||||||
|
from ..const import DOMAIN
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class ApplianceApi:
|
||||||
|
"""
|
||||||
|
API class to represent a single physical device.
|
||||||
|
|
||||||
|
Since a physical device can have many entities, we"ll pool common elements here
|
||||||
|
"""
|
||||||
|
APPLIANCE_TYPE = None # type: Optional[ErdApplianceType]
|
||||||
|
|
||||||
|
def __init__(self, coordinator: DataUpdateCoordinator, appliance: GeAppliance):
|
||||||
|
if not appliance.initialized:
|
||||||
|
raise RuntimeError("Appliance not ready")
|
||||||
|
self._appliance = appliance
|
||||||
|
self._loop = appliance.client.loop
|
||||||
|
self._hass = coordinator.hass
|
||||||
|
self.coordinator = coordinator
|
||||||
|
self.initial_update = False
|
||||||
|
self._entities = {} # type: Optional[Dict[str, Entity]]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hass(self) -> HomeAssistant:
|
||||||
|
return self._hass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def loop(self) -> Optional[asyncio.AbstractEventLoop]:
|
||||||
|
if self._loop is None:
|
||||||
|
self._loop = self._appliance.client.loop
|
||||||
|
return self._loop
|
||||||
|
|
||||||
|
@property
|
||||||
|
def appliance(self) -> GeAppliance:
|
||||||
|
return self._appliance
|
||||||
|
|
||||||
|
@appliance.setter
|
||||||
|
def appliance(self, value: GeAppliance):
|
||||||
|
self._appliance = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self) -> bool:
|
||||||
|
#Note - online will be there since we're using the GE coordinator
|
||||||
|
#Didn't want to deal with the circular references to get the type hints
|
||||||
|
#working.
|
||||||
|
return self.appliance.available and self.coordinator.online
|
||||||
|
|
||||||
|
@property
|
||||||
|
def serial_number(self) -> str:
|
||||||
|
return self.appliance.get_erd_value(ErdCode.SERIAL_NUMBER)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mac_addr(self) -> str:
|
||||||
|
return self.appliance.mac_addr
|
||||||
|
|
||||||
|
@property
|
||||||
|
def serial_or_mac(self) -> str:
|
||||||
|
def is_zero(val: str) -> bool:
|
||||||
|
try:
|
||||||
|
intVal = int(val)
|
||||||
|
return intVal == 0
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if (self.serial_number and not
|
||||||
|
self.serial_number.isspace() and not
|
||||||
|
is_zero(self.serial_number)):
|
||||||
|
return self.serial_number
|
||||||
|
return self.mac_addr
|
||||||
|
|
||||||
|
@property
|
||||||
|
def model_number(self) -> str:
|
||||||
|
return self.appliance.get_erd_value(ErdCode.MODEL_NUMBER)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sw_version(self) -> str:
|
||||||
|
appVer = self.try_get_erd_value(ErdCode.APPLIANCE_SW_VERSION)
|
||||||
|
wifiVer = self.try_get_erd_value(ErdCode.WIFI_MODULE_SW_VERSION)
|
||||||
|
|
||||||
|
return 'Appliance=' + str(appVer or 'Unknown') + '/Wifi=' + str(wifiVer or 'Unknown')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self) -> str:
|
||||||
|
appliance_type = self.appliance.appliance_type
|
||||||
|
if appliance_type is None or appliance_type == ErdApplianceType.UNKNOWN:
|
||||||
|
appliance_type = "Appliance"
|
||||||
|
else:
|
||||||
|
appliance_type = appliance_type.name.replace("_", " ").title()
|
||||||
|
return f"GE {appliance_type} {self.serial_or_mac}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_info(self) -> Dict:
|
||||||
|
"""Device info dictionary."""
|
||||||
|
|
||||||
|
return {
|
||||||
|
"identifiers": {(DOMAIN, self.serial_or_mac)},
|
||||||
|
"name": self.name,
|
||||||
|
"manufacturer": "GE",
|
||||||
|
"model": self.model_number,
|
||||||
|
"sw_version": self.sw_version
|
||||||
|
}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def entities(self) -> List[Entity]:
|
||||||
|
return list(self._entities.values())
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
"""Create Entities for this device."""
|
||||||
|
return self.get_base_entities()
|
||||||
|
|
||||||
|
def get_base_entities(self) -> List[Entity]:
|
||||||
|
"""Create base entities (i.e. common between all appliances)."""
|
||||||
|
from ..entities import GeErdSensor, GeErdSwitch
|
||||||
|
entities = [
|
||||||
|
GeErdSensor(self, ErdCode.CLOCK_TIME),
|
||||||
|
GeErdSwitch(self, ErdCode.SABBATH_MODE),
|
||||||
|
]
|
||||||
|
return entities
|
||||||
|
|
||||||
|
def build_entities_list(self) -> None:
|
||||||
|
"""Build the entities list, adding anything new."""
|
||||||
|
from ..entities import GeErdEntity, GeErdButton
|
||||||
|
entities = [
|
||||||
|
e for e in self.get_all_entities()
|
||||||
|
if not isinstance(e, GeErdEntity) or isinstance(e, GeErdButton) or e.erd_code in self.appliance.known_properties
|
||||||
|
]
|
||||||
|
|
||||||
|
for entity in entities:
|
||||||
|
if entity.unique_id not in self._entities:
|
||||||
|
self._entities[entity.unique_id] = entity
|
||||||
|
|
||||||
|
def try_get_erd_value(self, code: ErdCodeType):
|
||||||
|
try:
|
||||||
|
return self.appliance.get_erd_value(code)
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def has_erd_code(self, code: ErdCodeType):
|
||||||
|
try:
|
||||||
|
self.appliance.get_erd_value(code)
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
35
devices/biac.py
Normal file
35
devices/biac.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
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 GeSacClimate, GeErdSensor, GeErdSwitch, ErdOnOffBoolConverter, GeErdBinarySensor
|
||||||
|
|
||||||
|
|
||||||
|
_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()
|
||||||
|
|
||||||
|
sac_entities = [
|
||||||
|
GeSacClimate(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 + sac_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
66
devices/coffee_maker.py
Normal file
66
devices/coffee_maker.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk import (
|
||||||
|
GeAppliance,
|
||||||
|
ErdCode,
|
||||||
|
ErdApplianceType,
|
||||||
|
ErdCcmBrewSettings
|
||||||
|
)
|
||||||
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from ..entities import (
|
||||||
|
GeCcmPotNotPresentBinarySensor,
|
||||||
|
GeErdSensor,
|
||||||
|
GeErdBinarySensor,
|
||||||
|
GeErdButton,
|
||||||
|
GeCcmBrewStrengthSelect,
|
||||||
|
GeCcmBrewTemperatureNumber,
|
||||||
|
GeCcmBrewCupsNumber,
|
||||||
|
GeCcmBrewSettingsButton
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class CcmApi(ApplianceApi):
|
||||||
|
"""API class for Cafe Coffee Maker objects"""
|
||||||
|
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]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
ccm_entities = [
|
||||||
|
GeErdBinarySensor(self, ErdCode.CCM_IS_BREWING),
|
||||||
|
GeErdBinarySensor(self, ErdCode.CCM_IS_DESCALING),
|
||||||
|
GeCcmBrewSettingsButton(self),
|
||||||
|
GeErdButton(self, ErdCode.CCM_CANCEL_DESCALING),
|
||||||
|
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),
|
||||||
|
GeErdBinarySensor(self, ErdCode.CCM_OUT_OF_WATER, device_class_override="problem"),
|
||||||
|
GeCcmPotNotPresentBinarySensor(self, ErdCode.CCM_POT_PRESENT, device_class_override="problem")
|
||||||
|
]
|
||||||
|
|
||||||
|
entities = base_entities + ccm_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
|
async def start_brewing(self) -> None:
|
||||||
|
"""Aggregate brew settings and start brewing."""
|
||||||
|
|
||||||
|
new_mode = ErdCcmBrewSettings(self._brew_cups_entity.native_value,
|
||||||
|
self._brew_strengh_entity.brew_strength,
|
||||||
|
self._brew_temperature_entity.native_value)
|
||||||
|
await self.appliance.async_set_erd_value(ErdCode.CCM_BREW_SETTINGS, new_mode)
|
||||||
62
devices/cooktop.py
Normal file
62
devices/cooktop.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
from gehomesdk.erd.erd_data_type import ErdDataType
|
||||||
|
|
||||||
|
from homeassistant.components.sensor import SensorDeviceClass
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk import (
|
||||||
|
ErdCode,
|
||||||
|
ErdApplianceType,
|
||||||
|
ErdCooktopConfig,
|
||||||
|
CooktopStatus
|
||||||
|
)
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from ..entities import (
|
||||||
|
GeErdBinarySensor,
|
||||||
|
GeErdPropertySensor,
|
||||||
|
GeErdPropertyBinarySensor
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class CooktopApi(ApplianceApi):
|
||||||
|
"""API class for cooktop objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.COOKTOP
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
cooktop_config = ErdCooktopConfig.NONE
|
||||||
|
if self.has_erd_code(ErdCode.COOKTOP_CONFIG):
|
||||||
|
cooktop_config: ErdCooktopConfig = self.appliance.get_erd_value(ErdCode.COOKTOP_CONFIG)
|
||||||
|
|
||||||
|
_LOGGER.debug(f"Cooktop Config: {cooktop_config}")
|
||||||
|
cooktop_entities = []
|
||||||
|
|
||||||
|
if cooktop_config == ErdCooktopConfig.PRESENT:
|
||||||
|
# attempt to get the cooktop status using legacy status
|
||||||
|
cooktop_status_erd = ErdCode.COOKTOP_STATUS
|
||||||
|
cooktop_status: CooktopStatus = self.try_get_erd_value(ErdCode.COOKTOP_STATUS)
|
||||||
|
|
||||||
|
# if we didn't get it, try using the new version
|
||||||
|
if cooktop_status is None:
|
||||||
|
cooktop_status_erd = ErdCode.COOKTOP_STATUS_EXT
|
||||||
|
cooktop_status: CooktopStatus = self.try_get_erd_value(ErdCode.COOKTOP_STATUS_EXT)
|
||||||
|
|
||||||
|
# if we got a status through either mechanism, we can add the entities
|
||||||
|
if cooktop_status is not None:
|
||||||
|
cooktop_entities.append(GeErdBinarySensor(self, cooktop_status_erd))
|
||||||
|
|
||||||
|
for (k, v) in cooktop_status.burners.items():
|
||||||
|
if v.exists:
|
||||||
|
prop = self._camel_to_snake(k)
|
||||||
|
cooktop_entities.append(GeErdPropertyBinarySensor(self, cooktop_status_erd, prop+".on"))
|
||||||
|
cooktop_entities.append(GeErdPropertyBinarySensor(self, cooktop_status_erd, prop+".synchronized"))
|
||||||
|
if not v.on_off_only:
|
||||||
|
cooktop_entities.append(GeErdPropertySensor(self, cooktop_status_erd, prop+".power_pct", icon_override="mdi:fire", device_class_override=SensorDeviceClass.POWER_FACTOR, data_type_override=ErdDataType.INT))
|
||||||
|
|
||||||
|
return base_entities + cooktop_entities
|
||||||
|
|
||||||
|
def _camel_to_snake(self, s):
|
||||||
|
return ''.join(['_'+c.lower() if c.isupper() else c for c in s]).lstrip('_')
|
||||||
44
devices/dehumidifier.py
Normal file
44
devices/dehumidifier.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk import (
|
||||||
|
ErdCode,
|
||||||
|
ErdApplianceType,
|
||||||
|
ErdOnOff
|
||||||
|
)
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from ..entities import (
|
||||||
|
GeErdSensor,
|
||||||
|
GeErdSelect,
|
||||||
|
GeErdPropertySensor,
|
||||||
|
GeErdSwitch,
|
||||||
|
ErdOnOffBoolConverter,
|
||||||
|
GeDehumidifierFanSpeedSensor,
|
||||||
|
GeDehumidifier
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class DehumidifierApi(ApplianceApi):
|
||||||
|
"""API class for Dehumidifier objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.DEHUMIDIFIER
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
dhum_entities = [
|
||||||
|
GeErdSwitch(self, ErdCode.AC_POWER_STATUS, bool_converter=ErdOnOffBoolConverter(), icon_on_override="mdi:power-on", icon_off_override="mdi:power-off"),
|
||||||
|
GeDehumidifierFanSpeedSensor(self, ErdCode.AC_FAN_SETTING, icon_override="mdi:fan"),
|
||||||
|
GeErdSensor(self, ErdCode.DHUM_CURRENT_HUMIDITY),
|
||||||
|
GeErdSensor(self, ErdCode.DHUM_TARGET_HUMIDITY),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DHUM_MAINTENANCE, "empty_bucket", device_class_override="problem"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DHUM_MAINTENANCE, "clean_filter", device_class_override="problem"),
|
||||||
|
GeDehumidifier(self)
|
||||||
|
]
|
||||||
|
|
||||||
|
entities = base_entities + dhum_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
55
devices/dishwasher.py
Normal file
55
devices/dishwasher.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
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 GeErdSensor, GeErdBinarySensor, GeErdPropertySensor, GeErdNumber
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class DishwasherApi(ApplianceApi):
|
||||||
|
"""API class for dishwasher objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.DISH_WASHER
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
dishwasher_entities = [
|
||||||
|
#GeDishwasherControlLockedSwitch(self, ErdCode.USER_INTERFACE_LOCKED),
|
||||||
|
GeErdSensor(self, ErdCode.DISHWASHER_CYCLE_NAME),
|
||||||
|
GeErdSensor(self, ErdCode.DISHWASHER_CYCLE_STATE, icon_override="mdi:state-machine"),
|
||||||
|
GeErdSensor(self, ErdCode.DISHWASHER_OPERATING_MODE),
|
||||||
|
# GeErdSensor(self, ErdCode.DISHWASHER_PODS_REMAINING_VALUE, uom_override="pods"),
|
||||||
|
GeErdNumber(self, ErdCode.DISHWASHER_PODS_REMAINING_VALUE, uom_override="pods", min_value=0, max_value=255),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_REMINDERS, "add_rinse_aid", icon_override="mdi:shimmer"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_REMINDERS, "clean_filter", icon_override="mdi:dishwasher-alert"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_REMINDERS, "sanitized", icon_override="mdi:silverware-clean"),
|
||||||
|
GeErdSensor(self, ErdCode.DISHWASHER_TIME_REMAINING),
|
||||||
|
GeErdBinarySensor(self, ErdCode.DISHWASHER_DOOR_STATUS),
|
||||||
|
GeErdBinarySensor(self, ErdCode.DISHWASHER_IS_CLEAN),
|
||||||
|
GeErdBinarySensor(self, ErdCode.DISHWASHER_REMOTE_START_ENABLE),
|
||||||
|
|
||||||
|
#User Setttings
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "mute", icon_override="mdi:volume-mute"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "lock_control", icon_override="mdi:lock"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "sabbath", icon_override="mdi:star-david"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "cycle_mode", icon_override="mdi:state-machine"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "presoak", icon_override="mdi:water"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "bottle_jet", icon_override="mdi:bottle-tonic-outline"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "wash_temp", icon_override="mdi:coolant-temperature"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "rinse_aid", icon_override="mdi:shimmer"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "dry_option", icon_override="mdi:fan"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "wash_zone", icon_override="mdi:dock-top"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "delay_hours", icon_override="mdi:clock-fast"),
|
||||||
|
|
||||||
|
#Cycle Counts
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_CYCLE_COUNTS, "started", icon_override="mdi:counter"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_CYCLE_COUNTS, "completed", icon_override="mdi:counter"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_CYCLE_COUNTS, "reset", icon_override="mdi:counter")
|
||||||
|
]
|
||||||
|
entities = base_entities + dishwasher_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
66
devices/dryer.py
Normal file
66
devices/dryer.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk import ErdCode, ErdApplianceType
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from ..entities import GeErdSensor, GeErdBinarySensor
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class DryerApi(ApplianceApi):
|
||||||
|
"""API class for dryer objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.DRYER
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
common_entities = [
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_MACHINE_STATE, icon_override="mdi:tumble-dryer"),
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_CYCLE, icon_override="mdi:state-machine"),
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_SUB_CYCLE, icon_override="mdi:state-machine"),
|
||||||
|
GeErdBinarySensor(self, ErdCode.LAUNDRY_END_OF_CYCLE, icon_on_override="mdi:tumble-dryer", icon_off_override="mdi:tumble-dryer"),
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_TIME_REMAINING),
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_DELAY_TIME_REMAINING),
|
||||||
|
GeErdBinarySensor(self, ErdCode.LAUNDRY_DOOR),
|
||||||
|
GeErdBinarySensor(self, ErdCode.LAUNDRY_REMOTE_STATUS, icon_on_override="mdi:tumble-dryer", icon_off_override="mdi:tumble-dryer"),
|
||||||
|
GeErdBinarySensor(self, ErdCode.LAUNDRY_DRYER_BLOCKED_VENT_FAULT, icon_on_override="mid:alert-circle", icon_off_override="mdi:alert-circle"),
|
||||||
|
]
|
||||||
|
|
||||||
|
dryer_entities = self.get_dryer_entities()
|
||||||
|
|
||||||
|
entities = base_entities + common_entities + dryer_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
|
def get_dryer_entities(self):
|
||||||
|
#Not all options appear to exist on every dryer... we'll look for the presence of
|
||||||
|
#a code to figure out which sensors are applicable beyond the common ones.
|
||||||
|
dryer_entities = [
|
||||||
|
]
|
||||||
|
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_DRYER_DRYNESS_LEVEL):
|
||||||
|
dryer_entities.extend([GeErdSensor(self, ErdCode.LAUNDRY_DRYER_DRYNESS_LEVEL)])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_DRYER_DRYNESSNEW_LEVEL):
|
||||||
|
dryer_entities.extend([GeErdSensor(self, ErdCode.LAUNDRY_DRYER_DRYNESSNEW_LEVEL)])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_DRYER_TEMPERATURE_OPTION):
|
||||||
|
dryer_entities.extend([GeErdSensor(self, ErdCode.LAUNDRY_DRYER_TEMPERATURE_OPTION)])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_DRYER_TEMPERATURENEW_OPTION):
|
||||||
|
dryer_entities.extend([GeErdSensor(self, ErdCode.LAUNDRY_DRYER_TEMPERATURENEW_OPTION)])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_DRYER_TUMBLE_STATUS):
|
||||||
|
dryer_entities.extend([GeErdSensor(self, ErdCode.LAUNDRY_DRYER_TUMBLE_STATUS)])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_DRYER_EXTENDED_TUMBLE_OPTION_SELECTION):
|
||||||
|
dryer_entities.extend([GeErdSensor(self, ErdCode.LAUNDRY_DRYER_EXTENDED_TUMBLE_OPTION_SELECTION)])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_DRYER_WASHERLINK_STATUS):
|
||||||
|
dryer_entities.extend([GeErdBinarySensor(self, ErdCode.LAUNDRY_DRYER_WASHERLINK_STATUS)])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_DRYER_LEVEL_SENSOR_DISABLED):
|
||||||
|
dryer_entities.extend([GeErdBinarySensor(self, ErdCode.LAUNDRY_DRYER_LEVEL_SENSOR_DISABLED)])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_DRYER_SHEET_USAGE_CONFIGURATION):
|
||||||
|
dryer_entities.extend([GeErdSensor(self, ErdCode.LAUNDRY_DRYER_SHEET_USAGE_CONFIGURATION)])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_DRYER_SHEET_INVENTORY):
|
||||||
|
dryer_entities.extend([GeErdSensor(self, ErdCode.LAUNDRY_DRYER_SHEET_INVENTORY, icon_override="mdi:tray-full", uom_override="sheets")])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_DRYER_ECODRY_OPTION_SELECTION):
|
||||||
|
dryer_entities.extend([GeErdSensor(self, ErdCode.LAUNDRY_DRYER_ECODRY_OPTION_SELECTION)])
|
||||||
|
|
||||||
|
return dryer_entities
|
||||||
|
|
||||||
71
devices/dual_dishwasher.py
Normal file
71
devices/dual_dishwasher.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
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 GeErdSensor, GeErdBinarySensor, GeErdPropertySensor
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class DualDishwasherApi(ApplianceApi):
|
||||||
|
"""API class for dual dishwasher objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.DISH_WASHER
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
lower_entities = [
|
||||||
|
GeErdSensor(self, ErdCode.DISHWASHER_CYCLE_STATE, erd_override="lower_cycle_state", icon_override="mdi:state-machine"),
|
||||||
|
GeErdSensor(self, ErdCode.DISHWASHER_TIME_REMAINING, erd_override="lower_time_remaining"),
|
||||||
|
GeErdBinarySensor(self, ErdCode.DISHWASHER_DOOR_STATUS, erd_override="lower_door_status"),
|
||||||
|
|
||||||
|
#Reminders
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_REMINDERS, "add_rinse_aid", erd_override="lower_reminder", icon_override="mdi:shimmer"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_REMINDERS, "clean_filter", erd_override="lower_reminder", icon_override="mdi:dishwasher-alert"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_REMINDERS, "sanitized", erd_override="lower_reminder", icon_override="mdi:silverware-clean"),
|
||||||
|
|
||||||
|
#User Setttings
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "mute", erd_override="lower_setting", icon_override="mdi:volume-mute"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "lock_control", erd_override="lower_setting", icon_override="mdi:lock"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "sabbath", erd_override="lower_setting", icon_override="mdi:star-david"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "cycle_mode", erd_override="lower_setting", icon_override="mdi:state-machine"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "presoak", erd_override="lower_setting", icon_override="mdi:water"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "bottle_jet", erd_override="lower_setting", icon_override="mdi:bottle-tonic-outline"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "wash_temp", erd_override="lower_setting", icon_override="mdi:coolant-temperature"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "rinse_aid", erd_override="lower_setting", icon_override="mdi:shimmer"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "dry_option", erd_override="lower_setting", icon_override="mdi:fan"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "wash_zone", erd_override="lower_setting", icon_override="mdi:dock-top"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_USER_SETTING, "delay_hours", erd_override="lower_setting", icon_override="mdi:clock-fast")
|
||||||
|
]
|
||||||
|
|
||||||
|
upper_entities = [
|
||||||
|
#GeDishwasherControlLockedSwitch(self, ErdCode.USER_INTERFACE_LOCKED),
|
||||||
|
GeErdSensor(self, ErdCode.DISHWASHER_UPPER_CYCLE_STATE, erd_override="upper_cycle_state", icon_override="mdi:state-machine"),
|
||||||
|
GeErdSensor(self, ErdCode.DISHWASHER_UPPER_TIME_REMAINING, erd_override="upper_time_remaining"),
|
||||||
|
GeErdBinarySensor(self, ErdCode.DISHWASHER_UPPER_DOOR_STATUS, erd_override="upper_door_status"),
|
||||||
|
|
||||||
|
#Reminders
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_UPPER_REMINDERS, "add_rinse_aid", erd_override="upper_reminder", icon_override="mdi:shimmer"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_UPPER_REMINDERS, "clean_filter", erd_override="upper_reminder", icon_override="mdi:dishwasher-alert"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_UPPER_REMINDERS, "sanitized", erd_override="upper_reminder", icon_override="mdi:silverware-clean"),
|
||||||
|
|
||||||
|
#User Setttings
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_UPPER_USER_SETTING, "mute", erd_override="upper_setting", icon_override="mdi:volume-mute"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_UPPER_USER_SETTING, "lock_control", erd_override="upper_setting", icon_override="mdi:lock"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_UPPER_USER_SETTING, "sabbath", erd_override="upper_setting", icon_override="mdi:star-david"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_UPPER_USER_SETTING, "cycle_mode", erd_override="upper_setting", icon_override="mdi:state-machine"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_UPPER_USER_SETTING, "presoak", erd_override="upper_setting", icon_override="mdi:water"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_UPPER_USER_SETTING, "bottle_jet", erd_override="upper_setting", icon_override="mdi:bottle-tonic-outline"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_UPPER_USER_SETTING, "wash_temp", erd_override="upper_setting", icon_override="mdi:coolant-temperature"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_UPPER_USER_SETTING, "rinse_aid", erd_override="upper_setting", icon_override="mdi:shimmer"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_UPPER_USER_SETTING, "dry_option", erd_override="upper_setting", icon_override="mdi:fan"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_UPPER_USER_SETTING, "wash_zone", erd_override="upper_setting", icon_override="mdi:dock-top"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.DISHWASHER_UPPER_USER_SETTING, "delay_hours", erd_override="upper_setting", icon_override="mdi:clock-fast")
|
||||||
|
]
|
||||||
|
|
||||||
|
entities = base_entities + lower_entities + upper_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
34
devices/espresso_maker.py
Normal file
34
devices/espresso_maker.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk import (
|
||||||
|
ErdCode,
|
||||||
|
ErdApplianceType
|
||||||
|
)
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from ..entities import (
|
||||||
|
GeErdBinarySensor,
|
||||||
|
GeErdButton
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class EspressoMakerApi(ApplianceApi):
|
||||||
|
"""API class for Espresso Maker objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.ESPRESSO_MAKER
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
em_entities = [
|
||||||
|
GeErdBinarySensor(self, ErdCode.CCM_IS_DESCALING),
|
||||||
|
GeErdButton(self, ErdCode.CCM_CANCEL_DESCALING),
|
||||||
|
GeErdButton(self, ErdCode.CCM_START_DESCALING),
|
||||||
|
GeErdBinarySensor(self, ErdCode.CCM_OUT_OF_WATER, device_class_override="problem"),
|
||||||
|
]
|
||||||
|
|
||||||
|
entities = base_entities + em_entities
|
||||||
|
return entities
|
||||||
138
devices/fridge.py
Normal file
138
devices/fridge.py
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
|
||||||
|
from homeassistant.components.sensor import SensorDeviceClass
|
||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk import (
|
||||||
|
ErdCode,
|
||||||
|
ErdApplianceType,
|
||||||
|
ErdOnOff,
|
||||||
|
ErdHotWaterStatus,
|
||||||
|
FridgeIceBucketStatus,
|
||||||
|
IceMakerControlStatus,
|
||||||
|
ErdFilterStatus,
|
||||||
|
HotWaterStatus,
|
||||||
|
FridgeModelInfo,
|
||||||
|
ErdConvertableDrawerMode,
|
||||||
|
ErdDataType
|
||||||
|
)
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from ..entities import (
|
||||||
|
ErdOnOffBoolConverter,
|
||||||
|
GeErdSensor,
|
||||||
|
GeErdBinarySensor,
|
||||||
|
GeErdSwitch,
|
||||||
|
GeErdSelect,
|
||||||
|
GeErdLight,
|
||||||
|
GeFridge,
|
||||||
|
GeFreezer,
|
||||||
|
GeDispenser,
|
||||||
|
GeErdPropertySensor,
|
||||||
|
GeErdPropertyBinarySensor,
|
||||||
|
ConvertableDrawerModeOptionsConverter,
|
||||||
|
GeFridgeIceControlSwitch
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class FridgeApi(ApplianceApi):
|
||||||
|
"""API class for fridge objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.FRIDGE
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
fridge_entities = []
|
||||||
|
freezer_entities = []
|
||||||
|
dispenser_entities = []
|
||||||
|
|
||||||
|
# Get the statuses used to determine presence
|
||||||
|
|
||||||
|
ice_maker_control: IceMakerControlStatus = self.try_get_erd_value(ErdCode.ICE_MAKER_CONTROL)
|
||||||
|
ice_bucket_status: FridgeIceBucketStatus = self.try_get_erd_value(ErdCode.ICE_MAKER_BUCKET_STATUS)
|
||||||
|
water_filter: ErdFilterStatus = self.try_get_erd_value(ErdCode.WATER_FILTER_STATUS)
|
||||||
|
air_filter: ErdFilterStatus = self.try_get_erd_value(ErdCode.AIR_FILTER_STATUS)
|
||||||
|
hot_water_status: HotWaterStatus = self.try_get_erd_value(ErdCode.HOT_WATER_STATUS)
|
||||||
|
fridge_model_info: FridgeModelInfo = self.try_get_erd_value(ErdCode.FRIDGE_MODEL_INFO)
|
||||||
|
convertable_drawer: ErdConvertableDrawerMode = self.try_get_erd_value(ErdCode.CONVERTABLE_DRAWER_MODE)
|
||||||
|
|
||||||
|
interior_light: int = self.try_get_erd_value(ErdCode.INTERIOR_LIGHT)
|
||||||
|
proximity_light: ErdOnOff = self.try_get_erd_value(ErdCode.PROXIMITY_LIGHT)
|
||||||
|
display_mode: ErdOnOff = self.try_get_erd_value(ErdCode.DISPLAY_MODE)
|
||||||
|
lockout_mode: ErdOnOff = self.try_get_erd_value(ErdCode.LOCKOUT_MODE)
|
||||||
|
turbo_cool: ErdOnOff = self.try_get_erd_value(ErdCode.TURBO_COOL_STATUS)
|
||||||
|
turbo_freeze: ErdOnOff = self.try_get_erd_value(ErdCode.TURBO_FREEZE_STATUS)
|
||||||
|
ice_boost: ErdOnOff = self.try_get_erd_value(ErdCode.FRIDGE_ICE_BOOST)
|
||||||
|
|
||||||
|
units = self.hass.config.units
|
||||||
|
|
||||||
|
# Common entities
|
||||||
|
common_entities = [
|
||||||
|
GeErdSensor(self, ErdCode.FRIDGE_MODEL_INFO),
|
||||||
|
GeErdSwitch(self, ErdCode.SABBATH_MODE),
|
||||||
|
GeErdSensor(self, ErdCode.DOOR_STATUS),
|
||||||
|
GeErdPropertyBinarySensor(self, ErdCode.DOOR_STATUS, "any_open")
|
||||||
|
]
|
||||||
|
if(ice_bucket_status and (ice_bucket_status.is_present_fridge or ice_bucket_status.is_present_freezer)):
|
||||||
|
common_entities.append(GeErdSensor(self, ErdCode.ICE_MAKER_BUCKET_STATUS))
|
||||||
|
|
||||||
|
# Fridge entities
|
||||||
|
if fridge_model_info is None or fridge_model_info.has_fridge:
|
||||||
|
fridge_entities.extend([
|
||||||
|
GeErdPropertySensor(self, ErdCode.CURRENT_TEMPERATURE, "fridge"),
|
||||||
|
GeFridge(self),
|
||||||
|
])
|
||||||
|
if turbo_cool is not None:
|
||||||
|
fridge_entities.append(GeErdSwitch(self, ErdCode.FRIDGE_ICE_BOOST))
|
||||||
|
if(ice_maker_control and ice_maker_control.status_fridge != ErdOnOff.NA):
|
||||||
|
fridge_entities.append(GeErdPropertyBinarySensor(self, ErdCode.ICE_MAKER_CONTROL, "status_fridge"))
|
||||||
|
fridge_entities.append(GeFridgeIceControlSwitch(self, "fridge"))
|
||||||
|
if(water_filter and water_filter != ErdFilterStatus.NA):
|
||||||
|
fridge_entities.append(GeErdSensor(self, ErdCode.WATER_FILTER_STATUS))
|
||||||
|
if(air_filter and air_filter != ErdFilterStatus.NA):
|
||||||
|
fridge_entities.append(GeErdSensor(self, ErdCode.AIR_FILTER_STATUS))
|
||||||
|
if(ice_bucket_status and ice_bucket_status.is_present_fridge):
|
||||||
|
fridge_entities.append(GeErdPropertySensor(self, ErdCode.ICE_MAKER_BUCKET_STATUS, "state_full_fridge"))
|
||||||
|
if(interior_light and interior_light != 255):
|
||||||
|
fridge_entities.append(GeErdLight(self, ErdCode.INTERIOR_LIGHT))
|
||||||
|
if(proximity_light and proximity_light != ErdOnOff.NA):
|
||||||
|
fridge_entities.append(GeErdSwitch(self, ErdCode.PROXIMITY_LIGHT, ErdOnOffBoolConverter(), icon_on_override="mdi:lightbulb-on", icon_off_override="mdi:lightbulb"))
|
||||||
|
if(convertable_drawer and convertable_drawer != ErdConvertableDrawerMode.NA):
|
||||||
|
fridge_entities.append(GeErdSelect(self, ErdCode.CONVERTABLE_DRAWER_MODE, ConvertableDrawerModeOptionsConverter(units)))
|
||||||
|
if(display_mode and display_mode != ErdOnOff.NA):
|
||||||
|
fridge_entities.append(GeErdSwitch(self, ErdCode.DISPLAY_MODE, ErdOnOffBoolConverter(), icon_on_override="mdi:lightbulb-on", icon_off_override="mdi:lightbulb"))
|
||||||
|
if(lockout_mode and lockout_mode != ErdOnOff.NA):
|
||||||
|
fridge_entities.append(GeErdSwitch(self, ErdCode.LOCKOUT_MODE, ErdOnOffBoolConverter(), icon_on_override="mdi:lock", icon_off_override="mdi:lock-open"))
|
||||||
|
|
||||||
|
# Freezer entities
|
||||||
|
if fridge_model_info is None or fridge_model_info.has_freezer:
|
||||||
|
freezer_entities.extend([
|
||||||
|
GeErdPropertySensor(self, ErdCode.CURRENT_TEMPERATURE, "freezer"),
|
||||||
|
GeFreezer(self),
|
||||||
|
])
|
||||||
|
if turbo_freeze is not None:
|
||||||
|
freezer_entities.append(GeErdSwitch(self, ErdCode.TURBO_FREEZE_STATUS))
|
||||||
|
if ice_boost is not None:
|
||||||
|
freezer_entities.append(GeErdSwitch(self, ErdCode.FRIDGE_ICE_BOOST))
|
||||||
|
if(ice_maker_control and ice_maker_control.status_freezer != ErdOnOff.NA):
|
||||||
|
freezer_entities.append(GeErdPropertyBinarySensor(self, ErdCode.ICE_MAKER_CONTROL, "status_freezer"))
|
||||||
|
freezer_entities.append(GeFridgeIceControlSwitch(self, "freezer"))
|
||||||
|
if(ice_bucket_status and ice_bucket_status.is_present_freezer):
|
||||||
|
freezer_entities.append(GeErdPropertySensor(self, ErdCode.ICE_MAKER_BUCKET_STATUS, "state_full_freezer"))
|
||||||
|
|
||||||
|
# Dispenser entities
|
||||||
|
if(hot_water_status and hot_water_status.status != ErdHotWaterStatus.NA):
|
||||||
|
dispenser_entities.extend([
|
||||||
|
GeErdBinarySensor(self, ErdCode.HOT_WATER_IN_USE),
|
||||||
|
GeErdSensor(self, ErdCode.HOT_WATER_SET_TEMP),
|
||||||
|
GeErdPropertySensor(self, ErdCode.HOT_WATER_STATUS, "status", icon_override="mdi:information-outline"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.HOT_WATER_STATUS, "time_until_ready", icon_override="mdi:timer-outline"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.HOT_WATER_STATUS, "current_temp", device_class_override=SensorDeviceClass.TEMPERATURE, data_type_override=ErdDataType.INT),
|
||||||
|
GeErdPropertyBinarySensor(self, ErdCode.HOT_WATER_STATUS, "faulted", device_class_override=BinarySensorDeviceClass.PROBLEM),
|
||||||
|
GeDispenser(self)
|
||||||
|
])
|
||||||
|
|
||||||
|
entities = base_entities + common_entities + fridge_entities + freezer_entities + dispenser_entities
|
||||||
|
return entities
|
||||||
52
devices/hood.py
Normal file
52
devices/hood.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk import (
|
||||||
|
ErdCode,
|
||||||
|
ErdApplianceType,
|
||||||
|
ErdHoodFanSpeedAvailability,
|
||||||
|
ErdHoodLightLevelAvailability,
|
||||||
|
ErdOnOff
|
||||||
|
)
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from ..entities import (
|
||||||
|
GeHoodLightLevelSelect,
|
||||||
|
GeHoodFanSpeedSelect,
|
||||||
|
GeErdTimerSensor,
|
||||||
|
GeErdSwitch,
|
||||||
|
ErdOnOffBoolConverter
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class HoodApi(ApplianceApi):
|
||||||
|
"""API class for Oven Hood objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.HOOD
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
#get the availabilities
|
||||||
|
fan_availability: ErdHoodFanSpeedAvailability = self.try_get_erd_value(ErdCode.HOOD_FAN_SPEED_AVAILABILITY)
|
||||||
|
light_availability: ErdHoodLightLevelAvailability = self.try_get_erd_value(ErdCode.HOOD_LIGHT_LEVEL_AVAILABILITY)
|
||||||
|
timer_availability: ErdOnOff = self.try_get_erd_value(ErdCode.HOOD_TIMER_AVAILABILITY)
|
||||||
|
|
||||||
|
hood_entities = [
|
||||||
|
#looks like this is always available?
|
||||||
|
GeErdSwitch(self, ErdCode.HOOD_DELAY_OFF, bool_converter=ErdOnOffBoolConverter(), icon_on_override="mdi:power-on", icon_off_override="mdi:power-off"),
|
||||||
|
]
|
||||||
|
|
||||||
|
if fan_availability and fan_availability.is_available:
|
||||||
|
hood_entities.append(GeHoodFanSpeedSelect(self, ErdCode.HOOD_FAN_SPEED))
|
||||||
|
#for now, represent as a select
|
||||||
|
if light_availability and light_availability.is_available:
|
||||||
|
hood_entities.append(GeHoodLightLevelSelect(self, ErdCode.HOOD_LIGHT_LEVEL))
|
||||||
|
if timer_availability == ErdOnOff.ON:
|
||||||
|
hood_entities.append(GeErdTimerSensor(self, ErdCode.HOOD_TIMER))
|
||||||
|
|
||||||
|
entities = base_entities + hood_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
56
devices/microwave.py
Normal file
56
devices/microwave.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk import (
|
||||||
|
ErdCode,
|
||||||
|
ErdApplianceType,
|
||||||
|
ErdHoodFanSpeedAvailability,
|
||||||
|
ErdHoodLightLevelAvailability,
|
||||||
|
ErdOnOff
|
||||||
|
)
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from ..entities import (
|
||||||
|
GeHoodLightLevelSelect,
|
||||||
|
GeHoodFanSpeedSelect,
|
||||||
|
GeErdPropertySensor,
|
||||||
|
GeErdPropertyBinarySensor,
|
||||||
|
GeErdBinarySensor,
|
||||||
|
GeErdTimerSensor
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class MicrowaveApi(ApplianceApi):
|
||||||
|
"""API class for Microwave objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.MICROWAVE
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
#get the availabilities
|
||||||
|
fan_availability: ErdHoodFanSpeedAvailability = self.try_get_erd_value(ErdCode.HOOD_FAN_SPEED_AVAILABILITY)
|
||||||
|
light_availability: ErdHoodLightLevelAvailability = self.try_get_erd_value(ErdCode.HOOD_LIGHT_LEVEL_AVAILABILITY)
|
||||||
|
|
||||||
|
mwave_entities = [
|
||||||
|
GeErdBinarySensor(self, ErdCode.MICROWAVE_REMOTE_ENABLE),
|
||||||
|
GeErdPropertySensor(self, ErdCode.MICROWAVE_STATE, "status"),
|
||||||
|
GeErdPropertyBinarySensor(self, ErdCode.MICROWAVE_STATE, "door_status", device_class_override="door"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.MICROWAVE_STATE, "cook_mode", icon_override="mdi:food-turkey"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.MICROWAVE_STATE, "power_level", icon_override="mdi:gauge"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.MICROWAVE_STATE, "temperature", icon_override="mdi:thermometer"),
|
||||||
|
GeErdTimerSensor(self, ErdCode.MICROWAVE_COOK_TIMER),
|
||||||
|
GeErdTimerSensor(self, ErdCode.MICROWAVE_KITCHEN_TIMER)
|
||||||
|
]
|
||||||
|
|
||||||
|
if fan_availability and fan_availability.is_available:
|
||||||
|
mwave_entities.append(GeHoodFanSpeedSelect(self, ErdCode.HOOD_FAN_SPEED))
|
||||||
|
#for now, represent as a select
|
||||||
|
if light_availability and light_availability.is_available:
|
||||||
|
mwave_entities.append(GeHoodLightLevelSelect(self, ErdCode.HOOD_LIGHT_LEVEL))
|
||||||
|
|
||||||
|
entities = base_entities + mwave_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
41
devices/oim.py
Normal file
41
devices/oim.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk import (
|
||||||
|
ErdCode,
|
||||||
|
ErdApplianceType,
|
||||||
|
ErdOnOff
|
||||||
|
)
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from ..entities import (
|
||||||
|
OimLightLevelOptionsConverter,
|
||||||
|
GeErdSensor,
|
||||||
|
GeErdBinarySensor,
|
||||||
|
GeErdSelect,
|
||||||
|
GeErdSwitch,
|
||||||
|
ErdOnOffBoolConverter
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class OimApi(ApplianceApi):
|
||||||
|
"""API class for Opal Ice Maker objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.OPAL_ICE_MAKER
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
oim_entities = [
|
||||||
|
GeErdSensor(self, ErdCode.OIM_STATUS),
|
||||||
|
GeErdBinarySensor(self, ErdCode.OIM_FILTER_STATUS, device_class_override="problem"),
|
||||||
|
GeErdBinarySensor(self, ErdCode.OIM_NEEDS_DESCALING, device_class_override="problem"),
|
||||||
|
GeErdSelect(self, ErdCode.OIM_LIGHT_LEVEL, OimLightLevelOptionsConverter()),
|
||||||
|
GeErdSwitch(self, ErdCode.OIM_POWER, bool_converter=ErdOnOffBoolConverter(), icon_on_override="mdi:power-on", icon_off_override="mdi:power-off"),
|
||||||
|
]
|
||||||
|
|
||||||
|
entities = base_entities + oim_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
146
devices/oven.py
Normal file
146
devices/oven.py
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
from gehomesdk.erd.erd_data_type import ErdDataType
|
||||||
|
|
||||||
|
from homeassistant.components.sensor import SensorDeviceClass
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk import (
|
||||||
|
ErdCode,
|
||||||
|
ErdApplianceType,
|
||||||
|
OvenConfiguration,
|
||||||
|
ErdCooktopConfig,
|
||||||
|
CooktopStatus,
|
||||||
|
ErdOvenLightLevel,
|
||||||
|
ErdOvenLightLevelAvailability,
|
||||||
|
ErdOvenWarmingState
|
||||||
|
)
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from ..entities import (
|
||||||
|
GeErdSensor,
|
||||||
|
GeErdTimerSensor,
|
||||||
|
GeErdBinarySensor,
|
||||||
|
GeErdPropertySensor,
|
||||||
|
GeErdPropertyBinarySensor,
|
||||||
|
GeOven,
|
||||||
|
GeOvenLightLevelSelect,
|
||||||
|
GeOvenWarmingStateSelect,
|
||||||
|
UPPER_OVEN,
|
||||||
|
LOWER_OVEN
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class OvenApi(ApplianceApi):
|
||||||
|
"""API class for oven objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.OVEN
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
oven_config: OvenConfiguration = self.appliance.get_erd_value(ErdCode.OVEN_CONFIGURATION)
|
||||||
|
|
||||||
|
cooktop_config = ErdCooktopConfig.NONE
|
||||||
|
if self.has_erd_code(ErdCode.COOKTOP_CONFIG):
|
||||||
|
cooktop_config: ErdCooktopConfig = self.appliance.get_erd_value(ErdCode.COOKTOP_CONFIG)
|
||||||
|
|
||||||
|
has_upper_raw_temperature = self.has_erd_code(ErdCode.UPPER_OVEN_RAW_TEMPERATURE)
|
||||||
|
has_lower_raw_temperature = self.has_erd_code(ErdCode.LOWER_OVEN_RAW_TEMPERATURE)
|
||||||
|
|
||||||
|
has_upper_probe_temperature = self.has_erd_code(ErdCode.UPPER_OVEN_PROBE_DISPLAY_TEMP)
|
||||||
|
has_lower_probe_temperature = self.has_erd_code(ErdCode.LOWER_OVEN_PROBE_DISPLAY_TEMP)
|
||||||
|
|
||||||
|
upper_light : ErdOvenLightLevel = self.try_get_erd_value(ErdCode.UPPER_OVEN_LIGHT)
|
||||||
|
upper_light_availability: ErdOvenLightLevelAvailability = self.try_get_erd_value(ErdCode.UPPER_OVEN_LIGHT_AVAILABILITY)
|
||||||
|
lower_light : ErdOvenLightLevel = self.try_get_erd_value(ErdCode.LOWER_OVEN_LIGHT)
|
||||||
|
lower_light_availability: ErdOvenLightLevelAvailability = self.try_get_erd_value(ErdCode.LOWER_OVEN_LIGHT_AVAILABILITY)
|
||||||
|
|
||||||
|
upper_warm_drawer : ErdOvenWarmingState = self.try_get_erd_value(ErdCode.UPPER_OVEN_WARMING_DRAWER_STATE)
|
||||||
|
lower_warm_drawer : ErdOvenWarmingState = self.try_get_erd_value(ErdCode.LOWER_OVEN_WARMING_DRAWER_STATE)
|
||||||
|
warm_drawer : ErdOvenWarmingState = self.try_get_erd_value(ErdCode.WARMING_DRAWER_STATE)
|
||||||
|
|
||||||
|
_LOGGER.debug(f"Oven Config: {oven_config}")
|
||||||
|
_LOGGER.debug(f"Cooktop Config: {cooktop_config}")
|
||||||
|
oven_entities = []
|
||||||
|
cooktop_entities = []
|
||||||
|
|
||||||
|
if oven_config.has_lower_oven:
|
||||||
|
oven_entities.extend([
|
||||||
|
GeErdSensor(self, ErdCode.LOWER_OVEN_COOK_MODE),
|
||||||
|
GeErdSensor(self, ErdCode.LOWER_OVEN_CURRENT_STATE),
|
||||||
|
GeErdSensor(self, ErdCode.LOWER_OVEN_COOK_TIME_REMAINING),
|
||||||
|
GeErdTimerSensor(self, ErdCode.LOWER_OVEN_KITCHEN_TIMER),
|
||||||
|
GeErdSensor(self, ErdCode.LOWER_OVEN_USER_TEMP_OFFSET),
|
||||||
|
GeErdSensor(self, ErdCode.LOWER_OVEN_DISPLAY_TEMPERATURE),
|
||||||
|
GeErdBinarySensor(self, ErdCode.LOWER_OVEN_REMOTE_ENABLED),
|
||||||
|
|
||||||
|
GeOven(self, LOWER_OVEN, True, self._temperature_code(has_lower_raw_temperature))
|
||||||
|
])
|
||||||
|
if has_lower_raw_temperature:
|
||||||
|
oven_entities.append(GeErdSensor(self, ErdCode.LOWER_OVEN_RAW_TEMPERATURE))
|
||||||
|
if lower_light_availability is None or lower_light_availability.is_available or lower_light is not None:
|
||||||
|
oven_entities.append(GeOvenLightLevelSelect(self, ErdCode.LOWER_OVEN_LIGHT))
|
||||||
|
if lower_warm_drawer is not None:
|
||||||
|
oven_entities.append(GeOvenWarmingStateSelect(self, ErdCode.LOWER_OVEN_WARMING_DRAWER_STATE))
|
||||||
|
if has_lower_probe_temperature:
|
||||||
|
oven_entities.append(GeErdSensor(self, ErdCode.LOWER_OVEN_PROBE_DISPLAY_TEMP))
|
||||||
|
|
||||||
|
oven_entities.extend([
|
||||||
|
GeErdSensor(self, ErdCode.UPPER_OVEN_COOK_MODE, self._single_name(ErdCode.UPPER_OVEN_COOK_MODE, ~oven_config.has_lower_oven)),
|
||||||
|
GeErdSensor(self, ErdCode.UPPER_OVEN_CURRENT_STATE, self._single_name(ErdCode.UPPER_OVEN_CURRENT_STATE, ~oven_config.has_lower_oven)),
|
||||||
|
GeErdSensor(self, ErdCode.UPPER_OVEN_COOK_TIME_REMAINING, self._single_name(ErdCode.UPPER_OVEN_COOK_TIME_REMAINING, ~oven_config.has_lower_oven)),
|
||||||
|
GeErdTimerSensor(self, ErdCode.UPPER_OVEN_KITCHEN_TIMER, self._single_name(ErdCode.UPPER_OVEN_KITCHEN_TIMER, ~oven_config.has_lower_oven)),
|
||||||
|
GeErdSensor(self, ErdCode.UPPER_OVEN_USER_TEMP_OFFSET, self._single_name(ErdCode.UPPER_OVEN_USER_TEMP_OFFSET, ~oven_config.has_lower_oven)),
|
||||||
|
GeErdSensor(self, ErdCode.UPPER_OVEN_DISPLAY_TEMPERATURE, self._single_name(ErdCode.UPPER_OVEN_DISPLAY_TEMPERATURE, ~oven_config.has_lower_oven)),
|
||||||
|
GeErdBinarySensor(self, ErdCode.UPPER_OVEN_REMOTE_ENABLED, self._single_name(ErdCode.UPPER_OVEN_REMOTE_ENABLED, ~oven_config.has_lower_oven)),
|
||||||
|
|
||||||
|
GeOven(self, UPPER_OVEN, False, self._temperature_code(has_upper_raw_temperature))
|
||||||
|
])
|
||||||
|
if has_upper_raw_temperature:
|
||||||
|
oven_entities.append(GeErdSensor(self, ErdCode.UPPER_OVEN_RAW_TEMPERATURE, self._single_name(ErdCode.UPPER_OVEN_RAW_TEMPERATURE, ~oven_config.has_lower_oven)))
|
||||||
|
if upper_light_availability is None or upper_light_availability.is_available or upper_light is not None:
|
||||||
|
oven_entities.append(GeOvenLightLevelSelect(self, ErdCode.UPPER_OVEN_LIGHT, self._single_name(ErdCode.UPPER_OVEN_LIGHT, ~oven_config.has_lower_oven)))
|
||||||
|
if upper_warm_drawer is not None:
|
||||||
|
oven_entities.append(GeOvenWarmingStateSelect(self, ErdCode.UPPER_OVEN_WARMING_DRAWER_STATE, self._single_name(ErdCode.UPPER_OVEN_WARMING_DRAWER_STATE, ~oven_config.has_lower_oven)))
|
||||||
|
if has_upper_probe_temperature:
|
||||||
|
oven_entities.append(GeErdSensor(self, ErdCode.UPPER_OVEN_PROBE_DISPLAY_TEMP, self._single_name(ErdCode.UPPER_OVEN_PROBE_DISPLAY_TEMP, ~oven_config.has_lower_oven)))
|
||||||
|
|
||||||
|
if oven_config.has_warming_drawer and warm_drawer is not None:
|
||||||
|
oven_entities.append(GeErdSensor(self, ErdCode.WARMING_DRAWER_STATE))
|
||||||
|
|
||||||
|
if cooktop_config == ErdCooktopConfig.PRESENT:
|
||||||
|
# attempt to get the cooktop status using legacy status
|
||||||
|
cooktop_status_erd = ErdCode.COOKTOP_STATUS
|
||||||
|
cooktop_status: CooktopStatus = self.try_get_erd_value(ErdCode.COOKTOP_STATUS)
|
||||||
|
|
||||||
|
# if we didn't get it, try using the new version
|
||||||
|
if cooktop_status is None:
|
||||||
|
cooktop_status_erd = ErdCode.COOKTOP_STATUS_EXT
|
||||||
|
cooktop_status: CooktopStatus = self.try_get_erd_value(ErdCode.COOKTOP_STATUS_EXT)
|
||||||
|
|
||||||
|
# if we got a status through either mechanism, we can add the entities
|
||||||
|
if cooktop_status is not None:
|
||||||
|
cooktop_entities.append(GeErdBinarySensor(self, cooktop_status_erd))
|
||||||
|
|
||||||
|
for (k, v) in cooktop_status.burners.items():
|
||||||
|
if v.exists:
|
||||||
|
prop = self._camel_to_snake(k)
|
||||||
|
cooktop_entities.append(GeErdPropertyBinarySensor(self, cooktop_status_erd, prop+".on"))
|
||||||
|
cooktop_entities.append(GeErdPropertyBinarySensor(self, cooktop_status_erd, prop+".synchronized"))
|
||||||
|
if not v.on_off_only:
|
||||||
|
cooktop_entities.append(GeErdPropertySensor(self, cooktop_status_erd, prop+".power_pct", icon_override="mdi:fire", device_class_override=SensorDeviceClass.POWER_FACTOR, data_type_override=ErdDataType.INT))
|
||||||
|
|
||||||
|
return base_entities + oven_entities + cooktop_entities
|
||||||
|
|
||||||
|
def _single_name(self, erd_code: ErdCode, make_single: bool):
|
||||||
|
name = erd_code.name
|
||||||
|
|
||||||
|
if make_single:
|
||||||
|
name = name.replace(UPPER_OVEN+"_","")
|
||||||
|
|
||||||
|
return name.replace("_", " ").title()
|
||||||
|
|
||||||
|
def _camel_to_snake(self, s):
|
||||||
|
return ''.join(['_'+c.lower() if c.isupper() else c for c in s]).lstrip('_')
|
||||||
|
|
||||||
|
def _temperature_code(self, has_raw: bool):
|
||||||
|
return "RAW_TEMPERATURE" if has_raw else "DISPLAY_TEMPERATURE"
|
||||||
31
devices/pac.py
Normal file
31
devices/pac.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
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 GePacClimate, GeErdSensor, GeErdSwitch, ErdOnOffBoolConverter
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class PacApi(ApplianceApi):
|
||||||
|
"""API class for Portable AC objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.PORTABLE_AIR_CONDITIONER
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
pac_entities = [
|
||||||
|
GePacClimate(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"),
|
||||||
|
]
|
||||||
|
|
||||||
|
entities = base_entities + pac_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
37
devices/sac.py
Normal file
37
devices/sac.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
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 GeSacClimate, GeErdSensor, GeErdSwitch, ErdOnOffBoolConverter
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class SacApi(ApplianceApi):
|
||||||
|
"""API class for Split AC objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.SPLIT_AIR_CONDITIONER
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
sac_entities = [
|
||||||
|
GeSacClimate(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"),
|
||||||
|
]
|
||||||
|
|
||||||
|
if self.has_erd_code(ErdCode.SAC_SLEEP_MODE):
|
||||||
|
sac_entities.append(GeErdSwitch(self, ErdCode.SAC_SLEEP_MODE, bool_converter=ErdOnOffBoolConverter(), icon_on_override="mdi:sleep", icon_off_override="mdi:sleep-off"))
|
||||||
|
if self.has_erd_code(ErdCode.SAC_AUTO_SWING_MODE):
|
||||||
|
sac_entities.append(GeErdSwitch(self, ErdCode.SAC_AUTO_SWING_MODE, bool_converter=ErdOnOffBoolConverter(), icon_on_override="mdi:arrow-decision-auto", icon_off_override="mdi:arrow-decision-auto-outline"))
|
||||||
|
|
||||||
|
|
||||||
|
entities = base_entities + sac_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
45
devices/ucim.py
Normal file
45
devices/ucim.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk import (
|
||||||
|
ErdCode,
|
||||||
|
ErdApplianceType,
|
||||||
|
ErdOnOff
|
||||||
|
)
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from ..entities import (
|
||||||
|
OimLightLevelOptionsConverter,
|
||||||
|
GeErdSensor,
|
||||||
|
GeErdBinarySensor,
|
||||||
|
GeErdSelect,
|
||||||
|
GeErdSwitch,
|
||||||
|
ErdOnOffBoolConverter
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class UcimApi(ApplianceApi):
|
||||||
|
"""API class for Opal Ice Maker objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.OPAL_ICE_MAKER
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
oim_entities = [
|
||||||
|
GeErdSensor(self, ErdCode.OIM_STATUS),
|
||||||
|
GeErdBinarySensor(self, ErdCode.OIM_FILTER_STATUS, device_class_override="problem"),
|
||||||
|
GeErdBinarySensor(self, ErdCode.OIM_NEEDS_DESCALING, device_class_override="problem"),
|
||||||
|
GeErdSelect(self, ErdCode.OIM_LIGHT_LEVEL, OimLightLevelOptionsConverter()),
|
||||||
|
GeErdSwitch(self, ErdCode.OIM_POWER, bool_converter=ErdOnOffBoolConverter(), icon_on_override="mdi:power-on", icon_off_override="mdi:power-off"),
|
||||||
|
GeErdSensor(self, ErdCode.OIM_PRODUCTION),
|
||||||
|
GeErdSensor(self, ErdCode.UCIM_CLEAN_STATUS),
|
||||||
|
GeErdSensor(self, ErdCode.UCIM_FILTER_PERCENTAGE_USED),
|
||||||
|
GeErdBinarySensor(self, ErdCode.UCIM_BIN_FULL, device_class_override="problem"),
|
||||||
|
]
|
||||||
|
|
||||||
|
entities = base_entities + oim_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
33
devices/wac.py
Normal file
33
devices/wac.py
Normal file
@ -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 GeWacClimate, GeErdSensor, GeErdBinarySensor, GeErdSwitch, ErdOnOffBoolConverter
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class WacApi(ApplianceApi):
|
||||||
|
"""API class for Window AC objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.AIR_CONDITIONER
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
wac_entities = [
|
||||||
|
GeWacClimate(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 + wac_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
63
devices/washer.py
Normal file
63
devices/washer.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk import ErdCode, ErdApplianceType
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from ..entities import GeErdSensor, GeErdBinarySensor, GeErdPropertySensor
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class WasherApi(ApplianceApi):
|
||||||
|
"""API class for washer objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.WASHER
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
common_entities = [
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_MACHINE_STATE),
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_CYCLE, icon_override="mdi:state-machine"),
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_SUB_CYCLE, icon_override="mdi:state-machine"),
|
||||||
|
GeErdBinarySensor(self, ErdCode.LAUNDRY_END_OF_CYCLE),
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_TIME_REMAINING),
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_DELAY_TIME_REMAINING),
|
||||||
|
GeErdBinarySensor(self, ErdCode.LAUNDRY_DOOR),
|
||||||
|
GeErdBinarySensor(self, ErdCode.LAUNDRY_REMOTE_STATUS),
|
||||||
|
]
|
||||||
|
|
||||||
|
washer_entities = self.get_washer_entities()
|
||||||
|
|
||||||
|
entities = base_entities + common_entities + washer_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
|
def get_washer_entities(self) -> List[Entity]:
|
||||||
|
washer_entities = [
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_WASHER_SOIL_LEVEL, icon_override="mdi:emoticon-poop"),
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_WASHER_WASHTEMP_LEVEL),
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_WASHER_SPINTIME_LEVEL, icon_override="mdi:speedometer"),
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_WASHER_RINSE_OPTION, icon_override="mdi:shimmer"),
|
||||||
|
]
|
||||||
|
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_WASHER_DOOR_LOCK):
|
||||||
|
washer_entities.extend([GeErdBinarySensor(self, ErdCode.LAUNDRY_WASHER_DOOR_LOCK)])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_WASHER_TANK_STATUS):
|
||||||
|
washer_entities.extend([GeErdSensor(self, ErdCode.LAUNDRY_WASHER_TANK_STATUS)])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_WASHER_TANK_SELECTED):
|
||||||
|
washer_entities.extend([GeErdSensor(self, ErdCode.LAUNDRY_WASHER_TANK_SELECTED)])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_WASHER_TIMESAVER):
|
||||||
|
washer_entities.extend([GeErdBinarySensor(self, ErdCode.LAUNDRY_WASHER_TIMESAVER, icon_on_override="mdi:sort-clock-ascending", icon_off_override="mdi:sort-clock-ascending-outline")])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_WASHER_POWERSTEAM):
|
||||||
|
washer_entities.extend([GeErdBinarySensor(self, ErdCode.LAUNDRY_WASHER_POWERSTEAM, icon_on_override="mdi:kettle-steam", icon_off_override="mdi:kettle-steam-outline")])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_WASHER_PREWASH):
|
||||||
|
washer_entities.extend([GeErdBinarySensor(self, ErdCode.LAUNDRY_WASHER_PREWASH, icon_on_override="mdi:water-plus", icon_off_override="mdi:water-remove-outline")])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_WASHER_TUMBLECARE):
|
||||||
|
washer_entities.extend([GeErdBinarySensor(self, ErdCode.LAUNDRY_WASHER_TUMBLECARE)])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_WASHER_SMART_DISPENSE):
|
||||||
|
washer_entities.extend([GeErdPropertySensor(self, ErdCode.LAUNDRY_WASHER_SMART_DISPENSE, "loads_left", uom_override="loads")])
|
||||||
|
if self.has_erd_code(ErdCode.LAUNDRY_WASHER_SMART_DISPENSE_TANK_STATUS):
|
||||||
|
washer_entities.extend([GeErdSensor(self, ErdCode.LAUNDRY_WASHER_SMART_DISPENSE_TANK_STATUS)])
|
||||||
|
|
||||||
|
return washer_entities
|
||||||
36
devices/washer_dryer.py
Normal file
36
devices/washer_dryer.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk import ErdCode, ErdApplianceType
|
||||||
|
|
||||||
|
from .washer import WasherApi
|
||||||
|
from .dryer import DryerApi
|
||||||
|
from ..entities import GeErdSensor, GeErdBinarySensor
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class WasherDryerApi(WasherApi, DryerApi):
|
||||||
|
"""API class for washer/dryer objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.COMBINATION_WASHER_DRYER
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = self.get_base_entities()
|
||||||
|
|
||||||
|
common_entities = [
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_MACHINE_STATE),
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_CYCLE),
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_SUB_CYCLE),
|
||||||
|
GeErdBinarySensor(self, ErdCode.LAUNDRY_END_OF_CYCLE),
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_TIME_REMAINING),
|
||||||
|
GeErdSensor(self, ErdCode.LAUNDRY_DELAY_TIME_REMAINING),
|
||||||
|
GeErdBinarySensor(self, ErdCode.LAUNDRY_DOOR),
|
||||||
|
GeErdBinarySensor(self, ErdCode.LAUNDRY_REMOTE_STATUS),
|
||||||
|
]
|
||||||
|
|
||||||
|
washer_entities = self.get_washer_entities()
|
||||||
|
dryer_entities = self.get_dryer_entities()
|
||||||
|
|
||||||
|
entities = base_entities + common_entities + washer_entities + dryer_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
38
devices/water_filter.py
Normal file
38
devices/water_filter.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk import ErdCode, ErdApplianceType
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from ..entities import (
|
||||||
|
GeErdSensor,
|
||||||
|
GeErdPropertySensor,
|
||||||
|
GeErdBinarySensor,
|
||||||
|
GeErdFilterPositionSelect,
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class WaterFilterApi(ApplianceApi):
|
||||||
|
"""API class for water filter objects"""
|
||||||
|
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.POE_WATER_FILTER
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
wf_entities = [
|
||||||
|
GeErdSensor(self, ErdCode.WH_FILTER_MODE),
|
||||||
|
GeErdSensor(self, ErdCode.WH_FILTER_VALVE_STATE, icon_override="mdi:state-machine"),
|
||||||
|
GeErdFilterPositionSelect(self, ErdCode.WH_FILTER_POSITION),
|
||||||
|
GeErdBinarySensor(self, ErdCode.WH_FILTER_MANUAL_MODE, icon_on_override="mdi:human", icon_off_override="mdi:robot"),
|
||||||
|
GeErdBinarySensor(self, ErdCode.WH_FILTER_LEAK_VALIDITY, device_class_override="moisture"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.WH_FILTER_FLOW_RATE, "flow_rate"),
|
||||||
|
GeErdSensor(self, ErdCode.WH_FILTER_DAY_USAGE, device_class_override="water"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.WH_FILTER_LIFE_REMAINING, "life_remaining"),
|
||||||
|
GeErdBinarySensor(self, ErdCode.WH_FILTER_FLOW_ALERT, device_class_override="moisture"),
|
||||||
|
]
|
||||||
|
entities = base_entities + wf_entities
|
||||||
|
return entities
|
||||||
54
devices/water_heater.py
Normal file
54
devices/water_heater.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk import (
|
||||||
|
ErdCode,
|
||||||
|
ErdApplianceType,
|
||||||
|
ErdOnOff
|
||||||
|
)
|
||||||
|
|
||||||
|
from custom_components.ge_home.entities.water_heater.ge_water_heater import GeWaterHeater
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from ..entities import (
|
||||||
|
GeErdSensor,
|
||||||
|
GeErdBinarySensor,
|
||||||
|
GeErdSelect,
|
||||||
|
GeErdSwitch,
|
||||||
|
ErdOnOffBoolConverter
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class WaterHeaterApi(ApplianceApi):
|
||||||
|
"""API class for Water Heater objects"""
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.WATER_HEATER
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
boost_mode: ErdOnOff = self.try_get_erd_value(ErdCode.WH_HEATER_BOOST_STATE)
|
||||||
|
active: ErdOnOff = self.try_get_erd_value(ErdCode.WH_HEATER_ACTIVE_STATE)
|
||||||
|
|
||||||
|
wh_entities = [
|
||||||
|
GeErdSensor(self, ErdCode.WH_HEATER_TARGET_TEMPERATURE),
|
||||||
|
GeErdSensor(self, ErdCode.WH_HEATER_TEMPERATURE),
|
||||||
|
GeErdSensor(self, ErdCode.WH_HEATER_MODE_HOURS_REMAINING),
|
||||||
|
GeErdSensor(self, ErdCode.WH_HEATER_ELECTRIC_MODE_MAX_TIME),
|
||||||
|
GeErdSensor(self, ErdCode.WH_HEATER_VACATION_MODE_MAX_TIME),
|
||||||
|
GeWaterHeater(self)
|
||||||
|
]
|
||||||
|
|
||||||
|
if(boost_mode and boost_mode != ErdOnOff.NA):
|
||||||
|
wh_entities.append(GeErdSensor(self, ErdCode.WH_HEATER_BOOST_STATE))
|
||||||
|
wh_entities.append(GeErdSwitch(self, ErdCode.WH_HEATER_BOOST_CONTROL, ErdOnOffBoolConverter(), icon_on_override="mdi:rocket-launch", icon_off_override="mdi:rocket-launch-outline"))
|
||||||
|
|
||||||
|
if(active and active != ErdOnOff.NA):
|
||||||
|
wh_entities.append(GeErdSensor(self, ErdCode.WH_HEATER_ACTIVE_STATE))
|
||||||
|
wh_entities.append(GeErdSwitch(self, ErdCode.WH_HEATER_ACTIVE_CONTROL, ErdOnOffBoolConverter(), icon_on_override="mdi:power", icon_off_override="mdi:power-standby"))
|
||||||
|
|
||||||
|
entities = base_entities + wh_entities
|
||||||
|
return entities
|
||||||
|
|
||||||
38
devices/water_softener.py
Normal file
38
devices/water_softener.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import logging
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from gehomesdk import ErdCode, ErdApplianceType
|
||||||
|
|
||||||
|
from .base import ApplianceApi
|
||||||
|
from ..entities import (
|
||||||
|
GeErdSensor,
|
||||||
|
GeErdPropertySensor,
|
||||||
|
GeErdBinarySensor,
|
||||||
|
GeErdShutoffPositionSelect,
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class WaterSoftenerApi(ApplianceApi):
|
||||||
|
"""API class for water softener objects"""
|
||||||
|
|
||||||
|
APPLIANCE_TYPE = ErdApplianceType.WATER_SOFTENER
|
||||||
|
|
||||||
|
def get_all_entities(self) -> List[Entity]:
|
||||||
|
base_entities = super().get_all_entities()
|
||||||
|
|
||||||
|
ws_entities = [
|
||||||
|
GeErdBinarySensor(self, ErdCode.WH_FILTER_MANUAL_MODE, icon_on_override="mdi:human", icon_off_override="mdi:robot"),
|
||||||
|
GeErdPropertySensor(self, ErdCode.WH_FILTER_FLOW_RATE, "flow_rate"),
|
||||||
|
GeErdBinarySensor(self, ErdCode.WH_FILTER_FLOW_ALERT, device_class_override="moisture"),
|
||||||
|
GeErdSensor(self, ErdCode.WH_FILTER_DAY_USAGE, device_class_override="water"),
|
||||||
|
GeErdSensor(self, ErdCode.WH_SOFTENER_ERROR_CODE, icon_override="mdi:alert-circle"),
|
||||||
|
GeErdBinarySensor(self, ErdCode.WH_SOFTENER_LOW_SALT, icon_on_override="mdi:alert", icon_off_override="mdi:grain"),
|
||||||
|
GeErdSensor(self, ErdCode.WH_SOFTENER_SHUTOFF_VALVE_STATE, icon_override="mdi:state-machine"),
|
||||||
|
GeErdSensor(self, ErdCode.WH_SOFTENER_SALT_LIFE_REMAINING, icon_override="mdi:calendar-clock"),
|
||||||
|
GeErdShutoffPositionSelect(self, ErdCode.WH_SOFTENER_SHUTOFF_VALVE_CONTROL),
|
||||||
|
]
|
||||||
|
entities = base_entities + ws_entities
|
||||||
|
return entities
|
||||||
13
entities/__init__.py
Normal file
13
entities/__init__.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from .common import *
|
||||||
|
from .dishwasher import *
|
||||||
|
from .fridge import *
|
||||||
|
from .oven import *
|
||||||
|
from .water_filter import *
|
||||||
|
from .advantium import *
|
||||||
|
from .ac import *
|
||||||
|
from .hood import *
|
||||||
|
from .water_softener import *
|
||||||
|
from .water_heater import *
|
||||||
|
from .opal_ice_maker import *
|
||||||
|
from .ccm import *
|
||||||
|
from .dehumidifier import *
|
||||||
BIN
entities/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
entities/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
4
entities/ac/__init__.py
Normal file
4
entities/ac/__init__.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
from .ge_wac_climate import GeWacClimate
|
||||||
|
from .ge_sac_climate import GeSacClimate
|
||||||
|
from .ge_pac_climate import GePacClimate
|
||||||
|
from .ge_biac_climate import GeBiacClimate
|
||||||
BIN
entities/ac/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
entities/ac/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
entities/ac/__pycache__/fan_mode_options.cpython-313.pyc
Normal file
BIN
entities/ac/__pycache__/fan_mode_options.cpython-313.pyc
Normal file
Binary file not shown.
BIN
entities/ac/__pycache__/ge_biac_climate.cpython-313.pyc
Normal file
BIN
entities/ac/__pycache__/ge_biac_climate.cpython-313.pyc
Normal file
Binary file not shown.
BIN
entities/ac/__pycache__/ge_pac_climate.cpython-313.pyc
Normal file
BIN
entities/ac/__pycache__/ge_pac_climate.cpython-313.pyc
Normal file
Binary file not shown.
BIN
entities/ac/__pycache__/ge_sac_climate.cpython-313.pyc
Normal file
BIN
entities/ac/__pycache__/ge_sac_climate.cpython-313.pyc
Normal file
Binary file not shown.
BIN
entities/ac/__pycache__/ge_wac_climate.cpython-313.pyc
Normal file
BIN
entities/ac/__pycache__/ge_wac_climate.cpython-313.pyc
Normal file
Binary file not shown.
45
entities/ac/fan_mode_options.py
Normal file
45
entities/ac/fan_mode_options.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import logging
|
||||||
|
from typing import Any, List, Optional
|
||||||
|
|
||||||
|
from gehomesdk import ErdAcFanSetting
|
||||||
|
from ..common import OptionsConverter
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class AcFanModeOptionsConverter(OptionsConverter):
|
||||||
|
def __init__(self, default_option: ErdAcFanSetting = ErdAcFanSetting.AUTO):
|
||||||
|
self._default = default_option
|
||||||
|
|
||||||
|
@property
|
||||||
|
def options(self) -> List[str]:
|
||||||
|
return [i.stringify() for i in [ErdAcFanSetting.AUTO, ErdAcFanSetting.LOW, ErdAcFanSetting.MED, ErdAcFanSetting.HIGH]]
|
||||||
|
|
||||||
|
def from_option_string(self, value: str) -> Any:
|
||||||
|
try:
|
||||||
|
return ErdAcFanSetting[value.upper().replace(" ","_")]
|
||||||
|
except:
|
||||||
|
_LOGGER.warning(f"Could not set fan mode to {value}")
|
||||||
|
return self._default
|
||||||
|
|
||||||
|
def to_option_string(self, value: Any) -> Optional[str]:
|
||||||
|
try:
|
||||||
|
return {
|
||||||
|
ErdAcFanSetting.AUTO: ErdAcFanSetting.AUTO,
|
||||||
|
ErdAcFanSetting.LOW: ErdAcFanSetting.LOW,
|
||||||
|
ErdAcFanSetting.LOW_AUTO: ErdAcFanSetting.AUTO,
|
||||||
|
ErdAcFanSetting.MED: ErdAcFanSetting.MED,
|
||||||
|
ErdAcFanSetting.MED_AUTO: ErdAcFanSetting.AUTO,
|
||||||
|
ErdAcFanSetting.HIGH: ErdAcFanSetting.HIGH,
|
||||||
|
ErdAcFanSetting.HIGH_AUTO: ErdAcFanSetting.HIGH
|
||||||
|
}.get(value).stringify()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return self._default.stringify()
|
||||||
|
|
||||||
|
class AcFanOnlyFanModeOptionsConverter(AcFanModeOptionsConverter):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(ErdAcFanSetting.LOW)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def options(self) -> List[str]:
|
||||||
|
return [i.stringify() for i in [ErdAcFanSetting.LOW, ErdAcFanSetting.MED, ErdAcFanSetting.HIGH]]
|
||||||
41
entities/ac/ge_biac_climate.py
Normal file
41
entities/ac/ge_biac_climate.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import logging
|
||||||
|
from typing import Any, List, Optional
|
||||||
|
|
||||||
|
from homeassistant.components.climate import HVACMode
|
||||||
|
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 [HVACMode.AUTO, HVACMode.COOL, HVACMode.FAN_ONLY]
|
||||||
|
def from_option_string(self, value: str) -> Any:
|
||||||
|
try:
|
||||||
|
return {
|
||||||
|
HVACMode.AUTO: ErdAcOperationMode.ENERGY_SAVER,
|
||||||
|
HVACMode.COOL: ErdAcOperationMode.COOL,
|
||||||
|
HVACMode.FAN_ONLY: ErdAcOperationMode.FAN_ONLY
|
||||||
|
}.get(value)
|
||||||
|
except:
|
||||||
|
_LOGGER.warning(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: HVACMode.AUTO,
|
||||||
|
ErdAcOperationMode.AUTO: HVACMode.AUTO,
|
||||||
|
ErdAcOperationMode.COOL: HVACMode.COOL,
|
||||||
|
ErdAcOperationMode.FAN_ONLY: HVACMode.FAN_ONLY
|
||||||
|
}.get(value)
|
||||||
|
except:
|
||||||
|
_LOGGER.warning(f"Could not determine operation mode mapping for {value}")
|
||||||
|
return HVACMode.COOL
|
||||||
|
|
||||||
|
class GeBiacClimate(GeClimate):
|
||||||
|
"""Class for Built-In AC units"""
|
||||||
|
def __init__(self, api: ApplianceApi):
|
||||||
|
super().__init__(api, BiacHvacModeOptionsConverter(), AcFanModeOptionsConverter(), AcFanOnlyFanModeOptionsConverter())
|
||||||
71
entities/ac/ge_pac_climate.py
Normal file
71
entities/ac/ge_pac_climate.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import logging
|
||||||
|
from typing import Any, List, Optional
|
||||||
|
|
||||||
|
from homeassistant.components.climate import HVACMode
|
||||||
|
from gehomesdk import ErdCode, ErdAcOperationMode, ErdSacAvailableModes, ErdSacTargetTemperatureRange
|
||||||
|
from ...devices import ApplianceApi
|
||||||
|
from ..common import GeClimate, OptionsConverter
|
||||||
|
from .fan_mode_options import AcFanOnlyFanModeOptionsConverter
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class PacHvacModeOptionsConverter(OptionsConverter):
|
||||||
|
def __init__(self, available_modes: ErdSacAvailableModes):
|
||||||
|
self._available_modes = available_modes
|
||||||
|
|
||||||
|
@property
|
||||||
|
def options(self) -> List[str]:
|
||||||
|
modes = [HVACMode.COOL, HVACMode.FAN_ONLY]
|
||||||
|
if self._available_modes and self._available_modes.has_heat:
|
||||||
|
modes.append(HVACMode.HEAT)
|
||||||
|
if self._available_modes and self._available_modes.has_dry:
|
||||||
|
modes.append(HVACMode.DRY)
|
||||||
|
return modes
|
||||||
|
def from_option_string(self, value: str) -> Any:
|
||||||
|
try:
|
||||||
|
return {
|
||||||
|
HVACMode.COOL: ErdAcOperationMode.COOL,
|
||||||
|
HVACMode.HEAT: ErdAcOperationMode.HEAT,
|
||||||
|
HVACMode.FAN_ONLY: ErdAcOperationMode.FAN_ONLY,
|
||||||
|
HVACMode.DRY: ErdAcOperationMode.DRY
|
||||||
|
}.get(value)
|
||||||
|
except:
|
||||||
|
_LOGGER.warning(f"Could not set HVAC mode to {value.upper()}")
|
||||||
|
return ErdAcOperationMode.COOL
|
||||||
|
def to_option_string(self, value: Any) -> Optional[str]:
|
||||||
|
try:
|
||||||
|
return {
|
||||||
|
ErdAcOperationMode.COOL: HVACMode.COOL,
|
||||||
|
ErdAcOperationMode.HEAT: HVACMode.HEAT,
|
||||||
|
ErdAcOperationMode.DRY: HVACMode.DRY,
|
||||||
|
ErdAcOperationMode.FAN_ONLY: HVACMode.FAN_ONLY
|
||||||
|
}.get(value)
|
||||||
|
except:
|
||||||
|
_LOGGER.warning(f"Could not determine operation mode mapping for {value}")
|
||||||
|
return HVACMode.COOL
|
||||||
|
|
||||||
|
class GePacClimate(GeClimate):
|
||||||
|
"""Class for Portable AC units"""
|
||||||
|
def __init__(self, api: ApplianceApi):
|
||||||
|
#initialize the climate control
|
||||||
|
super().__init__(api, None, AcFanOnlyFanModeOptionsConverter(), AcFanOnlyFanModeOptionsConverter())
|
||||||
|
|
||||||
|
#get a couple ERDs that shouldn't change if available
|
||||||
|
self._modes: ErdSacAvailableModes = self.api.try_get_erd_value(ErdCode.SAC_AVAILABLE_MODES)
|
||||||
|
self._temp_range: ErdSacTargetTemperatureRange = self.api.try_get_erd_value(ErdCode.SAC_TARGET_TEMPERATURE_RANGE)
|
||||||
|
#construct the converter based on the available modes
|
||||||
|
self._hvac_mode_converter = PacHvacModeOptionsConverter(self._modes)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def min_temp(self) -> float:
|
||||||
|
temp = 64
|
||||||
|
if self._temp_range:
|
||||||
|
temp = self._temp_range.min
|
||||||
|
return self._convert_temp(temp)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def max_temp(self) -> float:
|
||||||
|
temp = 86
|
||||||
|
if self._temp_range:
|
||||||
|
temp = self._temp_range.max
|
||||||
|
return self._convert_temp(temp)
|
||||||
75
entities/ac/ge_sac_climate.py
Normal file
75
entities/ac/ge_sac_climate.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import logging
|
||||||
|
from typing import Any, List, Optional
|
||||||
|
|
||||||
|
from homeassistant.components.climate import HVACMode
|
||||||
|
from gehomesdk import ErdCode, ErdAcOperationMode, ErdSacAvailableModes, ErdSacTargetTemperatureRange
|
||||||
|
from ...devices import ApplianceApi
|
||||||
|
from ..common import GeClimate, OptionsConverter
|
||||||
|
from .fan_mode_options import AcFanOnlyFanModeOptionsConverter, AcFanModeOptionsConverter
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class SacHvacModeOptionsConverter(OptionsConverter):
|
||||||
|
def __init__(self, available_modes: ErdSacAvailableModes):
|
||||||
|
self._available_modes = available_modes
|
||||||
|
|
||||||
|
@property
|
||||||
|
def options(self) -> List[str]:
|
||||||
|
modes = [HVACMode.COOL, HVACMode.FAN_ONLY]
|
||||||
|
if self._available_modes and self._available_modes.has_heat:
|
||||||
|
modes.append(HVACMode.HEAT)
|
||||||
|
modes.append(HVACMode.AUTO)
|
||||||
|
if self._available_modes and self._available_modes.has_dry:
|
||||||
|
modes.append(HVACMode.DRY)
|
||||||
|
return modes
|
||||||
|
def from_option_string(self, value: str) -> Any:
|
||||||
|
try:
|
||||||
|
return {
|
||||||
|
HVACMode.AUTO: ErdAcOperationMode.AUTO,
|
||||||
|
HVACMode.COOL: ErdAcOperationMode.COOL,
|
||||||
|
HVACMode.HEAT: ErdAcOperationMode.HEAT,
|
||||||
|
HVACMode.FAN_ONLY: ErdAcOperationMode.FAN_ONLY,
|
||||||
|
HVACMode.DRY: ErdAcOperationMode.DRY
|
||||||
|
}.get(value)
|
||||||
|
except:
|
||||||
|
_LOGGER.warning(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: HVACMode.AUTO,
|
||||||
|
ErdAcOperationMode.AUTO: HVACMode.AUTO,
|
||||||
|
ErdAcOperationMode.COOL: HVACMode.COOL,
|
||||||
|
ErdAcOperationMode.HEAT: HVACMode.HEAT,
|
||||||
|
ErdAcOperationMode.DRY: HVACMode.DRY,
|
||||||
|
ErdAcOperationMode.FAN_ONLY: HVACMode.FAN_ONLY
|
||||||
|
}.get(value)
|
||||||
|
except:
|
||||||
|
_LOGGER.warning(f"Could not determine operation mode mapping for {value}")
|
||||||
|
return HVACMode.COOL
|
||||||
|
|
||||||
|
class GeSacClimate(GeClimate):
|
||||||
|
"""Class for Split AC units"""
|
||||||
|
def __init__(self, api: ApplianceApi):
|
||||||
|
#initialize the climate control
|
||||||
|
super().__init__(api, None, AcFanModeOptionsConverter(), AcFanOnlyFanModeOptionsConverter())
|
||||||
|
|
||||||
|
#get a couple ERDs that shouldn't change if available
|
||||||
|
self._modes: ErdSacAvailableModes = self.api.try_get_erd_value(ErdCode.SAC_AVAILABLE_MODES)
|
||||||
|
self._temp_range: ErdSacTargetTemperatureRange = self.api.try_get_erd_value(ErdCode.SAC_TARGET_TEMPERATURE_RANGE)
|
||||||
|
#construct the converter based on the available modes
|
||||||
|
self._hvac_mode_converter = SacHvacModeOptionsConverter(self._modes)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def min_temp(self) -> float:
|
||||||
|
temp = 60
|
||||||
|
if self._temp_range:
|
||||||
|
temp = self._temp_range.min
|
||||||
|
return self._convert_temp(temp)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def max_temp(self) -> float:
|
||||||
|
temp = 86
|
||||||
|
if self._temp_range:
|
||||||
|
temp = self._temp_range.max
|
||||||
|
return self._convert_temp(temp)
|
||||||
41
entities/ac/ge_wac_climate.py
Normal file
41
entities/ac/ge_wac_climate.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import logging
|
||||||
|
from typing import Any, List, Optional
|
||||||
|
|
||||||
|
from homeassistant.components.climate import HVACMode
|
||||||
|
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 WacHvacModeOptionsConverter(OptionsConverter):
|
||||||
|
@property
|
||||||
|
def options(self) -> List[str]:
|
||||||
|
return [HVACMode.AUTO, HVACMode.COOL, HVACMode.FAN_ONLY]
|
||||||
|
def from_option_string(self, value: str) -> Any:
|
||||||
|
try:
|
||||||
|
return {
|
||||||
|
HVACMode.AUTO: ErdAcOperationMode.ENERGY_SAVER,
|
||||||
|
HVACMode.COOL: ErdAcOperationMode.COOL,
|
||||||
|
HVACMode.FAN_ONLY: ErdAcOperationMode.FAN_ONLY
|
||||||
|
}.get(value)
|
||||||
|
except:
|
||||||
|
_LOGGER.warning(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: HVACMode.AUTO,
|
||||||
|
ErdAcOperationMode.AUTO: HVACMode.AUTO,
|
||||||
|
ErdAcOperationMode.COOL: HVACMode.COOL,
|
||||||
|
ErdAcOperationMode.FAN_ONLY: HVACMode.FAN_ONLY
|
||||||
|
}.get(value)
|
||||||
|
except:
|
||||||
|
_LOGGER.warning(f"Could not determine operation mode mapping for {value}")
|
||||||
|
return HVACMode.COOL
|
||||||
|
|
||||||
|
class GeWacClimate(GeClimate):
|
||||||
|
"""Class for Window AC units"""
|
||||||
|
def __init__(self, api: ApplianceApi):
|
||||||
|
super().__init__(api, WacHvacModeOptionsConverter(), AcFanModeOptionsConverter(), AcFanOnlyFanModeOptionsConverter())
|
||||||
1
entities/advantium/__init__.py
Normal file
1
entities/advantium/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from .ge_advantium import GeAdvantium
|
||||||
BIN
entities/advantium/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
entities/advantium/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
entities/advantium/__pycache__/const.cpython-313.pyc
Normal file
BIN
entities/advantium/__pycache__/const.cpython-313.pyc
Normal file
Binary file not shown.
BIN
entities/advantium/__pycache__/ge_advantium.cpython-313.pyc
Normal file
BIN
entities/advantium/__pycache__/ge_advantium.cpython-313.pyc
Normal file
Binary file not shown.
5
entities/advantium/const.py
Normal file
5
entities/advantium/const.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from homeassistant.components.water_heater import WaterHeaterEntityFeature
|
||||||
|
|
||||||
|
SUPPORT_NONE = WaterHeaterEntityFeature(0)
|
||||||
|
GE_ADVANTIUM_WITH_TEMPERATURE = (WaterHeaterEntityFeature.OPERATION_MODE | WaterHeaterEntityFeature.TARGET_TEMPERATURE)
|
||||||
|
GE_ADVANTIUM = WaterHeaterEntityFeature.OPERATION_MODE
|
||||||
283
entities/advantium/ge_advantium.py
Normal file
283
entities/advantium/ge_advantium.py
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
"""GE Home Sensor Entities - Advantium"""
|
||||||
|
import logging
|
||||||
|
from typing import Any, Dict, List, Mapping, Optional, Set
|
||||||
|
from random import randrange
|
||||||
|
|
||||||
|
from gehomesdk import (
|
||||||
|
ErdCode,
|
||||||
|
ErdPersonality,
|
||||||
|
ErdAdvantiumCookStatus,
|
||||||
|
ErdAdvantiumCookSetting,
|
||||||
|
AdvantiumOperationMode,
|
||||||
|
AdvantiumCookSetting,
|
||||||
|
ErdAdvantiumRemoteCookModeConfig,
|
||||||
|
ADVANTIUM_OPERATION_MODE_COOK_SETTING_MAPPING
|
||||||
|
)
|
||||||
|
from gehomesdk.erd.values.advantium.advantium_enums import CookAction, CookMode
|
||||||
|
|
||||||
|
from homeassistant.components.sensor import SensorDeviceClass
|
||||||
|
from homeassistant.const import ATTR_TEMPERATURE
|
||||||
|
from ...const import DOMAIN
|
||||||
|
from ...devices import ApplianceApi
|
||||||
|
from ..common import GeAbstractWaterHeater
|
||||||
|
from .const import *
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class GeAdvantium(GeAbstractWaterHeater):
|
||||||
|
"""GE Appliance Advantium"""
|
||||||
|
|
||||||
|
icon = "mdi:microwave"
|
||||||
|
|
||||||
|
def __init__(self, api: ApplianceApi):
|
||||||
|
super().__init__(api)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def supported_features(self):
|
||||||
|
if self.remote_enabled:
|
||||||
|
return GE_ADVANTIUM_WITH_TEMPERATURE if self.can_set_temperature else GE_ADVANTIUM
|
||||||
|
else:
|
||||||
|
return SUPPORT_NONE
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_id(self) -> str:
|
||||||
|
return f"{DOMAIN}_{self.serial_number}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self) -> Optional[str]:
|
||||||
|
return f"{self.serial_number} Advantium"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def personality(self) -> Optional[ErdPersonality]:
|
||||||
|
try:
|
||||||
|
return self.appliance.get_erd_value(ErdCode.PERSONALITY)
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def remote_enabled(self) -> bool:
|
||||||
|
"""Returns whether the oven is remote enabled"""
|
||||||
|
value = self.appliance.get_erd_value(ErdCode.UPPER_OVEN_REMOTE_ENABLED)
|
||||||
|
return value == True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_temperature(self) -> Optional[int]:
|
||||||
|
return self.appliance.get_erd_value(ErdCode.UPPER_OVEN_DISPLAY_TEMPERATURE)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_operation(self) -> Optional[str]:
|
||||||
|
try:
|
||||||
|
return self.current_operation_mode.stringify()
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def operation_list(self) -> List[str]:
|
||||||
|
invalid = []
|
||||||
|
if not self._remote_config.broil_enable:
|
||||||
|
invalid.append(CookMode.BROIL)
|
||||||
|
if not self._remote_config.convection_bake_enable:
|
||||||
|
invalid.append(CookMode.CONVECTION_BAKE)
|
||||||
|
if not self._remote_config.proof_enable:
|
||||||
|
invalid.append(CookMode.PROOF)
|
||||||
|
if not self._remote_config.warm_enable:
|
||||||
|
invalid.append(CookMode.WARM)
|
||||||
|
|
||||||
|
return [
|
||||||
|
k.stringify()
|
||||||
|
for k, v in ADVANTIUM_OPERATION_MODE_COOK_SETTING_MAPPING.items()
|
||||||
|
if v.cook_mode not in invalid]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_cook_setting(self) -> ErdAdvantiumCookSetting:
|
||||||
|
"""Get the current cook setting."""
|
||||||
|
return self.appliance.get_erd_value(ErdCode.ADVANTIUM_COOK_SETTING)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_cook_status(self) -> ErdAdvantiumCookStatus:
|
||||||
|
"""Get the current status."""
|
||||||
|
return self.appliance.get_erd_value(ErdCode.ADVANTIUM_COOK_STATUS)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_operation_mode(self) -> AdvantiumOperationMode:
|
||||||
|
"""Gets the current operation mode"""
|
||||||
|
return self._current_operation_mode
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_operation_setting(self) -> Optional[AdvantiumCookSetting]:
|
||||||
|
if self.current_operation_mode is None:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return ADVANTIUM_OPERATION_MODE_COOK_SETTING_MAPPING[self.current_operation_mode]
|
||||||
|
except:
|
||||||
|
_LOGGER.debug(f"Unable to determine operation setting, mode = {self.current_operation_mode}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def can_set_temperature(self) -> bool:
|
||||||
|
"""Indicates whether we can set the temperature based on the current mode"""
|
||||||
|
try:
|
||||||
|
return self.current_operation_setting.allow_temperature_set
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def target_temperature(self) -> Optional[int]:
|
||||||
|
"""Return the temperature we try to reach."""
|
||||||
|
try:
|
||||||
|
cook_mode = self.current_cook_setting
|
||||||
|
if cook_mode.target_temperature and cook_mode.target_temperature > 0:
|
||||||
|
return cook_mode.target_temperature
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def min_temp(self) -> int:
|
||||||
|
"""Return the minimum temperature."""
|
||||||
|
min_temp, _ = self.appliance.get_erd_value(ErdCode.OVEN_MODE_MIN_MAX_TEMP)
|
||||||
|
return min_temp
|
||||||
|
|
||||||
|
@property
|
||||||
|
def max_temp(self) -> int:
|
||||||
|
"""Return the maximum temperature."""
|
||||||
|
_, max_temp = self.appliance.get_erd_value(ErdCode.OVEN_MODE_MIN_MAX_TEMP)
|
||||||
|
return max_temp
|
||||||
|
|
||||||
|
@property
|
||||||
|
def extra_state_attributes(self) -> Optional[Mapping[str, Any]]:
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
cook_time_remaining = self.appliance.get_erd_value(ErdCode.ADVANTIUM_COOK_TIME_REMAINING)
|
||||||
|
kitchen_timer = self.appliance.get_erd_value(ErdCode.ADVANTIUM_KITCHEN_TIME_REMAINING)
|
||||||
|
data["unit_type"] = self._stringify(self.personality)
|
||||||
|
if cook_time_remaining:
|
||||||
|
data["cook_time_remaining"] = self._stringify(cook_time_remaining)
|
||||||
|
if kitchen_timer:
|
||||||
|
data["kitchen_timer"] = self._stringify(kitchen_timer)
|
||||||
|
return data
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _remote_config(self) -> ErdAdvantiumRemoteCookModeConfig:
|
||||||
|
return self.appliance.get_erd_value(ErdCode.ADVANTIUM_REMOTE_COOK_MODE_CONFIG)
|
||||||
|
|
||||||
|
async def async_set_operation_mode(self, operation_mode: str):
|
||||||
|
"""Set the operation mode."""
|
||||||
|
|
||||||
|
#try to get the mode/setting for the selection
|
||||||
|
try:
|
||||||
|
mode = AdvantiumOperationMode(operation_mode)
|
||||||
|
setting = ADVANTIUM_OPERATION_MODE_COOK_SETTING_MAPPING[mode]
|
||||||
|
except:
|
||||||
|
_LOGGER.debug(f"Attempted to set mode to {operation_mode}, unknown.")
|
||||||
|
return
|
||||||
|
|
||||||
|
#determine the target temp for this mode
|
||||||
|
target_temp = self._convert_target_temperature(setting.target_temperature_120v_f, setting.target_temperature_240v_f)
|
||||||
|
|
||||||
|
#if we allow temperature to be set in this mode, and already have a temperature, use it
|
||||||
|
if setting.allow_temperature_set and self.target_temperature:
|
||||||
|
target_temp = self.target_temperature
|
||||||
|
|
||||||
|
#by default we will start an operation, but handle other actions too
|
||||||
|
action = CookAction.START
|
||||||
|
if mode == AdvantiumOperationMode.OFF:
|
||||||
|
action = CookAction.STOP
|
||||||
|
elif self.current_cook_setting.cook_action == CookAction.PAUSE:
|
||||||
|
action = CookAction.RESUME
|
||||||
|
elif self.current_cook_setting.cook_action in [CookAction.START, CookAction.RESUME]:
|
||||||
|
action = CookAction.UPDATED
|
||||||
|
|
||||||
|
#construct the new mode based on the existing mode
|
||||||
|
new_cook_mode = self.current_cook_setting
|
||||||
|
new_cook_mode.d = randrange(255)
|
||||||
|
new_cook_mode.target_temperature = target_temp
|
||||||
|
if(setting.target_power_level != 0):
|
||||||
|
new_cook_mode.power_level = setting.target_power_level
|
||||||
|
new_cook_mode.cook_mode = setting.cook_mode
|
||||||
|
new_cook_mode.cook_action = action
|
||||||
|
|
||||||
|
await self.appliance.async_set_erd_value(ErdCode.ADVANTIUM_COOK_SETTING, new_cook_mode)
|
||||||
|
|
||||||
|
async def async_set_temperature(self, **kwargs):
|
||||||
|
"""Set the cook temperature"""
|
||||||
|
|
||||||
|
target_temp = kwargs.get(ATTR_TEMPERATURE)
|
||||||
|
if target_temp is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
#get the current mode/operation
|
||||||
|
mode = self.current_operation_mode
|
||||||
|
setting = self.current_operation_setting
|
||||||
|
|
||||||
|
#if we can't figure out the mode/setting, exit
|
||||||
|
if mode is None or setting is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
#if we're off or can't set temperature, just exit
|
||||||
|
if mode == AdvantiumOperationMode.OFF or not setting.allow_temperature_set:
|
||||||
|
return
|
||||||
|
|
||||||
|
#should only need to update
|
||||||
|
action = CookAction.UPDATED
|
||||||
|
|
||||||
|
#construct the new mode based on the existing mode
|
||||||
|
new_cook_mode = self.current_cook_setting
|
||||||
|
new_cook_mode.d = randrange(255)
|
||||||
|
new_cook_mode.target_temperature = target_temp
|
||||||
|
new_cook_mode.cook_action = action
|
||||||
|
|
||||||
|
await self.appliance.async_set_erd_value(ErdCode.ADVANTIUM_COOK_SETTING, new_cook_mode)
|
||||||
|
|
||||||
|
async def _ensure_operation_mode(self):
|
||||||
|
cook_setting = self.current_cook_setting
|
||||||
|
cook_mode = cook_setting.cook_mode
|
||||||
|
|
||||||
|
#if we have a current mode
|
||||||
|
if(self._current_operation_mode is not None):
|
||||||
|
#and the cook mode is the same as what the appliance says, we'll just leave things alone
|
||||||
|
#and assume that things are in sync
|
||||||
|
if ADVANTIUM_OPERATION_MODE_COOK_SETTING_MAPPING[self._current_operation_mode].cook_mode == cook_mode:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self._current_operation_mode = None
|
||||||
|
|
||||||
|
#synchronize the operation mode with the device state
|
||||||
|
if cook_mode == CookMode.MICROWAVE:
|
||||||
|
#microwave matches on cook mode and power level
|
||||||
|
if cook_setting.power_level == 3:
|
||||||
|
self._current_operation_mode = AdvantiumOperationMode.MICROWAVE_PL3
|
||||||
|
elif cook_setting.power_level == 5:
|
||||||
|
self._current_operation_mode = AdvantiumOperationMode.MICROWAVE_PL5
|
||||||
|
elif cook_setting.power_level == 7:
|
||||||
|
self._current_operation_mode = AdvantiumOperationMode.MICROWAVE_PL7
|
||||||
|
else:
|
||||||
|
self._current_operation_mode = AdvantiumOperationMode.MICROWAVE_PL10
|
||||||
|
elif cook_mode == CookMode.WARM:
|
||||||
|
for key, value in ADVANTIUM_OPERATION_MODE_COOK_SETTING_MAPPING.items():
|
||||||
|
#warm matches on the mode, warm status, and target temp
|
||||||
|
if (cook_mode == value.cook_mode and
|
||||||
|
cook_setting.warm_status == value.warm_status and
|
||||||
|
cook_setting.target_temperature == self._convert_target_temperature(
|
||||||
|
value.target_temperature_120v_f, value.target_temperature_240v_f)):
|
||||||
|
self._current_operation_mode = key
|
||||||
|
return
|
||||||
|
|
||||||
|
#just pick the first match based on cook mode if we made it here
|
||||||
|
if self._current_operation_mode is None:
|
||||||
|
for key, value in ADVANTIUM_OPERATION_MODE_COOK_SETTING_MAPPING.items():
|
||||||
|
if cook_mode == value.cook_mode:
|
||||||
|
self._current_operation_mode = key
|
||||||
|
return
|
||||||
|
|
||||||
|
async def _convert_target_temperature(self, temp_120v: int, temp_240v: int):
|
||||||
|
unit_type = self.personality
|
||||||
|
target_temp_f = temp_240v if unit_type in [ErdPersonality.PERSONALITY_240V_MONOGRAM, ErdPersonality.PERSONALITY_240V_CAFE, ErdPersonality.PERSONALITY_240V_STANDALONE_CAFE] else temp_120v
|
||||||
|
if self.temperature_unit == SensorDeviceClass.FAHRENHEIT:
|
||||||
|
return float(target_temp_f)
|
||||||
|
else:
|
||||||
|
return (target_temp_f - 32.0) * (5/9)
|
||||||
|
|
||||||
|
async def async_device_update(self, warning: bool) -> None:
|
||||||
|
await super().async_device_update(warning=warning)
|
||||||
|
await self._ensure_operation_mode()
|
||||||
5
entities/ccm/__init__.py
Normal file
5
entities/ccm/__init__.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from .ge_ccm_pot_not_present_binary_sensor import GeCcmPotNotPresentBinarySensor
|
||||||
|
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
|
||||||
BIN
entities/ccm/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
entities/ccm/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
entities/ccm/__pycache__/ge_ccm_brew_cups.cpython-313.pyc
Normal file
BIN
entities/ccm/__pycache__/ge_ccm_brew_cups.cpython-313.pyc
Normal file
Binary file not shown.
BIN
entities/ccm/__pycache__/ge_ccm_brew_settings.cpython-313.pyc
Normal file
BIN
entities/ccm/__pycache__/ge_ccm_brew_settings.cpython-313.pyc
Normal file
Binary file not shown.
BIN
entities/ccm/__pycache__/ge_ccm_brew_strength.cpython-313.pyc
Normal file
BIN
entities/ccm/__pycache__/ge_ccm_brew_strength.cpython-313.pyc
Normal file
Binary file not shown.
BIN
entities/ccm/__pycache__/ge_ccm_brew_temperature.cpython-313.pyc
Normal file
BIN
entities/ccm/__pycache__/ge_ccm_brew_temperature.cpython-313.pyc
Normal file
Binary file not shown.
BIN
entities/ccm/__pycache__/ge_ccm_cached_value.cpython-313.pyc
Normal file
BIN
entities/ccm/__pycache__/ge_ccm_cached_value.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
19
entities/ccm/ge_ccm_brew_cups.py
Normal file
19
entities/ccm/ge_ccm_brew_cups.py
Normal 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_native_value(self, value):
|
||||||
|
GeCcmCachedValue.set_value(self, value)
|
||||||
|
self.schedule_update_ha_state()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def native_value(self):
|
||||||
|
return self.get_value(device_value = super().native_value)
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user