TapHome

Shelly DUO RGBW

Packet Parser → HTTP
Submitted by
Last updated: 03. 2026
Shelly DUO RGBW

The Shelly DUO RGBW is a Gen1 Wi-Fi smart LED bulb in a GU10 form factor. It supports full RGB color and tunable white (CCT 3000–6500 K) with smooth transition effects. TapHome communicates with the device over the local network — no cloud connection is required.

Two TapHome templates are available: an HTTP template for controlling a single bulb via REST API, and an MQTT template that can control up to 5 bulbs through a shared MQTT broker. Both templates expose full light control and power metering.

Configuration

HTTP template

The HTTP template requires the bulb’s IP address (default placeholder 192.168.0.1) and an optional transition time in milliseconds (default 300 ms). TapHome polls the /status endpoint every 2.5 seconds to read light state, color values, and energy metering data.

The module-level read script caches the /status response into a jsonStatus custom variable so that individual device scripts can parse the data without making redundant HTTP calls.

MQTT template

The MQTT template requires the broker connection details and one or more Device IDs — one per bulb. Each bulb’s Device ID is configured via a bulbNtopic custom variable (format: shellycolorbulb-DEVICEID). The Device ID can be found in the Shelly web UI under Settings > Device Info.

The template supports up to 5 bulbs simultaneously. Only configure the bulbNtopic variables for bulbs you actually have — unused slots can be left at their default placeholder values.

After enabling MQTT on the Shelly DUO RGBW (Internet & Security > Advanced — MQTT), TapHome subscribes to shellies/# and routes messages to the correct bulb instance based on the topic prefix.

On Gen1 Shelly devices, enabling MQTT disables Shelly Cloud. Both cannot run simultaneously.

Device capabilities

Light control

The bulb operates in two mutually exclusive modes:

  • Color mode — full RGB control via red, green, and blue channels (0–255 each) plus gain (brightness, 0–100%). TapHome represents this as an HSB light — hue (0–360), saturation (0.0–1.0), and brightness (0.0–1.0) are converted from RGB using the RGBTOHSV function.
  • White mode — tunable white via color temperature (3000–6500 K) and brightness (0–100%). Setting a CCT value in TapHome automatically switches the bulb to white mode.

The mode switches automatically based on which property you set:

  • Setting hue or saturation sends a /light/0?mode=color command (HTTP) or a color/0/set JSON payload with "mode":"color" (MQTT)
  • Setting CCT sends a /light/0?mode=white command (HTTP) or a payload with "mode":"white" (MQTT)

All write commands include the configured transitionTime parameter for smooth fading between states. A debounce mechanism prevents stale reads during transitions — the template ignores /status responses for a short period after each write.

In MQTT mode, the debounce window is 3 seconds after each write (longer than the HTTP template) to account for MQTT message delivery latency.

Power metering

Both templates expose an electric meter that reads two values:

  • Real-time power — reported in watts, converted to kW by dividing by 1000
  • Total consumption — reported in watt-minutes, converted to kWh by dividing by 60 000

The HTTP template reads meters[0].power and meters[0].total from the /status response. The MQTT template listens to shellies/{id}/light/0/power and shellies/{id}/light/0/energy topics for each bulb independently.

Power monitoring requires the device model to be configured in the Shelly app or web UI under Settings > Device Model. If the model is not set and the bulb is on but power reads zero, the template will display a warning.

Service diagnostics (HTTP only)

The HTTP template exposes 10 service attributes for device monitoring:

  • Network info — IP address, MAC address, WiFi signal strength (dB)
  • Connectivity — cloud enabled/connected, MQTT connected
  • System — device time, firmware update available, uptime, RAM usage
Service actions (HTTP only)

Two service actions are available in the HTTP template:

  • Enable cloud — enables or disables Shelly Cloud connectivity
  • Reboot — triggers a device reboot
Additional capabilities

The Shelly DUO RGBW also supports light effects (meteor shower, gradual change, breath, flash, on/off gradual, red/green change), a dedicated white LED channel in color mode, and MQTT connection status (LWT). These capabilities can be added in a future template update.

Troubleshooting

Bulb not responding (HTTP)
  1. Verify the bulb is connected to Wi-Fi and has a valid IP address
  2. Try using the mDNS hostname (shellycolorbulb-AABBCCDDEE.local) instead of the IP address — the IP may have changed after a DHCP renewal
  3. Open http://{device-ip}/shelly in a browser — if it responds, the device is reachable
  4. Check that TapHome CCU and the bulb are on the same network / VLAN
Colors appear incorrect
  1. Verify the bulb is in the correct mode — RGB colors only work in color mode, not white mode
  2. When setting a color via TapHome, ensure saturation is greater than zero — a saturation of 0 produces white light regardless of hue
  3. Check that gain (brightness in color mode) is not set to zero
Power readings show zero
  1. Confirm the device model is configured in the Shelly app/web UI (Settings > Device Model)
  2. Verify the bulb is turned on — the meter only reads when the bulb draws power
  3. Poll /status manually and check that meters[0].power returns a non-zero value
