mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-07-25 21:16:40 +10:00
fix: auto-add flag parsing, contact cache restore, and USB reconnect
- Fix operator precedence bug in _handleAutoAddConfig where `flags & flag != 0` was parsed as `flags & (flag != 0)`, always checking bit 0 instead of the correct flag bit - Populate _contacts from cache in loadContactCache() so contacts persist across app restarts - Toggle DTR low→high on USB connect to force device to see a fresh connection - Add 10ms inter-frame delay for USB sends to prevent missed responses - Deassert DTR before closing USB port on disconnect/dispose Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -708,6 +708,9 @@ class MeshCoreConnector extends ChangeNotifier {
|
|||||||
_knownContactKeys
|
_knownContactKeys
|
||||||
..clear()
|
..clear()
|
||||||
..addAll(cached.map((c) => c.publicKeyHex));
|
..addAll(cached.map((c) => c.publicKeyHex));
|
||||||
|
_contacts
|
||||||
|
..clear()
|
||||||
|
..addAll(cached);
|
||||||
for (final contact in cached) {
|
for (final contact in cached) {
|
||||||
_ensureContactSmazSettingLoaded(contact.publicKeyHex);
|
_ensureContactSmazSettingLoaded(contact.publicKeyHex);
|
||||||
}
|
}
|
||||||
@@ -1540,6 +1543,10 @@ class MeshCoreConnector extends ChangeNotifier {
|
|||||||
|
|
||||||
if (_activeTransport == MeshCoreTransportType.usb) {
|
if (_activeTransport == MeshCoreTransportType.usb) {
|
||||||
await _usbManager.write(data);
|
await _usbManager.write(data);
|
||||||
|
// Brief pause so the device firmware can process each frame before the
|
||||||
|
// next arrives. Without this, rapid-fire frames over USB can cause the
|
||||||
|
// device to miss responses (especially on reconnect).
|
||||||
|
await Future<void>.delayed(const Duration(milliseconds: 10));
|
||||||
} else if (_activeTransport == MeshCoreTransportType.tcp) {
|
} else if (_activeTransport == MeshCoreTransportType.tcp) {
|
||||||
await _tcpConnector.write(data);
|
await _tcpConnector.write(data);
|
||||||
} else {
|
} else {
|
||||||
@@ -4837,11 +4844,11 @@ class MeshCoreConnector extends ChangeNotifier {
|
|||||||
try {
|
try {
|
||||||
reader.skipBytes(1); // Skip the response code byte
|
reader.skipBytes(1); // Skip the response code byte
|
||||||
final flags = reader.readByte();
|
final flags = reader.readByte();
|
||||||
_autoAddUsers = flags & autoAddChatFlag != 0;
|
_autoAddUsers = (flags & autoAddChatFlag) != 0;
|
||||||
_autoAddRepeaters = flags & autoAddRepeaterFlag != 0;
|
_autoAddRepeaters = (flags & autoAddRepeaterFlag) != 0;
|
||||||
_autoAddRoomServers = flags & autoAddRoomServerFlag != 0;
|
_autoAddRoomServers = (flags & autoAddRoomServerFlag) != 0;
|
||||||
_autoAddSensors = flags & autoAddSensorFlag != 0;
|
_autoAddSensors = (flags & autoAddSensorFlag) != 0;
|
||||||
_overwriteOldest = flags & autoAddOverwriteOldestFlag != 0;
|
_overwriteOldest = (flags & autoAddOverwriteOldestFlag) != 0;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
appLogger.error('Failed to parse auto-add config: $e', tag: 'Connector');
|
appLogger.error('Failed to parse auto-add config: $e', tag: 'Connector');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ class MeshCoreUsbManager {
|
|||||||
|
|
||||||
Future<void> write(Uint8List data) => _service.write(data);
|
Future<void> write(Uint8List data) => _service.write(data);
|
||||||
|
|
||||||
|
Future<void> writeRaw(Uint8List data) => _service.writeRaw(data);
|
||||||
|
|
||||||
// --- Label management ---
|
// --- Label management ---
|
||||||
void updateConnectedLabel(String selfName) {
|
void updateConnectedLabel(String selfName) {
|
||||||
_service.updateConnectedLabel(selfName);
|
_service.updateConnectedLabel(selfName);
|
||||||
|
|||||||
@@ -189,6 +189,10 @@ class UsbSerialService {
|
|||||||
serial.setStopBits1();
|
serial.setStopBits1();
|
||||||
serial.setFlowControlNone();
|
serial.setFlowControlNone();
|
||||||
serial.setRTS(false);
|
serial.setRTS(false);
|
||||||
|
// Toggle DTR low→high so the device sees a fresh connection even
|
||||||
|
// if the previous disconnect didn't cleanly signal DTR drop.
|
||||||
|
serial.setDTR(false);
|
||||||
|
await Future<void>.delayed(const Duration(milliseconds: 50));
|
||||||
serial.setDTR(true);
|
serial.setDTR(true);
|
||||||
_serial = serial;
|
_serial = serial;
|
||||||
// Update the normalized port name to whichever candidate succeeded.
|
// Update the normalized port name to whichever candidate succeeded.
|
||||||
@@ -249,6 +253,23 @@ class UsbSerialService {
|
|||||||
_status = UsbSerialStatus.connected;
|
_status = UsbSerialStatus.connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> writeRaw(Uint8List data) async {
|
||||||
|
if (!isConnected) {
|
||||||
|
throw StateError('USB serial port is not open');
|
||||||
|
}
|
||||||
|
if (_useAndroidUsbHost) {
|
||||||
|
try {
|
||||||
|
await _androidMethodChannel.invokeMethod<void>('write', {
|
||||||
|
'data': data,
|
||||||
|
});
|
||||||
|
} on PlatformException catch (error) {
|
||||||
|
throw StateError(error.message ?? error.code);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_serial!.write(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> write(Uint8List data) async {
|
Future<void> write(Uint8List data) async {
|
||||||
if (!isConnected) {
|
if (!isConnected) {
|
||||||
throw StateError('USB serial port is not open');
|
throw StateError('USB serial port is not open');
|
||||||
@@ -300,6 +321,7 @@ class UsbSerialService {
|
|||||||
_serial = null;
|
_serial = null;
|
||||||
try {
|
try {
|
||||||
if (serial?.isOpen() == FlOpenStatus.open) {
|
if (serial?.isOpen() == FlOpenStatus.open) {
|
||||||
|
serial?.setDTR(false);
|
||||||
serial?.closePort();
|
serial?.closePort();
|
||||||
}
|
}
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
@@ -350,6 +372,7 @@ class UsbSerialService {
|
|||||||
final serial = _serial;
|
final serial = _serial;
|
||||||
try {
|
try {
|
||||||
if (serial?.isOpen() == FlOpenStatus.open) {
|
if (serial?.isOpen() == FlOpenStatus.open) {
|
||||||
|
serial?.setDTR(false);
|
||||||
serial?.closePort(); // synchronous C call — kills the SerialThread
|
serial?.closePort(); // synchronous C call — kills the SerialThread
|
||||||
}
|
}
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
|||||||
@@ -127,6 +127,17 @@ class UsbSerialService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> writeRaw(Uint8List data) async {
|
||||||
|
if (!isConnected || _writer == null) {
|
||||||
|
throw StateError('USB serial port is not open');
|
||||||
|
}
|
||||||
|
final promise = _writer!.callMethod<JSPromise<JSAny?>>(
|
||||||
|
'write'.toJS,
|
||||||
|
data.toJS,
|
||||||
|
);
|
||||||
|
await promise.toDart;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> write(Uint8List data) async {
|
Future<void> write(Uint8List data) async {
|
||||||
if (!isConnected || _writer == null) {
|
if (!isConnected || _writer == null) {
|
||||||
throw StateError('USB serial port is not open');
|
throw StateError('USB serial port is not open');
|
||||||
|
|||||||
Reference in New Issue
Block a user