Discover and handshake

This commit is contained in:
Aode (lion) 2021-10-02 12:57:14 -05:00
parent 94539a08c4
commit 9b0a398143
7 changed files with 356 additions and 47 deletions

241
Cargo.lock generated
View file

@ -32,6 +32,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]]
name = "anyhow"
version = "1.0.44"
@ -178,6 +187,18 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
dependencies = [
"libc",
"num-integer",
"num-traits",
"winapi",
]
[[package]]
name = "concurrent-queue"
version = "1.2.2"
@ -384,6 +405,18 @@ dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "itoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.103"
@ -426,6 +459,15 @@ dependencies = [
"libc",
]
[[package]]
name = "matchers"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1"
dependencies = [
"regex-automata",
]
[[package]]
name = "memchr"
version = "2.4.1"
@ -524,6 +566,25 @@ dependencies = [
"winapi",
]
[[package]]
name = "num-integer"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.13.0"
@ -571,6 +632,26 @@ dependencies = [
"winapi",
]
[[package]]
name = "pin-project"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "pin-project-lite"
version = "0.2.7"
@ -702,12 +783,27 @@ dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "scopeguard"
version = "1.1.0"
@ -734,6 +830,17 @@ dependencies = [
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_repr"
version = "0.1.7"
@ -767,6 +874,15 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
[[package]]
name = "sharded-slab"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "740223c51853f3145fe7c90360d2d4232f2b62e3449489c207eccde818979982"
dependencies = [
"lazy_static",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.0"
@ -818,13 +934,30 @@ name = "streamdeck-dbus"
version = "0.1.0"
dependencies = [
"anyhow",
"streamdeck-handshake",
"tokio",
"tokio-actors",
"tokio-serial",
"tracing",
"tracing-error",
"tracing-futures",
"tracing-subscriber",
"uuid",
"zbus",
]
[[package]]
name = "streamdeck-handshake"
version = "0.1.0"
source = "git+https://git.asonix.dog/asonix/streamdeck-handshake?branch=main#4a17be0e0ffbdc132f53d16848585cab5207b084"
dependencies = [
"rand",
"thiserror",
"tokio",
"tokio-serial",
"tracing-error",
]
[[package]]
name = "syn"
version = "1.0.77"
@ -856,6 +989,15 @@ dependencies = [
"syn",
]
[[package]]
name = "thread_local"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
dependencies = [
"once_cell",
]
[[package]]
name = "tokio"
version = "1.12.0"
@ -889,9 +1031,9 @@ dependencies = [
[[package]]
name = "tokio-macros"
version = "1.4.0"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bad447894d469f905c43bffb355333bcc9eaaaf736d2815214e962714cad02d"
checksum = "154794c8f499c2619acd19e839294703e9e32e7630ef5f46ea80d4ef0fbee5eb"
dependencies = [
"proc-macro2",
"quote",
@ -920,6 +1062,101 @@ dependencies = [
"serde",
]
[[package]]
name = "tracing"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8"
dependencies = [
"cfg-if 1.0.0",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4f915eb6abf914599c200260efced9203504c4c37380af10cdf3b7d36970650"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4"
dependencies = [
"lazy_static",
]
[[package]]
name = "tracing-error"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4d7c0b83d4a500748fa5879461652b361edf5c9d51ede2a2ac03875ca185e24"
dependencies = [
"tracing",
"tracing-subscriber",
]
[[package]]
name = "tracing-futures"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
dependencies = [
"pin-project",
"tracing",
]
[[package]]
name = "tracing-log"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3"
dependencies = [
"lazy_static",
"log",
"tracing-core",
]
[[package]]
name = "tracing-serde"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b"
dependencies = [
"serde",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.2.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdd0568dbfe3baf7048b7908d2b32bca0d81cd56bec6d2a8f894b01d74f86be3"
dependencies = [
"ansi_term",
"chrono",
"lazy_static",
"matchers",
"regex",
"serde",
"serde_json",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
"tracing-serde",
]
[[package]]
name = "unicode-xid"
version = "0.2.2"

View file

@ -7,8 +7,13 @@ edition = "2018"
[dependencies]
anyhow = "1"
streamdeck-handshake = { version = "0.1.0", git = "https://git.asonix.dog/asonix/streamdeck-handshake", branch = "main" }
tokio = { version = "1", features = ["full"] }
tokio-serial = "5.4.1"
tokio-actors = { version = "0.1", git = "https://git.asonix.dog/asonix/tokio-actors", branch = "main" }
tracing = "0.1.28"
tracing-error = "0.1.2"
tracing-futures = "0.2.5"
tracing-subscriber = { version = "0.2.24", features = ["fmt"] }
uuid = { version = "0.8.2", features = ["serde", "v4"]}
zbus = "2.0.0-beta.7"

View file

@ -1,6 +1,5 @@
use crate::deck::Deck;
use crate::ManagerMessage;
use std::path::PathBuf;
use tokio_actors::{BoxFuture, Context, SendHandle};
use uuid::Uuid;
use zbus::Connection;
@ -13,19 +12,29 @@ pub(crate) struct Connector {
impl Connector {
pub(crate) fn new(connection: Connection, parent: SendHandle<ManagerMessage>) -> Self {
println!("new connector");
tracing::debug!("new connector");
Connector { connection, parent }
}
pub(crate) fn turn<'a>(
&'a mut self,
path: PathBuf,
ctx: &'a mut Context<PathBuf>,
port_name: String,
ctx: &'a mut Context<String>,
) -> BoxFuture<'a> {
println!("Connector");
tracing::debug!("Connector");
Box::pin(async move {
ctx.stop();
let port = match streamdeck_handshake::handshake(port_name.as_str().into()).await {
Ok(port) => port,
Err(e) => {
tracing::info!("Error: {}", e);
tracing::info!("Details: {:?}", e);
self.parent.send(ManagerMessage::Ignored(port_name)).await?;
return Err(e.into());
}
};
// TODO: Run connection logic
let deck = Deck::build(
self.connection.clone(),
@ -33,7 +42,7 @@ impl Connector {
"".to_owned(),
// TODO: look up device id
Uuid::new_v4().as_bytes().to_vec(),
path,
port_name,
self.parent.clone(),
)
.await?;

View file

@ -1,8 +1,5 @@
use crate::{DeckMessage, ManagerMessage};
use std::{
path::{Path, PathBuf},
sync::Arc,
};
use std::sync::Arc;
use tokio::sync::RwLock;
use tokio_actors::{BoxFuture, Context, SendHandle};
use zbus::Connection;
@ -19,7 +16,7 @@ struct Inner {
pub(crate) struct Deck {
connection: Connection,
id: Id,
path: PathBuf,
port_name: String,
parent: SendHandle<ManagerMessage>,
inner: Arc<RwLock<Inner>>,
}
@ -47,13 +44,13 @@ impl Deck {
connection: Connection,
name: String,
id: Vec<u8>,
path: PathBuf,
port_name: String,
parent: SendHandle<ManagerMessage>,
) -> anyhow::Result<Self> {
let deck = Deck {
connection: connection.clone(),
id: Id(id),
path,
port_name,
parent,
inner: Arc::new(RwLock::new(Inner { name })),
};
@ -63,7 +60,7 @@ impl Deck {
.await
.at(deck.object_name(), deck.clone())?;
println!("new deck");
tracing::debug!("new deck");
Ok(deck)
}
@ -79,8 +76,8 @@ impl Deck {
match msg {}
}
pub(crate) fn path(&self) -> &Path {
&self.path
pub(crate) fn port_name(&self) -> &str {
&self.port_name
}
}

View file

@ -1,4 +1,5 @@
use std::{path::PathBuf, time::Duration};
use std::time::Duration;
use tracing_subscriber::{fmt::format::FmtSpan, layer::SubscriberExt, EnvFilter};
mod connector;
mod deck;
@ -14,13 +15,16 @@ enum DeckMessage {}
#[derive(Clone, Debug)]
enum ManagerMessage {
Found(PathBuf),
Found(String),
Removed(String),
Connected(Deck),
Ignored(PathBuf),
Ignored(String),
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
init_tracing()?;
let mut root = tokio_actors::root();
let manager = Manager::build().await?;
@ -35,3 +39,20 @@ async fn main() -> anyhow::Result<()> {
Ok(())
}
fn init_tracing() -> anyhow::Result<()> {
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
let formatter = tracing_subscriber::fmt::layer()
.pretty()
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE);
let subscriber = tracing_subscriber::Registry::default()
.with(env_filter)
.with(formatter)
.with(tracing_error::ErrorLayer::default());
tracing::subscriber::set_global_default(subscriber)?;
Ok(())
}

View file

@ -1,7 +1,6 @@
use crate::{connector::Connector, deck::Deck, ManagerMessage};
use std::{
collections::{HashMap, HashSet},
path::PathBuf,
sync::Arc,
};
use tokio::sync::RwLock;
@ -10,9 +9,9 @@ use zbus::SignalContext;
#[derive(Debug, Default)]
struct Inner {
pending_ports: HashSet<PathBuf>,
connected_decks: HashMap<PathBuf, String>,
ignored_ports: HashSet<PathBuf>,
pending_ports: HashSet<String>,
connected_decks: HashMap<String, String>,
ignored_ports: HashSet<String>,
}
#[derive(Clone, Debug)]
@ -54,7 +53,7 @@ impl Manager {
.await
.at(manager.object_name(), manager.clone())?;
println!("new manager");
tracing::debug!("new manager");
Ok(manager)
}
@ -64,9 +63,10 @@ impl Manager {
ctx: &'a mut Context<ManagerMessage>,
) -> BoxFuture<'a> {
match msg {
ManagerMessage::Found(path) => Box::pin(self.found(path, ctx)),
ManagerMessage::Found(port_name) => Box::pin(self.found(port_name, ctx)),
ManagerMessage::Removed(port_name) => Box::pin(self.removed(port_name)),
ManagerMessage::Connected(deck) => Box::pin(self.connected(deck, ctx)),
ManagerMessage::Ignored(path) => Box::pin(self.ignored(path, ctx)),
ManagerMessage::Ignored(port_name) => Box::pin(self.ignored(port_name, ctx)),
}
}
@ -76,11 +76,11 @@ impl Manager {
async fn ignored(
&mut self,
path: PathBuf,
port_name: String,
_: &'_ mut Context<ManagerMessage>,
) -> anyhow::Result<()> {
println!("ignored");
self.inner.write().await.ignored_ports.insert(path);
tracing::debug!("ignored");
self.inner.write().await.ignored_ports.insert(port_name);
Ok(())
}
@ -89,12 +89,12 @@ impl Manager {
deck: Deck,
ctx: &'_ mut Context<ManagerMessage>,
) -> anyhow::Result<()> {
println!("connected");
tracing::debug!("connected");
self.inner
.write()
.await
.connected_decks
.insert(deck.path().to_owned(), deck.object_name());
.insert(deck.port_name().to_owned(), deck.object_name());
ctx.spawn_child(deck, Deck::turn);
// auto generated
@ -103,20 +103,30 @@ impl Manager {
Ok(())
}
async fn removed(&mut self, port_name: String) -> anyhow::Result<()> {
let mut inner = self.inner.write().await;
inner.pending_ports.remove(&port_name);
inner.ignored_ports.remove(&port_name);
inner.connected_decks.remove(&port_name);
Ok(())
}
async fn found(
&mut self,
path: PathBuf,
port_name: String,
ctx: &'_ mut Context<ManagerMessage>,
) -> anyhow::Result<()> {
println!("found");
tracing::debug!("found");
let inner = self.inner.read().await;
for set in [&inner.pending_ports, &inner.ignored_ports] {
if set.contains(&path) {
if set.contains(&port_name) {
return Ok(());
}
}
if inner.connected_decks.contains_key(&path) {
if inner.connected_decks.contains_key(&port_name) {
return Ok(());
}
@ -124,11 +134,11 @@ impl Manager {
let connector = Connector::new(self.connection.clone(), ctx.handle());
let mut handle = ctx.spawn_child(connector, Connector::turn);
if let Err(e) = handle.send(path.clone()).await {
if let Err(e) = handle.send(port_name.clone()).await {
handle.stop();
return Err(e.into());
}
self.inner.write().await.pending_ports.insert(path);
self.inner.write().await.pending_ports.insert(port_name);
Ok(())
}

View file

@ -1,16 +1,23 @@
use crate::ManagerMessage;
use std::path::PathBuf;
use std::{
collections::HashSet,
path::{Path, PathBuf},
};
use tokio_actors::{BoxFuture, Context, SendHandle};
#[derive(Clone, Debug)]
pub(crate) struct Searcher {
manager: SendHandle<ManagerMessage>,
connected: HashSet<String>,
}
impl Searcher {
pub(crate) fn new(manager: SendHandle<ManagerMessage>) -> Self {
println!("new searcher");
Searcher { manager }
tracing::debug!("new searcher");
Searcher {
manager,
connected: HashSet::new(),
}
}
pub(crate) fn turn<'a>(&'a mut self, _: (), _: &'a mut Context<()>) -> BoxFuture<'a> {
@ -18,11 +25,34 @@ impl Searcher {
}
async fn search(&mut self) -> anyhow::Result<()> {
println!("Search");
// TODO: do searching
self.manager
.send(ManagerMessage::Found(PathBuf::new()))
.await?;
let ports = tokio::task::block_in_place(|| tokio_serial::available_ports())?;
let port_names = ports
.into_iter()
.map(|p| p.port_name)
.collect::<HashSet<String>>();
for port in port_names.difference(&self.connected) {
let port = if port.starts_with("/sys/class/tty") {
let port: &Path = port.as_ref();
let port = port.iter().rev().next().unwrap();
let device = PathBuf::new().join("/").join("dev").join(port);
device.to_string_lossy().to_string()
} else {
port.to_owned()
};
self.manager.send(ManagerMessage::Found(port)).await?;
}
for port in self.connected.difference(&port_names) {
self.manager
.send(ManagerMessage::Removed(port.to_owned()))
.await?;
}
self.connected = port_names;
Ok(())
}
}