huehue 0.5.0

Rust wrapper for Hue v2 API.
Documentation
use std::net::Ipv4Addr;
use std::str::FromStr;

use huehue::color::{Component, RGB8};
use huehue::models::device_type::DeviceType;
use huehue::{Hue, Light};
use serde::Serialize;
use structopt::StructOpt;

#[derive(Debug, StructOpt, Serialize)]
struct XyArguments {
	#[structopt(long)]
	pub x: f32,

	#[structopt(long)]
	pub y: f32,
}

#[derive(Debug, StructOpt, Serialize)]
struct RgbArguments {
	#[structopt(long)]
	pub r: u8,

	#[structopt(long)]
	pub g: u8,

	#[structopt(long)]
	pub b: u8,
}

#[derive(Debug, StructOpt, Serialize)]
struct DimmArguments {
	#[structopt(long)]
	pub value: f32,
}

#[derive(Debug, StructOpt, Serialize)]
enum ActionArguments {
	Switch,
	Dimm(DimmArguments),
	Xy(XyArguments),
	Rgb(RgbArguments),
}

#[derive(Debug, StructOpt, Serialize)]
struct Arguments {
	#[structopt(subcommand)]
	pub action: ActionArguments,

	#[structopt(long, env = "RUES_BRIDGE")]
	pub bridge: Ipv4Addr,

	#[structopt(long, env = "RUES_DEVICE_TYPE")]
	pub device_type: String,

	#[structopt(long, env = "RUES_APPLICATION_KEY")]
	pub application_key: String,

	#[structopt(long)]
	pub id: uuid::Uuid,
}

fn print_light(light: &Light) {
	println!("> Light {}:", light.name);
	println!("\tIdentifier: {}", light.id);
	println!("\tOn: {}", light.on);

	if let Some(brightness) = &light.brightness {
		println!("\tBrightness: {}", brightness);
	}

	if let Some(color) = &light.color {
		println!("\tColor: ({}, {})", color.xy.x, color.xy.y);
		println!(
			"\tGamut: R={},{} G={},{} B={},{}",
			color.gamut.red.x,
			color.gamut.red.y,
			color.gamut.green.x,
			color.gamut.green.y,
			color.gamut.blue.x,
			color.gamut.blue.y
		);
	}

	if let Some(temperature) = &light.temperature {
		if let Some(value) = &temperature.mirek {
			let mirek_schema = &temperature.mirek_schema;
			println!(
				"\tTemperature: {} (min: {}, max {})",
				value, mirek_schema.mirek_minimum, mirek_schema.mirek_maximum
			);
		}
	}
}

#[tokio::main]
async fn main() {
	let arguments = Arguments::from_args();

	let device_type = DeviceType::from_str(arguments.device_type.as_str()).expect("Invalid device name.");
	let hue = Hue::new_with_key(arguments.bridge, device_type, arguments.application_key)
		.await
		.expect("Failed to read bridge information.");

	let light_opt = match hue.lights().await {
		Ok(lights) => lights.into_iter().filter(|light| light.id == arguments.id).next(),
		Err(e) => {
			println!("Unexpected Hue error {:?}.", e);
			return;
		},
	};

	let mut light = match light_opt {
		Some(light) => light,
		None => {
			println!("Light {} not found.", arguments.id);
			return;
		},
	};

	match arguments.action {
		ActionArguments::Switch => {
			match light.switch(!light.on).await {
				Ok(_) => (),
				Err(e) => {
					println!("Unexpected Hue error {:?}.", e);
					return;
				},
			}
		},
		ActionArguments::Xy(color) => {
			match light
				.set_color(Component::new(color.x, color.y).expect("Invalid color."))
				.await
			{
				Ok(_) => (),
				Err(e) => {
					println!("Unexpected Hue error {:?}.", e);
					return;
				},
			}
		},
		ActionArguments::Rgb(color) => {
			match light.set_color_rgb(RGB8::new(color.r, color.g, color.b)).await {
				Ok(_) => (),
				Err(e) => {
					println!("Unexpected Hue error {:?}.", e);
					return;
				},
			}
		},
		ActionArguments::Dimm(dimm) => {
			match light.dimm(dimm.value).await {
				Ok(_) => (),
				Err(e) => {
					println!("Unexpected Hue error {:?}.", e);
					return;
				},
			}
		},
	}

	print_light(&light);
}