Closed josejachuf closed 2 years ago
Hey! Thanks for the suggestion.
You can already do this today using the standard library. To be specific, you can wrap the serial port in a std::io::BufReader
. Then you can use std::io::BufRead::read_until()
to read into a vector until a certain byte is found.
Would this fit your use case?
Hello @de-vri-es , thanks for the answer. Sorry I am very new in Rust, I do not realize how to use what you suggest.
Jose
No problem! You can use it something like this:
use std::io::BufRead;
let port = serial2::SerialPort::open("/dev/ttyUSB0", 57600)?;
let mut port = std::io::BufReader::new(port);
let mut buffer = Vec::with_capacity(128);
// Keep reading until the read returns Ok(0), which indicates the stream is closed.
while port.read_until(b'\n', &mut buffer)? != 0 {
process_message(&buffer);
buffer.clear();
}
In that example, the question mark is used to return errors to the calling function. You can check out the Rust book if you're not familiar with it yet.
Thanks, I'm going to check it tonight. A more query, to port I use it to read as to write, I understand that in this way I can not write in the port
Something like that would work? Creating 2 instances of the Port one to read and another to write. I do not know if it is blocked when it opens. At night I try
use std::io::BufRead;
let port = serial2::SerialPort::open("/dev/ttyUSB0", 57600)?;
let mut port_r = std::io::BufReader::new(port);
let mut buffer = Vec::with_capacity(128);
// Keep reading until the read returns Ok(0), which indicates the stream is closed.
while port_r.read_until(b'\n', &mut buffer)? != 0 {
process_message(&buffer);
buffer.clear();
}
Jose
You can still access the underlying serial port through the BufReader object with the get_mut()
method:
use std::io::{BufRead, Write};
let port = serial2::SerialPort::open("/dev/ttyUSB0", 57600)?;
let mut port = std::io::BufReader::new(port);
let mut buffer = Vec::with_capacity(128);
// Keep reading until the read returns Ok(0), which indicates the stream is closed.
while port.read_until(b'\n', &mut buffer)? != 0 {
process_message(&buffer);
port.get_mut().write_all(b"OK\n")?; // Use `get_mut()` to write to the port.
buffer.clear();
}
However, you should do all reads through the BufReader. Otherwise you may miss bytes that have already been read into the buffer of the BufReader.
Thanks. I will see in these days.
Hi @de-vri-es , I get an error when it starts, before sending any data to the port
'main' panicked at 'called
Result::unwrap()
on anErr
value: Kind(TimedOut)',
[For now I'm not controlling the errors ]
use std::io::{BufRead, BufReader, Write};
use serial2::SerialPort;
fn process_message(buffer_str: &str) {
print!("{:?}", buffer_str );
}
fn main() {
let port = SerialPort::open("/dev/cuaU0", 9600).unwrap();
let mut port = BufReader::new(port);
let mut buffer = Vec::with_capacity(128);
loop {
while port.read_until(b'\n', &mut buffer).unwrap() != 0 {
let buffer_str = std::str::from_utf8(&buffer[..10]).unwrap();
process_message(&buffer_str);
port.get_mut().write_all(b"v\n").unwrap(); // Use `get_mut()` to write to the port.
buffer.clear();
}
}
}
@de-vri-es For now I resolved, keeping the readings until the message is completed. But I want to do later to what you suggest
You could also increase the timeout of the serial port with the set_read_timeout()
function.
Ok. I will try this. Thanks very much
I will try to describe in the best way what happens
I have an app that reads the data sent via wireless to a USB device connected to the computer
To read the data entry into the device continuously I have a loop similar to the example
It is stipulated that "data" have a certain structure (field separator). Once obtained, the fields were separated and actions are made. For example:
My customer had given me a USB device and everything worked very well.
A few days ago my customer changed the USB device hardware and the readings began to have faults The previous example now looked like this
In this example there were 3 different readings and obviously do not respect the protocol of how the data should come
I made a change in the code by adding a sleep of 1000 ms
Now the readings behaved as I expected, but I started noting that some data sent to the device were not read, they were lost, I understand why at that time the sleep was happening
I changed the sleep to 300, 500 and now 800, it seems that with 800 I read the data and I do not lose readings, but I do not have any certainty.
There is some way that if you are entering the data wait for you to finish arriving. For example, in PySerial there is read_until [1]
[1] https://pyserial.readthedocs.io/en/latest/pyserial_api.html#serial.Serial.read_until