//! navka-client – forward keyboard/mouse HID reports to navka-server #![forbid(unsafe_code)] use anyhow::Result; use navka_common::navka::{relay_client::RelayClient, HidReport}; use tokio::{sync::mpsc, time::sleep}; use tokio_stream::wrappers::ReceiverStream; use tonic::{transport::Channel, Request}; #[tokio::main] async fn main() -> Result<()> { tracing_subscriber::fmt::init(); // -- server address comes from CLI arg, env or falls back to localhost let addr = std::env::args() .nth(1) .or_else(|| std::env::var("NAVKA_SERVER_ADDR").ok()) .unwrap_or_else(|| "http://127.0.0.1:50051".to_owned()); let channel: Channel = Channel::from_shared(addr)? .connect() .await?; // mpsc -> ReceiverStream -> bidirectional gRPC let (tx, rx) = mpsc::channel::(32); let outbound = ReceiverStream::new(rx); let mut inbound = RelayClient::new(channel) .stream(Request::new(outbound)) .await? .into_inner(); // demo: press & release ‘a’ tokio::spawn(async move { let press_a = HidReport { data: vec![0, 0, 0x04, 0, 0, 0, 0, 0] }; let release = HidReport { data: vec![0; 8] }; tx.send(press_a).await.ok(); sleep(std::time::Duration::from_millis(100)).await; tx.send(release).await.ok(); }); while let Some(report) = inbound.message().await? { tracing::info!(bytes=?report.data, "echo from server"); } Ok(()) }