Enhance USB port opening and reading logic with improved error handling and debug logging

This commit is contained in:
zjs81
2026-03-07 12:55:15 -07:00
parent fef73b7b62
commit 421bc71bb7
+33 -4
View File
@@ -268,9 +268,23 @@ class UsbSerialService {
return null; return null;
} }
Future<void> _openPort(JSObject port, int baudRate) { Future<void> _openPort(JSObject port, int baudRate) async {
final options = JSObject()..['baudRate'] = baudRate.toJS; final options = JSObject()
return port.callMethod<JSPromise<JSAny?>>('open'.toJS, options).toDart; ..['baudRate'] = baudRate.toJS
..['flowControl'] = 'none'.toJS;
await port.callMethod<JSPromise<JSAny?>>('open'.toJS, options).toDart;
// Prevent ESP32 USB-CDC reset: hold DTR=true, RTS=false after open.
try {
final signals = JSObject()
..['dataTerminalReady'] = true.toJS
..['requestToSend'] = false.toJS;
await port
.callMethod<JSPromise<JSAny?>>('setSignals'.toJS, signals)
.toDart;
} catch (_) {
// setSignals may not be supported on all browsers/devices.
}
} }
Future<void> _cleanupFailedConnect() async { Future<void> _cleanupFailedConnect() async {
@@ -324,8 +338,12 @@ class UsbSerialService {
Future<void> _pumpReads() async { Future<void> _pumpReads() async {
final reader = _reader; final reader = _reader;
if (reader == null) return; if (reader == null) {
_debugLogService?.warn('_pumpReads: reader is null', tag: 'USB Serial');
return;
}
_debugLogService?.info('_pumpReads: started', tag: 'USB Serial');
try { try {
while (_status == UsbSerialStatus.connected && while (_status == UsbSerialStatus.connected &&
identical(reader, _reader)) { identical(reader, _reader)) {
@@ -333,6 +351,7 @@ class UsbSerialService {
.callMethod<JSPromise<JSAny?>>('read'.toJS) .callMethod<JSPromise<JSAny?>>('read'.toJS)
.toDart; .toDart;
if (result == null) { if (result == null) {
_debugLogService?.warn('_pumpReads: null result', tag: 'USB Serial');
break; break;
} }
final resultObject = result as JSObject; final resultObject = result as JSObject;
@@ -340,20 +359,30 @@ class UsbSerialService {
final doneValue = resultObject.getProperty<JSAny?>('done'.toJS); final doneValue = resultObject.getProperty<JSAny?>('done'.toJS);
final done = doneValue != null && doneValue.dartify() == true; final done = doneValue != null && doneValue.dartify() == true;
if (done) { if (done) {
_debugLogService?.info('_pumpReads: done=true', tag: 'USB Serial');
break; break;
} }
final value = resultObject.getProperty<JSAny?>('value'.toJS); final value = resultObject.getProperty<JSAny?>('value'.toJS);
final bytes = _coerceBytes(value); final bytes = _coerceBytes(value);
if (bytes != null && bytes.isNotEmpty) { if (bytes != null && bytes.isNotEmpty) {
_debugLogService?.info(
'USB RX raw: ${bytes.length} byte(s)',
tag: 'USB Serial',
);
_ingestRawBytes(bytes); _ingestRawBytes(bytes);
} }
} }
} catch (error, stackTrace) { } catch (error, stackTrace) {
_debugLogService?.error(
'_pumpReads error: $error',
tag: 'USB Serial',
);
if (_status == UsbSerialStatus.connected) { if (_status == UsbSerialStatus.connected) {
_addFrameError(error, stackTrace); _addFrameError(error, stackTrace);
} }
} finally { } finally {
_debugLogService?.info('_pumpReads: ended', tag: 'USB Serial');
_releaseLock(reader); _releaseLock(reader);
if (_status == UsbSerialStatus.connected && identical(reader, _reader)) { if (_status == UsbSerialStatus.connected && identical(reader, _reader)) {
_addFrameError(StateError('USB serial connection closed')); _addFrameError(StateError('USB serial connection closed'));