---
title: "Shelly EM MQTT"
description: "Shelly EM single-phase energy meter connected to TapHome via MQTT. Per-channel energy consumption (kWh), voltage monitoring, and contactor relay control."
url: "https://taphome.com/en/compatibility/shelly-em-mqtt/"
language: en
lastmod: 2026-10-08
generator: hugo
ai:
  topics: ["mqtt","electric-meter","wifi","energy-metering","contactor-control","ct-clamp"]
  questions: ["How to integrate Shelly EM with TapHome via MQTT?","What does the Shelly EM MQTT template measure?","How to find the Shelly EM Device ID for MQTT?","Can I control the Shelly EM contactor relay from TapHome via MQTT?","Why is my Shelly EM not reporting energy data over MQTT?","Does the Shelly EM MQTT template support instantaneous power readings?"]
---

# Shelly EM MQTT

Communication: Packet Parser → MQTT

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

> 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 EM is a single-phase energy meter with two independent metering channels and a 2A relay output for contactor control. Each channel connects to an external CT (current transformer) clamp -- available in 50A and 120A variants -- allowing non-invasive monitoring of two separate circuits simultaneously. This template connects to the device via an MQTT broker on the local network. No cloud connection is required.

The template exposes three devices: two electric meters (one per CT channel) tracking cumulative energy consumption, and a switch for the contactor relay.

## Configuration

### Device ID

The Shelly EM uses a Device ID in the format `shellyem-XXXXXX`, where `XXXXXX` is the last 6 characters of the MAC address in uppercase hex (e.g., `shellyem-B929CC`). During template import, enter only the hex part (e.g., `B929CC`) into the **Device ID** parameter.

The Device ID can be found:

- In the Shelly web UI: **Settings** > **Device Info**
- Via API: `GET http://<device-ip>/settings` -- the `mqtt.id` field

> [!TIP]
> This device supports **mDNS discovery**. You can use the hostname `shellyem-{MAC}.local` instead of an IP address when configuring the MQTT broker. Replace `{MAC}` with the same hex part as in the Device ID (e.g., `shellyem-B929CC.local`). Using a hostname prevents connectivity issues when the device's IP address changes.

### MQTT setup

Before importing the template, enable MQTT on the Shelly EM:

1. Open the Shelly web UI at `http://<device-ip>`
2. Go to **Internet & Security** > **Advanced — Developer Settings**
3. Tick **Enable action execution via MQTT**
4. In the **Server** field, enter the MQTT broker address in the format `broker-ip:1883`
5. Press **SAVE**

> [!WARNING]
> On Gen1 Shelly devices, enabling MQTT **disables Shelly Cloud**. Both cannot run simultaneously.

### Template setup

After importing the template in TapHome:

1. Set the **MQTT Broker IP** to the address of your MQTT broker
2. Set the **MQTT Broker Port** (default `1883`)
3. Set the **Device ID** to the Shelly EM's Device ID hex part (e.g., `B929CC`)

The module subscribes to `shellies/#` and the listener scripts on each device filter messages by the configured Device ID.

## Device capabilities

### Energy metering (per channel)

Each channel is exposed as an independent Electric Meter device in TapHome. The listener script subscribes to two MQTT topics per channel:

| Topic | Unit | Description |
|-------|------|-------------|
| `emeter/{i}/energy` | watt-minutes | Cumulative energy since last reboot -- divided by 60 000 to convert to kWh |
| `emeter/{i}/total` | Wh | Persistent total energy consumed -- survives reboots |

The template stores both values: `Ed` (energy from the watt-minutes topic, converted to kWh) and `To` (total in Wh from the persistent topic).

> [!TIP]
> The `energy` topic resets to zero on device reboot. For persistent energy tracking, the template also reads the `total` topic which survives reboots.

Each channel also exposes a **Voltage** service attribute, which reads the RMS line voltage from the `emeter/{i}/voltage` MQTT topic.

> [!NOTE]
> The `readtotalconsumption` and `readdemand` scripts are commented-out boilerplate -- all energy data comes through the MQTT listener. This means the template does **not** provide instantaneous power readings (W). Only cumulative energy (kWh) and total consumed (Wh) are tracked. Instantaneous active power is available via the `emeter/{i}/power` MQTT topic but is not subscribed to by this template.

### Contactor relay

The relay output is exposed as a switch device in TapHome. The relay is rated **2A / 230 VAC** -- it is designed for contactor control only, not for direct load switching.

- **Read:** subscribes to `shellies/shellyem-{id}/relay/0` -- payload `on` maps to ON, `off` maps to OFF
- **Write:** publishes `on` or `off` to `shellies/shellyem-{id}/relay/0/command`

> [!WARNING]
> The relay is rated only 2A. Always use an external contactor for loads exceeding this rating. Direct connection of high-power loads will damage the relay.

## Troubleshooting

### No energy data

1. Verify MQTT is enabled in the Shelly web UI (Internet & Security > Advanced — Developer Settings)
2. Confirm the MQTT broker address and port are correct in both the Shelly device and TapHome module settings
3. Check that the **Device ID** custom variable matches the Shelly's Device ID exactly (e.g., `B929CC`)
4. Use an MQTT client (e.g., MQTT Explorer) to subscribe to `shellies/#` and verify the device publishes `emeter/0/energy` and `emeter/1/energy` topics

