| Crates.io | wiz-lights-rs |
| lib.rs | wiz-lights-rs |
| version | 0.1.0 |
| created_at | 2026-01-20 12:16:24.230423+00 |
| updated_at | 2026-01-20 12:16:24.230423+00 |
| description | A Rust library for controlling Wiz smart lights. |
| homepage | https://github.com/jorgeajimenezl/wiz-lights-rs |
| repository | https://github.com/jorgeajimenezl/wiz-lights-rs |
| max_upload_size | |
| id | 2056471 |
| size | 166,904 |
A runtime-agnostic async Rust library for controlling Philips Wiz smart lights over UDP.
Add to your Cargo.toml:
[dependencies]
wiz-lights-rs = "0.1"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
[dependencies]
wiz-lights-rs = "0.1"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
[dependencies]
wiz-lights-rs = { version = "0.1", default-features = false, features = ["runtime-async-std"] }
async-std = { version = "1.12", features = ["attributes"] }
[dependencies]
wiz-lights-rs = { version = "0.1", default-features = false, features = ["runtime-smol"] }
smol = "2"
use std::net::Ipv4Addr;
use std::str::FromStr;
use wiz_lights_rs::{Light, Payload, Color, Brightness};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a light instance
let light = Light::new(
Ipv4Addr::from_str("192.168.1.100")?,
Some("Living Room")
);
// Set color and brightness
let mut payload = Payload::new();
payload.color(&Color::from_str("255,0,0")?); // Red
payload.brightness(&Brightness::create(80).unwrap());
light.set(&payload).await?;
// Toggle power
light.toggle().await?;
Ok(())
}
Find all bulbs on your network:
use std::time::Duration;
use wiz_lights_rs::discover_bulbs;
let bulbs = discover_bulbs(Duration::from_secs(5)).await?;
for bulb in bulbs {
println!("Found: {} at {}", bulb.mac, bulb.ip);
let light = bulb.into_light(Some("My Light"));
}
use wiz_lights_rs::{Payload, Color, Brightness};
// RGB color
let mut payload = Payload::new();
payload.color(&Color::from_str("0,255,0")?); // Green
payload.brightness(&Brightness::create(100).unwrap());
light.set(&payload).await?;
// Color temperature
let mut payload = Payload::new();
payload.temp(&Kelvin::create(4000).unwrap()); // Warm white
light.set(&payload).await?;
use wiz_lights_rs::{Payload, SceneMode};
let mut payload = Payload::new();
payload.scene(&SceneMode::Sunset);
light.set(&payload).await?;
Available scenes: Ocean, Romance, Sunset, Party, Fireplace, Cozy, Forest, WakeUp, Bedtime, Focus, Relax, Christmas, Halloween, and more.
Batch operations on multiple lights:
use wiz_lights_rs::{Room, Light};
let mut room = Room::new("Living Room");
// Add lights
let light1 = Light::new(Ipv4Addr::from_str("192.168.1.100")?, Some("Lamp 1"));
let light2 = Light::new(Ipv4Addr::from_str("192.168.1.101")?, Some("Lamp 2"));
room.new_light(light1)?;
room.new_light(light2)?;
// Get status from all lights concurrently
let statuses = room.get_status().await?;
For fan-equipped fixtures:
use wiz_lights_rs::{FanSpeed, FanMode, FanDirection};
// Turn fan on at speed 3
light.fan_turn_on(Some(FanMode::Normal), Some(FanSpeed::create(3, None)?)).await?;
// Set fan direction
light.set_fan_direction(FanDirection::Reverse).await?;
// Toggle fan
light.fan_toggle().await?;
Receive real-time updates:
use wiz_lights_rs::push::PushManager;
let mut manager = PushManager::new();
manager.register_callback(|response| {
println!("Light updated: {:?}", response);
});
manager.start().await?;
// Get current state
let status = light.get_status().await?;
println!("Power: {}", status.emitting());
if let Some(color) = status.color() {
println!("Color: RGB({}, {}, {})", color.red(), color.green(), color.blue());
}
if let Some(brightness) = status.brightness() {
println!("Brightness: {}%", brightness.value());
}
// Get diagnostics
let diag = light.diagnostics().await;
println!("{}", serde_json::to_string_pretty(&diag)?);
All parameters use strongly-typed wrappers with validation:
Types provide two creation methods:
create(value): Returns Option<T>, None if invalidcreate_or(value): Returns valid value or defaultlet brightness = Brightness::create(80).unwrap(); // Some(80)
let invalid = Brightness::create(5); // None (below minimum)
let safe = Brightness::create_or(5); // Returns default (100)
All network operations return Result<T, Error>:
match light.set(&payload).await {
Ok(response) => println!("Success"),
Err(e) => eprintln!("Error: {}", e),
}
Common errors:
Socket: Network communication failuresNoAttribute: Empty payload validationJsonLoad/JsonDump: Serialization errorsLightNotFound: Invalid light referenceThe library uses:
Contributions are welcome! Please ensure code passes:
cargo test
cargo clippy
cargo fmt --check
This project is licensed under the MIT License.
This library is not affiliated with or endorsed by Philips or WiZ. It is a reverse-engineered implementation of the WiZ local UDP protocol.