---
title: "Shelly TRV (valve)"
description: "Drive the Shelly TRV valve position (0-100 %) from TapHome Smart Rules over local HTTP, built-in regulation off. Battery, setpoint and Wi-Fi diagnostics."
url: "https://taphome.com/en/compatibility/shelly-trv-valve/"
language: en
lastmod: 2026-11-10
generator: hugo
ai:
  topics: ["http","thermostat","wifi","battery-powered","radiator-valve","valve-position-control","smart-rule","mdns"]
  questions: ["How to control the Shelly TRV valve position directly from a TapHome Smart Rule?","What is the difference between the Shelly TRV thermostat and valve templates?","Why does the Shelly TRV valve template switch off automatic temperature control?","How to connect Shelly TRV to Wi-Fi and calibrate it after mounting on a radiator?","Why does Shelly TRV reject valve position writes with Device is not calibrated?","How to disable the Shelly TRV weekly schedule so it does not override TapHome?"]
---

# Shelly TRV (valve)

Communication: Packet Parser → HTTP

## Integration guide

The Shelly TRV (SHTRV-01) is a battery-powered Wi-Fi thermostatic radiator valve from Allterco Robotics. It mounts directly on a standard hot-water radiator valve body and changes the flow of hot water through the radiator by driving the valve pin with an internal motor. TapHome communicates with the device over HTTP on the local network — no bridge, no cloud, no MQTT broker required.

This template exposes the valve position as a separate **Valve state** device so that a TapHome Smart Rule can drive the valve directly. The device's own temperature regulation is switched off: every setpoint written from TapHome is sent together with `target_t_enabled=false`, so the firmware no longer moves the valve by itself.

