diff --git a/platypush/entities/_managers/switches.py b/platypush/entities/_managers/switches.py
index eef80f0f7..ff3c7364a 100644
--- a/platypush/entities/_managers/switches.py
+++ b/platypush/entities/_managers/switches.py
@@ -1,9 +1,30 @@
 from abc import ABC, abstractmethod
+from typing import Any, Optional
+from typing_extensions import override
 
 from . import EntityManager
 
 
-class SwitchEntityManager(EntityManager, ABC):
+class WriteableEntityManager(EntityManager, ABC):
+    """
+    Base class for integrations that support entities whose values can be set.
+    """
+
+    @abstractmethod
+    def set(self, entity: str, value: Any, attribute: Optional[str] = None, **kwargs):
+        """
+        Set the value of an entity.
+
+        :param entity: The entity to set the value for. It's usually the ID of
+            the entity provided by the plugin.
+        :param value: The value to set the entity to.
+        :param attribute: The name of the attribute to set for the entity, if
+            required by the integration.
+        """
+        raise NotImplementedError()
+
+
+class SwitchEntityManager(WriteableEntityManager, ABC):
     """
     Base class for integrations that support binary switches.
     """
@@ -23,31 +44,19 @@ class SwitchEntityManager(EntityManager, ABC):
         """Toggle the state of a device (on->off or off->on)"""
         raise NotImplementedError()
 
-
-class MultiLevelSwitchEntityManager(EntityManager, ABC):
-    """
-    Base class for integrations that support dimmers/multi-level/enum switches.
-
-    Don't extend this class directly. Instead, use on of the available
-    intermediate abstract classes - like ``DimmerEntityManager`` or
-    ``EnumSwitchEntityManager``.
-    """
-
-    @abstractmethod
-    def set_value(  # pylint: disable=redefined-builtin
-        self, device=None, property=None, *, data=None, **__
-    ):
-        """Set a value"""
-        raise NotImplementedError()
+    @override
+    def set(self, entity: str, value: Any, attribute: Optional[str] = None, **kwargs):
+        method = self.on if value else self.off
+        return method(entity, **kwargs)
 
 
-class DimmerEntityManager(MultiLevelSwitchEntityManager, ABC):
+class DimmerEntityManager(WriteableEntityManager, ABC):
     """
     Base class for integrations that support dimmers/multi-level switches.
     """
 
 
-class EnumSwitchEntityManager(MultiLevelSwitchEntityManager, ABC):
+class EnumSwitchEntityManager(WriteableEntityManager, ABC):
     """
     Base class for integrations that support switches with a pre-defined,
     enum-like set of possible values.
diff --git a/platypush/message/event/bluetooth/ble.py b/platypush/message/event/bluetooth/ble.py
index 5289e6b95..ba3df9873 100644
--- a/platypush/message/event/bluetooth/ble.py
+++ b/platypush/message/event/bluetooth/ble.py
@@ -36,6 +36,7 @@ class BluetoothEvent(Event):
             connected=connected,
             paired=paired,
             blocked=blocked,
+            trusted=trusted,
             service_uuids=service_uuids or [],
             **kwargs
         )
diff --git a/platypush/plugins/smartthings/__init__.py b/platypush/plugins/smartthings/__init__.py
index 3c7dd867e..f92ec91cc 100644
--- a/platypush/plugins/smartthings/__init__.py
+++ b/platypush/plugins/smartthings/__init__.py
@@ -33,6 +33,7 @@ from platypush.utils import camel_case_to_snake_case
 from ._mappers import DeviceMapper, device_mappers
 
 
+# pylint: disable=too-many-ancestors
 class SmartthingsPlugin(
     RunnablePlugin,
     DimmerEntityManager,
@@ -817,18 +818,18 @@ class SmartthingsPlugin(
 
         :param device: Device ID or name.
         :param level: Level, usually a percentage value between 0 and 1.
-        :param kwarsg: Extra arguments that should be passed to :meth:`.execute`.
+        :param kwargs: Extra arguments that should be passed to :meth:`.execute`.
         """
         return self.set_value(device, Capability.switch_level, level, **kwargs)
 
     def _set_value(  # pylint: disable=redefined-builtin
-        self, device: str, property: Optional[str] = None, data=None, **kwargs
+        self, device: str, property: Optional[str] = None, value: Any = None, **kwargs
     ):
         if not property:
             device, property = self._to_device_and_property(device)
 
         assert property, 'No property name specified'
-        assert data is not None, 'No value specified'
+        assert value is not None, 'No value specified'
         entity_id = f'{device}:{property}'
         entity = self._entities_by_id.get(entity_id)
         assert entity, f'No such entity ID: {entity_id}'
@@ -837,13 +838,15 @@ class SmartthingsPlugin(
             iter([m for m in device_mappers if m.attribute == property]), None
         )
 
