From 0edd7302d5f2c1f26702923c7bd6386e3c0173c2 Mon Sep 17 00:00:00 2001
From: guillempages <guillempages@users.noreply.github.com>
Date: Tue, 30 Jun 2020 23:39:20 +0200
Subject: [PATCH] Improve support for homematic garage covers (#35350)

---
 .../components/homematic/__init__.py          |  3 ++
 homeassistant/components/homematic/const.py   |  3 +-
 homeassistant/components/homematic/cover.py   | 41 +++++++++++++++++--
 3 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/homeassistant/components/homematic/__init__.py b/homeassistant/components/homematic/__init__.py
index 4dfc27650c8..97f3bf05205 100644
--- a/homeassistant/components/homematic/__init__.py
+++ b/homeassistant/components/homematic/__init__.py
@@ -25,6 +25,7 @@ import homeassistant.helpers.config_validation as cv
 from .const import (
     ATTR_ADDRESS,
     ATTR_CHANNEL,
+    ATTR_DEVICE_TYPE,
     ATTR_DISCOVER_DEVICES,
     ATTR_DISCOVERY_TYPE,
     ATTR_ERRORCODE,
@@ -99,6 +100,7 @@ DEVICE_SCHEMA = vol.Schema(
         vol.Required(ATTR_NAME): cv.string,
         vol.Required(ATTR_ADDRESS): cv.string,
         vol.Required(ATTR_INTERFACE): cv.string,
+        vol.Optional(ATTR_DEVICE_TYPE): cv.string,
         vol.Optional(ATTR_CHANNEL, default=DEFAULT_CHANNEL): vol.Coerce(int),
         vol.Optional(ATTR_PARAM): cv.string,
         vol.Optional(ATTR_UNIQUE_ID): cv.string,
@@ -533,6 +535,7 @@ def _get_devices(hass, discovery_type, keys, interface):
                     ATTR_ADDRESS: key,
                     ATTR_INTERFACE: interface,
                     ATTR_NAME: name,
+                    ATTR_DEVICE_TYPE: class_name,
                     ATTR_CHANNEL: channel,
                     ATTR_UNIQUE_ID: unique_id,
                 }
diff --git a/homeassistant/components/homematic/const.py b/homeassistant/components/homematic/const.py
index 9339fca84e5..bbb8c1ff1ca 100644
--- a/homeassistant/components/homematic/const.py
+++ b/homeassistant/components/homematic/const.py
@@ -15,6 +15,7 @@ ATTR_DISCOVER_DEVICES = "devices"
 ATTR_PARAM = "param"
 ATTR_CHANNEL = "channel"
 ATTR_ADDRESS = "address"
+ATTR_DEVICE_TYPE = "device_type"
 ATTR_VALUE = "value"
 ATTR_VALUE_TYPE = "value_type"
 ATTR_INTERFACE = "interface"
@@ -151,7 +152,7 @@ HM_DEVICE_TYPES = {
         "IPRemoteMotionV2",
         "IPWInputDevice",
     ],
-    DISCOVER_COVER: ["Blind", "KeyBlind", "IPKeyBlind", "IPKeyBlindTilt"],
+    DISCOVER_COVER: ["Blind", "KeyBlind", "IPKeyBlind", "IPKeyBlindTilt", "IPGarage"],
     DISCOVER_LOCKS: ["KeyMatic"],
 }
 
diff --git a/homeassistant/components/homematic/cover.py b/homeassistant/components/homematic/cover.py
index a520c08e478..c0074d349d1 100644
--- a/homeassistant/components/homematic/cover.py
+++ b/homeassistant/components/homematic/cover.py
@@ -4,14 +4,17 @@ import logging
 from homeassistant.components.cover import (
     ATTR_POSITION,
     ATTR_TILT_POSITION,
+    DEVICE_CLASS_GARAGE,
     CoverEntity,
 )
 
-from .const import ATTR_DISCOVER_DEVICES
+from .const import ATTR_DEVICE_TYPE, ATTR_DISCOVER_DEVICES
 from .entity import HMDevice
 
 _LOGGER = logging.getLogger(__name__)
 
+HM_GARAGE = ("IPGarage",)
+
 
 def setup_platform(hass, config, add_entities, discovery_info=None):
     """Set up the platform."""
@@ -20,7 +23,10 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
 
     devices = []
     for conf in discovery_info[ATTR_DISCOVER_DEVICES]:
-        new_device = HMCover(conf)
+        if conf[ATTR_DEVICE_TYPE] in HM_GARAGE:
+            new_device = HMGarage(conf)
+        else:
+            new_device = HMCover(conf)
         devices.append(new_device)
 
     add_entities(devices, True)
@@ -48,7 +54,7 @@ class HMCover(HMDevice, CoverEntity):
 
     @property
     def is_closed(self):
-        """Return if the cover is closed."""
+        """Return whether the cover is closed."""
         if self.current_cover_position is not None:
             return self.current_cover_position == 0
         return None
@@ -105,3 +111,32 @@ class HMCover(HMDevice, CoverEntity):
         """Stop cover tilt."""
         if "LEVEL_2" in self._data:
             self.stop_cover(**kwargs)
+
+
+class HMGarage(HMCover):
+    """Represents a Homematic Garage cover. Homematic garage covers do not support position attributes."""
+
+    @property
+    def current_cover_position(self):
+        """
+        Return current position of cover.
+
+        None is unknown, 0 is closed, 100 is fully open.
+        """
+        # Garage covers do not support position; always return None
+        return None
+
+    @property
+    def is_closed(self):
+        """Return whether the cover is closed."""
+        return self._hmdevice.is_closed(self._hm_get_state())
+
+    @property
+    def device_class(self):
+        """Return the device class."""
+        return DEVICE_CLASS_GARAGE
+
+    def _init_data_struct(self):
+        """Generate a data dictionary (self._data) from metadata."""
+        self._state = "DOOR_STATE"
+        self._data.update({self._state: None})
-- 
GitLab