Shelly TRV is **discontinued** and has been succeeded by the Bluetooth-based [Shelly BLU TRV](https://www.shelly.com/products/shelly-blu-trv). Existing units keep working and this template remains fully supported; for new projects consider the successor.

Two alternative templates are provided for the same physical device — choose one based on the intended control pattern.

| Template | Exposes | Use case |
|----------|---------|----------|
| [**Shelly TRV**](https://taphome.com/en/compatibility/shelly-trv/) (main) | Battery + closed-loop thermostat | End-user room temperature control via setpoint (5-30 °C). Firmware drives the valve internally. |
| **Shelly TRV (valve)** (this template) | Battery + valve dimmer + thermostat (setpoint variant) | Smart Rules that need direct valve control — valve position is exposed as a 0-100 % dimmer, automatic regulation is off. |

> [!WARNING]
> Do not import both templates for the same physical device. Both bind to the same endpoint and poll loops will collide — writes will conflict and valve behaviour becomes unpredictable.

## Hardware installation

The Shelly TRV has **no wiring** — it is a mechanical radiator head with internal electronics, powered by a built-in rechargeable battery (Panasonic NCR18650BD, 3.6 V / 6500 mAh). It mounts on the radiator valve body via a metal retaining ring. The device is intended for indoor use only and must be protected from dirt, moisture and splashing water.

### Compatible valve bodies

If the radiator already has a thermostatic valve head (typically a dial numbered 1 to 5), the valve body is most likely compatible. Radiators with small manual valves — common where a separate room or central thermostat is installed — are **not** compatible.

Native thread: **M30 × 1.5**. The following adapters are included in the retail box:

- **Danfoss** — RA, RAV, RAVL
- **Caleffi**
- **Giacomini**
- **M28 × 1.5** — Sam, Slovarm, Comap, TA, Herz, MMA, Remagg
- **Pont à Mousson**

Third-party adapters (not included) extend compatibility to Gampper, Ista, Meges, Ondal, Oventrop, Rossweiner, Vaillant and others.

### Mounting procedure

1. Ensure the radiator is turned off and cooled down.
2. Turn the existing valve head counter-clockwise until the valve is fully open, then unscrew the metal ring counter-clockwise to remove it.
3. Fit the correct adapter if the valve thread is not native M30 × 1.5.
4. Fasten the Shelly TRV to the valve body by turning the metal ring clockwise — do not fully tighten it yet.
5. Rotate the display to the desired orientation, then fully tighten the metal ring.

> [!WARNING]
> Do not try to rotate the device once the metal ring is fully tightened — this can damage it.

### Charging

The device charges over **USB-C** with a USB-C compliant charger of at least 1 A. Fully charge it for about 7 hours before first use. While charging, the battery level line on the display flashes and a dot next to the bottom line indicates a connected charger. Battery life is up to 2 years, depending on how often the valve moves and on Wi-Fi signal quality.

> [!WARNING]
> During charging the body of the device warms up and the internal temperature sensor reads incorrectly. Expect skewed room-temperature values while the charger is connected.

## Calibration

Calibration teaches the motor the stroke of the particular valve body. Without it TapHome cannot read or write the valve position.

1. Briefly press **Reset** (back of the device). The display shows `CL` and the internal motor turns in both directions.
2. Successful calibration ends with `AP` on the display — the device is ready to be connected to Wi-Fi.
3. `E1` means calibration failed: the ring is not tightened enough or the device is not properly seated. Tighten the ring or remount the device, then press and hold **Up** or **Down** for 3 seconds and press **Down** a couple of times to start a new calibration.

Once the device is in TapHome, a new calibration cycle can also be triggered with the **Calibrate** service action on the module.

> [!NOTE]
> Calibrate again after every remount on a different valve body. Until the device reports `calibrated=true`, the Valve state device shows `Device is not calibrated` and TapHome rejects both valve position and setpoint writes.

## Network setup

The Shelly TRV uses 2.4 GHz Wi-Fi (802.11 b/g/n) with a range of up to 30 m, depending on building construction. After calibration it starts in Access Point mode (`AP` on the display).

> [!WARNING]
> If the device is not added to a Wi-Fi network within 3 minutes, it switches off. Briefly press **Reset** to start it again.

### Connecting to Wi-Fi

The device can be connected through the Shelly Cloud mobile app or manually through its embedded web interface:

1. Connect a phone or computer to the Wi-Fi network created by the device and open `http://192.168.33.1`.
2. Click **Internet & Security** and select **WIFI MODE - CLIENT**.
3. Check **Connect the Shelly device to an existing WiFi Network**, enter the network name and password, and press **SAVE**.
4. Find the device IP address in the local network (router client list or the Shelly device finder tool for Windows or macOS).

Enabling Client mode disables Access Point mode. To return to Access Point mode, hold **Reset** for 5 seconds.

A DHCP reservation for the device in the router keeps the IP address used by TapHome stable.

### Authentication

The template sends HTTP requests without credentials on port `80`; HTTPS is not supported on Gen1 devices. If login protection has been enabled in the device web interface, disable it — otherwise TapHome cannot read or control the device.

## Configuration

In TapHome, import the template and enter the device IP address as the only import parameter, then build a Smart Rule that drives the **Valve state** device.

### Disable the weekly schedule

Shelly TRV has a built-in weekly scheduler (5 profiles, up to 20 temperature changes per profile). When a schedule is active, the firmware overrides any externally written setpoint at the next scheduled change.

The template reports this as a module error (`Schedule is enabled`). Before putting the device under TapHome control, either:

- trigger the **Disable schedule** service action on the module (sends `/settings/thermostats/0?schedule=false`), or
- select the **Disable** profile under **Weekly schedule** in the device web interface or in the Shelly Cloud app.

### Automatic valve control

Both the Valve state and the Thermostat device show the warning `Automatic valve control is on`, because it may conflict with Smart Rule operation, whenever the device reports its own temperature regulation as active. Writing a setpoint from the Thermostat device switches it off again (`target_t_enabled=false`).

### External room sensor (recommended)

Every radiator-mounted thermostat measures close to the radiator, so the built-in sensor deviates from the actual room temperature. Two correction paths are available:

- **External sensor** — a Shelly H&T or a compatible sensor in the room can send the ambient temperature to the TRV. Enable it in the device web interface → **Sensor Settings** → **TEMPERATURE OFFSET** → **Enable external temperature corrections endpoint**.
- **Static offset** — use the **Set temperature offset** service action on the Thermostat device (range ±20 °C) to compensate for a constant bias.

## Device capabilities

The template exposes the device as a battery indicator, a valve position dimmer and a thermostat. Module-level diagnostics and actions are the same as in the main template.

### Valve state

The valve actuator is exposed as a dimmer (0-100 %). TapHome reads the position from `thermostats[0].pos` and writes it via `/thermostats/0?pos={0-100}`; the firmware moves the motor to the requested position. A negative position means the valve is not calibrated and the device shows `Device is not calibrated`.

Service attributes report **Force close**, **Extra pressure** and **Automatic calibration correction**. Service actions toggle force-close mode (valve stays fully closed) and extra-pressure mode (stronger actuation for stiff valves), so that Smart Rules can handle scenarios such as emergency close, pre-heating or boost sequences.

### Thermostat

The thermostat reads the measured room temperature (`thermostats[0].tmp.value`) and the stored target (`thermostats[0].target_t.value`). A setpoint write sends **both** `target_t` and `target_t_enabled=false` to `/settings/thermostats/0`, so the firmware does not move the valve on its own — the setpoint serves as a reference value for the Smart Rule that drives the Valve state device.

The only service attribute is **Temperature offset [°C]**, with the matching **Set temperature offset** action. The device adds a `Temperature sensor error` when the sensor reading is invalid.

### Battery status

The battery is exposed as a **multi-value switch** derived from the reported charge level and charger state. The charger state takes precedence over the level:

| State | Condition |
|-------|-----------|
| Critical | `bat.value` 25 % or less |
| Low | `bat.value` 26-50 % |
| Normal | `bat.value` 51-75 % |
| Full | `bat.value` above 75 % |
| Charging | charger connected |

Two service attributes report the raw battery charge (`%`) and voltage (V). The module raises `Low battery` below 50 % and `Battery charge is criticaly low` below 25 %.

### Module diagnostics and actions

The module polls `/status` and `/settings` every 3 seconds and exposes device-wide diagnostics and actions:

- **Diagnostics:** Wi-Fi SSID, IP address, MAC, received signal strength, calibration state, schedule on/off, display brightness (1-7) and display flipped state. A warning appears when a firmware update is available.
- **Actions:** Disable schedule, Reboot, Calibrate (triggers `/calibrate`), Update firmware (pulls `SHTRV-01_build.gbl` from the official Shelly EU firmware server), Set display brightness and Flip display.

## Troubleshooting

### Device is not calibrated

Valve position and setpoint writes are rejected with `Device is not calibrated` until the TRV completes a successful calibration cycle.

1. Make sure the device is firmly seated on the valve body — the ring must be tight enough for the motor to load against the valve pin.
2. Trigger the **Calibrate** service action on the module, or start calibration on the device (hold **Up** or **Down** for 3 seconds, then press **Down** a couple of times). The display shows `CL` while the motor moves in both directions.
3. On success the **Calibrated** attribute changes to `Yes`; `E1` on the display usually indicates an incorrect mount.

### Valve moves although no Smart Rule changed it

The device's own regulation or the weekly schedule is active. Check the `Automatic valve control is on` warning and the **Schedule** module attribute — write a setpoint from the Thermostat device to switch automatic control off, and trigger **Disable schedule** if the schedule is on.

### Room temperature reads too high

- **Charger connected.** Room-temperature readings are invalid while charging. Unplug USB-C and allow the device to cool down.
- **Built-in sensor bias.** The sensor sits close to the radiator. Enable the external temperature corrections endpoint and pair a Shelly H&T (or a compatible sensor) in the same room, or apply a static **Set temperature offset**.

### Display shows E1 / E2

To check the status, press and hold **Up** and **Down** together for 5 seconds and scroll with **Up** or **Down**.

- `E1` — calibration problem. Remount the device, tighten the ring carefully and start a new calibration cycle.
- `E2` — temperature sensor problem. The template adds a `Temperature sensor error` on the Thermostat device. If the issue persists after a reboot, contact Shelly support.

### Device unreachable

1. Verify the TRV is connected to Wi-Fi — press and hold **Up** and **Down** for 5 seconds and scroll through the status parameters; `CO` indicates a connection to the Wi-Fi network, `AP` means the device is still in Access Point mode.
2. Confirm the TapHome Core and the TRV are on the same network / VLAN.
3. Try the mDNS hostname (`shellytrv-XXXXXX.local`) instead of the IP address — the DHCP lease may have changed.
4. Open `http://{device-ip}/status` in a browser. If the JSON response arrives, the device is reachable and the problem is in the TapHome configuration.

> [!WARNING]
> Gen1 Shelly devices accept only **2 concurrent HTTP connections**. If TapHome and another system poll the same device at the same time, communication becomes unreliable. Keep the poll interval at the template default (3 s) and avoid additional pollers.

> [!NOTE]
> Enabling MQTT on Gen1 Shelly devices disables the Shelly Cloud connection. TapHome uses HTTP only — leave MQTT off.

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

These devices appear in TapHome after import.

Shelly TRV Module

Service Attributes

|                          |
|--------------------------|
| Wifi                     |
| ${ipAddress}             |
| MAC                      |
| Received signal strength |
| Calibrated               |
| Schedule                 |
| Display brightness       |
| Display flipped          |

Service Actions

|                        |
|------------------------|
| Disable schedule       |
| Reboot                 |
| Calibrate              |
| Update firmware        |
| Set display brightness |
| Flip display           |

Custom Variables

|                         |
|-------------------------|
| `settings` (string) = 0 |
| `status` (string) = 0   |

Read (module)

```taphome
VAR response := SENDHTTPREQUEST("/status");
IF response.IsSuccess
    status := response.Content;
END

response := SENDHTTPREQUEST("/settings");
IF response.IsSuccess
    settings := response.Content;
END

if(PARSEJSON(status, "$.thermostats[0].schedule"), adderror("Schedule is enabled"));
if(PARSEJSON(status, "$.update.has_update"), addwarning("Firmware update is available"));

var bat := PARSEJSON(status, "$.bat.value");
if bat < 25
    addwarning("Battery charge is criticaly low");
elseif bat < 50
    addwarning("Low battery");
end
```

Service Attributes

Wifi

```taphome
PARSEJSON(status, "$.wifi_sta.ssid")
```

${ipAddress}

```taphome
PARSEJSON(status, "$.wifi_sta.ip")
```

MAC

```taphome
PARSEJSON(status, "$.mac")
```

Received signal strength

```taphome
PARSEJSON(status, "$.wifi_sta.rssi")
```

Calibrated

```taphome
if(PARSEJSON(status, "$.calibrated"), "${detail_deviceSettings_true}", "${detail_deviceSettings_false}")
```

Schedule

```taphome
 VAR response := SENDHTTPREQUEST("/thermostats/0");
IF response.IsSuccess
 VAR content := response.Content;
 VAR responseHeaders := response.Headers;
 RETURN(SWITCH(PARSEJSON(content, "$.schedule"), true, "On", "Off"));
END
```

Display brightness

```taphome
PARSEJSON(settings, "$.display.brightness")
```

Display flipped

```taphome
if(PARSEJSON(settings, "$.display.flipped"), "${detail_deviceSettings_true}", "${detail_deviceSettings_false}")
```

Service Actions

Disable schedule

```taphome
var response := SENDHTTPREQUEST("/settings/thermostats/0?schedule=false");
if(response.IsSuccess, return("OK"), return(response.Content));
```

Reboot

```taphome
VAR response := SENDHTTPREQUEST("/reboot");
if(response.IsSuccess, return("OK"), return(response.Content));
```

Calibrate

```taphome
VAR response := SENDHTTPREQUEST("/calibrate");
if(response.IsSuccess, return("OK"), return(response.Content));
```

Update firmware

```taphome
VAR response := SENDHTTPREQUEST("/ota?url=http://shelly-api-eu.shelly.cloud/firmware/SHTRV-01_build.gbl");
if(response.IsSuccess, return("OK"), return(response.Content));
```

Set display brightness

Parameters: Brightness (1-7) (1–7 Br)

```taphome
var response := SENDHTTPREQUEST("/settings?display_brightness=" + Br);
if(response.IsSuccess, return("OK"), return(response.Content));
```

Flip display

```taphome
var response := SENDHTTPREQUEST("/settings?display_flipped=" + if(PARSEJSON(settings, "$.display.flipped"), "false", "true"));
if(response.IsSuccess, return("OK"), return(response.Content));
```

Battery Multi-value Switch

Values / States: Critical · Low · Normal · Full · Charging

Read switch state

```taphome
if PARSEJSON(status, "$.charger")
    return(4);
end

var bat := PARSEJSON(status, "$.bat.value");
if bat > 75
    return(3);
elseif bat > 50
    return(2);
elseif bat > 25
    return(1);
else
    return(0);
end
```

Service Attributes

Value \[%]

```taphome
PARSEJSON(status, "$.bat.value");
```

Voltage \[V]

```taphome
PARSEJSON(status, "$.bat.voltage");
```

${device\_variable\_valvestate} Dimmer

Service Attributes

|                                  |
|----------------------------------|
| Force close                      |
| Extra pressure                   |
| Automatic calibration correction |

Service Actions

|                       |
|-----------------------|
| Toggle force close    |
| Toggle extra pressure |

Read (module)

```taphome
if(PARSEJSON(status, "$.thermostats[0].target_t.enabled"), addwarning("Automatic valve control is on. It may conflict with smart rule opration."));
```

Read level

```taphome
var pos := PARSEJSON(status, "$.thermostats[0].pos");
if pos >= 0
    return(pos / 100);
else
    adderror("Device is not calibrated");
    return(NaN);
end
```

Write level

```taphome
if(status = "0", return(Le));

if !PARSEJSON(status, "$.calibrated")
    ADDERROR("Device is not calibrated");
    return(NaN);
end
 
 VAR response := SENDHTTPREQUEST("/thermostats/0?pos=" + Le*100);
 IF response.IsSuccess = false
  ADDERROR(response.StatusCode);
 END
```

Service Attributes

Force close

```taphome
if(PARSEJSON(settings, "$.thermostats[0].force_close"), "${detail_deviceSettings_true}", "${detail_deviceSettings_false}")
```

Extra pressure

```taphome
if(PARSEJSON(settings, "$.thermostats[0].extra_pressure"), "${detail_deviceSettings_true}", "${detail_deviceSettings_false}")
```

Automatic calibration correction

```taphome
if(PARSEJSON(settings, "$.thermostats[0].calibration_correction"), "${detail_deviceSettings_true}", "${detail_deviceSettings_false}")
```

Service Actions

Toggle force close

```taphome
var response := SENDHTTPREQUEST("/settings/thermostats/0?force_close=" + if(PARSEJSON(settings, "$.thermostats[0].force_close"), "false", "true"));
if(response.IsSuccess, return("OK"), return(response.Content));
```

Toggle extra pressure

```taphome
var response := SENDHTTPREQUEST("/settings/thermostats/0?extra_pressure=" + if(PARSEJSON(settings, "$.thermostats[0].extra_pressure"), "false", "true"));
if(response.IsSuccess, return("OK"), return(response.Content));
```

${adddevice\_thermostat} Thermostat

Service Attributes

|                          |
|--------------------------|
| Temperature offset \[°C] |

Service Actions

|                        |
|------------------------|
| Set temperature offset |

Read temperature

```taphome
PARSEJSON(status, "$.thermostats[0].tmp.value")
```

Read (module)

```taphome
if(! PARSEJSON(status, "$.thermostats[0].tmp.is_valid"), adderror("Temperature sensor error"));
if(PARSEJSON(status, "$.thermostats[0].target_t.enabled"), addwarning("Automatic valve control is on. It may conflict with smart rule opration."));
```

Read desired temperature

```taphome
PARSEJSON(status, "$.thermostats[0].target_t.value")
```

Write desired temperature

```taphome
if(status = "0", return(Se));

if !PARSEJSON(status, "$.calibrated")
    ADDERROR("Device is not calibrated");
    return(NaN);
end

VAR response := SENDHTTPREQUEST("/settings/thermostats/0?target_t=" + Se + "&target_t_enabled=false");
IF response.IsSuccess = false
  ADDERROR(response.StatusCode);
END
```

Service Attributes

Temperature offset \[°C]

```taphome
PARSEJSON(settings, "$.thermostats[0].temperature_offset")
```

Service Actions

Set temperature offset

Parameters: Offset (-20–20 C)

```taphome
VAR response := SENDHTTPREQUEST("/settings/thermostats/0?temperature_offset=" + C);
if(response.IsSuccess, return("OK"), return(response.Content));
```

**Connection:** Packet Parser → HTTP

## Import parameters

Enter these values when you import the XML.

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

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

