I'm pretty new to Rust and I thought I gonna start with some things I once coded in other languages. To get started I chose a small program. I just want to connect to a UART device write and read to it, but I cannot get it to work. I use https://crates.io/crates/serialport library. This is my code:
use std::time::Duration;
use std::io::Write;
fn main() {
let mut port = serialport::new("/dev/ttys002", 115_200).open_native().expect("Failed to open port").expect("Failed to open.");
let output = "This is a test. This is only a test.".as_bytes();
port.write(output).expect("Write failed!");
}
I mean it is a simple example but I keep getting the following error:
thread 'main' panicked at 'Failed to open port: Error { kind: Unknown, description: "Not a typewriter" }', src/main.rs:5:75
That's definitely a solid idea. Apple have been doing some pretty funny business around revoking permissions of files located in system directories. I wouldn't be surprised if Big Sur was programmed to silently deny TTY connections with a misleading error message to everything except their own apps.
I am on Big Sur myself, so I'll try to reproduce the error on my own machine.
Ah, okay. You should definitely have either homebrew Rust or rustup Rust on your machine, not both. I recommend rustup, which will always have the latest releases; there might be (and from what you've said it sounds like there is) a significant lag in homebrew's packaging.
I see, This idea came to my mind after I saw your post. I tried it via brew upgrade rust and got this:
Error: homebrew-cask is a shallow clone. To `brew update` first run:
git -C "/usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask" fetch --unshallow
This restriction has been made on GitHub's request because updating shallow
clones is an extremely expensive operation due to the tree layout and traffic of
Homebrew/homebrew-cask. We don't do this for you automatically to avoid
repeatedly performing an expensive unshallow operation in CI systems (which
should instead be fixed to not use shallow clones). Sorry for the inconvenience!
Warning: rust 1.47.0 already installed
Ok, I uninstall the homebrerw version and reinstall
Can you write to the device using other programms, e.g. cat? If that does not work, the problem is probably not in your rust code.
(cat "This is a test. This is only a test." > /dev/ttys002)
It took a while but it seems serialport does not work with virtual ports. I finally have access to the LoRa module and now I can write and receive data. Which brings me to my next question.
I send an AT command and the expected value should be AT, OK. What I get is 1. I mean that's the right value for Vec<u8> and usize as return value of the read() function.
let mut serial_buf: Vec<u8> = vec![0; 32]; let message = port.read(serial_buf.as_mut_slice()).expect("Found no data!"); println!("{}", message);
What do you mean by "converting to UTF-8"? Either what you have is already UTF-8, in which case you can convert it to a string or an &str using one of the suitable functions (str::from_utf8(), String::from_utf8()), or what you have is not yet UTF-8, in which case you have to consider what the encoding format and the semantics of the data read into the buffer is, then possibly output a string based on its contents.
Do you mean that serial_buf is supposed to contain the string AT, OK? If so, then 1 is not the right return value, because read() returns the number of bytes read, and the string AT, OK is definitely not 1 byte long. This might happen for a number of reasons:
Maybe the serial port just couldn't provide more bytes at a time. Unlikely, but possible. In this case, you should probably be using read_to_end() instead of plain read(). There's no guarantee that read() can or will read all available data at once.
Or perhaps what you get back isn't a literal string, only a single-byte status code that means "OK". In this case, you should read up on the relevant documentation to be able to convert this status code to a human-readable message, if that's what you need.