---
title: "Shelly Plus i4"
description: "Shelly Plus i4 Wi-Fi 4-channel digital input module. Detect push-button presses and toggle switch states via MQTT from TapHome — no relays, pure input."
url: "https://taphome.com/en/compatibility/shelly-plus-i4/"
language: en
lastmod: 2026-03-29
generator: hugo
ai:
  topics: ["mqtt","i/o-module","wifi","digital-input","push-button","reed-contact","4-channel"]
  questions: ["How to integrate Shelly Plus i4 with TapHome?","How to detect button presses with Shelly Plus i4 in TapHome?","How to connect Shelly Plus i4 via MQTT to TapHome?","What is the difference between button mode and switch mode on Shelly Plus i4?","How to configure Shelly Plus i4 inputs as push buttons or toggle switches?","Why does Shelly Plus i4 show \"Device is set as switch\" error in TapHome?","Can Shelly Plus i4 control relays directly?"]
---

# Shelly Plus i4

Communication: Packet Parser → MQTT

- [Shelly Plus i4 Product Page](https://www.shelly.com/en/products/shop/shelly-plus-i4)
- [Shelly Gen2+ Input Component API](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Input/)

> Network address
> 
> With the MQTT broker built into TapHome, enter `127.0.0.1` as the broker address in TapHome. In the device, enter the IP address of the TapHome Core and give the Core an IP reservation in the router.
> 
> [Network Preparation](https://taphome.com/en/docs/setup/network-preparation/)

## Integration guide

The Shelly Plus i4 is a compact Wi-Fi 4-channel digital input module. It has no relays or outputs — it functions purely as an input device that detects button presses and switch states on four independent terminals (SW1–SW4). It fits behind a standard wall switch (37 x 42 x 16 mm) and is powered by 110–240 VAC. TapHome communicates with the device over MQTT using Gen2+ JSON-RPC 2.0 notifications on the local network — no cloud connection is required.

Each of the four inputs can be independently configured as either **button mode** (detects single push, double push, long push) or **switch mode** (detects open/closed state). The TapHome template creates both a push-button device and a reed-contact device for each input — you use the one that matches how the input is configured in the Shelly web UI.

## Configuration

### MQTT broker setup

The Shelly Plus i4 communicates via MQTT. You need an MQTT broker running on your network (e.g., Mosquitto). In the Shelly web UI (`http://{device-ip}`), go to Settings → MQTT and enable MQTT, entering the broker IP address and port.

### Template import parameters

During TapHome template import, enter three parameters:

| Parameter | Description | Example |
|-----------|-------------|---------|
| **MQTT Broker IP** | IP address of the MQTT broker | `192.168.1.10` |
| **MQTT Broker Port** | Broker port (default 1883) | `1883` |
| **Shelly ID** | MQTT client ID from the Shelly web UI → Settings → MQTT | `shellyplusi4-xxxxxxxxxxxx` |

### Input mode configuration

After importing the template, configure each input in the Shelly web UI (`http://{device-ip}`) → Inputs:

- **Button mode** — for momentary push buttons. Use the corresponding Button 1–4 device in TapHome.
- **Switch mode** — for toggle switches or reed contacts. Use the corresponding Switch 1–4 device in TapHome.

Each physical input can only be one type at a time. If an input is set to switch mode but TapHome receives a button event (or vice versa), the listener script raises an error indicating the mismatch.

## Device capabilities

### Push-button detection (Button 1–4)

Four push-button devices listen for MQTT `NotifyEvent` messages on the `{device_id}/events/rpc` topic. Each button detects three press types and maps them to numeric values:

| Press type | Value |
|------------|-------|
| Single push | 1 |
| Long push | 2 |
| Double push | 3 |

The button devices are read-only — they report the last detected event. Each button listens for events from its corresponding input component (`input:0` through `input:3`).

### Switch/reed-contact detection (Switch 1–4)

Four reed-contact devices listen for MQTT `NotifyStatus` messages. Each switch reads the binary state of its corresponding input:

| State | Value |
|-------|-------|
| Closed (active) | 1 |
| Open (inactive) | 0 |

The switch devices are read-only with a 2.5-second poll interval. They are suitable for toggle switches, magnetic reed contacts, or any binary on/off sensor connected to the input terminals.

### Additional capabilities

The Shelly Plus i4 API also supports triple-push detection, raw button-down/button-up events, and a programmatic `Input.Trigger` method (unique to i4 devices) that can emit events without physical input. System diagnostics (uptime, MAC, WiFi RSSI) are available via HTTP RPC but not exposed in this MQTT-only template. These capabilities can be added in a future template update.

## Troubleshooting

### Button presses not detected

1. Verify the input is configured as **button** mode in the Shelly web UI → Inputs
2. Check that TapHome is connected to the MQTT broker and the Shelly ID matches the device's MQTT client ID
3. If TapHome shows "Device is set as switch" error, the input is in switch mode — change it to button mode in the Shelly web UI or use the Switch 1–4 device instead

### Switch state not updating

1. Verify the input is configured as **switch** mode in the Shelly web UI → Inputs
2. If TapHome shows "Device is set as button" error, the input is in button mode — change it to switch mode or use the Button 1–4 device instead
3. Toggle the physical switch and check the MQTT broker for `NotifyStatus` messages on the `shellyplusi4-{id}/events/rpc` topic

### Device not reachable

1. Verify the Shelly is connected to Wi-Fi — the blue LED should be constantly on
2. Confirm MQTT is enabled in the Shelly web UI → Settings → MQTT and the broker address is correct
3. Try using the mDNS hostname (`shellyplusi4-AABBCCDDEE.local`) to access the Shelly web UI
4. Check that the MQTT broker is running and accessible from both TapHome Core and the Shelly device

> [!NOTE]
> The Shelly Plus i4 has an MQTT rate limit of **80 notifications per 60-second window**. Rapid repeated button presses may exceed this limit and cause some events to be dropped. This is a firmware-level limitation.

## How to install in TapHome

### Prerequisites

- Shelly device connected to Wi-Fi (2.4 GHz), e.g. through the Shelly app or the device's own access point
- MQTT broker running on your local network (e.g., Mosquitto, Home Assistant, or TapHome built-in broker)
- TapHome CCU on the same network as the broker

> [!WARNING]
> On **Gen1** devices, enabling MQTT **disables Shelly Cloud**. Both cannot run simultaneously. On Gen2/Plus devices this limitation does not apply.

### Step 1 — Enable MQTT on the Shelly device

#### Gen1 devices (Shelly 1, 1PM, 2.5, EM, 3EM, Plug S, RGBW2, Dimmer, TRV…)

1. Open the Shelly web UI: `http://<device-ip>/`
2. Navigate to **Internet & Security** → **Advanced — MQTT**
3. Enable **MQTT**
4. Set **MQTT Server**: `<broker-ip>:<port>` (e.g., `192.168.1.10:1883`)
5. Optionally set **MQTT User** and **MQTT Password** if your broker requires authentication
6. Click **Save** — the device will reboot and connect to the broker

#### Gen2 / Plus devices (Shelly Plus 1, Plus 1PM, Plus 2PM, Plus Plug S, Plus H&T, Pro 3EM…)

1. Open the Shelly web UI: `http://<device-ip>/`
2. Navigate to **Settings** → **MQTT**
3. Enable **MQTT**
4. Set **Server**: `<broker-ip>:<port>` (e.g., `192.168.1.10:1883`)
5. The **Client ID** is pre-filled with the device ID (e.g., `shellyplus1pm-AABBCCDDEE`) — leave as-is unless you have a specific reason to change it
6. Click **Save** and reboot the device

With the TapHome built-in broker, `<broker-ip>` is the IP address of the TapHome Core. Give the Core an IP reservation in the router, otherwise the device loses the broker when the router changes the address → [Network Preparation](https://taphome.com/en/docs/setup/network-preparation/).

> [!TIP]
> To verify MQTT is working, use an MQTT client (e.g., MQTT Explorer) and subscribe to `shellies/#` (Gen1) or `<device-id>/#` (Gen2). You should see status messages from the device.

### Step 2 — Find the Device ID / MQTT Client ID

Some templates require a **Device ID** or **MQTT Client ID** parameter. This is the unique identifier used in MQTT topics.

- **Gen1:** found on the label as MAC address (e.g., `AABBCCDDEE`). Device ID = `shelly<model>-<mac>`, e.g., `shelly1pm-AABBCCDDEE`
- **Gen2/Plus:** found in the Shelly web UI under **Settings** → **Device Info** → **Device ID**, or on the device label

### Step 3 — Configure in TapHome

1. In TapHome, add a new **Packet Parser (MQTT)** module
2. **IP Address:** `127.0.0.1` for the TapHome built-in broker (the control unit connects to itself, the address never changes); for an external broker its IP address (e.g., `192.168.1.10`)
3. **Port:** `1883` (default; use `8883` for TLS)
4. **Device ID / MQTT Client ID:** enter the value from Step 2 (if required by the template)
5. Import the template — TapHome will subscribe to the device topics automatically

## Available devices 8

These devices appear in TapHome after import.

Shelly Plus i4 Module

Custom Variables

|               |
|---------------|
| `ID` (string) |

Button 1 Push Button Read-only

Push button on input:0 — detects single push (1), long push (2), double push (3)

numeric JSON-RPC event

Variable: `Button`

Listener

```taphome
Bp := 0;
#index of shelly
if INDEXOF(RECEIVEDMSG.TOPIC, ID) = 0
    VAR method := PARSEJSON(RECEIVEDMSG.PAYLOAD, "method", true);
    VAR params := PARSEJSON(RECEIVEDMSG.PAYLOAD, "params", true);

    IF method = "NotifyEvent"
        VAR zero := PARSEJSON(PARSEJSON(params, "events"),"[0]");
        VAR component := PARSEJSON(zero, "component");
        VAR event := PARSEJSON(zero, "event");
    
        if component = "input:0"
            Bp := SWITCH(event, "single_push", Bp := 1, "double_push", Bp :=3,  "long_push", Bp := 2, Bp := 0 );
            #RETURN(Bp);
        END
    elseif method = "NotifyStatus"
        IF( INDEXOF(params, "input:0") > -1, ADDERROR("Device is set as switch"));
    END
END
```

Button 2 Push Button Read-only

Push button on input:1 — detects single push (1), long push (2), double push (3)

numeric JSON-RPC event

Listener

```taphome
Bp := 0;

#index of shelly
if INDEXOF(RECEIVEDMSG.TOPIC, ID) = 0

    VAR method := PARSEJSON(RECEIVEDMSG.PAYLOAD, "method", true);
    VAR params := PARSEJSON(RECEIVEDMSG.PAYLOAD, "params", true);

    IF method = "NotifyEvent"
        VAR zero := PARSEJSON(PARSEJSON(params, "events"),"[0]");
        VAR component := PARSEJSON(zero, "component");
        VAR event := PARSEJSON(zero, "event");
    
        if component = "input:1"
            Bp := SWITCH(event, "single_push", Bp := 1, "double_push", Bp :=3,  "long_push", Bp := 2, Bp := 0 );
            #RETURN(Bp);
        END
    elseif method = "NotifyStatus"
        IF( INDEXOF(params, "input:0") > -1, ADDERROR("Device is set as switch"));
    END
END
```

Button 3 Push Button Read-only

Push button on input:2 — detects single push (1), long push (2), double push (3)

numeric JSON-RPC event

Listener

```taphome
Bp := 0;

#index of shelly
if INDEXOF(RECEIVEDMSG.TOPIC, ID) = 0

    VAR method := PARSEJSON(RECEIVEDMSG.PAYLOAD, "method", true);
    VAR params := PARSEJSON(RECEIVEDMSG.PAYLOAD, "params", true);

    IF method = "NotifyEvent"
        VAR zero := PARSEJSON(PARSEJSON(params, "events"),"[0]");
        VAR component := PARSEJSON(zero, "component");
        VAR event := PARSEJSON(zero, "event");
    
        if component = "input:2"
            Bp := SWITCH(event, "single_push", Bp := 1, "double_push", Bp :=3,  "long_push", Bp := 2, Bp := 0 );
            #RETURN(Bp);
        END
    elseif method = "NotifyStatus"
        IF( INDEXOF(params, "input:0") > -1, ADDERROR("Device is set as switch"));
    END
END
```

Button 4 Push Button Read-only

Push button on input:3 — detects single push (1), long push (2), double push (3)

numeric JSON-RPC event

Listener

```taphome
Bp := 0;

#index of shelly
if INDEXOF(RECEIVEDMSG.TOPIC, ID) = 0

    VAR method := PARSEJSON(RECEIVEDMSG.PAYLOAD, "method", true);
    VAR params := PARSEJSON(RECEIVEDMSG.PAYLOAD, "params", true);

    IF method = "NotifyEvent"
        VAR zero := PARSEJSON(PARSEJSON(params, "events"),"[0]");
        VAR component := PARSEJSON(zero, "component");
        VAR event := PARSEJSON(zero, "event");
    
        if component = "input:3"
            Bp := SWITCH(event, "single_push", Bp := 1, "double_push", Bp :=3,  "long_push", Bp := 2, Bp := 0 );
            #RETURN(Bp);
        END
    elseif method = "NotifyStatus"
        IF( INDEXOF(params, "input:0") > -1, ADDERROR("Device is set as switch"));
    END
END
```

Switch 1 Reed Contact Read-only

Reed contact on input:0 — closed (1), open (0)

boolean JSON-RPC status

Listener

```taphome
#index of shelly
if INDEXOF(RECEIVEDMSG.TOPIC, ID) = 0

    VAR method := PARSEJSON(RECEIVEDMSG.PAYLOAD, "method", true);
    VAR params := PARSEJSON(RECEIVEDMSG.PAYLOAD, "params", true);

    IF(method ="NotifyEvent")
    VAR zero := PARSEJSON(PARSEJSON(params, "events"),"[0]");
    VAR component := PARSEJSON(zero, "component");
    
    if component = "input:0"
    ADDERROR("Device is set as button");
    END
    
    IF(method = "NotifyStatus")
    IF( INDEXOF(params, "input:0") > -1)
        VAR input := PARSEJSON(params, "input:0");
        SWITCH(PARSEJSON(input, "state"), true, Rc := 1, Rc := 0);
    END  
    END
END
END
```

Switch 2 Reed Contact Read-only

Reed contact on input:1 — closed (1), open (0)

boolean JSON-RPC status

Listener

```taphome
#index of shelly
if INDEXOF(RECEIVEDMSG.TOPIC, ID) = 0

    VAR method := PARSEJSON(RECEIVEDMSG.PAYLOAD, "method", true);
    VAR params := PARSEJSON(RECEIVEDMSG.PAYLOAD, "params", true);

    IF(method ="NotifyEvent")
    VAR zero := PARSEJSON(PARSEJSON(params, "events"),"[0]");
    VAR component := PARSEJSON(zero, "component");
    
    if component = "input:1"
    ADDERROR("Device is set as button");
    END
    
    IF(method = "NotifyStatus")
    IF( INDEXOF(params, "input:1") > -1)
    VAR input := PARSEJSON(params, "input:1");
        SWITCH(PARSEJSON(input, "state"), true, Rc := 1, Rc := 0);
    END  
    END
END
END
```

Switch 3 Reed Contact Read-only

Reed contact on input:2 — closed (1), open (0)

boolean JSON-RPC status

Listener

```taphome
#index of shelly
if INDEXOF(RECEIVEDMSG.TOPIC, ID) = 0

    VAR method := PARSEJSON(RECEIVEDMSG.PAYLOAD, "method", true);
    VAR params := PARSEJSON(RECEIVEDMSG.PAYLOAD, "params", true);

    IF(method ="NotifyEvent")
    VAR zero := PARSEJSON(PARSEJSON(params, "events"),"[0]");
    VAR component := PARSEJSON(zero, "component");
    
    if component = "input:2"
    ADDERROR("Device is set as button");
    END
    
    IF(method = "NotifyStatus")
    IF( INDEXOF(params, "input:2") > -1)
    VAR input := PARSEJSON(params, "input:2");
        SWITCH(PARSEJSON(input, "state"), true, Rc := 1, Rc := 0);
    END  
    END
END
END
```

Switch 4 Reed Contact Read-only

Reed contact on input:3 — closed (1), open (0)

boolean JSON-RPC status

Listener

```taphome
#index of shelly
if INDEXOF(RECEIVEDMSG.TOPIC, ID) = 0

    VAR method := PARSEJSON(RECEIVEDMSG.PAYLOAD, "method", true);
    VAR params := PARSEJSON(RECEIVEDMSG.PAYLOAD, "params", true);

    IF(method ="NotifyEvent")
    VAR zero := PARSEJSON(PARSEJSON(params, "events"),"[0]");
    VAR component := PARSEJSON(zero, "component");
    
    if component = "input:3"
    ADDERROR("Device is set as button");
    END
    
    IF(method = "NotifyStatus")
    IF( INDEXOF(params, "input:3") > -1)
    VAR input := PARSEJSON(params, "input:3");
        SWITCH(PARSEJSON(input, "state"), true, Rc := 1, Rc := 0);
    END  
    END
END
END
```

**Connection:** Packet Parser → MQTT • Hostname: `shellyplusi4-{MAC}.local`

Possible improvements (7)

- Triple Push Detection — Input component supports triple\_push events but template only maps single\_push, double\_push, long\_push
- Button Press/Release Events — Raw button-down and button-up events available via MQTT but not captured by template
- Programmatic Input Trigger — Input.Trigger method allows emitting events without physical input — unique to i4/i4 Gen3 devices
- System Status (uptime, RAM, MAC, time) — Available via HTTP /rpc/Sys.GetStatus but template uses MQTT only — no HTTP polling configured
- WiFi Status (SSID, IP, RSSI) — Available via HTTP /rpc/WiFi.GetStatus but template uses MQTT only
- Analog Input Mode — Input component supports analog mode (0-100%) but template does not implement it — Plus i4 hardware supports digital inputs only
- Counter/Pulse Input Mode — Input component supports pulse counting mode but template does not implement it

## Import parameters

Enter these values when you import the XML.

| Asked in the app       | Default                     |
|------------------------|-----------------------------|
| Mqtt Broker IP address | `192.168.0.1`               |
| Mqtt Broker port       | `1883`                      |
| Shelly ID              | `shellyplusi4-xxxxxxxxxxxx` |

## Sources

- Shelly Gen2+ RPC API Reference
  
  [shelly-api-docs.shelly.cloud](https://shelly-api-docs.shelly.cloud/gen2/) 2026-03-29
- Shelly Gen2+ System Component API
  
  [shelly-api-docs.shelly.cloud](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Shelly/) 2026-03-29
- Shelly Gen2+ WiFi Component API
  
  [shelly-api-docs.shelly.cloud](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Wifi/) 2026-03-29
- Shelly Gen2+ MQTT Component API
  
  [shelly-api-docs.shelly.cloud](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Mqtt/) 2026-03-29
- Home Assistant Shelly Integration
  
  [www.home-assistant.io](https://www.home-assistant.io/integrations/shelly/) 2026-03-29
- Shelly Gen2+ Input Component API
  
  [shelly-api-docs.shelly.cloud](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Input/) 2026-03-29
- Shelly Plus i4 Knowledge Base
  
  [kb.shelly.cloud](https://kb.shelly.cloud/knowledge-base/shelly-plus-i4) 2026-03-29

## Related Documentation

- [MQTT Integration](https://taphome.com/en/compatibility/mqtt-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/)
- [MQTT Broker](https://taphome.com/en/docs/integration/packet-parser/mqtt-broker/)
- [Listener scripts](https://taphome.com/en/docs/script/listener-scripts/)

