Open mihai-dinculescu opened 2 years ago
Can you run it through strace -f
and post the result? Not really sure what's failing there. I suspect something Windows-specific, but I don't have the ability to test on Windows.
I couldn't get strace
to work, but I have attached the export of Process Monitor.
From the little I understand about all this, The device does not recognize the command.
is actually an expected error, on Windows.
When the ESP32 S3 device goes into deep sleep the USB port gets disconnected, the serial connection is closed, and that error is produced. From the logs above you can see that idf.py
receives the very same error, but it handles it gracefully by attempting to reconnect until the device wakes up.
I suspect that espmonitor could benefit from the same reconnect functionality?
Another issue that I've discovered is that the data that was produced close to the port getting disconnected is not getting handled. This must be because dev.read
returns Uncategorized
, a fatal error, instead of a non-fatal one like Interrupted
. I suspect that espmonitor crashes with data left in the buffer.
This is the code I've had to change in order to get the same behavior as idf.py monitor
.
The only way I've been able to make sure to get all the data before disconnection was to change the buffer size to 1, which obviously is far from ideal...
Please let me know if you're open to exploring this avenue. I can put a PR up.
let mut buf = [0u8; 1];
// reconnect = -1 => connected
// reconnect = 0 => something went wrong, trying to reconnect for the first time
// reconnect > 0 => multiple reconnects attempted so far
let mut reconnect = -1;
loop {
if reconnect >= 0 {
if reconnect == 0 {
print!("Waiting for the device to reconnect");
std::io::stdout().flush()?;
}
let dev_new = || -> Result<_, Box<dyn std::error::Error>> {
let mut dev_new = serial::open(&args.serial)?;
dev_new.set_timeout(Duration::from_secs(60))?;
dev_new.reconfigure(&|settings| settings.set_baud_rate(speed))?;
Ok(dev_new)
}();
if let Ok(dev_new) = dev_new {
dev = dev_new;
reconnect = -1;
} else {
print!(".");
std::io::stdout().flush()?;
std::thread::sleep(Duration::from_secs(1));
}
}
match dev.read(&mut buf) {
Ok(bytes) if bytes > 0 => {
handle_serial(&mut serial_state, &buf[0..bytes], &mut output)?
}
Ok(_) => {
if dev.read_dsr().is_err() {
rprintln!("Device disconnected; exiting");
break Ok(());
}
}
Err(err) if err.kind() == ErrorKind::TimedOut => (),
Err(err) if err.kind() == ErrorKind::WouldBlock => (),
Err(err) if err.kind() == ErrorKind::Interrupted => (),
Err(_) => {
reconnect += 1;
()
}
}
So I'm kinda torn on this. On one hand I do kinda like espmonitor to automatically quit if I disconnect the device. But I can see how it could be useful to wait and auto-reconnect.
The only way I've been able to make sure to get all the data before disconnection was to change the buffer size to 1, which obviously is far from ideal...
Hmm, that's strange; I would think that if the read()
is able to give at least one byte, it would return that data, and then the next read would throw the error.
I've been happily using espmonitor with several ESP32s, but with a FeatherS3 from UM, it crashes when winding down.
idf.py monitor
behaves as expectedOS: MINGW64 on Windows 11