-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Works on Windows? #7
Comments
I did test it, it should work. Although someone did report an isue with a particular serial device on windows recently. |
Yeah, I read it. It was about a Windows serial port to USB adapter, in theory that should be handled by the drivers, ¿right? About the issue, thx for answering. I'll take a look on it tomorrow, and I will tell you. Thx again |
Hey, I already tested it. I run into some problems. This is the code: fn check_if_active(&mut self) -> bool {
let write_buffer: &[u8] = &[255, 255, 255, 255];
let mut read_buffer = vec![0; 16];
println!("Generic write in {} port", self.name());
self.port
.write_all(write_buffer)
.expect(stringify!("Write in port {} failed: ", self.name()));
println!("After generic write in {} port", self.name());
thread::sleep(Duration::from_millis(75));
println!("Generic read in {} port", self.name());
let read = self.port
.read(&mut read_buffer);
println!("After generic read in {} port", self.name());
match read {
Ok(n) => {
green!("There wasn't an error");
if is_zero(&read_buffer) {
red_ln!("Didn't read anything");
prnt!();
return false;
} else {
green_ln!("Read data. Something connected");
prnt!();
return true;
}
},
Err(e) => {
red_ln!("ERROR in check if active");
prnt!();
println!("Something went wrong while reading in the port {}: {}", self.name(), e);
},
}
println!("Buffer: {:?}", read_buffer);
false
} (Sorry if there is to much boilerplate in the code, I used that for debugging) PRs (both waiting for approval):
I don't know if you can solve this, because they mantainers said they will look it on june, and I need this to be finished by June 7, and I don't know if it will be ready by that time |
Have you tried That should give a timeout error when the read fails due to the timeout. It will not report a zero-sized read, because that indicates that the stream closed on Unix platforms. |
Ok, I will try it and I tell you. |
I tested it with the timeouts of 100milis and it gave me a timeout error, in every single read for every single device. I know it's not about the timeout, because if it were for that without timeout it should have worked. I know (I remembered this now, sorry) that it is not the device connected, the cable, Windows, the PC or the port, because I tried with a piece of software which came with one of the devices and was able to connect to it without much trouble |
Interesting, thanks for testing. Can you tell me what serial device you are using? Maybe I can debug things myself too. |
Ok, the Port driver is the Windows one. And the device is an industrial IoT one, it's called an let write_buffer: &[u8] = "$FFID0000".as_bytes(); |
I tested this PR #94 of the serialport-rs library and it fixed my problem, it no longer timesout. Here's the link to the fork with the code if it helps you solve this problem LukaOber/serialport-rs |
Thanks for the extra information. It appears that the problem you are experiencing is due to hardware flow control. By default, no hardware flow control options are modified by this library. You can enable or disable hardware flow control with I'm not sure if this will cover your needs, because hardware flow control is hard to find proper documentation for. Do you know if your converter and/or device use a type of hardware flow control? |
Note that you could also bypass normal hardware flow control (just keep it disabled or explicitly disable it) and then manually set the https://docs.rs/serial2/latest/serial2/struct.SerialPort.html#method.set_dtr |
The device I use only need TX, RX and GND, even the cable doesn't use it. So, is Hardware control flow enabled by default? I think I disabled it. I can't look into it right now, because I'm not at work until Monday but I will keep you updated. |
Hmm, strange. Then I really don't see why the PR you linked fixes your use case. Unless for some weird reason hardware flow control is enabled by default. That would be weird though. But you should be able to replicate what that PR did by disabling flow control and setting the RTS and DTR lines manually. So even though it seems odd, what I would test is: let mut serial = SerialPort::open(device_path, baud_rate)?;
serial.set_dtr(true)?;
serial.set_rts(true)?; If that works, I would also try with only one of DTR and RTS enabled, just to figure out which one(s) are really needed. If that doesn't work, the problem seems to be elsewhere. But this behaviour may be a weird quirk of the windows driver. Who knows.. |
It may also have be caused by the |
I mean it is a really weird thing, because I use the code for that PR and the read no longer timesout, but it doesn't read from the buffer. Port settings:
With these it should work, but it doesn't fill the buffer. I don't know (with the PR) if now it's my fault, because the command I send through the line doesn't work. |
I'll try my best to help :) I also want to fix any potential issues in the library.
Did you try this? Also, please make sure to update to |
Ok, so I did that. use serial2::*;
use std::thread;
use std::time::Duration;
fn main() -> Result<(), std::io::Error> {
println!("Open port");
let mut serial = SerialPort::open("COM1", 9600)?;
println!("Extract Settings");
let mut settings = serial.get_configuration()?;
settings.set_raw();
println!("Set settings");
serial.set_configuration(&settings)?;
println!("Setting timeouts");
serial.set_read_timeout(Duration::from_millis(100))?;
serial.set_write_timeout(Duration::from_millis(100))?;
println!("SET DTR and RTS");
serial.set_dtr(true)?;
serial.set_rts(true)?;
println!("Writing");
serial.write("$FFID0000".as_bytes())?;
println!("Flushing the buffer");
serial.flush()?;
thread::sleep(Duration::from_millis(100));
let mut vector = Vec::new();
println!("Reading from the buffer");
serial.read(&mut vector)?;
println!("{:?}", vector);
Ok(())
} and I get this output:
It gives me a Timeout, again. I don't know what could be the problem. |
Hmm, for now you have me stumped too. I will need to find a way to reproduce this for myself if I want to say anything sensible.
The flush function waits for the data written with |
Ok, if it serves you I'm using a custom made PC (provided by the company) with Windows 10 IoT 2021 (A trimmed version of Windows that cuts bloatware only sold to companies for the PCs they use in their products). |
I remebered something now. Every library I tried, had this issue (read timeout or if not, not reading anything), don't know why. So maybe it's not your fault. Maybe it's because the winapi is broken. List of libraries I tried: Worth mentioning (I guess), that none of them are async, because as async in Rust isn't very well polished yet, I thought it wasn't a good idea (don't know if I was being a fool here) |
Windows has really weird IO Port behavior that have unexpected behavior in the common case. You can make some settings cheanges to the config so serial ports on windows work more like Posix One thing would be look at how PySerial ( which is pretty robust ) does it. Here is previous discussion on a windows fix https://gitlab.com/susurrus/serialport-rs/-/merge_requests/78 Info on commtimeouts https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-commtimeouts It seems page has settings that will give you posix like settings: https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-commtimeouts#remarks If an application sets ReadIntervalTimeout and ReadTotalTimeoutMultiplier to MAXDWORD and sets ReadTotalTimeoutConstant to a value greater than zero and less than MAXDWORD, one of the following occurs when the ReadFile function is called:
|
the normal developer experience which is mostly POSIX-style these days See ticket de-vri-es#7 for discussion
It would be very cool if serial on Windows could work since currently none of the serial crates work on Windows (I did not try the async ones since I don't need it). I posted in serialport/serialport-rs#94 and how that PR does not fix my issue. |
Yeah, agreed. What would really help me is something simple to reproduce though. A not-too-expensive serial converter I can buy that exhibits the problem so I can test it. With the hardware I have at home, this crate works on Windows. |
I did just release You may also need to set the DTR and RTS signals after opening the port, depending on the device you are talking too, and maybe even depending on the Windows driver for your serial port. |
The board I am talking to does not require hardware flow control, but I can try playing with those settings next week as I am leaving work right now. |
Ah, I see one problem with your code: If you want to read one line of input, you can wrap the Or it looks like maybe you just want to read exactly one byte? Then you can just call: let mut response = [0u8; 1];
port.read(&mut response)?; |
I modified the constants because it is a proprietary serial protocol, so it is reading more than one byte. But regardless you are correct. I changed it to port.write_all(GET_STATUS).expect("Write failed!");
let mut response = [0; STATUS_NOMINAL.len()];
port.read_exact(&mut response).unwrap();
assert_eq!(response, STATUS_NOMINAL); I am used to Python serial where you just called "port.readline()" and it will read until a timeout is raised. Which may be a useful API for testing, as it is sort of dual to just the normal Below is the Python I have used in the past. port.write(to_send)
out_str = port.readline()
assert out_str == compare |
I believe Windows compatibility is properly fixed now, so I'm closing this issue. This one is a bit long, so if there are still problems on Windows, let's open a new issue. |
…ponse changed functions to return a response struct,
I need to make sure this library works on Windows, because I tried using serialport-rs and I always get a "Operation timed out" error when I try to read fro mthe buffer. They have a working PR in wait to be merged but I don't know how much it will take and I need to finish the project in less than two weeks, so I need to make sure this works before considering to use it. Have you tested it in Windows? Thanks in advance :)
The text was updated successfully, but these errors were encountered: