| Crates.io | tplink |
| lib.rs | tplink |
| version | 0.2.0 |
| created_at | 2025-10-09 00:52:53.849746+00 |
| updated_at | 2025-10-09 15:36:18.331168+00 |
| description | Pure Rust TP-Link smart device client library |
| homepage | |
| repository | |
| max_upload_size | |
| id | 1874781 |
| size | 62,132 |
A pure Rust library for communicating with TP-Link smart devices including smart plugs, smart lights, smart dimmers, and power strips.
Add this to your Cargo.toml:
[dependencies]
tplink = "0.1.0"
tokio = { version = "1", features = ["full"] }
For local development or monorepo usage:
[dependencies]
tplink = { path = "path/to/tplink" }
tokio = { version = "1", features = ["full"] }
The new API provides device objects with embedded clients for type-safe operations:
use tplink::{discover, Device};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Discover all TP-Link devices on the network
let devices = discover().await?;
for device in devices {
println!("Found device: {} at {}", device.alias(), device.ip_string().unwrap());
match device {
Device::SmartPlug(plug) => {
println!(" Type: Smart Plug");
plug.turn_on().await?;
println!(" ✅ Turned on!");
}
Device::SmartLight(light) => {
println!(" ✅ Type: Smart Light (Dimmable: {}, Color: {})",
light.is_dimmable(), light.is_color());
light.turn_on().await?;
light.set_brightness(75).await?;
light.set_color("#FF6B35").await?; // Set to orange
println!(" Configured light!");
}
Device::SmartDimmer(dimmer) => {
println!(" Type: Smart Dimmer");
dimmer.set_brightness(50).await?;
println!(" 🔆 Set brightness!");
}
Device::PowerStrip(strip) => {
println!(" Type: Power Strip ({} sockets)", strip.sockets().len());
for socket in strip.sockets() {
strip.turn_socket_on(&socket.id).await?;
println!(" 🔌 Socket '{}' turned on", socket.alias);
}
}
}
}
Ok(())
}
For applications that need persistent device management:
use tplink::{create_registry, DeviceRegistry};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let registry = create_registry();
// Discover and register devices
{
let mut reg = registry.write().await;
let devices = reg.discover_and_register().await?;
println!("Discovered {} devices", devices.len());
}
// Use devices by IP
{
let reg = registry.read().await;
if let Some(plug) = reg.get_smart_plug("192.168.1.100") {
plug.turn_on().await?;
println!("Turned on plug at 192.168.1.100");
}
if let Some(light) = reg.get_smart_light("192.168.1.101") {
light.set_brightness(100).await?;
light.set_color("hsl(240, 100%, 50%)").await?; // Blue
println!("Set light to bright blue");
}
}
Ok(())
}
use tplink::Device;
// Assuming you have a smart plug device
if let Device::SmartPlug(plug) = device {
// Basic control
plug.turn_on().await?;
plug.turn_off().await?;
// Device management
plug.set_alias("Living Room Lamp").await?;
plug.reboot().await?;
// Get device info
println!("Plug: {} ({})", plug.alias(), plug.device_id());
}
use tplink::Device;
if let Device::SmartLight(light) = device {
// Power control
light.turn_on().await?;
light.turn_off().await?;
// Brightness control (0-100)
light.set_brightness(75).await?;
// Color control - supports multiple formats
light.set_color("#FF0000").await?; // Hex
light.set_color("red").await?; // Named colors
light.set_color("rgb(255, 0, 0)").await?; // RGB
light.set_color("hsl(0, 100%, 50%)").await?; // HSL
// Check capabilities
if light.is_color() {
println!("This light supports color!");
}
if light.is_dimmable() {
println!("This light is dimmable!");
}
}
use tplink::Device;
if let Device::SmartDimmer(dimmer) = device {
// Brightness control (0-100)
dimmer.set_brightness(25).await?;
// Set auto-off timeout (in minutes)
dimmer.set_inactivity_timeout(30).await?;
}
use tplink::Device;
if let Device::PowerStrip(strip) = device {
// Get available sockets
let sockets = strip.sockets();
println!("Power strip has {} sockets", sockets.len());
for socket in sockets {
println!("Socket: {} (ID: {})", socket.alias, socket.id);
// Control individual sockets
strip.turn_socket_on(&socket.id).await?;
strip.turn_socket_off(&socket.id).await?;
// Energy monitoring
let usage = strip.get_energy_usage(&socket.id).await?;
let emeter = strip.get_emeter_data(&socket.id).await?;
println!("Energy data: {:?}", usage);
}
}
Old way (function-based):
// ❌ Old API - not type safe, easy to make mistakes
use tplink::{turn_plug_on, set_light_brightness};
turn_plug_on("192.168.1.100").await?;
set_light_brightness("192.168.1.100", 75).await?; // Wrong! This is a plug, not a light
New way (device-based):
// ✅ New API - type safe, self-documenting
use tplink::{discover, Device};
let devices = discover().await?;
for device in devices {
match device {
Device::SmartPlug(plug) => {
plug.turn_on().await?;
// plug.set_brightness(75).await?; // ❌ Compile error - plugs don't have brightness!
}
Device::SmartLight(light) => {
light.turn_on().await?;
light.set_brightness(75).await?; // ✅ Type safe!
}
_ => {}
}
}
use tplink::{TpLinkClient, DeviceRegistry};
use std::sync::Arc;
let client = Arc::new(TpLinkClient::new());
let registry = DeviceRegistry::with_client(client.clone());
// Use the same client across multiple registries or operations
let devices = tplink::discovery::discover_devices_with_client(client).await?;
use tplink::{TpLinkError, Result};
match plug.turn_on().await {
Ok(()) => println!("Success!"),
Err(TpLinkError::Network(e)) => eprintln!("Network error: {}", e),
Err(TpLinkError::InvalidIpAddress(ip)) => eprintln!("Invalid IP: {}", ip),
Err(TpLinkError::DeviceCommunication { message }) => eprintln!("Device error: {}", message),
Err(e) => eprintln!("Other error: {}", e),
}
| Device Type | Models | Features |
|---|---|---|
| Smart Plugs | HS100, HS110, KP100+ | On/Off, Scheduling, Energy Monitoring* |
| Smart Lights | LB100, LB110, LB120, LB130+ | On/Off, Dimming*, Color* |
| Smart Dimmers | ES20M(US), KS230(US) | Dimming, Inactivity Timer |
| Power Strips | HS300, KP303+ | Individual Socket Control, Energy Monitoring |
*Feature availability depends on specific model
TP-Link smart devices use:
Device not found:
Connection timeouts:
Color commands not working:
light.is_color())#RRGGBB, rgb(), hsl(), named colorsContributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under either of
at your option.