WP
This commit is contained in:
parent
4f1f1ba88e
commit
d8ebb16486
31
src/main.rs
31
src/main.rs
@ -22,6 +22,7 @@ use std::env;
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
use std::sync::{Arc, Barrier};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
use crate::filter::*;
|
use crate::filter::*;
|
||||||
@ -73,7 +74,7 @@ fn main() {
|
|||||||
simplelog::TermLogger::init(
|
simplelog::TermLogger::init(
|
||||||
level,
|
level,
|
||||||
simplelog::Config {
|
simplelog::Config {
|
||||||
time: Some(simplelog::Level::Debug),
|
time: None,
|
||||||
level: Some(simplelog::Level::Error),
|
level: Some(simplelog::Level::Error),
|
||||||
target: Some(simplelog::Level::Info),
|
target: Some(simplelog::Level::Info),
|
||||||
location: Some(simplelog::Level::Debug),
|
location: Some(simplelog::Level::Debug),
|
||||||
@ -93,10 +94,14 @@ fn main() {
|
|||||||
let config: AppConfig =
|
let config: AppConfig =
|
||||||
serde_yaml::from_str(&config_content).expect("Invalid config file content");
|
serde_yaml::from_str(&config_content).expect("Invalid config file content");
|
||||||
|
|
||||||
|
let thread_count = config.monitors.len() + config.outputs.len();
|
||||||
|
let barrier = Arc::new(Barrier::new(thread_count + 1));
|
||||||
|
|
||||||
// Monitors -> dispatcher channel
|
// Monitors -> dispatcher channel
|
||||||
let (mon_sender, mon_receiver) = mpsc::channel();
|
let (mon_sender, mon_receiver) = mpsc::channel();
|
||||||
|
|
||||||
// Instantiate monitor threads and structs
|
// Instantiate monitor threads and structs
|
||||||
|
let mut mon_threads = vec![];
|
||||||
for mon_config in config.monitors {
|
for mon_config in config.monitors {
|
||||||
let mon_type = mon_config
|
let mon_type = mon_config
|
||||||
.get("type")
|
.get("type")
|
||||||
@ -106,21 +111,23 @@ fn main() {
|
|||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
let snd = mon_sender.clone();
|
let snd = mon_sender.clone();
|
||||||
|
let bar = barrier.clone();
|
||||||
|
|
||||||
thread::spawn(move || {
|
mon_threads.push(thread::spawn(move || {
|
||||||
log::info!("+> monitor: {}", mon_type);
|
log::info!("+> monitor: {}", mon_type);
|
||||||
match monitors::factory(&mon_type, &mon_config) {
|
match monitors::factory(&mon_type, &mon_config) {
|
||||||
Ok(mut mon) => loop {
|
Ok(mut mon) => loop {
|
||||||
|
bar.wait();
|
||||||
mon.run(&snd);
|
mon.run(&snd);
|
||||||
},
|
},
|
||||||
Err(e) => log::error!("Cannot instantiate monitor {}: {}", mon_type, e),
|
Err(e) => log::error!("Cannot instantiate monitor {}: {}", mon_type, e),
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instantiate output threads and structs
|
// Instantiate output threads and structs
|
||||||
// let mut outputs: Vec<(Box<Output>, Filter)> = vec![];
|
|
||||||
let mut output_senders: Vec<mpsc::Sender<Message>> = vec![];
|
let mut output_senders: Vec<mpsc::Sender<Message>> = vec![];
|
||||||
|
let mut output_threads = vec![];
|
||||||
for out_config in config.outputs {
|
for out_config in config.outputs {
|
||||||
let out_type = out_config
|
let out_type = out_config
|
||||||
.get("type")
|
.get("type")
|
||||||
@ -133,11 +140,13 @@ fn main() {
|
|||||||
output_senders.push(out_sender);
|
output_senders.push(out_sender);
|
||||||
|
|
||||||
let filter = Filter::new(&out_config);
|
let filter = Filter::new(&out_config);
|
||||||
|
let bar = barrier.clone();
|
||||||
|
|
||||||
thread::spawn(move || {
|
output_threads.push(thread::spawn(move || {
|
||||||
log::info!("+> output: {}", out_type);
|
log::info!("+> output: {}", out_type);
|
||||||
match outputs::factory(&out_type, &out_config) {
|
match outputs::factory(&out_type, &out_config) {
|
||||||
Ok(mut output) => loop {
|
Ok(mut output) => loop {
|
||||||
|
bar.wait();
|
||||||
let message = out_receiver.recv().unwrap();
|
let message = out_receiver.recv().unwrap();
|
||||||
if filter.is_message_allowed(&message) {
|
if filter.is_message_allowed(&message) {
|
||||||
output.process_message(message);
|
output.process_message(message);
|
||||||
@ -145,10 +154,20 @@ fn main() {
|
|||||||
},
|
},
|
||||||
Err(e) => log::error!("Cannot instantiate output {}: {}", out_type, e),
|
Err(e) => log::error!("Cannot instantiate output {}: {}", out_type, e),
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
let output_senders = output_senders;
|
let output_senders = output_senders;
|
||||||
|
|
||||||
|
// Start all the threads
|
||||||
|
barrier.wait();
|
||||||
|
log::info!("Started rnetmon");
|
||||||
|
for t in &mon_threads {
|
||||||
|
t.thread().unpark();
|
||||||
|
}
|
||||||
|
for t in &output_threads {
|
||||||
|
t.thread().unpark();
|
||||||
|
}
|
||||||
|
|
||||||
// Dispatch messages
|
// Dispatch messages
|
||||||
loop {
|
loop {
|
||||||
let message = mon_receiver.recv().unwrap();
|
let message = mon_receiver.recv().unwrap();
|
||||||
|
@ -31,14 +31,15 @@ impl Monitor for DHCPLeases {
|
|||||||
.get("config")
|
.get("config")
|
||||||
.unwrap_or(&serde_yaml::Mapping::new().into())
|
.unwrap_or(&serde_yaml::Mapping::new().into())
|
||||||
.clone();
|
.clone();
|
||||||
let config = serde_yaml::from_value(config_node).expect("Invalid config for dhcp_leases");
|
let config = serde_yaml::from_value(config_node)?;
|
||||||
|
|
||||||
// Regex compilation
|
// Regex compilation
|
||||||
let rgx_lease = Regex::new(r"(?s)lease\s+(\d+(?:\.\d+){3})\s*\{\n?(.*?)\}").unwrap();
|
let rgx_lease = Regex::new(r"(?s)lease\s+(\d+(?:\.\d+){3})\s*\{\n?(.*?)\}").unwrap();
|
||||||
let rgx_mac =
|
let rgx_mac =
|
||||||
Regex::new(r"^\s*hardware\s+ethernet\s([a-f0-9]{2}(?::[a-f0-9]{2}){5})\s*;").unwrap();
|
Regex::new(r"(?m)^\s*hardware\s+ethernet\s([a-f0-9]{2}(?::[a-f0-9]{2}){5})\s*;")
|
||||||
let rgx_date_start = Regex::new(r"^\s*starts\s+(.*?)\s*;").unwrap();
|
.unwrap();
|
||||||
let rgx_date_ends = Regex::new(r"^\s*ends\s+(.*?)\s*;").unwrap();
|
let rgx_date_start = Regex::new(r"(?m)^\s*starts\s+\d+\s+(.*?)\s*;").unwrap();
|
||||||
|
let rgx_date_ends = Regex::new(r"(?m)^\s*ends\s+\d+\s+(.*?)\s*;").unwrap();
|
||||||
|
|
||||||
Ok(DHCPLeases {
|
Ok(DHCPLeases {
|
||||||
config: config,
|
config: config,
|
||||||
@ -66,36 +67,38 @@ impl Monitor for DHCPLeases {
|
|||||||
let mut unauthorized_macs: Vec<String> = vec![];
|
let mut unauthorized_macs: Vec<String> = vec![];
|
||||||
|
|
||||||
for cap in self.rgx_lease.captures_iter(&config_content) {
|
for cap in self.rgx_lease.captures_iter(&config_content) {
|
||||||
let ip = cap.get(1).unwrap().as_str();
|
let _ip = cap.get(1).unwrap().as_str();
|
||||||
let content = cap.get(2).unwrap().as_str();
|
let content = cap.get(2).unwrap().as_str();
|
||||||
|
|
||||||
let mac = self
|
let mac = self
|
||||||
.rgx_mac
|
.rgx_mac
|
||||||
.captures(content)
|
.captures(content)
|
||||||
.expect("No 'hardware ethernet' field found for MAC address")
|
.expect(&format!(
|
||||||
.get(0)
|
"No 'hardware ethernet' field found for MAC address in {}",
|
||||||
|
content
|
||||||
|
))
|
||||||
|
.get(1)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_str();
|
.as_str();
|
||||||
let starts_str = self
|
let starts_str = self
|
||||||
.rgx_date_start
|
.rgx_date_start
|
||||||
.captures(content)
|
.captures(content)
|
||||||
.expect("No 'starts' field found in lease")
|
.expect("No 'starts' field found in lease")
|
||||||
.get(0)
|
.get(1)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_str();
|
.as_str();
|
||||||
let starts =
|
let starts =
|
||||||
chrono::naive::NaiveDateTime::parse_from_str(starts_str, "%U %Y/%m/%d %H:%M:%S")
|
chrono::naive::NaiveDateTime::parse_from_str(starts_str, "%Y/%m/%d %H:%M:%S")
|
||||||
.expect("Bad date format");
|
.expect(&format!("Bad date format: '{}'", starts_str));
|
||||||
let ends_str = self
|
let ends_str = self
|
||||||
.rgx_date_ends
|
.rgx_date_ends
|
||||||
.captures(content)
|
.captures(content)
|
||||||
.expect("No 'ends' field found in lease")
|
.expect("No 'ends' field found in lease")
|
||||||
.get(0)
|
.get(1)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_str();
|
.as_str();
|
||||||
let ends =
|
let ends = chrono::naive::NaiveDateTime::parse_from_str(ends_str, "%Y/%m/%d %H:%M:%S")
|
||||||
chrono::naive::NaiveDateTime::parse_from_str(ends_str, "%U %Y/%m/%d %H:%M:%S")
|
.expect(&format!("Bad date format: '{}'", ends_str));
|
||||||
.expect("Bad date format");
|
|
||||||
|
|
||||||
let now = Local::now().naive_local();
|
let now = Local::now().naive_local();
|
||||||
if starts <= now && now < ends {
|
if starts <= now && now < ends {
|
||||||
|
@ -2,6 +2,7 @@ extern crate blurz;
|
|||||||
|
|
||||||
use blurz::bluetooth_adapter::BluetoothAdapter;
|
use blurz::bluetooth_adapter::BluetoothAdapter;
|
||||||
use blurz::bluetooth_device::BluetoothDevice;
|
use blurz::bluetooth_device::BluetoothDevice;
|
||||||
|
use blurz::bluetooth_discovery_session::BluetoothDiscoverySession;
|
||||||
use blurz::bluetooth_gatt_characteristic::BluetoothGATTCharacteristic;
|
use blurz::bluetooth_gatt_characteristic::BluetoothGATTCharacteristic;
|
||||||
use blurz::bluetooth_gatt_service::BluetoothGATTService;
|
use blurz::bluetooth_gatt_service::BluetoothGATTService;
|
||||||
use blurz::bluetooth_session::BluetoothSession;
|
use blurz::bluetooth_session::BluetoothSession;
|
||||||
@ -63,13 +64,19 @@ impl LightConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl BluetoothLightbulb {
|
impl BluetoothLightbulb {
|
||||||
fn set_color(&self, characs: &Vec<BluetoothGATTCharacteristic>, r: f64, g: f64, b: f64) {
|
fn set_color(
|
||||||
|
&self,
|
||||||
|
targets: &Vec<(BluetoothDevice, BluetoothGATTCharacteristic)>,
|
||||||
|
r: f64,
|
||||||
|
g: f64,
|
||||||
|
b: f64,
|
||||||
|
) {
|
||||||
let r = (r * 255.0) as u8;
|
let r = (r * 255.0) as u8;
|
||||||
let g = (g * 255.0) as u8;
|
let g = (g * 255.0) as u8;
|
||||||
let b = (b * 255.0) as u8;
|
let b = (b * 255.0) as u8;
|
||||||
|
|
||||||
// println!("r={} g={} b={}", r, g, b);
|
// println!("r={} g={} b={}", r, g, b);
|
||||||
for charac in characs {
|
for (_, charac) in targets {
|
||||||
charac
|
charac
|
||||||
.write_value(vec![0x55, 0x13, r, g, b, '\r' as u8, '\n' as u8], None)
|
.write_value(vec![0x55, 0x13, r, g, b, '\r' as u8, '\n' as u8], None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -78,10 +85,15 @@ impl BluetoothLightbulb {
|
|||||||
|
|
||||||
fn initiate_scan(&self, adapter: &BluetoothAdapter) {
|
fn initiate_scan(&self, adapter: &BluetoothAdapter) {
|
||||||
if !adapter.is_discovering().unwrap() {
|
if !adapter.is_discovering().unwrap() {
|
||||||
log::info!("bluetooth adapter {}: Set scan ON", adapter.get_id());
|
log::info!("{}: Searching for new devices...", adapter.get_id());
|
||||||
adapter
|
|
||||||
|
let disc_session =
|
||||||
|
BluetoothDiscoverySession::create_session(&self.session, adapter.get_id())
|
||||||
|
.expect("Could not create discovery session");
|
||||||
|
|
||||||
|
disc_session
|
||||||
.start_discovery()
|
.start_discovery()
|
||||||
.expect("Cannot activate scanning on bluetooth device");
|
.expect("Could not start discovery session");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,8 +106,7 @@ impl Output for BluetoothLightbulb {
|
|||||||
.get("config")
|
.get("config")
|
||||||
.unwrap_or(&serde_yaml::Mapping::new().into())
|
.unwrap_or(&serde_yaml::Mapping::new().into())
|
||||||
.clone();
|
.clone();
|
||||||
let config: BluetoothLightbulbConfig =
|
let config: BluetoothLightbulbConfig = serde_yaml::from_value(config_node)?;
|
||||||
serde_yaml::from_value(config_node).expect("Invalid config for light_beewi_bbl227");
|
|
||||||
|
|
||||||
let msg_types = config
|
let msg_types = config
|
||||||
.msg_types
|
.msg_types
|
||||||
@ -115,8 +126,7 @@ impl Output for BluetoothLightbulb {
|
|||||||
.map(|(k, v)| (k.clone(), v.clone()))
|
.map(|(k, v)| (k.clone(), v.clone()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let session =
|
let session = BluetoothSession::create_session(None)?;
|
||||||
BluetoothSession::create_session(None).expect("Could not initialize bluetooth session");
|
|
||||||
|
|
||||||
let ret = BluetoothLightbulb {
|
let ret = BluetoothLightbulb {
|
||||||
config: config,
|
config: config,
|
||||||
@ -125,9 +135,8 @@ impl Output for BluetoothLightbulb {
|
|||||||
session: session,
|
session: session,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize bluetooth device
|
// Initialize bluetooth adapter
|
||||||
let adapter =
|
let adapter = BluetoothAdapter::init(&ret.session)?;
|
||||||
BluetoothAdapter::init(&ret.session).expect("Could not initialize bluetooth adapter");
|
|
||||||
// Power on
|
// Power on
|
||||||
if !adapter.is_powered().unwrap() {
|
if !adapter.is_powered().unwrap() {
|
||||||
log::info!("bluetooth adapter {}: Set power ON", adapter.get_id());
|
log::info!("bluetooth adapter {}: Set power ON", adapter.get_id());
|
||||||
@ -135,8 +144,6 @@ impl Output for BluetoothLightbulb {
|
|||||||
.set_powered(true)
|
.set_powered(true)
|
||||||
.expect("Cannot power on bluetooth device");
|
.expect("Cannot power on bluetooth device");
|
||||||
}
|
}
|
||||||
// Start scan
|
|
||||||
ret.initiate_scan(&adapter);
|
|
||||||
|
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
@ -144,7 +151,7 @@ impl Output for BluetoothLightbulb {
|
|||||||
let adapter =
|
let adapter =
|
||||||
BluetoothAdapter::init(&self.session).expect("Could not initialize bluetooth adapter");
|
BluetoothAdapter::init(&self.session).expect("Could not initialize bluetooth adapter");
|
||||||
|
|
||||||
let mut characs = vec![];
|
let mut targets = vec![];
|
||||||
let mut found_macs: HashMap<String, bool> = HashMap::new();
|
let mut found_macs: HashMap<String, bool> = HashMap::new();
|
||||||
for mac in self.config.mac.keys() {
|
for mac in self.config.mac.keys() {
|
||||||
found_macs.insert(mac.to_owned(), false);
|
found_macs.insert(mac.to_owned(), false);
|
||||||
@ -157,13 +164,19 @@ impl Output for BluetoothLightbulb {
|
|||||||
if self.config.mac.contains_key(&addr) {
|
if self.config.mac.contains_key(&addr) {
|
||||||
if !device.is_connected().unwrap() {
|
if !device.is_connected().unwrap() {
|
||||||
log::info!("Connecting to {}", addr);
|
log::info!("Connecting to {}", addr);
|
||||||
match device.connect(5000) {
|
match device.connect(30000) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let power = device.get_tx_power().expect("Could not request tx power");
|
let power = match device.get_tx_power() {
|
||||||
|
Ok(p) => p.to_string(),
|
||||||
|
Err(_) => "?".to_owned(),
|
||||||
|
};
|
||||||
log::info!("Connected to {}, tx power={}", addr, power);
|
log::info!("Connected to {}, tx power={}", addr, power);
|
||||||
|
|
||||||
|
// GATT characteristics can take a second to correctly load once connected
|
||||||
|
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Could not connect to {}: {}", addr, e);
|
log::error!("Could not connect to {}: {:?}", addr, e);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -182,7 +195,7 @@ impl Output for BluetoothLightbulb {
|
|||||||
let charac_uuid = charac.get_uuid().unwrap();
|
let charac_uuid = charac.get_uuid().unwrap();
|
||||||
|
|
||||||
if charac_uuid == "a8b3fff1-4834-4051-89d0-3de95cddd318" {
|
if charac_uuid == "a8b3fff1-4834-4051-89d0-3de95cddd318" {
|
||||||
characs.push(charac);
|
targets.push((device.clone(), charac));
|
||||||
found_macs.insert(addr.clone(), true);
|
found_macs.insert(addr.clone(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,11 +204,11 @@ impl Output for BluetoothLightbulb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// List devices not found
|
||||||
let macs_not_found: HashMap<String, bool> = found_macs
|
let macs_not_found: HashMap<String, bool> = found_macs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|(_, v)| *v == false)
|
.filter(|(_, v)| *v == false)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if macs_not_found.len() > 0 {
|
if macs_not_found.len() > 0 {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
"Could not find configured lightbulbs: {:?}",
|
"Could not find configured lightbulbs: {:?}",
|
||||||
@ -205,7 +218,7 @@ impl Output for BluetoothLightbulb {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find out color & pattern to play
|
// Merge LightConfig properties
|
||||||
let mut cfg = LightConfig {
|
let mut cfg = LightConfig {
|
||||||
color: Some(0xffffff),
|
color: Some(0xffffff),
|
||||||
animation: Some(Animation::Smooth),
|
animation: Some(Animation::Smooth),
|
||||||
@ -222,6 +235,7 @@ impl Output for BluetoothLightbulb {
|
|||||||
cfg.merge(level_cfg);
|
cfg.merge(level_cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Aimation properties
|
||||||
let color = cfg.color.unwrap();
|
let color = cfg.color.unwrap();
|
||||||
let r = ((color >> 16) & 0xff) as f64 / 255.0;
|
let r = ((color >> 16) & 0xff) as f64 / 255.0;
|
||||||
let g = ((color >> 8) & 0xff) as f64 / 255.0;
|
let g = ((color >> 8) & 0xff) as f64 / 255.0;
|
||||||
@ -235,16 +249,16 @@ impl Output for BluetoothLightbulb {
|
|||||||
for _ in 0..cfg.repeat.unwrap() {
|
for _ in 0..cfg.repeat.unwrap() {
|
||||||
match anim {
|
match anim {
|
||||||
Animation::None => {
|
Animation::None => {
|
||||||
self.set_color(&characs, r, g, b);
|
self.set_color(&targets, r, g, b);
|
||||||
std::thread::sleep(std::time::Duration::from_millis((2000.0 / speed) as u64));
|
std::thread::sleep(std::time::Duration::from_millis((2000.0 / speed) as u64));
|
||||||
}
|
}
|
||||||
Animation::Bounce => {
|
Animation::Bounce => {
|
||||||
for _ in 0..4 {
|
for _ in 0..4 {
|
||||||
self.set_color(&characs, r, g, b);
|
self.set_color(&targets, r, g, b);
|
||||||
std::thread::sleep(std::time::Duration::from_millis(
|
std::thread::sleep(std::time::Duration::from_millis(
|
||||||
(250.0 / speed) as u64,
|
(250.0 / speed) as u64,
|
||||||
));
|
));
|
||||||
self.set_color(&characs, r * 0.5, g * 0.5, b * 0.5);
|
self.set_color(&targets, r * 0.5, g * 0.5, b * 0.5);
|
||||||
std::thread::sleep(std::time::Duration::from_millis(
|
std::thread::sleep(std::time::Duration::from_millis(
|
||||||
(250.0 / speed) as u64,
|
(250.0 / speed) as u64,
|
||||||
));
|
));
|
||||||
@ -253,11 +267,11 @@ impl Output for BluetoothLightbulb {
|
|||||||
Animation::Smooth => {
|
Animation::Smooth => {
|
||||||
for i in 0..10 {
|
for i in 0..10 {
|
||||||
let mult = i as f64 / 10.0;
|
let mult = i as f64 / 10.0;
|
||||||
self.set_color(&characs, r * mult, g * mult, b * mult);
|
self.set_color(&targets, r * mult, g * mult, b * mult);
|
||||||
}
|
}
|
||||||
for i in 0..10 {
|
for i in 0..10 {
|
||||||
let mult = 1.0 - (i as f64 / 10.0);
|
let mult = 1.0 - (i as f64 / 10.0);
|
||||||
self.set_color(&characs, r * mult, g * mult, b * mult);
|
self.set_color(&targets, r * mult, g * mult, b * mult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Animation::Blink => {
|
Animation::Blink => {
|
||||||
@ -266,7 +280,7 @@ impl Output for BluetoothLightbulb {
|
|||||||
0 => (r, g, b),
|
0 => (r, g, b),
|
||||||
_ => (0.0, 0.0, 0.0),
|
_ => (0.0, 0.0, 0.0),
|
||||||
};
|
};
|
||||||
self.set_color(&characs, r, g, b);
|
self.set_color(&targets, r, g, b);
|
||||||
std::thread::sleep(std::time::Duration::from_millis(
|
std::thread::sleep(std::time::Duration::from_millis(
|
||||||
(400.0 / speed) as u64,
|
(400.0 / speed) as u64,
|
||||||
));
|
));
|
||||||
@ -275,24 +289,24 @@ impl Output for BluetoothLightbulb {
|
|||||||
Animation::RampUp => {
|
Animation::RampUp => {
|
||||||
for i in 0..20 {
|
for i in 0..20 {
|
||||||
let mult = i as f64 / 20.0;
|
let mult = i as f64 / 20.0;
|
||||||
self.set_color(&characs, r * mult, g * mult, b * mult);
|
self.set_color(&targets, r * mult, g * mult, b * mult);
|
||||||
}
|
}
|
||||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||||
self.set_color(&characs, 0.0, 0.0, 0.0);
|
self.set_color(&targets, 0.0, 0.0, 0.0);
|
||||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||||
}
|
}
|
||||||
Animation::RampDown => {
|
Animation::RampDown => {
|
||||||
self.set_color(&characs, r, g, b);
|
self.set_color(&targets, r, g, b);
|
||||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||||
for i in 1..20 {
|
for i in 1..20 {
|
||||||
let mult = 1.0 - (i as f64 / 20.0);
|
let mult = 1.0 - (i as f64 / 20.0);
|
||||||
self.set_color(&characs, r * mult, g * mult, b * mult);
|
self.set_color(&targets, r * mult, g * mult, b * mult);
|
||||||
}
|
}
|
||||||
self.set_color(&characs, 0.0, 0.0, 0.0);
|
self.set_color(&targets, 0.0, 0.0, 0.0);
|
||||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.set_color(&characs, 0.0, 0.0, 0.0);
|
self.set_color(&targets, 0.0, 0.0, 0.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user