### Only one channel reporting data

1. Verify the CT clamp is connected to the correct 3.5mm jack (channel 0 or channel 1)
2. Check that current is flowing through the monitored conductor -- the CT clamp must encircle a single conductor, not the entire cable
3. Subscribe to `shellies/shellyem-{id}/emeter/0/#` and `shellies/shellyem-{id}/emeter/1/#` separately to confirm both channels publish data

### Relay not responding

1. Check that the Shelly EM is powered and connected to the MQTT broker
2. Publish `on` or `off` manually to `shellies/shellyem-{id}/relay/0/command` via an MQTT client to test relay operation independently from TapHome
3. Verify the relay output is wired correctly (check terminal labels on the device)

> [!WARNING]
> Gen1 Shelly devices do **not** support MQTT over TLS. Communication between the device and the MQTT broker is unencrypted (plain MQTT, port 1883). Ensure the MQTT broker is on a trusted local network.

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

These devices appear in TapHome after import.

Shelly EM MQTT Module

Custom Variables

`deviceID` (string) MQTT Device ID of the Shelly EM — format is 'shellyem-DEVICEID' where DEVICEID is the last 6 hex chars of the MAC address (e.g., B929CC)

Open http://shellyIpAddress → Settings → Device Info → copy Device ID

Electric Meter - Channel 1 Electricity Meter Read-only

Energy consumption on CT clamp channel 1 -- cumulative energy (kWh) and total consumed (Wh)

numeric Unit: kWh

Service Attributes

|         |                                                                    |
|---------|--------------------------------------------------------------------|
| Voltage | RMS voltage on channel 1 read from the emeter/0/voltage MQTT topic |

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
VAR whatEd := "shellies/shellyem-"+deviceID+"/emeter/0/energy";
VAR whatTo := "shellies/shellyem-"+deviceID+"/emeter/0/total";

IF (whatEd = RECEIVEDMSG.TOPIC)
 Ed := todouble(TOSTRING(RECEIVEDMSG.PAYLOAD))/60000;
END
IF (whatTo = RECEIVEDMSG.TOPIC)
 To := todouble(TOSTRING(RECEIVEDMSG.PAYLOAD));
END
```

Service Attributes

Voltage \[V]

```taphome
if parsejson(response, "Topic") = "shellies/shellyem-"+deviceID+"/emeter/0/voltage"
 return(todouble(parsejson(response, "Payload")));
end
```

Electric Meter - Channel 2 Electricity Meter Read-only

Energy consumption on CT clamp channel 2 -- cumulative energy (kWh) and total consumed (Wh)

numeric Unit: kWh

Service Attributes

|         |                                                                    |
|---------|--------------------------------------------------------------------|
| Voltage | RMS voltage on channel 2 read from the emeter/1/voltage MQTT topic |

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
VAR whatEd := "shellies/shellyem-"+deviceID+"/emeter/1/energy";
VAR whatTo := "shellies/shellyem-"+deviceID+"/emeter/1/total";

IF (whatEd = RECEIVEDMSG.TOPIC)
 Ed := todouble(TOSTRING(RECEIVEDMSG.PAYLOAD))/60000;
END
IF (whatTo = RECEIVEDMSG.TOPIC)
 To := todouble(TOSTRING(RECEIVEDMSG.PAYLOAD));
END
```

Service Attributes

voltage \[V]

```taphome
if parsejson(response, "Topic") = "shellies/shellyem-"+deviceID+"/emeter/1/voltage"
 return(parsejson(response, "Payload"));
end
```

Contactor Relay Switch Read and write

2A relay output for contactor control -- reads relay/0 state and publishes on/off commands

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
MQTTPUBLISH("shellies/shellyem-" + deviceID + "/relay/0/command",if(St = 1, "on","off"));

# Simple HTTP Request:
# 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
VAR whatSt := "shellies/shellyem-"+deviceID+"/relay/0";
IF (whatSt = RECEIVEDMSG.TOPIC)
 IF (TOSTRING(RECEIVEDMSG.PAYLOAD) = "on")
  St := 1;
 ELSE
  St := 0;
 END
END
```

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

Possible improvements (5)

- Active Power — Instantaneous active power in W per channel. Available via MQTT but template listener scripts do not subscribe to it — readdemand is commented-out boilerplate.
- Reactive Power — Instantaneous reactive power in VAR per channel. Available via MQTT topic.
- Total Energy Returned — Total energy returned to grid in Wh per channel. Useful for solar/bidirectional setups.
- Connection Status — LWT topic — true on connect, false on disconnect. Could detect device offline state.
- Reset Energy Data — Payload 'reset\_data' resets all accumulated energy counters on both channels.

## 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 EM — API Endpoints & MQTT Topics
  
  [shelly-api-docs.shelly.cloud](https://shelly-api-docs.shelly.cloud/gen1/#shelly-em) 2026-03-29
- Shelly EM — Product Specifications
  
  [robomaterial.com](https://robomaterial.com/product/shelly-em-single-phase-energy-meter-with-contactor-control/) 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/)

