---
title: "Yeelight"
description: "Dim and switch Yeelight bulbs, strips and ceiling lights from TapHome over JSON-RPC on TCP port 55443. Enable LAN Control on the bulb, no cloud needed."
url: "https://taphome.com/en/compatibility/yeelight/"
language: en
lastmod: 2026-04-15
generator: hugo
ai:
  topics: ["data-pp","lighting","wifi","json-rpc","lan-control","dimmer"]
  questions: ["How to integrate a Yeelight bulb with TapHome?","What does the Yeelight TapHome template control?","How to enable LAN Control / Developer Mode on a Yeelight bulb?","Can TapHome change the color or color temperature of a Yeelight bulb?","Why does my Yeelight bulb not respond to TapHome commands?","Why do some Yeelight commands fail with \"client quota exceeded\"?"]
---

# Yeelight

Communication: Packet Parser → TCP

- [Yeelight Developer Portal](https://www.yeelight.com/en_US/developer)
- [Yeelight LAN Control FAQ](https://www.yeelight.com/faqs/lan_control)

> Network address
> 
> TapHome reaches this device at the address entered on import. Give the device a fixed address — an IP reservation in the router, or its mDNS name if it supports one — otherwise the integration stops working when the router changes the address.
> 
> [Network Preparation](https://taphome.com/en/docs/setup/network-preparation/)

## Integration guide

Yeelight is a brand of Wi-Fi smart LED lighting — single-color bulbs, tunable white and full-color bulbs, LED strips, and ceiling lights — published by Qingdao Yeelink (part of the Xiaomi ecosystem). Every LAN-enabled Yeelight product speaks the same JSON-RPC **Inter-Operation Protocol** on TCP port **55443**, so a single TapHome template covers the whole family.

The template exposes a dimmer device: brightness (0–100 %) and on/off control with smooth transitions. The current color mode and color temperature are reported as read-only service attributes. TapHome communicates with the bulb directly on the local network — no Yeelight cloud account is required once LAN Control is enabled on the bulb.

## Hardware connection

Yeelight bulbs are powered from the standard mains (typically E27, E14, GU10 or 24 V strip power supply depending on product). No wiring is needed between TapHome and the bulb — all communication goes over Wi-Fi. The bulb must be on the **same LAN / VLAN** as the TapHome CCU, because the JSON-RPC protocol has no authentication and no encryption, and the traffic is never routed through the Yeelight cloud.

> [!WARNING]
> The Yeelight LAN protocol is unencrypted. Do not expose TCP port 55443 to the public internet, and place the bulbs on a trusted network segment — anyone with access to the LAN can issue commands to the bulb.

## Configuration

### Enabling LAN Control

LAN Control (also called **Developer Mode** in some regions) is disabled on the bulb by default. Without it, TCP connections on port 55443 are refused.

1. Open the **Yeelight** mobile app and pair the bulb to the local Wi-Fi network with the SmartConfig / QuickConnect procedure if it has not been paired yet.
2. Select the target bulb in the app.
3. Tap the settings icon (top-right) and open **LAN Control** (in some firmware versions labelled **Developer Mode**).
4. Toggle **LAN Control** to ON.
5. Note the bulb's IP address — it is shown in the Yeelight app device info or can be read from the router's DHCP lease table.

Once LAN Control is enabled, the bulb listens on TCP port `55443` and periodically advertises itself over UDP multicast `239.255.255.250:1982`.

### Network configuration

- **IP address** — the TapHome template does not auto-discover bulbs. Assign a **static IP** or a **DHCP reservation** in the router so the bulb's address does not change after a lease renewal.
- **Same LAN segment** — the TapHome CCU and the bulb must be in the same broadcast domain. If Wi-Fi and wired clients are on separate VLANs, add a firewall rule that allows TCP 55443 between them.

### Import parameters

During template import in TapHome the user enters three values:

| Parameter | Description | Default |
|-----------|-------------|---------|
| `ipAddress` | IP address of the Yeelight bulb on the LAN | `192.168.0.1` (placeholder — replace with real IP) |
| `Port` | TCP control port on the bulb | `55443` |
| `Internal poll interval` | How often the template sends `get_prop` (in milliseconds) | `10000` (10 s) |

The default port `55443` is the standard Yeelight LAN Control port and should not be changed unless the bulb has been configured for a non-standard port.

> [!TIP]
> Between polls, the template also reacts to `props` notifications that the bulb pushes whenever its state changes. In practice this means brightness / on-off changes made from the Yeelight app, a wall switch adapter, or another Home Assistant instance appear in TapHome almost immediately, without waiting for the next poll.

## Device capabilities

### Dimmer (brightness and on/off)

The template exposes a single dimmer device. On every poll it sends:

```json
{"id":951,"method":"get_prop","params":["bright","power"]}
```

and parses the response `result[0]` (brightness 1–100, divided by 100 to the TapHome 0.0–1.0 range) and `result[1]` (`"on"` / `"off"`).

Writes are translated to two JSON-RPC commands:

- If the target level is greater than zero, the template sends `set_power ["on","smooth",300]` followed by `set_bright [round(level*100),"smooth",500]`. The 300 ms power transition and 500 ms brightness transition give a soft fade instead of a hard step.
- If the target level is zero, the template sends `set_power ["off","smooth",300]`.

The dimmer also consumes `props` notifications pushed by the bulb (power / brightness) so external state changes are reflected in TapHome without waiting for the next poll cycle.

### Color mode and color temperature (read-only)

Two module-level service attributes are read via a separate `get_prop` request (`id=981`):

- **Color mode** — `RGB`, `Temperature`, or `HSV`, decoded from the numeric `color_mode` property (1 / 2 / 3) using a `SWITCH` expression in the listener script.
- **Color temperature** — Kelvin value reported as `"{ct}K"` (for example `"4000K"`). Only meaningful when the bulb is in Temperature mode. Typical model-dependent range: **1700–6500 K** for color bulbs and strips, **2700–6500 K** for ceiling lights (ceiling3 caps at 6000 K).

Both attributes are diagnostic only — the template does not switch color mode or write a new color temperature.

### Additional capabilities

The Yeelight LAN protocol also exposes RGB and HSV color control (`set_rgb`, `set_hsv`), color temperature control (`set_ct_abx`), color-flow programs (`start_cf` / `stop_cf`), predefined scenes (`set_scene`), on-device sleep timers (`cron_add`), background-light control on dual-light fixtures (`bg_*` methods) and music mode (`set_music`, a reverse-TCP channel that bypasses the rate limit). None of these are implemented by the current TapHome dimmer template — users who need full color or effects must extend the template or use the native Yeelight app in parallel.

> [!TIP]
> Color, color temperature and scenes can be added in a future template update on top of the same TCP channel. The PacketParser read / write scripts can be extended to send `set_ct_abx`, `set_rgb`, or `set_scene` without changing the import parameters.

## Troubleshooting

### Bulb does not respond to commands

1. Verify **LAN Control** is enabled on the bulb (Yeelight app → bulb settings → LAN Control). Without it, the bulb refuses all TCP connections on port 55443.
2. Confirm the bulb IP in the Yeelight app or in the router's DHCP lease table, and make sure it matches the `ipAddress` import parameter. Yeelight bulbs do not keep a fixed IP by default — the lease may have expired and the IP changed.
3. Assign a static IP or DHCP reservation to the bulb to prevent the address from drifting.
4. Check that the TapHome CCU and the bulb are on the same LAN / VLAN and that TCP `55443` is not blocked by a firewall between them.
5. Test connectivity manually: `telnet {bulb-ip} 55443` and send a raw request followed by `\r\n`:

   ```json
   {"id":1,"method":"get_prop","params":["bright","power"]}
   ```

   A valid bulb replies with `{"id":1,"result":["<bright>","<power>"]}`.

### Read error: client quota exceeded

Each TCP connection to a Yeelight bulb is limited to **60 commands per minute**, and the bulb accepts at most **4 concurrent connections** in total (144 commands/minute across the whole LAN). If another system polls the bulb at the same time — Home Assistant, a Yeelight cloud session, a custom script — the combined traffic can trigger rate-limit errors that are reported in TapHome as `Read error: client quota exceeded`.

1. Disable or slow down other integrations that share the bulb.
2. Keep the TapHome poll interval at the default `10000` ms or higher. One `get_prop` plus two `set_*` writes per change stays well under the 60 cmd/min quota.
3. Close unused `telnet` debug sessions — they count against the 4-connection limit.

### Color temperature service attribute shows "error"

The Color mode and Color temperature service attributes read `color_mode` and `ct` from the bulb. If the bulb is a **mono** (white-only) model that does not support tunable white, or if it is currently in RGB or HSV mode, the `ct` value is not meaningful and the listener script reports `"error"` for Color temperature. This is expected behaviour and does not indicate a fault.

### Changes made in the Yeelight app are not reflected

The template reacts to `props` notifications pushed by the bulb, so external changes normally appear within a second. If they do not:

1. The notification may have arrived while the TCP socket was being re-established — the next poll (default 10 s) will resynchronize.
2. Some older firmware versions only push notifications when a command is actively sent. Upgrade the bulb firmware from the Yeelight app.
3. The bulb may have hit the 4-connection limit — reduce the number of concurrent clients on the LAN.

## Available devices 1

These devices appear in TapHome after import.

Yeelight module Module

Service Attributes

|                   |                                                                                                                                                                                                                                      |
|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Color mode        | Active color mode reported by the bulb — RGB, Temperature (tunable white) or HSV. Read-only — the template does not switch color mode.                                                                                               |
| Color temperature | Current white-point in Kelvin (valid only when color mode is Temperature). Read-only — the template does not write color temperature. Model-dependent range: 1700–6500 K for color bulbs and strips, 2700–6500 K for ceiling lights. |

Custom Variables

Listener

```taphome
VAR jsonResponse := TOSTRING(RECEIVEDBYTES);
VAR id := PARSEJSON(jsonResponse, "id", 1);

IF(id = 981)
   VAR error := PARSEJSON(jsonResponse, "error.message", 1);
   
   IF(!ISNULL(error))
      COMPLETESERVICEATTRIBUTE("Color mode", "", "error");
      COMPLETESERVICEATTRIBUTE("Color temperature", "", "error");
   ELSE
      VAR colorMode := PARSEJSON(jsonResponse, "result[0]", 1);
      VAR colorTemp := PARSEJSON(jsonResponse, "result[1]", 1);
      
      IF(!ISNULL(colorMode))
      VAR colorModeValue := SWITCH(TODOUBLE(colorMode), 1, "RGB", 2, "Temperature", 3, "HSV", "Unknown");
         COMPLETESERVICEATTRIBUTE("Color mode", colorModeValue, "");
      ELSE
         COMPLETESERVICEATTRIBUTE("Color mode", "", "error");
      END
      
      IF(!ISNULL(colorTemp))
         COMPLETESERVICEATTRIBUTE("Color temperature", colorTemp + "K", "");
      ELSE
         COMPLETESERVICEATTRIBUTE("Color temperature", "", "error");
      END
   END
END
```

Service Attributes

Color mode

```taphome
VAR json := "{\"id\":981, \"method\":\"get_prop\", \"params\":[\"color_mode\", \"ct\"]}";
SENDDATA(json);
```

Color temperature

```

```

Yeelight dimmer Dimmer Read and write

Brightness (0–100 %) and on/off control with smooth 300–500 ms transitions. Color, color temperature and effects are not exposed by this template.

numeric Unit: brightness 0–100 %

Variable: `receiveError`, Variable: `notificationError`, Variable: `sendError`

Read level

```taphome
VAR json := "{\"id\":951, \"method\":\"get_prop\", \"params\":[\"bright\", \"power\"]}";
SENDDATA(json);
```

Write level

```taphome
IF(Le > 0)
    VAR jsonPowerOn := "{\"id\":952,\"method\":\"set_power\",\"params\":[\"on\", \"smooth\", 300]}";
    SENDDATA(jsonPowerOn);

    VAR jsonBrightness := "{\"id\":953,\"method\":\"set_bright\",\"params\":[" + ROUND(Le*100) + ",\"smooth\", 500]}";
    SENDDATA(jsonBrightness);
ELSE
    VAR jsonPowerOff := "{\"id\":954,\"method\":\"set_power\",\"params\":[\"off\", \"smooth\", 300]}";
    SENDDATA(jsonPowerOff);
END
```

Listener

```taphome
VAR jsonResponse := TOSTRING(RECEIVEDBYTES);
VAR method := PARSEJSON(jsonResponse, "method", 1);
VAR id := PARSEJSON(jsonResponse, "id", 1);
STRING onOff;

IF(id = 951)
   receiveError := PARSEJSON(jsonResponse, "error.message", 1);
   
   IF(LENGTH(receiveError) = 0)
      VAR brightnessStr := PARSEJSON(jsonResponse, "result[0]", 1);
      onOff := PARSEJSON(jsonResponse, "result[1]", 1);
   
      IF(!ISNULL(brightnessStr))
         Le := TODOUBLE(brightnessStr) / 100.0;
      END
   
      IF(onOff = "on")
         St := 1;
      ELSEIF(onOff = "off")
         Le := 0;
         St := 0;
      END
   END
END

IF(id > 951 AND id < 955)
   sendError := PARSEJSON(jsonResponse, "error.message", 1);
END

IF(method = "props")
   notificationError := PARSEJSON(jsonResponse, "error.message", 1);
   
   IF(LENGTH(notificationError) = 0)
      VAR brightness := PARSEJSON(jsonResponse, "params.bright", 1);
      onOff := PARSEJSON(jsonResponse, "params.power", 1);
   
      IF(!ISNULL(brightness))
         Le := brightness / 100.0;
      END
   
      IF(onOff = "on")
         St := 1;
         IF(ISNULL(brightness))
            SENDDATA("{\"id\":951, \"method\":\"get_prop\", \"params\":[\"bright\", \"power\"]}");
         END
      ELSEIF(onOff = "off")
         Le := 0;
         St := 0;
      END
   END
END

IF(LENGTH(receiveError) > 0)
   ADDERROR("Read error: " + receiveError);
END

IF(LENGTH(sendError) > 0)
   ADDERROR("Write error: " + sendError);
END

IF(LENGTH(notificationError) > 0)
   ADDERROR(notificationError);
END
```

**Connection:** Packet Parser → TCP

Possible improvements (13)

- Set color temperature — Write color temperature (1700–6500 K, model-dependent). Color temperature is exposed as a read-only service attribute but cannot be changed from TapHome.
- Set RGB color — Write full RGB color (0–16777215). TapHome dimmer template exposes brightness + on/off only — no color control.
- Set HSV color — Write hue (0–359) + saturation (0–100). Not exposed by dimmer template.
- Color flow — Scripted sequences of brightness / color / CT changes (sunrise effect, strobe, ambient cycles). Not exposed by dimmer template.
- Set scene — Jump directly to a predefined state (color, hsv, ct, cf, auto\_delay\_off). Not exposed by dimmer template.
- Toggle power — Single-parameter power toggle. Not exposed — TapHome writes explicit on/off via set\_power instead.
- Sleep timer (cron) — On-device auto-off timer in minutes. Not exposed — TapHome uses its own Smart Rules for scheduling instead.
- Music mode — Reverse-TCP channel bypassing the 60 cmd/min rate limit. Not used by TapHome.
- Relative adjustments — Relative +/- changes without knowing the current value. Not exposed — TapHome always writes absolute brightness.
- Save current state as power-on default — Persist current brightness/color to flash so it survives a hard power cut. Not exposed by dimmer template.
- Background light control — Secondary light channel on dual-light fixtures (e.g., some ceiling lights). Not exposed by dimmer template.
- Extended state properties — Additional properties pushed via props notifications (rgb, hue, sat, flowing, delayoff, music\_on, name). Template only consumes bright and power.
- LAN auto-discovery — User must enter the bulb IP manually during import — template does not perform SSDP discovery. A static DHCP lease is strongly recommended.

## Import parameters

Enter these values when you import the XML.

| Asked in the app       | Default       |
|------------------------|---------------|
| IP address             | `192.168.0.1` |
| Port                   | `55443`       |
| Internal poll interval | `10000`       |

## Sources

- Yeelight WiFi Light Inter-Operation Specification
  
  [www.yeelight.com](https://www.yeelight.com/download/Yeelight_Inter-Operation_Spec.pdf) 2026-04-15
  
  [PDF](https://taphome.com/compatibility/devices/yeelight/manufacturer/Yeelight_Inter-Operation_Spec.pdf)
- Yeelight Developer — Third-party Control Protocol
  
  [www.yeelight.com](https://www.yeelight.com/en_US/developer) 2026-04-15
- python-yeelight library documentation
  
  [yeelight.readthedocs.io](https://yeelight.readthedocs.io/en/latest/) 2026-04-15

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

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

