From 547910b8802036c6095641f611edbd8c7fd64406 Mon Sep 17 00:00:00 2001 From: hayzamjs Date: Mon, 18 Mar 2024 17:13:58 +0530 Subject: [PATCH] first commit --- .gitignore | 22 +++++++++++++ Cargo.toml | 17 ++++++++++ README.md | 51 ++++++++++++++++++++++++++++ src/main.rs | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 185 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f6a1736 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ + +/target +**/*.rs.bk +Cargo.lock +**/*.rs.bk +/.idea +*.swp +*.swo +.vscode/ +*.sublime-workspace +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db +.env +docker-compose.override.yml +*.env +*.env.template +*.env.sample diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9e63e27 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "at-sender" +version = "0.1.0" +edition = "2021" + +[dependencies] +serialport = { version = "4.0", default-features = false } +serde = { version = "1.0", features = ["derive"] } +serde_json = { version = "1.0", features = ["alloc"] } +clap = { version = "3.0", features = ["std"] } + +[profile.release] +opt-level = 'z' +lto = true +codegen-units = 1 +panic = 'abort' +strip = true \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..4004e1a --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# AT Sender + +The `at_sender` program is a simple command-line tool written in Rust, designed to send AT commands to 4G/5G modems on embedded devices. It is intended to be used as a diagnostic tool for testing the modem's AT command interface. + +## Requirements + +- Rust 1.41 or later +- Access to a serial device +- Linux operating system (for the provided build commands) + +## Installation + +Clone the repository and navigate into the project directory: + +```bash +git clone https://git.difuse.io/Difuse/at-sender.git +cd at-sender +``` + +For easy native builds, use the following command: + +```bash +cargo build --release +``` + +Compiling for other targets is also possible, but requires additional setup (You are on your own for this one), here's a great docker container that you can use to build for `aarch64-musl`: + +```bash +docker run --rm -v $(pwd):/home/rust/src messense/rust-musl-cross:aarch64-musl cargo build --release +``` + +## Usage + +``` +./at_sender --port /dev/ttyUSB2 --baud 115200 --data 8 --stop 1 --cmd "AT" --buf 32 +``` + +### Flags + +* `--port`: The serial port to connect to (default "/dev/ttyUSB2") +* `--baud`: The baud rate (default 115200) +* `--data`: The number of data bits (default 8) +* `--stop`: The number of stop bits (default 1) +* `--cmd`: The command to send to the serial device (default "AT") +* `--buf`: The buffer size for reading from the serial device (default 4) + +The flags can be specified in any order. If a flag is omitted, the default value will be used. + +## License + +GPL-3.0 \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..5e55f77 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,95 @@ +use clap::{App, Arg}; +use serde::{Serialize}; +use serialport::{DataBits, FlowControl, Parity, StopBits}; +use std::{io::Write, thread, time::Duration}; +use serde_json; + +#[derive(Serialize)] +struct Result { + data: String, +} + +fn main() { + let matches = App::new("Serial Port Communication with AT commands") + .version("0.1.0") + .author("Hayzam ") + .about("Sends AT commands to a serial device and reads the response.") + .arg(Arg::with_name("port") + .long("port") + .takes_value(true) + .default_value("/dev/ttyUSB2") + .help("The serial port to connect to")) + .arg(Arg::with_name("baud") + .long("baud") + .takes_value(true) + .default_value("115200") + .help("The baud rate")) + .arg(Arg::with_name("data") + .long("data") + .takes_value(true) + .default_value("8") + .help("The number of data bits")) + .arg(Arg::with_name("stop") + .long("stop") + .takes_value(true) + .default_value("1") + .help("The number of stop bits")) + .arg(Arg::with_name("cmd") + .long("cmd") + .takes_value(true) + .default_value("AT") + .help("The command to send to the serial device")) + .arg(Arg::with_name("buf") + .long("buf") + .takes_value(true) + .default_value("4") + .help("The buffer size for reading from the serial device")) + .get_matches(); + + let port_name = matches.value_of("port").unwrap(); + let baud_rate = matches.value_of("baud").unwrap().parse::().expect("Invalid baud rate format"); + + let data_bits = match matches.value_of("data").unwrap() { + "8" => DataBits::Eight, + "7" => DataBits::Seven, + _ => panic!("Unsupported data bits"), + }; + + let stop_bits = match matches.value_of("stop").unwrap() { + "1" => StopBits::One, + "2" => StopBits::Two, + _ => panic!("Unsupported stop bits"), + }; + + let command = matches.value_of("cmd").unwrap(); + + let buf_size: usize = matches.value_of("buf").unwrap_or("4").parse().unwrap_or_else(|err| { + eprintln!("Error parsing buffer size: {}", err); + std::process::exit(1); + }); + + let port = serialport::new(port_name, baud_rate) + .data_bits(data_bits) + .flow_control(FlowControl::None) + .parity(Parity::None) + .stop_bits(stop_bits) + .timeout(Duration::from_secs(1)) + .open() + .expect("Failed to open port"); + + let mut port = Box::new(port); + + port.write_all(command.as_bytes()).expect("Failed to write to port"); + port.write_all(b"\r").expect("Failed to write CR to port"); + + thread::sleep(Duration::from_millis(1000)); + + let mut buf = vec![0u8; buf_size]; + let n = port.read(&mut buf).expect("Failed to read from port"); + let result = Result { + data: String::from_utf8_lossy(&buf[..n]).into_owned(), + }; + + let json_output = serde_json::to_string(&result).expect("Failed to serialize result"); + println!("{}", json_output); +}