---
title: "Shelly Plus 2PM"
description: "Shelly Plus 2PM in TapHome over local HTTP RPC: two relays with power metering, or cover mode for a roller shutter with position control and calibration."
url: "https://taphome.com/en/compatibility/shelly-plus-2-pm/"
language: en
lastmod: 2026-10-08
generator: hugo
ai:
  topics: ["http","electric-meter","wifi","relay","power-metering","cover","shutter","mdns","profile"]
  questions: ["How to integrate Shelly Plus 2PM with TapHome?","What is the difference between switch and cover profile on Shelly Plus 2PM?","How to control a roller shutter with Shelly Plus 2PM and TapHome?","How to switch between relay and cover mode on Shelly Plus 2PM?","Why does the Shelly Plus 2PM template show a profile error in TapHome?","How to calibrate the Shelly Plus 2PM cover for position control?","What diagnostics are available for Shelly Plus 2PM in TapHome?"]
---

# Shelly Plus 2PM

Communication: Packet Parser → HTTP

- [Shelly Plus 2PM Product Page](https://www.shelly.com/en/products/shop/shelly-plus-2pm)
- [Shelly Plus 2PM API Documentation](https://shelly-api-docs.shelly.cloud/gen2/Devices/Gen2/ShellyPlus2PM/)

> Network address
> 
> TapHome reaches this device at the address entered on import. Give the device a fixed address — an IP reservation in the router, or its mDNS name if it supports one — otherwise the integration stops working when the router changes the address.
> 
> [Network Preparation](https://taphome.com/en/docs/setup/network-preparation/)

## Integration guide

The Shelly Plus 2PM is a compact dual-channel Wi-Fi relay with built-in power metering on both channels. It fits behind a standard wall switch and can control two independent circuits, each rated up to 10 A (16 A total at 230 V AC), or drive a single motorized roller shutter. TapHome communicates with the device over HTTP using the Gen2+ RPC API on the local network — no cloud connection is required.

The device supports two operation profiles — **switch** and **cover** — selectable through the Shelly web UI or via the TapHome service action. In switch profile, both relay outputs (O1 and O2) operate independently with per-channel power monitoring. In cover profile, the two outputs drive a single motor for roller shutters, blinds, or curtains, with position control and calibration.

> [!NOTE]
> The Shelly Plus 2PM is discontinued. Its successor, the [Shelly 2PM Gen3](https://taphome.com/en/compatibility/shelly-2pm-gen3/), offers the same dual-profile functionality with an upgraded processor (8 MB flash), up to 6 concurrent HTTP connections, and Matter upgradeability.

## Configuration

The Shelly Plus 2PM connects over Wi-Fi. During TapHome template import, enter the device's IP address (default placeholder `192.168.0.1`).

> [!WARNING]
> Authentication must be **disabled** on the Shelly device for TapHome integration. TapHome does not support HTTP Digest Auth used by Gen2+ devices. Open the Shelly web UI (`http://{device-ip}`) → Settings → Authentication and ensure it is turned off.

> [!NOTE]
> If ECO mode is enabled on the Shelly device, it may cause communication timeouts due to the fast poll intervals used by the template (2.5–5 seconds). Disable ECO mode in the Shelly web UI if you experience intermittent connectivity issues.

### Profile selection

The Shelly Plus 2PM operates in one of two profiles at a time. The active profile determines which TapHome devices are functional:

- **Switch profile** — enables both relay switches (Switch 1 and Switch 2) and their per-channel energy meters. The shutter device and shutter energy meter will not respond.
- **Cover profile** — enables the shutter device and its energy meter. The two switch devices and their energy meters will not respond.

The active profile is visible as a module-level service attribute ("Profile") in TapHome. To change the profile, use the **Profile** service action at the module level, or switch it in the Shelly web UI. After changing the profile, the device reboots and only the devices matching the new profile will operate.

> [!TIP]
> The template includes all six devices (2 switches + 2 switch energy meters + 1 shutter + 1 shutter energy meter), but only the devices matching the active profile will work. This is expected behavior — devices on the wrong profile simply do not respond.

### Cover calibration

When using the cover profile, the motor travel limits must be calibrated before position control works. Until calibration is complete, `current_pos` returns null and the "Calibrated" service attribute shows `false`. Calibrate either through the Shelly web UI or by triggering the **Calibrate** service action on the Shutter device in TapHome. During calibration, the cover runs a multi-step sequence (full open → full close → full open → close in steps → open in steps) to measure travel distances.

## Device capabilities

### Relay control (switch profile)

The template exposes two independent relay switches. Each switch reads its state from `/rpc/Switch.GetStatus?id={0,1}` (`output` field, boolean) and controls the relay via `/rpc/Switch.Set?id={0,1}&on=true|false`.

Each switch exposes seven service attributes:

- **Source** — source of the last command (http, UI, WS_in, etc.)
- **Temperature** — internal device temperature in °C
- **Initial State** — switch behavior on power-up (off, on, restore_last, or match_input)
- **Input Mode** — physical input wiring mode (follow or detached)
- **Power Limit** — maximum power threshold in watts for overpower protection
- **Voltage Limit** — maximum voltage threshold in volts
- **Current Limit** — maximum current threshold in amperes

Two service actions are available on each switch:

- **Set Initial State** — configures the relay behavior after power-up (off, on, restore_last, match_input)
- **Set Mode** — configures the physical input wiring mode (follow, detached)

### Power metering (switch profile)

Each switch channel has a dedicated energy meter that reads two values from `/rpc/Switch.GetStatus`:

- **Real-time power** — `apower` reported in watts, converted to kW by the template
- **Total consumption** — `aenergy.total` reported in watt-hours, converted to kWh by the template

Each energy meter also exposes three service attributes:

- **Voltage** — supply voltage in volts
- **Current** — load current in amperes
- **Power Factor** — power factor of the load

The meters are read-only — they update automatically with every poll cycle.

### Shutter control (cover profile)

The shutter device controls a motorized roller shutter, curtain, or awning. It reads position from `/rpc/Cover.GetStatus?id=0` (`current_pos` field, 0–100%) and writes via `/rpc/Cover.GoToPosition?id=0&pos=N`.

The shutter device exposes 21 service attributes:

- **Status** — source, state (open/closed/opening/closing/stopped/calibrating), current and target position, movement timeout and start time
- **Calibrated** — whether position control is enabled (`pos_control`)
- **Temperature** — internal device temperature in °C
- **Power-up behavior** — initial state configuration (open, closed, stopped)
- **Input settings** — input mode (single, dual, detached), swap inputs, invert directions
- **Protection limits** — power limit (W), voltage limit (V), current limit (A)
- **Motor tuning** — idle power threshold (0–50 W), idle confirmation period (0.25–2 s)
- **Movement limits** — maximum open time (0.1–300 s), maximum close time (0.1–300 s)
- **Safety features** — obstruction detection status, safety switch status

Six service actions are available on the shutter:

- **Open** — fully opens the cover
- **Close** — fully closes the cover
- **Stop** — stops movement immediately
- **Calibrate** — starts the calibration procedure for position control
- **Go to Position** — moves the cover to a specific position (0–100%)
- **Reverse directions** — toggles the `invert_directions` config and reboots the device

### Power metering (cover profile)

The shutter has a dedicated energy meter that reads from `/rpc/Cover.GetStatus`:

- **Real-time power** — `apower` reported in watts, converted to kW by the template
- **Total consumption** — `aenergy.total` reported in watt-hours, converted to kWh by the template

The shutter energy meter also exposes voltage, current, and power factor as service attributes.

### Service diagnostics

The template exposes two module-level service attributes:

- **MAC** — device MAC address from system config
- **Profile** — currently active device profile (switch or cover)

The module read script also checks `restart_required` from `/rpc/Sys.GetStatus` and surfaces a warning in TapHome if a reboot is pending.

### Service actions

Two service actions are available at the module level:

- **Reboot** — triggers a device reboot via `/rpc/Shelly.Reboot`
- **Profile** — switches between switch and cover operating profiles via `/rpc/Shelly.SetProfile`

### Additional capabilities

The Shelly Plus 2PM also exposes network frequency (`freq`), per-minute energy values (`aenergy.by_minute`), physical input states (`input:0`, `input:1`), WiFi signal strength (RSSI), and a switch toggle endpoint in its RPC responses. Energy counters can be reset via `/rpc/Switch.ResetCounters` (switch profile) or `/rpc/Cover.ResetCounters` (cover profile). In cover mode, slat/tilt position for venetian blinds is available when the hardware supports it. These capabilities can be added in a future template update.

## Troubleshooting

### Device not responding

1. Verify the Shelly is connected to Wi-Fi and has a valid IP address
2. Try using the mDNS hostname (`shellyplus2pm-AABBCCDDEE.local`) instead of the IP address — the IP may have changed after a DHCP renewal
3. Open `http://{device-ip}/rpc/Shelly.GetDeviceInfo` in a browser — if it responds with JSON, the device is reachable
4. Check that TapHome Core and Shelly are on the same network / VLAN
5. Confirm authentication is disabled on the Shelly device

### Profile mismatch — devices not responding

If some devices show no readings while others work correctly:

1. Check which profile is currently active — the "Profile" service attribute at the module level shows the current mode
2. Switch to the correct profile using the **Profile** service action, or ignore the unused devices
3. After switching profiles, the device reboots automatically — allow a few seconds for reconnection

### Cover position not working

1. Verify the device is in cover profile — switch profile does not expose cover functionality
2. Run the **Calibrate** service action on the Shutter device — position control requires completed calibration
3. Check that the motor is connected correctly to O1 and O2 terminals
4. Poll `/rpc/Cover.GetStatus?id=0` manually and verify `pos_control` is `true`

### Cover calibration fails

Calibration aborts if:

- The cover fails to reach the end position within `maxtime_open` or `maxtime_close`
- A safety feature (obstruction detection or safety switch) is triggered during calibration
- An external stop command is issued during calibration
- The motor direction does not match expected feedback
- The device reboots during calibration

Check motor wiring, increase `maxtime_open`/`maxtime_close` if the motor is slow, and ensure no obstructions are present.

### Power readings show zero

1. Confirm the load is connected through the Shelly relay (not bypassed)
2. Check that the relay is turned on — the meter only reads when current flows through the relay
3. Poll `/rpc/Switch.GetStatus?id=0` (switch profile) or `/rpc/Cover.GetStatus?id=0` (cover profile) manually and verify `apower` returns a non-zero value

> [!WARNING]
> Gen2+ Shelly devices support up to **6 concurrent HTTP connections**. While this is an improvement over Gen1 (2 connections), avoid polling from too many systems simultaneously (TapHome, Home Assistant, custom scripts) to prevent connection exhaustion.

## How to install in TapHome

### Prerequisites

- Shelly device installed and powered on
- Local Wi-Fi network (2.4 GHz)
- TapHome CCU on the same network

### Step 1 — Connect Shelly to Wi-Fi

**Option A — Shelly app (recommended):**

1. Download the [Shelly app](https://www.shelly.com/en/support/shelly-app) (iOS / Android)
2. Tap **+** → **Add Device** and follow the Bluetooth pairing wizard
3. Enter your Wi-Fi credentials when prompted

**Option B — AP mode (no app):**

1. On first power-up the device creates a hotspot: `ShellyXXX-AABBCCDDEE`
2. Connect your phone/PC to that hotspot
3. Open `http://192.168.33.1` → **Internet & Security** → **Wi-Fi Mode - Client**
4. Enter SSID and password → **Save**

> [!NOTE]
> Shelly only supports **2.4 GHz** networks. 5 GHz networks will not appear in the scan.

### Step 2 — Find the device address

Shelly Gen1 devices support **mDNS** (Zeroconf). You can reach the device using a hostname instead of an IP address:

```
shelly<model>-<MAC>.local
```

For example: `shelly1pm-AABBCCDDEE.local` (MAC address in uppercase hex, no colons).

> [!TIP]
> **Recommended: use the TapHome IP Scanner.** Open the TapHome app and use the **IP Scanner** (Settings → Network → Scan). The scanner will discover devices on your network and show both the IP address and the mDNS hostname. Use the **hostname** instead of the IP address for a more reliable connection — it stays the same even if the device's IP changes after a router reboot.

**Alternative methods** to find the IP address:

- **Shelly app:** Device detail → **Device info** → IP address
- **Shelly web UI:** Connect to the device AP before Wi-Fi setup — the IP is shown after saving
- **Router DHCP table:** Look for a hostname like `shelly1pm-AABBCCDDEE`

### Step 3 — Configure in TapHome

1. In TapHome, add a new **Packet Parser (HTTP)** module
2. **Address:** enter the mDNS hostname (e.g., `shelly1pm-AABBCCDDEE.local`) or IP address from Step 2
3. **Port:** `80` (default, no change needed)
4. Import the template — TapHome will poll `/status` to read device state

> [!NOTE]
> HTTP authentication is disabled by default on Shelly devices. If you have enabled login protection, TapHome does not support HTTP Basic Auth at this time — keep auth disabled for TapHome integration.

## Available devices 6

These devices appear in TapHome after import.

Shelly Plus 2PM Module

Service Attributes

|         |                                         |
|---------|-----------------------------------------|
| MAC     | Device MAC address from system config   |
| Profile | Active device profile — switch or cover |

Service Actions

|         |                                                                               |
|---------|-------------------------------------------------------------------------------|
| Reboot  | Reboots the device                                                            |
| Profile | Switches between switch and cover operating profiles — requires device reboot |

Custom Variables

Read (module)

```taphome
VAR response := SENDHTTPREQUEST("/rpc/Sys.GetConfig");
IF response.IsSuccess
  VAR content := response.Content;
  VAR responseHeaders := response.Headers;
  SysConfig := response.Content;
END;
 
response := SENDHTTPREQUEST("/rpc/Sys.GetStatus");
IF response.IsSuccess
  content := response.Content;
  responseHeaders := response.Headers;
  if(PARSEJSON(response.Content, "$.restart_required") = true, ADDERROR("Restart required"));
END
```

Service Attributes

MAC

```taphome
PARSEJSON(SysConfig, "$.device.mac");
```

Profile

```taphome
PARSEJSON(SysConfig, "$.device.profile");
```

Service Actions

Reboot

```taphome
VAR response := SENDHTTPREQUEST("/rpc/Shelly.Reboot");
IF response.IsSuccess
  VAR content := response.Content;
  VAR responseHeaders := response.Headers;
  Return("OK");
END;
```

Profile

Parameters: Profile

```taphome
var profile := SWITCH(pr, 1, "cover", "switch");
VAR response := SENDHTTPREQUEST("/rpc/Shelly.SetProfile?name=\""+profile+"\"");
IF response.IsSuccess
  VAR content := response.Content;
  VAR responseHeaders := response.Headers;
  Return("OK");
END;
```

Power Meter (Shutter) Electricity Meter Read-only

Energy metering for cover mode — instantaneous power (kW) and cumulative energy (kWh)

numeric Unit: kW / kWh json\_path

Service Attributes

|              |                          |
|--------------|--------------------------|
| Voltage      | Supply voltage in Volts  |
| Current      | Load current in Amperes  |
| Power Factor | Power factor of the load |

Read total consumption

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "switch"
    adderror("Device profile is set to switch");
else
    return(PARSEJSON(CoverStatus, "$.aenergy.total") / 1000);
end
```

Read demand

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "cover"
    return(PARSEJSON(CoverStatus, "$.apower", true) / 1000);
end
```

Read (module)

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "cover"
    var response := SENDHTTPREQUEST("/rpc/Cover.GetStatus?id=" + Id);
    IF response.IsSuccess
        VAR content := response.Content;
        VAR responseHeaders := response.Headers;
        CoverStatus := response.Content;
    END
end
```

Service Attributes

Voltage \[V]

```taphome
PARSEJSON(CoverStatus, "$.voltage", true);
```

Current \[A]

```taphome
PARSEJSON(CoverStatus, "$.current", true);
```

Power Factor

```taphome
PARSEJSON(CoverStatus, "$.pf", true);
```

Power Meter (Switch 1) Electricity Meter Read-only

Energy metering for switch channel 1 — instantaneous power (kW) and cumulative energy (kWh)

numeric Unit: kW / kWh json\_path

Service Attributes

|              |                          |
|--------------|--------------------------|
| Voltage      | Supply voltage in Volts  |
| Current      | Load current in Amperes  |
| Power Factor | Power factor of the load |

Read total consumption

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "cover"
    adderror("Device profile is set to cover");
else
    return(PARSEJSON(SwitchStatus, "$.aenergy.total", true) / 1000);
end
```

Read demand

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "switch"
    return(PARSEJSON(SwitchStatus, "$.apower", true) / 1000);
end
```

Read (module)

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "switch"
    var response := SENDHTTPREQUEST("/rpc/Switch.GetStatus?id=" + Id);
    IF response.IsSuccess
        VAR content := response.Content;
        VAR responseHeaders := response.Headers;
        SwitchStatus := response.Content;
    END
end
```

Service Attributes

Voltage \[V]

```taphome
PARSEJSON(SwitchStatus, "$.voltage", true);
```

Current \[A]

```taphome
PARSEJSON(SwitchStatus, "$.current", true);
```

Power Factor

```taphome
PARSEJSON(SwitchStatus, "$.pf", true);
```

Power Meter (Switch 2) Electricity Meter Read-only

Energy metering for switch channel 2 — instantaneous power (kW) and cumulative energy (kWh)

numeric Unit: kW / kWh json\_path

Service Attributes

|              |                          |
|--------------|--------------------------|
| Voltage      | Supply voltage in Volts  |
| Current      | Load current in Amperes  |
| Power Factor | Power factor of the load |

Read total consumption

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "cover"
    adderror("Device profile is set to cover");
else
    return(PARSEJSON(SwitchStatus, "$.aenergy.total", true) / 1000);
end
```

Read demand

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "switch"
    return(PARSEJSON(SwitchStatus, "$.apower", true) / 1000);
end
```

Read (module)

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "switch"
    var response := SENDHTTPREQUEST("/rpc/Switch.GetStatus?id=" + Id);
    IF response.IsSuccess
        VAR content := response.Content;
        VAR responseHeaders := response.Headers;
        SwitchStatus := response.Content;
    END
end
```

Service Attributes

Voltage \[V]

```taphome
PARSEJSON(SwitchStatus, "$.voltage", true);
```

Current \[A]

```taphome
PARSEJSON(SwitchStatus, "$.current", true);
```

Power Factor

```taphome
PARSEJSON(SwitchStatus, "$.pf", true);
```

Shutter Slide Read and write

Motorized cover control with position tracking — requires calibration for position control

numeric Unit: % json\_path

Service Attributes

|                            |                                                                            |
|----------------------------|----------------------------------------------------------------------------|
| Source                     | Source of the last cover command                                           |
| State                      | Current cover state — open, closed, opening, closing, stopped, calibrating |
| Current Position           | Current cover position in percent (0–100), null if uncalibrated            |
| Target Position            | Target position when cover is moving                                       |
| Move Timeout               | Seconds until auto-stop during movement                                    |
| Move Started at            | Timestamp when current movement started                                    |
| Calibrated                 | Whether position control is enabled (true after successful calibration)    |
| Temperature                | Internal device temperature in Celsius                                     |
| Initial State              | Cover behavior on power-up — open, closed, or stopped                      |
| Input Mode                 | Physical input wiring mode — single, dual, or detached                     |
| Power Limit                | Maximum power threshold in Watts for overpower protection                  |
| Voltage Limit              | Maximum voltage threshold in Volts for overvoltage protection              |
| Current Limit              | Maximum current threshold in Amperes for overcurrent protection            |
| Motor Idle Power Threshold | Power threshold below which the motor is considered idle (0–50 W)          |
| Motor Idle Confirm Period  | Duration motor must stay below idle threshold to confirm stop (0.25–2 s)   |
| Max Time Open              | Maximum opening time before auto-stop (0.1–300 s)                          |
| Max Time Close             | Maximum closing time before auto-stop (0.1–300 s)                          |
| Swap Inputs                | Whether S1/S2 input assignment is swapped                                  |
| Invert Directions          | Whether open/close directions are inverted                                 |
| Obstruction Detection      | Whether obstruction detection is enabled                                   |
| Safety Switch              | Whether the safety switch feature is enabled                               |

Service Actions

|                    |                                                          |
|--------------------|----------------------------------------------------------|
| Open               | Fully opens the cover                                    |
| Close              | Fully closes the cover                                   |
| Stop               | Stops cover movement immediately                         |
| Calibrate          | Starts cover calibration — required for position control |
| Go to Position     | Moves the cover to a specific position (0–100%)          |
| Reverse directions | Toggles invert\_directions config and reboots the device |

Read (module)

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "switch"
    adderror("Device profile is set to switch");
else
    var response := SENDHTTPREQUEST("/rpc/Cover.GetStatus?id=" + Id);
    IF response.IsSuccess
        VAR content := response.Content;
        VAR responseHeaders := response.Headers;
        CoverStatus := response.Content;
    END
    
    response := SENDHTTPREQUEST("/rpc/Cover.GetConfig?id=" + Id);
    IF response.IsSuccess
        content := response.Content;
        responseHeaders := response.Headers;
        CoverConfig := response.Content;
    END
end
```

Read blind level

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "switch"
    adderror("Device profile is set to switch");
else
    var response := SENDHTTPREQUEST("/rpc/Cover.GetStatus?id=" + Id);
    IF response.IsSuccess
        CoverStatus := response.Content;
    END
    if PARSEJSON(CoverStatus, "$.pos_control", true) = true
        var pos := -1;
        var curpos := PARSEJSON(CoverStatus, "$.current_pos", true);
        if ISNULL(curpos)
            adderror("Device lost its position. Open or close the cover completely to enable back position control.");
            return(0);
        end
        var target := PARSEJSON(CoverStatus, "$.target_pos", true);
        if(ISNULL(target), pos := curpos, pos := target);
        if PARSEJSON(CoverConfig, "$.invert_directions", true)
            return(linear(pos, 0, 0, 100, 1));
        else
            return(linear(pos, 0, 1, 100, 0));
        end
    else
        adderror("Device is not calibrated");
    end
end
```

Write blind level

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "switch"
    adderror("Device profile is set to switch");
else
    var pos := 0;
    if PARSEJSON(CoverConfig, "$.invert_directions", true)
        pos := linear(Bl, 0, 0, 1, 100);
    else
        pos := linear(Bl, 0, 100, 1, 0);
    end
    VAR response := SENDHTTPREQUEST("rpc/Cover.GoToPosition?id=" + Id + "&pos=" + pos);
    IF response.IsSuccess
      VAR content := response.Content;
      Return("OK");
    else
      return(parsejson(response.Content,"$.message"));
    END
end
```

Service Attributes

Source

```taphome
PARSEJSON(CoverStatus, "$.source", true);
```

State

```taphome
PARSEJSON(CoverStatus, "$.state", true);
```

Current Position

```taphome
PARSEJSON(CoverStatus, "$.current_pos", true);
```

Target Position

```taphome
PARSEJSON(CoverStatus, "$.target_pos", true);
```

Move Timeout

```taphome
PARSEJSON(CoverStatus, "$.move_timeout", true);
```

Move Started at

```taphome
PARSEJSON(CoverStatus, "$.move_started_at", true);
```

Calibrated

```taphome
PARSEJSON(CoverStatus, "$.pos_control", true);
```

Temperature \[°C]

```taphome
PARSEJSON(CoverStatus, "$.temperature.tC", true);
```

Initial State

```taphome
PARSEJSON(CoverConfig, "$.initial_state", true);
```

Input Mode

```taphome
PARSEJSON(CoverConfig, "$.in_mode", true);
```

Power Limit \[W]

```taphome
PARSEJSON(CoverConfig, "$.power_limit", true);
```

Voltage Limit \[V]

```taphome
PARSEJSON(CoverConfig, "$.voltage_limit", true);
```

Current Limit \[A]

```taphome
PARSEJSON(CoverConfig, "$.current_limit", true);
```

Motor Idle Power Threshold \[W]

```taphome
PARSEJSON(CoverConfig, "$.motor.idle_power_thr", true);
```

Motor Idle Confirm Period \[s]

```taphome
PARSEJSON(CoverConfig, "$.motor.idle_confirm_period", true);
```

Max Time Open \[s]

```taphome
PARSEJSON(CoverConfig, "$.maxtime_open", true);
```

Max Time Close \[s]

```taphome
PARSEJSON(CoverConfig, "$.maxtime_close", true);
```

Swap Inputs

```taphome
PARSEJSON(CoverConfig, "$.swap_inputs", true);
```

Invert Directions

```taphome
PARSEJSON(CoverConfig, "$.invert_directions", true);
```

Obstruction Detection

```taphome
PARSEJSON(CoverConfig, "$.obstruction_detection", true);
```

Safety Switch

```taphome
PARSEJSON(CoverConfig, "$.safety_switch", true);
```

Service Actions

Open

```taphome
VAR response := SENDHTTPREQUEST("rpc/Cover.Open?id=" + Id );
IF response.IsSuccess
  VAR content := response.Content;
  Return("OK");
else
  return(parsejson(response.Content,"$.message"));
END;
```

Close

```taphome
VAR response := SENDHTTPREQUEST("rpc/Cover.Close?id=" + Id );
IF response.IsSuccess
  VAR content := response.Content;
  Return("OK");
else
  return(parsejson(response.Content,"$.message"));
END;
```

Stop

```taphome
VAR response := SENDHTTPREQUEST("rpc/Cover.Stop?id=" + Id );
IF response.IsSuccess
  VAR content := response.Content;
  Return("OK");
else
  return(parsejson(response.Content,"$.message"));
END;
```

Calibrate

```taphome
VAR response := SENDHTTPREQUEST("rpc/Cover.Calibrate?id=" + Id );
IF response.IsSuccess
  VAR content := response.Content;
  Return("OK");
else
  return(parsejson(response.Content,"$.message"));
END;
```

Go to Position

Parameters: Position (0–100 pos)

```taphome
VAR response := SENDHTTPREQUEST("rpc/Cover.GoToPosition?id=" + Id + "&pos=" + pos);
IF response.IsSuccess
  VAR content := response.Content;
  Return("OK");
else
  return(parsejson(response.Content,"$.message"));
END;
```

Reverse directions

```taphome
var reverse := "false";
if(PARSEJSON(CoverConfig, "$.invert_directions"), reverse := "false", reverse := "true");
VAR response := SENDHTTPREQUEST("rpc/Cover.SetConfig?id=0&config={\"invert_directions\":" + reverse + "}");
IF response.IsSuccess
  SENDHTTPREQUEST("rpc/Shelly.Reboot");
  Return("OK");
else
  return(parsejson(response.Content,"$.message"));
END;
```

Switch 1 Switch Read and write

Relay output channel 1 — on/off control with power-up behavior and input mode configuration

boolean json\_path

Values / States: ON · OFF

Service Actions

|                   |                                            |
|-------------------|--------------------------------------------|
| Set Initial State | Configures the switch behavior on power-up |
| Set Mode          | Configures the physical input wiring mode  |

Read switch state

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "cover"
    adderror("Device profile is set to cover");
else
    RETURN(PARSEJSON(SwitchStatus, "$.output", true));
end
```

Write switch state

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "switch"
    VAR response := SENDHTTPREQUEST("rpc/Switch.Set?id=" + Id + "&on=" + if(St,"true","false"));
    IF response.IsSuccess = false
      ADDERROR(response.StatusCode);
    END
end
```

Read (module)

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "switch"
    var response := SENDHTTPREQUEST("/rpc/Switch.GetStatus?id=" + Id);
    IF response.IsSuccess
        VAR content := response.Content;
        VAR responseHeaders := response.Headers;
        SwitchStatus := response.Content;
    END
    
    response := SENDHTTPREQUEST("/rpc/Switch.GetConfig?id=" + Id);
    IF response.IsSuccess
        content := response.Content;
        responseHeaders := response.Headers;
        SwitchConfig := response.Content;
    END
end
```

Service Attributes

Source

```taphome
PARSEJSON(SwitchStatus, "$.source", true);
```

Temprature \[°C]

```taphome
PARSEJSON(SwitchStatus, "$.temperature.tC", true);
```

Initial State

```taphome
PARSEJSON(SwitchConfig, "$.initial_state", true);
```

Input Mode

```taphome
PARSEJSON(SwitchConfig, "$.in_mode", true);
```

Power Limit \[W]

```taphome
PARSEJSON(SwitchConfig, "$.power_limit", true);
```

Voltage Limit \[V]

```taphome
PARSEJSON(SwitchConfig, "$.voltage_limit", true);
```

Current Limit \[A]

```taphome
PARSEJSON(SwitchConfig, "$.current_limit", true);
```

Service Actions

Set Initial State

Parameters: Mode

```taphome
var mode := SWITCH(md, 1, "on", 2, "restore_last", 3, "match_input", "off");
VAR response := SENDHTTPREQUEST("rpc/Switch.SetConfig?id=" + Id +"&config={\"initial_state\":\""+mode+"\"}");
IF response.IsSuccess
  VAR content := response.Content;
  Return("OK");
else
  return(parsejson(response.Content,"$.message"));
END;
```

Set Mode

Parameters: Mode

```taphome
var mode := SWITCH(md, 1, "detached", "follow");
VAR response := SENDHTTPREQUEST("rpc/Switch.SetConfig?id=" + Id +"&config={\"in_mode\":\""+mode+"\"}");
IF response.IsSuccess
  VAR content := response.Content;
  Return("OK");
else
  return(parsejson(response.Content,"$.message"));
END;
```

Switch 2 Switch Read and write

Relay output channel 2 — on/off control with power-up behavior and input mode configuration

boolean json\_path

Values / States: ON · OFF

Service Actions

|                   |                                            |
|-------------------|--------------------------------------------|
| Set Initial State | Configures the switch behavior on power-up |
| Set Mode          | Configures the physical input wiring mode  |

Read switch state

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "cover"
    adderror("Device profile is set to cover");
else
    RETURN(PARSEJSON(SwitchStatus, "$.output", true));
end
```

Write switch state

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "switch"
    VAR response := SENDHTTPREQUEST("rpc/Switch.Set?id=" + Id + "&on=" + if(St,"true","false"));
    IF response.IsSuccess = false
      ADDERROR(response.StatusCode);
    END
end
```

Read (module)

```taphome
if PARSEJSON(SysConfig, "$.device.profile") = "switch"
    var response := SENDHTTPREQUEST("/rpc/Switch.GetStatus?id=" + Id);
    IF response.IsSuccess
        VAR content := response.Content;
        VAR responseHeaders := response.Headers;
        SwitchStatus := response.Content;
    END
    
    response := SENDHTTPREQUEST("/rpc/Switch.GetConfig?id=" + Id);
    IF response.IsSuccess
        content := response.Content;
        responseHeaders := response.Headers;
        SwitchConfig := response.Content;
    END
end
```

Service Attributes

Source

```taphome
PARSEJSON(SwitchStatus, "$.source", true);
```

Temprature \[°C]

```taphome
PARSEJSON(SwitchStatus, "$.temperature.tC", true);
```

Initial State

```taphome
PARSEJSON(SwitchConfig, "$.initial_state", true);
```

Input Mode

```taphome
PARSEJSON(SwitchConfig, "$.in_mode", true);
```

Power Limit \[W]

```taphome
PARSEJSON(SwitchConfig, "$.power_limit", true);
```

Voltage Limit \[V]

```taphome
PARSEJSON(SwitchConfig, "$.voltage_limit", true);
```

Current Limit \[A]

```taphome
PARSEJSON(SwitchConfig, "$.current_limit", true);
```

Service Actions

Set Initial State

Parameters: Mode

```taphome
var mode := SWITCH(md, 1, "on", 2, "restore_last", 3, "match_input", "off");
VAR response := SENDHTTPREQUEST("rpc/Switch.SetConfig?id=" + Id +"&config={\"initial_state\":\""+mode+"\"}");
IF response.IsSuccess
  VAR content := response.Content;
  Return("OK");
else
  return(parsejson(response.Content,"$.message"));
END;
```

Set Mode

Parameters: Mode

```taphome
var mode := SWITCH(md, 1, "detached", "follow");
VAR response := SENDHTTPREQUEST("rpc/Switch.SetConfig?id=" + Id +"&config={\"in_mode\":\""+mode+"\"}");
IF response.IsSuccess
  VAR content := response.Content;
  Return("OK");
else
  return(parsejson(response.Content,"$.message"));
END;
```

**Connection:** Packet Parser → HTTP • Hostname: `shellyplus2pm-{MAC}.local`

Possible improvements (8)

- Frequency — Network frequency in Hz, available in both Switch and Cover status responses
- Energy per Minute — Last 3 minute energy values in Wh, available but not exposed as separate device
- Input 1 State — Physical input state (input:0), available in both profiles
- Input 2 State — Physical input state (input:1), available in both profiles
- Switch Toggle — Toggle switch without knowing current state — could be added as service action
- Reset Energy Counters — Resets energy measurement counters — could be added as service action
- Slat Position — Slat/tilt position for venetian blinds, if hardware supports it
- WiFi Signal Strength — RSSI in dBm, available via WiFi component

## Import parameters

Enter these values when you import the XML.

| Asked in the app | Default       |
|------------------|---------------|
| IP address       | `192.168.0.1` |

## Sources

- Shelly Gen2+ RPC API Reference
  
  [shelly-api-docs.shelly.cloud](https://shelly-api-docs.shelly.cloud/gen2/) 2026-03-27
- Switch Component API
  
  [shelly-api-docs.shelly.cloud](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Switch/) 2026-03-27
- System (Sys) Component API
  
  [shelly-api-docs.shelly.cloud](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Sys/) 2026-03-27
- WiFi Component API
  
  [shelly-api-docs.shelly.cloud](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Wifi/) 2026-03-27
- MQTT Component API
  
  [shelly-api-docs.shelly.cloud](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/MQTT/) 2026-03-27
- HA Shelly Integration (Gen2+)
  
  [www.home-assistant.io](https://www.home-assistant.io/integrations/shelly/) 2026-03-27
- Shelly Plus 2PM Knowledge Base
  
  [kb.shelly.cloud](https://kb.shelly.cloud/knowledge-base/shelly-plus-2pm) 2026-03-29
- Cover Component API (Gen2+)
  
  [shelly-api-docs.shelly.cloud](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Cover/) 2026-03-29
- Shelly Plus 2PM Device API Reference
  
  [shelly-api-docs.shelly.cloud](https://shelly-api-docs.shelly.cloud/gen2/Devices/Gen2/ShellyPlus2PM/) 2026-03-29

## Related Documentation

- [Packet Parser Integration](https://taphome.com/en/compatibility/packet-parser-guide/)
- [Packet Parser (HTTP, TCP, UDP, FTP, MQTT)](https://taphome.com/en/docs/integration/packet-parser/)
- [Packet parser functions](https://taphome.com/en/docs/script/packet-parser/)
- [Parsing functions](https://taphome.com/en/docs/script/parsing-functions/)

