diff --git a/.github/workflows/mobile.yml b/.github/workflows/mobile.yml index 85ea82e8..8ff28dc1 100644 --- a/.github/workflows/mobile.yml +++ b/.github/workflows/mobile.yml @@ -24,6 +24,8 @@ jobs: - run: flutter pub get + - run: flutter analyze + - run: flutter test - run: flutter build apk diff --git a/mobile/analysis_options.yaml b/mobile/analysis_options.yaml new file mode 100644 index 00000000..fba11c7b --- /dev/null +++ b/mobile/analysis_options.yaml @@ -0,0 +1,9 @@ +include: package:pedantic/analysis_options.yaml + +analyzer: + exclude: + - lib/protos + +linter: + rules: + avoid_shadowing_type_parameters: false diff --git a/mobile/ios/Flutter/AppFrameworkInfo.plist b/mobile/ios/Flutter/AppFrameworkInfo.plist index beffb28c..4f8d4d24 100644 --- a/mobile/ios/Flutter/AppFrameworkInfo.plist +++ b/mobile/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 10.0 + 11.0 diff --git a/mobile/ios/Runner.xcodeproj/project.pbxproj b/mobile/ios/Runner.xcodeproj/project.pbxproj index a81b9d8b..b6768355 100644 --- a/mobile/ios/Runner.xcodeproj/project.pbxproj +++ b/mobile/ios/Runner.xcodeproj/project.pbxproj @@ -272,7 +272,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -354,7 +354,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -403,7 +403,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/mobile/lib/src/application/device/device_selector_cubit.dart b/mobile/lib/src/application/device/device_selector_cubit.dart index 7479a403..659a0006 100644 --- a/mobile/lib/src/application/device/device_selector_cubit.dart +++ b/mobile/lib/src/application/device/device_selector_cubit.dart @@ -5,6 +5,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:polydodo/src/domain/acquisition_device/acquisition_device.dart'; import 'package:polydodo/src/domain/acquisition_device/i_acquisition_device_repository.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; +import 'package:pedantic/pedantic.dart'; import 'device_selector_state.dart'; class DeviceSelectorCubit extends Cubit { @@ -21,13 +22,11 @@ class DeviceSelectorCubit extends Cubit { void startSearching() { _deviceRepository.initializeRepository(); - if (_acquisitionDeviceStream == null) { - _acquisitionDeviceStream = _deviceRepository - .watch() - .asBroadcastStream() - .listen((devices) => emit(DeviceSearchInProgress(devices)), - onError: (e) => emit(DeviceSearchFailure(e))); - } + _acquisitionDeviceStream ??= _deviceRepository + .watch() + .asBroadcastStream() + .listen((devices) => emit(DeviceSearchInProgress(devices)), + onError: (e) => emit(DeviceSearchFailure(e))); } Future connect(AcquisitionDevice device) async { @@ -53,11 +52,9 @@ class DeviceSelectorCubit extends Cubit { // todo: change bluetooth preferences in the preference section of the app void swapBluetooth() async { - print("swap"); usingBluetooth = !usingBluetooth; - StreamingSharedPreferences _prefs = - await StreamingSharedPreferences.instance; + var _prefs = await StreamingSharedPreferences.instance; - _prefs.setBool('using_bluetooth', usingBluetooth); + unawaited(_prefs.setBool('using_bluetooth', usingBluetooth)); } } diff --git a/mobile/lib/src/domain/unique_id.dart b/mobile/lib/src/domain/unique_id.dart index 56895b7e..28c03140 100644 --- a/mobile/lib/src/domain/unique_id.dart +++ b/mobile/lib/src/domain/unique_id.dart @@ -16,5 +16,5 @@ class UniqueId extends Equatable { List get props => [_id]; @override - toString() => _id; + String toString() => _id; } diff --git a/mobile/lib/src/infrastructure/connection_repositories/acquisition_device_repository.dart b/mobile/lib/src/infrastructure/connection_repositories/acquisition_device_repository.dart index 44a52fbd..d703295f 100644 --- a/mobile/lib/src/infrastructure/connection_repositories/acquisition_device_repository.dart +++ b/mobile/lib/src/infrastructure/connection_repositories/acquisition_device_repository.dart @@ -7,8 +7,8 @@ import 'package:polydodo/src/infrastructure/connection_repositories/serial_repos import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; class AcquisitionDeviceRepository implements IAcquisitionDeviceRepository { - final BluetoothRepository _bluetoothRepository = new BluetoothRepository(); - final SerialRepository _serialRepository = new SerialRepository(); + final BluetoothRepository _bluetoothRepository = BluetoothRepository(); + final SerialRepository _serialRepository = SerialRepository(); IAcquisitionDeviceRepository _currentRepository; StreamSubscription _bluetoothStream; @@ -20,9 +20,10 @@ class AcquisitionDeviceRepository implements IAcquisitionDeviceRepository { AcquisitionDeviceRepository() { _currentRepository = _serialRepository; - _acquisitionDeviceController = new StreamController(); + _acquisitionDeviceController = StreamController(); } + @override Future initializeRepository() async { if (_preferences == null) { _preferences = await StreamingSharedPreferences.instance; @@ -50,22 +51,27 @@ class AcquisitionDeviceRepository implements IAcquisitionDeviceRepository { } } + @override void connect(AcquisitionDevice device, Function(bool, Exception) callback) { _currentRepository.connect(device, callback); } + @override void disconnect() { _currentRepository.disconnect(); } + @override Future>> startDataStream() { return _currentRepository.startDataStream(); } + @override void stopDataStream() { _currentRepository.stopDataStream(); } + @override Stream> watch() { return _acquisitionDeviceController.stream; } diff --git a/mobile/lib/src/infrastructure/connection_repositories/bluetooth_repository.dart b/mobile/lib/src/infrastructure/connection_repositories/bluetooth_repository.dart index 0ee14865..c362c7c9 100644 --- a/mobile/lib/src/infrastructure/connection_repositories/bluetooth_repository.dart +++ b/mobile/lib/src/infrastructure/connection_repositories/bluetooth_repository.dart @@ -5,11 +5,12 @@ import 'package:polydodo/src/domain/acquisition_device/acquisition_device.dart'; import 'package:polydodo/src/domain/acquisition_device/i_acquisition_device_repository.dart'; import 'package:polydodo/src/infrastructure/constants.dart'; import 'package:polydodo/src/domain/unique_id.dart'; +import 'package:pedantic/pedantic.dart'; class BluetoothRepository implements IAcquisitionDeviceRepository { - static const String BLE_SERVICE = "0000fe84-0000-1000-8000-00805f9b34fb"; - static const String BLE_RECEIVE = "2d30c082-f39f-4ce6-923f-3484ea480596"; - static const String BLE_SEND = "2d30c083-f39f-4ce6-923f-3484ea480596"; + static const String BLE_SERVICE = '0000fe84-0000-1000-8000-00805f9b34fb'; + static const String BLE_RECEIVE = '2d30c082-f39f-4ce6-923f-3484ea480596'; + static const String BLE_SEND = '2d30c083-f39f-4ce6-923f-3484ea480596'; AcquisitionDevice _selectedDevice; QualifiedCharacteristic _sendCharacteristic; @@ -18,7 +19,7 @@ class BluetoothRepository implements IAcquisitionDeviceRepository { FlutterReactiveBle flutterReactiveBle; StreamSubscription _connectedDeviceStream; StreamSubscription _bluetoothScanSubscription; - List _acquisitionDevicePersistency = []; + final List _acquisitionDevicePersistency = []; final streamController = StreamController>(); @override @@ -35,7 +36,7 @@ class BluetoothRepository implements IAcquisitionDeviceRepository { } void addDevice(DiscoveredDevice bluetoothDevice) { - AcquisitionDevice device = AcquisitionDevice( + var device = AcquisitionDevice( UniqueId.from(bluetoothDevice.id.toString()), bluetoothDevice.name); final idx = _acquisitionDevicePersistency.indexOf(device); @@ -66,15 +67,15 @@ class BluetoothRepository implements IAcquisitionDeviceRepository { callback(true); } else if (event.connectionState == DeviceConnectionState.disconnected) { disconnect(); - callback(false, Exception("Failed to connect to device")); + callback(false, Exception('Failed to connect to device')); } }); } @override - void disconnect() async { + Future disconnect() async { _selectedDevice = null; - _connectedDeviceStream?.cancel(); + await _connectedDeviceStream?.cancel(); } void setupCharacteristics() async { @@ -95,8 +96,9 @@ class BluetoothRepository implements IAcquisitionDeviceRepository { deviceId: _selectedDevice.id.toString(), priority: ConnectionPriority.highPerformance); - flutterReactiveBle.writeCharacteristicWithoutResponse(_sendCharacteristic, - value: START_STREAM_CHAR.codeUnits); + unawaited(flutterReactiveBle.writeCharacteristicWithoutResponse( + _sendCharacteristic, + value: START_STREAM_CHAR.codeUnits)); return flutterReactiveBle.subscribeToCharacteristic(_receiveCharacteristic); } @@ -106,8 +108,9 @@ class BluetoothRepository implements IAcquisitionDeviceRepository { await flutterReactiveBle.requestConnectionPriority( deviceId: _selectedDevice.id.toString(), priority: ConnectionPriority.balanced); - flutterReactiveBle.writeCharacteristicWithoutResponse(_sendCharacteristic, - value: STOP_STREAM_CHAR.codeUnits); + unawaited(flutterReactiveBle.writeCharacteristicWithoutResponse( + _sendCharacteristic, + value: STOP_STREAM_CHAR.codeUnits)); } @override diff --git a/mobile/lib/src/infrastructure/connection_repositories/eeg_data_repository.dart b/mobile/lib/src/infrastructure/connection_repositories/eeg_data_repository.dart index 784d5f46..8746b3ff 100644 --- a/mobile/lib/src/infrastructure/connection_repositories/eeg_data_repository.dart +++ b/mobile/lib/src/infrastructure/connection_repositories/eeg_data_repository.dart @@ -12,26 +12,26 @@ import 'package:polydodo/src/infrastructure/eeg_data_transformers/cytonTransform import 'package:polydodo/src/infrastructure/constants.dart'; import 'package:polydodo/src/infrastructure/eeg_data_transformers/ganglionTransformer.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; +import 'package:pedantic/pedantic.dart'; class EEGDataRepository implements IEEGDataRepository { EEGData _recordingData; BaseOpenBCITransformer, List> currentStreamTransformer; final GanglionTransformer, List> _ganglionTransformer = - new GanglionTransformer, List>.broadcast(); + GanglionTransformer, List>.broadcast(); final CytonTransformer, List> _cytonTransformer = - new CytonTransformer.broadcast(); + CytonTransformer.broadcast(); BaseOpenBCITransformer, List> _currentTransformer; StreamSubscription _currentTransformerStream; StreamingSharedPreferences _preferences; + @override void initialize() async { - if (_preferences == null) { - _preferences = await StreamingSharedPreferences.instance; - } + _preferences ??= await StreamingSharedPreferences.instance; _currentTransformer = _preferences.getBool('using_bluetooth', defaultValue: false).getValue() @@ -39,9 +39,9 @@ class EEGDataRepository implements IEEGDataRepository { : _cytonTransformer; } + @override void createRecordingFromStream(Stream> stream) { - _recordingData = - EEGData(UniqueId.from(DateTime.now().toString()), List()); + _recordingData = EEGData(UniqueId.from(DateTime.now().toString()), [[]]); _currentTransformer.reset(); _currentTransformerStream = stream @@ -50,23 +50,27 @@ class EEGDataRepository implements IEEGDataRepository { .listen((data) => _recordingData.values.add(data)); } + @override Future stopRecordingFromStream() async { // todo: move save future to another file - _currentTransformerStream.cancel(); + unawaited(_currentTransformerStream.cancel()); final directory = await getExternalStorageDirectory(); final pathOfTheFileToWrite = - directory.path + '/' + _recordingData.fileName + ".txt"; - File file = File(pathOfTheFileToWrite); - List fileContent = []; + directory.path + '/' + _recordingData.fileName + '.txt'; + var file = File(pathOfTheFileToWrite); + var fileContent = [[]]; //todo: dynamically change header when we change transformer fileContent.addAll(OPEN_BCI_CYTON_HEADER); fileContent.addAll(_recordingData.values); - String csv = const ListToCsvConverter().convert(fileContent); + var csv = const ListToCsvConverter().convert(fileContent); await file.writeAsString(csv); } // todo: implement export and import + @override void importData() {} + + @override void exportData() {} } diff --git a/mobile/lib/src/infrastructure/connection_repositories/serial_repository.dart b/mobile/lib/src/infrastructure/connection_repositories/serial_repository.dart index 091831d7..0e854546 100644 --- a/mobile/lib/src/infrastructure/connection_repositories/serial_repository.dart +++ b/mobile/lib/src/infrastructure/connection_repositories/serial_repository.dart @@ -6,13 +6,14 @@ import 'package:polydodo/src/domain/acquisition_device/acquisition_device.dart'; import 'package:polydodo/src/domain/acquisition_device/i_acquisition_device_repository.dart'; import 'package:polydodo/src/infrastructure/constants.dart'; import 'package:usb_serial/usb_serial.dart'; +import 'package:pedantic/pedantic.dart'; class SerialRepository implements IAcquisitionDeviceRepository { UsbDevice _selectedDevice; UsbPort _serialPort; - List _acquisitionDevicePersistency = []; - List _serialDevices = []; StreamSubscription _inputStreamSubscription; + final List _acquisitionDevicePersistency = []; + final List _serialDevices = []; final streamController = StreamController>(); @override @@ -23,8 +24,8 @@ class SerialRepository implements IAcquisitionDeviceRepository { } void addDevices(List serialDevices) { - for (UsbDevice serialDevice in serialDevices) { - AcquisitionDevice device = AcquisitionDevice( + for (var serialDevice in serialDevices) { + var device = AcquisitionDevice( UniqueId.from(serialDevice.deviceId.toString()), serialDevice.productName); @@ -40,21 +41,21 @@ class SerialRepository implements IAcquisitionDeviceRepository { _selectedDevice = _serialDevices[_acquisitionDevicePersistency.indexOf(device)]; _serialPort = await _selectedDevice.create(); - bool openSuccessful = await _serialPort.open(); + var openSuccessful = await _serialPort.open(); if (!openSuccessful) { - callback(false, Exception("Could not open port")); + callback(false, Exception('Could not open port')); } - _serialPort.setPortParameters( + await _serialPort.setPortParameters( 115200, UsbPort.DATABITS_8, UsbPort.STOPBITS_1, UsbPort.PARITY_NONE); - _checkCytonConnection(callback); + unawaited(_checkCytonConnection(callback)); } Future _checkCytonConnection( Function(bool, [Exception]) callback) async { - var status = ""; + var status = ''; _inputStreamSubscription = _serialPort.inputStream.listen((event) { status += String.fromCharCodes(event); @@ -62,9 +63,9 @@ class SerialRepository implements IAcquisitionDeviceRepository { if (isFullMessage(status)) { _inputStreamSubscription.cancel(); - if (status == CYTON_SYSTEM_UP) + if (status == CYTON_SYSTEM_UP) { callback(true); - else { + } else { disconnect(); callback(false, Exception(status)); } @@ -83,7 +84,7 @@ class SerialRepository implements IAcquisitionDeviceRepository { @override Future disconnect() async { await _serialPort?.close(); - _inputStreamSubscription?.cancel(); + await _inputStreamSubscription?.cancel(); _selectedDevice = null; _serialPort = null; } diff --git a/mobile/lib/src/infrastructure/constants.dart b/mobile/lib/src/infrastructure/constants.dart index 73d90293..98848681 100644 --- a/mobile/lib/src/infrastructure/constants.dart +++ b/mobile/lib/src/infrastructure/constants.dart @@ -6,32 +6,32 @@ const GANGLION_PACKET_SIZE = 20; const GANGLION_NUMBER_COLUMNS = 15; const GANGLION_EXTRA_COLUMNS = 10; const OPEN_BCI_GANGLION_HEADER = [ - ["%OpenBCI Raw EEG Data"], - ["%Number of channels = 4"], - ["%Sample Rate = 200 Hz"], - ["%Board = OpenBCI_GUI\$BoardGanglionBLE"], + ['%OpenBCI Raw EEG Data'], + ['%Number of channels = 4'], + ['%Sample Rate = 200 Hz'], + ['%Board = OpenBCI_GUI\$BoardGanglionBLE'], [ - "Sample Index", - " EXG Channel 0", - " EXG Channel 1", - " EXG Channel 2", - " EXG Channel 3", - " Accel Channel 0", - " Accel Channel 1", - " Accel Channel 2", - " Other", - " Other", - " Other", - " Other", - " Other", - " Timestamp", - " Timestamp (Formatted)" + 'Sample Index', + ' EXG Channel 0', + ' EXG Channel 1', + ' EXG Channel 2', + ' EXG Channel 3', + ' Accel Channel 0', + ' Accel Channel 1', + ' Accel Channel 2', + ' Other', + ' Other', + ' Other', + ' Other', + ' Other', + ' Timestamp', + ' Timestamp (Formatted)' ] ]; -const CYTON_MESSAGE_FOOTER = "\$\$\$"; +const CYTON_MESSAGE_FOOTER = '\$\$\$'; const CYTON_GET_STATUS = [0xF0, 0x07]; -const CYTON_SYSTEM_UP = "Success: System is Up\$\$\$"; +const CYTON_SYSTEM_UP = 'Success: System is Up\$\$\$'; const CYTON_NUMBER_CHANNELS = 8; const CYTON_PACKET_SIZE = 33; const CYTON_NUMBER_COLUMNS = 24; @@ -39,34 +39,34 @@ const CYTON_EXTRA_COLUMNS = 15; const CYTON_HEADER = 160; const CYTON_FOOTER_MINIMUM = 192; const OPEN_BCI_CYTON_HEADER = [ - ["%OpenBCI Raw EEG Data"], - ["%Number of channels = 8"], - ["%Sample Rate = 250 Hz"], - ["%Board = OpenBCI_GUI\$BoardCytonSerial"], + ['%OpenBCI Raw EEG Data'], + ['%Number of channels = 8'], + ['%Sample Rate = 250 Hz'], + ['%Board = OpenBCI_GUI\$BoardCytonSerial'], [ - "Sample Index", - " EXG Channel 0", - " EXG Channel 1", - " EXG Channel 2", - " EXG Channel 3", - " EXG Channel 4", - " EXG Channel 5", - " EXG Channel 6", - " EXG Channel 7", - " Accel Channel 0", - " Accel Channel 1", - " Accel Channel 2", - " Other", - " Other", - " Other", - " Other", - " Other", - " Other", - " Other", - " Analog Channel 0", - " Analog Channel 1", - " Analog Channel 2", - " Timestamp", - " Timestamp (Formatted)" + 'Sample Index', + ' EXG Channel 0', + ' EXG Channel 1', + ' EXG Channel 2', + ' EXG Channel 3', + ' EXG Channel 4', + ' EXG Channel 5', + ' EXG Channel 6', + ' EXG Channel 7', + ' Accel Channel 0', + ' Accel Channel 1', + ' Accel Channel 2', + ' Other', + ' Other', + ' Other', + ' Other', + ' Other', + ' Other', + ' Other', + ' Analog Channel 0', + ' Analog Channel 1', + ' Analog Channel 2', + ' Timestamp', + ' Timestamp (Formatted)' ] ]; diff --git a/mobile/lib/src/infrastructure/eeg_data_transformers/baseOpenBCITransformer.dart b/mobile/lib/src/infrastructure/eeg_data_transformers/baseOpenBCITransformer.dart index 3e3bd609..10d84c06 100644 --- a/mobile/lib/src/infrastructure/eeg_data_transformers/baseOpenBCITransformer.dart +++ b/mobile/lib/src/infrastructure/eeg_data_transformers/baseOpenBCITransformer.dart @@ -6,8 +6,8 @@ abstract class BaseOpenBCITransformer implements StreamTransformer { bool cancelOnError; Stream _stream; - BaseOpenBCITransformer({bool synchronous: false, this.cancelOnError}) { - controller = new StreamController( + BaseOpenBCITransformer({bool synchronous = false, this.cancelOnError}) { + controller = StreamController( onListen: _onListen, onCancel: _onCancel, onPause: () { @@ -20,8 +20,8 @@ abstract class BaseOpenBCITransformer implements StreamTransformer { } BaseOpenBCITransformer.broadcast( - {bool synchronous: false, this.cancelOnError}) { - controller = new StreamController.broadcast( + {bool synchronous = false, this.cancelOnError}) { + controller = StreamController.broadcast( onListen: _onListen, onCancel: _onCancel, sync: synchronous); } @@ -45,7 +45,7 @@ abstract class BaseOpenBCITransformer implements StreamTransformer { @override Stream bind(Stream stream) { - this._stream = stream; + _stream = stream; return controller.stream; } diff --git a/mobile/lib/src/infrastructure/eeg_data_transformers/cytonTransformer.dart b/mobile/lib/src/infrastructure/eeg_data_transformers/cytonTransformer.dart index e42fc0fb..419d78af 100644 --- a/mobile/lib/src/infrastructure/eeg_data_transformers/cytonTransformer.dart +++ b/mobile/lib/src/infrastructure/eeg_data_transformers/cytonTransformer.dart @@ -4,22 +4,24 @@ import 'package:polydodo/src/infrastructure/constants.dart'; import 'baseOpenBCITransformer.dart'; class CytonTransformer extends BaseOpenBCITransformer { - List packet = List(); + List packet = []; - CytonTransformer.broadcast({bool synchronous: false, cancelOnError}) + CytonTransformer.broadcast({bool synchronous = false, cancelOnError}) : super.broadcast(synchronous: synchronous, cancelOnError: cancelOnError); + @override void reset() { packet.clear(); } + @override void onData(S data) { - List event = data as List; + var event = data as List; for (var i in event) { - if (packet.length == 0) { + if (packet.isEmpty) { if (i != CYTON_HEADER) { - print("Missing header byte"); + print('Missing header byte'); continue; } } @@ -27,12 +29,12 @@ class CytonTransformer extends BaseOpenBCITransformer { if (packet.length == CYTON_PACKET_SIZE) { if (packet[CYTON_PACKET_SIZE - 1] < CYTON_FOOTER_MINIMUM) { - print("Invalid packet"); + print('Invalid packet'); packet.clear(); continue; } - List data = parsePacket(packet); + var data = parsePacket(packet); packet.clear(); @@ -44,7 +46,7 @@ class CytonTransformer extends BaseOpenBCITransformer { } List parsePacket(List fullPacket) { - List data = getListForCSV(); + var data = getListForCSV(); data[0] = fullPacket[1]; data[1] = (fullPacket[2] << 16) | (fullPacket[3] << 8) | fullPacket[4]; @@ -62,9 +64,9 @@ class CytonTransformer extends BaseOpenBCITransformer { List getListForCSV() => List.generate(CYTON_NUMBER_COLUMNS, (index) => 0); List processData(List data, bool hasNegativeCompression) { - List result = List.from(data); + var result = List.from(data); - for (int i = 1; i < CYTON_NUMBER_CHANNELS + 1; ++i) { + for (var i = 1; i < CYTON_NUMBER_CHANNELS + 1; ++i) { if (hasNegativeCompression) result[i] = handleNegative(result[i]); result[i] = convertToMicrovolts(result[i]); diff --git a/mobile/lib/src/infrastructure/eeg_data_transformers/ganglionTransformer.dart b/mobile/lib/src/infrastructure/eeg_data_transformers/ganglionTransformer.dart index 8785956d..81e2a0bb 100644 --- a/mobile/lib/src/infrastructure/eeg_data_transformers/ganglionTransformer.dart +++ b/mobile/lib/src/infrastructure/eeg_data_transformers/ganglionTransformer.dart @@ -5,29 +5,31 @@ class GanglionTransformer extends BaseOpenBCITransformer { List _lastSampleData = [0, 0, 0, 0, 0]; int _sampleCounter = 0; - GanglionTransformer.broadcast({bool synchronous: false, cancelOnError}) + GanglionTransformer.broadcast({bool synchronous = false, cancelOnError}) : super.broadcast(synchronous: synchronous, cancelOnError: cancelOnError); + @override void reset() { _lastSampleData = [0, 0, 0, 0, 0]; _sampleCounter = 0; } + @override void onData(S data) { - List event = data as List; + var event = data as List; if (event.length != GANGLION_PACKET_SIZE) return; int packetID = event[0]; if (packetID == 0) { - List data = parseRaw(event); + var data = parseRaw(event); data = processData(data, nbSamples: 1, hasNegativeCompression: false, isDelta: false); controller.add(data.sublist(0, 15)); } else if (packetID >= 101 && packetID <= 200) { - List data = parse19Bit(event); + var data = parse19Bit(event); data = processData(data, nbSamples: 2, hasNegativeCompression: true, isDelta: true); @@ -37,7 +39,7 @@ class GanglionTransformer extends BaseOpenBCITransformer { } List parseRaw(event) { - List data = getListForCSV(); + var data = getListForCSV(); data[0] = _sampleCounter++; data[1] = (event[1] << 16) | (event[2] << 8) | event[3]; @@ -49,7 +51,7 @@ class GanglionTransformer extends BaseOpenBCITransformer { } List parse19Bit(event) { - List data = getListForCSV(); + var data = getListForCSV(); data[0] = _sampleCounter; data[1] = (event[1] << 11) | (event[2] << 3) | (event[3] >> 5); @@ -76,19 +78,21 @@ class GanglionTransformer extends BaseOpenBCITransformer { List processData(List data, {int nbSamples, bool hasNegativeCompression, bool isDelta}) { - List result = List.from(data); + var result = List.from(data); - for (int i = 1; i < GANGLION_NUMBER_CHANNELS + 1; ++i) { - for (int j = 0; j < nbSamples; ++j) { - int offset = 15 * j; + for (var i = 1; i < GANGLION_NUMBER_CHANNELS + 1; ++i) { + for (var j = 0; j < nbSamples; ++j) { + var offset = 15 * j; - if (hasNegativeCompression) + if (hasNegativeCompression) { result[i + offset] = handleNegative(result[i + offset]); + } result[i + offset] = convertToMicrovolts(result[i + offset]); - if (isDelta) + if (isDelta) { result[i + offset] = convertDeltaToData(i, result[i + offset]); + } _lastSampleData[i] = result[i + offset]; } @@ -98,7 +102,7 @@ class GanglionTransformer extends BaseOpenBCITransformer { } int handleNegative(int i) { - String binary = i.toRadixString(2); + var binary = i.toRadixString(2); return binary[binary.length - 1] == '1' ? (~i & 524287 | 1) * -1 : i; } diff --git a/mobile/lib/src/presentation/bluetooth_route/bluetoothSelector_route.dart b/mobile/lib/src/presentation/bluetooth_route/bluetoothSelector_route.dart index 97b2eef3..3805ad55 100644 --- a/mobile/lib/src/presentation/bluetooth_route/bluetoothSelector_route.dart +++ b/mobile/lib/src/presentation/bluetooth_route/bluetoothSelector_route.dart @@ -35,7 +35,7 @@ class BluetoothSelectorRoute extends StatelessWidget { } }, builder: (context, state) { - if (state is DeviceSearchInProgress) + if (state is DeviceSearchInProgress) { return ListView.builder( itemCount: state.devices.length, itemBuilder: (context, index) { @@ -48,8 +48,9 @@ class BluetoothSelectorRoute extends StatelessWidget { subtitle: Text(state.devices[index].id.toString())), ); }); - else + } else { return Container(); + } }, ), floatingActionButton: FloatingActionButton( diff --git a/mobile/lib/src/presentation/recording/recording_route.dart b/mobile/lib/src/presentation/recording/recording_route.dart index bcb475ac..43a4bb72 100644 --- a/mobile/lib/src/presentation/recording/recording_route.dart +++ b/mobile/lib/src/presentation/recording/recording_route.dart @@ -14,37 +14,38 @@ class RecordingRoute extends StatelessWidget { appBar: AppBar( // Here we take the value from the MyHomePage object that was created by // the App.build method, and use it to set our appbar title. - title: Text("Recording"), + title: Text('Recording'), ), body: BlocConsumer( listener: (context, state) { print(state.runtimeType); }, builder: (context, state) { - if (state is DataStateInitial) + if (state is DataStateInitial) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ RaisedButton( - child: Text("Start"), + child: Text('Start'), onPressed: () => BlocProvider.of(context).startStreaming(), ), ]), ); - else + } else { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ RaisedButton( - child: Text("Stop"), + child: Text('Stop'), onPressed: () => BlocProvider.of(context).stopStreaming(), ), ]), ); + } }, ), ); diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 98a50879..783f75ee 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -21,7 +21,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.2" + version: "2.5.0-nullsafety.1" battery: dependency: "direct main" description: @@ -56,35 +56,35 @@ packages: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety.1" characters: dependency: transitive description: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.1.0-nullsafety.3" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.3" + version: "1.2.0-nullsafety.1" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.1.0-nullsafety.1" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.13" + version: "1.15.0-nullsafety.3" convert: dependency: transitive description: @@ -126,7 +126,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0-nullsafety.1" ffi: dependency: transitive description: @@ -166,7 +166,7 @@ packages: name: flutter_reactive_ble url: "https://pub.dartlang.org" source: hosted - version: "2.5.3" + version: "2.6.1+1" flutter_test: dependency: "direct dev" description: flutter @@ -211,14 +211,14 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.8" + version: "0.12.10-nullsafety.1" meta: dependency: "direct main" description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0-nullsafety.3" mime: dependency: transitive description: @@ -239,14 +239,14 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety.1" path_provider: dependency: "direct main" description: name: path_provider url: "https://pub.dartlang.org" source: hosted - version: "1.6.21" + version: "1.6.22" path_provider_linux: dependency: transitive description: @@ -276,12 +276,12 @@ packages: source: hosted version: "0.0.4+1" pedantic: - dependency: transitive + dependency: "direct main" description: name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "1.9.0" + version: "1.9.2" plain_optional: dependency: transitive description: @@ -316,7 +316,7 @@ packages: name: protobuf url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.1.0" provider: dependency: transitive description: @@ -330,7 +330,7 @@ packages: name: share url: "https://pub.dartlang.org" source: hosted - version: "0.6.5+3" + version: "0.6.5+4" shared_preferences: dependency: transitive description: @@ -384,21 +384,21 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety.2" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.5" + version: "1.10.0-nullsafety.1" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety.1" streaming_shared_preferences: dependency: "direct main" description: @@ -412,28 +412,28 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "1.1.0-nullsafety.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0-nullsafety.1" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.17" + version: "0.2.19-nullsafety.2" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0-nullsafety.3" usb_serial: dependency: "direct main" description: @@ -454,7 +454,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0-nullsafety.3" win32: dependency: transitive description: @@ -468,7 +468,7 @@ packages: name: xdg_directories url: "https://pub.dartlang.org" source: hosted - version: "0.1.0" + version: "0.1.2" sdks: - dart: ">=2.9.0-14.0.dev <3.0.0" + dart: ">=2.10.0-110 <2.11.0" flutter: ">=1.16.0 <2.0.0" diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index b76a979a..13299cdc 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -3,7 +3,7 @@ description: A new Flutter project. # The following line prevents the package from being accidentally published to # pub.dev using `pub publish`. This is preferred for private packages. -publish_to: "none" # Remove this line if you wish to publish to pub.dev +publish_to: 'none' # Remove this line if you wish to publish to pub.dev # The following defines the version and build number for your application. # A version number is three numbers separated by dots, like 1.2.43 @@ -18,7 +18,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=2.7.0 <3.0.0" + sdk: '>=2.7.0 <3.0.0' dependencies: flutter: @@ -34,11 +34,12 @@ dependencies: cupertino_icons: ^0.1.3 equatable: ^1.2.5 flutter_bloc: ^6.0.5 - flutter_reactive_ble : ^2.5.2 + flutter_reactive_ble: ^2.5.2 get_it: ^4.0.4 hive: ^1.4.4 meta: ^1.1.8 path_provider: ^1.6.16 + pedantic: ^1.9.0 share: ^0.6.5 streaming_shared_preferences: ^1.0.1 uuid: ^2.2.2