diff --git a/Cargo.lock b/Cargo.lock index c6530ef..1704ae2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,6 +28,12 @@ dependencies = [ "syn", ] +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + [[package]] name = "backtrace" version = "0.3.75" @@ -202,9 +208,19 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.173" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8cfeafaffdbc32176b64fb251369d52ea9f0a8fbc6f8759edffef7b525d64bb" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "lock_api" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +dependencies = [ + "autocfg", + "scopeguard", +] [[package]] name = "log" @@ -265,10 +281,12 @@ dependencies = [ name = "modbus_agent" version = "0.1.0" dependencies = [ + "byteorder", "futures", "tokio", "tokio-modbus", "tokio-serial", + "tokio-util", ] [[package]] @@ -303,6 +321,29 @@ dependencies = [ "memchr", ] +[[package]] +name = "parking_lot" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + [[package]] name = "pin-project-lite" version = "0.2.16" @@ -333,6 +374,15 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +dependencies = [ + "bitflags 2.9.1", +] + [[package]] name = "rustc-demangle" version = "0.1.25" @@ -363,6 +413,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +dependencies = [ + "libc", +] + [[package]] name = "slab" version = "0.4.10" @@ -426,7 +485,9 @@ dependencies = [ "bytes", "libc", "mio", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.52.0", diff --git a/Cargo.toml b/Cargo.toml index 807103d..12854ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,5 @@ tokio = { version = "1.45.1", features = ["full"] } tokio-modbus = "0.16.1" tokio-serial = "5.4.1" futures = "0.3.31" +byteorder = "1.5.0" tokio-util = "0.7.15" \ No newline at end of file diff --git a/src/codec.rs b/src/codec.rs new file mode 100644 index 0000000..499a092 --- /dev/null +++ b/src/codec.rs @@ -0,0 +1,32 @@ +use std::io::{Cursor, Read}; +use byteorder::{BigEndian, ReadBytesExt}; + +#[derive(Debug)] +pub(crate) struct SerialConfig { + pub port: Vec, // Port/binary(变长二进制数据) + pub baudrate: u32, // Baudrate:32 + pub stopbits: u8, // Stopbits:8 + pub parity: u8, // Parity:8 + pub timeout: u32, // Timeout:32 +} + +pub(crate) fn parse_serial_config(data: &[u8]) -> std::io::Result { + let mut cursor = Cursor::new(data); + + let port_len = cursor.read_u8()?; + let mut port = vec![0u8; port_len as usize]; + cursor.read_exact(&mut port)?; + + let baudrate = cursor.read_u32::()?; + let stopbits = cursor.read_u8()?; + let parity = cursor.read_u8()?; + let timeout = cursor.read_u32::()?; + + Ok(SerialConfig { + port, + baudrate, + stopbits, + parity, + timeout, + }) +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 7a1b1fb..0ca2c88 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,43 +1,94 @@ +mod codec; + use tokio::net::{UnixListener, UnixStream}; //use tokio_util::codec::{Framed, LinesCodec}; use futures::SinkExt; use tokio::io::AsyncReadExt; //use tokio::io::AsyncReadExt; -const SOCKET_PATH: &str = "/tmp/modbus.sock"; +use std::io::{self, Read, Write}; +use std::process; + #[tokio::main] -async fn main() -> Result<(), Box> { - // 绑定Unix Domain Socket - let listener = UnixListener::bind(SOCKET_PATH)?; - println!("Server listening on {}", SOCKET_PATH); +async fn main() { + let stdin = io::stdin(); + let mut stdin = stdin.lock(); + let mut stdout = io::stdout(); + + let d = vec![ + 0x05, // port_len: 5 + b'C', b'O', b'M', b'1', 0x00, // Port: "COM1" + null终止符(假设) + 0x00, 0x00, 0x25, 0x80, // baudrate: 9600 (大端) + 0x01, // stopbits: 1 + 0x00, // parity: 0 + 0x00, 0x00, 0x03, 0xE8, // timeout: 1000 (大端) + ]; + + let c = codec::parse_serial_config(&d).unwrap(); + println!("{:?}", c); + + let s = String::from_utf8(c.port.clone()).unwrap(); + println!("port: {}", s); + + println!("port: {:?}", c.port); + loop { - // 接受新连接 - let (stream, _addr) = listener.accept().await?; - println!("New client connected"); + // 1. 读取4字节长度前缀 (big-endian) + let mut len_bytes = [0u8; 2]; + if stdin.read_exact(&mut len_bytes).is_err() { + // 读取失败或EOF退出 + process::exit(-1); + } - // 为每个连接创建异步任务 - tokio::spawn(async move { - handle_client(stream).await.unwrap_or_else(|e| { - eprintln!("Client error: {}", e); - }); - }); + let length = u16::from_be_bytes(len_bytes) as usize; + // 2. 读取实际数据 + let mut data = vec![0u8; length]; + if stdin.read_exact(&mut data).is_err() { + process::exit(-1); + } + + match data[0] { + 0x01 => { + let config = codec::parse_serial_config(&data[1..]).unwrap(); + println!("{:?}", config) + }, + _ => { + + } + } + + + // let data_str = String::from_utf8(data).unwrap_or_else(|_| { + // eprintln!("Invalid UTF-8 data"); + // process::exit(-1); + // }); + // + // // 3. 处理数据并生成响应 + // let response = format!("Processed: {}", data_str); + // let response_bytes = response.as_bytes(); + // + // // 4. 写入响应(长度前缀 + 数据) + // stdout.write_all(&(response_bytes.len() as u32).to_be_bytes())?; + // stdout.write_all(response_bytes)?; + // stdout.flush()?; // 确保立即发送 } } async fn handle_client(mut stream: UnixStream) -> Result<(), Box> { - let len = stream.read_u16().await.unwrap(); - let mut buf = vec![0u8; len as usize]; + loop { + let len = stream.read_u16().await.unwrap(); + let mut buf = vec![0u8; len as usize]; - match stream.read_exact(&mut buf).await { - Ok(_) => { - - }, - Err(err) => { - println!("read data get error: {}", err) + match stream.read_exact(&mut buf).await { + Ok(bytes) => { + let str = String::from_utf8(buf).unwrap(); + println!("read bytes: {}", str) + }, + Err(err) => { + println!("read data get error: {}", err) + } } } - - Ok(()) } \ No newline at end of file