From fbd5ccf1566d665f6aa3a03e6083869dd2862bda Mon Sep 17 00:00:00 2001 From: bsmappee <58250533+bsmappee@users.noreply.github.com> Date: Wed, 24 Jun 2020 14:37:48 +0200 Subject: [PATCH] Add smappee binary_sensor platform (#37023) --- .coveragerc | 1 + .../components/smappee/binary_sensor.py | 173 ++++++++++++++++++ homeassistant/components/smappee/const.py | 2 +- 3 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 homeassistant/components/smappee/binary_sensor.py diff --git a/.coveragerc b/.coveragerc index bd91654f28b..a15d22550eb 100644 --- a/.coveragerc +++ b/.coveragerc @@ -726,6 +726,7 @@ omit = homeassistant/components/sma/sensor.py homeassistant/components/smappee/__init__.py homeassistant/components/smappee/api.py + homeassistant/components/smappee/binary_sensor.py homeassistant/components/smappee/sensor.py homeassistant/components/smappee/switch.py homeassistant/components/smarty/* diff --git a/homeassistant/components/smappee/binary_sensor.py b/homeassistant/components/smappee/binary_sensor.py new file mode 100644 index 00000000000..7de6766bcb3 --- /dev/null +++ b/homeassistant/components/smappee/binary_sensor.py @@ -0,0 +1,173 @@ +"""Support for monitoring a Smappee appliance binary sensor.""" +import logging + +from homeassistant.components.binary_sensor import BinarySensorEntity + +from .const import BASE, DOMAIN + +_LOGGER = logging.getLogger(__name__) + +BINARY_SENSOR_PREFIX = "Appliance" +PRESENCE_PREFIX = "Presence" + + +async def async_setup_entry(hass, config_entry, async_add_entities): + """Set up the Smappee binary sensor.""" + smappee_base = hass.data[DOMAIN][BASE] + + entities = [] + for service_location in smappee_base.smappee.service_locations.values(): + for appliance_id, appliance in service_location.appliances.items(): + if appliance.type != "Find me" and appliance.source_type == "NILM": + entities.append( + SmappeeAppliance( + smappee_base=smappee_base, + service_location=service_location, + appliance_id=appliance_id, + appliance_name=appliance.name, + appliance_type=appliance.type, + ) + ) + + entities.append(SmappeePresence(smappee_base, service_location)) + + async_add_entities(entities, True) + + +class SmappeePresence(BinarySensorEntity): + """Implementation of a Smappee presence binary sensor.""" + + def __init__(self, smappee_base, service_location): + """Initialize the Smappee sensor.""" + self._smappee_base = smappee_base + self._service_location = service_location + self._state = self._service_location.is_present + + @property + def name(self): + """Return the name of the binary sensor.""" + return f"{self._service_location.service_location_name} - {PRESENCE_PREFIX}" + + @property + def is_on(self): + """Return if the binary sensor is turned on.""" + return self._state + + @property + def device_class(self): + """Return the class of this device, from component DEVICE_CLASSES.""" + return "presence" + + @property + def unique_id(self,): + """Return the unique ID for this binary sensor.""" + return ( + f"{self._service_location.device_serial_number}-" + f"{self._service_location.service_location_id}-" + f"presence" + ) + + @property + def device_info(self): + """Return the device info for this binary sensor.""" + return { + "identifiers": {(DOMAIN, self._service_location.device_serial_number)}, + "name": self._service_location.service_location_name, + "manufacturer": "Smappee", + "model": self._service_location.device_model, + "sw_version": self._service_location.firmware_version, + } + + async def async_update(self): + """Get the latest data from Smappee and update the state.""" + await self._smappee_base.async_update() + + self._state = self._service_location.is_present + + +class SmappeeAppliance(BinarySensorEntity): + """Implementation of a Smappee binary sensor.""" + + def __init__( + self, + smappee_base, + service_location, + appliance_id, + appliance_name, + appliance_type, + ): + """Initialize the Smappee sensor.""" + self._smappee_base = smappee_base + self._service_location = service_location + self._appliance_id = appliance_id + self._appliance_name = appliance_name + self._appliance_type = appliance_type + self._state = False + + @property + def name(self): + """Return the name of the sensor.""" + return ( + f"{self._service_location.service_location_name} - " + f"{BINARY_SENSOR_PREFIX} - " + f"{self._appliance_name if self._appliance_name != '' else self._appliance_type}" + ) + + @property + def is_on(self): + """Return if the binary sensor is turned on.""" + return self._state + + @property + def icon(self): + """Icon to use in the frontend.""" + icon_mapping = { + "Car Charger": "mdi:car", + "Coffeemaker": "mdi:coffee", + "Clothes Dryer": "mdi:tumble-dryer", + "Clothes Iron": "mdi:hanger", + "Dishwasher": "mdi:dishwasher", + "Lights": "mdi:lightbulb", + "Fan": "mdi:fan", + "Freezer": "mdi:fridge", + "Microwave": "mdi:microwave", + "Oven": "mdi:stove", + "Refrigerator": "mdi:fridge", + "Stove": "mdi:stove", + "Washing Machine": "mdi:washing-machine", + "Water Pump": "mdi:water-pump", + } + return icon_mapping.get(self._appliance_type) + + @property + def device_class(self): + """Return the class of this device, from component DEVICE_CLASSES.""" + # Only lights can be mapped onto the generic list of binary sensors + return "light" if self._appliance_type == "Lights" else "power" + + @property + def unique_id(self,): + """Return the unique ID for this binary sensor.""" + return ( + f"{self._service_location.device_serial_number}-" + f"{self._service_location.service_location_id}-" + f"appliance-{self._appliance_id}" + ) + + @property + def device_info(self): + """Return the device info for this binary sensor.""" + return { + "identifiers": {(DOMAIN, self._service_location.device_serial_number)}, + "name": self._service_location.service_location_name, + "manufacturer": "Smappee", + "model": self._service_location.device_model, + "sw_version": self._service_location.firmware_version, + } + + async def async_update(self): + """Get the latest data from Smappee and update the state.""" + await self._smappee_base.async_update() + + appliance = self._service_location.appliances.get(self._appliance_id) + self._state = bool(appliance.state) diff --git a/homeassistant/components/smappee/const.py b/homeassistant/components/smappee/const.py index 3c174d47427..05998ac6716 100644 --- a/homeassistant/components/smappee/const.py +++ b/homeassistant/components/smappee/const.py @@ -7,7 +7,7 @@ DATA_CLIENT = "smappee_data" BASE = "BASE" -SMAPPEE_PLATFORMS = ["sensor", "switch"] +SMAPPEE_PLATFORMS = ["binary_sensor", "sensor", "switch"] MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=5)