-        assert mapper, f'No mappers found to set {property}={data} on device "{device}"'
+        assert (
+            mapper
+        ), f'No mappers found to set {property}={value} on device "{device}"'
         assert (
             mapper.set_command
         ), f'The property "{property}" on the device "{device}" cannot be set'
 
         command = (
-            mapper.set_command(data)
+            mapper.set_command(value)
             if callable(mapper.set_command)
             else mapper.set_command
         )
@@ -852,16 +855,20 @@ class SmartthingsPlugin(
             device,
             mapper.capability,
             command,
-            args=mapper.set_value_args(data),  # type: ignore
+            args=mapper.set_value_args(value),  # type: ignore
             **kwargs,
         )
 
         return self.status(device)
 
     @action
-    # pylint: disable=redefined-builtin,arguments-differ
-    def set_value(
-        self, device: str, *_, property: Optional[str] = None, data=None, **kwargs
+    def set(self, entity: str, value: Any, attribute: Optional[str] = None, **kwargs):
+        super().set(entity, value, attribute, **kwargs)
+        return self.set_value(entity, property=attribute, value=value, **kwargs)
+
+    @action
+    def set_value(  # pylint: disable=redefined-builtin
+        self, device: str, property: Optional[str] = None, value=None, **kwargs
     ):
         """
         Set the value of a device. It is compatible with the generic
@@ -871,10 +878,11 @@ class SmartthingsPlugin(
             ``device_id:property``.
         :param property: Name of the property to be set. If not specified here
             then it should be specified on the ``device`` level.
-        :param data: Value to be set.
+        :param value: Value to set.
         """
+        assert device, 'No device specified'
         try:
-            return self._set_value(device, property, data, **kwargs)
+            return self._set_value(device, property, value, **kwargs)
         except Exception as e:
             self.logger.exception(e)
             raise AssertionError(e) from e
diff --git a/platypush/plugins/switchbot/__init__.py b/platypush/plugins/switchbot/__init__.py
index 54ad171c5..5d750fe4b 100644
--- a/platypush/plugins/switchbot/__init__.py
+++ b/platypush/plugins/switchbot/__init__.py
@@ -1104,10 +1104,21 @@ class SwitchbotPlugin(
         return self._run('post', 'scenes', scenes[0]['id'], 'execute')
 
     @action
-    # pylint: disable=redefined-builtin,arguments-differ
-    def set_value(self, device: str, *_, property=None, data=None, **__):
+    # pylint: disable=redefined-builtin
+    def set_value(
+        self, device: str, property: Optional[str] = None, value: Any = None, **__
+    ):
+        """
+        Set the value of a property of a device.
+
+        :param device: Device name or ID, or entity (external) ID.
+        :param property: Property to set. It should be present if you are
+            passing a root device ID to ``device`` and not an atomic entity in
+            the format ``<device_id>:<property_name>``.
+        :param value: Value to set.
+        """
         entity = self._to_entity(device, property)
-        assert entity, f'No such entity: "{device}"'
+        assert entity, f'No such device: "{device}"'
 
         dt = entity.data.get('device_type')
         assert dt, f'Could not infer the device type for "{device}"'
@@ -1117,7 +1128,11 @@ class SwitchbotPlugin(
         assert setter_class, f'No setters found for device type "{device_type}"'
 
         setter = setter_class(entity)
-        return setter(property=property, value=data)
+        return setter(property=property, value=value)
+
+    @action
+    def set(self, entity: str, value: Any, attribute: Optional[str] = None, **kwargs):
+        return self.set_value(entity, property=attribute, value=value, **kwargs)
 
     def _to_entity(
         self,
diff --git a/platypush/plugins/switchbot/bluetooth/__init__.py b/platypush/plugins/switchbot/bluetooth/__init__.py
index 353a59f23..cf8caaf48 100644
--- a/platypush/plugins/switchbot/bluetooth/__init__.py
+++ b/platypush/plugins/switchbot/bluetooth/__init__.py
@@ -1,5 +1,5 @@
 import enum
-from typing import Collection
+from typing import Any, Collection, Optional
 from uuid import UUID
 
 from bleak.backends.device import BLEDevice
@@ -98,28 +98,32 @@ class SwitchbotBluetoothPlugin(BluetoothBlePlugin, EnumSwitchEntityManager):
         loop = get_or_create_event_loop()
         return loop.run_until_complete(self._run(device, Command.OFF))
 
-    @override
     @action
-    def set_value(self, device: str, *_, data: str, **__):
+    def set_value(self, device: Optional[str] = None, value: Optional[str] = None, **_):
         """
-        Entity-compatible ``set_value`` method to send a command to a device.
+        Send a command to a device as a value.
 
-        :param device: Device name or address
-        :param data: Command to send. Possible values are:
+        :param entity: Device name or address
+        :param value: Command to send. Possible values are:
 
             - ``on``: Press the button and remain in the pressed state.
             - ``off``: Release a previously pressed button.
             - ``press``: Press and release the button.
 
         """
-        if data == 'on':
+        assert device, 'No device specified'
+        if value == 'on':
             self.on(device)
-        if data == 'off':
+        if value == 'off':
             self.off(device)
-        if data == 'press':
+        if value == 'press':
             self.press(device)
 
-        self.logger.warning('Unknown command for SwitchBot "%s": "%s"', device, data)
+        self.logger.warning('Unknown command for SwitchBot "%s": "%s"', device, value)
+
+    @override
+    def set(self, entity: str, value: Any, attribute: Optional[str] = None, **kwargs):
+        return self.set_value(entity, value, **kwargs)
 
     @override
     def transform_entities(
diff --git a/platypush/plugins/zigbee/mqtt/__init__.py b/platypush/plugins/zigbee/mqtt/__init__.py
index 2094cde13..74505bb76 100644
--- a/platypush/plugins/zigbee/mqtt/__init__.py
+++ b/platypush/plugins/zigbee/mqtt/__init__.py
@@ -13,6 +13,7 @@ from typing import (
     Type,
     Union,
 )
+from typing_extensions import override
 
 from platypush.entities import (
     DimmerEntityManager,
@@ -48,6 +49,7 @@ from platypush.plugins import RunnablePlugin
 from platypush.plugins.mqtt import MqttPlugin, action
 
 
+# pylint: disable=too-many-ancestors
 class ZigbeeMqttPlugin(
     RunnablePlugin,
     MqttPlugin,
@@ -56,7 +58,7 @@ class ZigbeeMqttPlugin(
     LightEntityManager,
     SensorEntityManager,
     SwitchEntityManager,
-):  # lgtm [py/missing-call-to-init]
+):
     """
     This plugin allows you to interact with Zigbee devices over MQTT through any Zigbee sniffer and
     `zigbee2mqtt <https://www.zigbee2mqtt.io/>`_.
@@ -616,7 +618,6 @@ class ZigbeeMqttPlugin(
                                     "genLevelCtrl",
                                     "touchlink",
                                     "lightingColorCtrl",
-                                    "manuSpecificUbisysDimmerSetup"
                                 ],
                                 "output": [
                                     "genOta"
@@ -925,7 +926,7 @@ class ZigbeeMqttPlugin(
         if not exposes:
             return {}
 
-        # If the device has no queriable properties, don't specify a reply
+        # If the device has no queryable properties, don't specify a reply
         # topic to listen on
         req = self._build_device_get_request(exposes)
         reply_topic = self._topic(device)
@@ -1072,9 +1073,9 @@ class ZigbeeMqttPlugin(
         return properties
 
     @action
-    # pylint: disable=redefined-builtin,arguments-differ
+    # pylint: disable=redefined-builtin
     def set_value(
-        self, device: str, *_, property: Optional[str] = None, data=None, **kwargs
+        self, device: str, property: Optional[str] = None, data=None, **kwargs
     ):
         """
         Entity-compatible way of setting a value on a node.
@@ -1094,6 +1095,11 @@ class ZigbeeMqttPlugin(
 
         self.device_set(dev, property, data, **kwargs)
 
+    @override
+    @action
+    def set(self, entity: str, value: Any, attribute: Optional[str] = None, **kwargs):
+        return self.set_value(entity, data=value, property=attribute, **kwargs)
+
     @action
     def device_check_ota_updates(self, device: str, **kwargs) -> dict:
         """
@@ -1578,13 +1584,13 @@ class ZigbeeMqttPlugin(
         assert device_info, f'No such device: {name}'
         name = self._preferred_name(device_info)
 
-        prop = self._get_properties(device_info).get(prop)
+        prop_info = self._get_properties(device_info).get(prop)
         option = self._get_options(device_info).get(prop)
         if option:
             return name, option
 
-        assert prop, f'No such property on device {name}: {prop}'
-        return name, prop
+        assert prop_info, f'No such property on device {name}: {prop}'
+        return name, prop_info
 
     @staticmethod
     def _is_read_only(feature: dict) -> bool:
diff --git a/platypush/plugins/zwave/_base.py b/platypush/plugins/zwave/_base.py
index cdcc3705e..0bd3e80a3 100644
--- a/platypush/plugins/zwave/_base.py
+++ b/platypush/plugins/zwave/_base.py
@@ -325,7 +325,7 @@ class ZwaveBasePlugin(
 
     @abstractmethod
     @action
-    def set_value(  # pylint: disable=arguments-differ
+    def set_value(
         self,
         data,
         value_id: Optional[int] = None,
@@ -347,6 +347,12 @@ class ZwaveBasePlugin(
         """
         raise NotImplementedError
 
+    @action
+    def set(self, entity: str, value: Any, attribute: Optional[str] = None, **kwargs):
+        return self.set_value(
+            value_id=entity, id_on_network=entity, data=value, **kwargs
+        )
+
     @abstractmethod
     @action
     def set_value_label(