Repository: zigpy/zha-device-handlers
Pull request #269 (2020-02-11 05:59:29)

initial tradfri blind quirks


Patch:
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..2c43fee
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,27 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: "[BUG]"
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Additional context**
+Add any other context about the problem here. Please include full debug logs as well as the device signature.
diff --git a/.github/ISSUE_TEMPLATE/device-support-request.md b/.github/ISSUE_TEMPLATE/device-support-request.md
new file mode 100644
index 0000000..141a187
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/device-support-request.md
@@ -0,0 +1,19 @@
+---
+name: Device support request
+about: Request support for an unsupported device or device feature
+title: "[Device Support Request]"
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Device signature - this can be acquired by removing the device from ZHA and pairing it again from the add devices screen. Be sure to add the entire content of the log panel after pairing the device to a code block below this line.**
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/Contributors.md b/Contributors.md
index 42735ae..732bc0d 100644
--- a/Contributors.md
+++ b/Contributors.md
@@ -18,3 +18,4 @@
 - [Nemesis24](https://github.com/Nemesis24)
 - [Andy Zickler](https://github.com/andyzickler)
 - [Piotr Majkrzak](https://github.com/majkrzak)
+- [Gleb Sinyavskiy](https://github.com/zhulik)
diff --git a/README.md b/README.md
index dcd3c51..65a4004 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[![Build Status](https://travis-ci.org/dmulcahey/zha-device-handlers.svg?branch=master)](https://travis-ci.org/dmulcahey/zha-device-handlers)
+[![Build Status](https://travis-ci.org/zigpy/zha-device-handlers.svg?branch=master)](https://travis-ci.org/zigpy/zha-device-handlers)
 
 # ZHA Device Handlers For Home Assistant
 
@@ -40,6 +40,8 @@ If you are looking to make your first code contribution to this project then we
 - [Motion Sensor](https://www.aqara.com/en/motion_sensor.html): lumi.sensor_motion.aq2
 - [Temperature / Humidity Sensor](https://www.aqara.com/en/temperature_and_humidity_sensor-product.html): lumi.weather
 - [Water Leak](https://www.aqara.com/en/water_leak_sensor.html): lumi.sensor_wleak.aq1
+- [US Plug](https://www.aqara.com/en/smart_plug.html): lumi.plug.maus01
+- [EU Plug](https://zigbee.blakadder.com/Xiaomi_ZNCZ04LM.html): lumi.plug.mmeu01
 
 ### Osram
 - [OSRAM LIGHTIFY Dimming Switch](https://assets.osram-americas.com/assets/Documents/LTFY012.06c0d6e6-17c7-4dcb-bd2c-1fca7feecfb4.pdf):
@@ -96,6 +98,7 @@ If you are looking to make your first code contribution to this project then we
 - Cube sends the following events: `flip (90 and 180 degrees)`, `rotate_left`, `rotate_right`, `knock`, `drop`, `slide` and `shake`
 - Motion sensor exposes binary sensors for motion and occupancy.
 - Button sends events to Home Assistant
+- All supported plugs report power consumption and can be toggled
 
 ### SmartThings
 
@@ -127,6 +130,28 @@ Please refer to [xbee.md](xbee.md) for details on configuration and usage exampl
 
 - All supported devices report battery level
 
+# Testing new releases
+
+Testing a new release of the zha-quirks package before it is released in Home Assistant.
+
+If you are using Supervised Home Assistant (formerly known as the Hassio/Hass.io distro):
+- Add https://github.com/home-assistant/hassio-addons-development as "add-on" repository
+- Install "Custom deps deployment" addon
+- Update config like: 
+  ```
+  pypi:
+    - zha-quirks==0.0.38
+  apk: []
+  ```
+  where 0.0.38 is the new version
+- Start the addon
+
+If you are instead using some custom python installation of Home Assistant then do this:
+- Activate your python virtual env
+- Update package with ``pip``
+  ```
+  pip install zha-quirks==0.0.38
+
 # Thanks
 
 - Special thanks to damarco for the majority of the device tracker code
diff --git a/pylintrc b/pylintrc
index 1ccde09..8cc5301 100644
--- a/pylintrc
+++ b/pylintrc
@@ -26,6 +26,7 @@ disable=
   not-context-manager,
   redefined-variable-type,
   too-few-public-methods,
+  too-many-ancestors,
   too-many-arguments,
   too-many-branches,
   too-many-instance-attributes,
diff --git a/setup.py b/setup.py
index e33db24..aed1344 100644
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@
 
 from setuptools import find_packages, setup
 
-VERSION = "0.0.32"
+VERSION = "0.0.41"
 
 
 def readme():
@@ -24,6 +24,6 @@ setup(
     keywords="zha quirks homeassistant hass",
     packages=find_packages(exclude=["*.tests"]),
     python_requires=">=3",
-    install_requires=["zigpy-homeassistant>=0.8.0"],
+    install_requires=["zigpy>=0.20.0"],
     tests_require=["pytest"],
 )
diff --git a/zhaquirks/__init__.py b/zhaquirks/__init__.py
index 8fcc04c..08c4694 100755
--- a/zhaquirks/__init__.py
+++ b/zhaquirks/__init__.py
@@ -33,6 +33,18 @@ class Bus(ListenableMixin):
 class LocalDataCluster(CustomCluster):
     """Cluster meant to prevent remote calls."""
 
+    async def bind(self):
+        """Prevent bind."""
+        return (foundation.Status.SUCCESS,)
+
+    async def unbind(self):
+        """Prevent unbind."""
+        return (foundation.Status.SUCCESS,)
+
+    async def _configure_reporting(self, *args, **kwargs):
+        """Prevent remote configure reporting."""
+        return foundation.ConfigureReportingResponse.deserialize(b"\x00")[0]
+
     async def read_attributes_raw(self, attributes, manufacturer=None):
         """Prevent remote reads."""
         records = [
@@ -51,7 +63,7 @@ class LocalDataCluster(CustomCluster):
         """Prevent remote writes."""
         for attrid, value in attributes.items():
             if isinstance(attrid, str):
-                attrid = self._attridx[attrid]
+                attrid = self.attridx[attrid]
             if attrid not in self.attributes:
                 self.error("%d is not a valid attribute id", attrid)
                 continue
@@ -69,14 +81,13 @@ class EventableCluster(CustomCluster):
             and self.server_commands.get(command_id) is not None
         ):
             self.listener_event(
-                ZHA_SEND_EVENT, self, self.server_commands.get(command_id)[0], args
+                ZHA_SEND_EVENT, self.server_commands.get(command_id)[0], args
             )
 
     def _update_attribute(self, attrid, value):
         super()._update_attribute(attrid, value)
         self.listener_event(
             ZHA_SEND_EVENT,
-            self,
             COMMAND_ATTRIBUTE_UPDATED,
             {
                 ATTRIBUTE_ID: attrid,
@@ -143,15 +154,13 @@ class PowerConfigurationCluster(CustomCluster, PowerConfiguration):
 
     def _update_attribute(self, attrid, value):
         super()._update_attribute(attrid, value)
-        if attrid == self.BATTERY_VOLTAGE_ATTR:
+        if attrid == self.BATTERY_VOLTAGE_ATTR and value not in (0, 255):
             super()._update_attribute(
                 self.BATTERY_PERCENTAGE_REMAINING,
                 self._calculate_battery_percentage(value),
             )
 
     def _calculate_battery_percentage(self, raw_value):
-        if raw_value in (0, 255):
-            return -1
         volts = raw_value / 10
         volts = max(volts, self.MIN_VOLTS)
         volts = min(volts, self.MAX_VOLTS)
diff --git a/zhaquirks/bosch/__init__.py b/zhaquirks/bosch/__init__.py
new file mode 100644
index 0000000..24605b6
--- /dev/null
+++ b/zhaquirks/bosch/__init__.py
@@ -0,0 +1,3 @@
+"""Bosch quirks."""
+
+BOSCH = "Bosch"
diff --git a/zhaquirks/bosch/motion.py b/zhaquirks/bosch/motion.py
new file mode 100755
index 0000000..3cca006
--- /dev/null
+++ b/zhaquirks/bosch/motion.py
@@ -0,0 +1,71 @@
+"""Device handler for Bosch motion sensors."""
+from zigpy.profiles import zha
+from zigpy.quirks import CustomDevice
+from zigpy.zcl.clusters.general import Basic, Identify, Ota, PollControl
+from zigpy.zcl.clusters.homeautomation import Diagnostic
+from zigpy.zcl.clusters.measurement import TemperatureMeasurement
+from zigpy.zcl.clusters.security import IasZone
+
+from zhaquirks import PowerConfigurationCluster
+
+from . import BOSCH
+from ..const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+)
+
+
+class BoschPowerConfiguration(PowerConfigurationCluster):
+    """Bosch power configuration cluster for motion sensor."""
+
+    MAX_VOLTS = 3.0
+    MIN_VOLTS = 1.9
+
+
+class ISWZPR1WP13(CustomDevice):
+    """Custom device representing Bosch motion sensors."""
+
+    signature = {
+        #  <SimpleDescriptor endpoint=1 profile=260 device_type=1026
+        #  device_version=0
+        #  input_clusters=[0, 1, 3, 1026, 1280, 32, 2821]
+        #  output_clusters=[25]>
+        MODELS_INFO: [(BOSCH, "ISW-ZPR1-WP13")],
+        ENDPOINTS: {
+            5: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfigurationCluster.cluster_id,
+                    Identify.cluster_id,
+                    PollControl.cluster_id,
+                    TemperatureMeasurement.cluster_id,
+                    IasZone.cluster_id,
+                    Diagnostic.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [Ota.cluster_id],
+            }
+        },
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            5: {
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    BoschPowerConfiguration,
+                    Identify.cluster_id,
+                    PollControl.cluster_id,
+                    TemperatureMeasurement.cluster_id,
+                    IasZone.cluster_id,
+                    Diagnostic.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [Ota.cluster_id],
+            }
+        }
+    }
diff --git a/zhaquirks/centralite/3460L.py b/zhaquirks/centralite/3460L.py
index eb6afa4..0ded4cc 100755
--- a/zhaquirks/centralite/3460L.py
+++ b/zhaquirks/centralite/3460L.py
@@ -15,12 +15,18 @@ from zigpy.zcl.clusters.measurement import TemperatureMeasurement
 from zhaquirks import PowerConfigurationCluster
 from zhaquirks.centralite import CENTRALITE
 from zhaquirks.const import (
+    BUTTON_1,
+    COMMAND,
+    COMMAND_OFF,
+    COMMAND_ON,
     DEVICE_TYPE,
     ENDPOINTS,
     INPUT_CLUSTERS,
     MODELS_INFO,
     OUTPUT_CLUSTERS,
     PROFILE_ID,
+    SHORT_PRESS,
+    SHORT_RELEASE,
 )
 
 DIAGNOSTICS_CLUSTER_ID = 0x0B05  # decimal = 2821
@@ -85,3 +91,8 @@ class CentraLite3460L(CustomDevice):
             }
         }
     }
+
+    device_automation_triggers = {
+        (SHORT_PRESS, BUTTON_1): {COMMAND: COMMAND_ON},
+        (SHORT_RELEASE, BUTTON_1): {COMMAND: COMMAND_OFF},
+    }
diff --git a/zhaquirks/centralite/ias.py b/zhaquirks/centralite/ias.py
index 235d332..ef70d10 100755
--- a/zhaquirks/centralite/ias.py
+++ b/zhaquirks/centralite/ias.py
@@ -1,11 +1,12 @@
 """Device handler for centralite ias sensors."""
 from zigpy.profiles import zha
 from zigpy.quirks import CustomDevice
-from zigpy.zcl.clusters.general import Basic, Identify, Ota, PollControl
+from zigpy.zcl.clusters.general import Basic, BinaryInput, Identify, Ota, PollControl
 from zigpy.zcl.clusters.measurement import TemperatureMeasurement
 from zigpy.zcl.clusters.security import IasZone
 
 from zhaquirks import PowerConfigurationCluster
+
 from . import CENTRALITE
 from ..const import (
     DEVICE_TYPE,
@@ -97,3 +98,70 @@ class CentraLiteIASSensor(CustomDevice):
             },
         }
     }
+
+
+class CentraLiteIASSensorV2(CustomDevice):
+    """Custom device representing centralite ias sensors."""
+
+    signature = {
+        #  <SimpleDescriptor endpoint=1 profile=260 device_type=1026
+        #  device_version=0
+        #  input_clusters=[0, 1, 3, 32, 1026, 1280, 2821]
+        #  output_clusters=[25]>
+        MODELS_INFO: CentraLiteIASSensor.signature[MODELS_INFO],
+        ENDPOINTS: {
+            1: CentraLiteIASSensor.signature[ENDPOINTS][1],
+            #  <SimpleDescriptor endpoint=2 profile=49887 device_type=12
+            #  device_version=0
+            #  input_clusters=[0, 1, 3, 15, 2821, 64527]
+            #  output_clusters=[3]>
+            2: {
+                PROFILE_ID: MANUFACTURER_SPECIFIC_PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.SIMPLE_SENSOR,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    BinaryInput.cluster_id,
+                    PowerConfigurationCluster.cluster_id,
+                    Identify.cluster_id,
+                    DIAGNOSTICS_CLUSTER_ID,
+                    MANUFACTURER_SPECIFIC_CLUSTER_ID,
+                ],
+                OUTPUT_CLUSTERS: [Identify.cluster_id],
+            },
+        },
+    }
+
+    replacement = CentraLiteIASSensor.replacement
+
+
+class CentraLiteIASSensorV3(CustomDevice):
+    """Custom device representing centralite ias sensors."""
+
+    signature = {
+        #  <SimpleDescriptor endpoint=1 profile=260 device_type=1026
+        #  device_version=0
+        #  input_clusters=[0, 1, 3, 32, 1026, 1280, 2821]
+        #  output_clusters=[25]>
+        MODELS_INFO: CentraLiteIASSensor.signature[MODELS_INFO],
+        ENDPOINTS: {
+            1: CentraLiteIASSensor.signature[ENDPOINTS][1],
+            #  <SimpleDescriptor endpoint=2 profile=49887 device_type=12
+            #  device_version=0
+            #  input_clusters=[0, 1, 3, 15, 2821]
+            #  output_clusters=[3]>
+            2: {
+                PROFILE_ID: MANUFACTURER_SPECIFIC_PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.SIMPLE_SENSOR,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    BinaryInput.cluster_id,
+                    PowerConfigurationCluster.cluster_id,
+                    Identify.cluster_id,
+                    DIAGNOSTICS_CLUSTER_ID,
+                ],
+                OUTPUT_CLUSTERS: [Identify.cluster_id],
+            },
+        },
+    }
+
+    replacement = CentraLiteIASSensor.replacement
diff --git a/zhaquirks/const.py b/zhaquirks/const.py
index 37e5af9..72c9674 100644
--- a/zhaquirks/const.py
+++ b/zhaquirks/const.py
@@ -48,12 +48,15 @@ DEVICE_TYPE = "device_type"
 DIM_DOWN = "dim_down"
 DIM_UP = "dim_up"
 DOUBLE_PRESS = "remote_button_double_press"
+ALT_DOUBLE_PRESS = "remote_button_alt_double_press"
 ENDPOINT_ID = "endpoint_id"
 ENDPOINTS = "endpoints"
 INPUT_CLUSTERS = "input_clusters"
 LEFT = "left"
 LONG_PRESS = "remote_button_long_press"
 LONG_RELEASE = "remote_button_long_release"
+ALT_LONG_PRESS = "remote_button_alt_long_press"
+ALT_LONG_RELEASE = "remote_button_alt_long_release"
 MODELS_INFO = "models_info"
 MOTION_EVENT = "motion_event"
 NODE_DESCRIPTOR = "node_desc"
@@ -69,6 +72,9 @@ RELATIVE_DEGREES = "relative_degrees"
 RIGHT = "right"
 SHAKEN = "device_shaken"
 SHORT_PRESS = "remote_button_short_press"
+ALT_SHORT_PRESS = "remote_button_alt_short_press"
+SKIP_CONFIGURATION = "skip_configuration"
+SHORT_RELEASE = "remote_button_short_release"
 TRIPLE_PRESS = "remote_button_triple_press"
 TURN_OFF = "turn_off"
 TURN_ON = "turn_on"
diff --git a/zhaquirks/echostar/__init__.py b/zhaquirks/echostar/__init__.py
new file mode 100644
index 0000000..8e3d9fb
--- /dev/null
+++ b/zhaquirks/echostar/__init__.py
@@ -0,0 +1,1 @@
+"""Module for Echostar quirks implementations."""
diff --git a/zhaquirks/echostar/bell.py b/zhaquirks/echostar/bell.py
new file mode 100644
index 0000000..64809af
--- /dev/null
+++ b/zhaquirks/echostar/bell.py
@@ -0,0 +1,87 @@
+"""Echostar Sage Doorbell Sensor Device."""
+from zigpy.profiles import zha
+from zigpy.quirks import CustomDevice
+from zigpy.zcl.clusters.general import (
+    Alarms,
+    Basic,
+    Identify,
+    LevelControl,
+    OnOff,
+    Ota,
+    PowerConfiguration,
+)
+
+from ..const import (
+    BUTTON_1,
+    BUTTON_2,
+    CLUSTER_ID,
+    COMMAND,
+    COMMAND_ON,
+    COMMAND_OFF,
+    DEVICE_TYPE,
+    ENDPOINT_ID,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+    SHORT_PRESS,
+)
+
+MANUFACTURER = " Echostar"
+MODEL = "   Bell"
+
+
+class Bell(CustomDevice):
+    """Echostar Bell device."""
+
+    signature = {
+        # <SimpleDescriptor endpoint=18 profile=260 device_type=260
+        # device_version=0
+        # input_clusters=[0, 3, 9, 1]
+        # output_clusters=[3, 6, 8, 25]>
+        MODELS_INFO: [(MANUFACTURER, MODEL)],
+        ENDPOINTS: {
+            18: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.DIMMER_SWITCH,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    Alarms.cluster_id,
+                    PowerConfiguration.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Identify.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Ota.cluster_id,
+                ],
+            }
+        },
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            18: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    Alarms.cluster_id,
+                    PowerConfiguration.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Identify.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Ota.cluster_id,
+                ],
+            }
+        }
+    }
+    device_automation_triggers = {
+        (SHORT_PRESS, BUTTON_1): {COMMAND: COMMAND_ON, CLUSTER_ID: 6, ENDPOINT_ID: 18},
+        (SHORT_PRESS, BUTTON_2): {COMMAND: COMMAND_OFF, CLUSTER_ID: 6, ENDPOINT_ID: 18},
+    }
diff --git a/zhaquirks/eurotronic/__init__.py b/zhaquirks/eurotronic/__init__.py
new file mode 100644
index 0000000..76c3211
--- /dev/null
+++ b/zhaquirks/eurotronic/__init__.py
@@ -0,0 +1,148 @@
+"""Eurotronic devices."""
+
+import logging
+
+import zigpy.types as types
+from zigpy.quirks import CustomCluster
+from zigpy.zcl import foundation
+from zigpy.zcl.clusters.hvac import Thermostat
+
+
+EUROTRONIC = "Eurotronic"
+
+THERMOSTAT_CHANNEL = "thermostat"
+
+MANUFACTURER = 0x1037  # 4151
+
+OCCUPIED_HEATING_SETPOINT_ATTR = 0x0012
+CTRL_SEQ_OF_OPER_ATTR = 0x001B
+SYSTEM_MODE_ATTR = 0x001C
+
+TRV_MODE_ATTR = 0x4000
+SET_VALVE_POS_ATTR = 0x4001
+ERRORS_ATTR = 0x4002
+CURRENT_TEMP_SETPOINT_ATTR = 0x4003
+HOST_FLAGS_ATTR = 0x4008
+
+
+# Host Flags
+# unknown (defaults to 1)       = 0b00000001 # 1
+MIRROR_SCREEN_FLAG = 0b00000010  # 2
+BOOST_FLAG = 0b00000100  # 4
+# unknown                       = 0b00001000 # 8
+CLR_OFF_MODE_FLAG = 0b00010000  # 16
+SET_OFF_MODE_FLAG = 0b00100000  # 32, reported back as 16
+# unknown                       = 0b01000000 # 64
+CHILD_LOCK_FLAG = 0b10000000  # 128
+
+
+_LOGGER = logging.getLogger(__name__)
+
+
+class ThermostatCluster(CustomCluster, Thermostat):
+    """Thermostat cluster."""
+
+    cluster_id = Thermostat.cluster_id
+
+    attributes = {
+        TRV_MODE_ATTR: ("trv_mode", types.enum8),
+        SET_VALVE_POS_ATTR: ("set_valve_position", types.uint8_t),
+        ERRORS_ATTR: ("errors", types.uint8_t),
+        CURRENT_TEMP_SETPOINT_ATTR: ("current_temperature_setpoint", types.int16s),
+        HOST_FLAGS_ATTR: ("host_flags", types.uint24_t),
+    }
+    attributes.update(Thermostat.attributes)
+
+    def _update_attribute(self, attrid, value):
+        _LOGGER.debug("update attribute %04x to %s... ", attrid, value)
+
+        if attrid == CURRENT_TEMP_SETPOINT_ATTR:
+            super()._update_attribute(OCCUPIED_HEATING_SETPOINT_ATTR, value)
+        elif attrid == HOST_FLAGS_ATTR:
+            if value & CLR_OFF_MODE_FLAG == CLR_OFF_MODE_FLAG:
+                super()._update_attribute(SYSTEM_MODE_ATTR, 0x0)
+                _LOGGER.debug("set system_mode to [off ]")
+            else:
+                super()._update_attribute(SYSTEM_MODE_ATTR, 0x4)
+                _LOGGER.debug("set system_mode to [heat]")
+
+        _LOGGER.debug("update attribute %04x to %s... [ ok ]", attrid, value)
+        super()._update_attribute(attrid, value)
+
+    async def read_attributes_raw(self, attributes, manufacturer=None):
+        """Override wrong attribute reports from the thermostat."""
+        success = []
+        error = []
+
+        if CTRL_SEQ_OF_OPER_ATTR in attributes:
+            rar = foundation.ReadAttributeRecord(
+                CTRL_SEQ_OF_OPER_ATTR, foundation.Status.SUCCESS, foundation.TypeValue()
+            )
+            rar.value.value = 0x2
+            success.append(rar)
+
+        if SYSTEM_MODE_ATTR in attributes:
+            rar = foundation.ReadAttributeRecord(
+                SYSTEM_MODE_ATTR, foundation.Status.SUCCESS, foundation.TypeValue()
+            )
+            rar.value.value = 0x4
+            success.append(rar)
+
+        if OCCUPIED_HEATING_SETPOINT_ATTR in attributes:
+
+            _LOGGER.debug("intercepting OCC_HS")
+
+            values = await super().read_attributes_raw(
+                [CURRENT_TEMP_SETPOINT_ATTR], manufacturer=MANUFACTURER
+            )
+
+            if len(values) == 2:
+                current_temp_setpoint = values[1][0]
+                current_temp_setpoint.attrid = OCCUPIED_HEATING_SETPOINT_ATTR
+
+                error.extend(values[1])
+            else:
+                current_temp_setpoint = values[0][0]
+                current_temp_setpoint.attrid = OCCUPIED_HEATING_SETPOINT_ATTR
+
+                success.extend(values[0])
+
+        attributes = list(
+            filter(
+                lambda x: x
+                not in (
+                    CTRL_SEQ_OF_OPER_ATTR,
+                    SYSTEM_MODE_ATTR,
+                    OCCUPIED_HEATING_SETPOINT_ATTR,
+                ),
+                attributes,
+            )
+        )
+
+        if attributes:
+            values = await super().read_attributes_raw(attributes, manufacturer)
+
+            success.extend(values[0])
+
+            if len(values) == 2:
+                error.extend(values[1])
+
+        return success, error
+
+    def write_attributes(self, attributes, manufacturer=None):
+        """Override wrong writes to thermostat attributes."""
+        if "system_mode" in attributes:
+
+            host_flags = self._attr_cache.get(HOST_FLAGS_ATTR, 1)
+            _LOGGER.debug("current host_flags: %s", host_flags)
+
+            if attributes.get("system_mode") == 0x0:
+                return super().write_attributes(
+                    {"host_flags": host_flags | SET_OFF_MODE_FLAG}, MANUFACTURER
+                )
+            if attributes.get("system_mode") == 0x4:
+                return super().write_attributes(
+                    {"host_flags": host_flags | CLR_OFF_MODE_FLAG}, MANUFACTURER
+                )
+
+        return super().write_attributes(attributes, manufacturer)
diff --git a/zhaquirks/eurotronic/spzb0001.py b/zhaquirks/eurotronic/spzb0001.py
new file mode 100644
index 0000000..ef6441e
--- /dev/null
+++ b/zhaquirks/eurotronic/spzb0001.py
@@ -0,0 +1,85 @@
+"""Eurotronic Spirit Zigbee quirk."""
+
+from zigpy.profiles import zha
+from zigpy.quirks import CustomDevice
+from zigpy.zcl.clusters.general import (
+    Basic,
+    Groups,
+    Identify,
+    Ota,
+    PowerConfiguration,
+    Time,
+)
+from zigpy.zcl.clusters.hvac import Thermostat
+
+from zhaquirks.const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+)
+
+from . import EUROTRONIC, ThermostatCluster
+
+
+class SPZB0001(CustomDevice):
+    """Eurotronic Spirit Zigbee device."""
+
+    signature = {
+        # <SimpleDescriptor endpoint=1 profile=260 device_type=769
+        # device_version=1
+        # input_clusters=[0, 1, 3, 513, 25, 10]
+        # output_clusters=[0, 1, 3, 4, 513, 25, 10]>
+        MODELS_INFO: [(EUROTRONIC, "SPZB0001")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.THERMOSTAT,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    Thermostat.cluster_id,
+                    Ota.cluster_id,
+                    Time.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    Thermostat.cluster_id,
+                    Ota.cluster_id,
+                    Time.cluster_id,
+                ],
+            }
+        },
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.THERMOSTAT,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    ThermostatCluster,
+                    Ota.cluster_id,
+                    Time.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    ThermostatCluster,
+                    Ota.cluster_id,
+                    Time.cluster_id,
+                ],
+            }
+        }
+    }
diff --git a/zhaquirks/ikea/__init__.py b/zhaquirks/ikea/__init__.py
index 9cdc751..d02ba52 100644
--- a/zhaquirks/ikea/__init__.py
+++ b/zhaquirks/ikea/__init__.py
@@ -1,7 +1,10 @@
 """Ikea module."""
 import logging
-from zigpy.zcl.clusters.lightlink import LightLink
+
+import zigpy.types as t
 from zigpy.quirks import CustomCluster
+from zigpy.zcl.clusters.general import Scenes
+from zigpy.zcl.clusters.lightlink import LightLink
 
 _LOGGER = logging.getLogger(__name__)
 IKEA = "IKEA of Sweden"
@@ -19,7 +22,29 @@ class LightLinkCluster(CustomCluster, LightLink):
             _LOGGER.warning("Aborting - unable to locate required coordinator device.")
             return
         group_list = await self.get_group_identifiers(0)
-        group_record = group_list[2]
-        group_id = group_record[0].group_id
+        try:
+            group_record = group_list[2]
+            group_id = group_record[0].group_id
+        except IndexError:
+            _LOGGER.warning(
+                "unable to locate required group info - falling back to group 0x0000."
+            )
+            group_id = 0x0000
         status = await coordinator.add_to_group(group_id)
         return [status]
+
+
+class ScenesCluster(CustomCluster, Scenes):
+    """Ikea Scenes cluster."""
+
+    def __init__(self, *args, **kwargs):
+        """Init."""
+        super().__init__(*args, **kwargs)
+        self.server_commands = Scenes.attributes.copy()
+        self.server_commands.update(
+            {
+                0x0007: ("press", (t.int16s, t.int8s, t.int8s), False),
+                0x0008: ("hold", (t.int16s, t.int8s), False),
+                0x0009: ("release", (t.int16s,), False),
+            }
+        )
diff --git a/zhaquirks/ikea/blinds.py b/zhaquirks/ikea/blinds.py
new file mode 100644
index 0000000..3ef5786
--- /dev/null
+++ b/zhaquirks/ikea/blinds.py
@@ -0,0 +1,79 @@
+"""Device handler for IKEA of Sweden TRADFRI Fyrtur blinds."""
+from zigpy.profiles import zha
+from zigpy.quirks import CustomDevice
+from zigpy.zcl.clusters.closures import WindowCovering
+from zigpy.zcl.clusters.general import (
+    Basic,
+    Groups,
+    Identify,
+    Ota,
+    PollControl,
+    PowerConfiguration,
+    Scenes,
+)
+from zigpy.zcl.clusters.lightlink import LightLink
+
+from . import IKEA
+from .. import DoublingPowerConfigurationCluster
+from ..const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+)
+
+IKEA_CLUSTER_ID = 0xFC7C  # decimal = 64636
+
+
+class IkeaTradfriRollerBlinds(CustomDevice):
+    """Custom device representing IKEA of Sweden TRADFRI Fyrtur blinds."""
+
+    signature = {
+        # <SimpleDescriptor endpoint=1 profile=260 device_type=2080
+        # device_version=1
+        # input_clusters=[0, 1, 3, 4, 5, 32, 258, 4096]
+        # output_clusters=[25, 4096]>
+        MODELS_INFO: [
+            (IKEA, "FYRTUR block-out roller blind"),
+            (IKEA, "KADRILJ roller blind"),
+        ],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                    PollControl.cluster_id,
+                    WindowCovering.cluster_id,
+                    LightLink.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [Ota.cluster_id, LightLink.cluster_id],
+            }
+        },
+    }
+
+    replacement = {
+        "endpoints": {
+            1: {
+                "profile_id": zha.PROFILE_ID,
+                "device_type": zha.DeviceType.WINDOW_COVERING_DEVICE,
+                "input_clusters": [
+                    Basic.cluster_id,
+                    DoublingPowerConfigurationCluster,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                    PollControl.cluster_id,
+                    WindowCovering.cluster_id,
+                    LightLink.cluster_id,
+                ],
+                "output_clusters": [Ota.cluster_id, LightLink.cluster_id],
+            }
+        }
+    }
diff --git a/zhaquirks/ikea/fivebtnremote.py b/zhaquirks/ikea/fivebtnremote.py
index ceb8e32..0677efb 100644
--- a/zhaquirks/ikea/fivebtnremote.py
+++ b/zhaquirks/ikea/fivebtnremote.py
@@ -1,7 +1,6 @@
 """Device handler for IKEA of Sweden TRADFRI remote control."""
 from zigpy.profiles import zll
 from zigpy.quirks import CustomDevice
-import zigpy.types as t
 from zigpy.zcl.clusters.general import (
     Alarms,
     Basic,
@@ -15,8 +14,8 @@ from zigpy.zcl.clusters.general import (
 )
 from zigpy.zcl.clusters.lightlink import LightLink
 
-from . import IKEA, LightLinkCluster
-from .. import DoublingPowerConfigurationCluster, EventableCluster
+from . import IKEA, LightLinkCluster, ScenesCluster
+from .. import DoublingPowerConfigurationCluster
 from ..const import (
     ARGS,
     CLUSTER_ID,
@@ -48,21 +47,6 @@ from ..const import (
 DIAGNOSTICS_CLUSTER_ID = 0x0B05  # decimal = 2821
 
 
-class ScenesCluster(EventableCluster, Scenes):
-    """Ikea Scenes cluster."""
-
-    def __init__(self, *args, **kwargs):
-        """Init."""
-        super().__init__(*args, **kwargs)
-        self.server_commands.update(
-            {
-                0x0007: ("press", (t.int16s, t.int8s, t.int8s), False),
-                0x0008: ("hold", (t.int16s, t.int8s), False),
-                0x0009: ("release", (t.int16s,), False),
-            }
-        )
-
-
 class IkeaTradfriRemote(CustomDevice):
     """Custom device representing IKEA of Sweden TRADFRI remote control."""
 
diff --git a/zhaquirks/ikea/fivebtnremotezha.py b/zhaquirks/ikea/fivebtnremotezha.py
index 6bd02aa..f95678f 100644
--- a/zhaquirks/ikea/fivebtnremotezha.py
+++ b/zhaquirks/ikea/fivebtnremotezha.py
@@ -1,8 +1,8 @@
 """Device handler for IKEA of Sweden TRADFRI remote control."""
 from zigpy.profiles import zha
 from zigpy.quirks import CustomDevice
-import zigpy.types as t
 from zigpy.zcl.clusters.general import (
+    Alarms,
     Basic,
     Groups,
     Identify,
@@ -11,12 +11,11 @@ from zigpy.zcl.clusters.general import (
     Ota,
     PollControl,
     PowerConfiguration,
-    Scenes,
 )
+from zigpy.zcl.clusters.homeautomation import Diagnostic
 from zigpy.zcl.clusters.lightlink import LightLink
 
-from . import IKEA, LightLinkCluster
-from .. import DoublingPowerConfigurationCluster, EventableCluster
+from .. import DoublingPowerConfigurationCluster
 from ..const import (
     ARGS,
     CLUSTER_ID,
@@ -44,25 +43,11 @@ from ..const import (
     SHORT_PRESS,
     TURN_ON,
 )
+from . import IKEA, LightLinkCluster, ScenesCluster
 
 IKEA_CLUSTER_ID = 0xFC7C  # decimal = 64636
 
 
-class ScenesCluster(EventableCluster, Scenes):
-    """Ikea Scenes cluster."""
-
-    def __init__(self, *args, **kwargs):
-        """Init."""
-        super().__init__(*args, **kwargs)
-        self.server_commands.update(
-            {
-                0x0007: ("press", (t.int16s, t.int8s, t.int8s), False),
-                0x0008: ("hold", (t.int16s, t.int8s), False),
-                0x0009: ("release", (t.int16s,), False),
-            }
-        )
-
-
 class IkeaTradfriRemote(CustomDevice):
     """Custom device representing IKEA of Sweden TRADFRI remote control."""
 
@@ -183,3 +168,62 @@ class IkeaTradfriRemote(CustomDevice):
             ARGS: [3328, 0],
         },
     }
+
+
+class IkeaTradfriRemote2(IkeaTradfriRemote):
+    """Custom device representing IKEA of Sweden TRADFRI 5 button remote control."""
+
+    signature = {
+        # <SimpleDescriptor endpoint = 1 profile = 260 device_type = 2064
+        # device_version = 2 input_clusters = [0, 1, 3, 9, 2821, 4096]
+        # output_clusters = [3, 4, 5, 6, 8, 25, 4096]
+        MODELS_INFO: [(IKEA, "TRADFRI remote control")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.COLOR_SCENE_CONTROLLER,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    Alarms.cluster_id,
+                    Diagnostic.cluster_id,
+                    LightLink.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    ScenesCluster.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Ota.cluster_id,
+                    LightLink.cluster_id,
+                ],
+            }
+        },
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.COLOR_SCENE_CONTROLLER,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    DoublingPowerConfigurationCluster,
+                    Identify.cluster_id,
+                    Alarms.cluster_id,
+                    LightLinkCluster,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    ScenesCluster,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Ota.cluster_id,
+                    LightLink.cluster_id,
+                ],
+            }
+        }
+    }
diff --git a/zhaquirks/ikea/motionzha.py b/zhaquirks/ikea/motionzha.py
index 7ebd33e..6122c38 100644
--- a/zhaquirks/ikea/motionzha.py
+++ b/zhaquirks/ikea/motionzha.py
@@ -1,6 +1,6 @@
 """Device handler for IKEA of Sweden TRADFRI remote control."""
 from zigpy.profiles import zha
-from zigpy.quirks import CustomCluster, CustomDevice
+from zigpy.quirks import CustomDevice
 from zigpy.zcl.clusters.general import (
     Alarms,
     Basic,
@@ -29,20 +29,6 @@ IKEA_CLUSTER_ID = 0xFC7C  # decimal = 64636
 DIAGNOSTICS_CLUSTER_ID = 0x0B05  # decimal = 2821
 
 
-class LightLinkClusterNew(CustomCluster, LightLink):
-    """Ikea LightLink cluster."""
-
-    async def bind(self):
-        """Bind LightLink cluster to coordinator."""
-        application = self._endpoint.device.application
-        try:
-            coordinator = application.get_device(application.ieee)
-        except KeyError:
-            return
-        status = await coordinator.add_to_group(0x0000)
-        return [status]
-
-
 class IkeaTradfriMotion(CustomDevice):
     """Custom device representing IKEA of Sweden TRADFRI remote control."""
 
@@ -145,7 +131,7 @@ class IkeaTradfriMotionE1745(CustomDevice):
                     Identify.cluster_id,
                     Alarms.cluster_id,
                     PollControl.cluster_id,
-                    LightLinkClusterNew,
+                    LightLinkCluster,
                     IKEA_CLUSTER_ID,
                 ],
                 OUTPUT_CLUSTERS: [
diff --git a/zhaquirks/ikea/opencloseremote.py b/zhaquirks/ikea/opencloseremote.py
new file mode 100644
index 0000000..9a6495c
--- /dev/null
+++ b/zhaquirks/ikea/opencloseremote.py
@@ -0,0 +1,89 @@
+"""Device handler for IKEA of Sweden TRADFRI remote control."""
+from zigpy.profiles import zha
+from zigpy.quirks import CustomDevice
+from zigpy.zcl.clusters.closures import WindowCovering
+from zigpy.zcl.clusters.general import (
+    Alarms,
+    Basic,
+    Groups,
+    Identify,
+    LevelControl,
+    OnOff,
+    Ota,
+    PollControl,
+    PowerConfiguration,
+)
+from zigpy.zcl.clusters.lightlink import LightLink
+
+from . import IKEA
+from .. import DoublingPowerConfigurationCluster
+from ..const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+)
+
+IKEA_CLUSTER_ID = 0xFC7C  # decimal = 64636
+
+
+class IkeaTradfriOpenCloseRemote(CustomDevice):
+    """Custom device representing IKEA of Sweden TRADFRI remote control."""
+
+    signature = {
+        MODELS_INFO: [("\x02KE", "TRADFRI open/close remote")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_CONTROLLER,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    Alarms.cluster_id,
+                    PollControl.cluster_id,
+                    LightLink.cluster_id,
+                    IKEA_CLUSTER_ID,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Ota.cluster_id,
+                    WindowCovering.cluster_id,
+                    LightLink.cluster_id,
+                ],
+            }
+        },
+    }
+
+    replacement = {
+        MODELS_INFO: [(IKEA, "TRADFRI open/close remote")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_CONTROLLER,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    DoublingPowerConfigurationCluster,
+                    Identify.cluster_id,
+                    Alarms.cluster_id,
+                    PollControl.cluster_id,
+                    LightLink.cluster_id,
+                    IKEA_CLUSTER_ID,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Ota.cluster_id,
+                    WindowCovering.cluster_id,
+                    LightLink.cluster_id,
+                ],
+            }
+        },
+    }
diff --git a/zhaquirks/ikea/twobtnremote.py b/zhaquirks/ikea/twobtnremote.py
index eaa4ad0..acd9e4a 100644
--- a/zhaquirks/ikea/twobtnremote.py
+++ b/zhaquirks/ikea/twobtnremote.py
@@ -1,6 +1,6 @@
 """Device handler for IKEA of Sweden TRADFRI remote control."""
 from zigpy.profiles import zha, zll
-from zigpy.quirks import CustomCluster, CustomDevice
+from zigpy.quirks import CustomDevice
 from zigpy.zcl.clusters.closures import WindowCovering
 from zigpy.zcl.clusters.general import (
     Alarms,
@@ -15,7 +15,7 @@ from zigpy.zcl.clusters.general import (
 )
 from zigpy.zcl.clusters.lightlink import LightLink
 
-from . import IKEA
+from . import IKEA, LightLinkCluster
 from .. import DoublingPowerConfigurationCluster
 from ..const import (
     ARGS,
@@ -43,20 +43,6 @@ from ..const import (
 IKEA_CLUSTER_ID = 0xFC7C  # decimal = 64636
 
 
-class LightLinkCluster(CustomCluster, LightLink):
-    """Ikea LightLink cluster."""
-
-    async def bind(self):
-        """Bind LightLink cluster to coordinator."""
-        application = self._endpoint.device.application
-        try:
-            coordinator = application.get_device(application.ieee)
-        except KeyError:
-            return
-        status = await coordinator.add_to_group(0x0000)
-        return [status]
-
-
 class IkeaTradfriRemote2Btn(CustomDevice):
     """Custom device representing IKEA of Sweden TRADFRI remote control."""
 
diff --git a/zhaquirks/keenhome/sv02612mp13.py b/zhaquirks/keenhome/sv02612mp13.py
index f0d16d9..f892d8b 100644
--- a/zhaquirks/keenhome/sv02612mp13.py
+++ b/zhaquirks/keenhome/sv02612mp13.py
@@ -37,7 +37,18 @@ class KeenHomeSmartVent(CustomDevice):
         # input_clusters=[
         #   0, 1, 3, 4, 5, 6, 8, 32, 1026, 1027, 2821, 64513, 64514]
         # output_clusters=[25]>
-        MODELS_INFO: [("Keen Home Inc", "SV02-612-MP-1.3")],
+        MODELS_INFO: [
+            ("Keen Home Inc", "SV01-410-MP-1.0"),
+            ("Keen Home Inc", "SV01-410-MP-1.1"),
+            ("Keen Home Inc", "SV01-410-MP-1.4"),
+            ("Keen Home Inc", "SV01-410-MP-1.5"),
+            ("Keen Home Inc", "SV02-410-MP-1.3"),
+            ("Keen Home Inc", "SV01-412-MP-1.0"),
+            ("Keen Home Inc", "SV01-610-MP-1.0"),
+            ("Keen Home Inc", "SV02-610-MP-1.3"),
+            ("Keen Home Inc", "SV01-612-MP-1.0"),
+            ("Keen Home Inc", "SV02-612-MP-1.3"),
+        ],
         ENDPOINTS: {
             1: {
                 PROFILE_ID: zha.PROFILE_ID,
diff --git a/zhaquirks/konke/magnet.py b/zhaquirks/konke/magnet.py
new file mode 100644
index 0000000..e96134e
--- /dev/null
+++ b/zhaquirks/konke/magnet.py
@@ -0,0 +1,62 @@
+"""Konke magnet sensor."""
+
+from zigpy.profiles import zha
+from zigpy.quirks import CustomDevice
+from zigpy.zcl.clusters.security import IasZone
+from zigpy.zcl.clusters.general import Basic, Identify, PowerConfiguration
+
+from . import KONKE
+from .. import PowerConfigurationCluster
+from ..const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+)
+
+KONKE_CLUSTER_ID = 0xFCC0
+
+
+class KonkeMagnet(CustomDevice):
+    """Custom device representing konke magnet sensors."""
+
+    signature = {
+        #  <SimpleDescriptor endpoint=1 profile=260 device_type=1026
+        # device_version=0
+        # input_clusters=[0, 1, 3, 1280, 64704]
+        # output_clusters=[3, 64704]>
+        MODELS_INFO: [(KONKE, "3AFE270104020015")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    IasZone.cluster_id,
+                    KONKE_CLUSTER_ID,
+                ],
+                OUTPUT_CLUSTERS: [Identify.cluster_id, KONKE_CLUSTER_ID],
+            }
+        },
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfigurationCluster,
+                    Identify.cluster_id,
+                    IasZone.cluster_id,
+                    KONKE_CLUSTER_ID,
+                ],
+                OUTPUT_CLUSTERS: [Identify.cluster_id, KONKE_CLUSTER_ID],
+            }
+        }
+    }
diff --git a/zhaquirks/konke/motion.py b/zhaquirks/konke/motion.py
index c74638f..04d5141 100644
--- a/zhaquirks/konke/motion.py
+++ b/zhaquirks/konke/motion.py
@@ -6,7 +6,7 @@ from zigpy.zcl.clusters.general import Basic, Identify, PowerConfiguration
 from zigpy.zcl.clusters.security import IasZone
 
 from . import KONKE, MotionCluster, OccupancyCluster
-from .. import Bus
+from .. import Bus, PowerConfigurationCluster
 from ..const import (
     DEVICE_TYPE,
     ENDPOINTS,
@@ -58,7 +58,7 @@ class KonkeMotion(CustomDevice):
             1: {
                 INPUT_CLUSTERS: [
                     Basic.cluster_id,
-                    PowerConfiguration.cluster_id,
+                    PowerConfigurationCluster,
                     Identify.cluster_id,
                     OccupancyCluster,
                     MotionCluster,
@@ -68,3 +68,52 @@ class KonkeMotion(CustomDevice):
             }
         }
     }
+
+
+class KonkeMotionB(CustomDevice):
+    """Custom device representing konke motion sensors."""
+
+    def __init__(self, *args, **kwargs):
+        """Init."""
+        self.occupancy_bus = Bus()
+        super().__init__(*args, **kwargs)
+
+    signature = {
+        #  <SimpleDescriptor endpoint=1 profile=260 device_type=1026
+        #  device_version=0
+        #  input_clusters=[0, 1, 3, 1280]
+        #  output_clusters=[3]>
+        MODELS_INFO: [
+            (KONKE, "3AFE28010402000D"),
+            (KONKE, "3AFE14010402000D"),
+            (KONKE, "3AFE27010402000D"),
+        ],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    IasZone.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [Identify.cluster_id],
+            }
+        },
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            1: {
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfigurationCluster,
+                    Identify.cluster_id,
+                    OccupancyCluster,
+                    MotionCluster,
+                ],
+                OUTPUT_CLUSTERS: [Identify.cluster_id],
+            }
+        }
+    }
diff --git a/zhaquirks/konke/temp.py b/zhaquirks/konke/temp.py
new file mode 100644
index 0000000..986c56d
--- /dev/null
+++ b/zhaquirks/konke/temp.py
@@ -0,0 +1,60 @@
+"""Konke temp and humidity sensor."""
+
+from zigpy.profiles import zha
+from zigpy.quirks import CustomDevice
+from zigpy.zcl.clusters.general import Basic, Identify, PowerConfiguration
+from zigpy.zcl.clusters.measurement import RelativeHumidity, TemperatureMeasurement
+
+from . import KONKE
+from .. import PowerConfigurationCluster
+from ..const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+)
+
+
+class KonkeTempHumidity(CustomDevice):
+    """Custom device representing konke temp and humidity sensors."""
+
+    signature = {
+        #  <SimpleDescriptor endpoint=1 profile=260 device_type=770
+        # device_version=0
+        # input_clusters=[0, 1, 3, 1026, 1029]
+        # output_clusters=[3]>
+        MODELS_INFO: [(KONKE, "3AFE140103020000"), (KONKE, "3AFE220103020000")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    TemperatureMeasurement.cluster_id,
+                    RelativeHumidity.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [Identify.cluster_id],
+            }
+        },
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfigurationCluster,
+                    Identify.cluster_id,
+                    TemperatureMeasurement.cluster_id,
+                    RelativeHumidity.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [Identify.cluster_id],
+            }
+        }
+    }
diff --git a/zhaquirks/legrand/__init__.py b/zhaquirks/legrand/__init__.py
new file mode 100644
index 0000000..c5c4742
--- /dev/null
+++ b/zhaquirks/legrand/__init__.py
@@ -0,0 +1,2 @@
+"""Module for Legrand devices."""
+LEGRAND = "Legrand"
diff --git a/zhaquirks/legrand/dimmer.py b/zhaquirks/legrand/dimmer.py
new file mode 100644
index 0000000..4268399
--- /dev/null
+++ b/zhaquirks/legrand/dimmer.py
@@ -0,0 +1,134 @@
+"""Device handler for Legrand Dimmer switch w/o neutral."""
+from zigpy.profiles import zha
+from zigpy.quirks import CustomCluster, CustomDevice
+import zigpy.types as t
+from zigpy.zcl.clusters.general import (
+    Basic,
+    BinaryInput,
+    Groups,
+    Identify,
+    LevelControl,
+    OnOff,
+    Ota,
+    Scenes,
+)
+from zigpy.zcl.clusters.manufacturer_specific import ManufacturerSpecificCluster
+
+from . import LEGRAND
+from ..const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+)
+
+MANUFACTURER_SPECIFIC_CLUSTER_ID = 0xFC01  # decimal = 64513
+
+
+class LegrandCluster(CustomCluster, ManufacturerSpecificCluster):
+    """LegrandCluster."""
+
+    cluster_id = MANUFACTURER_SPECIFIC_CLUSTER_ID
+    name = "LegrandCluster"
+    ep_attribute = "legrand_cluster"
+    attributes = {
+        0x0000: ("dimmer", t.data16),
+        0x0001: ("led_dark", t.Bool),
+        0x0002: ("led_on", t.Bool),
+    }
+    server_commands = {}
+    client_commands = {}
+
+
+class DimmerWithoutNeutral(CustomDevice):
+    """Dimmer switch w/o neutral."""
+
+    signature = {
+        #  <SimpleDescriptor endpoint=1 profile=260 device_type=256
+        # device_version=1
+        # input_clusters=[0, 3, 4, 8, 6, 5, 15, 64513]
+        # output_clusters=[0, 64513, 25]>
+        MODELS_INFO: [(f" {LEGRAND}", " Dimmer switch w/o neutral")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Scenes.cluster_id,
+                    BinaryInput.cluster_id,
+                    MANUFACTURER_SPECIFIC_CLUSTER_ID,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    MANUFACTURER_SPECIFIC_CLUSTER_ID,
+                    Ota.cluster_id,
+                ],
+            }
+        },
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Scenes.cluster_id,
+                    BinaryInput.cluster_id,
+                    LegrandCluster,
+                ],
+                OUTPUT_CLUSTERS: [Basic.cluster_id, LegrandCluster, Ota.cluster_id],
+            }
+        }
+    }
+
+
+class DimmerWithoutNeutral2(DimmerWithoutNeutral):
+    """Dimmer switch w/o neutral 2."""
+
+    signature = {
+        #  <SimpleDescriptor endpoint=1 profile=260 device_type=256
+        # device_version=1
+        # input_clusters=[0, 3, 4, 8, 6, 5, 15, 64513]
+        # output_clusters=[0, 64513, 25]>
+        MODELS_INFO: [(f" {LEGRAND}", " Dimmer switch w/o neutral")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Scenes.cluster_id,
+                    BinaryInput.cluster_id,
+                    MANUFACTURER_SPECIFIC_CLUSTER_ID,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    MANUFACTURER_SPECIFIC_CLUSTER_ID,
+                    Ota.cluster_id,
+                ],
+            },
+            242: {
+                PROFILE_ID: 41440,
+                DEVICE_TYPE: 0x0061,
+                INPUT_CLUSTERS: [],
+                OUTPUT_CLUSTERS: [0x0021],
+            },
+        },
+    }
diff --git a/zhaquirks/osram/lightifyx4.py b/zhaquirks/osram/lightifyx4.py
index 9bf652c..dcec905 100644
--- a/zhaquirks/osram/lightifyx4.py
+++ b/zhaquirks/osram/lightifyx4.py
@@ -1,4 +1,5 @@
 """Osram Lightify X4 device."""
+import copy
 import logging
 
 from zigpy.profiles import zha
@@ -48,55 +49,71 @@ OSRAM_MFG_CODE = 0x110C
 _LOGGER = logging.getLogger(__name__)
 
 
-class LightifyX4(CustomDevice):
-    """Osram Lightify X4 device."""
+class OsramButtonCluster(CustomCluster):
+    """OsramButtonCluster."""
 
-    class OsramButtonCluster(CustomCluster):
-        """OsramButtonCluster."""
+    cluster_id = OSRAM_CLUSTER
+    name = "OsramCluster"
+    ep_attribute = "osram_cluster"
+    attributes = {
+        0x000A: ("osram_1", t.uint8_t),
+        0x000B: ("osram_2", t.uint8_t),
+        0x000C: ("osram_3", t.uint16_t),
+        0x000D: ("osram_4", t.uint16_t),
+        0x0019: ("osram_5", t.uint8_t),
+        0x001A: ("osram_6", t.uint16_t),
+        0x001B: ("osram_7", t.uint16_t),
+        0x001C: ("osram_8", t.uint8_t),
+        0x001D: ("osram_9", t.uint16_t),
+        0x001E: ("osram_10", t.uint16_t),
+        0x002C: ("osram_11", t.uint16_t),
+        0x002D: ("osram_12", t.uint16_t),
+        0x002E: ("osram_13", t.uint16_t),
+        0x002F: ("osram_14", t.uint16_t),
+    }
+    server_commands = {}
+    client_commands = {}
+    attr_config = {
+        0x000A: 0x01,
+        0x000B: 0x00,
+        0x000C: 0xFFFF,
+        0x000D: 0xFFFF,
+        0x0019: 0x06,
+        0x001A: 0x0001,
+        0x001B: 0x0026,
+        0x001C: 0x07,
+        0x001D: 0xFFFF,
+        0x001E: 0xFFFF,
+        0x002C: 0xFFFF,
+        0x002D: 0xFFFF,
+        0x002E: 0xFFFF,
+        0x002F: 0xFFFF,
+    }
 
-        cluster_id = OSRAM_CLUSTER
-        name = "OsramCluster"
-        ep_attribute = "osram_cluster"
-        attributes = {
-            0x000A: ("osram_1", t.uint8_t),
-            0x000B: ("osram_2", t.uint8_t),
-            0x000C: ("osram_3", t.uint16_t),
-            0x000D: ("osram_4", t.uint16_t),
-            0x0019: ("osram_5", t.uint8_t),
-            0x001A: ("osram_6", t.uint16_t),
-            0x001B: ("osram_7", t.uint16_t),
-            0x001C: ("osram_8", t.uint8_t),
-            0x001D: ("osram_9", t.uint16_t),
-            0x001E: ("osram_10", t.uint16_t),
-            0x002C: ("osram_11", t.uint16_t),
-            0x002D: ("osram_12", t.uint16_t),
-            0x002E: ("osram_13", t.uint16_t),
-            0x002F: ("osram_14", t.uint16_t),
-        }
-        server_commands = {}
-        client_commands = {}
-        attr_config = {
-            0x000A: 0x01,
-            0x000B: 0x00,
-            0x000C: 0xFFFF,
-            0x000D: 0xFFFF,
-            0x0019: 0x06,
-            0x001A: 0x0001,
-            0x001B: 0x0026,
-            0x001C: 0x07,
-            0x001D: 0xFFFF,
-            0x001E: 0xFFFF,
-            0x002C: 0xFFFF,
-            0x002D: 0xFFFF,
-            0x002E: 0xFFFF,
-            0x002F: 0xFFFF,
-        }
+    async def bind(self):
+        """Bind cluster."""
+        result = await super().bind()
+        await self.write_attributes(self.attr_config, manufacturer=OSRAM_MFG_CODE)
+        return result
 
-        async def bind(self):
-            """Bind cluster."""
-            result = await super().bind()
-            await self.write_attributes(self.attr_config, manufacturer=OSRAM_MFG_CODE)
-            return result
+
+class LightifyX4(CustomDevice):
+    """Osram Lightify X4 device."""
+
+    SIGNATURE_ENDPOINT = {
+        PROFILE_ID: zha.PROFILE_ID,
+        DEVICE_TYPE: OSRAM_DEVICE,
+        INPUT_CLUSTERS: [Basic.cluster_id, LightLink.cluster_id, OSRAM_CLUSTER],
+        OUTPUT_CLUSTERS: [
+            Groups.cluster_id,
+            Identify.cluster_id,
+            Scenes.cluster_id,
+            OnOff.cluster_id,
+            Color.cluster_id,
+            LevelControl.cluster_id,
+            LightLink.cluster_id,
+        ],
+    }
 
     signature = {
         #  <SimpleDescriptor endpoint=1 profile=260 device_type=2064
@@ -130,95 +147,45 @@ class LightifyX4(CustomDevice):
             # device_version=2
             # input_clusters=[0, 4096, 64768]
             # output_clusters=[3, 4, 5, 6, 8, 768, 4096]>
-            2: {
-                PROFILE_ID: zha.PROFILE_ID,
-                DEVICE_TYPE: OSRAM_DEVICE,
-                INPUT_CLUSTERS: [Basic.cluster_id, LightLink.cluster_id, OSRAM_CLUSTER],
-                OUTPUT_CLUSTERS: [
-                    Groups.cluster_id,
-                    Identify.cluster_id,
-                    Scenes.cluster_id,
-                    OnOff.cluster_id,
-                    Color.cluster_id,
-                    LevelControl.cluster_id,
-                    LightLink.cluster_id,
-                ],
-            },
+            2: copy.deepcopy(SIGNATURE_ENDPOINT),
             # <SimpleDescriptor endpoint=3 profile=260 device_type=2064
             # device_version=2
             # input_clusters=[0, 4096, 64768]
             # output_clusters=[3, 4, 5, 6, 8, 768, 4096]>
-            3: {
-                PROFILE_ID: zha.PROFILE_ID,
-                DEVICE_TYPE: OSRAM_DEVICE,
-                INPUT_CLUSTERS: [Basic.cluster_id, LightLink.cluster_id, OSRAM_CLUSTER],
-                OUTPUT_CLUSTERS: [
-                    Groups.cluster_id,
-                    Identify.cluster_id,
-                    Scenes.cluster_id,
-                    OnOff.cluster_id,
-                    Color.cluster_id,
-                    LevelControl.cluster_id,
-                    LightLink.cluster_id,
-                ],
-            },
+            3: copy.deepcopy(SIGNATURE_ENDPOINT),
             # <SimpleDescriptor endpoint=4 profile=260 device_type=2064
             # device_version=2
             # input_clusters=[0, 4096, 64768]
             # output_clusters=[3, 4, 5, 6, 8, 768, 4096]>
-            4: {
-                PROFILE_ID: zha.PROFILE_ID,
-                DEVICE_TYPE: OSRAM_DEVICE,
-                INPUT_CLUSTERS: [Basic.cluster_id, LightLink.cluster_id, OSRAM_CLUSTER],
-                OUTPUT_CLUSTERS: [
-                    Groups.cluster_id,
-                    Identify.cluster_id,
-                    Scenes.cluster_id,
-                    OnOff.cluster_id,
-                    Color.cluster_id,
-                    LevelControl.cluster_id,
-                    LightLink.cluster_id,
-                ],
-            },
+            4: copy.deepcopy(SIGNATURE_ENDPOINT),
             # <SimpleDescriptor endpoint=5 profile=260 device_type=2064
             # device_version=2
             # input_clusters=[0, 4096, 64768]
             # output_clusters=[3, 4, 5, 6, 8, 768, 4096]>
-            5: {
-                PROFILE_ID: zha.PROFILE_ID,
-                DEVICE_TYPE: OSRAM_DEVICE,
-                INPUT_CLUSTERS: [Basic.cluster_id, LightLink.cluster_id, OSRAM_CLUSTER],
-                OUTPUT_CLUSTERS: [
-                    Groups.cluster_id,
-                    Identify.cluster_id,
-                    Scenes.cluster_id,
-                    OnOff.cluster_id,
-                    Color.cluster_id,
-                    LevelControl.cluster_id,
-                    LightLink.cluster_id,
-                ],
-            },
+            5: copy.deepcopy(SIGNATURE_ENDPOINT),
             # <SimpleDescriptor endpoint=6 profile=260 device_type=2064
             # device_version=2
             # input_clusters=[0, 4096, 64768]
             # output_clusters=[3, 4, 5, 6, 8, 768, 4096]>
-            6: {
-                PROFILE_ID: zha.PROFILE_ID,
-                DEVICE_TYPE: OSRAM_DEVICE,
-                INPUT_CLUSTERS: [Basic.cluster_id, LightLink.cluster_id, OSRAM_CLUSTER],
-                OUTPUT_CLUSTERS: [
-                    Groups.cluster_id,
-                    Identify.cluster_id,
-                    Scenes.cluster_id,
-                    OnOff.cluster_id,
-                    Color.cluster_id,
-                    LevelControl.cluster_id,
-                    LightLink.cluster_id,
-                ],
-            },
+            6: copy.deepcopy(SIGNATURE_ENDPOINT),
         },
     }
 
+    REPLACEMENT_ENDPOINT = {
+        PROFILE_ID: zha.PROFILE_ID,
+        DEVICE_TYPE: OSRAM_DEVICE,
+        INPUT_CLUSTERS: [Basic.cluster_id, LightLink.cluster_id, OsramButtonCluster],
+        OUTPUT_CLUSTERS: [
+            Groups.cluster_id,
+            Identify.cluster_id,
+            Scenes.cluster_id,
+            OnOff.cluster_id,
+            Color.cluster_id,
+            LevelControl.cluster_id,
+            LightLink.cluster_id,
+        ],
+    }
+
     replacement = {
         ENDPOINTS: {
             1: {
@@ -242,88 +209,11 @@ class LightifyX4(CustomDevice):
                     LightLink.cluster_id,
                 ],
             },
-            2: {
-                PROFILE_ID: zha.PROFILE_ID,
-                DEVICE_TYPE: OSRAM_DEVICE,
-                INPUT_CLUSTERS: [
-                    Basic.cluster_id,
-                    LightLink.cluster_id,
-                    OsramButtonCluster,
-                ],
-                OUTPUT_CLUSTERS: [
-                    Groups.cluster_id,
-                    Identify.cluster_id,
-                    Scenes.cluster_id,
-                    OnOff.cluster_id,
-                    Color.cluster_id,
-                    LevelControl.cluster_id,
-                    LightLink.cluster_id,
-                ],
-            },
-            3: {
-                PROFILE_ID: zha.PROFILE_ID,
-                DEVICE_TYPE: OSRAM_DEVICE,
-                INPUT_CLUSTERS: [
-                    Basic.cluster_id,
-                    LightLink.cluster_id,
-                    OsramButtonCluster,
-                ],
-                OUTPUT_CLUSTERS: [
-                    Groups.cluster_id,
-                    Identify.cluster_id,
-                    Scenes.cluster_id,
-                    OnOff.cluster_id,
-                    Color.cluster_id,
-                    LevelControl.cluster_id,
-                    LightLink.cluster_id,
-                ],
-            },
-            4: {
-                PROFILE_ID: zha.PROFILE_ID,
-                DEVICE_TYPE: OSRAM_DEVICE,
-                INPUT_CLUSTERS: [
-                    Basic.cluster_id,
-                    LightLink.cluster_id,
-                    OsramButtonCluster,
-                ],
-                OUTPUT_CLUSTERS: [
-                    Groups.cluster_id,
-                    Identify.cluster_id,
-                    Scenes.cluster_id,
-                    OnOff.cluster_id,
-                    Color.cluster_id,
-                    LevelControl.cluster_id,
-                    LightLink.cluster_id,
-                ],
-            },
-            5: {
-                PROFILE_ID: zha.PROFILE_ID,
-                DEVICE_TYPE: OSRAM_DEVICE,
-                INPUT_CLUSTERS: [Basic.cluster_id, LightLink.cluster_id, OSRAM_CLUSTER],
-                OUTPUT_CLUSTERS: [
-                    Groups.cluster_id,
-                    Identify.cluster_id,
-                    Scenes.cluster_id,
-                    OnOff.cluster_id,
-                    Color.cluster_id,
-                    LevelControl.cluster_id,
-                    LightLink.cluster_id,
-                ],
-            },
-            6: {
-                PROFILE_ID: zha.PROFILE_ID,
-                DEVICE_TYPE: OSRAM_DEVICE,
-                INPUT_CLUSTERS: [Basic.cluster_id, LightLink.cluster_id, OSRAM_CLUSTER],
-                OUTPUT_CLUSTERS: [
-                    Groups.cluster_id,
-                    Identify.cluster_id,
-                    Scenes.cluster_id,
-                    OnOff.cluster_id,
-                    Color.cluster_id,
-                    LevelControl.cluster_id,
-                    LightLink.cluster_id,
-                ],
-            },
+            2: copy.deepcopy(REPLACEMENT_ENDPOINT),
+            3: copy.deepcopy(REPLACEMENT_ENDPOINT),
+            4: copy.deepcopy(REPLACEMENT_ENDPOINT),
+            5: copy.deepcopy(REPLACEMENT_ENDPOINT),
+            6: copy.deepcopy(REPLACEMENT_ENDPOINT),
         }
     }
 
@@ -341,3 +231,86 @@ class LightifyX4(CustomDevice):
         (LONG_RELEASE, BUTTON_3): {COMMAND: COMMAND_STOP, ENDPOINT_ID: 3},
         (LONG_RELEASE, BUTTON_4): {COMMAND: COMMAND_STOP, ENDPOINT_ID: 4},
     }
+
+
+class LightifySwitch(CustomDevice):
+    """Osram Lightify Switch device."""
+
+    SIGNATURE_ENDPOINT = {
+        PROFILE_ID: zha.PROFILE_ID,
+        DEVICE_TYPE: OSRAM_DEVICE,
+        INPUT_CLUSTERS: [LightLink.cluster_id, OSRAM_CLUSTER],
+        OUTPUT_CLUSTERS: [
+            Groups.cluster_id,
+            Identify.cluster_id,
+            Scenes.cluster_id,
+            OnOff.cluster_id,
+            Color.cluster_id,
+            LevelControl.cluster_id,
+            LightLink.cluster_id,
+        ],
+    }
+
+    signature = {
+        #  <SimpleDescriptor endpoint=1 profile=260 device_type=2064
+        #  device_version=2
+        #  input_clusters=[0, 1, 32, 4096, 64768]
+        #  output_clusters=[3, 4, 5, 6, 8, 25, 768, 4096]>
+        MODELS_INFO: [(OSRAM, "Switch-LIGHTIFY")],
+        ENDPOINTS: {
+            1: copy.deepcopy(LightifyX4.signature[ENDPOINTS][1]),
+            # <SimpleDescriptor endpoint=2 profile=260 device_type=2064
+            # device_version=2
+            # input_clusters=[4096, 64768]
+            # output_clusters=[3, 4, 5, 6, 8, 768, 4096]>
+            2: copy.deepcopy(SIGNATURE_ENDPOINT),
+            # <SimpleDescriptor endpoint=3 profile=260 device_type=2064
+            # device_version=2
+            # input_clusters=[4096, 64768]
+            # output_clusters=[3, 4, 5, 6, 8, 768, 4096]>
+            3: copy.deepcopy(SIGNATURE_ENDPOINT),
+            # <SimpleDescriptor endpoint=4 profile=260 device_type=2064
+            # device_version=2
+            # input_clusters=[4096, 64768]
+            # output_clusters=[3, 4, 5, 6, 8, 768, 4096]>
+            4: copy.deepcopy(SIGNATURE_ENDPOINT),
+            # <SimpleDescriptor endpoint=5 profile=260 device_type=2064
+            # device_version=2
+            # input_clusters=[4096, 64768]
+            # output_clusters=[3, 4, 5, 6, 8, 768, 4096]>
+            5: copy.deepcopy(SIGNATURE_ENDPOINT),
+            # <SimpleDescriptor endpoint=6 profile=260 device_type=2064
+            # device_version=2
+            # input_clusters=[4096, 64768]
+            # output_clusters=[3, 4, 5, 6, 8, 768, 4096]>
+            6: copy.deepcopy(SIGNATURE_ENDPOINT),
+        },
+    }
+
+    REPLACEMENT_ENDPOINT = {
+        PROFILE_ID: zha.PROFILE_ID,
+        DEVICE_TYPE: OSRAM_DEVICE,
+        INPUT_CLUSTERS: [LightLink.cluster_id, OsramButtonCluster],
+        OUTPUT_CLUSTERS: [
+            Groups.cluster_id,
+            Identify.cluster_id,
+            Scenes.cluster_id,
+            OnOff.cluster_id,
+            Color.cluster_id,
+            LevelControl.cluster_id,
+            LightLink.cluster_id,
+        ],
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            1: copy.deepcopy(LightifyX4.replacement[ENDPOINTS][1]),
+            2: copy.deepcopy(REPLACEMENT_ENDPOINT),
+            3: copy.deepcopy(REPLACEMENT_ENDPOINT),
+            4: copy.deepcopy(REPLACEMENT_ENDPOINT),
+            5: copy.deepcopy(REPLACEMENT_ENDPOINT),
+            6: copy.deepcopy(REPLACEMENT_ENDPOINT),
+        }
+    }
+
+    device_automation_triggers = copy.deepcopy(LightifyX4.device_automation_triggers)
diff --git a/zhaquirks/philips/__init__.py b/zhaquirks/philips/__init__.py
index 3210b3d..7f364f4 100644
--- a/zhaquirks/philips/__init__.py
+++ b/zhaquirks/philips/__init__.py
@@ -1,1 +1,115 @@
-"""Module for Phillips quirks implementations."""
+"""Module for Philips quirks implementations."""
+import logging
+
+from zigpy.quirks import CustomCluster
+import zigpy.types as t
+from zigpy.zcl.clusters.general import Basic, OnOff
+
+from ..const import (
+    ARGS,
+    BUTTON,
+    COMMAND,
+    COMMAND_ID,
+    DIM_DOWN,
+    DIM_UP,
+    LONG_PRESS,
+    LONG_RELEASE,
+    PRESS_TYPE,
+    SHORT_PRESS,
+    SHORT_RELEASE,
+    TURN_OFF,
+    TURN_ON,
+    ZHA_SEND_EVENT,
+)
+
+DIAGNOSTICS_CLUSTER_ID = 0x0B05  # decimal = 2821
+PHILIPS = "Philips"
+_LOGGER = logging.getLogger(__name__)
+
+HUE_REMOTE_DEVICE_TRIGGERS = {
+    (SHORT_PRESS, TURN_ON): {COMMAND: "on_press"},
+    (SHORT_PRESS, TURN_OFF): {COMMAND: "off_press"},
+    (SHORT_PRESS, DIM_UP): {COMMAND: "up_press"},
+    (SHORT_PRESS, DIM_DOWN): {COMMAND: "down_press"},
+    (LONG_PRESS, TURN_ON): {COMMAND: "on_hold"},
+    (LONG_PRESS, TURN_OFF): {COMMAND: "off_hold"},
+    (LONG_PRESS, DIM_UP): {COMMAND: "up_hold"},
+    (LONG_PRESS, DIM_DOWN): {COMMAND: "down_hold"},
+    (SHORT_RELEASE, TURN_ON): {COMMAND: "on_short_release"},
+    (SHORT_RELEASE, TURN_OFF): {COMMAND: "off_short_release"},
+    (SHORT_RELEASE, DIM_UP): {COMMAND: "up_short_release"},
+    (SHORT_RELEASE, DIM_DOWN): {COMMAND: "down_short_release"},
+    (LONG_RELEASE, TURN_ON): {COMMAND: "on_long_release"},
+    (LONG_RELEASE, TURN_OFF): {COMMAND: "off_long_release"},
+    (LONG_RELEASE, DIM_UP): {COMMAND: "up_long_release"},
+    (LONG_RELEASE, DIM_DOWN): {COMMAND: "down_long_release"},
+}
+
+
+class PowerOnState(t.enum8):
+    """Philips power on state enum."""
+
+    Off = 0x00
+    On = 0x01
+    LastState = 0xFF
+
+
+class PhilipsOnOffCluster(CustomCluster, OnOff):
+    """Philips OnOff cluster."""
+
+    attributes = OnOff.attributes.copy()
+    attributes.update({0x4003: ("power_on_state", PowerOnState)})
+
+
+class PhilipsBasicCluster(CustomCluster, Basic):
+    """Philips Basic cluster."""
+
+    attributes = Basic.attributes.copy()
+    attributes.update({0x0031: ("philips", t.bitmap16)})
+
+    attr_config = {0x0031: 0x000B}
+
+    async def bind(self):
+        """Bind cluster."""
+        result = await super().bind()
+        await self.write_attributes(self.attr_config, manufacturer=0x100B)
+        return result
+
+
+class PhilipsRemoteCluster(CustomCluster):
+    """Philips remote cluster."""
+
+    cluster_id = 64512
+    name = "PhilipsRemoteCluster"
+    ep_attribute = "philips_remote_cluster"
+    attributes = {}
+    server_commands = {}
+    client_commands = {
+        0x0000: (
+            "notification",
+            (t.uint8_t, t.uint24_t, t.uint8_t, t.uint8_t, t.uint8_t, t.uint8_t),
+            False,
+        )
+    }
+    BUTTONS = {1: "on", 2: "up", 3: "down", 4: "off"}
+    PRESS_TYPES = {0: "press", 1: "hold", 2: "short_release", 3: "long_release"}
+
+    def handle_cluster_request(self, tsn, command_id, args):
+        """Handle the cluster command."""
+        _LOGGER.debug(
+            "PhilipsRemoteCluster - handle_cluster_request tsn: [%s] command id: %s - args: [%s]",
+            tsn,
+            command_id,
+            args,
+        )
+        button = self.BUTTONS.get(args[0], args[0])
+        press_type = self.PRESS_TYPES.get(args[2], args[2])
+
+        event_args = {
+            BUTTON: button,
+            PRESS_TYPE: press_type,
+            COMMAND_ID: command_id,
+            ARGS: args,
+        }
+        action = "{}_{}".format(button, press_type)
+        self.listener_event(ZHA_SEND_EVENT, action, event_args)
diff --git a/zhaquirks/philips/lca003.py b/zhaquirks/philips/lca003.py
new file mode 100644
index 0000000..f027c1a
--- /dev/null
+++ b/zhaquirks/philips/lca003.py
@@ -0,0 +1,95 @@
+"""Quirk for Phillips LCA003."""
+from zigpy.profiles import zha
+from zigpy.quirks import CustomDevice
+from zigpy.zcl.clusters.general import (
+    OnOff,
+    Basic,
+    Identify,
+    LevelControl,
+    Scenes,
+    Groups,
+    Ota,
+    GreenPowerProxy,
+)
+
+from zigpy.zcl.clusters.lighting import Color
+from zigpy.zcl.clusters.lightlink import LightLink
+
+from zhaquirks.const import (
+    ENDPOINTS,
+    OUTPUT_CLUSTERS,
+    INPUT_CLUSTERS,
+    DEVICE_TYPE,
+    PROFILE_ID,
+    MODELS_INFO,
+)
+from zhaquirks.philips import PHILIPS, PhilipsOnOffCluster
+
+
+class PhilipsLCA003(CustomDevice):
+    """Philips LCA003 device."""
+
+    signature = {
+        MODELS_INFO: [(PHILIPS, "LCA003")],
+        ENDPOINTS: {
+            11: {
+                # <SimpleDescriptor endpoint=11 profile=260 device_type=269
+                # device_version=1
+                # input_clusters=[0, 3, 4, 5, 6, 8, 4096, 64514, 768, 64513]
+                # output_clusters=[25]>
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.EXTENDED_COLOR_LIGHT,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    LightLink.cluster_id,
+                    64514,
+                    Color.cluster_id,
+                    64513,
+                ],
+                OUTPUT_CLUSTERS: [Ota.cluster_id],
+            },
+            242: {
+                # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
+                # device_version=0
+                # input_clusters=[]
+                # output_clusters=[33]>
+                PROFILE_ID: 41440,
+                DEVICE_TYPE: 97,
+                INPUT_CLUSTERS: [],
+                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
+            },
+        },
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            11: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.EXTENDED_COLOR_LIGHT,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                    PhilipsOnOffCluster,
+                    LevelControl.cluster_id,
+                    LightLink.cluster_id,
+                    64514,
+                    Color.cluster_id,
+                    64513,
+                ],
+                OUTPUT_CLUSTERS: [Ota.cluster_id],
+            },
+            242: {
+                PROFILE_ID: 41440,
+                DEVICE_TYPE: 97,
+                INPUT_CLUSTERS: [],
+                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
+            },
+        }
+    }
diff --git a/zhaquirks/philips/lct016.py b/zhaquirks/philips/lct016.py
new file mode 100644
index 0000000..8905e94
--- /dev/null
+++ b/zhaquirks/philips/lct016.py
@@ -0,0 +1,94 @@
+"""Quirk for Phillips LCT016."""
+from zigpy.profiles import zll
+from zigpy.quirks import CustomDevice
+from zigpy.zcl.clusters.general import (
+    OnOff,
+    Basic,
+    Identify,
+    LevelControl,
+    Scenes,
+    Groups,
+    Ota,
+    GreenPowerProxy,
+)
+
+from zigpy.zcl.clusters.lighting import Color
+from zigpy.zcl.clusters.lightlink import LightLink
+
+from zhaquirks.const import (
+    ENDPOINTS,
+    OUTPUT_CLUSTERS,
+    INPUT_CLUSTERS,
+    DEVICE_TYPE,
+    PROFILE_ID,
+    MODELS_INFO,
+)
+from zhaquirks.philips import PHILIPS, PhilipsOnOffCluster
+
+
+class PhilipsLCT016(CustomDevice):
+    """Philips LCT016 device."""
+
+    signature = {
+        MODELS_INFO: [(PHILIPS, "LCT016")],
+        ENDPOINTS: {
+            11: {
+                # <SimpleDescriptor endpoint=11 profile=49246 device_type=528
+                # device_version=2
+                # input_clusters=[0, 3, 4, 5, 6, 8, 4096, 768, 64513]
+                # output_clusters=[25]
+                PROFILE_ID: zll.PROFILE_ID,
+                DEVICE_TYPE: zll.DeviceType.EXTENDED_COLOR_LIGHT,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    LightLink.cluster_id,
+                    Color.cluster_id,
+                    64513,
+                ],
+                OUTPUT_CLUSTERS: [Ota.cluster_id],
+            },
+            242: {
+                # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
+                # device_version=0
+                # input_clusters=[33]
+                # output_clusters=[33]
+                PROFILE_ID: 41440,
+                DEVICE_TYPE: 97,
+                INPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
+                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
+            },
+        },
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            11: {
+                PROFILE_ID: zll.PROFILE_ID,
+                DEVICE_TYPE: zll.DeviceType.EXTENDED_COLOR_LIGHT,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                    PhilipsOnOffCluster,
+                    LevelControl.cluster_id,
+                    LightLink.cluster_id,
+                    64514,
+                    Color.cluster_id,
+                    64513,
+                ],
+                OUTPUT_CLUSTERS: [Ota.cluster_id],
+            },
+            242: {
+                PROFILE_ID: 41440,
+                DEVICE_TYPE: 97,
+                INPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
+                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
+            },
+        }
+    }
diff --git a/zhaquirks/philips/rom001.py b/zhaquirks/philips/rom001.py
index d517c0c..ad34786 100644
--- a/zhaquirks/philips/rom001.py
+++ b/zhaquirks/philips/rom001.py
@@ -1,4 +1,4 @@
-"""Phillips ROM001 device."""
+"""Philips ROM001 device."""
 from zigpy.profiles import zha
 from zigpy.quirks import CustomDevice
 from zigpy.zcl.clusters.general import (
@@ -31,7 +31,7 @@ DEVICE_SPECIFIC_UNKNOWN = 64512
 
 
 class PhilipsROM001(CustomDevice):
-    """Phillips ROM001 device."""
+    """Philips ROM001 device."""
 
     signature = {
         #  <SimpleDescriptor endpoint=1 profile=260 device_type=2096
diff --git a/zhaquirks/philips/rwl020.py b/zhaquirks/philips/rwl020.py
new file mode 100644
index 0000000..9af7aec
--- /dev/null
+++ b/zhaquirks/philips/rwl020.py
@@ -0,0 +1,87 @@
+"""Philips RWL020 device."""
+
+from zigpy.profiles import zha, zll
+from zigpy.quirks import CustomDevice
+from zigpy.zcl.clusters.general import (
+    Basic,
+    BinaryInput,
+    Groups,
+    Identify,
+    LevelControl,
+    OnOff,
+    Ota,
+    PowerConfiguration,
+)
+
+from . import HUE_REMOTE_DEVICE_TRIGGERS, PhilipsBasicCluster, PhilipsRemoteCluster
+from ..const import DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, OUTPUT_CLUSTERS, PROFILE_ID
+
+DIAGNOSTICS_CLUSTER_ID = 0x0B05  # decimal = 2821
+
+
+class PhilipsRWL020(CustomDevice):
+    """Philips RWL020 device."""
+
+    signature = {
+        #  <SimpleDescriptor endpoint=1 profile=49246 device_type=2080
+        #  device_version=2
+        #  input_clusters=[0]
+        #  output_clusters=[0, 3, 4, 6, 8]>
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zll.PROFILE_ID,
+                DEVICE_TYPE: zll.DeviceType.CONTROLLER,
+                INPUT_CLUSTERS: [Basic.cluster_id],
+                OUTPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                ],
+            },
+            #  <SimpleDescriptor endpoint=2 profile=260 device_type=12
+            #  device_version=0
+            #  input_clusters=[0, 1, 3, 15, 64512]
+            #  output_clusters=[25]>
+            2: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.SIMPLE_SENSOR,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    BinaryInput.cluster_id,
+                    64512,
+                ],
+                OUTPUT_CLUSTERS: [Ota.cluster_id],
+            },
+        }
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            1: {
+                INPUT_CLUSTERS: [Basic.cluster_id],
+                OUTPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                ],
+            },
+            2: {
+                INPUT_CLUSTERS: [
+                    PhilipsBasicCluster,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    BinaryInput.cluster_id,
+                    PhilipsRemoteCluster,
+                ],
+                OUTPUT_CLUSTERS: [Ota.cluster_id],
+            },
+        }
+    }
+
+    device_automation_triggers = HUE_REMOTE_DEVICE_TRIGGERS
diff --git a/zhaquirks/philips/rwl021.py b/zhaquirks/philips/rwl021.py
index 15247ea..6c9157b 100644
--- a/zhaquirks/philips/rwl021.py
+++ b/zhaquirks/philips/rwl021.py
@@ -1,7 +1,7 @@
-"""Phillips RWL021 device."""
+"""Philips RWL021 device."""
+
 from zigpy.profiles import zha, zll
-from zigpy.quirks import CustomCluster, CustomDevice
-import zigpy.types as t
+from zigpy.quirks import CustomDevice
 from zigpy.zcl.clusters.general import (
     Basic,
     BinaryInput,
@@ -14,39 +14,14 @@ from zigpy.zcl.clusters.general import (
     Scenes,
 )
 
-from ..const import (
-    ARGS,
-    CLUSTER_ID,
-    COMMAND,
-    COMMAND_OFF_WITH_EFFECT,
-    COMMAND_ON,
-    COMMAND_STEP,
-    DEVICE_TYPE,
-    DIM_DOWN,
-    DIM_UP,
-    ENDPOINT_ID,
-    ENDPOINTS,
-    INPUT_CLUSTERS,
-    LONG_PRESS,
-    OUTPUT_CLUSTERS,
-    PROFILE_ID,
-    SHORT_PRESS,
-    TURN_OFF,
-    TURN_ON,
-)
+from . import HUE_REMOTE_DEVICE_TRIGGERS, PhilipsBasicCluster, PhilipsRemoteCluster
+from ..const import DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, OUTPUT_CLUSTERS, PROFILE_ID
 
 DIAGNOSTICS_CLUSTER_ID = 0x0B05  # decimal = 2821
 
 
-class BasicCluster(CustomCluster, Basic):
-    """Centralite acceleration cluster."""
-
-    attributes = Basic.attributes.copy()
-    attributes.update({0x0031: ("phillips", t.bitmap16)})
-
-
 class PhilipsRWL021(CustomDevice):
-    """Phillips RWL021 device."""
+    """Philips RWL021 device."""
 
     signature = {
         #  <SimpleDescriptor endpoint=1 profile=49246 device_type=2096
@@ -101,42 +76,15 @@ class PhilipsRWL021(CustomDevice):
             },
             2: {
                 INPUT_CLUSTERS: [
-                    BasicCluster,
+                    PhilipsBasicCluster,
                     PowerConfiguration.cluster_id,
                     Identify.cluster_id,
                     BinaryInput.cluster_id,
-                    64512,
+                    PhilipsRemoteCluster,
                 ],
                 OUTPUT_CLUSTERS: [Ota.cluster_id],
             },
         }
     }
 
-    device_automation_triggers = {
-        (SHORT_PRESS, TURN_ON): {COMMAND: COMMAND_ON},
-        (LONG_PRESS, TURN_OFF): {COMMAND: COMMAND_OFF_WITH_EFFECT},
-        (SHORT_PRESS, DIM_UP): {
-            COMMAND: COMMAND_STEP,
-            CLUSTER_ID: 8,
-            ENDPOINT_ID: 1,
-            ARGS: [0, 30, 9],
-        },
-        (LONG_PRESS, DIM_UP): {
-            COMMAND: COMMAND_STEP,
-            CLUSTER_ID: 8,
-            ENDPOINT_ID: 1,
-            ARGS: [0, 56, 9],
-        },
-        (SHORT_PRESS, DIM_DOWN): {
-            COMMAND: COMMAND_STEP,
-            CLUSTER_ID: 8,
-            ENDPOINT_ID: 1,
-            ARGS: [1, 30, 9],
-        },
-        (LONG_PRESS, DIM_DOWN): {
-            COMMAND: COMMAND_STEP,
-            CLUSTER_ID: 8,
-            ENDPOINT_ID: 1,
-            ARGS: [1, 56, 9],
-        },
-    }
+    device_automation_triggers = HUE_REMOTE_DEVICE_TRIGGERS
diff --git a/zhaquirks/philips/sml002.py b/zhaquirks/philips/sml002.py
new file mode 100644
index 0000000..01d7245
--- /dev/null
+++ b/zhaquirks/philips/sml002.py
@@ -0,0 +1,115 @@
+"""Quirk for Philips SML002."""
+from zigpy.profiles import zha, zll
+from zigpy.quirks import CustomCluster, CustomDevice
+import zigpy.types as t
+from zigpy.zcl.clusters.general import (
+    Basic,
+    Groups,
+    Identify,
+    LevelControl,
+    OnOff,
+    Ota,
+    PowerConfiguration,
+    Scenes,
+)
+from zigpy.zcl.clusters.lighting import Color
+from zigpy.zcl.clusters.measurement import (
+    IlluminanceMeasurement,
+    OccupancySensing,
+    TemperatureMeasurement,
+)
+
+from . import PHILIPS
+from ..const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+)
+
+
+class OccupancyCluster(CustomCluster, OccupancySensing):
+    """philips occupancy cluster."""
+
+    attributes = OccupancySensing.attributes.copy()
+    attributes.update({0x0030: ("sensitivity", t.uint8_t)})
+    attributes.update({0x0031: ("sensitivity_max", t.uint8_t)})
+
+
+class PhilipsSML002(CustomDevice):
+    """philips SML002 device."""
+
+    signature = {
+        MODELS_INFO: [(PHILIPS, "SML002")],
+        ENDPOINTS: {
+            #  <SimpleDescriptor endpoint=1 profile=49246 device_type=0x0850
+            #  device_version=?
+            #  input_clusters=[0]
+            #  output_clusters=[0, 3, 4, 5, 6, 8, 768]>
+            1: {
+                PROFILE_ID: zll.PROFILE_ID,
+                DEVICE_TYPE: zll.DeviceType.ON_OFF_SENSOR,
+                INPUT_CLUSTERS: [Basic.cluster_id],
+                OUTPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Color.cluster_id,
+                ],
+            },
+            #  <SimpleDescriptor endpoint=2 profile=260 device_type=0x0107
+            #  device_version=?
+            #  input_clusters=[0, 1, 3, 1024, 1026, 1030]
+            #  output_clusters=[25]>
+            2: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    IlluminanceMeasurement.cluster_id,
+                    TemperatureMeasurement.cluster_id,
+                    OccupancySensing.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [Ota.cluster_id],
+            },
+        },
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zll.PROFILE_ID,
+                DEVICE_TYPE: zll.DeviceType.ON_OFF_SENSOR,
+                INPUT_CLUSTERS: [Basic.cluster_id],
+                OUTPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Color.cluster_id,
+                ],
+            },
+            2: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    IlluminanceMeasurement.cluster_id,
+                    TemperatureMeasurement.cluster_id,
+                    OccupancyCluster,
+                ],
+                OUTPUT_CLUSTERS: [Ota.cluster_id],
+            },
+        }
+    }
diff --git a/zhaquirks/plaid/__init__.py b/zhaquirks/plaid/__init__.py
new file mode 100644
index 0000000..203efe3
--- /dev/null
+++ b/zhaquirks/plaid/__init__.py
@@ -0,0 +1,2 @@
+"""Quirks for Plaid Systems devices."""
+PLAID_SYSTEMS = "PLAID SYSTEMS"
diff --git a/zhaquirks/plaid/soil.py b/zhaquirks/plaid/soil.py
new file mode 100644
index 0000000..ae0a960
--- /dev/null
+++ b/zhaquirks/plaid/soil.py
@@ -0,0 +1,90 @@
+"""PLAID SYSTEMS PS-SPRZMS-SLP3 soil moisture sensor."""
+
+from zigpy.profiles import zha
+from zigpy.quirks import CustomDevice
+from zigpy.zcl.clusters.general import Basic, Identify, Ota, PowerConfiguration
+from zigpy.zcl.clusters.measurement import RelativeHumidity, TemperatureMeasurement
+
+from . import PLAID_SYSTEMS
+from .. import PowerConfigurationCluster
+from ..const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+)
+
+
+class PowerConfigurationClusterMains(PowerConfigurationCluster):
+    """Common use power configuration cluster."""
+
+    MAINS_VOLTAGE_ATTR = 0x0000
+    ATTR_ID_BATT_SIZE = 0x0031
+    ATTR_ID_BATT_QTY = 0x0033
+    _CONSTANT_ATTRIBUTES = {ATTR_ID_BATT_SIZE: 0x08, ATTR_ID_BATT_QTY: 1}
+
+    def _update_attribute(self, attrid, value):
+        super()._update_attribute(attrid, value)
+        if attrid == self.MAINS_VOLTAGE_ATTR:
+            super()._update_attribute(self.BATTERY_VOLTAGE_ATTR, round(value / 100))
+
+    def _remap(self, attr):
+        """Replace battery voltage attribute name/id with mains_voltage."""
+        if attr in (self.BATTERY_VOLTAGE_ATTR, "battery_voltage"):
+            return self.MAINS_VOLTAGE_ATTR
+        return attr
+
+    def read_attributes(self, attributes, *args, **kwargs):  # pylint: disable=W0221
+        """Replace battery voltage with mains voltage."""
+        return super().read_attributes(
+            [self._remap(attr) for attr in attributes], *args, **kwargs
+        )
+
+    def configure_reporting(self, attribute, *args, **kwargs):  # pylint: disable=W0221
+        """Replace battery voltage with mains voltage."""
+        return super().configure_reporting(self._remap(attribute), *args, **kwargs)
+
+
+class SoilMoisture(CustomDevice):
+    """Custom device representing plaid systems soil sensors."""
+
+    signature = {
+        #  <SimpleDescriptor endpoint=1 profile=260 device_type=1029
+        # device_version=0
+        # input_clusters=[0, 1, 3, 1026, 1029]
+        # output_clusters=[3, 25]>
+        MODELS_INFO: [(PLAID_SYSTEMS, "PS-SPRZMS-SLP3")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: 1029,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    TemperatureMeasurement.cluster_id,
+                    RelativeHumidity.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [Identify.cluster_id, Ota.cluster_id],
+            }
+        },
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: 1029,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfigurationClusterMains,
+                    Identify.cluster_id,
+                    TemperatureMeasurement.cluster_id,
+                    RelativeHumidity.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [Identify.cluster_id, Ota.cluster_id],
+            }
+        }
+    }
diff --git a/zhaquirks/samjin/button.py b/zhaquirks/samjin/button.py
index a0f2183..0003700 100644
--- a/zhaquirks/samjin/button.py
+++ b/zhaquirks/samjin/button.py
@@ -58,7 +58,7 @@ class SamjinButton(CustomDevice):
                     ARGS: args,
                 }
                 action = "button_{}".format(CLICK_TYPES[state])
-                self.listener_event(ZHA_SEND_EVENT, self, action, event_args)
+                self.listener_event(ZHA_SEND_EVENT, action, event_args)
 
     signature = {
         # <SimpleDescriptor endpoint=1 profile=260 device_type=1026
diff --git a/zhaquirks/samjin/button2.py b/zhaquirks/samjin/button2.py
index 2e16040..5126b14 100644
--- a/zhaquirks/samjin/button2.py
+++ b/zhaquirks/samjin/button2.py
@@ -56,7 +56,7 @@ class SamjinButton(CustomDevice):
                     ARGS: args,
                 }
                 action = "button_{}".format(CLICK_TYPES[state])
-                self.listener_event(ZHA_SEND_EVENT, self, action, event_args)
+                self.listener_event(ZHA_SEND_EVENT, action, event_args)
 
     signature = {
         # <SimpleDescriptor endpoint=1 profile=260 device_type=1026
diff --git a/zhaquirks/smartthings/__init__.py b/zhaquirks/smartthings/__init__.py
index 66bdbee..65cf689 100644
--- a/zhaquirks/smartthings/__init__.py
+++ b/zhaquirks/smartthings/__init__.py
@@ -2,6 +2,7 @@
 
 import zigpy.types as t
 from zigpy.quirks import CustomCluster
+from zigpy.zcl.clusters.security import IasZone
 
 SMART_THINGS = "SmartThings"
 MANUFACTURER_SPECIFIC_CLUSTER_ID = 0xFC02  # decimal = 64514
@@ -24,3 +25,20 @@ class SmartThingsAccelCluster(CustomCluster):
 
     client_commands = {}
     server_commands = {}
+
+
+class SmartThingsIasZone(CustomCluster, IasZone):
+    """IasZone cluster patched to support SmartThings spec violations."""
+
+    client_commands = IasZone.client_commands.copy()
+    client_commands[0x0000] = (
+        "status_change_notification",
+        (
+            IasZone.ZoneStatus,
+            t.bitmap8,
+            # SmartThings never sends these two
+            t.Optional(t.uint8_t),
+            t.Optional(t.uint16_t),
+        ),
+        False,
+    )
diff --git a/zhaquirks/smartthings/motionv4.py b/zhaquirks/smartthings/motion.py
similarity index 92%
rename from zhaquirks/smartthings/motionv4.py
rename to zhaquirks/smartthings/motion.py
index 1337bda..edf1724 100755
--- a/zhaquirks/smartthings/motionv4.py
+++ b/zhaquirks/smartthings/motion.py
@@ -18,15 +18,15 @@ from ..const import (
 )
 
 
-class SmartThingsMotionV4(CustomDevice):
-    """SmartThingsMotionV4."""
+class SmartThingsMotion(CustomDevice):
+    """SmartThingsMotionV4 or V5."""
 
     signature = {
         #  <SimpleDescriptor endpoint=1 profile=260 device_type=1026
         #  device_version=0
         #  input_clusters=[0, 1, 3, 15, 1026, 1280, 32]
         #  output_clusters=[25]>
-        MODELS_INFO: [(SMART_THINGS, "motionv4")],
+        MODELS_INFO: [(SMART_THINGS, "motionv4"), (SMART_THINGS, "motionv5")],
         ENDPOINTS: {
             1: {
                 PROFILE_ID: zha.PROFILE_ID,
diff --git a/zhaquirks/smartthings/pgc313.py b/zhaquirks/smartthings/pgc313.py
new file mode 100755
index 0000000..863a085
--- /dev/null
+++ b/zhaquirks/smartthings/pgc313.py
@@ -0,0 +1,59 @@
+"""SmartThings SmartSense Multi Sensor quirk."""
+from zigpy.profiles import zha
+from zigpy.quirks import CustomDevice
+from zigpy.zcl.clusters.general import Basic, Ota
+
+from ..const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+)
+from . import SMART_THINGS, SmartThingsIasZone
+
+SMARTSENSE_MULTI_DEVICE_TYPE = 0x0139  # decimal = 313
+
+
+class IasZoneContactSwitchCluster(SmartThingsIasZone):
+    """Custom IasZone cluster."""
+
+    ZONE_TYPE = 0x0001
+    CONTACT_SWITCH_TYPE = 0x0015
+    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: CONTACT_SWITCH_TYPE}
+
+
+class SmartthingsSmartSenseMultiSensor(CustomDevice):
+    """Multipurpose sensor."""
+
+    signature = {
+        #  <SimpleDescriptor endpoint=1 profile=260 device_type=313
+        #  device_version=0 input_clusters=[0] output_clusters=[25]>
+        MODELS_INFO: [(SMART_THINGS, "PGC313")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: SMARTSENSE_MULTI_DEVICE_TYPE,
+                INPUT_CLUSTERS: [Basic.cluster_id],
+                OUTPUT_CLUSTERS: [Ota.cluster_id],
+            },
+            #  <SimpleDescriptor endpoint=2 profile=64513 device_type=313
+            #  device_version=0 input_clusters=[] output_clusters=[]>
+            2: {
+                PROFILE_ID: 0xFC01,  # decimal = 64513
+                DEVICE_TYPE: SMARTSENSE_MULTI_DEVICE_TYPE,
+                INPUT_CLUSTERS: [],
+                OUTPUT_CLUSTERS: [],
+            },
+        },
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            1: {
+                INPUT_CLUSTERS: [Basic.cluster_id, IasZoneContactSwitchCluster],
+                OUTPUT_CLUSTERS: [Ota.cluster_id],
+            }
+        }
+    }
diff --git a/zhaquirks/smartthings/pgc314.py b/zhaquirks/smartthings/pgc314.py
new file mode 100644
index 0000000..7c1f194
--- /dev/null
+++ b/zhaquirks/smartthings/pgc314.py
@@ -0,0 +1,59 @@
+"""SmartThings SmartSense Motion quirk."""
+from zigpy.profiles import zha
+from zigpy.quirks import CustomDevice
+from zigpy.zcl.clusters.general import Basic, Ota
+
+from ..const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+)
+from . import SMART_THINGS, SmartThingsIasZone
+
+SMARTSENSE_MOTION_DEVICE_TYPE = 0x013A  # decimal = 314
+
+
+class IasZoneMotionCluster(SmartThingsIasZone):
+    """Custom IasZone cluster."""
+
+    ZONE_TYPE = 0x0001
+    MOTION_TYPE = 0x000D
+    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: MOTION_TYPE}
+
+
+class SmartthingsSmartSenseMotionSensor(CustomDevice):
+    """SmartSense Motion Sensor."""
+
+    signature = {
+        #  <SimpleDescriptor endpoint=1 profile=260 device_type=314
+        #  device_version=0 input_clusters=[0] output_clusters=[25]>
+        MODELS_INFO: [(SMART_THINGS, "PGC314")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: SMARTSENSE_MOTION_DEVICE_TYPE,
+                INPUT_CLUSTERS: [Basic.cluster_id],
+                OUTPUT_CLUSTERS: [Ota.cluster_id],
+            },
+            #  <SimpleDescriptor endpoint=2 profile=64513 device_type=314
+            #  device_version=0 input_clusters=[] output_clusters=[]>
+            2: {
+                PROFILE_ID: 0xFC01,  # decimal = 64513
+                DEVICE_TYPE: SMARTSENSE_MOTION_DEVICE_TYPE,
+                INPUT_CLUSTERS: [],
+                OUTPUT_CLUSTERS: [],
+            },
+        },
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            1: {
+                INPUT_CLUSTERS: [Basic.cluster_id, IasZoneMotionCluster],
+                OUTPUT_CLUSTERS: [Ota.cluster_id],
+            }
+        }
+    }
diff --git a/zhaquirks/xbee/__init__.py b/zhaquirks/xbee/__init__.py
index afc0cf6..af2a5fb 100644
--- a/zhaquirks/xbee/__init__.py
+++ b/zhaquirks/xbee/__init__.py
@@ -78,18 +78,20 @@ ENDPOINT_TO_AT = {
 class XBeeOnOff(LocalDataCluster, OnOff):
     """XBee on/off cluster."""
 
-    async def command(self, command, *args, manufacturer=None, expect_reply=True):
+    async def command(
+        self, command_id, *args, manufacturer=None, expect_reply=True, tsn=None
+    ):
         """Xbee change pin state command, requires zigpy_xbee."""
         pin_name = ENDPOINT_TO_AT.get(self._endpoint.endpoint_id)
-        if command not in [0, 1] or pin_name is None:
-            return super().command(command, *args)
-        if command == 0:
+        if command_id not in [0, 1] or pin_name is None:
+            return super().command(command_id, *args)
+        if command_id == 0:
             pin_cmd = DIO_PIN_LOW
         else:
             pin_cmd = DIO_PIN_HIGH
         result = await self._endpoint.device.remote_at(pin_name, pin_cmd)
         if result == foundation.Status.SUCCESS:
-            self._update_attribute(ATTR_ON_OFF, command)
+            self._update_attribute(ATTR_ON_OFF, command_id)
         return 0, result
 
 
@@ -283,6 +285,7 @@ class XBeeCommon(CustomDevice):
         """Serial Data Cluster for the XBee."""
 
         cluster_id = XBEE_DATA_CLUSTER
+        ep_attribute = "xbee_serial_data"
 
         class BinaryString(str):
             """Class to parse and serialize binary data as string."""
@@ -297,7 +300,9 @@ class XBeeCommon(CustomDevice):
                 data = str(data, encoding="latin1")
                 return (cls(data), b"")
 
-        def command(self, command, *args, manufacturer=None, expect_reply=False):
+        def command(
+            self, command_id, *args, manufacturer=None, expect_reply=False, tsn=None
+        ):
             """Handle outgoing data."""
             data = self.BinaryString(args[0]).serialize()
             return self._endpoint.device.application.request(
diff --git a/zhaquirks/xiaomi/__init__.py b/zhaquirks/xiaomi/__init__.py
index 53d62d2..9149b91 100644
--- a/zhaquirks/xiaomi/__init__.py
+++ b/zhaquirks/xiaomi/__init__.py
@@ -2,19 +2,23 @@
 import asyncio
 import binascii
 import logging
+import math
+from typing import Optional, Union
 
+import zigpy.zcl.foundation as foundation
 from zigpy import types as t
+from zigpy.profiles import zha
 from zigpy.quirks import CustomCluster, CustomDevice
-from zigpy.zcl.clusters.general import Basic, PowerConfiguration
+from zigpy.zcl.clusters.general import AnalogInput, Basic, OnOff, PowerConfiguration
 from zigpy.zcl.clusters.homeautomation import ElectricalMeasurement
 from zigpy.zcl.clusters.measurement import (
+    IlluminanceMeasurement,
     OccupancySensing,
     PressureMeasurement,
     RelativeHumidity,
     TemperatureMeasurement,
 )
 from zigpy.zcl.clusters.security import IasZone
-import zigpy.zcl.foundation as foundation
 
 from .. import Bus, LocalDataCluster
 from ..const import (
@@ -56,6 +60,8 @@ TEMPERATURE_REPORTED = "temperature_reported"
 POWER_REPORTED = "power_reported"
 CONSUMPTION_REPORTED = "consumption_reported"
 VOLTAGE_REPORTED = "voltage_reported"
+ILLUMINANCE_MEASUREMENT = "illuminance_measurement"
+ILLUMINANCE_REPORTED = "illuminance_reported"
 XIAOMI_AQARA_ATTRIBUTE = 0xFF01
 XIAOMI_ATTR_3 = "X-attrib-3"
 XIAOMI_ATTR_4 = "X-attrib-4"
@@ -125,7 +131,7 @@ class BasicCluster(CustomCluster, Basic):
                 and self._attr_cache[MODEL] == "lumi.sensor_switch.aq2"
             ):
                 if value.raw == b"\x04!\xa8C\n!\x00\x00":
-                    self.listener_event(ZHA_SEND_EVENT, self, COMMAND_TRIPLE, [])
+                    self.listener_event(ZHA_SEND_EVENT, COMMAND_TRIPLE, [])
         elif attrid == XIAOMI_MIJA_ATTRIBUTE:
             attributes = self._parse_mija_attributes(value)
         else:
@@ -136,7 +142,6 @@ class BasicCluster(CustomCluster, Basic):
                 # pressed quickly."""
                 self.listener_event(
                     ZHA_SEND_EVENT,
-                    self,
                     COMMAND_ATTRIBUTE_UPDATED,
                     {
                         ATTRIBUTE_ID: attrid,
@@ -182,6 +187,10 @@ class BasicCluster(CustomCluster, Basic):
             self.endpoint.device.voltage_bus.listener_event(
                 VOLTAGE_REPORTED, attributes[VOLTAGE] * 0.1
             )
+        if ILLUMINANCE_MEASUREMENT in attributes:
+            self.endpoint.device.illuminance_bus.listener_event(
+                ILLUMINANCE_REPORTED, attributes[ILLUMINANCE_MEASUREMENT]
+            )
 
     def _parse_aqara_attributes(self, value):
         """Parse non standard atrributes."""
@@ -214,6 +223,11 @@ class BasicCluster(CustomCluster, Basic):
             "lumi.relay.c2acn01",
         ]:
             attribute_names.update({149: CONSUMPTION, 150: VOLTAGE, 152: POWER})
+        elif (
+            MODEL in self._attr_cache
+            and self._attr_cache[MODEL] == "lumi.sensor_motion.aq2"
+        ):
+            attribute_names.update({11: ILLUMINANCE_MEASUREMENT})
 
         result = {}
         while value:
@@ -236,8 +250,7 @@ class BasicCluster(CustomCluster, Basic):
         return attributes
 
     def _parse_mija_attributes(self, value):
-        """Parse non standard atrributes."""
-        attributes = {}
+        """Parse non standard attributes."""
         attribute_names = (
             STATE,
             BATTERY_VOLTAGE_MV,
@@ -405,12 +418,34 @@ class PressureMeasurementCluster(CustomCluster, PressureMeasurement):
         super().__init__(*args, **kwargs)
         self.endpoint.device.pressure_bus.add_listener(self)
 
+    def _update_attribute(self, attrid, value):
+        # drop values above and below documented range for this sensor
+        # value is in hectopascals
+        if attrid == self.ATTR_ID and (300 <= value <= 1100):
+            super()._update_attribute(attrid, value)
+
     def pressure_reported(self, value):
         """Pressure reported."""
         self._update_attribute(self.ATTR_ID, value)
 
 
-class ElectricalMeasurementCluster(CustomCluster, ElectricalMeasurement):
+class AnalogInputCluster(CustomCluster, AnalogInput):
+    """Analog input cluster, only used to relay power consumtion information to ElectricalMeasurementCluster."""
+
+    cluster_id = AnalogInput.cluster_id
+
+    def __init__(self, *args, **kwargs):
+        """Init."""
+        self._current_state = {}
+        super().__init__(*args, **kwargs)
+
+    def _update_attribute(self, attrid, value):
+        super()._update_attribute(attrid, value)
+        if value is not None and value >= 0:
+            self.endpoint.device.power_bus.listener_event(POWER_REPORTED, value)
+
+
+class ElectricalMeasurementCluster(LocalDataCluster, ElectricalMeasurement):
     """Electrical measurement cluster to receive reports that are sent to the basic cluster."""
 
     cluster_id = ElectricalMeasurement.cluster_id
@@ -437,8 +472,52 @@ class ElectricalMeasurementCluster(CustomCluster, ElectricalMeasurement):
         """Consumption reported."""
         self._update_attribute(self.CONSUMPTION_ID, value)
 
-    async def read_attributes_raw(self, attributes, manufacturer=None):
-        """Prevent remote reads."""
-        attributes = [t.uint16_t(a) for a in attributes]
-        values = [self._attr_cache.get(attr) for attr in attributes]
-        return values
+
+class IlluminanceMeasurementCluster(CustomCluster, IlluminanceMeasurement):
+    """Multistate input cluster."""
+
+    cluster_id = IlluminanceMeasurement.cluster_id
+    ATTR_ID = 0
+
+    def __init__(self, *args, **kwargs):
+        """Init."""
+        super().__init__(*args, **kwargs)
+        self.endpoint.device.illuminance_bus.add_listener(self)
+
+    def _update_attribute(self, attrid, value):
+        if attrid == self.ATTR_ID and value > 0:
+            value = 10000 * math.log10(value) + 1
+        super()._update_attribute(attrid, value)
+
+    def illuminance_reported(self, value):
+        """Illuminance reported."""
+        self._update_attribute(self.ATTR_ID, value)
+
+
+class OnOffCluster(OnOff, CustomCluster):
+    """Aqara wall switch cluster."""
+
+    def command(
+        self,
+        command_id: Union[foundation.Command, int, t.uint8_t],
+        *args,
+        manufacturer: Optional[Union[int, t.uint16_t]] = None,
+        expect_reply: bool = True,
+        tsn: Optional[Union[int, t.uint8_t]] = None
+    ):
+        """Command handler."""
+        src_ep = 1
+        dst_ep = self.endpoint.endpoint_id
+        device = self.endpoint.device
+        if tsn is None:
+            tsn = self._endpoint.device.application.get_sequence()
+        return device.request(
+            # device,
+            zha.PROFILE_ID,
+            OnOff.cluster_id,
+            src_ep,
+            dst_ep,
+            tsn,
+            bytes([src_ep, tsn, command_id]),
+            expect_reply=expect_reply,
+        )
diff --git a/zhaquirks/xiaomi/aqara/__init__.py b/zhaquirks/xiaomi/aqara/__init__.py
index 4771c74..d54b08c 100644
--- a/zhaquirks/xiaomi/aqara/__init__.py
+++ b/zhaquirks/xiaomi/aqara/__init__.py
@@ -1,15 +1,1 @@
 """Module for Xiaomi Aqara quirks implementations."""
-import math
-from zigpy.zcl.clusters.measurement import IlluminanceMeasurement
-from zhaquirks import CustomCluster
-
-
-class IlluminanceMeasurementCluster(CustomCluster, IlluminanceMeasurement):
-    """Multistate input cluster."""
-
-    cluster_id = IlluminanceMeasurement.cluster_id
-
-    def _update_attribute(self, attrid, value):
-        if attrid == 0 and value > 0:
-            value = 10000 * math.log10(value) + 1
-        super()._update_attribute(attrid, value)
diff --git a/zhaquirks/xiaomi/aqara/ctrl_ln.py b/zhaquirks/xiaomi/aqara/ctrl_ln.py
new file mode 100644
index 0000000..ed92cf4
--- /dev/null
+++ b/zhaquirks/xiaomi/aqara/ctrl_ln.py
@@ -0,0 +1,135 @@
+"""Xiaomi aqara single key wall switch devices."""
+from zigpy.profiles import zha
+from zigpy.zcl.clusters.general import (
+    AnalogInput,
+    Basic,
+    Groups,
+    Identify,
+    MultistateInput,
+    OnOff,
+    Ota,
+    Scenes,
+    DeviceTemperature,
+    Time,
+    BinaryOutput,
+)
+
+from zhaquirks import Bus
+from .. import (
+    LUMI,
+    AnalogInputCluster,
+    BasicCluster,
+    OnOffCluster,
+    PowerConfigurationCluster,
+    XiaomiCustomDevice,
+)
+from ...const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+    SKIP_CONFIGURATION,
+)
+
+
+class CtrlLn(XiaomiCustomDevice):
+    """Aqara double key switch device."""
+
+    def __init__(self, *args, **kwargs):
+        """Init."""
+        self.power_bus = Bus()
+        super().__init__(*args, **kwargs)
+
+    signature = {
+        MODELS_INFO: [(LUMI, "lumi.ctrl_ln1.aq1"), (LUMI, "lumi.ctrl_ln2.aq1")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    PowerConfigurationCluster.cluster_id,
+                    DeviceTemperature.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                    OnOff.cluster_id,
+                    Time.cluster_id,
+                    BinaryOutput.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
+            },
+            2: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
+                INPUT_CLUSTERS: [OnOff.cluster_id, BinaryOutput.cluster_id],
+                OUTPUT_CLUSTERS: [],
+            },
+            3: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.MAIN_POWER_OUTLET,
+                INPUT_CLUSTERS: [AnalogInput.cluster_id],
+                OUTPUT_CLUSTERS: [Groups.cluster_id, AnalogInput.cluster_id],
+            },
+            4: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.METER_INTERFACE,
+                INPUT_CLUSTERS: [AnalogInput.cluster_id],
+                OUTPUT_CLUSTERS: [AnalogInput.cluster_id],
+            },
+            5: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
+                INPUT_CLUSTERS: [MultistateInput.cluster_id, BinaryOutput.cluster_id],
+                OUTPUT_CLUSTERS: [],
+            },
+            6: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
+                INPUT_CLUSTERS: [MultistateInput.cluster_id, BinaryOutput.cluster_id],
+                OUTPUT_CLUSTERS: [],
+            },
+            7: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
+                INPUT_CLUSTERS: [MultistateInput.cluster_id, BinaryOutput.cluster_id],
+                OUTPUT_CLUSTERS: [],
+            },
+        },
+    }
+
+    replacement = {
+        SKIP_CONFIGURATION: True,
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
+                INPUT_CLUSTERS: [
+                    BasicCluster,
+                    PowerConfigurationCluster,
+                    DeviceTemperature.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                    OnOffCluster,
+                    Time.cluster_id,
+                    BinaryOutput.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
+            },
+            2: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
+                INPUT_CLUSTERS: [OnOffCluster, BinaryOutput.cluster_id],
+                OUTPUT_CLUSTERS: [],
+            },
+            3: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.MAIN_POWER_OUTLET,
+                INPUT_CLUSTERS: [AnalogInputCluster],
+                OUTPUT_CLUSTERS: [Groups.cluster_id, AnalogInput.cluster_id],
+            },
+        },
+    }
diff --git a/zhaquirks/xiaomi/aqara/ctrl_neutral.py b/zhaquirks/xiaomi/aqara/ctrl_neutral.py
new file mode 100644
index 0000000..f53ff40
--- /dev/null
+++ b/zhaquirks/xiaomi/aqara/ctrl_neutral.py
@@ -0,0 +1,185 @@
+"""Xiaomi aqara single key wall switch devices."""
+import logging
+
+from zigpy.profiles import zha
+from zigpy.zcl.clusters.general import (
+    AnalogInput,
+    Basic,
+    Groups,
+    Identify,
+    MultistateInput,
+    OnOff,
+    Ota,
+    Scenes,
+    DeviceTemperature,
+    Time,
+    BinaryOutput,
+)
+
+from .. import (
+    LUMI,
+    BasicCluster,
+    OnOffCluster,
+    PowerConfigurationCluster,
+    XiaomiCustomDevice,
+)
+from ...const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+    SKIP_CONFIGURATION,
+)
+
+DOUBLE = "double"
+HOLD = "long press"
+PRESS_TYPES = {0: "long press", 1: "single", 2: "double"}
+SINGLE = "single"
+STATUS_TYPE_ATTR = 0x0055  # decimal = 85
+XIAOMI_CLUSTER_ID = 0xFFFF
+XIAOMI_DEVICE_TYPE = 0x5F01
+XIAOMI_DEVICE_TYPE2 = 0x5F02
+XIAOMI_DEVICE_TYPE3 = 0x5F03
+
+_LOGGER = logging.getLogger(__name__)
+
+# click attr 0xF000
+# single click 0x3FF1F00
+# double click 0xCFF1F00
+
+
+class CtrlNeutral(XiaomiCustomDevice):
+    """Aqara single and double key switch device."""
+
+    signature = {
+        MODELS_INFO: [(LUMI, "lumi.ctrl_neutral1"), (LUMI, "lumi.ctrl_neutral2")],
+        ENDPOINTS: {
+            # <SimpleDescriptor endpoint=1 profile=260 device_type=6
+            # device_version=2
+            # input_clusters=[0, 3, 1, 2, 25, 10]
+            # output_clusters=[0, 10, 25]>
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    PowerConfigurationCluster.cluster_id,
+                    DeviceTemperature.cluster_id,
+                    Ota.cluster_id,
+                    Time.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [Basic.cluster_id, Time.cluster_id, Ota.cluster_id],
+            },
+            # <SimpleDescriptor endpoint=2 profile=260 device_type=256
+            # device_version=2
+            # input_clusters=[16, 6, 4, 5]
+            # output_clusters=[]>
+            2: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
+                INPUT_CLUSTERS: [
+                    BinaryOutput.cluster_id,
+                    OnOff.cluster_id,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [],
+            },
+            # <SimpleDescriptor endpoint=3 profile=260 device_type=256
+            # device_version=2
+            # input_clusters=[16, 6, 4, 5]
+            # output_clusters=[]
+            3: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
+                INPUT_CLUSTERS: [
+                    BinaryOutput.cluster_id,
+                    OnOff.cluster_id,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [],
+            },
+            # <SimpleDescriptor endpoint=4 profile=260 device_type=0
+            # device_version=2
+            # input_clusters=[18, 6]
+            # output_clusters=[]>
+            4: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
+                INPUT_CLUSTERS: [MultistateInput.cluster_id, OnOff.cluster_id],
+                OUTPUT_CLUSTERS: [],
+            },
+            # <SimpleDescriptor endpoint=5 profile=260 device_type=0
+            # device_version=2
+            # input_clusters=[18, 6]
+            # output_clusters=[]>
+            5: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
+                INPUT_CLUSTERS: [MultistateInput.cluster_id, OnOff.cluster_id],
+                OUTPUT_CLUSTERS: [],
+            },
+            # <SimpleDescriptor endpoint=6 profile=260 device_type=0
+            # device_version=2
+            # input_clusters=[18, 6]
+            # output_clusters=[]>
+            6: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
+                INPUT_CLUSTERS: [MultistateInput.cluster_id, OnOff.cluster_id],
+                OUTPUT_CLUSTERS: [],
+            },
+            # <SimpleDescriptor endpoint=8 profile=260 device_type=83
+            # device_version=2
+            # input_clusters=[12]
+            # output_clusters=[]>
+            8: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.METER_INTERFACE,
+                INPUT_CLUSTERS: [AnalogInput.cluster_id],
+                OUTPUT_CLUSTERS: [],
+            },
+        },
+    }
+
+    replacement = {
+        SKIP_CONFIGURATION: True,
+        ENDPOINTS: {
+            1: {
+                DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
+                INPUT_CLUSTERS: [
+                    BasicCluster,
+                    Identify.cluster_id,
+                    PowerConfigurationCluster.cluster_id,
+                    DeviceTemperature.cluster_id,
+                    Ota.cluster_id,
+                    Time.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [Basic.cluster_id, Time.cluster_id, Ota.cluster_id],
+            },
+            2: {
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
+                INPUT_CLUSTERS: [
+                    BinaryOutput.cluster_id,
+                    OnOffCluster,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [],
+            },
+            3: {
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH,
+                INPUT_CLUSTERS: [
+                    BinaryOutput.cluster_id,
+                    OnOffCluster,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [],
+            },
+        },
+    }
diff --git a/zhaquirks/xiaomi/aqara/cube.py b/zhaquirks/xiaomi/aqara/cube.py
index 4892689..5549721 100644
--- a/zhaquirks/xiaomi/aqara/cube.py
+++ b/zhaquirks/xiaomi/aqara/cube.py
@@ -11,7 +11,6 @@ from zigpy.zcl.clusters.general import (
     Scenes,
 )
 
-from .. import LUMI, BasicCluster, PowerConfigurationCluster, XiaomiCustomDevice
 from ... import CustomCluster
 from ...const import (
     ARGS,
@@ -23,10 +22,12 @@ from ...const import (
     OUTPUT_CLUSTERS,
     PROFILE_ID,
     SHAKEN,
+    SKIP_CONFIGURATION,
     TURN_ON,
     VALUE,
     ZHA_SEND_EVENT,
 )
+from .. import LUMI, BasicCluster, PowerConfigurationCluster, XiaomiCustomDevice
 
 ACTIVATED_FACE = "activated_face"
 DESCRIPTION = "description"
@@ -34,7 +35,7 @@ DROP = "drop"
 DROP_VALUE = 3
 DROPPED = "device_dropped"
 
-FACE_ANY = "fave_any"
+FACE_ANY = "face_any"
 FACE_1 = "face_1"
 FACE_2 = "face_2"
 FACE_3 = "face_3"
@@ -183,7 +184,7 @@ class Cube(XiaomiCustomDevice):
                             event_args[FLIP_DEGREES] = 90
                         event_args[ACTIVATED_FACE] = (value % 8) + 1
 
-                    self.listener_event(ZHA_SEND_EVENT, self, action, event_args)
+                    self.listener_event(ZHA_SEND_EVENT, action, event_args)
 
                 # show something in the sensor in HA
                 super()._update_attribute(0, action)
@@ -206,13 +207,10 @@ class Cube(XiaomiCustomDevice):
                 else:
                     self._current_state[STATUS_TYPE_ATTR] = ROTATE_LEFT
                 # show something in the sensor in HA
-                super()._update_attribute(
-                    0, "{}:{}".format(self._current_state[STATUS_TYPE_ATTR], value)
-                )
+                super()._update_attribute(0, value)
                 if self._current_state[STATUS_TYPE_ATTR] is not None:
                     self.listener_event(
                         ZHA_SEND_EVENT,
-                        self,
                         self._current_state[STATUS_TYPE_ATTR],
                         {RELATIVE_DEGREES: value},
                     )
@@ -276,6 +274,7 @@ class Cube(XiaomiCustomDevice):
     }
 
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 DEVICE_TYPE: XIAOMI_SENSORS_REPLACEMENT,
@@ -314,7 +313,7 @@ class Cube(XiaomiCustomDevice):
                     AnalogInput.cluster_id,
                 ],
             },
-        }
+        },
     }
 
     device_automation_triggers = {
diff --git a/zhaquirks/xiaomi/aqara/cube_aqgl01.py b/zhaquirks/xiaomi/aqara/cube_aqgl01.py
index 95bdd3a..86e8773 100644
--- a/zhaquirks/xiaomi/aqara/cube_aqgl01.py
+++ b/zhaquirks/xiaomi/aqara/cube_aqgl01.py
@@ -23,6 +23,7 @@ from ...const import (
     OUTPUT_CLUSTERS,
     PROFILE_ID,
     SHAKEN,
+    SKIP_CONFIGURATION,
     TURN_ON,
     VALUE,
     ZHA_SEND_EVENT,
@@ -34,7 +35,7 @@ DROP = "drop"
 DROP_VALUE = 3
 DROPPED = "device_dropped"
 
-FACE_ANY = "fave_any"
+FACE_ANY = "face_any"
 FACE_1 = "face_1"
 FACE_2 = "face_2"
 FACE_3 = "face_3"
@@ -183,7 +184,7 @@ class CubeAQGL01(XiaomiCustomDevice):
                             event_args[FLIP_DEGREES] = 90
                         event_args[ACTIVATED_FACE] = (value % 8) + 1
 
-                    self.listener_event(ZHA_SEND_EVENT, self, action, event_args)
+                    self.listener_event(ZHA_SEND_EVENT, action, event_args)
 
                 # show something in the sensor in HA
                 super()._update_attribute(0, action)
@@ -206,13 +207,10 @@ class CubeAQGL01(XiaomiCustomDevice):
                 else:
                     self._current_state[STATUS_TYPE_ATTR] = ROTATE_LEFT
                 # show something in the sensor in HA
-                super()._update_attribute(
-                    0, "{}:{}".format(self._current_state[STATUS_TYPE_ATTR], value)
-                )
+                super()._update_attribute(0, value)
                 if self._current_state[STATUS_TYPE_ATTR] is not None:
                     self.listener_event(
                         ZHA_SEND_EVENT,
-                        self,
                         self._current_state[STATUS_TYPE_ATTR],
                         {RELATIVE_DEGREES: value},
                     )
@@ -276,6 +274,7 @@ class CubeAQGL01(XiaomiCustomDevice):
     }
 
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 DEVICE_TYPE: XIAOMI_SENSORS_REPLACEMENT,
@@ -314,7 +313,7 @@ class CubeAQGL01(XiaomiCustomDevice):
                     AnalogInput.cluster_id,
                 ],
             },
-        }
+        },
     }
 
     device_automation_triggers = {
diff --git a/zhaquirks/xiaomi/aqara/illumination.py b/zhaquirks/xiaomi/aqara/illumination.py
new file mode 100644
index 0000000..c46daea
--- /dev/null
+++ b/zhaquirks/xiaomi/aqara/illumination.py
@@ -0,0 +1,65 @@
+"""Quirk for lumi.sen_ill.mgl01 illumination sensor."""
+import logging
+
+from zigpy.profiles import zha
+from zigpy.zcl.clusters.general import Basic, Identify
+from zigpy.zcl.clusters.measurement import IlluminanceMeasurement
+from zigpy.zdo.types import NodeDescriptor
+
+from .. import LUMI, BasicCluster, XiaomiCustomDevice
+from ... import PowerConfigurationCluster
+from ...const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    NODE_DESCRIPTOR,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+)
+
+_LOGGER = logging.getLogger(__name__)
+
+
+class Illumination(XiaomiCustomDevice):
+    """Aqara LUMI lumi.sen_ill.mgl01."""
+
+    signature = {
+        # <SimpleDescriptor endpoint=1 profile=260 device_type=262
+        # device_version=1
+        # input_clusters=[0, 1024, 3, 1]
+        # output_clusters=[3]>
+        MODELS_INFO: [(LUMI, "lumi.sen_ill.mgl01")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.LIGHT_SENSOR,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    IlluminanceMeasurement.cluster_id,
+                    PowerConfigurationCluster.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [Identify.cluster_id],
+            }
+        },
+    }
+
+    replacement = {
+        NODE_DESCRIPTOR: NodeDescriptor(
+            0x02, 0x40, 0x80, 0x115F, 0x7F, 0x0064, 0x2C00, 0x0064, 0x00
+        ),
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.LIGHT_SENSOR,
+                INPUT_CLUSTERS: [
+                    BasicCluster,
+                    Identify.cluster_id,
+                    IlluminanceMeasurement.cluster_id,
+                    PowerConfigurationCluster,
+                ],
+                OUTPUT_CLUSTERS: [Identify.cluster_id],
+            }
+        },
+    }
diff --git a/zhaquirks/xiaomi/aqara/light_aqcn2.py b/zhaquirks/xiaomi/aqara/light_aqcn2.py
new file mode 100644
index 0000000..9f0bfff
--- /dev/null
+++ b/zhaquirks/xiaomi/aqara/light_aqcn2.py
@@ -0,0 +1,109 @@
+"""Quirk for Xiaomi Aqara Smart LED bulb ZNLDP12LM."""
+import logging
+
+from zigpy.profiles import zha
+from zigpy.zcl.clusters.closures import WindowCovering
+from zigpy.zcl.clusters.general import (
+    AnalogOutput,
+    Groups,
+    Identify,
+    LevelControl,
+    MultistateOutput,
+    OnOff,
+    Ota,
+    PowerConfiguration,
+    Scenes,
+    Time,
+)
+from zigpy.zcl.clusters.lighting import Color
+from zigpy.zcl.clusters.measurement import (
+    OccupancySensing,
+    PressureMeasurement,
+    RelativeHumidity,
+    TemperatureMeasurement,
+)
+
+from .. import LUMI, BasicCluster, XiaomiCustomDevice
+from ... import CustomCluster
+from ...const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+)
+
+_LOGGER = logging.getLogger(__name__)
+
+
+class LightAqcn02(XiaomiCustomDevice):
+    """Custom device for ZNLDP12LM."""
+
+    class ColorCluster(CustomCluster, Color):
+        """Color Cluster."""
+
+        _CONSTANT_ATTRIBUTES = {0x400A: 0x0010, 0x400B: 153, 0x400C: 370}
+
+    signature = {
+        # endpoint=1 profile=260 device_type=258 device_version=1 input_clusters=[0, 4, 3, 5, 10, 258, 13, 19, 6, 1, 1030, 8, 768, 1027, 1029, 1026] output_clusters=[25, 10, 13, 258, 19, 6, 1, 1030, 8, 768]>
+        MODELS_INFO: [(LUMI, "lumi.light.aqcn02")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.COLOR_DIMMABLE_LIGHT,
+                INPUT_CLUSTERS: [
+                    BasicCluster.cluster_id,
+                    PowerConfiguration.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Time.cluster_id,
+                    AnalogOutput.cluster_id,
+                    MultistateOutput.cluster_id,
+                    WindowCovering.cluster_id,
+                    Color.cluster_id,
+                    TemperatureMeasurement.cluster_id,
+                    PressureMeasurement.cluster_id,
+                    RelativeHumidity.cluster_id,
+                    OccupancySensing.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [
+                    PowerConfiguration.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Time.cluster_id,
+                    AnalogOutput.cluster_id,
+                    MultistateOutput.cluster_id,
+                    Ota.cluster_id,
+                    WindowCovering.cluster_id,
+                    ColorCluster.cluster_id,
+                    OccupancySensing.cluster_id,
+                ],
+            }
+        },
+    }
+    replacement = {
+        ENDPOINTS: {
+            1: {
+                DEVICE_TYPE: zha.DeviceType.COLOR_DIMMABLE_LIGHT,
+                INPUT_CLUSTERS: [
+                    BasicCluster,  # 0
+                    Groups.cluster_id,  # 4
+                    Identify.cluster_id,  # 3
+                    Scenes.cluster_id,  # 5
+                    OnOff.cluster_id,  # 6
+                    PowerConfiguration.cluster_id,  # 1
+                    LevelControl.cluster_id,  # 8
+                    ColorCluster,  # 768
+                ],
+                OUTPUT_CLUSTERS: [
+                    Time.cluster_id,  # 10
+                    Ota.cluster_id,  # 19
+                    OccupancySensing.cluster_id,  # 1030
+                ],
+            }
+        }
+    }
diff --git a/zhaquirks/xiaomi/aqara/magnet_aq2.py b/zhaquirks/xiaomi/aqara/magnet_aq2.py
index 13709f7..c9ae8d3 100644
--- a/zhaquirks/xiaomi/aqara/magnet_aq2.py
+++ b/zhaquirks/xiaomi/aqara/magnet_aq2.py
@@ -12,6 +12,7 @@ from ...const import (
     MODELS_INFO,
     OUTPUT_CLUSTERS,
     PROFILE_ID,
+    SKIP_CONFIGURATION,
 )
 
 OPEN_CLOSE_DEVICE_TYPE = 0x5F01
@@ -53,6 +54,7 @@ class MagnetAQ2(XiaomiCustomDevice):
         },
     }
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 INPUT_CLUSTERS: [
@@ -68,5 +70,5 @@ class MagnetAQ2(XiaomiCustomDevice):
                     XIAOMI_CLUSTER_ID,
                 ],
             }
-        }
+        },
     }
diff --git a/zhaquirks/xiaomi/aqara/motion_aq2.py b/zhaquirks/xiaomi/aqara/motion_aq2.py
index 3f92fd4..52b35a6 100644
--- a/zhaquirks/xiaomi/aqara/motion_aq2.py
+++ b/zhaquirks/xiaomi/aqara/motion_aq2.py
@@ -5,10 +5,10 @@ from zigpy.zcl.clusters.general import Basic, Identify, Ota, PowerConfiguration
 from zigpy.zcl.clusters.measurement import OccupancySensing
 from zigpy.zcl.clusters.security import IasZone
 
-from . import IlluminanceMeasurementCluster
 from .. import (
     LUMI,
     BasicCluster,
+    IlluminanceMeasurementCluster,
     MotionCluster,
     OccupancyCluster,
     PowerConfigurationCluster,
@@ -22,6 +22,7 @@ from ...const import (
     MODELS_INFO,
     OUTPUT_CLUSTERS,
     PROFILE_ID,
+    SKIP_CONFIGURATION,
 )
 
 XIAOMI_CLUSTER_ID = 0xFFFF
@@ -34,6 +35,7 @@ class MotionAQ2(XiaomiCustomDevice):
         """Init."""
         self.battery_size = 9
         self.motion_bus = Bus()
+        self.illuminance_bus = Bus()
         super().__init__(*args, **kwargs)
 
     signature = {
@@ -61,6 +63,7 @@ class MotionAQ2(XiaomiCustomDevice):
     }
 
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 INPUT_CLUSTERS: [
@@ -74,5 +77,5 @@ class MotionAQ2(XiaomiCustomDevice):
                 ],
                 OUTPUT_CLUSTERS: [Basic.cluster_id, Ota.cluster_id],
             }
-        }
+        },
     }
diff --git a/zhaquirks/xiaomi/aqara/motion_aq2b.py b/zhaquirks/xiaomi/aqara/motion_aq2b.py
index d2199b0..8f5ed9d 100644
--- a/zhaquirks/xiaomi/aqara/motion_aq2b.py
+++ b/zhaquirks/xiaomi/aqara/motion_aq2b.py
@@ -4,8 +4,14 @@ from zigpy.profiles import zha
 from zigpy.zcl.clusters.general import Basic, Ota
 from zigpy.zcl.clusters.measurement import OccupancySensing
 
-from . import IlluminanceMeasurementCluster
-from .. import LUMI, BasicCluster, MotionCluster, OccupancyCluster, XiaomiCustomDevice
+from .. import (
+    LUMI,
+    BasicCluster,
+    IlluminanceMeasurementCluster,
+    MotionCluster,
+    OccupancyCluster,
+    XiaomiCustomDevice,
+)
 from ... import Bus
 from ...const import (
     DEVICE_TYPE,
@@ -14,6 +20,7 @@ from ...const import (
     MODELS_INFO,
     OUTPUT_CLUSTERS,
     PROFILE_ID,
+    SKIP_CONFIGURATION,
 )
 
 XIAOMI_CLUSTER_ID = 0xFFFF
@@ -26,6 +33,7 @@ class MotionAQ2(XiaomiCustomDevice):
         """Init."""
         self.battery_size = 9
         self.motion_bus = Bus()
+        self.illuminance_bus = Bus()
         super().__init__(*args, **kwargs)
 
     signature = {
@@ -50,6 +58,7 @@ class MotionAQ2(XiaomiCustomDevice):
     }
 
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 INPUT_CLUSTERS: [
@@ -61,5 +70,5 @@ class MotionAQ2(XiaomiCustomDevice):
                 ],
                 OUTPUT_CLUSTERS: [Basic.cluster_id, Ota.cluster_id],
             }
-        }
+        },
     }
diff --git a/zhaquirks/xiaomi/aqara/opple_remote.py b/zhaquirks/xiaomi/aqara/opple_remote.py
index 72f8ceb..1a0eab2 100644
--- a/zhaquirks/xiaomi/aqara/opple_remote.py
+++ b/zhaquirks/xiaomi/aqara/opple_remote.py
@@ -2,13 +2,28 @@
 import logging
 
 from zigpy.profiles import zha
-from zigpy.zcl.clusters.general import Basic, Identify, LevelControl, OnOff
+import zigpy.types as types
+from zigpy.zcl.clusters.general import (
+    Basic,
+    Identify,
+    LevelControl,
+    MultistateInput,
+    OnOff,
+)
 from zigpy.zcl.clusters.lighting import Color
 from zigpy.zdo.types import NodeDescriptor
 
-from .. import LUMI, BasicCluster, PowerConfigurationCluster, XiaomiCustomDevice
+from zhaquirks import CustomCluster
+
+from .. import LUMI, BasicCluster, XiaomiCustomDevice
+from ... import PowerConfigurationCluster
 from ...const import (
+    ALT_DOUBLE_PRESS,
+    ALT_LONG_PRESS,
+    ALT_SHORT_PRESS,
     ARGS,
+    ATTR_ID,
+    BUTTON,
     BUTTON_1,
     BUTTON_2,
     BUTTON_3,
@@ -28,34 +43,120 @@ from ...const import (
     ENDPOINTS,
     INPUT_CLUSTERS,
     LONG_PRESS,
+    LONG_RELEASE,
     MODELS_INFO,
     NODE_DESCRIPTOR,
     OUTPUT_CLUSTERS,
+    PRESS_TYPE,
     PROFILE_ID,
     SHORT_PRESS,
+    TRIPLE_PRESS,
+    VALUE,
+    ZHA_SEND_EVENT,
 )
 
-BOTH_BUTTONS = "both_buttons"
-BOTH_DOUBLE = "both_double"
-BOTH_HOLD = "both_long press"
-BOTH_SINGLE = "both_single"
-ENDPOINT_MAP = {1: "left", 2: "right", 3: "both"}
-LEFT_DOUBLE = "left_double"
-LEFT_HOLD = "left_long press"
-LEFT_SINGLE = "left_single"
-PRESS_TYPES = {0: "long press", 1: "single", 2: "double"}
-RIGHT_DOUBLE = "right_double"
-RIGHT_HOLD = "right_long press"
-RIGHT_SINGLE = "right_single"
+PRESS_TYPES = {0: "long press", 1: "single", 2: "double", 3: "triple", 255: "release"}
 STATUS_TYPE_ATTR = 0x0055  # decimal = 85
-XIAOMI_CLUSTER_ID = 0xFFFF
-XIAOMI_DEVICE_TYPE = 0x5F01
-XIAOMI_DEVICE_TYPE2 = 0x5F02
-XIAOMI_DEVICE_TYPE3 = 0x5F03
+
+COMMAND_1_SINGLE = "1_single"
+COMMAND_1_DOUBLE = "1_double"
+COMMAND_1_TRIPLE = "1_triple"
+COMMAND_1_HOLD = "1_hold"
+COMMAND_1_RELEASE = "1_release"
+
+COMMAND_2_SINGLE = "2_single"
+COMMAND_2_DOUBLE = "2_double"
+COMMAND_2_TRIPLE = "2_triple"
+COMMAND_2_HOLD = "2_hold"
+COMMAND_2_RELEASE = "2_release"
+
+COMMAND_3_SINGLE = "3_single"
+COMMAND_3_DOUBLE = "3_double"
+COMMAND_3_TRIPLE = "3_triple"
+COMMAND_3_HOLD = "3_hold"
+COMMAND_3_RELEASE = "3_release"
+
+COMMAND_4_SINGLE = "4_single"
+COMMAND_4_DOUBLE = "4_double"
+COMMAND_4_TRIPLE = "4_triple"
+COMMAND_4_HOLD = "4_hold"
+COMMAND_4_RELEASE = "4_release"
+
+COMMAND_5_SINGLE = "5_single"
+COMMAND_5_DOUBLE = "5_double"
+COMMAND_5_TRIPLE = "5_triple"
+COMMAND_5_HOLD = "5_hold"
+COMMAND_5_RELEASE = "5_release"
+
+COMMAND_6_SINGLE = "6_single"
+COMMAND_6_DOUBLE = "6_double"
+COMMAND_6_TRIPLE = "6_triple"
+COMMAND_6_HOLD = "6_hold"
+COMMAND_6_RELEASE = "6_release"
+
+OPPLE_CLUSTER_ID = 0xFCC0
+OPPLE_MFG_CODE = 0x115F
 
 _LOGGER = logging.getLogger(__name__)
 
 
+class MultistateInputCluster(CustomCluster, MultistateInput):
+    """Multistate input cluster."""
+
+    cluster_id = MultistateInput.cluster_id
+
+    def __init__(self, *args, **kwargs):
+        """Init."""
+        self._current_state = None
+        super().__init__(*args, **kwargs)
+
+    async def configure_reporting(
+        self,
+        attribute,
+        min_interval,
+        max_interval,
+        reportable_change,
+        manufacturer=None,
+    ):
+        """Configure reporting."""
+        pass
+
+    def _update_attribute(self, attrid, value):
+        super()._update_attribute(attrid, value)
+        if attrid == STATUS_TYPE_ATTR:
+            self._current_state = PRESS_TYPES.get(value)
+            event_args = {
+                BUTTON: self.endpoint.endpoint_id,
+                PRESS_TYPE: self._current_state,
+                ATTR_ID: attrid,
+                VALUE: value,
+            }
+            action = "{}_{}".format(self.endpoint.endpoint_id, self._current_state)
+            self.listener_event(ZHA_SEND_EVENT, action, event_args)
+            # show something in the sensor in HA
+            super()._update_attribute(0, action)
+
+
+class OppleCluster(CustomCluster):
+    """Opple cluster."""
+
+    ep_attribute = "opple_cluster"
+    cluster_id = OPPLE_CLUSTER_ID
+    attributes = {0x0009: ("mode", types.uint8_t)}
+    attr_config = {0x0009: 0x01}
+
+    def __init__(self, *args, **kwargs):
+        """Init."""
+        self._current_state = None
+        super().__init__(*args, **kwargs)
+
+    async def bind(self):
+        """Bind cluster."""
+        result = await super().bind()
+        await self.write_attributes(self.attr_config, manufacturer=OPPLE_MFG_CODE)
+        return result
+
+
 class RemoteB286OPCN01(XiaomiCustomDevice):
     """Aqara Opple 2 button remote device."""
 
@@ -110,6 +211,8 @@ class RemoteB286OPCN01(XiaomiCustomDevice):
                     BasicCluster,
                     Identify.cluster_id,
                     PowerConfigurationCluster,
+                    OppleCluster,
+                    MultistateInputCluster,
                 ],
                 OUTPUT_CLUSTERS: [
                     Identify.cluster_id,
@@ -121,7 +224,7 @@ class RemoteB286OPCN01(XiaomiCustomDevice):
             2: {
                 PROFILE_ID: zha.PROFILE_ID,
                 DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
-                INPUT_CLUSTERS: [Identify.cluster_id],
+                INPUT_CLUSTERS: [Identify.cluster_id, MultistateInputCluster],
                 OUTPUT_CLUSTERS: [Identify.cluster_id, OnOff.cluster_id],
             },
             3: {},
@@ -154,6 +257,16 @@ class RemoteB286OPCN01(XiaomiCustomDevice):
             ENDPOINT_ID: 1,
             ARGS: [3, 69, 7, 0, 0],
         },
+        (ALT_SHORT_PRESS, BUTTON_1): {COMMAND: COMMAND_1_SINGLE},
+        (ALT_DOUBLE_PRESS, BUTTON_1): {COMMAND: COMMAND_1_DOUBLE},
+        (TRIPLE_PRESS, BUTTON_1): {COMMAND: COMMAND_1_TRIPLE},
+        (ALT_LONG_PRESS, BUTTON_1): {COMMAND: COMMAND_1_HOLD},
+        (LONG_RELEASE, BUTTON_1): {COMMAND: COMMAND_1_RELEASE},
+        (ALT_SHORT_PRESS, BUTTON_2): {COMMAND: COMMAND_2_SINGLE},
+        (ALT_DOUBLE_PRESS, BUTTON_2): {COMMAND: COMMAND_2_DOUBLE},
+        (TRIPLE_PRESS, BUTTON_2): {COMMAND: COMMAND_2_TRIPLE},
+        (ALT_LONG_PRESS, BUTTON_2): {COMMAND: COMMAND_2_HOLD},
+        (LONG_RELEASE, BUTTON_2): {COMMAND: COMMAND_2_RELEASE},
     }
 
 
@@ -211,6 +324,8 @@ class RemoteB486OPCN01(XiaomiCustomDevice):
                     BasicCluster,
                     Identify.cluster_id,
                     PowerConfigurationCluster,
+                    OppleCluster,
+                    MultistateInputCluster,
                 ],
                 OUTPUT_CLUSTERS: [
                     Identify.cluster_id,
@@ -222,11 +337,21 @@ class RemoteB486OPCN01(XiaomiCustomDevice):
             2: {
                 PROFILE_ID: zha.PROFILE_ID,
                 DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
-                INPUT_CLUSTERS: [Identify.cluster_id],
+                INPUT_CLUSTERS: [Identify.cluster_id, MultistateInputCluster],
                 OUTPUT_CLUSTERS: [Identify.cluster_id, OnOff.cluster_id],
             },
-            3: {},
-            4: {},
+            3: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [MultistateInputCluster],
+                OUTPUT_CLUSTERS: [],
+            },
+            4: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [MultistateInputCluster],
+                OUTPUT_CLUSTERS: [],
+            },
             5: {},
             6: {},
         },
@@ -255,6 +380,26 @@ class RemoteB486OPCN01(XiaomiCustomDevice):
             ENDPOINT_ID: 1,
             ARGS: [3, 69, 7, 0, 0],
         },
+        (ALT_SHORT_PRESS, BUTTON_1): {COMMAND: COMMAND_1_SINGLE},
+        (ALT_DOUBLE_PRESS, BUTTON_1): {COMMAND: COMMAND_1_DOUBLE},
+        (TRIPLE_PRESS, BUTTON_1): {COMMAND: COMMAND_1_TRIPLE},
+        (ALT_LONG_PRESS, BUTTON_1): {COMMAND: COMMAND_1_HOLD},
+        (LONG_RELEASE, BUTTON_1): {COMMAND: COMMAND_1_RELEASE},
+        (ALT_SHORT_PRESS, BUTTON_2): {COMMAND: COMMAND_2_SINGLE},
+        (ALT_DOUBLE_PRESS, BUTTON_2): {COMMAND: COMMAND_2_DOUBLE},
+        (TRIPLE_PRESS, BUTTON_2): {COMMAND: COMMAND_2_TRIPLE},
+        (ALT_LONG_PRESS, BUTTON_2): {COMMAND: COMMAND_2_HOLD},
+        (LONG_RELEASE, BUTTON_2): {COMMAND: COMMAND_2_RELEASE},
+        (ALT_SHORT_PRESS, BUTTON_3): {COMMAND: COMMAND_3_SINGLE},
+        (ALT_DOUBLE_PRESS, BUTTON_3): {COMMAND: COMMAND_3_DOUBLE},
+        (TRIPLE_PRESS, BUTTON_3): {COMMAND: COMMAND_3_TRIPLE},
+        (ALT_LONG_PRESS, BUTTON_3): {COMMAND: COMMAND_3_HOLD},
+        (LONG_RELEASE, BUTTON_3): {COMMAND: COMMAND_3_RELEASE},
+        (ALT_SHORT_PRESS, BUTTON_4): {COMMAND: COMMAND_4_SINGLE},
+        (ALT_DOUBLE_PRESS, BUTTON_4): {COMMAND: COMMAND_4_DOUBLE},
+        (TRIPLE_PRESS, BUTTON_4): {COMMAND: COMMAND_4_TRIPLE},
+        (ALT_LONG_PRESS, BUTTON_4): {COMMAND: COMMAND_4_HOLD},
+        (LONG_RELEASE, BUTTON_4): {COMMAND: COMMAND_4_RELEASE},
     }
 
 
@@ -312,6 +457,8 @@ class RemoteB686OPCN01(XiaomiCustomDevice):
                     BasicCluster,
                     Identify.cluster_id,
                     PowerConfigurationCluster,
+                    OppleCluster,
+                    MultistateInputCluster,
                 ],
                 OUTPUT_CLUSTERS: [
                     Identify.cluster_id,
@@ -323,13 +470,33 @@ class RemoteB686OPCN01(XiaomiCustomDevice):
             2: {
                 PROFILE_ID: zha.PROFILE_ID,
                 DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
-                INPUT_CLUSTERS: [Identify.cluster_id],
+                INPUT_CLUSTERS: [Identify.cluster_id, MultistateInputCluster],
                 OUTPUT_CLUSTERS: [Identify.cluster_id, OnOff.cluster_id],
             },
-            3: {},
-            4: {},
-            5: {},
-            6: {},
+            3: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [MultistateInputCluster],
+                OUTPUT_CLUSTERS: [],
+            },
+            4: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [MultistateInputCluster],
+                OUTPUT_CLUSTERS: [],
+            },
+            5: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [MultistateInputCluster],
+                OUTPUT_CLUSTERS: [],
+            },
+            6: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [MultistateInputCluster],
+                OUTPUT_CLUSTERS: [],
+            },
         },
     }
 
@@ -368,4 +535,388 @@ class RemoteB686OPCN01(XiaomiCustomDevice):
             ENDPOINT_ID: 1,
             ARGS: [3, 15, 0, 0],
         },
+        (ALT_SHORT_PRESS, BUTTON_1): {COMMAND: COMMAND_1_SINGLE},
+        (ALT_DOUBLE_PRESS, BUTTON_1): {COMMAND: COMMAND_1_DOUBLE},
+        (TRIPLE_PRESS, BUTTON_1): {COMMAND: COMMAND_1_TRIPLE},
+        (ALT_LONG_PRESS, BUTTON_1): {COMMAND: COMMAND_1_HOLD},
+        (LONG_RELEASE, BUTTON_1): {COMMAND: COMMAND_1_RELEASE},
+        (ALT_SHORT_PRESS, BUTTON_2): {COMMAND: COMMAND_2_SINGLE},
+        (ALT_DOUBLE_PRESS, BUTTON_2): {COMMAND: COMMAND_2_DOUBLE},
+        (TRIPLE_PRESS, BUTTON_2): {COMMAND: COMMAND_2_TRIPLE},
+        (ALT_LONG_PRESS, BUTTON_2): {COMMAND: COMMAND_2_HOLD},
+        (LONG_RELEASE, BUTTON_2): {COMMAND: COMMAND_2_RELEASE},
+        (ALT_SHORT_PRESS, BUTTON_3): {COMMAND: COMMAND_3_SINGLE},
+        (ALT_DOUBLE_PRESS, BUTTON_3): {COMMAND: COMMAND_3_DOUBLE},
+        (TRIPLE_PRESS, BUTTON_3): {COMMAND: COMMAND_3_TRIPLE},
+        (ALT_LONG_PRESS, BUTTON_3): {COMMAND: COMMAND_3_HOLD},
+        (LONG_RELEASE, BUTTON_3): {COMMAND: COMMAND_3_RELEASE},
+        (ALT_SHORT_PRESS, BUTTON_4): {COMMAND: COMMAND_4_SINGLE},
+        (ALT_DOUBLE_PRESS, BUTTON_4): {COMMAND: COMMAND_4_DOUBLE},
+        (TRIPLE_PRESS, BUTTON_4): {COMMAND: COMMAND_4_TRIPLE},
+        (ALT_LONG_PRESS, BUTTON_4): {COMMAND: COMMAND_4_HOLD},
+        (LONG_RELEASE, BUTTON_4): {COMMAND: COMMAND_4_RELEASE},
+        (ALT_SHORT_PRESS, BUTTON_5): {COMMAND: COMMAND_5_SINGLE},
+        (ALT_DOUBLE_PRESS, BUTTON_5): {COMMAND: COMMAND_5_DOUBLE},
+        (TRIPLE_PRESS, BUTTON_5): {COMMAND: COMMAND_5_TRIPLE},
+        (ALT_LONG_PRESS, BUTTON_5): {COMMAND: COMMAND_5_HOLD},
+        (LONG_RELEASE, BUTTON_5): {COMMAND: COMMAND_5_RELEASE},
+        (ALT_SHORT_PRESS, BUTTON_6): {COMMAND: COMMAND_6_SINGLE},
+        (ALT_DOUBLE_PRESS, BUTTON_6): {COMMAND: COMMAND_6_DOUBLE},
+        (TRIPLE_PRESS, BUTTON_6): {COMMAND: COMMAND_6_TRIPLE},
+        (ALT_LONG_PRESS, BUTTON_6): {COMMAND: COMMAND_6_HOLD},
+        (LONG_RELEASE, BUTTON_6): {COMMAND: COMMAND_6_RELEASE},
+    }
+
+
+class RemoteB286OPCN01V2(XiaomiCustomDevice):
+    """Aqara Opple 2 button remote device."""
+
+    signature = {
+        # <SimpleDescriptor endpoint=1 profile=260 device_type=261
+        # device_version=1
+        # input_clusters=[0, 3, 1]
+        # output_clusters=[3, 6, 8, 768]>
+        MODELS_INFO: [(LUMI, "lumi.remote.b286opcn01")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.COLOR_DIMMER_SWITCH,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    PowerConfigurationCluster.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Identify.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Color.cluster_id,
+                ],
+            },
+            # <SimpleDescriptor endpoint=2 profile=260 device_type=259
+            # device_version=1
+            # input_clusters=[3]
+            # output_clusters=[6, 3]>
+            2: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [Identify.cluster_id],
+                OUTPUT_CLUSTERS: [Identify.cluster_id, OnOff.cluster_id],
+            },
+        },
+    }
+
+    replacement = {
+        NODE_DESCRIPTOR: NodeDescriptor(
+            0x02, 0x40, 0x80, 0x115F, 0x7F, 0x0064, 0x2C00, 0x0064, 0x00
+        ),
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.COLOR_DIMMER_SWITCH,
+                INPUT_CLUSTERS: [
+                    BasicCluster,
+                    Identify.cluster_id,
+                    PowerConfigurationCluster,
+                    OppleCluster,
+                    MultistateInputCluster,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Identify.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Color.cluster_id,
+                ],
+            }
+        },
+    }
+
+    device_automation_triggers = RemoteB286OPCN01.device_automation_triggers
+
+
+class RemoteB486OPCN01V2(XiaomiCustomDevice):
+    """Aqara Opple 4 button remote device."""
+
+    signature = {
+        # <SimpleDescriptor endpoint=1 profile=260 device_type=261
+        # device_version=1
+        # input_clusters=[0, 3, 1]
+        # output_clusters=[3, 6, 8, 768]>
+        MODELS_INFO: [(LUMI, "lumi.remote.b486opcn01")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.COLOR_DIMMER_SWITCH,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    PowerConfigurationCluster.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Identify.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Color.cluster_id,
+                ],
+            }
+        },
+    }
+
+    replacement = {
+        NODE_DESCRIPTOR: NodeDescriptor(
+            0x02, 0x40, 0x80, 0x115F, 0x7F, 0x0064, 0x2C00, 0x0064, 0x00
+        ),
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.COLOR_DIMMER_SWITCH,
+                INPUT_CLUSTERS: [
+                    BasicCluster,
+                    Identify.cluster_id,
+                    PowerConfigurationCluster,
+                    OppleCluster,
+                    MultistateInputCluster,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Identify.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Color.cluster_id,
+                ],
+            },
+            2: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [Identify.cluster_id, MultistateInputCluster],
+                OUTPUT_CLUSTERS: [Identify.cluster_id, OnOff.cluster_id],
+            },
+            3: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [MultistateInputCluster],
+                OUTPUT_CLUSTERS: [],
+            },
+            4: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [MultistateInputCluster],
+                OUTPUT_CLUSTERS: [],
+            },
+        },
+    }
+
+    device_automation_triggers = RemoteB486OPCN01.device_automation_triggers
+
+
+class RemoteB686OPCN01V2(XiaomiCustomDevice):
+    """Aqara Opple 6 button remote device."""
+
+    signature = {
+        # <SimpleDescriptor endpoint=1 profile=260 device_type=261
+        # device_version=1
+        # input_clusters=[0, 3, 1]
+        # output_clusters=[3, 6, 8, 768]>
+        MODELS_INFO: [(LUMI, "lumi.remote.b686opcn01")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.COLOR_DIMMER_SWITCH,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    PowerConfigurationCluster.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Identify.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Color.cluster_id,
+                ],
+            }
+        },
+    }
+
+    replacement = {
+        NODE_DESCRIPTOR: NodeDescriptor(
+            0x02, 0x40, 0x80, 0x115F, 0x7F, 0x0064, 0x2C00, 0x0064, 0x00
+        ),
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.COLOR_DIMMER_SWITCH,
+                INPUT_CLUSTERS: [
+                    BasicCluster,
+                    Identify.cluster_id,
+                    PowerConfigurationCluster,
+                    OppleCluster,
+                    MultistateInputCluster,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Identify.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Color.cluster_id,
+                ],
+            },
+            2: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [Identify.cluster_id, MultistateInputCluster],
+                OUTPUT_CLUSTERS: [Identify.cluster_id, OnOff.cluster_id],
+            },
+            3: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [MultistateInputCluster],
+                OUTPUT_CLUSTERS: [],
+            },
+            4: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [MultistateInputCluster],
+                OUTPUT_CLUSTERS: [],
+            },
+            5: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [MultistateInputCluster],
+                OUTPUT_CLUSTERS: [],
+            },
+            6: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [MultistateInputCluster],
+                OUTPUT_CLUSTERS: [],
+            },
+        },
+    }
+
+    device_automation_triggers = RemoteB686OPCN01.device_automation_triggers
+
+
+class RemoteB686OPCN01V3(XiaomiCustomDevice):
+    """Aqara Opple 6 button remote device."""
+
+    signature = {
+        # <SimpleDescriptor endpoint=1 profile=260 device_type=261
+        # device_version=1
+        # input_clusters=[0, 3, 1]
+        # output_clusters=[3, 6, 8, 768]>
+        MODELS_INFO: [(LUMI, "lumi.remote.b686opcn01")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.COLOR_DIMMER_SWITCH,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    Identify.cluster_id,
+                    PowerConfigurationCluster.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Identify.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Color.cluster_id,
+                ],
+            },
+            2: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [Identify.cluster_id],
+                OUTPUT_CLUSTERS: [OnOff.cluster_id, Identify.cluster_id],
+            },
+            3: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [
+                    MultistateInputCluster.cluster_id,
+                    Identify.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [OnOff.cluster_id],
+            },
+            4: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [
+                    MultistateInputCluster.cluster_id,
+                    Identify.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [OnOff.cluster_id],
+            },
+            5: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [
+                    MultistateInputCluster.cluster_id,
+                    Identify.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [OnOff.cluster_id],
+            },
+            6: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [
+                    MultistateInputCluster.cluster_id,
+                    Identify.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [OnOff.cluster_id],
+            },
+        },
+    }
+
+    replacement = {
+        NODE_DESCRIPTOR: NodeDescriptor(
+            0x02, 0x40, 0x80, 0x115F, 0x7F, 0x0064, 0x2C00, 0x0064, 0x00
+        ),
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.COLOR_DIMMER_SWITCH,
+                INPUT_CLUSTERS: [
+                    BasicCluster,
+                    Identify.cluster_id,
+                    PowerConfigurationCluster,
+                    OppleCluster,
+                    MultistateInputCluster,
+                ],
+                OUTPUT_CLUSTERS: [
+                    Identify.cluster_id,
+                    OnOff.cluster_id,
+                    LevelControl.cluster_id,
+                    Color.cluster_id,
+                ],
+            },
+            2: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [Identify.cluster_id],
+                OUTPUT_CLUSTERS: [OnOff.cluster_id, Identify.cluster_id],
+            },
+            3: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [MultistateInputCluster, Identify.cluster_id],
+                OUTPUT_CLUSTERS: [OnOff.cluster_id],
+            },
+            4: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [MultistateInputCluster, Identify.cluster_id],
+                OUTPUT_CLUSTERS: [OnOff.cluster_id],
+            },
+            5: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [MultistateInputCluster, Identify.cluster_id],
+                OUTPUT_CLUSTERS: [OnOff.cluster_id],
+            },
+            6: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT_SWITCH,
+                INPUT_CLUSTERS: [MultistateInputCluster, Identify.cluster_id],
+                OUTPUT_CLUSTERS: [OnOff.cluster_id],
+            },
+        },
     }
+
+    device_automation_triggers = RemoteB686OPCN01.device_automation_triggers
diff --git a/zhaquirks/xiaomi/aqara/plug.py b/zhaquirks/xiaomi/aqara/plug_maus01.py
similarity index 88%
rename from zhaquirks/xiaomi/aqara/plug.py
rename to zhaquirks/xiaomi/aqara/plug_maus01.py
index f11a530..1373d43 100644
--- a/zhaquirks/xiaomi/aqara/plug.py
+++ b/zhaquirks/xiaomi/aqara/plug_maus01.py
@@ -1,4 +1,4 @@
-"""Xiaomi aqara button sensor."""
+"""Xiaomi lumi.plug.maus01 plug."""
 import logging
 
 from zigpy.profiles import zha
@@ -18,7 +18,14 @@ from zigpy.zcl.clusters.general import (
 )
 from zigpy.zcl.clusters.homeautomation import ElectricalMeasurement
 
-from ... import Bus, CustomCluster
+from .. import (
+    LUMI,
+    AnalogInputCluster,
+    BasicCluster,
+    ElectricalMeasurementCluster,
+    XiaomiCustomDevice,
+)
+from ... import Bus
 from ...const import (
     DEVICE_TYPE,
     ENDPOINTS,
@@ -26,36 +33,14 @@ from ...const import (
     MODELS_INFO,
     OUTPUT_CLUSTERS,
     PROFILE_ID,
-)
-from .. import (
-    LUMI,
-    POWER_REPORTED,
-    BasicCluster,
-    ElectricalMeasurementCluster,
-    XiaomiCustomDevice,
+    SKIP_CONFIGURATION,
 )
 
 _LOGGER = logging.getLogger(__name__)
 
 
-class AnalogInputCluster(CustomCluster, AnalogInput):
-    """Analog input cluster."""
-
-    cluster_id = AnalogInput.cluster_id
-
-    def __init__(self, *args, **kwargs):
-        """Init."""
-        self._current_state = {}
-        super().__init__(*args, **kwargs)
-
-    def _update_attribute(self, attrid, value):
-        super()._update_attribute(attrid, value)
-        if value is not None and value >= 0:
-            self.endpoint.device.power_bus.listener_event(POWER_REPORTED, value)
-
-
 class Plug(XiaomiCustomDevice):
-    """lumi.plug.maus01 device."""
+    """lumi.plug.maus01 plug."""
 
     def __init__(self, *args, **kwargs):
         """Init."""
@@ -121,6 +106,7 @@ class Plug(XiaomiCustomDevice):
         },
     }
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 PROFILE_ID: zha.PROFILE_ID,
@@ -157,5 +143,5 @@ class Plug(XiaomiCustomDevice):
                 INPUT_CLUSTERS: [BinaryInput.cluster_id],
                 OUTPUT_CLUSTERS: [BinaryInput.cluster_id, Groups.cluster_id],
             },
-        }
+        },
     }
diff --git a/zhaquirks/xiaomi/aqara/plug_mmeu01.py b/zhaquirks/xiaomi/aqara/plug_mmeu01.py
new file mode 100644
index 0000000..0760231
--- /dev/null
+++ b/zhaquirks/xiaomi/aqara/plug_mmeu01.py
@@ -0,0 +1,120 @@
+"""Xiaomi lumi.plug.mmeu01 plug."""
+import logging
+
+from zigpy.profiles import zha
+from zigpy.zcl.clusters.general import (
+    Alarms,
+    AnalogInput,
+    Basic,
+    DeviceTemperature,
+    GreenPowerProxy,
+    Groups,
+    Identify,
+    OnOff,
+    Ota,
+    Scenes,
+    Time,
+)
+from zigpy.zcl.clusters.homeautomation import ElectricalMeasurement
+from zigpy.zcl.clusters.smartenergy import Metering
+
+from .. import (
+    LUMI,
+    AnalogInputCluster,
+    BasicCluster,
+    ElectricalMeasurementCluster,
+    XiaomiCustomDevice,
+)
+from ... import Bus
+from ...const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+    SKIP_CONFIGURATION,
+)
+
+_LOGGER = logging.getLogger(__name__)
+
+XIAOMI_PROFILE_ID = 0xA1E0
+XIAOMI_DEVICE_TYPE = 0x61
+
+
+class Plug(XiaomiCustomDevice):
+    """lumi.plug.mmeu01 plug."""
+
+    def __init__(self, *args, **kwargs):
+        """Init."""
+        self.voltage_bus = Bus()
+        self.consumption_bus = Bus()
+        self.power_bus = Bus()
+        super().__init__(*args, **kwargs)
+
+    signature = {
+        MODELS_INFO: [(LUMI, "lumi.plug.mmeu01")],
+        ENDPOINTS: {
+            # <SimpleDescriptor endpoint=1 profile=260 device_type=81
+            # device_version=1
+            # input_clusters=[0, 2, 3, 4, 5, 6, 9, 1794, 2820]
+            # output_clusters=[10, 25]>
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
+                INPUT_CLUSTERS: [
+                    Basic.cluster_id,
+                    DeviceTemperature.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                    OnOff.cluster_id,
+                    Alarms.cluster_id,
+                    Metering.cluster_id,
+                    ElectricalMeasurement.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
+            },
+            # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
+            # device_version=0
+            # input_clusters=[]
+            # output_clusters=[33]>
+            242: {
+                PROFILE_ID: XIAOMI_PROFILE_ID,
+                DEVICE_TYPE: XIAOMI_DEVICE_TYPE,
+                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
+            },
+        },
+    }
+    replacement = {
+        SKIP_CONFIGURATION: True,
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
+                INPUT_CLUSTERS: [
+                    BasicCluster,
+                    DeviceTemperature.cluster_id,
+                    Identify.cluster_id,
+                    Groups.cluster_id,
+                    Scenes.cluster_id,
+                    OnOff.cluster_id,
+                    Alarms.cluster_id,
+                    Metering.cluster_id,
+                    ElectricalMeasurementCluster,
+                ],
+                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
+            },
+            21: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.MAIN_POWER_OUTLET,
+                INPUT_CLUSTERS: [AnalogInputCluster],
+                OUTPUT_CLUSTERS: [AnalogInput.cluster_id, Groups.cluster_id],
+            },
+            242: {
+                PROFILE_ID: XIAOMI_PROFILE_ID,
+                DEVICE_TYPE: XIAOMI_DEVICE_TYPE,
+                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
+            },
+        },
+    }
diff --git a/zhaquirks/xiaomi/aqara/relay.py b/zhaquirks/xiaomi/aqara/relay_c2acn01.py
similarity index 85%
rename from zhaquirks/xiaomi/aqara/relay.py
rename to zhaquirks/xiaomi/aqara/relay_c2acn01.py
index af8c17f..4d3eb51 100644
--- a/zhaquirks/xiaomi/aqara/relay.py
+++ b/zhaquirks/xiaomi/aqara/relay_c2acn01.py
@@ -1,4 +1,4 @@
-"""Xiaomi aqara button sensor."""
+"""Xiaomi lumi.relay.c2acn01 relay."""
 import logging
 
 from zigpy.profiles import zha
@@ -17,7 +17,14 @@ from zigpy.zcl.clusters.general import (
 )
 from zigpy.zcl.clusters.homeautomation import ElectricalMeasurement
 
-from ... import Bus, CustomCluster
+from .. import (
+    LUMI,
+    AnalogInputCluster,
+    BasicCluster,
+    ElectricalMeasurementCluster,
+    XiaomiCustomDevice,
+)
+from ... import Bus
 from ...const import (
     DEVICE_TYPE,
     ENDPOINTS,
@@ -25,36 +32,14 @@ from ...const import (
     MODELS_INFO,
     OUTPUT_CLUSTERS,
     PROFILE_ID,
-)
-from .. import (
-    LUMI,
-    POWER_REPORTED,
-    BasicCluster,
-    ElectricalMeasurementCluster,
-    XiaomiCustomDevice,
+    SKIP_CONFIGURATION,
 )
 
 _LOGGER = logging.getLogger(__name__)
 
 
-class AnalogInputCluster(CustomCluster, AnalogInput):
-    """Analog input cluster."""
-
-    cluster_id = AnalogInput.cluster_id
-
-    def __init__(self, *args, **kwargs):
-        """Init."""
-        self._current_state = {}
-        super().__init__(*args, **kwargs)
-
-    def _update_attribute(self, attrid, value):
-        super()._update_attribute(attrid, value)
-        if value is not None and value >= 0:
-            self.endpoint.device.power_bus.listener_event(POWER_REPORTED, value)
-
-
 class Relay(XiaomiCustomDevice):
-    """lumi.plug.maus01 device."""
+    """lumi.relay.c2acn01 relay."""
 
     def __init__(self, *args, **kwargs):
         """Init."""
@@ -106,6 +91,7 @@ class Relay(XiaomiCustomDevice):
         },
     }
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 PROFILE_ID: zha.PROFILE_ID,
@@ -136,5 +122,5 @@ class Relay(XiaomiCustomDevice):
                 ],
                 OUTPUT_CLUSTERS: [],
             },
-        }
+        },
     }
diff --git a/zhaquirks/xiaomi/aqara/remote_b186acn01.py b/zhaquirks/xiaomi/aqara/remote_b186acn01.py
index 1a204f1..d548d9d 100644
--- a/zhaquirks/xiaomi/aqara/remote_b186acn01.py
+++ b/zhaquirks/xiaomi/aqara/remote_b186acn01.py
@@ -8,6 +8,7 @@ from zigpy.zcl.clusters.general import (
     Groups,
     Identify,
     MultistateInput,
+    OnOff,
     Ota,
     Scenes,
 )
@@ -27,6 +28,7 @@ from ...const import (
     PRESS_TYPE,
     PROFILE_ID,
     SHORT_PRESS,
+    SKIP_CONFIGURATION,
     VALUE,
     ZHA_SEND_EVENT,
 )
@@ -66,9 +68,7 @@ class RemoteB186ACN01(XiaomiCustomDevice):
                     ATTR_ID: attrid,
                     VALUE: value,
                 }
-                self.listener_event(
-                    ZHA_SEND_EVENT, self, self._current_state, event_args
-                )
+                self.listener_event(ZHA_SEND_EVENT, self._current_state, event_args)
                 # show something in the sensor in HA
                 super()._update_attribute(0, self._current_state)
 
@@ -136,9 +136,10 @@ class RemoteB186ACN01(XiaomiCustomDevice):
     }
 
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
-                DEVICE_TYPE: XIAOMI_DEVICE_TYPE,
+                DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
                 INPUT_CLUSTERS: [
                     BasicCluster,
                     PowerConfigurationCluster,
@@ -155,10 +156,11 @@ class RemoteB186ACN01(XiaomiCustomDevice):
                     Ota.cluster_id,
                     XIAOMI_CLUSTER_ID,
                     MultistateInputCluster,
+                    OnOff.cluster_id,
                 ],
             },
             2: {
-                DEVICE_TYPE: XIAOMI_DEVICE_TYPE2,
+                DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
                 INPUT_CLUSTERS: [Identify.cluster_id, MultistateInputCluster],
                 OUTPUT_CLUSTERS: [
                     Identify.cluster_id,
@@ -168,7 +170,7 @@ class RemoteB186ACN01(XiaomiCustomDevice):
                 ],
             },
             3: {
-                DEVICE_TYPE: XIAOMI_DEVICE_TYPE3,
+                DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
                 INPUT_CLUSTERS: [Identify.cluster_id, MultistateInputCluster],
                 OUTPUT_CLUSTERS: [
                     Identify.cluster_id,
@@ -178,7 +180,7 @@ class RemoteB186ACN01(XiaomiCustomDevice):
                     MultistateInputCluster,
                 ],
             },
-        }
+        },
     }
 
     device_automation_triggers = {
diff --git a/zhaquirks/xiaomi/aqara/remote_b286acn01.py b/zhaquirks/xiaomi/aqara/remote_b286acn01.py
index 0c3e413..6643ff9 100644
--- a/zhaquirks/xiaomi/aqara/remote_b286acn01.py
+++ b/zhaquirks/xiaomi/aqara/remote_b286acn01.py
@@ -8,6 +8,7 @@ from zigpy.zcl.clusters.general import (
     Groups,
     Identify,
     MultistateInput,
+    OnOff,
     Ota,
     Scenes,
 )
@@ -31,6 +32,7 @@ from ...const import (
     PRESS_TYPE,
     PROFILE_ID,
     SHORT_PRESS,
+    SKIP_CONFIGURATION,
     VALUE,
     ZHA_SEND_EVENT,
 )
@@ -81,7 +83,7 @@ class RemoteB286ACN01(XiaomiCustomDevice):
                     VALUE: value,
                 }
                 action = "{}_{}".format(button, self._current_state)
-                self.listener_event(ZHA_SEND_EVENT, self, action, event_args)
+                self.listener_event(ZHA_SEND_EVENT, action, event_args)
                 # show something in the sensor in HA
                 super()._update_attribute(0, action)
 
@@ -149,9 +151,10 @@ class RemoteB286ACN01(XiaomiCustomDevice):
     }
 
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
-                DEVICE_TYPE: XIAOMI_DEVICE_TYPE,
+                DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
                 INPUT_CLUSTERS: [
                     BasicCluster,
                     PowerConfigurationCluster,
@@ -168,20 +171,22 @@ class RemoteB286ACN01(XiaomiCustomDevice):
                     Ota.cluster_id,
                     XIAOMI_CLUSTER_ID,
                     MultistateInputCluster,
+                    OnOff.cluster_id,
                 ],
             },
             2: {
-                DEVICE_TYPE: XIAOMI_DEVICE_TYPE2,
+                DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
                 INPUT_CLUSTERS: [Identify.cluster_id, MultistateInputCluster],
                 OUTPUT_CLUSTERS: [
                     Identify.cluster_id,
                     Groups.cluster_id,
                     Scenes.cluster_id,
                     MultistateInputCluster,
+                    OnOff.cluster_id,
                 ],
             },
             3: {
-                DEVICE_TYPE: XIAOMI_DEVICE_TYPE3,
+                DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
                 INPUT_CLUSTERS: [Identify.cluster_id, MultistateInputCluster],
                 OUTPUT_CLUSTERS: [
                     Identify.cluster_id,
@@ -189,9 +194,10 @@ class RemoteB286ACN01(XiaomiCustomDevice):
                     Scenes.cluster_id,
                     AnalogInput.cluster_id,
                     MultistateInputCluster,
+                    OnOff.cluster_id,
                 ],
             },
-        }
+        },
     }
 
     device_automation_triggers = {
diff --git a/zhaquirks/xiaomi/aqara/sensor_swit.py b/zhaquirks/xiaomi/aqara/sensor_swit.py
index 0ff0c1d..c58126e 100644
--- a/zhaquirks/xiaomi/aqara/sensor_swit.py
+++ b/zhaquirks/xiaomi/aqara/sensor_swit.py
@@ -24,6 +24,7 @@ from ...const import (
     PROFILE_ID,
     SHAKEN,
     SHORT_PRESS,
+    SKIP_CONFIGURATION,
     VALUE,
     ZHA_SEND_EVENT,
 )
@@ -68,7 +69,7 @@ class SwitchAQ3V2(XiaomiCustomDevice):
                 )
                 event_args = {VALUE: value}
                 if action is not None:
-                    self.listener_event(ZHA_SEND_EVENT, self, action, event_args)
+                    self.listener_event(ZHA_SEND_EVENT, action, event_args)
 
                 # show something in the sensor in HA
                 super()._update_attribute(0, action)
@@ -94,6 +95,7 @@ class SwitchAQ3V2(XiaomiCustomDevice):
         },
     }
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
@@ -104,7 +106,7 @@ class SwitchAQ3V2(XiaomiCustomDevice):
                 ],
                 OUTPUT_CLUSTERS: [Basic.cluster_id, OnOff.cluster_id],
             }
-        }
+        },
     }
 
     device_automation_triggers = {
diff --git a/zhaquirks/xiaomi/aqara/sensor_switch_aq3.py b/zhaquirks/xiaomi/aqara/sensor_switch_aq3.py
index 6bc02a4..f7cf976 100644
--- a/zhaquirks/xiaomi/aqara/sensor_switch_aq3.py
+++ b/zhaquirks/xiaomi/aqara/sensor_switch_aq3.py
@@ -2,7 +2,7 @@
 import logging
 
 from zigpy.profiles import zha
-from zigpy.zcl.clusters.general import Basic, MultistateInput, OnOff, Identify
+from zigpy.zcl.clusters.general import Basic, Identify, MultistateInput, OnOff
 
 from .. import LUMI, BasicCluster, PowerConfigurationCluster, XiaomiCustomDevice
 from ... import CustomCluster
@@ -24,6 +24,7 @@ from ...const import (
     PROFILE_ID,
     SHAKEN,
     SHORT_PRESS,
+    SKIP_CONFIGURATION,
     VALUE,
     ZHA_SEND_EVENT,
 )
@@ -68,7 +69,7 @@ class MultistateInputCluster(CustomCluster, MultistateInput):
             self._current_state[STATUS_TYPE_ATTR] = action = MOVEMENT_TYPE.get(value)
             event_args = {VALUE: value}
             if action is not None:
-                self.listener_event(ZHA_SEND_EVENT, self, action, event_args)
+                self.listener_event(ZHA_SEND_EVENT, action, event_args)
 
             # show something in the sensor in HA
             super()._update_attribute(0, action)
@@ -98,6 +99,7 @@ class SwitchAQ3(XiaomiCustomDevice):
         },
     }
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
@@ -108,7 +110,7 @@ class SwitchAQ3(XiaomiCustomDevice):
                 ],
                 OUTPUT_CLUSTERS: [Basic.cluster_id, OnOff.cluster_id],
             }
-        }
+        },
     }
 
     device_automation_triggers = {
@@ -143,6 +145,7 @@ class SwitchAQ3B(XiaomiCustomDevice):
         },
     }
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
@@ -153,7 +156,7 @@ class SwitchAQ3B(XiaomiCustomDevice):
                 ],
                 OUTPUT_CLUSTERS: [Basic.cluster_id],
             }
-        }
+        },
     }
 
     device_automation_triggers = SwitchAQ3.device_automation_triggers
diff --git a/zhaquirks/xiaomi/aqara/switch_aq2.py b/zhaquirks/xiaomi/aqara/switch_aq2.py
index 6cb8842..87dd2c3 100644
--- a/zhaquirks/xiaomi/aqara/switch_aq2.py
+++ b/zhaquirks/xiaomi/aqara/switch_aq2.py
@@ -22,6 +22,7 @@ from ...const import (
     OUTPUT_CLUSTERS,
     PROFILE_ID,
     SHORT_PRESS,
+    SKIP_CONFIGURATION,
     TRIPLE_PRESS,
     UNKNOWN,
     VALUE,
@@ -58,6 +59,7 @@ class SwitchAQ2(XiaomiCustomDevice):
     }
 
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
@@ -73,7 +75,7 @@ class SwitchAQ2(XiaomiCustomDevice):
                     OnOff.cluster_id,
                 ],
             }
-        }
+        },
     }
 
     device_automation_triggers = {
diff --git a/zhaquirks/xiaomi/aqara/vibration_aq1.py b/zhaquirks/xiaomi/aqara/vibration_aq1.py
index 2490424..333dc89 100644
--- a/zhaquirks/xiaomi/aqara/vibration_aq1.py
+++ b/zhaquirks/xiaomi/aqara/vibration_aq1.py
@@ -31,6 +31,7 @@ from ...const import (
     MOTION_EVENT,
     OUTPUT_CLUSTERS,
     PROFILE_ID,
+    SKIP_CONFIGURATION,
     UNKNOWN,
     ZHA_SEND_EVENT,
 )
@@ -143,7 +144,7 @@ class VibrationAQ1(XiaomiCustomDevice):
 
         def send_event(self, event, *args):
             """Send event."""
-            self.listener_event(ZHA_SEND_EVENT, self, event, args)
+            self.listener_event(ZHA_SEND_EVENT, event, args)
 
         def _turn_off(self):
             self._timer_handle = None
@@ -186,6 +187,7 @@ class VibrationAQ1(XiaomiCustomDevice):
     }
 
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 DEVICE_TYPE: zha.DeviceType.DOOR_LOCK,
@@ -215,7 +217,7 @@ class VibrationAQ1(XiaomiCustomDevice):
                     MultistateInput.cluster_id,
                 ],
             },
-        }
+        },
     }
 
     device_automation_triggers = {
diff --git a/zhaquirks/xiaomi/aqara/weather.py b/zhaquirks/xiaomi/aqara/weather.py
index 8bdff84..1551d7e 100644
--- a/zhaquirks/xiaomi/aqara/weather.py
+++ b/zhaquirks/xiaomi/aqara/weather.py
@@ -22,6 +22,7 @@ from ...const import (
     MODELS_INFO,
     OUTPUT_CLUSTERS,
     PROFILE_ID,
+    SKIP_CONFIGURATION,
 )
 
 TEMPERATURE_HUMIDITY_DEVICE_TYPE = 0x5F01
@@ -68,6 +69,7 @@ class Weather(XiaomiCustomDevice):
     }
 
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 INPUT_CLUSTERS: [
@@ -85,5 +87,36 @@ class Weather(XiaomiCustomDevice):
                     XIAOMI_CLUSTER_ID,
                 ],
             }
-        }
+        },
+    }
+
+
+class Weather2(Weather):
+    """New Xiaomi weather sensor device."""
+
+    signature = {
+        #  <SimpleDescriptor endpoint=1 profile=260 device_type=24321
+        #  device_version=1
+        #  input_clusters=[0, 3, 65535, 1026, 1027, 1029]
+        #  output_clusters=[0, 4, 65535]>
+        MODELS_INFO: [(LUMI, "lumi.weather")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,
+                INPUT_CLUSTERS: [
+                    BasicCluster.cluster_id,
+                    Identify.cluster_id,
+                    TemperatureMeasurementCluster.cluster_id,
+                    PressureMeasurement.cluster_id,
+                    RelativeHumidityCluster.cluster_id,
+                    XIAOMI_CLUSTER_ID,
+                ],
+                OUTPUT_CLUSTERS: [
+                    BasicCluster.cluster_id,
+                    Groups.cluster_id,
+                    XIAOMI_CLUSTER_ID,
+                ],
+            }
+        },
     }
diff --git a/zhaquirks/xiaomi/aqara/wleak_aq1.py b/zhaquirks/xiaomi/aqara/wleak_aq1.py
index 8d1f8aa..c8f67fe 100644
--- a/zhaquirks/xiaomi/aqara/wleak_aq1.py
+++ b/zhaquirks/xiaomi/aqara/wleak_aq1.py
@@ -11,6 +11,7 @@ from ...const import (
     MODELS_INFO,
     OUTPUT_CLUSTERS,
     PROFILE_ID,
+    SKIP_CONFIGURATION,
 )
 from .. import LUMI, BasicCluster, PowerConfigurationCluster, XiaomiCustomDevice
 
@@ -51,6 +52,7 @@ class LeakAQ1(XiaomiCustomDevice):
         },
     }
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 INPUT_CLUSTERS: [
@@ -61,5 +63,5 @@ class LeakAQ1(XiaomiCustomDevice):
                 ],
                 OUTPUT_CLUSTERS: [Ota.cluster_id],
             }
-        }
+        },
     }
diff --git a/zhaquirks/xiaomi/mija/motion.py b/zhaquirks/xiaomi/mija/motion.py
index a509bd8..afd9580 100644
--- a/zhaquirks/xiaomi/mija/motion.py
+++ b/zhaquirks/xiaomi/mija/motion.py
@@ -28,6 +28,7 @@ from ...const import (
     MODELS_INFO,
     OUTPUT_CLUSTERS,
     PROFILE_ID,
+    SKIP_CONFIGURATION,
 )
 
 XIAOMI_CLUSTER_ID = 0xFFFF
@@ -74,6 +75,7 @@ class Motion(XiaomiCustomDevice):
     }
 
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
@@ -93,5 +95,5 @@ class Motion(XiaomiCustomDevice):
                     Ota.cluster_id,
                 ],
             }
-        }
+        },
     }
diff --git a/zhaquirks/xiaomi/mija/sensor_ht.py b/zhaquirks/xiaomi/mija/sensor_ht.py
index 67f4366..2422856 100644
--- a/zhaquirks/xiaomi/mija/sensor_ht.py
+++ b/zhaquirks/xiaomi/mija/sensor_ht.py
@@ -27,6 +27,7 @@ from ...const import (
     MODELS_INFO,
     OUTPUT_CLUSTERS,
     PROFILE_ID,
+    SKIP_CONFIGURATION,
 )
 
 TEMPERATURE_HUMIDITY_DEVICE_TYPE = 0x5F01
@@ -107,6 +108,7 @@ class Weather(XiaomiCustomDevice):
     }
 
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 DEVICE_TYPE: TEMPERATURE_HUMIDITY_DEVICE_TYPE2,
@@ -153,5 +155,5 @@ class Weather(XiaomiCustomDevice):
                     AnalogInput.cluster_id,
                 ],
             },
-        }
+        },
     }
diff --git a/zhaquirks/xiaomi/mija/sensor_magnet.py b/zhaquirks/xiaomi/mija/sensor_magnet.py
index 7bf6526..2b8b6b3 100644
--- a/zhaquirks/xiaomi/mija/sensor_magnet.py
+++ b/zhaquirks/xiaomi/mija/sensor_magnet.py
@@ -11,7 +11,6 @@ from zigpy.zcl.clusters.general import (
     Scenes,
 )
 
-from .. import LUMI, BasicCluster, PowerConfigurationCluster, XiaomiCustomDevice
 from ...const import (
     DEVICE_TYPE,
     ENDPOINTS,
@@ -19,7 +18,9 @@ from ...const import (
     MODELS_INFO,
     OUTPUT_CLUSTERS,
     PROFILE_ID,
+    SKIP_CONFIGURATION,
 )
+from .. import LUMI, BasicCluster, PowerConfigurationCluster, XiaomiCustomDevice
 
 OPEN_CLOSE_DEVICE_TYPE = 0x5F01
 XIAOMI_CLUSTER_ID = 0xFFFF
@@ -65,6 +66,7 @@ class Magnet(XiaomiCustomDevice):
     }
 
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 DEVICE_TYPE: zha.DeviceType.ON_OFF_SENSOR,
@@ -85,5 +87,5 @@ class Magnet(XiaomiCustomDevice):
                     Ota.cluster_id,
                 ],
             }
-        }
+        },
     }
diff --git a/zhaquirks/xiaomi/mija/sensor_switch.py b/zhaquirks/xiaomi/mija/sensor_switch.py
index ae73dd5..35d42be 100644
--- a/zhaquirks/xiaomi/mija/sensor_switch.py
+++ b/zhaquirks/xiaomi/mija/sensor_switch.py
@@ -34,6 +34,7 @@ from ...const import (
     QUADRUPLE_PRESS,
     QUINTUPLE_PRESS,
     SHORT_PRESS,
+    SKIP_CONFIGURATION,
     TRIPLE_PRESS,
     UNKNOWN,
     ZHA_SEND_EVENT,
@@ -83,7 +84,7 @@ class MijaButton(XiaomiCustomDevice):
 
             if click_type:
                 self.listener_event(
-                    ZHA_SEND_EVENT, self, COMMAND_CLICK, {CLICK_TYPE: click_type}
+                    ZHA_SEND_EVENT, COMMAND_CLICK, {CLICK_TYPE: click_type}
                 )
 
             super()._update_attribute(attrid, value)
@@ -129,6 +130,7 @@ class MijaButton(XiaomiCustomDevice):
     }
 
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
@@ -146,7 +148,7 @@ class MijaButton(XiaomiCustomDevice):
                     Ota.cluster_id,
                 ],
             }
-        }
+        },
     }
 
     device_automation_triggers = {
diff --git a/zhaquirks/xiaomi/mija/smoke.py b/zhaquirks/xiaomi/mija/smoke.py
index 4f3a4fc..81f9d67 100644
--- a/zhaquirks/xiaomi/mija/smoke.py
+++ b/zhaquirks/xiaomi/mija/smoke.py
@@ -27,7 +27,14 @@ from zigpy.zcl.clusters.security import IasZone
 
 from .. import BasicCluster, PowerConfigurationCluster, XiaomiCustomDevice
 from ... import CustomCluster
-from ...const import DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, OUTPUT_CLUSTERS, PROFILE_ID
+from ...const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+    SKIP_CONFIGURATION,
+)
 
 IAS_ZONE = 0x0402
 
@@ -75,6 +82,7 @@ class MijiaHoneywellSmokeDetectorSensor(XiaomiCustomDevice):
     }
 
     replacement = {
+        SKIP_CONFIGURATION: True,
         ENDPOINTS: {
             1: {
                 INPUT_CLUSTERS: [
@@ -87,5 +95,5 @@ class MijiaHoneywellSmokeDetectorSensor(XiaomiCustomDevice):
                 ],
                 OUTPUT_CLUSTERS: [Ota.cluster_id],
             }
-        }
+        },
     }
diff --git a/zhaquirks/zen/__init__.py b/zhaquirks/zen/__init__.py
new file mode 100644
index 0000000..2ed7478
--- /dev/null
+++ b/zhaquirks/zen/__init__.py
@@ -0,0 +1,12 @@
+"""Module for Zen Within quirks implementations."""
+
+from .. import PowerConfigurationCluster
+
+ZEN = "Zen Within"
+
+
+class ZenPowerConfiguration(PowerConfigurationCluster):
+    """Common use power configuration cluster."""
+
+    MIN_VOLTS = 3.6
+    MAX_VOLTS = 6.0
diff --git a/zhaquirks/zen/thermostat.py b/zhaquirks/zen/thermostat.py
new file mode 100644
index 0000000..c5fc508
--- /dev/null
+++ b/zhaquirks/zen/thermostat.py
@@ -0,0 +1,69 @@
+"""This module handles quirks of the  Zen Within thermostat."""
+
+import zigpy.profiles.zha as zha_p
+from zigpy.quirks import CustomDevice
+from zigpy.zcl.clusters import general, homeautomation, hvac
+
+from . import ZEN, ZenPowerConfiguration
+from ..const import (
+    DEVICE_TYPE,
+    ENDPOINTS,
+    INPUT_CLUSTERS,
+    MODELS_INFO,
+    OUTPUT_CLUSTERS,
+    PROFILE_ID,
+)
+
+
+class ZenThermostat(CustomDevice):
+    """Zen Within Thermostat custom device."""
+
+    signature = {
+        # Node Descriptor: <Optional byte1=2 byte2=64 mac_capability_flags=128
+        # manufacturer_code=4440 maximum_buffer_size=82
+        # maximum_incoming_transfer_size=128 server_mask=0
+        # maximum_outgoing_transfer_size=128 descriptor_capability_field=0>
+        # <SimpleDescriptor endpoint=1 profile=260 device_type=769 device_version=0
+        # input_clusters=[0, 1, 3, 4, 5, 32, 513, 514, 516, 2821]
+        # output_clusters=[10, 25]>
+        MODELS_INFO: [(ZEN, "Zen-01")],
+        ENDPOINTS: {
+            1: {
+                PROFILE_ID: zha_p.PROFILE_ID,
+                DEVICE_TYPE: zha_p.DeviceType.THERMOSTAT,
+                INPUT_CLUSTERS: [
+                    general.Basic.cluster_id,
+                    general.PowerConfiguration.cluster_id,
+                    general.Identify.cluster_id,
+                    general.Groups.cluster_id,
+                    general.Scenes.cluster_id,
+                    general.PollControl.cluster_id,
+                    hvac.Thermostat.cluster_id,
+                    hvac.Fan.cluster_id,
+                    hvac.UserInterface.cluster_id,
+                    homeautomation.Diagnostic.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [general.Time.cluster_id, general.Ota.cluster_id],
+            }
+        },
+    }
+
+    replacement = {
+        ENDPOINTS: {
+            1: {
+                INPUT_CLUSTERS: [
+                    general.Basic.cluster_id,
+                    ZenPowerConfiguration,
+                    general.Identify.cluster_id,
+                    general.Groups.cluster_id,
+                    general.Scenes.cluster_id,
+                    general.PollControl.cluster_id,
+                    hvac.Thermostat.cluster_id,
+                    hvac.Fan.cluster_id,
+                    hvac.UserInterface.cluster_id,
+                    homeautomation.Diagnostic.cluster_id,
+                ],
+                OUTPUT_CLUSTERS: [general.Time.cluster_id, general.Ota.cluster_id],
+            }
+        }
+    }


Test patch:
diff --git a/requirements_test_all.txt b/requirements_test_all.txt
index 255312c..e717df4 100644
--- a/requirements_test_all.txt
+++ b/requirements_test_all.txt
@@ -20,5 +20,5 @@ pytest-timeout==1.3.3
 pytest==5.1.2
 requests_mock==1.6.0
 
-zigpy-homeassistant==0.8.0
+zigpy-homeassistant==0.18.1
 homeassistant
diff --git a/tests/test_ctrl_neutral1.py b/tests/test_ctrl_neutral1.py
new file mode 100644
index 0000000..96436bd
--- /dev/null
+++ b/tests/test_ctrl_neutral1.py
@@ -0,0 +1,53 @@
+"""Tests for xiaomi."""
+from unittest import mock
+from unittest.mock import call
+
+import zigpy.application
+from zigpy.device import Device
+
+from zhaquirks.xiaomi.aqara.ctrl_neutral import CtrlNeutral
+
+
+# zigbee-herdsman:controller:endpoint Command 0x00158d00024be541/2 genOnOff.on({},
+#   {"timeout":6000,"manufacturerCode":null,"disableDefaultResponse":false})
+# zigbee-herdsman:adapter:zStack:znp:SREQ --> AF - dataRequest -
+#   {"dstaddr":65311,"destendpoint":2,"srcendpoint":1,"clusterid":6,"transid":17,"options":0,"radius":30,"len":3,
+#       "data":{"type":"Buffer","data":[1,8,1]}}
+# zigbee-herdsman:adapter:zStack:unpi:writer -->frame [254,13,36,1,31,255,2,1,6,0,17,0,30,3,1,8,1,201]
+
+
+# zigbee-herdsman:controller:endpoint Command 0x00158d00024be541/2 genOnOff.off({},
+#   {"timeout":6000,"manufacturerCode":null,"disableDefaultResponse":false})
+# zigbee-herdsman:adapter:zStack:znp:SREQ --> AF - dataRequest -
+#   {"dstaddr":65311,"destendpoint":2,"srcendpoint":1,"clusterid":6,"transid":16,"options":0,"radius":30,"len":3,
+#       "data":{"type":"Buffer","data":[1,7,0]}}
+# zigbee-herdsman:adapter:zStack:unpi:writer --> frame [254,13,36,1,31,255,2,1,6,0,16,0,30,3,1,7,0,198]
+
+
+def test_ctrl_neutral():
+    """Test ctrl neutral 1 sends correct request."""
+    sec = 8
+    ieee = 0
+    nwk = 1234
+    data = b"\x01\x08\x01"
+    cluster = 6
+    src_ep = 1
+    dst_ep = 2
+
+    app = zigpy.application.ControllerApplication()
+    app.request = mock.MagicMock()
+    app.get_sequence = mock.MagicMock(return_value=sec)
+
+    rep = Device(app, ieee, nwk)
+    rep.add_endpoint(1)
+    rep.add_endpoint(2)
+    rep.add_endpoint(3)
+
+    dev = CtrlNeutral(app, ieee, nwk, rep)
+    dev.request = mock.MagicMock()
+
+    dev[2].in_clusters[cluster].command(1)
+
+    assert dev.request.call_args == call(
+        260, cluster, src_ep, dst_ep, sec, data, expect_reply=True
+    )