diff --git a/homeassistant/components/shelly/binary_sensor.py b/homeassistant/components/shelly/binary_sensor.py
index bdbf5904b15ae69fb0158a7fee54858a69563e53..bc2ba3326a7773419d08216831b71b8c82227d71 100644
--- a/homeassistant/components/shelly/binary_sensor.py
+++ b/homeassistant/components/shelly/binary_sensor.py
@@ -8,6 +8,7 @@ from typing import Final, cast
 from aioshelly.const import RPC_GENERATIONS
 
 from homeassistant.components.binary_sensor import (
+    DOMAIN as BINARY_SENSOR_PLATFORM,
     BinarySensorDeviceClass,
     BinarySensorEntity,
     BinarySensorEntityDescription,
@@ -33,7 +34,9 @@ from .entity import (
     async_setup_entry_rpc,
 )
 from .utils import (
+    async_remove_orphaned_virtual_entities,
     get_device_entry_gen,
+    get_virtual_component_ids,
     is_block_momentary_input,
     is_rpc_momentary_input,
 )
@@ -215,6 +218,11 @@ RPC_SENSORS: Final = {
         entity_registry_enabled_default=False,
         entity_category=EntityCategory.DIAGNOSTIC,
     ),
+    "boolean": RpcBinarySensorDescription(
+        key="boolean",
+        sub_key="value",
+        has_entity_name=True,
+    ),
 }
 
 
@@ -234,9 +242,26 @@ async def async_setup_entry(
                 RpcSleepingBinarySensor,
             )
         else:
+            coordinator = config_entry.runtime_data.rpc
+            assert coordinator
+
             async_setup_entry_rpc(
                 hass, config_entry, async_add_entities, RPC_SENSORS, RpcBinarySensor
             )
+
+            # the user can remove virtual components from the device configuration, so
+            # we need to remove orphaned entities
+            virtual_binary_sensor_ids = get_virtual_component_ids(
+                coordinator.device.config, BINARY_SENSOR_PLATFORM
+            )
+            async_remove_orphaned_virtual_entities(
+                hass,
+                config_entry.entry_id,
+                coordinator.mac,
+                BINARY_SENSOR_PLATFORM,
+                "boolean",
+                virtual_binary_sensor_ids,
+            )
         return
 
     if config_entry.data[CONF_SLEEP_PERIOD]:
