YeelightClient 1.0.0-beta.2

This is a prerelease version of YeelightClient.
dotnet add package YeelightClient --version 1.0.0-beta.2
                    
NuGet\Install-Package YeelightClient -Version 1.0.0-beta.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="YeelightClient" Version="1.0.0-beta.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="YeelightClient" Version="1.0.0-beta.2" />
                    
Directory.Packages.props
<PackageReference Include="YeelightClient" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add YeelightClient --version 1.0.0-beta.2
                    
#r "nuget: YeelightClient, 1.0.0-beta.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package YeelightClient@1.0.0-beta.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=YeelightClient&version=1.0.0-beta.2&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=YeelightClient&version=1.0.0-beta.2&prerelease
                    
Install as a Cake Tool

Yeelight Client

NuGet Downloads Build and Test License: MIT OpenSSF Scorecard

A complete cross platform .NET client for Yeelight smart lights: find them on your network, control them, and follow what they do.
Currently implementing: the Yeelight WiFi Light Inter-Operation Specification (the LAN control that every light has to switch on in the Yeelight app)
Targets net10.0, the current LTS release of .NET (see Compatibility).
Our intent is to create a complete and easy to use client for Yeelight lights.
Documentation, guides and the API reference: tinodo.github.io/yeelightclient

Installation

Install from the NuGet Gallery
Or through the NuGet CLI: NuGet\Install-Package YeelightClient -Version 1.0.0-beta.2
From the command line: dotnet add package YeelightClient --version 1.0.0-beta.2

1.0.0-beta.2 is a prerelease: it is meant to be tried, and its public API can still change before 1.0.0. A plain dotnet add package YeelightClient installs the latest stable release, which there is none of yet, so name the version (or add --prerelease) to get it. Please report what you find in an issue.

Every light needs LAN Control. In the Yeelight app: select the light, open its settings and switch on LAN Control. A light without it neither answers a search nor accepts a connection.

Sample usage

Simple

using Yeelight;

await using var client = new YeelightClient();

// Search the networks of this computer for four seconds.
var lights = await client.DiscoverAsync(TimeSpan.FromSeconds(4));

foreach (var light in lights)
{
    await light.TurnOnAsync();
    await light.SetBrightnessAsync(60, TimeSpan.FromSeconds(1));   // a smooth change, over one second
    await light.SetRgbAsync(255, 140, 0);
}

A light that you know the address of

await using var client = new YeelightClient();

// One search, sent straight to that address: it also works across a VPN, or on another subnet.
var light = await client.ProbeAsync("192.168.1.50");
if (light is not null)
{
    await light.ToggleAsync();
}

Follow the lights

await using var client = new YeelightClient();

client.DeviceDiscovered += (_, e) => Console.WriteLine($"Found {e.Device.Name} ({e.Device.Id})");
client.DeviceStateChanged += (_, e) => Console.WriteLine($"{e.Device.Name}: {e.PropertyName}, on: {e.Light.IsOn}, brightness: {e.Light.Brightness}%");

client.StartDiscovery();   // search now and every minute (client.StartListening() also takes over what the lights announce by themselves)
await Task.Delay(Timeout.Infinite);

The state of a light (IsOn, Brightness, ColorMode, Rgb, ColorTemperature, Hue, Saturation, ...) is what the light told: it reports every change to the connection that the client keeps, whoever made it (the app of Yeelight, a remote, the switch on the wall).

Colour flows, scenes and the background light

var sunrise = new ColorFlow(
[
    ColorFlowStep.ColorTemperature(1700, TimeSpan.FromSeconds(1), brightness: 1),
    ColorFlowStep.ColorTemperature(2700, TimeSpan.FromMinutes(5), brightness: 60),
    ColorFlowStep.ColorTemperature(5000, TimeSpan.FromMinutes(5), brightness: 100),
],
count: 3,
action: ColorFlowAction.Stay);

await light.StartColorFlowAsync(sunrise);
await light.SetSceneAsync(YeelightScene.AutoDelayOff(brightness: 30, minutes: 20));   // on at 30%, and off again after 20 minutes

if (light.SupportsBackgroundLight)
{
    await light.Background.SetRgbAsync(0, 128, 128);   // the same commands, for the second light of a ceiling light
}

Music mode