MQTT bulbs not responding
  1. Verify MQTT is enabled in each bulb’s web UI (Internet & Security > Advanced — MQTT)
  2. Confirm the broker address and port are correct in both the Shelly device and TapHome module settings
  3. Check that each bulbNtopic custom variable matches the bulb’s Device ID exactly (e.g., shellycolorbulb-B929CC)
  4. Use an MQTT client (e.g., MQTT Explorer) to subscribe to shellies/# and verify each bulb publishes messages

Gen1 Shelly devices support only 2 concurrent HTTP connections. If TapHome and another system (e.g., Home Assistant) poll the same bulb simultaneously, communication may become unreliable. Consider switching to the MQTT template for multi-system environments.

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 (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.1Internet & SecurityWi-Fi Mode - Client
  4. Enter SSID and password → Save

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:

1
shelly<model>-<MAC>.local

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

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

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

Shelly DUO RGBW Module Module
Service Attributes
IP Address
MAC Address
WIFI signal
Cloud enabled
Cloud connected
MQTT connected
Device time
FW update available
Uptime
RAM
Service Actions
Enable cloud
Reboot
Custom Variables
jsonStatus (string)
debounceTimestamp (numeric)
transitionTime (numeric) = TransitionTime

Shelly DUO RGBW Module

Read (module)
VAR now := NOW();

IF now.Ticks < debounceTimestamp
    RETURN(0);
END

VAR response := SENDHTTPREQUEST("/status");

IF response.IsSuccess
    jsonStatus := response.Content;
ELSE
    jsonStatus := NULL;
END
Service Attributes
IP Address
VAR response := SENDHTTPREQUEST("/status");

IF response.IsSuccess
    jsonStatus := response.Content;
ELSE
    jsonStatus := NULL;
END

VAR address := PARSEJSON(jsonStatus, "$.wifi_sta.ip", 1);
IF (ISNULL(address), "-", address)
MAC Address
VAR value := PARSEJSON(jsonStatus, "$.mac", 1);
IF ISNULL(value)
    RETURN("-");
END;

STRING mac;
INT i := 0;
INT len := LENGTH(value);

WHILE i < len
    mac += GETAT(value, i);
    i += 1;
    
    IF MOD(i, 2) = 0 AND i < len
        mac += ":";
    END
LOOP

mac
WIFI signal
VAR signal := PARSEJSON(jsonStatus, "$.wifi_sta.rssi", 1);
IF (ISNULL(signal), "-", signal + "db");
Cloud enabled
VAR value := PARSEJSON(jsonStatus, "$.cloud.enabled", 1);
IF (ISNULL(value), "-", value)
Cloud connected
VAR value := PARSEJSON(jsonStatus, "$.cloud.connected", 1);
IF (ISNULL(value), "-", value)
MQTT connected
VAR value := PARSEJSON(jsonStatus, "$.mqtt.connected", 1);
IF (ISNULL(value), "-", value)
Device time
VAR value := PARSEJSON(jsonStatus, "$.time", 1);
IF (ISNULL(value), "-", value)
FW update available
VAR value := PARSEJSON(jsonStatus, "$.has_update");
IF (ISNULL(value), "-", value)
Uptime
VAR value := PARSEJSON(jsonStatus, "$.uptime", 1);
IF ISNULL(value)
    RETURN("-");
END

VAR days := FLOOR(value/86400, 1);
value := MOD(value, 86400);
VAR hours := FLOOR(value/3600, 1);
value := MOD(value, 3600);
VAR minutes := FLOOR(value/60, 1);

days + "day(s) " + hours + "h " + minutes + "m"
RAM
VAR ramFree := PARSEJSON(jsonStatus, "$.ram_free", 1);
VAR ramTotal := PARSEJSON(jsonStatus, "$.ram_total", 1);

IF ISNULL(ramFree) OR ISNULL(ramTotal)
    RETURN("-");
END

ramFree + " bytes free of " + ramTotal
Service Actions
Enable cloud
Parameters: Enable (Enable / Disable)
VAR response := SENDHTTPREQUEST("/settings/cloud?enabled=" + enable);
VAR contentJson := response.Content;
VAR wasEnabled := PARSEJSON(contentJson, "enabled");

IF(wasEnabled, "Cloud enabled", "Cloud disabled");
Reboot
VAR response := SENDHTTPREQUEST("/reboot");
VAR contentJson := response.Content;
VAR wasRebooted := PARSEJSON(contentJson, "ok");

IF(wasRebooted, "Reboot successful", "Error");
Shelly DUO RGBW ${deviceType_Light} HSB Light

Shelly DUO RGBW ${deviceType_Light}

Read brightness
VAR now := NOW();

IF now.Ticks < debounceTimestamp
    RETURN(Hb);
END

INT value;
VAR mode := PARSEJSON(jsonStatus, "$.lights[0].mode", 1);

IF mode = "white"
    value := PARSEJSON(jsonStatus, "$.lights[0].brightness", 1);
ELSE
    value := PARSEJSON(jsonStatus, "$.lights[0].gain", 1);
END

IF ISNULL(value)
    RETURN(NaN);
END

BOOL isOn := PARSEJSON(jsonStatus, "$.lights[0].ison", 1);

IF ISNULL(isOn)
    RETURN(NaN);
END

IF(isOn, value/100.0, 0);
Write brightness
IF St > 0.5
    VAR mode := PARSEJSON(jsonStatus, "$.lights[0].mode", 1);
    
    IF mode = "white"
        SENDHTTPREQUEST("light/0?turn=on&transition=" + transitionTime + "&brightness=" + ROUND(Hb*100.0));
    ELSE
        SENDHTTPREQUEST("light/0?turn=on&transition=" + transitionTime + "&gain=" + ROUND(Hb*100.0));
    END
ELSE
    SENDHTTPREQUEST("light/0?turn=off&transition=" + transitionTime);
END

VAR now := NOW();
debounceTimestamp := now.Ticks + transitionTime + 500;
Read hue
VAR now := NOW();

IF now.Ticks < debounceTimestamp
    RETURN(Hd);
END

INT r := PARSEJSON(jsonStatus, "$.lights[0].red", 1);
INT g := PARSEJSON(jsonStatus, "$.lights[0].green", 1);
INT b := PARSEJSON(jsonStatus, "$.lights[0].blue", 1);
 
VAR HSVColor := RGBTOHSV(r, g, b);
ROUND(HSVColor.Hue);
Write hue
IF !ISNAN(Ct)
    RETURN(0);
END

VAR color := HSVTORGB(Hd, Sa, 1);

SENDHTTPREQUEST("light/0?mode=color&transition=" + transitionTime + "&gain=" + ROUND(Hb*100) + "&red=" + color.RED + "&green=" + color.GREEN + "&blue=" + color.BLUE);


VAR now := NOW();
debounceTimestamp := now.Ticks + transitionTime + 500;
Read saturation
VAR now := NOW();

IF now.Ticks < debounceTimestamp
    RETURN(Sa);
END

INT r := PARSEJSON(jsonStatus, "$.lights[0].red", 1);
INT g := PARSEJSON(jsonStatus, "$.lights[0].green", 1);
INT b := PARSEJSON(jsonStatus, "$.lights[0].blue", 1);
 
VAR HSVColor := RGBTOHSV(r, g, b);
ROUND(HSVColor.Saturation * 100.0) / 100.0;
Write saturation
IF !ISNAN(Ct)
    RETURN(0);
END

VAR color := HSVTORGB(Hd, Sa, 1);

SENDHTTPREQUEST("light/0?mode=color&transition=" + transitionTime + "&gain=" + ROUND(Hb*100) + "&red=" + color.RED + "&green=" + color.GREEN + "&blue=" + color.BLUE);


VAR now := NOW();
debounceTimestamp := now.Ticks + transitionTime + 500;
Read color temperature
VAR now := NOW();

IF now.Ticks < debounceTimestamp
    RETURN(Ct);
END

INT value := PARSEJSON(jsonStatus, "$.lights[0].temp", 1);
STRING mode := PARSEJSON(jsonStatus, "$.lights[0].mode", 1);

IF ISNULL(value) OR mode != "white"
    RETURN(NaN);
END
 
value
Write color temperature
IF Ct = NaN
    RETURN(0);
END

VAR temp := MIN(Ct, 6500);
temp := MAX(temp, 3000);

SENDHTTPREQUEST("light/0?mode=white&transition=" + transitionTime + "&brightness=" + ROUND(Hb*100) + "&temp=" + temp);

VAR now := NOW();
debounceTimestamp := now.Ticks + transitionTime + 500;
Shelly DUO RGBW Electric meter Electricity Meter

Shelly DUO RGBW Electric meter

Read total consumption
IF LENGTH(jsonStatus) = 0
    RETURN(NaN);
END

VAR power := PARSEJSON(jsonStatus, "$.meters[0].power");
VAR total := PARSEJSON(jsonStatus, "$.meters[0].total");
BOOL isOn := PARSEJSON(jsonStatus, "$.lights[0].ison");

IF ISNULL(power) OR ISNULL(total) OR (ison AND power=0)
	ADDWARNING("To enable power monitoring, open device settings in Shelly app or web browser and configure device model in Settings->Device Model");
	
    RETURN(NaN);
END

total / 60000.0
Read demand
IF LENGTH(jsonStatus) = 0
    RETURN(NaN);
END

VAR power := PARSEJSON(jsonStatus, "$.meters[0].power", 1);

IF ISNULL(power)
    RETURN(NaN);
END

power / 1000.0
Connection: Packet Parser → HTTP
Possible improvements (4)
  • Light Effect — Effect index (0=Off, 1=Meteor Shower, 2=Gradual Change, 3=Breath, 4=Flash, 5=On/Off Gradual, 6=Red/Green Change). Available in both /light/0 and MQTT color/0/set.
  • WiFi Signal Strength — WiFi RSSI in dBm, available in /status response (HTTP only; MQTT template reads it as service attribute already)
  • White Channel — Dedicated white LED channel (0–255) in color mode, separate from CCT. Available in /light/0?white=N.
  • Connection Status (MQTT) — LWT topic — true on connect, false on disconnect. Could detect offline bulbs.

Sources