diff --git a/homeassistant/components/shelly/const.py b/homeassistant/components/shelly/const.py
index c5bdb88bbd19e54fa02675dcf1e322352ea729af..837e7abfca1f6ca96332f7c695331b8a5e0177cf 100644
--- a/homeassistant/components/shelly/const.py
+++ b/homeassistant/components/shelly/const.py
@@ -238,3 +238,8 @@ DEVICES_WITHOUT_FIRMWARE_CHANGELOG = (
 CONF_GEN = "gen"
 
 SHELLY_PLUS_RGBW_CHANNELS = 4
+
+VIRTUAL_COMPONENTS_MAP = {
+    "binary_sensor": {"type": "boolean", "mode": "label"},
+    "switch": {"type": "boolean", "mode": "toggle"},
+}
diff --git a/homeassistant/components/shelly/coordinator.py b/homeassistant/components/shelly/coordinator.py
index 33ed07c35de20684a91c2052aa1bd50dfc9ce03c..8d7eafd096c00f840c15755136ef997069fadfba 100644
--- a/homeassistant/components/shelly/coordinator.py
+++ b/homeassistant/components/shelly/coordinator.py
@@ -551,7 +551,7 @@ class ShellyRpcCoordinator(ShellyCoordinatorBase[RpcDevice]):
             for event_callback in self._event_listeners:
                 event_callback(event)
 
-            if event_type == "config_changed":
+            if event_type in ("component_added", "component_removed", "config_changed"):
                 self.update_sleep_period()
                 LOGGER.info(
                     "Config for %s changed, reloading entry in %s seconds",
@@ -739,6 +739,7 @@ class ShellyRpcPollingCoordinator(ShellyCoordinatorBase[RpcDevice]):
         LOGGER.debug("Polling Shelly RPC Device - %s", self.name)
         try:
             await self.device.update_status()
+            await self.device.get_dynamic_components()
         except (DeviceConnectionError, RpcCallError) as err:
             raise UpdateFailed(f"Device disconnected: {err!r}") from err
         except InvalidAuthError:
diff --git a/homeassistant/components/shelly/entity.py b/homeassistant/components/shelly/entity.py
index e1530a669a1abb4dae418d94d9ca41ec18aa25c3..9f8b4c8d30626a0b52a0b0e54f47ca412d3d5455 100644
--- a/homeassistant/components/shelly/entity.py
+++ b/homeassistant/components/shelly/entity.py
@@ -505,6 +505,8 @@ class ShellyRpcAttributeEntity(ShellyRpcEntity, Entity):
         self._attr_unique_id = f"{super().unique_id}-{attribute}"
         self._attr_name = get_rpc_entity_name(coordinator.device, key, description.name)
         self._last_value = None
+        id_key = key.split(":")[-1]
+        self._id = int(id_key) if id_key.isnumeric() else None
 
     @property
     def sub_status(self) -> Any:
diff --git a/homeassistant/components/shelly/manifest.json b/homeassistant/components/shelly/manifest.json
index 4076f53c28ca7e6e50933697d8a64bcd5200880b..1e65a51733d17b9413a428359c193b35b8bc696d 100644
--- a/homeassistant/components/shelly/manifest.json
+++ b/homeassistant/components/shelly/manifest.json
@@ -9,7 +9,7 @@
   "iot_class": "local_push",
   "loggers": ["aioshelly"],
   "quality_scale": "platinum",
-  "requirements": ["aioshelly==11.0.0"],
+  "requirements": ["aioshelly==11.1.0"],
   "zeroconf": [
     {
       "type": "_http._tcp.local.",
diff --git a/homeassistant/components/shelly/switch.py b/homeassistant/components/shelly/switch.py
index 09ee133589b358932d4d115ef168838a03e05430..2b9b1cadc6953659eb025dc8106837f260da6c66 100644
--- a/homeassistant/components/shelly/switch.py
+++ b/homeassistant/components/shelly/switch.py
@@ -8,7 +8,11 @@ from typing import Any, cast
 from aioshelly.block_device import Block
 from aioshelly.const import MODEL_2, MODEL_25, MODEL_WALL_DISPLAY, RPC_GENERATIONS
 
-from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
+from homeassistant.components.switch import (
+    DOMAIN as SWITCH_PLATFORM,
+    SwitchEntity,
+    SwitchEntityDescription,
+)
 from homeassistant.const import STATE_ON, EntityCategory
 from homeassistant.core import HomeAssistant, State, callback
 from homeassistant.helpers.entity_platform import AddEntitiesCallback
@@ -19,15 +23,20 @@ from .const import CONF_SLEEP_PERIOD, MOTION_MODELS
 from .coordinator import ShellyBlockCoordinator, ShellyConfigEntry, ShellyRpcCoordinator
 from .entity import (
     BlockEntityDescription,
+    RpcEntityDescription,
     ShellyBlockEntity,
+    ShellyRpcAttributeEntity,
     ShellyRpcEntity,
     ShellySleepingBlockAttributeEntity,
     async_setup_entry_attribute_entities,
+    async_setup_rpc_attribute_entities,
 )
 from .utils import (
+    async_remove_orphaned_virtual_entities,
     async_remove_shelly_entity,
     get_device_entry_gen,
     get_rpc_key_ids,
+    get_virtual_component_ids,
     is_block_channel_type_light,
     is_rpc_channel_type_light,
     is_rpc_thermostat_internal_actuator,
@@ -47,6 +56,17 @@ MOTION_SWITCH = BlockSwitchDescription(
 )
 
 
+@dataclass(frozen=True, kw_only=True)
+class RpcSwitchDescription(RpcEntityDescription, SwitchEntityDescription):
+    """Class to describe a RPC virtual switch."""
+
+
+RPC_VIRTUAL_SWITCH = RpcSwitchDescription(
+    key="boolean",
+    sub_key="value",
+)
+
+
 async def async_setup_entry(
     hass: HomeAssistant,
     config_entry: ShellyConfigEntry,
@@ -148,6 +168,28 @@ def async_setup_rpc_entry(
         unique_id = f"{coordinator.mac}-switch:{id_}"
         async_remove_shelly_entity(hass, "light", unique_id)
 
+    async_setup_rpc_attribute_entities(
+        hass,
+        config_entry,
+        async_add_entities,
+        {"boolean": RPC_VIRTUAL_SWITCH},
+        RpcVirtualSwitch,
+    )
+
+    # the user can remove virtual components from the device configuration, so we need
+    # to remove orphaned entities
+    virtual_switch_ids = get_virtual_component_ids(
+        coordinator.device.config, SWITCH_PLATFORM
+    )
+    async_remove_orphaned_virtual_entities(
+        hass,
+        config_entry.entry_id,
+        coordinator.mac,
+        SWITCH_PLATFORM,
+        "boolean",
+        virtual_switch_ids,
+    )
+
     if not switch_ids:
         return
 
@@ -255,3 +297,23 @@ class RpcRelaySwitch(ShellyRpcEntity, SwitchEntity):
     async def async_turn_off(self, **kwargs: Any) -> None:
         """Turn off relay."""
         await self.call_rpc("Switch.Set", {"id": self._id, "on": False})
+
+
+class RpcVirtualSwitch(ShellyRpcAttributeEntity, SwitchEntity):
+    """Entity that controls a virtual boolean component on RPC based Shelly devices."""
+
+    entity_description: RpcSwitchDescription
+    _attr_has_entity_name = True
+
+    @property
+    def is_on(self) -> bool:
+        """If switch is on."""
+        return bool(self.attribute_value)
+
+    async def async_turn_on(self, **kwargs: Any) -> None:
+        """Turn on relay."""
+        await self.call_rpc("Boolean.Set", {"id": self._id, "value": True})
+
+    async def async_turn_off(self, **kwargs: Any) -> None:
+        """Turn off relay."""
+        await self.call_rpc("Boolean.Set", {"id": self._id, "value": False})
diff --git a/homeassistant/components/shelly/utils.py b/homeassistant/components/shelly/utils.py
index bcd5a859538a94454dc046272c4020c922c7dffb..a1d357e3beba6446af53900820302d52b121a4a2 100644
--- a/homeassistant/components/shelly/utils.py
+++ b/homeassistant/components/shelly/utils.py
@@ -4,6 +4,7 @@ from __future__ import annotations
 
 from datetime import datetime, timedelta
 from ipaddress import IPv4Address
+import re
 from types import MappingProxyType
 from typing import Any, cast
 
@@ -52,6 +53,7 @@ from .const import (
     SHBTN_MODELS,
     SHIX3_1_INPUTS_EVENTS_TYPES,
     UPTIME_DEVIATION,
+    VIRTUAL_COMPONENTS_MAP,
 )
 
 
@@ -321,6 +323,8 @@ def get_rpc_channel_name(device: RpcDevice, key: str) -> str:
             return f"{device_name} {key.replace(':', '_')}"
         if key.startswith("em1"):
             return f"{device_name} EM{key.split(':')[-1]}"
+        if key.startswith("boolean:"):
+            return key.replace(":", " ").title()
         return device_name
 
     return entity_name
@@ -497,3 +501,55 @@ def async_remove_shelly_rpc_entities(
 def is_rpc_thermostat_mode(ident: int, status: dict[str, Any]) -> bool:
     """Return True if 'thermostat:<IDent>' is present in the status."""
     return f"thermostat:{ident}" in status
+
+
+def get_virtual_component_ids(config: dict[str, Any], platform: str) -> list[str]:
+    """Return a list of virtual component IDs for a platform."""
+    component = VIRTUAL_COMPONENTS_MAP.get(platform)
+
+    if not component:
+        return []
+
+    return [
+        k
+        for k, v in config.items()
+        if k.startswith(component["type"])
+        and v["meta"]["ui"]["view"] == component["mode"]
+    ]
+
+
+@callback
+def async_remove_orphaned_virtual_entities(
+    hass: HomeAssistant,
+    config_entry_id: str,
+    mac: str,
+    platform: str,
+    virt_comp_type: str,
+    virt_comp_ids: list[str],
+) -> None:
+    """Remove orphaned virtual entities."""
+    orphaned_entities = []
+    entity_reg = er.async_get(hass)
+    device_reg = dr.async_get(hass)
+
+    if not (
+        devices := device_reg.devices.get_devices_for_config_entry_id(config_entry_id)
+    ):
+        return
+
+    device_id = devices[0].id
+    entities = er.async_entries_for_device(entity_reg, device_id, True)
+    for entity in entities:
+        if not entity.entity_id.startswith(platform):
+            continue
+        if virt_comp_type not in entity.unique_id:
+            continue
+        # we are looking for the component ID, e.g. boolean:201
+        if not (match := re.search(r"[a-z]+:\d+", entity.unique_id)):
+            continue
+        virt_comp_id = match.group()
+        if virt_comp_id not in virt_comp_ids:
+            orphaned_entities.append(f"{virt_comp_id}-{virt_comp_type}")
+
+    if orphaned_entities:
+        async_remove_shelly_rpc_entities(hass, platform, mac, orphaned_entities)
diff --git a/requirements_all.txt b/requirements_all.txt
index d0c4b2a62eb27471212fc2841a0d58a766797951..684a716d0529c047213edc70d579137f8d3a804b 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -365,7 +365,7 @@ aioruuvigateway==0.1.0
 aiosenz==1.0.0
 
 # homeassistant.components.shelly
-aioshelly==11.0.0
+aioshelly==11.1.0
 
 # homeassistant.components.skybell
 aioskybell==22.7.0
diff --git a/requirements_test_all.txt b/requirements_test_all.txt
index 669ee59fc8f89b37a14bc4cda8ca91df2a5da28d..934b107118caf93aca988b38996e86806a792d98 100644
--- a/requirements_test_all.txt
+++ b/requirements_test_all.txt
@@ -338,7 +338,7 @@ aioruuvigateway==0.1.0
 aiosenz==1.0.0
 
 # homeassistant.components.shelly
-aioshelly==11.0.0
+aioshelly==11.1.0
 
 # homeassistant.components.skybell
 aioskybell==22.7.0
diff --git a/tests/components/shelly/__init__.py b/tests/components/shelly/__init__.py
index 4631a17969e739978738a2f0d378781b9ac9c88c..7de45eeee9865b2e45e4a6332b0bc81cbf455890 100644
--- a/tests/components/shelly/__init__.py
+++ b/tests/components/shelly/__init__.py
@@ -23,6 +23,7 @@ from homeassistant.core import HomeAssistant
 from homeassistant.helpers import entity_registry as er
 from homeassistant.helpers.device_registry import (
     CONNECTION_NETWORK_MAC,
+    DeviceEntry,
     DeviceRegistry,
     format_mac,
 )
@@ -111,6 +112,7 @@ def register_entity(
     unique_id: str,
     config_entry: ConfigEntry | None = None,
     capabilities: Mapping[str, Any] | None = None,
+    device_id: str | None = None,
 ) -> str:
     """Register enabled entity, return entity_id."""
     entity_registry = er.async_get(hass)
@@ -122,6 +124,7 @@ def register_entity(
         disabled_by=None,
         config_entry=config_entry,
         capabilities=capabilities,
+        device_id=device_id,
     )
     return f"{domain}.{object_id}"
 
@@ -145,9 +148,11 @@ def get_entity_state(hass: HomeAssistant, entity_id: str) -> str:
     return entity.state
 
 
-def register_device(device_registry: DeviceRegistry, config_entry: ConfigEntry) -> None:
+def register_device(
+    device_registry: DeviceRegistry, config_entry: ConfigEntry
+) -> DeviceEntry:
     """Register Shelly device."""
-    device_registry.async_get_or_create(
+    return device_registry.async_get_or_create(
         config_entry_id=config_entry.entry_id,
         connections={(CONNECTION_NETWORK_MAC, format_mac(MOCK_MAC))},
     )
diff --git a/tests/components/shelly/test_binary_sensor.py b/tests/components/shelly/test_binary_sensor.py
index 3bfbf350f7e9b084366bb1356ea9d3171221cbbc..8bbf87d6ed34083e35d957fc47807e9f30ee8d0d 100644
--- a/tests/components/shelly/test_binary_sensor.py
+++ b/tests/components/shelly/test_binary_sensor.py
@@ -1,5 +1,6 @@
 """Tests for Shelly binary sensor platform."""
 
+from copy import deepcopy
 from unittest.mock import Mock
 
 from aioshelly.const import MODEL_MOTION
@@ -10,6 +11,7 @@ from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAI
 from homeassistant.components.shelly.const import UPDATE_PERIOD_MULTIPLIER
 from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNKNOWN
 from homeassistant.core import HomeAssistant, State
+from homeassistant.helpers import entity_registry as er
 from homeassistant.helpers.device_registry import DeviceRegistry
 from homeassistant.helpers.entity_registry import EntityRegistry
 
@@ -353,3 +355,125 @@ async def test_rpc_restored_sleeping_binary_sensor_no_last_state(
     await hass.async_block_till_done()
 
     assert hass.states.get(entity_id).state == STATE_OFF
+
+
+async def test_rpc_device_virtual_binary_sensor_with_name(
+    hass: HomeAssistant,
+    entity_registry: er.EntityRegistry,
+    mock_rpc_device: Mock,
+    monkeypatch: pytest.MonkeyPatch,
+) -> None:
+    """Test a virtual binary sensor for RPC device."""
+    config = deepcopy(mock_rpc_device.config)
+    config["boolean:203"] = {
+        "name": "Virtual binary sensor",
+        "meta": {"ui": {"view": "label"}},
+    }
+    monkeypatch.setattr(mock_rpc_device, "config", config)
+
+    status = deepcopy(mock_rpc_device.status)
+    status["boolean:203"] = {"value": True}
+    monkeypatch.setattr(mock_rpc_device, "status", status)
+
+    entity_id = "binary_sensor.test_name_virtual_binary_sensor"
+
+    await init_integration(hass, 3)
+
+    state = hass.states.get(entity_id)
+    assert state
+    assert state.state == STATE_ON
+
+    entry = entity_registry.async_get(entity_id)
+    assert entry
+    assert entry.unique_id == "123456789ABC-boolean:203-boolean"
+
+    monkeypatch.setitem(mock_rpc_device.status["boolean:203"], "value", False)
+    mock_rpc_device.mock_update()
+    assert hass.states.get(entity_id).state == STATE_OFF
+
+
+async def test_rpc_device_virtual_binary_sensor_without_name(
+    hass: HomeAssistant,
+    entity_registry: er.EntityRegistry,
+    mock_rpc_device: Mock,
+    monkeypatch: pytest.MonkeyPatch,
+) -> None:
+    """Test a virtual binary sensor for RPC device."""
+    config = deepcopy(mock_rpc_device.config)
+    config["boolean:203"] = {"name": None, "meta": {"ui": {"view": "label"}}}
+    monkeypatch.setattr(mock_rpc_device, "config", config)
+
+    status = deepcopy(mock_rpc_device.status)
+    status["boolean:203"] = {"value": True}
+    monkeypatch.setattr(mock_rpc_device, "status", status)
+
+    entity_id = "binary_sensor.test_name_boolean_203"
+
+    await init_integration(hass, 3)
+
+    state = hass.states.get(entity_id)
+    assert state
+    assert state.state == STATE_ON
+
+    entry = entity_registry.async_get(entity_id)
+    assert entry
+    assert entry.unique_id == "123456789ABC-boolean:203-boolean"
+
+
+async def test_rpc_remove_virtual_binary_sensor_when_mode_toggle(
+    hass: HomeAssistant,
+    entity_registry: er.EntityRegistry,
+    device_registry: DeviceRegistry,
+    mock_rpc_device: Mock,
+    monkeypatch: pytest.MonkeyPatch,
+) -> None:
+    """Test if the virtual binary sensor will be removed if the mode has been changed to a toggle."""
+    config = deepcopy(mock_rpc_device.config)
+    config["boolean:200"] = {"name": None, "meta": {"ui": {"view": "toggle"}}}
+    monkeypatch.setattr(mock_rpc_device, "config", config)
+
+    status = deepcopy(mock_rpc_device.status)
+    status["boolean:200"] = {"value": True}
+    monkeypatch.setattr(mock_rpc_device, "status", status)
+
+    config_entry = await init_integration(hass, 3, skip_setup=True)
+    device_entry = register_device(device_registry, config_entry)
+    entity_id = register_entity(
+        hass,
+        BINARY_SENSOR_DOMAIN,
+        "test_name_boolean_200",
+        "boolean:200-boolean",
+        config_entry,
+        device_id=device_entry.id,
+    )
+
+    await hass.config_entries.async_setup(config_entry.entry_id)
+    await hass.async_block_till_done()
+
+    entry = entity_registry.async_get(entity_id)
+    assert not entry
+
+
+async def test_rpc_remove_virtual_binary_sensor_when_orphaned(
+    hass: HomeAssistant,
+    entity_registry: er.EntityRegistry,
+    device_registry: DeviceRegistry,
+    mock_rpc_device: Mock,
+) -> None:
+    """Check whether the virtual binary sensor will be removed if it has been removed from the device configuration."""
+    config_entry = await init_integration(hass, 3, skip_setup=True)
+    device_entry = register_device(device_registry, config_entry)
+    entity_id = register_entity(
+        hass,
+        BINARY_SENSOR_DOMAIN,
+        "test_name_boolean_200",
+        "boolean:200-boolean",
+        config_entry,
+        device_id=device_entry.id,
+    )
+
+    await hass.config_entries.async_setup(config_entry.entry_id)
+    await hass.async_block_till_done()
+
+    entry = entity_registry.async_get(entity_id)
+    assert not entry
diff --git a/tests/components/shelly/test_switch.py b/tests/components/shelly/test_switch.py
index de87d11d2557cfa016a8d4a74559b700711a0aab..0906395f901234439e5abc837c812aacebd7a283 100644
--- a/tests/components/shelly/test_switch.py
+++ b/tests/components/shelly/test_switch.py
@@ -25,6 +25,7 @@ from homeassistant.const import (
 )
 from homeassistant.core import HomeAssistant, State
 from homeassistant.exceptions import HomeAssistantError
+from homeassistant.helpers import entity_registry as er
 from homeassistant.helpers.device_registry import DeviceRegistry
 from homeassistant.helpers.entity_registry import EntityRegistry
 
@@ -430,3 +431,163 @@ async def test_wall_display_relay_mode(
     entry = entity_registry.async_get(switch_entity_id)
     assert entry
     assert entry.unique_id == "123456789ABC-switch:0"
+
+
+async def test_rpc_device_virtual_switch_with_name(
+    hass: HomeAssistant,
+    entity_registry: er.EntityRegistry,
+    mock_rpc_device: Mock,
+    monkeypatch: pytest.MonkeyPatch,
+) -> None:
+    """Test a virtual switch for RPC device."""
+    config = deepcopy(mock_rpc_device.config)
+    config["boolean:200"] = {
+        "name": "Virtual switch",
+        "meta": {"ui": {"view": "toggle"}},
+    }
+    monkeypatch.setattr(mock_rpc_device, "config", config)
+
+    status = deepcopy(mock_rpc_device.status)
+    status["boolean:200"] = {"value": True}
+    monkeypatch.setattr(mock_rpc_device, "status", status)
+
+    entity_id = "switch.test_name_virtual_switch"
+
+    await init_integration(hass, 3)
+
+    state = hass.states.get(entity_id)
+    assert state
+    assert state.state == STATE_ON
+
+    entry = entity_registry.async_get(entity_id)
+    assert entry
+    assert entry.unique_id == "123456789ABC-boolean:200-boolean"
+
+    monkeypatch.setitem(mock_rpc_device.status["boolean:200"], "value", False)
+    await hass.services.async_call(
+        SWITCH_DOMAIN,
+        SERVICE_TURN_OFF,
+        {ATTR_ENTITY_ID: entity_id},
+        blocking=True,
+    )
+    mock_rpc_device.mock_update()
+    assert hass.states.get(entity_id).state == STATE_OFF
+
+    monkeypatch.setitem(mock_rpc_device.status["boolean:200"], "value", True)
+    await hass.services.async_call(
+        SWITCH_DOMAIN,
+        SERVICE_TURN_ON,
+        {ATTR_ENTITY_ID: entity_id},
+        blocking=True,
+    )
+    mock_rpc_device.mock_update()
+    assert hass.states.get(entity_id).state == STATE_ON
+
+
+async def test_rpc_device_virtual_switch_without_name(
+    hass: HomeAssistant,
+    entity_registry: er.EntityRegistry,
+    mock_rpc_device: Mock,
+    monkeypatch: pytest.MonkeyPatch,
+) -> None:
+    """Test a virtual switch for RPC device."""
+    config = deepcopy(mock_rpc_device.config)
+    config["boolean:200"] = {"name": None, "meta": {"ui": {"view": "toggle"}}}
+    monkeypatch.setattr(mock_rpc_device, "config", config)
+
+    status = deepcopy(mock_rpc_device.status)
+    status["boolean:200"] = {"value": True}
+    monkeypatch.setattr(mock_rpc_device, "status", status)
+
+    entity_id = "switch.test_name_boolean_200"
+
+    await init_integration(hass, 3)
+
+    state = hass.states.get(entity_id)
+    assert state
+    assert state.state == STATE_ON
+
+    entry = entity_registry.async_get(entity_id)
+    assert entry
+    assert entry.unique_id == "123456789ABC-boolean:200-boolean"
+
+
+async def test_rpc_device_virtual_binary_sensor(
+    hass: HomeAssistant,
+    mock_rpc_device: Mock,
+    monkeypatch: pytest.MonkeyPatch,
+) -> None:
+    """Test that a switch entity has not been created for a virtual binary sensor."""
+    config = deepcopy(mock_rpc_device.config)
+    config["boolean:200"] = {"name": None, "meta": {"ui": {"view": "label"}}}
+    monkeypatch.setattr(mock_rpc_device, "config", config)
+
+    status = deepcopy(mock_rpc_device.status)
+    status["boolean:200"] = {"value": True}
+    monkeypatch.setattr(mock_rpc_device, "status", status)
+
+    entity_id = "switch.test_name_boolean_200"
+
+    await init_integration(hass, 3)
+
+    state = hass.states.get(entity_id)
+    assert not state
+
+
+async def test_rpc_remove_virtual_switch_when_mode_label(
+    hass: HomeAssistant,
+    entity_registry: er.EntityRegistry,
+    device_registry: DeviceRegistry,
+    mock_rpc_device: Mock,
+    monkeypatch: pytest.MonkeyPatch,
+) -> None:
+    """Test if the virtual switch will be removed if the mode has been changed to a label."""
+    config = deepcopy(mock_rpc_device.config)
+    config["boolean:200"] = {"name": None, "meta": {"ui": {"view": "label"}}}
+    monkeypatch.setattr(mock_rpc_device, "config", config)
+
+    status = deepcopy(mock_rpc_device.status)
+    status["boolean:200"] = {"value": True}
+    monkeypatch.setattr(mock_rpc_device, "status", status)
+
+    config_entry = await init_integration(hass, 3, skip_setup=True)
+    device_entry = register_device(device_registry, config_entry)
+    entity_id = register_entity(
+        hass,
+        SWITCH_DOMAIN,
+        "test_name_boolean_200",
+        "boolean:200-boolean",
+        config_entry,
+        device_id=device_entry.id,
+    )
+
+    await hass.config_entries.async_setup(config_entry.entry_id)
+    await hass.async_block_till_done()
+
+    entry = entity_registry.async_get(entity_id)
+    assert not entry
+
+
+async def test_rpc_remove_virtual_switch_when_orphaned(
+    hass: HomeAssistant,
+    entity_registry: er.EntityRegistry,
+    device_registry: DeviceRegistry,
+    mock_rpc_device: Mock,
+) -> None:
+    """Check whether the virtual switch will be removed if it has been removed from the device configuration."""
+    config_entry = await init_integration(hass, 3, skip_setup=True)
+    device_entry = register_device(device_registry, config_entry)
+    entity_id = register_entity(
+        hass,
+        SWITCH_DOMAIN,
+        "test_name_boolean_200",
+        "boolean:200-boolean",
+        config_entry,
+        device_id=device_entry.id,
+    )
+
+    await hass.config_entries.async_setup(config_entry.entry_id)
+    await hass.async_block_till_done()
+
+    entry = entity_registry.async_get(entity_id)
+    assert not entry