Browse Source

Colors & stuff!

translation
Colin Reeder 4 years ago
parent
commit
89db499142
4 changed files with 187 additions and 23 deletions
  1. +1
    -1
      Cargo.toml
  2. +65
    -9
      qml/Main.qml
  3. +13
    -0
      src/adapters.rs
  4. +108
    -13
      src/connection_connector.rs

+ 1
- 1
Cargo.toml View File

@@ -10,7 +10,7 @@ qmetaobject = "0.0.5"
cstr = "0.1.0"
cpp = "0.5"
tokio = "0.1.15"
huey = { git = "https://git.vpzom.click/vpzom/huey", rev = "3d6582bc" }
huey = { git = "https://git.vpzom.click/vpzom/huey", rev = "cdbe0684" }
# huey = { path = "../hueclient" }
futures = "0.1.25"
try_future = "0.1.3"


+ 65
- 9
qml/Main.qml View File

@@ -126,9 +126,7 @@ ApplicationWindow {
RowLayout {
height: parent.height
width: parent.width
Item {
Layout.preferredWidth: 8
}
Item { Layout.preferredWidth: 8 }
Label {
text: name
font.pointSize: 12
@@ -142,6 +140,7 @@ ApplicationWindow {
connector.start_set_light_on(model.id, checked);
}
}
Item { Layout.preferredWidth: 2 }
}
}
}
@@ -221,6 +220,7 @@ ApplicationWindow {
connector.start_set_light_on(light.id, checked);
}
}
Item { Layout.preferredWidth: 2 }
}
}
ItemDelegate {
@@ -228,9 +228,7 @@ ApplicationWindow {
RowLayout {
height: parent.height
width: parent.width
Item {
Layout.preferredWidth: 8
}
Item { Layout.preferredWidth: 8 }
Label {
text: "Brightness"
verticalAlignment: Text.AlignVCenter
@@ -247,6 +245,63 @@ ApplicationWindow {
connector.start_set_light_brightness(light.id, value);
}
}
Item { Layout.preferredWidth: 2 }
}
}
ItemDelegate {
Layout.fillWidth: true
visible: light.state.color.valid
RowLayout {
height: parent.height
width: parent.width
Item {
Layout.preferredWidth: 8
}
Label {
text: "Hue"
verticalAlignment: Text.AlignVCenter
}
Item { Layout.fillWidth: true }
Slider {
from: 0
to: 65535
value: light.state.color.hue
stepSize: 1

onMoved: {
console.log(value);
connector.start_set_light_hue(light.id, value);
}
}
Item { Layout.preferredWidth: 2 }
}
}
ItemDelegate {
Layout.fillWidth: true
visible: light.state.color.valid
RowLayout {
height: parent.height
width: parent.width
Item {
Layout.preferredWidth: 8
}
Label {
text: "Saturation"
verticalAlignment: Text.AlignVCenter
}
Item { Layout.fillWidth: true }
Slider {
from: 0
to: 254
value: light.state.color.sat
stepSize: 1

onMoved: {
console.log(value);
connector.start_set_light_saturation(light.id, value);
}
}
Item { Layout.preferredWidth: 2 }
}
}
}
@@ -256,11 +311,12 @@ ApplicationWindow {

function fetchLight() {
const newLight = connector.get_light(light.id);
console.log(typeof light.state, typeof newLight.state);
console.log(light.state, newLight.state);
const newState = newLight.state;
console.log(typeof light.state, typeof newState);
console.log(light.state, newState);

light.name = newLight.name.toString();
light.state = newLight.state;
light.state = newState;
}

onLights_changed: fetchLight()


+ 13
- 0
src/adapters.rs View File

@@ -11,6 +11,14 @@ pub struct RadiateLight {
pub struct RadiateLightState {
on: qt_property!(bool),
bri: qt_property!(u8),
color: qt_property!(RadiateLightColorState),
}

#[derive(QGadget, Default, Clone)]
pub struct RadiateLightColorState {
valid: qt_property!(bool),
hue: qt_property!(u16),
sat: qt_property!(u8),
}

impl From<&huey::connection::Light> for RadiateLight {
@@ -19,6 +27,11 @@ impl From<&huey::connection::Light> for RadiateLight {
result.name = light.name.clone();
result.state.on = light.state.on;
result.state.bri = light.state.bri;
if let Some(ref color) = light.state.color {
result.state.color.valid = true;
result.state.color.hue = color.hue;
result.state.color.sat = color.sat;
}

result
}


+ 108
- 13
src/connection_connector.rs View File

@@ -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(()))));
}
}
}

Loading…
Cancel
Save