|
|
@@ -1,5 +1,6 @@ |
|
|
|
use futures::Future; |
|
|
|
use huey::connection::Light; |
|
|
|
use huey::HueError; |
|
|
|
use qmetaobject::*; |
|
|
|
use std::collections::HashMap; |
|
|
|
use std::sync::{Arc, Mutex, RwLock}; |
|
|
@@ -36,42 +37,47 @@ pub struct BridgeConnectionConnector { |
|
|
|
get_light: qt_method!(fn(&self, id: String) -> QVariant), |
|
|
|
start_set_light_on: qt_method!(fn(&self, id: String, on: bool)), |
|
|
|
start_set_light_brightness: qt_method!(fn(&self, id: String, new_value: u8)), |
|
|
|
start_set_light_hue: qt_method!(fn(&self, id: String, new_value: u16)), |
|
|
|
start_set_light_saturation: qt_method!(fn(&self, id: String, new_value: u8)), |
|
|
|
lights_changed: qt_signal!(), |
|
|
|
light_changed: qt_signal!(id: String), |
|
|
|
|
|
|
|
brightness_queue: Arc<Mutex<HashMap<String, u8>>>, |
|
|
|
hue_queue: Arc<Mutex<HashMap<String, u16>>>, |
|
|
|
saturation_queue: Arc<Mutex<HashMap<String, u8>>>, |
|
|
|
} |
|
|
|
|
|
|
|
fn set_brightness_loop<'a>(brightness_queue: Arc<Mutex<HashMap<String, u8>>>, id: String, new_value: u8, callback: Box<Fn() + Send>) -> Box<Future<Item=(), Error=()> + Send> { |
|
|
|
fn set_prop_loop<T: PartialEq + Copy + Send + 'static>( |
|
|
|
make_request: impl Fn(&str, T) -> Box<Future<Item=(),Error=HueError> + Send> + Send + 'static, |
|
|
|
update_model: impl Fn(&str, T) + Send + 'static, |
|
|
|
queue: Arc<Mutex<HashMap<String, T>>>, |
|
|
|
id: String, |
|
|
|
new_value: T, |
|
|
|
callback: Box<Fn() + Send> |
|
|
|
) -> Box<Future<Item=(), Error=()> + Send> { |
|
|
|
if let Some(ref state) = *STATE.read().unwrap() { |
|
|
|
let future = state.connection.set_light_brightness(&id, new_value); |
|
|
|
let future = make_request(&id, new_value); |
|
|
|
std::mem::drop(state); |
|
|
|
Box::new(future |
|
|
|
.then(move |res| { |
|
|
|
match res { |
|
|
|
Ok(_) => { |
|
|
|
if let Some(ref mut state) = *STATE.write().unwrap() { |
|
|
|
if let Some(ref mut lights) = state.lights { |
|
|
|
if let Some(ref mut light) = lights.get_mut(&id) { |
|
|
|
light.state.bri = new_value; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
update_model(&id, new_value); |
|
|
|
}, |
|
|
|
Err(err) => { |
|
|
|
eprintln!("{:?}", err); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
let mut queue = brightness_queue.lock().unwrap(); |
|
|
|
let target_value = queue.get(&id); |
|
|
|
let mut queue_map = queue.lock().unwrap(); |
|
|
|
let target_value = queue_map.get(&id); |
|
|
|
match target_value { |
|
|
|
Some(target_value) if *target_value != new_value => { |
|
|
|
println!("looping"); |
|
|
|
set_brightness_loop(brightness_queue.clone(), id, *target_value, callback) |
|
|
|
set_prop_loop(make_request, update_model, queue.clone(), id, *target_value, callback) |
|
|
|
}, |
|
|
|
_ => { |
|
|
|
queue.remove(&id); |
|
|
|
queue_map.remove(&id); |
|
|
|
callback(); |
|
|
|
println!("ending"); |
|
|
|
Box::new(futures::future::ok(())) |
|
|
@@ -83,6 +89,64 @@ fn set_brightness_loop<'a>(brightness_queue: Arc<Mutex<HashMap<String, u8>>>, id |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fn set_brightness_loop(brightness_queue: Arc<Mutex<HashMap<String, u8>>>, id: String, new_value: u8, callback: Box<Fn() + Send>) -> Box<Future<Item=(), Error=()> + Send> { |
|
|
|
set_prop_loop(|id, new_value| { |
|
|
|
if let Some(ref state) = *STATE.read().unwrap() { |
|
|
|
Box::new(state.connection.set_light_brightness(id, new_value)) |
|
|
|
} else { |
|
|
|
panic!("STATE missing"); |
|
|
|
} |
|
|
|
}, |id, new_value| { |
|
|
|
if let Some(ref mut state) = *STATE.write().unwrap() { |
|
|
|
if let Some(ref mut lights) = state.lights { |
|
|
|
if let Some(ref mut light) = lights.get_mut(id) { |
|
|
|
light.state.bri = new_value; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}, brightness_queue, id, new_value, callback) |
|
|
|
} |
|
|
|
|
|
|
|
fn set_hue_loop(hue_queue: Arc<Mutex<HashMap<String, u16>>>, id: String, new_value: u16, callback: Box<Fn() + Send>) -> Box<Future<Item=(), Error=()> + Send> { |
|
|
|
set_prop_loop(|id, new_value| { |
|
|
|
if let Some(ref state) = *STATE.read().unwrap() { |
|
|
|
Box::new(state.connection.set_light_hue(id, new_value)) |
|
|
|
} else { |
|
|
|
panic!("STATE missing"); |
|
|
|
} |
|
|
|
}, |id, new_value| { |
|
|
|
if let Some(ref mut state) = *STATE.write().unwrap() { |
|
|
|
if let Some(ref mut lights) = state.lights { |
|
|
|
if let Some(ref mut light) = lights.get_mut(id) { |
|
|
|
if let Some(ref mut color) = light.state.color { |
|
|
|
color.hue = new_value; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}, hue_queue, id, new_value, callback) |
|
|
|
} |
|
|
|
|
|
|
|
fn set_saturation_loop(saturation_queue: Arc<Mutex<HashMap<String, u8>>>, id: String, new_value: u8, callback: Box<Fn() + Send>) -> Box<Future<Item=(), Error=()> + Send> { |
|
|
|
set_prop_loop(|id, new_value| { |
|
|
|
if let Some(ref state) = *STATE.read().unwrap() { |
|
|
|
Box::new(state.connection.set_light_saturation(id, new_value)) |
|
|
|
} else { |
|
|
|
panic!("STATE missing"); |
|
|
|
} |
|
|
|
}, |id, new_value| { |
|
|
|
if let Some(ref mut state) = *STATE.write().unwrap() { |
|
|
|
if let Some(ref mut lights) = state.lights { |
|
|
|
if let Some(ref mut light) = lights.get_mut(id) { |
|
|
|
if let Some(ref mut color) = light.state.color { |
|
|
|
color.sat = new_value; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}, saturation_queue, id, new_value, callback) |
|
|
|
} |
|
|
|
|
|
|
|
impl BridgeConnectionConnector { |
|
|
|
fn init(&mut self, address: String, username: String) { |
|
|
|
let connection = huey::connection::BridgeConnection::new(&address, username).expect("Failed to construct BridgeConnection"); |
|
|
@@ -193,4 +257,35 @@ impl BridgeConnectionConnector { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fn start_set_light_hue(&self, id: String, new_value: u16) { |
|
|
|
let mut queue = self.hue_queue.lock().unwrap(); |
|
|
|
let old_value = queue.insert(id.clone(), new_value); |
|
|
|
if old_value == None { |
|
|
|
let callback = { |
|
|
|
let ptr = QPointer::from(&*self); |
|
|
|
let id = id.clone(); |
|
|
|
queued_callback(move |_| { |
|
|
|
ptr.as_ref().map(|x| x.light_changed(id.clone())); |
|
|
|
}) |
|
|
|
}; |
|
|
|
|
|
|
|
tokio::spawn(set_hue_loop(self.hue_queue.clone(), id, new_value, Box::new(move || callback(())))); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fn start_set_light_saturation(&self, id: String, new_value: u8) { |
|
|
|
let mut queue = self.saturation_queue.lock().unwrap(); |
|
|
|
let old_value = queue.insert(id.clone(), new_value); |
|
|
|
if old_value == None { |
|
|
|
let callback = { |
|
|
|
let ptr = QPointer::from(&*self); |
|
|
|
let id = id.clone(); |
|
|
|
queued_callback(move |_| { |
|
|
|
ptr.as_ref().map(|x| x.light_changed(id.clone())); |
|
|
|
}) |
|
|
|
}; |
|
|
|
|
|
|
|
tokio::spawn(set_saturation_loop(self.saturation_queue.clone(), id, new_value, Box::new(move || callback(())))); |
|
|
|
} |
|
|
|
} |
|
|
|
} |