diff --git a/homeassistant/components/shelly/__init__.py b/homeassistant/components/shelly/__init__.py
index b29079affcf0309d858e9264627aaed5e8185cb9..4747d044bfaff149ca34f85851bafac57ce16e46 100644
--- a/homeassistant/components/shelly/__init__.py
+++ b/homeassistant/components/shelly/__init__.py
@@ -86,6 +86,7 @@ BLOCK_SLEEPING_PLATFORMS: Final = [
 RPC_PLATFORMS: Final = [
     Platform.BINARY_SENSOR,
     Platform.BUTTON,
+    Platform.COVER,
     Platform.LIGHT,
     Platform.SENSOR,
     Platform.SWITCH,
diff --git a/homeassistant/components/shelly/cover.py b/homeassistant/components/shelly/cover.py
index f9bd1b7ce85960ed2e5ad522b5d952cc989fa4d5..4885a2a0d2eeae14ba485eb0dc005ee022f22a9b 100644
--- a/homeassistant/components/shelly/cover.py
+++ b/homeassistant/components/shelly/cover.py
@@ -18,15 +18,28 @@ from homeassistant.config_entries import ConfigEntry
 from homeassistant.core import HomeAssistant, callback
 from homeassistant.helpers.entity_platform import AddEntitiesCallback
 
-from . import BlockDeviceWrapper
-from .const import BLOCK, DATA_CONFIG_ENTRY, DOMAIN
-from .entity import ShellyBlockEntity
+from . import BlockDeviceWrapper, RpcDeviceWrapper
+from .const import BLOCK, DATA_CONFIG_ENTRY, DOMAIN, RPC
+from .entity import ShellyBlockEntity, ShellyRpcEntity
+from .utils import get_device_entry_gen, get_rpc_key_ids
 
 
 async def async_setup_entry(
     hass: HomeAssistant,
     config_entry: ConfigEntry,
     async_add_entities: AddEntitiesCallback,
+) -> None:
+    """Set up switches for device."""
+    if get_device_entry_gen(config_entry) == 2:
+        return await async_setup_rpc_entry(hass, config_entry, async_add_entities)
+
+    return await async_setup_block_entry(hass, config_entry, async_add_entities)
+
+
+async def async_setup_block_entry(
+    hass: HomeAssistant,
+    config_entry: ConfigEntry,
+    async_add_entities: AddEntitiesCallback,
 ) -> None:
     """Set up cover for device."""
     wrapper = hass.data[DOMAIN][DATA_CONFIG_ENTRY][config_entry.entry_id][BLOCK]
@@ -35,16 +48,32 @@ async def async_setup_entry(
     if not blocks:
         return
 
-    async_add_entities(ShellyCover(wrapper, block) for block in blocks)
+    async_add_entities(BlockShellyCover(wrapper, block) for block in blocks)
 
 
-class ShellyCover(ShellyBlockEntity, CoverEntity):
-    """Switch that controls a cover block on Shelly devices."""
+async def async_setup_rpc_entry(
+    hass: HomeAssistant,
+    config_entry: ConfigEntry,
+    async_add_entities: AddEntitiesCallback,
+) -> None:
+    """Set up entities for RPC device."""
+    wrapper = hass.data[DOMAIN][DATA_CONFIG_ENTRY][config_entry.entry_id][RPC]
+
+    cover_key_ids = get_rpc_key_ids(wrapper.device.status, "cover")
+
+    if not cover_key_ids:
+        return
+
+    async_add_entities(RpcShellyCover(wrapper, id_) for id_ in cover_key_ids)
+
+
+class BlockShellyCover(ShellyBlockEntity, CoverEntity):
+    """Entity that controls a cover on block based Shelly devices."""
 
     _attr_device_class = CoverDeviceClass.SHUTTER
 
     def __init__(self, wrapper: BlockDeviceWrapper, block: Block) -> None:
-        """Initialize light."""
+        """Initialize block cover."""
         super().__init__(wrapper, block)
         self.control_result: dict[str, Any] | None = None
         self._attr_supported_features: int = SUPPORT_OPEN | SUPPORT_CLOSE | SUPPORT_STOP
@@ -110,3 +139,61 @@ class ShellyCover(ShellyBlockEntity, CoverEntity):
         """When device updates, clear control result that overrides state."""
         self.control_result = None
         super()._update_callback()
+
+
+class RpcShellyCover(ShellyRpcEntity, CoverEntity):
+    """Entity that controls a cover on RPC based Shelly devices."""
+
+    _attr_device_class = CoverDeviceClass.SHUTTER
+
+    def __init__(self, wrapper: RpcDeviceWrapper, id_: int) -> None:
+        """Initialize rpc cover."""
+        super().__init__(wrapper, f"cover:{id_}")
+        self._id = id_
+        self._attr_supported_features: int = SUPPORT_OPEN | SUPPORT_CLOSE | SUPPORT_STOP
+        if self.status["pos_control"]:
+            self._attr_supported_features |= SUPPORT_SET_POSITION
+
+    @property
+    def is_closed(self) -> bool | None:
+        """If cover is closed."""
+        if not self.status["pos_control"]:
+            return None
+
+        return cast(bool, self.status["state"] == "closed")
+
+    @property
+    def current_cover_position(self) -> int | None:
+        """Position of the cover."""
+        if not self.status["pos_control"]:
+            return None
+
+        return cast(int, self.status["current_pos"])
+
+    @property
+    def is_closing(self) -> bool:
+        """Return if the cover is closing."""
+        return cast(bool, self.status["state"] == "closing")
+
+    @property
+    def is_opening(self) -> bool:
+        """Return if the cover is opening."""
+        return cast(bool, self.status["state"] == "opening")
+
+    async def async_close_cover(self, **kwargs: Any) -> None:
+        """Close cover."""
+        await self.call_rpc("Cover.Close", {"id": self._id})
+
+    async def async_open_cover(self, **kwargs: Any) -> None:
+        """Open cover."""
+        await self.call_rpc("Cover.Open", {"id": self._id})
+
+    async def async_set_cover_position(self, **kwargs: Any) -> None:
+        """Move the cover to a specific position."""
+        await self.call_rpc(
+            "Cover.GoToPosition", {"id": self._id, "pos": kwargs[ATTR_POSITION]}
+        )
+
+    async def async_stop_cover(self, **_kwargs: Any) -> None:
+        """Stop the cover."""
+        await self.call_rpc("Cover.Stop", {"id": self._id})
diff --git a/homeassistant/components/shelly/entity.py b/homeassistant/components/shelly/entity.py
index 51e0711b035b59b813f77f28b6f51252182eb31e..85abd67c069862188b0c0915d5af5872d4aa8f87 100644
--- a/homeassistant/components/shelly/entity.py
+++ b/homeassistant/components/shelly/entity.py
@@ -351,6 +351,11 @@ class ShellyRpcEntity(entity.Entity):
         """Available."""
         return self.wrapper.device.connected
 
+    @property
+    def status(self) -> dict:
+        """Device status by entity key."""
+        return cast(dict, self.wrapper.device.status[self.key])
+
     async def async_added_to_hass(self) -> None:
         """When entity is added to HASS."""
         self.async_on_remove(self.wrapper.async_add_listener(self._update_callback))
diff --git a/tests/components/shelly/conftest.py b/tests/components/shelly/conftest.py
index 5391f3f74fe45dd84a0049a2ff0ff46c125c44b9..c0e0bbadda233eb6cef3417e5aa12504819fe92c 100644
--- a/tests/components/shelly/conftest.py
+++ b/tests/components/shelly/conftest.py
@@ -58,6 +58,7 @@ MOCK_BLOCKS = [
 MOCK_CONFIG = {
     "input:0": {"id": 0, "type": "button"},
     "switch:0": {"name": "test switch_0"},
+    "cover:0": {"name": "test cover_0"},
     "sys": {
         "ui_data": {},
         "device": {"name": "Test name"},
@@ -84,6 +85,7 @@ MOCK_STATUS_COAP = {
 
 MOCK_STATUS_RPC = {
     "switch:0": {"output": True},
+    "cover:0": {"state": "stopped", "pos_control": True, "current_pos": 50},
     "sys": {
         "available_updates": {
             "beta": {"version": "some_beta_version"},
diff --git a/tests/components/shelly/test_cover.py b/tests/components/shelly/test_cover.py
index 5c34fcc1bf57e0bb5fd0559861925285333348a2..f5b25ce6cb525e6e3eee831d960022c61de9f46d 100644
--- a/tests/components/shelly/test_cover.py
+++ b/tests/components/shelly/test_cover.py
@@ -12,13 +12,13 @@ from homeassistant.components.cover import (
     STATE_OPEN,
     STATE_OPENING,
 )
-from homeassistant.const import ATTR_ENTITY_ID
+from homeassistant.const import ATTR_ENTITY_ID, STATE_UNKNOWN
 
 ROLLER_BLOCK_ID = 1
 
 
-async def test_services(hass, coap_wrapper, monkeypatch):
-    """Test device turn on/off services."""
+async def test_block_device_services(hass, coap_wrapper, monkeypatch):
+    """Test block device cover services."""
     assert coap_wrapper
 
     monkeypatch.setitem(coap_wrapper.device.settings, "mode", "roller")
@@ -61,8 +61,8 @@ async def test_services(hass, coap_wrapper, monkeypatch):
     assert hass.states.get("cover.test_name").state == STATE_CLOSED
 
 
-async def test_update(hass, coap_wrapper, monkeypatch):
-    """Test device update."""
+async def test_block_device_update(hass, coap_wrapper, monkeypatch):
+    """Test block device update."""
     assert coap_wrapper
 
     hass.async_create_task(
@@ -81,8 +81,8 @@ async def test_update(hass, coap_wrapper, monkeypatch):
     assert hass.states.get("cover.test_name").state == STATE_OPEN
 
 
-async def test_no_roller_blocks(hass, coap_wrapper, monkeypatch):
-    """Test device without roller blocks."""
+async def test_block_device_no_roller_blocks(hass, coap_wrapper, monkeypatch):
+    """Test block device without roller blocks."""
     assert coap_wrapper
 
     monkeypatch.setattr(coap_wrapper.device.blocks[ROLLER_BLOCK_ID], "type", None)
@@ -91,3 +91,101 @@ async def test_no_roller_blocks(hass, coap_wrapper, monkeypatch):
     )
     await hass.async_block_till_done()
     assert hass.states.get("cover.test_name") is None
+
+
+async def test_rpc_device_services(hass, rpc_wrapper, monkeypatch):
+    """Test RPC device cover services."""
+    assert rpc_wrapper
+
+    hass.async_create_task(
+        hass.config_entries.async_forward_entry_setup(rpc_wrapper.entry, COVER_DOMAIN)
+    )
+    await hass.async_block_till_done()
+
+    await hass.services.async_call(
+        COVER_DOMAIN,
+        SERVICE_SET_COVER_POSITION,
+        {ATTR_ENTITY_ID: "cover.test_cover_0", ATTR_POSITION: 50},
+        blocking=True,
+    )
+    state = hass.states.get("cover.test_cover_0")
+    assert state.attributes[ATTR_CURRENT_POSITION] == 50
+
+    monkeypatch.setitem(rpc_wrapper.device.status["cover:0"], "state", "opening")
+    await hass.services.async_call(
+        COVER_DOMAIN,
+        SERVICE_OPEN_COVER,
+        {ATTR_ENTITY_ID: "cover.test_cover_0"},
+        blocking=True,
+    )
+    rpc_wrapper.async_set_updated_data("")
+    assert hass.states.get("cover.test_cover_0").state == STATE_OPENING
+
+    monkeypatch.setitem(rpc_wrapper.device.status["cover:0"], "state", "closing")
+    await hass.services.async_call(
+        COVER_DOMAIN,
+        SERVICE_CLOSE_COVER,
+        {ATTR_ENTITY_ID: "cover.test_cover_0"},
+        blocking=True,
+    )
+    rpc_wrapper.async_set_updated_data("")
+    assert hass.states.get("cover.test_cover_0").state == STATE_CLOSING
+
+    monkeypatch.setitem(rpc_wrapper.device.status["cover:0"], "state", "closed")
+    await hass.services.async_call(
+        COVER_DOMAIN,
+        SERVICE_STOP_COVER,
+        {ATTR_ENTITY_ID: "cover.test_cover_0"},
+        blocking=True,
+    )
+    rpc_wrapper.async_set_updated_data("")
+    assert hass.states.get("cover.test_cover_0").state == STATE_CLOSED
+
+
+async def test_rpc_device_no_cover_keys(hass, rpc_wrapper, monkeypatch):
+    """Test RPC device without cover keys."""
+    assert rpc_wrapper
+
+    monkeypatch.delitem(rpc_wrapper.device.status, "cover:0")
+
+    hass.async_create_task(
+        hass.config_entries.async_forward_entry_setup(rpc_wrapper.entry, COVER_DOMAIN)
+    )
+    await hass.async_block_till_done()
+    assert hass.states.get("cover.test_cover_0") is None
+
+
+async def test_rpc_device_update(hass, rpc_wrapper, monkeypatch):
+    """Test RPC device update."""
+    assert rpc_wrapper
+
+    hass.async_create_task(
+        hass.config_entries.async_forward_entry_setup(rpc_wrapper.entry, COVER_DOMAIN)
+    )
+    await hass.async_block_till_done()
+
+    monkeypatch.setitem(rpc_wrapper.device.status["cover:0"], "state", "closed")
+    await hass.helpers.entity_component.async_update_entity("cover.test_cover_0")
+    await hass.async_block_till_done()
+    assert hass.states.get("cover.test_cover_0").state == STATE_CLOSED
+
+    monkeypatch.setitem(rpc_wrapper.device.status["cover:0"], "state", "open")
+    await hass.helpers.entity_component.async_update_entity("cover.test_cover_0")
+    await hass.async_block_till_done()
+    assert hass.states.get("cover.test_cover_0").state == STATE_OPEN
+
+
+async def test_rpc_device_no_position_control(hass, rpc_wrapper, monkeypatch):
+    """Test RPC device with no position control."""
+    assert rpc_wrapper
+
+    monkeypatch.setitem(rpc_wrapper.device.status["cover:0"], "pos_control", False)
+
+    hass.async_create_task(
+        hass.config_entries.async_forward_entry_setup(rpc_wrapper.entry, COVER_DOMAIN)
+    )
+    await hass.async_block_till_done()
+
+    await hass.helpers.entity_component.async_update_entity("cover.test_cover_0")
+    await hass.async_block_till_done()
+    assert hass.states.get("cover.test_cover_0").state == STATE_UNKNOWN