rust_lum/src/main.rs
2022-03-12 20:45:27 +01:00

107 lines
3.2 KiB
Rust

mod args;
mod audio;
mod bluetooth;
mod config;
mod patterns;
mod runner;
mod spectacle;
use crate::args::Cli;
use crate::audio::play_sound;
use crate::config::{load_from_file, Config};
use crate::runner::Spectacle;
use bluer::gatt::remote::Characteristic;
use bluer::{Device, Error};
use clap::Parser;
use patterns::Strip;
use std::path::Path;
use std::sync::{Arc, Mutex};
use tokio::sync::mpsc;
use tokio::sync::watch;
const SERVICE_UUID: bluer::Uuid = bluer::Uuid::from_u128(0xadaf0900c33242a893bd25e905756cb8);
const PIXEL_DATA_UUID: bluer::Uuid = bluer::Uuid::from_u128(0xadaf0903c33242a893bd25e905756cb8);
const STRIP_SIZE: usize = 25;
const BASE_STRIP_DATA: [u8; 3] = [0x00, 0x00, 0x01];
#[tokio::main(flavor = "current_thread")]
async fn main() -> bluer::Result<()> {
let command_line = Cli::parse();
let file = Path::new(&command_line.spectacle_file);
let config: Config<25> = load_from_file(file);
let spectacle = Spectacle::from(config);
let spectacle = Arc::new(Mutex::new(spectacle));
let adapter = bluetooth::create_session().await?;
let (tx_scan, rx_scan) = mpsc::channel(3);
tokio::spawn(bluetooth::bluetooth_scan(
tx_scan,
adapter.clone(),
SERVICE_UUID,
));
tokio::spawn(connect_device(spectacle.clone(), rx_scan));
println!("starting");
let musique_file = command_line.musique_file;
let musique = tokio::task::spawn_blocking(move || play_sound(Path::new(&musique_file)));
let futures;
{
let mut spectacle = spectacle.lock().unwrap();
futures = spectacle.run();
}
let mut joinhandles = vec![];
for future in futures {
joinhandles.push(tokio::spawn(future));
}
for joinhandle in joinhandles {
joinhandle.await.unwrap();
}
musique.await.unwrap();
Ok(())
}
async fn connect_device(
spectacle: Arc<Mutex<Spectacle<STRIP_SIZE>>>,
mut rx_scan: mpsc::Receiver<Device>,
) -> Result<(), Error> {
while let Some(device) = rx_scan.recv().await {
bluetooth::connect(&device, 3).await?;
let char = bluetooth::get_char(&device, SERVICE_UUID, PIXEL_DATA_UUID).await?;
if let Some(char) = char {
let rx: Option<watch::Receiver<Strip<STRIP_SIZE>>>;
{
let spectacle = spectacle.lock().unwrap();
rx = spectacle.get_channel(&device.address());
}
if let Some(mut rx) = rx {
tokio::spawn(async move {
println!("device connected : {}", &device.address());
while rx.changed().await.is_ok() {
let strip = *rx.borrow();
if write_strip(&strip, &char).await.is_err() {
break;
};
}
println!("device {} disconnected", &device.address());
// drop(rx_device);
});
}
}
}
bluer::Result::Ok(())
}
pub async fn write_strip<const N: usize>(
data: &Strip<N>,
char: &Characteristic,
) -> bluer::Result<()> {
let frame = [BASE_STRIP_DATA.to_vec(), data.to_array()].concat();
// print!("{:?}", frame);
char.write(&*frame).await?;
Ok(())
}