A light in music mode takes commands without the limit of 60 a minute, which is what it takes to follow music or a screen. The light connects back to this computer, and the client takes care of it:

await using var music = await light.StartMusicModeAsync();
for (var hue = 0; hue < 360; hue += 6)
{
    await music.SetHsvAsync(hue, 100);
    await Task.Delay(50);
}

Failures

Every command returns when the light has answered, and throws a YeelightException when it did not succeed. An argument that a light would refuse (a brightness of 101) is refused with an ArgumentOutOfRangeException first, and nothing is sent.

try
{
    await light.SetBrightnessAsync(50);
}
catch (YeelightException ex) when (ex.Kind == YeelightFailureKind.DeviceRejected)
{
    Console.WriteLine($"The light refused it: {ex.Error?.Message}");   // for example, it is off
}
catch (YeelightException ex)
{
    Console.WriteLine($"It did not get through: {ex.Message}");        // not connected, no answer in time, the connection was lost
}

Good to know

  • Nothing is sent until you ask. A client that is made does nothing. DiscoverAsync, StartDiscovery, StartListening and ProbeAsync are what use the network, and they send UDP searches (to the multicast group of the lights and as a broadcast, from every network of the computer, three times) and listen for the answers. The client never scans a network: it only talks to an address that a light announced itself from, and to the one you give it.
  • A light takes four connections and 60 commands a minute on each. The client keeps one connection per light, keeps within the limit (a command waits for its turn, and fails with YeelightFailureKind.RateLimited when that would take too long), and a light that refuses with client quota exceeded is reported as it is. Music mode has no limit.
  • Events are raised by a dispatcher of the client, one at a time and in the order in which they happened, on a thread that is not the one that reads from a light: a handler can wait for the answer to a command, and a slow handler only delays the events behind it. The event of a change says which property changed, not what it changed to, and a change that is still waiting when the same property changes again is raised once: read the property in the handler.
  • Every call can be cancelled. Every command, ConnectAsync, ProbeAsync and DiscoverAsync take a CancellationToken: cancelling it ends the wait with an OperationCanceledException and leaves the connection usable. A command that was already sent is not undone.
  • A lost connection is made again. IsConnected tells you when it is gone and when it is back, commands that were waiting fail at once with YeelightFailureKind.ConnectionLost, and the client connects again, with a wait that grows, until the light is back or the client is disposed.
  • A light is known by its id, never by its name or its address: when the router gives a light a new address, the connection follows it.
  • The protocol of Yeelight has no authentication and no encryption. Any computer on the network can control a light, and any computer can announce one. The client only takes an announcement that names the address that it was sent from, which has to be on the local network; it does not move a light that it is connected to to another address; and it keeps at most YeelightClientOptions.MaxDevices lights (1000 by default). That is as far as a client can go: use it on a network that you trust.
  • See what goes over the wire. The client logs every message that it sends and receives at the debug level (Sending: …, Received: …) to the ILogger<YeelightClient> that you give it.

Try it: the test app

YeelightClient.TestApp is a Windows (WinUI 3) application to try every command of this library by hand against your own lights (or against lights that it simulates, when you have none at hand), to watch the events, and to see what goes over the wire. Every release has it as a download (YeelightClient.TestApp-<version>-win-x64.zip: unzip it, start YeelightClient.TestApp.exe), and every CI run publishes it as an artifact; see CONTRIBUTING.md.

How it is tested

The tests run against a simulated light (YeelightClient.Tests/TestSupport/SimulatedBulb.cs): an in-process light on the loopback that answers a search over UDP and speaks the control protocol over TCP the way the specification says, with a state that the commands change, reports of every change, the commands that only a light that is on accepts, a quota on every connection, four connections at most and music mode. Nothing that a test does leaves the loopback. On top of that sit tests of the exact messages that every command sends (compared with the specification), of what a hostile network neighbour can send, property-based and fuzz tests, and a chaos test that cuts the connection at random while the client keeps working.

Build and Test CodeQL Docs NuGet

Yeelight Client is an independent open source project. It is not affiliated with or endorsed by Yeelight.

See CONTRIBUTING.md for how to build, test, and contribute, and CHANGELOG.md for release history.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0-beta.2 8 11/9/2026
1.0.0-beta.1 126 11/6/2026