diff --git a/homeassistant/components/home_connect/api.py b/homeassistant/components/home_connect/api.py index 8db8afa3a6b..44669ed200f 100644 --- a/homeassistant/components/home_connect/api.py +++ b/homeassistant/components/home_connect/api.py @@ -13,6 +13,7 @@ from homeassistant.helpers.dispatcher import dispatcher_send from .const import ( BSH_ACTIVE_PROGRAM, + BSH_OPERATION_STATE, BSH_POWER_OFF, BSH_POWER_STANDBY, SIGNAL_UPDATE_ENTITIES, @@ -156,6 +157,25 @@ class DeviceWithPrograms(HomeConnectDevice): ] +class DeviceWithOpState(HomeConnectDevice): + """Device that has an operation state sensor.""" + + def get_opstate_sensor(self): + """Get a list with info about operation state sensors.""" + + return [ + { + "device": self, + "desc": "Operation State", + "unit": None, + "key": BSH_OPERATION_STATE, + "icon": "mdi:state-machine", + "device_class": None, + "sign": 1, + } + ] + + class DeviceWithDoor(HomeConnectDevice): """Device that has a door sensor.""" @@ -164,6 +184,7 @@ class DeviceWithDoor(HomeConnectDevice): return { "device": self, "desc": "Door", + "sensor_type": "door", "device_class": "door", } @@ -173,11 +194,7 @@ class DeviceWithLight(HomeConnectDevice): def get_light_entity(self): """Get a dictionary with info about the lighting.""" - return { - "device": self, - "desc": "Light", - "ambient": None, - } + return {"device": self, "desc": "Light", "ambient": None} class DeviceWithAmbientLight(HomeConnectDevice): @@ -185,14 +202,36 @@ class DeviceWithAmbientLight(HomeConnectDevice): def get_ambientlight_entity(self): """Get a dictionary with info about the ambient lighting.""" + return {"device": self, "desc": "AmbientLight", "ambient": True} + + +class DeviceWithRemoteControl(HomeConnectDevice): + """Device that has Remote Control binary sensor.""" + + def get_remote_control(self): + """Get a dictionary with info about the remote control sensor.""" return { "device": self, - "desc": "AmbientLight", - "ambient": True, + "desc": "Remote Control", + "sensor_type": "remote_control", } -class Dryer(DeviceWithDoor, DeviceWithPrograms): +class DeviceWithRemoteStart(HomeConnectDevice): + """Device that has a Remote Start binary sensor.""" + + def get_remote_start(self): + """Get a dictionary with info about the remote start sensor.""" + return {"device": self, "desc": "Remote Start", "sensor_type": "remote_start"} + + +class Dryer( + DeviceWithDoor, + DeviceWithOpState, + DeviceWithPrograms, + DeviceWithRemoteControl, + DeviceWithRemoteStart, +): """Dryer class.""" PROGRAMS = [ @@ -217,16 +256,26 @@ class Dryer(DeviceWithDoor, DeviceWithPrograms): def get_entity_info(self): """Get a dictionary with infos about the associated entities.""" door_entity = self.get_door_entity() + remote_control = self.get_remote_control() + remote_start = self.get_remote_start() + op_state_sensor = self.get_opstate_sensor() program_sensors = self.get_program_sensors() program_switches = self.get_program_switches() return { - "binary_sensor": [door_entity], + "binary_sensor": [door_entity, remote_control, remote_start], "switch": program_switches, - "sensor": program_sensors, + "sensor": program_sensors + op_state_sensor, } -class Dishwasher(DeviceWithDoor, DeviceWithAmbientLight, DeviceWithPrograms): +class Dishwasher( + DeviceWithDoor, + DeviceWithAmbientLight, + DeviceWithOpState, + DeviceWithPrograms, + DeviceWithRemoteControl, + DeviceWithRemoteStart, +): """Dishwasher class.""" PROGRAMS = [ @@ -257,16 +306,25 @@ class Dishwasher(DeviceWithDoor, DeviceWithAmbientLight, DeviceWithPrograms): def get_entity_info(self): """Get a dictionary with infos about the associated entities.""" door_entity = self.get_door_entity() + remote_control = self.get_remote_control() + remote_start = self.get_remote_start() + op_state_sensor = self.get_opstate_sensor() program_sensors = self.get_program_sensors() program_switches = self.get_program_switches() return { - "binary_sensor": [door_entity], + "binary_sensor": [door_entity, remote_control, remote_start], "switch": program_switches, - "sensor": program_sensors, + "sensor": program_sensors + op_state_sensor, } -class Oven(DeviceWithDoor, DeviceWithPrograms): +class Oven( + DeviceWithDoor, + DeviceWithOpState, + DeviceWithPrograms, + DeviceWithRemoteControl, + DeviceWithRemoteStart, +): """Oven class.""" PROGRAMS = [ @@ -282,16 +340,25 @@ class Oven(DeviceWithDoor, DeviceWithPrograms): def get_entity_info(self): """Get a dictionary with infos about the associated entities.""" door_entity = self.get_door_entity() + remote_control = self.get_remote_control() + remote_start = self.get_remote_start() + op_state_sensor = self.get_opstate_sensor() program_sensors = self.get_program_sensors() program_switches = self.get_program_switches() return { - "binary_sensor": [door_entity], + "binary_sensor": [door_entity, remote_control, remote_start], "switch": program_switches, - "sensor": program_sensors, + "sensor": program_sensors + op_state_sensor, } -class Washer(DeviceWithDoor, DeviceWithPrograms): +class Washer( + DeviceWithDoor, + DeviceWithOpState, + DeviceWithPrograms, + DeviceWithRemoteControl, + DeviceWithRemoteStart, +): """Washer class.""" PROGRAMS = [ @@ -321,16 +388,19 @@ class Washer(DeviceWithDoor, DeviceWithPrograms): def get_entity_info(self): """Get a dictionary with infos about the associated entities.""" door_entity = self.get_door_entity() + remote_control = self.get_remote_control() + remote_start = self.get_remote_start() + op_state_sensor = self.get_opstate_sensor() program_sensors = self.get_program_sensors() program_switches = self.get_program_switches() return { - "binary_sensor": [door_entity], + "binary_sensor": [door_entity, remote_control, remote_start], "switch": program_switches, - "sensor": program_sensors, + "sensor": program_sensors + op_state_sensor, } -class CoffeeMaker(DeviceWithPrograms): +class CoffeeMaker(DeviceWithOpState, DeviceWithPrograms, DeviceWithRemoteStart): """Coffee maker class.""" PROGRAMS = [ @@ -354,12 +424,25 @@ class CoffeeMaker(DeviceWithPrograms): def get_entity_info(self): """Get a dictionary with infos about the associated entities.""" + remote_start = self.get_remote_start() + op_state_sensor = self.get_opstate_sensor() program_sensors = self.get_program_sensors() program_switches = self.get_program_switches() - return {"switch": program_switches, "sensor": program_sensors} + return { + "binary_sensor": [remote_start], + "switch": program_switches, + "sensor": program_sensors + op_state_sensor, + } -class Hood(DeviceWithLight, DeviceWithAmbientLight, DeviceWithPrograms): +class Hood( + DeviceWithLight, + DeviceWithAmbientLight, + DeviceWithOpState, + DeviceWithPrograms, + DeviceWithRemoteControl, + DeviceWithRemoteStart, +): """Hood class.""" PROGRAMS = [ @@ -370,13 +453,17 @@ class Hood(DeviceWithLight, DeviceWithAmbientLight, DeviceWithPrograms): def get_entity_info(self): """Get a dictionary with infos about the associated entities.""" + remote_control = self.get_remote_control() + remote_start = self.get_remote_start() light_entity = self.get_light_entity() ambientlight_entity = self.get_ambientlight_entity() + op_state_sensor = self.get_opstate_sensor() program_sensors = self.get_program_sensors() program_switches = self.get_program_switches() return { + "binary_sensor": [remote_control, remote_start], "switch": program_switches, - "sensor": program_sensors, + "sensor": program_sensors + op_state_sensor, "light": [light_entity, ambientlight_entity], } @@ -390,13 +477,19 @@ class FridgeFreezer(DeviceWithDoor): return {"binary_sensor": [door_entity]} -class Hob(DeviceWithPrograms): +class Hob(DeviceWithOpState, DeviceWithPrograms, DeviceWithRemoteControl): """Hob class.""" PROGRAMS = [{"name": "Cooking.Hob.Program.PowerLevelMode"}] def get_entity_info(self): """Get a dictionary with infos about the associated entities.""" + remote_control = self.get_remote_control() + op_state_sensor = self.get_opstate_sensor() program_sensors = self.get_program_sensors() program_switches = self.get_program_switches() - return {"switch": program_switches, "sensor": program_sensors} + return { + "binary_sensor": [remote_control], + "switch": program_switches, + "sensor": program_sensors + op_state_sensor, + } diff --git a/homeassistant/components/home_connect/binary_sensor.py b/homeassistant/components/home_connect/binary_sensor.py index 4810231b432..1713d34809a 100644 --- a/homeassistant/components/home_connect/binary_sensor.py +++ b/homeassistant/components/home_connect/binary_sensor.py @@ -3,7 +3,12 @@ import logging from homeassistant.components.binary_sensor import BinarySensorEntity -from .const import BSH_DOOR_STATE, DOMAIN +from .const import ( + BSH_DOOR_STATE, + BSH_REMOTE_CONTROL_ACTIVATION_STATE, + BSH_REMOTE_START_ALLOWANCE_STATE, + DOMAIN, +) from .entity import HomeConnectEntity _LOGGER = logging.getLogger(__name__) @@ -26,11 +31,27 @@ async def async_setup_entry(hass, config_entry, async_add_entities): class HomeConnectBinarySensor(HomeConnectEntity, BinarySensorEntity): """Binary sensor for Home Connect.""" - def __init__(self, device, desc, device_class): + def __init__(self, device, desc, sensor_type, device_class=None): """Initialize the entity.""" super().__init__(device, desc) - self._device_class = device_class self._state = None + self._device_class = device_class + self._type = sensor_type + if self._type == "door": + self._update_key = BSH_DOOR_STATE + self._false_value_list = ( + "BSH.Common.EnumType.DoorState.Closed", + "BSH.Common.EnumType.DoorState.Locked", + ) + self._true_value_list = ["BSH.Common.EnumType.DoorState.Open"] + elif self._type == "remote_control": + self._update_key = BSH_REMOTE_CONTROL_ACTIVATION_STATE + self._false_value_list = [False] + self._true_value_list = [True] + elif self._type == "remote_start": + self._update_key = BSH_REMOTE_START_ALLOWANCE_STATE + self._false_value_list = [False] + self._true_value_list = [True] @property def is_on(self): @@ -44,18 +65,17 @@ class HomeConnectBinarySensor(HomeConnectEntity, BinarySensorEntity): async def async_update(self): """Update the binary sensor's status.""" - state = self.device.appliance.status.get(BSH_DOOR_STATE, {}) + state = self.device.appliance.status.get(self._update_key, {}) if not state: self._state = None - elif state.get("value") in [ - "BSH.Common.EnumType.DoorState.Closed", - "BSH.Common.EnumType.DoorState.Locked", - ]: + elif state.get("value") in self._false_value_list: self._state = False - elif state.get("value") == "BSH.Common.EnumType.DoorState.Open": + elif state.get("value") in self._true_value_list: self._state = True else: - _LOGGER.warning("Unexpected value for HomeConnect door state: %s", state) + _LOGGER.warning( + "Unexpected value for HomeConnect %s state: %s", self._type, state + ) self._state = None _LOGGER.debug("Updated, new state: %s", self._state) diff --git a/homeassistant/components/home_connect/const.py b/homeassistant/components/home_connect/const.py index 22ce4dba676..98dd8d383bd 100644 --- a/homeassistant/components/home_connect/const.py +++ b/homeassistant/components/home_connect/const.py @@ -11,6 +11,8 @@ BSH_POWER_OFF = "BSH.Common.EnumType.PowerState.Off" BSH_POWER_STANDBY = "BSH.Common.EnumType.PowerState.Standby" BSH_ACTIVE_PROGRAM = "BSH.Common.Root.ActiveProgram" BSH_OPERATION_STATE = "BSH.Common.Status.OperationState" +BSH_REMOTE_CONTROL_ACTIVATION_STATE = "BSH.Common.Status.RemoteControlActive" +BSH_REMOTE_START_ALLOWANCE_STATE = "BSH.Common.Status.RemoteControlStartAllowed" COOKING_LIGHTING = "Cooking.Common.Setting.Lighting" COOKING_LIGHTING_BRIGHTNESS = "Cooking.Common.Setting.LightingBrightness" diff --git a/homeassistant/components/home_connect/sensor.py b/homeassistant/components/home_connect/sensor.py index 0ae5a9fcd36..e51efe06057 100644 --- a/homeassistant/components/home_connect/sensor.py +++ b/homeassistant/components/home_connect/sensor.py @@ -6,7 +6,7 @@ import logging from homeassistant.const import DEVICE_CLASS_TIMESTAMP import homeassistant.util.dt as dt_util -from .const import DOMAIN +from .const import BSH_OPERATION_STATE, DOMAIN from .entity import HomeConnectEntity _LOGGER = logging.getLogger(__name__) @@ -51,7 +51,7 @@ class HomeConnectSensor(HomeConnectEntity): return self._state is not None async def async_update(self): - """Update the sensos status.""" + """Update the sensor's status.""" status = self.device.appliance.status if self._key not in status: self._state = None @@ -74,6 +74,11 @@ class HomeConnectSensor(HomeConnectEntity): ).isoformat() else: self._state = status[self._key].get("value") + if self._key == BSH_OPERATION_STATE: + # Value comes back as an enum, we only really care about the + # last part, so split it off + # https://developer.home-connect.com/docs/status/operation_state + self._state = self._state.split(".")[-1] _LOGGER.debug("Updated, new state: %s", self._state) @property