//! navka-client – forward keyboard/mouse HID reports to navka-server #![forbid(unsafe_code)] use anyhow::Result; use navka_common::navka::{hid_report::*, 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<()> { // Connect to navka-server (adjust the address if server not local) let channel = Channel::from_static("http://127.0.0.1:50051") .connect() .await?; // mpsc channel -> ReceiverStream -> gRPC bidirectional stream let (tx, rx) = mpsc::channel::(32); let outbound = ReceiverStream::new(rx); // Kick off the RPC – note: in tonic 0.11 the request object is built // by wrapping the outbound stream in `Request::new(...)`. let mut inbound = RelayClient::new(channel) .stream(Request::new(outbound)) .await? .into_inner(); // Example task: press and release the 'a' key once. tokio::spawn(async move { // 8-byte boot-keyboard report: [mods, reserved, key1..6] let press_a = HidReport { data: vec![0x00, 0x00, 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(); }); // Print whatever the server echoes back. while let Some(report) = inbound.message().await? { println!("🔄 received: {:?}", report.data); } Ok(()) }