diff --git a/mobile/lib/src/application/device/device_selector_cubit.dart b/mobile/lib/src/application/device/device_selector_cubit.dart index 8db63920..7479a403 100644 --- a/mobile/lib/src/application/device/device_selector_cubit.dart +++ b/mobile/lib/src/application/device/device_selector_cubit.dart @@ -36,7 +36,7 @@ class DeviceSelectorCubit extends Cubit { _deviceRepository.connect(device, connectionCallback); } - void connectionCallback(bool connected, Exception e) { + void connectionCallback(bool connected, [Exception e]) { if (e != null) { emit(DeviceConnectionFailure(e)); resetSearch(); diff --git a/mobile/lib/src/domain/acquisition_device/i_acquisition_device_repository.dart b/mobile/lib/src/domain/acquisition_device/i_acquisition_device_repository.dart index 4c6148a7..f0b569e8 100644 --- a/mobile/lib/src/domain/acquisition_device/i_acquisition_device_repository.dart +++ b/mobile/lib/src/domain/acquisition_device/i_acquisition_device_repository.dart @@ -3,7 +3,7 @@ import 'acquisition_device.dart'; abstract class IAcquisitionDeviceRepository { void initializeRepository(); - void connect(AcquisitionDevice device, Function(bool, Exception) callback); + void connect(AcquisitionDevice device, Function(bool, [Exception]) callback); void disconnect(); Future>> startDataStream(); diff --git a/mobile/lib/src/infrastructure/connection_repositories/bluetooth_repository.dart b/mobile/lib/src/infrastructure/connection_repositories/bluetooth_repository.dart index b9a2500e..0ee14865 100644 --- a/mobile/lib/src/infrastructure/connection_repositories/bluetooth_repository.dart +++ b/mobile/lib/src/infrastructure/connection_repositories/bluetooth_repository.dart @@ -21,6 +21,7 @@ class BluetoothRepository implements IAcquisitionDeviceRepository { List _acquisitionDevicePersistency = []; final streamController = StreamController>(); + @override void initializeRepository() { if (_bluetoothScanSubscription == null) { flutterReactiveBle = FlutterReactiveBle(); @@ -48,8 +49,9 @@ class BluetoothRepository implements IAcquisitionDeviceRepository { streamController.add(_acquisitionDevicePersistency); } + @override void connect( - AcquisitionDevice device, Function(bool, Exception) callback) async { + AcquisitionDevice device, Function(bool, [Exception]) callback) async { _selectedDevice = device; _acquisitionDevicePersistency.clear(); _bluetoothScanSubscription.pause(); @@ -61,7 +63,7 @@ class BluetoothRepository implements IAcquisitionDeviceRepository { .listen((event) { if (event.connectionState == DeviceConnectionState.connected) { setupCharacteristics(); - callback(true, null); + callback(true); } else if (event.connectionState == DeviceConnectionState.disconnected) { disconnect(); callback(false, Exception("Failed to connect to device")); @@ -69,6 +71,7 @@ class BluetoothRepository implements IAcquisitionDeviceRepository { }); } + @override void disconnect() async { _selectedDevice = null; _connectedDeviceStream?.cancel(); @@ -86,6 +89,7 @@ class BluetoothRepository implements IAcquisitionDeviceRepository { deviceId: _selectedDevice.id.toString()); } + @override Future>> startDataStream() async { await flutterReactiveBle.requestConnectionPriority( deviceId: _selectedDevice.id.toString(), @@ -97,6 +101,7 @@ class BluetoothRepository implements IAcquisitionDeviceRepository { return flutterReactiveBle.subscribeToCharacteristic(_receiveCharacteristic); } + @override Future stopDataStream() async { await flutterReactiveBle.requestConnectionPriority( deviceId: _selectedDevice.id.toString(), diff --git a/mobile/lib/src/infrastructure/connection_repositories/serial_repository.dart b/mobile/lib/src/infrastructure/connection_repositories/serial_repository.dart index 8715e355..091831d7 100644 --- a/mobile/lib/src/infrastructure/connection_repositories/serial_repository.dart +++ b/mobile/lib/src/infrastructure/connection_repositories/serial_repository.dart @@ -12,8 +12,10 @@ class SerialRepository implements IAcquisitionDeviceRepository { UsbPort _serialPort; List _acquisitionDevicePersistency = []; List _serialDevices = []; + StreamSubscription _inputStreamSubscription; final streamController = StreamController>(); + @override void initializeRepository() { _acquisitionDevicePersistency.clear(); _serialDevices.clear(); @@ -32,6 +34,7 @@ class SerialRepository implements IAcquisitionDeviceRepository { streamController.add(_acquisitionDevicePersistency); } + @override Future connect( AcquisitionDevice device, Function(bool, Exception) callback) async { _selectedDevice = @@ -46,24 +49,57 @@ class SerialRepository implements IAcquisitionDeviceRepository { _serialPort.setPortParameters( 115200, UsbPort.DATABITS_8, UsbPort.STOPBITS_1, UsbPort.PARITY_NONE); - callback(true, null); + _checkCytonConnection(callback); } + Future _checkCytonConnection( + Function(bool, [Exception]) callback) async { + var status = ""; + + _inputStreamSubscription = _serialPort.inputStream.listen((event) { + status += String.fromCharCodes(event); + + if (isFullMessage(status)) { + _inputStreamSubscription.cancel(); + + if (status == CYTON_SYSTEM_UP) + callback(true); + else { + disconnect(); + callback(false, Exception(status)); + } + } + }); + + await _serialPort.write(Uint8List.fromList(CYTON_GET_STATUS)); + } + + bool isFullMessage(String message) { + return message.length > CYTON_MESSAGE_FOOTER.length && + message.substring(message.length - CYTON_MESSAGE_FOOTER.length) == + CYTON_MESSAGE_FOOTER; + } + + @override Future disconnect() async { await _serialPort?.close(); + _inputStreamSubscription?.cancel(); _selectedDevice = null; _serialPort = null; } + @override Future>> startDataStream() async { await _serialPort.write(Uint8List.fromList(START_STREAM_CHAR.codeUnits)); return _serialPort.inputStream; } + @override Future stopDataStream() async { await _serialPort.write(Uint8List.fromList(STOP_STREAM_CHAR.codeUnits)); } + @override Stream> watch() => streamController.stream; } diff --git a/mobile/lib/src/infrastructure/constants.dart b/mobile/lib/src/infrastructure/constants.dart index dd30eddf..73d90293 100644 --- a/mobile/lib/src/infrastructure/constants.dart +++ b/mobile/lib/src/infrastructure/constants.dart @@ -29,6 +29,9 @@ const OPEN_BCI_GANGLION_HEADER = [ ] ]; +const CYTON_MESSAGE_FOOTER = "\$\$\$"; +const CYTON_GET_STATUS = [0xF0, 0x07]; +const CYTON_SYSTEM_UP = "Success: System is Up\$\$\$"; const CYTON_NUMBER_CHANNELS = 8; const CYTON_PACKET_SIZE = 33; const CYTON_NUMBER_COLUMNS = 24;