---
title: "Shelly 3EM MQTT"
description: "Per-phase active power, voltage, current, power factor and bidirectional energy plus contactor control via MQTT. TapHome template for Shelly 3EM Gen1."
url: "https://taphome.com/en/compatibility/shelly-3em-gen1-mqtt/"
language: en
lastmod: 2026-10-08
generator: hugo
ai:
  topics: ["mqtt","electric-meter","3-phase","wifi","energy-metering","bidirectional-metering","mdns"]
  questions: ["How to integrate Shelly 3EM with TapHome via MQTT?","What does the Shelly 3EM MQTT TapHome template measure per phase?","How to find the Shelly 3EM Device ID for the MQTT template?","Why is the Shelly 3EM MQTT topic prefix shellyem3- instead of shelly3em-?","Does the Shelly 3EM MQTT template support bidirectional metering for solar?","How to reset per-phase energy counters on the Shelly 3EM from TapHome?"]
---

# Shelly 3EM MQTT

Communication: Packet Parser → MQTT

- [Shelly 3EM Product Page](https://www.shelly.com/en/products/shop/shelly-3em)

> 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 3EM is a 3-phase Wi-Fi energy meter from Shelly's first generation (Gen1). It measures active power, voltage, current, power factor and lifetime energy independently for each of three phases using three included 120 A split-core CT clamps, and includes a built-in 10 A relay typically used to drive an external power contactor coil. TapHome communicates with the device over MQTT — the device pushes per-phase measurements to a broker, the TapHome PacketParser module subscribes to the `shellies/#` topic tree and routes the values to four child devices (3 electric meters + 1 contactor switch).

This is the **MQTT variant** of the Shelly 3EM template. An HTTP variant is also available — choose MQTT when you already run a local MQTT broker, want push-based updates instead of polling, or need to share the meter with multiple consumers (TapHome plus another system). Note that enabling MQTT on Gen1 firmware **disables Shelly Cloud** — the two cannot run simultaneously.

## Configuration

### Enabling MQTT in the Shelly 3EM

Open the Shelly 3EM web UI (`http://{device-ip}` or `http://shelly3em-{MAC}.local`) and configure the MQTT client:

1. Go to **Internet & Security** → **Advanced - Developer Settings**
2. Tick **Enable action execution via MQTT**
3. Fill **Server** with `{MQTT broker IP address}:{port}` — typically `192.168.1.10:1883`
4. (Optional) Set **Username** and **Password** if the broker requires authentication
5. Click **SAVE** — the device reboots and connects to the broker

> [!WARNING]
> Gen1 Shelly devices do **not** support MQTT over TLS. Communication between the device and the broker is unencrypted plain TCP on port 1883. Username and password are sent in plaintext. Use the MQTT broker only on a trusted local network.

> [!NOTE]
> Enabling MQTT automatically **disables Shelly Cloud** on Gen1 firmware. To revert, untick the MQTT option and re-enable Cloud in Internet & Security.

### Finding the Device ID

The TapHome template subscribes to `shellies/shellyem3-{dID}/#`, where `{dID}` is the device's MAC suffix used as the MQTT topic prefix.

To find it in the Shelly 3EM web UI:

1. Open the device web UI in a browser
2. Go to **Settings** → **Device Info**
3. Copy the **first Device ID string** (NOT the value in brackets) — this equals the WiFi MAC address (e.g., `DC4F227649A1`)

Alternatively, query `GET http://{device-ip}/settings` and read the `mqtt.id` field.

### Template setup

After importing the template in TapHome, set three import parameters:

| Parameter | Description | Example |
|-----------|-------------|---------|
| **IpAddress** | MQTT broker IP address | `192.168.1.10` |
| **Port** | MQTT broker port | `1883` |
| **dID** | Device ID (MAC suffix) of the Shelly 3EM | `DC4F227649A1` |

The module then subscribes to `shellies/#` (QoS 0) and listener scripts route per-phase emeter and relay messages to the corresponding child devices. The default MQTT update period of the device is 30 seconds — it can be reduced via `GET http://{device-ip}/settings?mqtt_update_period=N` (set `0` to publish only on change).

> [!NOTE]
> The MQTT topic prefix on the wire is `shellyem3-{MAC}` while the device's mDNS hostname is `shelly3em-{MAC}.local` — Shelly uses two different forms for the same device. The template follows the actual MQTT topic prefix (`shellyem3-`). If MQTT messages do not arrive, subscribe to `shellies/#` with an MQTT client to verify the prefix the firmware is using.

## Device capabilities

### Per-phase active power and lifetime energy

The template creates three electric meter devices — one for each phase (CT clamp 1 → phase A, clamp 2 → phase B, clamp 3 → phase C). Each meter reads two values:

- **Active power** — instantaneous power from `shellies/shellyem3-{dID}/emeter/{i}/power` (W), divided by 1000 and stored as kW
- **Total energy consumed** — lifetime cumulative energy from `.../emeter/{i}/total` (Wh), divided by 1000 and stored as kWh

Each CT clamp is rated for **120 A** and is non-invasive (clip-on, no wire cutting required). The included 3 CT clamps are individually marked and calibrated — they are NOT interchangeable between channels.

### Per-phase electrical parameters

Each electric meter exposes four service attributes for advanced monitoring:

- **Voltage** (V) — RMS line-to-neutral voltage on that phase (`.../emeter/{i}/voltage`)
- **Current** (A) — RMS current measured by the corresponding CT clamp (`.../emeter/{i}/current`)
- **Power factor** — ratio of active to apparent power, range −1.00 to 1.00 (`.../emeter/{i}/pf`)
- **Returned Energy** (Wh) — lifetime energy returned **to** the grid on that phase (`.../emeter/{i}/total_returned`), useful for PV / bidirectional metering

The combination of `total` (consumed) and `total_returned` (exported) per phase makes the template suitable for solar / grid-feed installations.

### Energy counter reset

Each phase has a **Reset Total** service action that publishes `reset_totals` to `shellies/shellyem3-{dID}/emeter/{i}/command`. This zeroes both the `total` and `total_returned` counters for that specific phase — useful when re-purposing the meter or starting a new measurement period.

### Contactor relay

The on-board 10 A relay is exposed as a switch device. The state is read from `shellies/shellyem3-{dID}/relay/0` (`on` → 1, anything else → 0) and controlled by publishing `on` or `off` to `.../relay/0/command`. The relay is rated 10 A / 240 V AC and is typically wired through the `I` (line input) and `O` (relay output) terminals to drive the coil of an external power contactor for switching higher loads.

> [!TIP]
> The MQTT template does not publish a 3-phase total power sum (`total_power` is HTTP-only on Gen1). Create a TapHome virtual device that sums the three per-phase power values if you need a single household-power figure.

## Troubleshooting

### No MQTT messages received

1. Confirm MQTT is enabled in the Shelly web UI (**Internet & Security** → **Advanced - Developer Settings** → **Enable action execution via MQTT**) and the device has rebooted after saving
2. Verify the broker IP and port in the device match the `IpAddress`/`Port` import parameters in TapHome
3. Subscribe to `shellies/#` with an MQTT client (e.g., MQTT Explorer, `mosquitto_sub`) and check whether the device publishes anything — verify the actual topic prefix (`shellyem3-{dID}`) matches the `dID` you entered in TapHome
4. Ensure the MQTT broker is running and reachable from both the Shelly 3EM and the TapHome Core
5. If the device IP recently changed, try connecting to the mDNS hostname `shelly3em-{MAC}.local` to verify the device is reachable on the network

### Energy readings show zero or implausible values

1. Confirm each CT clamp is connected to the **correct** input — clamp marked `IA` must be wired to terminals `IA-/IA+`, `IB` to `IB-/IB+`, `IC` to `IC-/IC+`. The clamps are calibrated per channel and are not interchangeable.
2. Verify the **arrow on the CT clamp body** points in the direction of current flow (from source towards load). A reversed clamp produces a negative power factor and inverts the consumption / return classification.
3. Check that voltage inputs `VA`, `VB`, `VC` are wired to the matching phases that the CT clamps measure — mismatched voltage / current pairing produces wrong power and power-factor readings.
4. If a single phase reads zero while the others are correct, swap that CT clamp with a known-good one to isolate clamp vs. circuit.

### Cannot enable MQTT — Cloud is in use

On Gen1 firmware, MQTT and Shelly Cloud are mutually exclusive. If the **Enable action execution via MQTT** checkbox is greyed out, disable Shelly Cloud first under **Internet & Security** → **Cloud**, then re-open the MQTT settings.

### Shelly Cloud history disappeared after enabling MQTT

This is expected — enabling MQTT disables Cloud, including its 365-day history retention. If you need both real-time MQTT control in TapHome and long-term history, route MQTT messages through your own broker and keep historical data in TapHome (or a separate logging system).

> [!WARNING]
> Each CT clamp must always be wired to the Shelly 3EM terminals **before** clipping it around a live conductor. Voltage induced across an open CT secondary winding can reach dangerous levels and damage the clamp.

## 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 4

These devices appear in TapHome after import.

Shelly 3EM MQTT Module

Custom Variables

`dID` (string) MAC suffix of the Shelly 3EM that forms the MQTT topic prefix shellies/shellyem3-{dID}/... — find it in Shelly web UI → Settings → Device Info (first string, NOT the value in brackets)

Open Shelly 3EM web UI → Settings → Device Info → copy the first Device ID string (NOT the value in brackets); equals the WiFi MAC address (e.g. DC4F227649A1)

Electric Meter (Phase 1) Electricity Meter Read-only

Active power (kW) and lifetime energy (kWh) on phase A — read from CT clamp 1, with W→kW and Wh→kWh conversion

numeric Unit: kW / kWh

Service Attributes

|                 |                                                                                               |
|-----------------|-----------------------------------------------------------------------------------------------|
| Returned Energy | Lifetime energy returned to the grid on phase A (Wh) — useful for PV / bidirectional metering |
| Voltage         | RMS line-to-neutral voltage on phase A (V)                                                    |
| Current         | RMS current measured by CT clamp 1 (A)                                                        |
| Power Factor    | Power factor on phase A — ratio of active to apparent power, range −1.00 to 1.00              |

Service Actions

|             |                                                                               |
|-------------|-------------------------------------------------------------------------------|
| Reset Total | Resets both the total and total\_returned energy counters for phase A to zero |

Read total consumption

```taphome
# Simple HTTP Request:
# VAR response := SENDHTTPREQUEST("/example/getValue");
# IF response.IsSuccess
#  VAR content := response.Content;
#  VAR responseHeaders := response.Headers;
#  RETURN(PARSEXML(content, "//element1/value1"));
# ELSE
#  ADDERROR(response.StatusCode + " (" + response.ReasonPhrase + ")");
#  RETURN(NaN);
# END
#
# Set Http request method, body and headers
# VAR response := SENDHTTPREQUEST("/example/getValue", "GET", "some data", "header1:value1", "header2:value2", ...);
# OR
# VAR request := HTTPREQUEST("/example/getValue", "POST", "some data");
# request.headers := { "header1:value1", "header2:value2", ...};
# request.method := "GET";
# request.data := null;
# VAR response := SENDHTTPREQUEST(request);
#
#
# Send TCP, UDP data:
# VAR data1 := BYTECOLLECTION("0a bb ea df 01");
# SENDDATA(data1);
# VAR data2 := "{\"name\":\"John\", \"age\":32}";
# SENDDATA(data2);
# VAR data3 := TOBYTES("{\"name\":\"John\", \"age\":32}", "iso-8859-1");
# SENDDATA(data3);
# Process received TCP or UDP data and set device values in the Listener script
#
#
# Download data from FTP:
# FTPDOWNLOAD("filePath");
```

Read demand

```taphome
# Simple HTTP Request:
# VAR response := SENDHTTPREQUEST("/example/getValue");
# IF response.IsSuccess
#  VAR content := response.Content;
#  VAR responseHeaders := response.Headers;
#  RETURN(PARSEXML(content, "//element1/value1"));
# ELSE
#  ADDERROR(response.StatusCode + " (" + response.ReasonPhrase + ")");
#  RETURN(NaN);
# END
#
# Set Http request method, body and headers
# VAR response := SENDHTTPREQUEST("/example/getValue", "GET", "some data", "header1:value1", "header2:value2", ...);
# OR
# VAR request := HTTPREQUEST("/example/getValue", "POST", "some data");
# request.headers := { "header1:value1", "header2:value2", ...};
# request.method := "GET";
# request.data := null;
# VAR response := SENDHTTPREQUEST(request);
#
#
# Send TCP, UDP data:
# VAR data1 := BYTECOLLECTION("0a bb ea df 01");
# SENDDATA(data1);
# VAR data2 := "{\"name\":\"John\", \"age\":32}";
# SENDDATA(data2);
# VAR data3 := TOBYTES("{\"name\":\"John\", \"age\":32}", "iso-8859-1");
# SENDDATA(data3);
# Process received TCP or UDP data and set device values in the Listener script
#
#
# Download data from FTP:
# FTPDOWNLOAD("filePath");
```

Listener

```taphome
IF(RECEIVEDMSG.TOPIC = "shellies/shellyem3-"+dID+"/emeter/0/power")
 Ed := todouble(TOSTRING(RECEIVEDMSG.PAYLOAD))/1000;
elseif(RECEIVEDMSG.TOPIC = "shellies/shellyem3-"+dID+"/emeter/0/total")
 To := todouble(TOSTRING(RECEIVEDMSG.PAYLOAD))/1000;
END
```

Service Attributes

returned energy \[Wh]

```taphome
IF(parsejson(x, "Topic") = "shellies/shellyem3-"+dID+"/emeter/0/total_returned")
 return(parsejson(x, "Payload"));
END
```

voltage \[V]

```taphome
IF(parsejson(x, "Topic") = "shellies/shellyem3-"+dID+"/emeter/0/voltage")
 return(todouble(parsejson(x, "Payload")));
END
```

current \[A]

```taphome
IF(parsejson(x, "Topic") = "shellies/shellyem3-"+dID+"/emeter/0/current")
 return(todouble(parsejson(x, "Payload")));
END
```

power factor

```taphome
IF(parsejson(x, "Topic") = "shellies/shellyem3-"+dID+"/emeter/0/pf")
 return(todouble(parsejson(x, "Payload")));
END
```

Service Actions

Reset total

```taphome
mqttpublish("shellies/shellyem3-"+dID+"/emeter/0/command", "reset_totals");
```

Electric Meter (Phase 2) Electricity Meter Read-only

Active power (kW) and lifetime energy (kWh) on phase B — read from CT clamp 2, with W→kW and Wh→kWh conversion

numeric Unit: kW / kWh

Service Attributes

|                 |                                                                                               |
|-----------------|-----------------------------------------------------------------------------------------------|
| Returned Energy | Lifetime energy returned to the grid on phase B (Wh) — useful for PV / bidirectional metering |
| Voltage         | RMS line-to-neutral voltage on phase B (V)                                                    |
| Current         | RMS current measured by CT clamp 2 (A)                                                        |
| Power Factor    | Power factor on phase B — ratio of active to apparent power, range −1.00 to 1.00              |

Service Actions

|             |                                                                               |
|-------------|-------------------------------------------------------------------------------|
| Reset Total | Resets both the total and total\_returned energy counters for phase B to zero |

Read total consumption

```taphome
# Simple HTTP Request:
# VAR response := SENDHTTPREQUEST("/example/getValue");
# IF response.IsSuccess
#  VAR content := response.Content;
#  VAR responseHeaders := response.Headers;
#  RETURN(PARSEXML(content, "//element1/value1"));
# ELSE
#  ADDERROR(response.StatusCode + " (" + response.ReasonPhrase + ")");
#  RETURN(NaN);
# END
#
# Set Http request method, body and headers
# VAR response := SENDHTTPREQUEST("/example/getValue", "GET", "some data", "header1:value1", "header2:value2", ...);
# OR
# VAR request := HTTPREQUEST("/example/getValue", "POST", "some data");
# request.headers := { "header1:value1", "header2:value2", ...};
# request.method := "GET";
# request.data := null;
# VAR response := SENDHTTPREQUEST(request);
#
#
# Send TCP, UDP data:
# VAR data1 := BYTECOLLECTION("0a bb ea df 01");
# SENDDATA(data1);
# VAR data2 := "{\"name\":\"John\", \"age\":32}";
# SENDDATA(data2);
# VAR data3 := TOBYTES("{\"name\":\"John\", \"age\":32}", "iso-8859-1");
# SENDDATA(data3);
# Process received TCP or UDP data and set device values in the Listener script
#
#
# Download data from FTP:
# FTPDOWNLOAD("filePath");
```

Read demand

```taphome
# Simple HTTP Request:
# VAR response := SENDHTTPREQUEST("/example/getValue");
# IF response.IsSuccess
#  VAR content := response.Content;
#  VAR responseHeaders := response.Headers;
#  RETURN(PARSEXML(content, "//element1/value1"));
# ELSE
#  ADDERROR(response.StatusCode + " (" + response.ReasonPhrase + ")");
#  RETURN(NaN);
# END
#
# Set Http request method, body and headers
# VAR response := SENDHTTPREQUEST("/example/getValue", "GET", "some data", "header1:value1", "header2:value2", ...);
# OR
# VAR request := HTTPREQUEST("/example/getValue", "POST", "some data");
# request.headers := { "header1:value1", "header2:value2", ...};
# request.method := "GET";
# request.data := null;
# VAR response := SENDHTTPREQUEST(request);
#
#
# Send TCP, UDP data:
# VAR data1 := BYTECOLLECTION("0a bb ea df 01");
# SENDDATA(data1);
# VAR data2 := "{\"name\":\"John\", \"age\":32}";
# SENDDATA(data2);
# VAR data3 := TOBYTES("{\"name\":\"John\", \"age\":32}", "iso-8859-1");
# SENDDATA(data3);
# Process received TCP or UDP data and set device values in the Listener script
#
#
# Download data from FTP:
# FTPDOWNLOAD("filePath");
```

Listener

```taphome
IF(RECEIVEDMSG.TOPIC = "shellies/shellyem3-"+dID+"/emeter/1/power")
 Ed := todouble(TOSTRING(RECEIVEDMSG.PAYLOAD))/1000;
 elseif(RECEIVEDMSG.TOPIC = "shellies/shellyem3-"+dID+"/emeter/1/total")
 To := todouble(TOSTRING(RECEIVEDMSG.PAYLOAD))/1000;
END
```

Service Attributes

total returned \[Wh]

```taphome
IF(parsejson(x, "Topic") = "shellies/shellyem3-"+dID+"/emeter/1/total_returned")
 return(todouble(parsejson(x, "Payload")));
END
```

voltage \[V]

```taphome
IF(parsejson(x, "Topic") = "shellies/shellyem3-"+dID+"/emeter/1/voltage")
 return(todouble(parsejson(x, "Payload")));
END
```

current \[A]

```taphome
IF(parsejson(x, "Topic") = "shellies/shellyem3-"+dID+"/emeter/1/current")
 return(todouble(parsejson(x, "Payload")));
END
```

power factor

```taphome
IF(parsejson(x, "Topic") = "shellies/shellyem3-"+dID+"/emeter/1/pf")
 return(todouble(parsejson(x, "Payload")));
END
```

Service Actions

Reset total

```taphome
mqttpublish("shellies/shellyem3-"+dID+"/emeter/1/command", "reset_totals");
```

Electric Meter (Phase 3) Electricity Meter Read-only

Active power (kW) and lifetime energy (kWh) on phase C — read from CT clamp 3, with W→kW and Wh→kWh conversion

numeric Unit: kW / kWh

Service Attributes

|                 |                                                                                               |
|-----------------|-----------------------------------------------------------------------------------------------|
| Returned Energy | Lifetime energy returned to the grid on phase C (Wh) — useful for PV / bidirectional metering |
| Voltage         | RMS line-to-neutral voltage on phase C (V)                                                    |
| Current         | RMS current measured by CT clamp 3 (A)                                                        |
| Power Factor    | Power factor on phase C — ratio of active to apparent power, range −1.00 to 1.00              |

Service Actions

|             |                                                                               |
|-------------|-------------------------------------------------------------------------------|
| Reset Total | Resets both the total and total\_returned energy counters for phase C to zero |

Read total consumption

```taphome
# Simple HTTP Request:
# VAR response := SENDHTTPREQUEST("/example/getValue");
# IF response.IsSuccess
#  VAR content := response.Content;
#  VAR responseHeaders := response.Headers;
#  RETURN(PARSEXML(content, "//element1/value1"));
# ELSE
#  ADDERROR(response.StatusCode + " (" + response.ReasonPhrase + ")");
#  RETURN(NaN);
# END
#
# Set Http request method, body and headers
# VAR response := SENDHTTPREQUEST("/example/getValue", "GET", "some data", "header1:value1", "header2:value2", ...);
# OR
# VAR request := HTTPREQUEST("/example/getValue", "POST", "some data");
# request.headers := { "header1:value1", "header2:value2", ...};
# request.method := "GET";
# request.data := null;
# VAR response := SENDHTTPREQUEST(request);
#
#
# Send TCP, UDP data:
# VAR data1 := BYTECOLLECTION("0a bb ea df 01");
# SENDDATA(data1);
# VAR data2 := "{\"name\":\"John\", \"age\":32}";
# SENDDATA(data2);
# VAR data3 := TOBYTES("{\"name\":\"John\", \"age\":32}", "iso-8859-1");
# SENDDATA(data3);
# Process received TCP or UDP data and set device values in the Listener script
#
#
# Download data from FTP:
# FTPDOWNLOAD("filePath");
```

Read demand

```taphome
# Simple HTTP Request:
# VAR response := SENDHTTPREQUEST("/example/getValue");
# IF response.IsSuccess
#  VAR content := response.Content;
#  VAR responseHeaders := response.Headers;
#  RETURN(PARSEXML(content, "//element1/value1"));
# ELSE
#  ADDERROR(response.StatusCode + " (" + response.ReasonPhrase + ")");
#  RETURN(NaN);
# END
#
# Set Http request method, body and headers
# VAR response := SENDHTTPREQUEST("/example/getValue", "GET", "some data", "header1:value1", "header2:value2", ...);
# OR
# VAR request := HTTPREQUEST("/example/getValue", "POST", "some data");
# request.headers := { "header1:value1", "header2:value2", ...};
# request.method := "GET";
# request.data := null;
# VAR response := SENDHTTPREQUEST(request);
#
#
# Send TCP, UDP data:
# VAR data1 := BYTECOLLECTION("0a bb ea df 01");
# SENDDATA(data1);
# VAR data2 := "{\"name\":\"John\", \"age\":32}";
# SENDDATA(data2);
# VAR data3 := TOBYTES("{\"name\":\"John\", \"age\":32}", "iso-8859-1");
# SENDDATA(data3);
# Process received TCP or UDP data and set device values in the Listener script
#
#
# Download data from FTP:
# FTPDOWNLOAD("filePath");
```

Listener

```taphome
IF(RECEIVEDMSG.TOPIC = "shellies/shellyem3-"+dID+"/emeter/2/power")
 Ed := todouble(TOSTRING(RECEIVEDMSG.PAYLOAD))/1000;
 elseif(RECEIVEDMSG.TOPIC = "shellies/shellyem3-"+dID+"/emeter/2/total")
 To := todouble(TOSTRING(RECEIVEDMSG.PAYLOAD))/1000;
END
```

Service Attributes

total returned \[Wh]

```taphome
IF(parsejson(x, "Topic") = "shellies/shellyem3-"+dID+"/emeter/2/total_returned")
 return(todouble(parsejson(x, "Payload")));
END
```

voltage \[V]

```taphome
IF(parsejson(x, "Topic") = "shellies/shellyem3-"+dID+"/emeter/2/voltage")
 return(todouble(parsejson(x, "Payload")));
END
```

current \[A]

```taphome
IF(parsejson(x, "Topic") = "shellies/shellyem3-"+dID+"/emeter/2/current")
 return(todouble(parsejson(x, "Payload")));
END
```

Power Factor

```taphome
IF(parsejson(x, "Topic") = "shellies/shellyem3-"+dID+"/emeter/2/pf")
 return(todouble(parsejson(x, "Payload")));
END
```

Service Actions

reset total

```taphome
mqttpublish("shellies/shellyem3-"+dID+"/emeter/2/command", "reset_totals");
```

Contactor Relay Switch Read and write

On-board 10 A relay — typically wired to drive the coil of an external power contactor through the I/O terminals

boolean

Values / States: ON · OFF

Read switch state

```taphome
# Simple HTTP Request:
# VAR response := SENDHTTPREQUEST("/example/getValue");
# IF response.IsSuccess
#  VAR content := response.Content;
#  VAR responseHeaders := response.Headers;
#  RETURN(PARSEXML(content, "//element1/value1"));
# ELSE
#  ADDERROR(response.StatusCode + " (" + response.ReasonPhrase + ")");
#  RETURN(NaN);
# END
#
# Set Http request method, body and headers
# VAR response := SENDHTTPREQUEST("/example/getValue", "GET", "some data", "header1:value1", "header2:value2", ...);
# OR
# VAR request := HTTPREQUEST("/example/getValue", "POST", "some data");
# request.headers := { "header1:value1", "header2:value2", ...};
# request.method := "GET";
# request.data := null;
# VAR response := SENDHTTPREQUEST(request);
#
#
# Send TCP, UDP data:
# VAR data1 := BYTECOLLECTION("0a bb ea df 01");
# SENDDATA(data1);
# VAR data2 := "{\"name\":\"John\", \"age\":32}";
# SENDDATA(data2);
# VAR data3 := TOBYTES("{\"name\":\"John\", \"age\":32}", "iso-8859-1");
# SENDDATA(data3);
# Process received TCP or UDP data and set device values in the Listener script
#
#
# Download data from FTP:
# FTPDOWNLOAD("filePath");
```

Write switch state

```taphome
# Simple HTTP Request:
MQTTPUBLISH("shellies/shellyem3-"+dID+"/relay/0/command", switch(St,1,"on","off"));
# VAR response := SENDHTTPREQUEST("/example/set/value=" + St);
# IF response.IsSuccess = false
#  ADDERROR(response.StatusCode);
# END
#
# Set Http request method, body and headers
# VAR response := SENDHTTPREQUEST("/example/setValue", "GET", "value=" + St, "header1:value1", "header2:value2", ...);\r
# Or VAR request := HTTPREQUEST("/example/setValue");
# request.Method := "PUT";
# VAR response := SENDHTTPREQUEST(request);
#r
#
# Send TCP, UDP data:
# VAR data1 := "{\"name\":\"John\", \"age\":" + St + "}";
# SENDDATA(data1);
# VAR data2 := TOBYTES("{\"name\":\"John\", \"age\":" + St + "}", "iso-8859-1");
# SENDDATA(data2);
# You can process received TCP or UDP data in the Listener script
#
#
# Upload data to FTP:
# FTPUPLOAD("filePath", "somedata=" + St, "write"); # use "append" mode to append data to existing file
```

Listener

```taphome
# Parse received bytes:
IF(RECEIVEDMSG.TOPIC = "shellies/shellyem3-"+dID+"/relay/0")
 St := switch(TOSTRING(RECEIVEDMSG.PAYLOAD),"on",1,0);
END
```

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

Possible improvements (10)

- Reactive Power (per phase) — Instantaneous reactive power in VAR per phase — useful for power-quality diagnostics.
- Short-term Energy Counter — Watt-minute counter since boot (volatile). Template uses lifetime 'total' instead.
- Short-term Returned Energy — Watt-minute returned counter since boot (volatile).
- Contactor Coil Power — Power draw through the on-board relay (small — coil only).
- Contactor Coil Energy — Energy through the on-board relay (Wm).
- Connection Status (LWT) — Last-Will-and-Testament topic — true on connect, false retained on disconnect. Could detect offline 3EM.
- Device Announcement (JSON) — Periodic JSON announce containing id, mac, ip, fw\_ver, new\_fw, model.
- Full Status JSON — Complete /status payload as JSON — could expose Wi-Fi RSSI, internal temperature, all 4 emeter channels.
- 4th CT — Theft / Leakage Detection — Optional 4th split-core CT on IN+/IN- terminal for neutral leakage / energy-theft detection. NOT published over MQTT — only HTTP.
- Total Active Power — 3EM does not publish total\_power over MQTT (only HTTP). Sum the three phase Ed values in a TapHome virtual device.

## 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`          |
| Device ID              | Enter at import |

## Sources

- Shelly Gen1 API Reference
  
  [shelly-api-docs.shelly.cloud](https://shelly-api-docs.shelly.cloud/gen1/) 2026-03-12
- Home Assistant Shelly Integration
  
  [www.home-assistant.io](https://www.home-assistant.io/integrations/shelly/) 2026-03-12
- Shelly 3EM MQTT API — device-specific topics
  
  [shelly-api-docs.shelly.cloud](https://shelly-api-docs.shelly.cloud/gen1/#shelly-3em-mqtt) 2026-04-25
- Shelly 3EM Knowledge Base — specs & wiring
  
  [kb.shelly.cloud](https://kb.shelly.cloud/knowledge-base/shelly-3em) 2026-04-25
- Shelly 3EM — User & Safety Guide
  
  [www.netxl.com](https://www.netxl.com/shelly/docs/shelly-3em-user-manual.pdf) 2026-04-25
  
  [PDF](https://taphome.com/compatibility/devices/shelly-3em-gen1-mqtt/manufacturer/shelly-3em-user-safety-guide.pdf)

Manufacturer documents are © their respective owners. They are provided as published by the manufacturer, for reference only.

## 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/)

