mirror of https://github.com/simbaja/ha_gehome.git
- Update to GE Home and use the gehomesdk
This commit is contained in:
parent
5d520e5ac8
commit
e399ff1652
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Andrew Marks
|
Copyright (c) 2021
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
39
README.md
39
README.md
|
@ -1,20 +1,19 @@
|
||||||
# GE Kitchen Appliances (SmartHQ)
|
# GE Home Appliances (SmartHQ)
|
||||||
|
|
||||||
## `ge_kitchen`
|
## `ge_home`
|
||||||
Integration for GE WiFi-enabled kitchen appliances. So far, I've only done fridges and ovens (because that's what I
|
Integration for GE WiFi-enabled appliances into Home Assistant. This integration currently contains fridge, oven, dishwasher, laundry washer, laundry dryer support.
|
||||||
have), but I hope to to dishwashers next. Because HA doesn't have Fridge or Oven platforms, both fridges and ovens are
|
|
||||||
primarily represented as water heater entities, which works surprisingly well. If anybody who has other GE appliances
|
**Forked from Andrew Mark's [repository](https://github.com/ajmarks/ha_components).**
|
||||||
sees this and wants to pitch in, please shoot me a message or make a PR.
|
|
||||||
|
Entities card:
|
||||||
Entities card:
|
|
||||||
|
![Entities](https://raw.githubusercontent.com/simbaja/ha_components/master/img/appliance_entities.png)
|
||||||
![Entities](https://raw.githubusercontent.com/ajmarks/ha_components/master/img/appliance_entities.png)
|
|
||||||
|
Fridge Controls:
|
||||||
Fridge Controls:
|
|
||||||
|
![Fridge controls](https://raw.githubusercontent.com/simbaja/ha_components/master/img/fridge_control.png)
|
||||||
![Fridge controls](https://raw.githubusercontent.com/ajmarks/ha_components/master/img/fridge_control.png)
|
|
||||||
|
Oven Controls:
|
||||||
Oven Controls:
|
|
||||||
|
![Fridge controls](https://raw.githubusercontent.com/simbaja/ha_components/master/img/oven_controls.png)
|
||||||
![Fridge controls](https://raw.githubusercontent.com/ajmarks/ha_components/master/img/oven_controls.png)
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
"""The ge_kitchen integration."""
|
"""The ge_home integration."""
|
||||||
|
|
||||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
@ -8,7 +8,7 @@ from homeassistant.core import HomeAssistant
|
||||||
from .const import (
|
from .const import (
|
||||||
DOMAIN
|
DOMAIN
|
||||||
)
|
)
|
||||||
from .update_coordinator import GeKitchenUpdateCoordinator
|
from .update_coordinator import GeHomeUpdateCoordinator
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({})}, extra=vol.ALLOW_EXTRA)
|
CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({})}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
|
@ -16,11 +16,11 @@ async def async_setup(hass: HomeAssistant, config: dict):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
"""Set up the ge_kitchen component."""
|
"""Set up the ge_home component."""
|
||||||
hass.data.setdefault(DOMAIN, {})
|
hass.data.setdefault(DOMAIN, {})
|
||||||
|
|
||||||
"""Set up ge_kitchen from a config entry."""
|
"""Set up ge_home from a config entry."""
|
||||||
coordinator = GeKitchenUpdateCoordinator(hass, entry)
|
coordinator = GeHomeUpdateCoordinator(hass, entry)
|
||||||
hass.data[DOMAIN][entry.entry_id] = coordinator
|
hass.data[DOMAIN][entry.entry_id] = coordinator
|
||||||
|
|
||||||
if not await coordinator.async_setup():
|
if not await coordinator.async_setup():
|
||||||
|
@ -32,7 +32,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
|
|
||||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
"""Unload a config entry."""
|
"""Unload a config entry."""
|
||||||
coordinator: GeKitchenUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
coordinator: GeHomeUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
||||||
ok = await coordinator.async_reset()
|
ok = await coordinator.async_reset()
|
||||||
if ok:
|
if ok:
|
||||||
hass.data[DOMAIN].pop(entry.entry_id)
|
hass.data[DOMAIN].pop(entry.entry_id)
|
|
@ -1,4 +1,4 @@
|
||||||
"""GE Kitchen Sensor Entities"""
|
"""GE Home Sensor Entities"""
|
||||||
import async_timeout
|
import async_timeout
|
||||||
import logging
|
import logging
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
@ -9,14 +9,14 @@ from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
from .entities import GeErdBinarySensor
|
from .entities import GeErdBinarySensor
|
||||||
from .update_coordinator import GeKitchenUpdateCoordinator
|
from .update_coordinator import GeHomeUpdateCoordinator
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: Callable):
|
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: Callable):
|
||||||
"""GE Kitchen sensors."""
|
"""GE Home sensors."""
|
||||||
|
|
||||||
coordinator: GeKitchenUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
coordinator: GeHomeUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
||||||
|
|
||||||
# This should be a NOP, but let's be safe
|
# This should be a NOP, but let's be safe
|
||||||
with async_timeout.timeout(20):
|
with async_timeout.timeout(20):
|
|
@ -1,4 +1,4 @@
|
||||||
"""Config flow for GE Kitchen integration."""
|
"""Config flow for GE Home integration."""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Dict, Optional
|
from typing import Dict, Optional
|
||||||
|
@ -7,7 +7,7 @@ import aiohttp
|
||||||
import asyncio
|
import asyncio
|
||||||
import async_timeout
|
import async_timeout
|
||||||
|
|
||||||
from gekitchensdk import GeAuthFailedError, GeNotAuthenticatedError, GeGeneralServerError, async_get_oauth2_token
|
from gehomesdk import GeAuthFailedError, GeNotAuthenticatedError, GeGeneralServerError, async_get_oauth2_token
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries, core
|
from homeassistant import config_entries, core
|
||||||
|
@ -18,7 +18,7 @@ from .exceptions import HaAuthError, HaCannotConnect
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
GEKITCHEN_SCHEMA = vol.Schema(
|
GEHOME_SCHEMA = vol.Schema(
|
||||||
{vol.Required(CONF_USERNAME): str, vol.Required(CONF_PASSWORD): str}
|
{vol.Required(CONF_USERNAME): str, vol.Required(CONF_PASSWORD): str}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -42,10 +42,10 @@ async def validate_input(hass: core.HomeAssistant, data):
|
||||||
raise HaCannotConnect('Unknown connection failure')
|
raise HaCannotConnect('Unknown connection failure')
|
||||||
|
|
||||||
# Return info that you want to store in the config entry.
|
# Return info that you want to store in the config entry.
|
||||||
return {"title": f"GE Kitchen ({data[CONF_USERNAME]:s})"}
|
return {"title": f"GE Home ({data[CONF_USERNAME]:s})"}
|
||||||
|
|
||||||
class GeKitchenConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
class GeHomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
"""Handle a config flow for GE Kitchen."""
|
"""Handle a config flow for GE Home."""
|
||||||
|
|
||||||
VERSION = 1
|
VERSION = 1
|
||||||
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_PUSH
|
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_PUSH
|
||||||
|
@ -77,7 +77,7 @@ class GeKitchenConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
return self.async_create_entry(title=info["title"], data=user_input)
|
return self.async_create_entry(title=info["title"], data=user_input)
|
||||||
|
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
step_id="user", data_schema=GEKITCHEN_SCHEMA, errors=errors
|
step_id="user", data_schema=GEHOME_SCHEMA, errors=errors
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_step_reauth(self, user_input: Optional[dict] = None):
|
async def async_step_reauth(self, user_input: Optional[dict] = None):
|
||||||
|
@ -100,5 +100,5 @@ class GeKitchenConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
return self.async_abort(reason=errors["base"])
|
return self.async_abort(reason=errors["base"])
|
||||||
|
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
step_id="reauth", data_schema=GEKITCHEN_SCHEMA, errors=errors,
|
step_id="reauth", data_schema=GEHOME_SCHEMA, errors=errors,
|
||||||
)
|
)
|
|
@ -1,7 +1,7 @@
|
||||||
"""Constants for the ge_kitchen integration."""
|
"""Constants for the gehome integration."""
|
||||||
from gekitchensdk.clients.const import LOGIN_URL
|
from gehomesdk.clients.const import LOGIN_URL
|
||||||
|
|
||||||
DOMAIN = "ge_kitchen"
|
DOMAIN = "ge_home"
|
||||||
|
|
||||||
EVENT_ALL_APPLIANCES_READY = 'all_appliances_ready'
|
EVENT_ALL_APPLIANCES_READY = 'all_appliances_ready'
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import logging
|
import logging
|
||||||
from typing import Type
|
from typing import Type
|
||||||
|
|
||||||
from gekitchensdk.erd import ErdApplianceType
|
from gehomesdk.erd import ErdApplianceType
|
||||||
|
|
||||||
from .base import ApplianceApi
|
from .base import ApplianceApi
|
||||||
from .oven import OvenApi
|
from .oven import OvenApi
|
|
@ -2,8 +2,8 @@ import asyncio
|
||||||
import logging
|
import logging
|
||||||
from typing import Dict, List, Optional
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
from gekitchensdk import GeAppliance
|
from gehomesdk import GeAppliance
|
||||||
from gekitchensdk.erd import ErdCode, ErdCodeType, ErdApplianceType
|
from gehomesdk.erd import ErdCode, ErdCodeType, ErdApplianceType
|
||||||
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
|
@ -2,7 +2,7 @@ import logging
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from gekitchensdk.erd import ErdCode, ErdApplianceType
|
from gehomesdk.erd import ErdCode, ErdApplianceType
|
||||||
|
|
||||||
from .base import ApplianceApi
|
from .base import ApplianceApi
|
||||||
from ..entities import GeErdSensor, GeDishwasherControlLockedSwitch
|
from ..entities import GeErdSensor, GeDishwasherControlLockedSwitch
|
||||||
|
@ -28,4 +28,4 @@ class DishwasherApi(ApplianceApi):
|
||||||
]
|
]
|
||||||
entities = base_entities + dishwasher_entities
|
entities = base_entities + dishwasher_entities
|
||||||
return entities
|
return entities
|
||||||
|
|
|
@ -2,7 +2,7 @@ import logging
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from gekitchensdk.erd import ErdCode, ErdApplianceType
|
from gehomesdk.erd import ErdCode, ErdApplianceType
|
||||||
|
|
||||||
from .base import ApplianceApi
|
from .base import ApplianceApi
|
||||||
from ..entities import GeErdSensor, GeDishwasherControlLockedSwitch
|
from ..entities import GeErdSensor, GeDishwasherControlLockedSwitch
|
|
@ -4,7 +4,7 @@ import logging
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from gekitchensdk import (
|
from gehomesdk import (
|
||||||
ErdCode,
|
ErdCode,
|
||||||
ErdApplianceType,
|
ErdApplianceType,
|
||||||
ErdOnOff,
|
ErdOnOff,
|
|
@ -3,7 +3,7 @@ from typing import List
|
||||||
|
|
||||||
from homeassistant.const import DEVICE_CLASS_POWER_FACTOR
|
from homeassistant.const import DEVICE_CLASS_POWER_FACTOR
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from gekitchensdk import (
|
from gehomesdk import (
|
||||||
ErdCode,
|
ErdCode,
|
||||||
ErdApplianceType,
|
ErdApplianceType,
|
||||||
OvenConfiguration,
|
OvenConfiguration,
|
|
@ -1,9 +1,9 @@
|
||||||
from custom_components.ge_kitchen.entities.common.ge_erd_binary_sensor import GeErdBinarySensor
|
from custom_components.ge_home.entities.common.ge_erd_binary_sensor import GeErdBinarySensor
|
||||||
import logging
|
import logging
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from gekitchensdk.erd import ErdCode, ErdApplianceType
|
from gehomesdk.erd import ErdCode, ErdApplianceType
|
||||||
|
|
||||||
from .base import ApplianceApi
|
from .base import ApplianceApi
|
||||||
from ..entities import GeErdSensor, GeErdBinarySensor
|
from ..entities import GeErdSensor, GeErdBinarySensor
|
||||||
|
@ -35,4 +35,4 @@ class WasherApi(ApplianceApi):
|
||||||
]
|
]
|
||||||
entities = base_entities + washer_entities
|
entities = base_entities + washer_entities
|
||||||
return entities
|
return entities
|
||||||
|
|
|
@ -2,7 +2,7 @@ import logging
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from gekitchensdk.erd import ErdCode, ErdApplianceType
|
from gehomesdk.erd import ErdCode, ErdApplianceType
|
||||||
|
|
||||||
from .base import ApplianceApi
|
from .base import ApplianceApi
|
||||||
from ..entities import GeErdSensor, GeErdBinarySensor
|
from ..entities import GeErdSensor, GeErdBinarySensor
|
||||||
|
@ -38,4 +38,4 @@ class WasherDryerApi(ApplianceApi):
|
||||||
]
|
]
|
||||||
entities = base_entities + washer_entities + dryer_entities
|
entities = base_entities + washer_entities + dryer_entities
|
||||||
return entities
|
return entities
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from typing import Optional, Dict, Any
|
from typing import Optional, Dict, Any
|
||||||
|
|
||||||
from gekitchensdk import GeAppliance
|
from gehomesdk import GeAppliance
|
||||||
from ...devices import ApplianceApi
|
from ...devices import ApplianceApi
|
||||||
|
|
||||||
class GeEntity:
|
class GeEntity:
|
||||||
|
@ -62,4 +62,4 @@ class GeEntity:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _get_device_class(self) -> Optional[str]:
|
def _get_device_class(self) -> Optional[str]:
|
||||||
return None
|
return None
|
|
@ -2,7 +2,7 @@ from typing import Optional
|
||||||
|
|
||||||
from homeassistant.components.binary_sensor import BinarySensorEntity
|
from homeassistant.components.binary_sensor import BinarySensorEntity
|
||||||
|
|
||||||
from gekitchensdk import ErdCode, ErdCodeType, ErdCodeClass
|
from gehomesdk import ErdCode, ErdCodeType, ErdCodeClass
|
||||||
from ...devices import ApplianceApi
|
from ...devices import ApplianceApi
|
||||||
from .ge_erd_entity import GeErdEntity
|
from .ge_erd_entity import GeErdEntity
|
||||||
|
|
|
@ -2,7 +2,7 @@ from datetime import timedelta
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from homeassistant.const import DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT
|
from homeassistant.const import DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT
|
||||||
from gekitchensdk import ErdCode, ErdCodeType, ErdCodeClass, ErdMeasurementUnits
|
from gehomesdk import ErdCode, ErdCodeType, ErdCodeClass, ErdMeasurementUnits
|
||||||
|
|
||||||
from ...const import DOMAIN
|
from ...const import DOMAIN
|
||||||
from ...devices import ApplianceApi
|
from ...devices import ApplianceApi
|
|
@ -1,7 +1,7 @@
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import magicattr
|
import magicattr
|
||||||
from gekitchensdk import ErdCodeType
|
from gehomesdk import ErdCodeType
|
||||||
from ...devices import ApplianceApi
|
from ...devices import ApplianceApi
|
||||||
from .ge_erd_binary_sensor import GeErdBinarySensor
|
from .ge_erd_binary_sensor import GeErdBinarySensor
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import magicattr
|
import magicattr
|
||||||
from gekitchensdk import ErdCode, ErdCodeType, ErdMeasurementUnits
|
from gehomesdk import ErdCode, ErdCodeType, ErdMeasurementUnits
|
||||||
from ...devices import ApplianceApi
|
from ...devices import ApplianceApi
|
||||||
from .ge_erd_sensor import GeErdSensor
|
from .ge_erd_sensor import GeErdSensor
|
||||||
|
|
|
@ -8,7 +8,7 @@ from homeassistant.const import (
|
||||||
TEMP_FAHRENHEIT
|
TEMP_FAHRENHEIT
|
||||||
)
|
)
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from gekitchensdk import ErdCode, ErdCodeClass, ErdMeasurementUnits
|
from gehomesdk import ErdCode, ErdCodeClass, ErdMeasurementUnits
|
||||||
|
|
||||||
from .ge_erd_entity import GeErdEntity
|
from .ge_erd_entity import GeErdEntity
|
||||||
|
|
|
@ -7,7 +7,7 @@ from homeassistant.const import (
|
||||||
TEMP_FAHRENHEIT,
|
TEMP_FAHRENHEIT,
|
||||||
TEMP_CELSIUS
|
TEMP_CELSIUS
|
||||||
)
|
)
|
||||||
from gekitchensdk import ErdCode, ErdMeasurementUnits
|
from gehomesdk import ErdCode, ErdMeasurementUnits
|
||||||
from ...const import DOMAIN
|
from ...const import DOMAIN
|
||||||
from .ge_erd_entity import GeEntity
|
from .ge_erd_entity import GeEntity
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from gekitchensdk import ErdCode, ErdOperatingMode
|
from gehomesdk import ErdCode, ErdOperatingMode
|
||||||
|
|
||||||
from ..common import GeErdSwitch
|
from ..common import GeErdSwitch
|
||||||
|
|
||||||
|
@ -9,4 +9,4 @@ class GeDishwasherControlLockedSwitch(GeErdSwitch):
|
||||||
def is_on(self) -> bool:
|
def is_on(self) -> bool:
|
||||||
mode: ErdOperatingMode = self.appliance.get_erd_value(ErdCode.OPERATING_MODE)
|
mode: ErdOperatingMode = self.appliance.get_erd_value(ErdCode.OPERATING_MODE)
|
||||||
return mode == ErdOperatingMode.CONTROL_LOCKED
|
return mode == ErdOperatingMode.CONTROL_LOCKED
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
"""GE Kitchen Sensor Entities - Abstract Fridge"""
|
"""GE Home Sensor Entities - Abstract Fridge"""
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import abc
|
import abc
|
||||||
|
@ -7,7 +7,7 @@ from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT
|
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT
|
||||||
|
|
||||||
from gekitchensdk import (
|
from gehomesdk import (
|
||||||
ErdCode,
|
ErdCode,
|
||||||
ErdOnOff,
|
ErdOnOff,
|
||||||
ErdFullNotFull,
|
ErdFullNotFull,
|
|
@ -1,4 +1,4 @@
|
||||||
"""GE Kitchen Sensor Entities - Dispenser"""
|
"""GE Home Sensor Entities - Dispenser"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import List, Optional, Dict, Any
|
from typing import List, Optional, Dict, Any
|
||||||
|
@ -6,7 +6,7 @@ from typing import List, Optional, Dict, Any
|
||||||
from homeassistant.const import ATTR_TEMPERATURE, TEMP_FAHRENHEIT
|
from homeassistant.const import ATTR_TEMPERATURE, TEMP_FAHRENHEIT
|
||||||
from homeassistant.util.temperature import convert as convert_temperature
|
from homeassistant.util.temperature import convert as convert_temperature
|
||||||
|
|
||||||
from gekitchensdk import (
|
from gehomesdk import (
|
||||||
ErdCode,
|
ErdCode,
|
||||||
ErdHotWaterStatus,
|
ErdHotWaterStatus,
|
||||||
ErdPresent,
|
ErdPresent,
|
|
@ -1,8 +1,8 @@
|
||||||
"""GE Kitchen Sensor Entities - Freezer"""
|
"""GE Home Sensor Entities - Freezer"""
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Dict, Optional
|
||||||
|
|
||||||
from gekitchensdk import (
|
from gehomesdk import (
|
||||||
ErdCode,
|
ErdCode,
|
||||||
ErdDoorStatus
|
ErdDoorStatus
|
||||||
)
|
)
|
|
@ -1,8 +1,8 @@
|
||||||
"""GE Kitchen Sensor Entities - Fridge"""
|
"""GE Home Sensor Entities - Fridge"""
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from gekitchensdk import (
|
from gehomesdk import (
|
||||||
ErdCode,
|
ErdCode,
|
||||||
ErdDoorStatus,
|
ErdDoorStatus,
|
||||||
ErdFilterStatus
|
ErdFilterStatus
|
|
@ -4,7 +4,7 @@ from homeassistant.components.water_heater import (
|
||||||
SUPPORT_OPERATION_MODE,
|
SUPPORT_OPERATION_MODE,
|
||||||
SUPPORT_TARGET_TEMPERATURE
|
SUPPORT_TARGET_TEMPERATURE
|
||||||
)
|
)
|
||||||
from gekitchensdk import ErdOvenCookMode
|
from gehomesdk import ErdOvenCookMode
|
||||||
|
|
||||||
SUPPORT_NONE = 0
|
SUPPORT_NONE = 0
|
||||||
GE_OVEN_SUPPORT = (SUPPORT_OPERATION_MODE | SUPPORT_TARGET_TEMPERATURE)
|
GE_OVEN_SUPPORT = (SUPPORT_OPERATION_MODE | SUPPORT_TARGET_TEMPERATURE)
|
|
@ -1,8 +1,8 @@
|
||||||
"""GE Kitchen Sensor Entities - Oven"""
|
"""GE Home Sensor Entities - Oven"""
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, List, Optional, Set
|
from typing import Any, Dict, List, Optional, Set
|
||||||
|
|
||||||
from gekitchensdk import (
|
from gehomesdk import (
|
||||||
ErdCode,
|
ErdCode,
|
||||||
ErdMeasurementUnits,
|
ErdMeasurementUnits,
|
||||||
ErdOvenCookMode,
|
ErdOvenCookMode,
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"domain": "ge_home",
|
||||||
|
"name": "GE Home",
|
||||||
|
"config_flow": true,
|
||||||
|
"documentation": "https://github.com/simbaja/ha_components",
|
||||||
|
"requirements": ["gehomesdk==0.3.12","magicattr==0.1.5"],
|
||||||
|
"codeowners": ["@simbaja"],
|
||||||
|
"version": "0.3.12"
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
"""GE Kitchen Sensor Entities"""
|
"""GE Home Sensor Entities"""
|
||||||
import async_timeout
|
import async_timeout
|
||||||
import logging
|
import logging
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
@ -8,14 +8,14 @@ from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
from .entities import GeErdSensor
|
from .entities import GeErdSensor
|
||||||
from .update_coordinator import GeKitchenUpdateCoordinator
|
from .update_coordinator import GeHomeUpdateCoordinator
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: Callable):
|
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: Callable):
|
||||||
"""GE Kitchen sensors."""
|
"""GE Home sensors."""
|
||||||
_LOGGER.debug('Adding GE Kitchen sensors')
|
_LOGGER.debug('Adding GE Home sensors')
|
||||||
coordinator: GeKitchenUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
coordinator: GeHomeUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
||||||
|
|
||||||
# This should be a NOP, but let's be safe
|
# This should be a NOP, but let's be safe
|
||||||
with async_timeout.timeout(20):
|
with async_timeout.timeout(20):
|
|
@ -1,4 +1,4 @@
|
||||||
"""GE Kitchen Switch Entities"""
|
"""GE Home Switch Entities"""
|
||||||
import async_timeout
|
import async_timeout
|
||||||
import logging
|
import logging
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
@ -8,14 +8,14 @@ from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
from .entities import GeErdSwitch
|
from .entities import GeErdSwitch
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
from .update_coordinator import GeKitchenUpdateCoordinator
|
from .update_coordinator import GeHomeUpdateCoordinator
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: Callable):
|
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: Callable):
|
||||||
"""GE Kitchen sensors."""
|
"""GE Home sensors."""
|
||||||
_LOGGER.debug('Adding GE Kitchen switches')
|
_LOGGER.debug('Adding GE Home switches')
|
||||||
coordinator: GeKitchenUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
coordinator: GeHomeUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
||||||
|
|
||||||
# This should be a NOP, but let's be safe
|
# This should be a NOP, but let's be safe
|
||||||
with async_timeout.timeout(20):
|
with async_timeout.timeout(20):
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"title": "GE Kitchen",
|
"title": "GE Home",
|
||||||
"config": {
|
"config": {
|
||||||
"step": {
|
"step": {
|
||||||
"init": {
|
"init": {
|
||||||
|
@ -24,4 +24,4 @@
|
||||||
"already_configured_account": "[%key:common::config_flow::abort::already_configured_account%]"
|
"already_configured_account": "[%key:common::config_flow::abort::already_configured_account%]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
"""Data update coordinator for GE Kitchen Appliances"""
|
"""Data update coordinator for GE Home Appliances"""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import async_timeout
|
import async_timeout
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, Iterable, Optional, Tuple
|
from typing import Any, Dict, Iterable, Optional, Tuple
|
||||||
|
|
||||||
from gekitchensdk import (
|
from gehomesdk import (
|
||||||
EVENT_APPLIANCE_INITIAL_UPDATE,
|
EVENT_APPLIANCE_INITIAL_UPDATE,
|
||||||
EVENT_APPLIANCE_UPDATE_RECEIVED,
|
EVENT_APPLIANCE_UPDATE_RECEIVED,
|
||||||
EVENT_CONNECTED,
|
EVENT_CONNECTED,
|
||||||
|
@ -15,7 +15,7 @@ from gekitchensdk import (
|
||||||
GeAppliance,
|
GeAppliance,
|
||||||
GeWebsocketClient,
|
GeWebsocketClient,
|
||||||
)
|
)
|
||||||
from gekitchensdk import GeAuthFailedError, GeGeneralServerError, GeNotAuthenticatedError
|
from gehomesdk import GeAuthFailedError, GeGeneralServerError, GeNotAuthenticatedError
|
||||||
from .exceptions import HaAuthError, HaCannotConnect
|
from .exceptions import HaAuthError, HaCannotConnect
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
@ -37,11 +37,11 @@ from .devices import ApplianceApi, get_appliance_api_type
|
||||||
PLATFORMS = ["binary_sensor", "sensor", "switch", "water_heater"]
|
PLATFORMS = ["binary_sensor", "sensor", "switch", "water_heater"]
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
class GeKitchenUpdateCoordinator(DataUpdateCoordinator):
|
class GeHomeUpdateCoordinator(DataUpdateCoordinator):
|
||||||
"""Define a wrapper class to update GE Kitchen data."""
|
"""Define a wrapper class to update GE Home data."""
|
||||||
|
|
||||||
def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry) -> None:
|
def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry) -> None:
|
||||||
"""Set up the GeKitchenUpdateCoordinator class."""
|
"""Set up the GeHomeUpdateCoordinator class."""
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
self._config_entry = config_entry
|
self._config_entry = config_entry
|
||||||
self._username = config_entry.data[CONF_USERNAME]
|
self._username = config_entry.data[CONF_USERNAME]
|
||||||
|
@ -176,7 +176,7 @@ class GeKitchenUpdateCoordinator(DataUpdateCoordinator):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
async def async_begin_session(self):
|
async def async_begin_session(self):
|
||||||
"""Begins the ge_kitchen session."""
|
"""Begins the ge_home session."""
|
||||||
_LOGGER.debug("Beginning session")
|
_LOGGER.debug("Beginning session")
|
||||||
session = self._hass.helpers.aiohttp_client.async_get_clientsession()
|
session = self._hass.helpers.aiohttp_client.async_get_clientsession()
|
||||||
await self.client.async_get_credentials(session)
|
await self.client.async_get_credentials(session)
|
||||||
|
@ -206,15 +206,15 @@ class GeKitchenUpdateCoordinator(DataUpdateCoordinator):
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def reconnect(self, log=False) -> None:
|
def reconnect(self, log=False) -> None:
|
||||||
"""Prepare to reconnect ge_kitchen session."""
|
"""Prepare to reconnect ge_home session."""
|
||||||
if log:
|
if log:
|
||||||
_LOGGER.info("Will try to reconnect to ge_kitchen service")
|
_LOGGER.info("Will try to reconnect to ge_home service")
|
||||||
self.hass.loop.create_task(self.async_reconnect())
|
self.hass.loop.create_task(self.async_reconnect())
|
||||||
|
|
||||||
async def async_reconnect(self) -> None:
|
async def async_reconnect(self) -> None:
|
||||||
"""Try to reconnect ge_kitchen session."""
|
"""Try to reconnect ge_home session."""
|
||||||
self._retry_count += 1
|
self._retry_count += 1
|
||||||
_LOGGER.info(f"attempting to reconnect to ge_kitchen service (attempt {self._retry_count})")
|
_LOGGER.info(f"attempting to reconnect to ge_home service (attempt {self._retry_count})")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with async_timeout.timeout(ASYNC_TIMEOUT):
|
with async_timeout.timeout(ASYNC_TIMEOUT):
|
||||||
|
@ -233,7 +233,7 @@ class GeKitchenUpdateCoordinator(DataUpdateCoordinator):
|
||||||
"""Close the connection on shutdown.
|
"""Close the connection on shutdown.
|
||||||
Used as an argument to EventBus.async_listen_once.
|
Used as an argument to EventBus.async_listen_once.
|
||||||
"""
|
"""
|
||||||
_LOGGER.info("ge_kitchen shutting down")
|
_LOGGER.info("ge_home shutting down")
|
||||||
if self.client:
|
if self.client:
|
||||||
self.client.clear_event_handlers()
|
self.client.clear_event_handlers()
|
||||||
self.client.disconnect()
|
self.client.disconnect()
|
|
@ -1,4 +1,4 @@
|
||||||
"""GE Kitchen Sensor Entities"""
|
"""GE Home Sensor Entities"""
|
||||||
import async_timeout
|
import async_timeout
|
||||||
import logging
|
import logging
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
@ -9,14 +9,14 @@ from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
from .entities import GeWaterHeater
|
from .entities import GeWaterHeater
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
from .update_coordinator import GeKitchenUpdateCoordinator
|
from .update_coordinator import GeHomeUpdateCoordinator
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: Callable):
|
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: Callable):
|
||||||
"""GE Kitchen Water Heaters."""
|
"""GE Home Water Heaters."""
|
||||||
_LOGGER.debug('Adding GE "Water Heaters"')
|
_LOGGER.debug('Adding GE "Water Heaters"')
|
||||||
coordinator: GeKitchenUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
coordinator: GeHomeUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
||||||
|
|
||||||
# This should be a NOP, but let's be safe
|
# This should be a NOP, but let's be safe
|
||||||
with async_timeout.timeout(20):
|
with async_timeout.timeout(20):
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"domain": "ge_kitchen",
|
|
||||||
"name": "GE Kitchen",
|
|
||||||
"config_flow": true,
|
|
||||||
"documentation": "https://github.com/simbaja/ha_components",
|
|
||||||
"requirements": ["gekitchensdk==0.3.11","magicattr==0.1.5"],
|
|
||||||
"codeowners": ["@simbaja"],
|
|
||||||
"version": "0.3.11"
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "GE Kitchen Appliances (SmartHQ)",
|
"name": "GE Appliances (SmartHQ)",
|
||||||
"homeassistant": "2021.1.5",
|
"homeassistant": "2021.1.5",
|
||||||
"domains": ["binary_sensor", "sensor", "switch", "water_heater"],
|
"domains": ["binary_sensor", "sensor", "switch", "water_heater"],
|
||||||
"iot_class": "Cloud Polling"
|
"iot_class": "Cloud Polling"
|
||||||
|
|
17
info.md
17
info.md
|
@ -1,20 +1,19 @@
|
||||||
# GE Kitchen Appliances (SmartHQ)
|
# GE Home Appliances (SmartHQ)
|
||||||
|
|
||||||
## `ge_kitchen`
|
## `ge_home`
|
||||||
Integration for GE WiFi-enabled kitchen appliances. So far, I've only done fridges and ovens (because that's what I
|
Integration for GE WiFi-enabled appliances into Home Assistant. This integration currently contains fridge, oven, dishwasher, laundry washer, laundry dryer support.
|
||||||
have), but I hope to to dishwashers next. Because HA doesn't have Fridge or Oven platforms, both fridges and ovens are
|
|
||||||
primarily represented as water heater entities, which works surprisingly well. If anybody who has other GE appliances
|
**Forked from Andrew Mark's [repository](https://github.com/ajmarks/ha_components).**
|
||||||
sees this and wants to pitch in, please shoot me a message or make a PR.
|
|
||||||
|
|
||||||
Entities card:
|
Entities card:
|
||||||
|
|
||||||
![Entities](https://raw.githubusercontent.com/ajmarks/ha_components/master/img/appliance_entities.png)
|
![Entities](https://raw.githubusercontent.com/simbaja/ha_components/master/img/appliance_entities.png)
|
||||||
|
|
||||||
Fridge Controls:
|
Fridge Controls:
|
||||||
|
|
||||||
![Fridge controls](https://raw.githubusercontent.com/ajmarks/ha_components/master/img/fridge_control.png)
|
![Fridge controls](https://raw.githubusercontent.com/simbaja/ha_components/master/img/fridge_control.png)
|
||||||
|
|
||||||
Oven Controls:
|
Oven Controls:
|
||||||
|
|
||||||
![Fridge controls](https://raw.githubusercontent.com/ajmarks/ha_components/master/img/oven_controls.png)
|
![Fridge controls](https://raw.githubusercontent.com/simbaja/ha_components/master/img/oven_controls.png)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue