diff --git a/Cargo.lock b/Cargo.lock index 91ba103..86666b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -136,12 +136,6 @@ dependencies = [ "slab", ] -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - [[package]] name = "io-kit-sys" version = "0.4.1" @@ -291,27 +285,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "strum" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "syn" version = "2.0.117" @@ -418,7 +391,6 @@ version = "0.1.0" dependencies = [ "bytes", "futures-util", - "strum", "thiserror", "tokio", "tokio-serial", diff --git a/Cargo.toml b/Cargo.toml index 43374bb..b84782e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,6 @@ edition = "2024" [dependencies] bytes = "1.11.0" futures-util = "0.3.31" -strum = { version = "0.28.0", features = ["derive"] } thiserror = "2.0.17" tokio = { version = "1.49.0", features = ["macros", "rt-multi-thread", "time"] } tokio-serial = { version = "5.4.5", features = ["codec"] } diff --git a/src/codec/command.rs b/src/codec/command.rs index fd35dea..ecac544 100644 --- a/src/codec/command.rs +++ b/src/codec/command.rs @@ -1,3 +1,5 @@ +use std::fmt::Write; + pub trait Command { fn as_bytes(&self) -> &'static [u8]; @@ -7,7 +9,13 @@ pub trait Command { } pub trait Param { - fn as_bytes(&self) -> &[u8]; + fn write_bytes(&self, dst: &mut tokio_util::bytes::BytesMut); +} + +impl Param for u8 { + fn write_bytes(&self, dst: &mut tokio_util::bytes::BytesMut) { + write!(dst, "{self}").unwrap() + } } // TODO: don't require named params @@ -21,7 +29,7 @@ macro_rules! command { } }; ($cmd:literal, $name: ident { $($param:ident: $param_ty:ty),+ }) => { - pub struct $name { $($param: $param_ty),+ } + pub struct $name { $(pub $param: $param_ty),+ } impl Command for $name { fn as_bytes(&self) -> &'static [u8] { $cmd @@ -39,16 +47,35 @@ macro_rules! param { $($variant),+ } impl Param for $name { - fn as_bytes(&self) -> &[u8] { - match self { + fn write_bytes(&self, dst: &mut tokio_util::bytes::BytesMut) { + let s = match self { $(Self::$variant => $val),+ - } + }; + dst.extend_from_slice(s); } } - } + }; + (pub range $name:ident ($range:expr)) => { + pub struct $name(u8); + impl $name { + pub fn new(value: u8) -> Self { + assert!($range.contains(&value)); + Self(value) + } + } + impl Param for $name { + fn write_bytes(&self, dst: &mut tokio_util::bytes::BytesMut) { + self.0.write_bytes(dst); + } + } + }; } +command!(b"PRG", EnterProgramMode); +command!(b"EPG", ExitProgramMode); +command!(b"MDL", GetModelInfo); command!(b"VER", GetFirmwareVersion); + command!(b"BLT", GetBacklight); command!( b"BLT", @@ -66,3 +93,12 @@ param! { KeySquelch => b"KS" } } + +command!(b"BSV", GetBatteryInfo); +command!( + b"BSV", + SetBatteryInfo { + charge_time: BatteryChargeTime + } +); +param!(pub range BatteryChargeTime(1..=16)); diff --git a/src/codec/mod.rs b/src/codec/mod.rs index 563893c..a4b1c84 100644 --- a/src/codec/mod.rs +++ b/src/codec/mod.rs @@ -36,7 +36,7 @@ where for param in item.params() { dst.put_u8(b','); - dst.extend_from_slice(param.as_bytes()); + param.write_bytes(dst); } dst.put_u8(b'\r'); diff --git a/src/lib.rs b/src/lib.rs index f08b82f..e86cb54 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,10 @@ use tokio_util::codec::{AnyDelimiterCodecError, Framed}; use crate::codec::Codec; use crate::codec::command::Command; -pub use crate::codec::command::{Backlight, GetBacklight, GetFirmwareVersion, SetBacklight}; +pub use crate::codec::command::{ + Backlight, BatteryChargeTime, EnterProgramMode, ExitProgramMode, GetBacklight, GetBatteryInfo, + GetFirmwareVersion, GetModelInfo, SetBacklight, SetBatteryInfo, +}; const VENDOR_ID: u16 = 0x1965; const PRODUCT_ID: u16 = 0x0017; diff --git a/src/main.rs b/src/main.rs index 2dd5d7a..d1603d0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,24 @@ -use uniden::{GetFirmwareVersion, Scanner}; +use uniden::{ + Backlight, BatteryChargeTime, EnterProgramMode, ExitProgramMode, GetBacklight, GetBatteryInfo, + GetFirmwareVersion, GetModelInfo, Scanner, SetBacklight, SetBatteryInfo, +}; #[tokio::main] async fn main() -> Result<(), Box> { let mut scanner = Scanner::open()?; dbg!(&scanner); dbg!(scanner.command(GetFirmwareVersion).await?); + dbg!(scanner.command(GetModelInfo).await?); + dbg!(scanner.command(EnterProgramMode).await?); + dbg!(scanner.command(GetBatteryInfo).await?); + dbg!( + scanner + .command(SetBatteryInfo { + charge_time: BatteryChargeTime::new(16) + }) + .await? + ); + dbg!(scanner.command(GetBatteryInfo).await?); + dbg!(scanner.command(ExitProgramMode).await?); Ok(()) }