Skip to content

Commit 0fc18aa

Browse files
MouradLachhababelfodilWilliam Harvey
authored
Linter (#52)
* Add base Flutter dependencies * Bump minimal android sdk version * Increment and decrement with counter cubit & create main/app/locator structure * create and implement domain layer * Connection bluetooth avec le ganglion * Create Flutter code structure example based on this [arch](https://github.com/PolyCortex/polydodo/wiki/Mobile-Architecture) * Remove widget test specific to counter app * Create an empty test for pipeline to perform build * Create an empty test in order for build pipeline to pass * fix mistake: move test/ under mobile/ * Requete de donnees et enregistrement sur csv * Changement du format du fichier output pour openBCI * Fixed some duplicates * Finished updating bluetooth files. Missing csv feature * Added recording feature * Removed main2 temporary file * Removed unecessary prints * Extracted variable and renamed for clarity * Removed unecessary imports and exposed methods in bluetooth interface * Removed unecessary bluetooth from domain * Created eeg data repository * Changed string id to UniqueID, fixed state inconsistency * Fixed typo, removed unecessary delay * format * Fixed typo * Removed general export files in favor of individual import * Added missing files for last commit * Extracted openbci header and only adding it at export time * Added error handling for failed connections * Handling already connected error and cleaned slightly findCharacteristics * Switched to generic acquisiton device in application layer * Reverted merge with master * Added handling for packet id 0 and fixed data values * Returning Container in view instead of new ListView * Remove default formatter for workspace because it prevents dartfmt to perform formating on dart files. * Reset esbenp.prettier-vscode as default formatter, but specified dartfmt as dart formatter * Changes based on last pull request comments (injecting flutter blue into repository, and small formatting changes) * Changed Acquisition initialization method to more generic name instead of bluetooth * Initial connection with usb serial achieved, missing data formatting * Renamed serial port * Moved back flutter instance into repository initialization and created generic entity extending equatable with unique id * Switched to AcquisitionDevice interface usage * Seperated data formatting into stream transformer * Implemented Cyton transformer * Small convention changes and changed BaseTransformer to an abstract class * Made async function into future * Removed transformer interface * Dynamically changing repositories and transformers * Added missing file * Fixed negative handling in cyton transformer and cleaned up a bit * Added unit testing * Awaiting stream in serial * Added status check for Cyton * Made exception parameter optional * Using implicit variable type instead of string * Added overrides for interface implemented methods * Linter changes using pedantic * Fixed error from list on data save * Trying minimum iOS 11.0 * Added analysis option file for linter * Fixed more linting issues, ignoring protos, added analyze to mobile workflow, added lint error to test workflow * Fixed linting issue Co-authored-by: Anes Belfodil <ans.belfodil@gmail.com> Co-authored-by: William Harvey <william.harvey@polymtl.ca>
1 parent 77e256a commit 0fc18aa

File tree

18 files changed

+199
-168
lines changed

18 files changed

+199
-168
lines changed

.github/workflows/mobile.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ jobs:
2424

2525
- run: flutter pub get
2626

27+
- run: flutter analyze
28+
2729
- run: flutter test
2830

2931
- run: flutter build apk

mobile/analysis_options.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
include: package:pedantic/analysis_options.yaml
2+
3+
analyzer:
4+
exclude:
5+
- lib/protos
6+
7+
linter:
8+
rules:
9+
avoid_shadowing_type_parameters: false

mobile/ios/Flutter/AppFrameworkInfo.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@
2121
<key>CFBundleVersion</key>
2222
<string>1.0</string>
2323
<key>MinimumOSVersion</key>
24-
<string>10.0</string>
24+
<string>11.0</string>
2525
</dict>
2626
</plist>

mobile/ios/Runner.xcodeproj/project.pbxproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@
272272
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
273273
GCC_WARN_UNUSED_FUNCTION = YES;
274274
GCC_WARN_UNUSED_VARIABLE = YES;
275-
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
275+
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
276276
MTL_ENABLE_DEBUG_INFO = NO;
277277
SDKROOT = iphoneos;
278278
SUPPORTED_PLATFORMS = iphoneos;
@@ -354,7 +354,7 @@
354354
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
355355
GCC_WARN_UNUSED_FUNCTION = YES;
356356
GCC_WARN_UNUSED_VARIABLE = YES;
357-
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
357+
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
358358
MTL_ENABLE_DEBUG_INFO = YES;
359359
ONLY_ACTIVE_ARCH = YES;
360360
SDKROOT = iphoneos;
@@ -403,7 +403,7 @@
403403
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
404404
GCC_WARN_UNUSED_FUNCTION = YES;
405405
GCC_WARN_UNUSED_VARIABLE = YES;
406-
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
406+
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
407407
MTL_ENABLE_DEBUG_INFO = NO;
408408
SDKROOT = iphoneos;
409409
SUPPORTED_PLATFORMS = iphoneos;

mobile/lib/src/application/device/device_selector_cubit.dart

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
55
import 'package:polydodo/src/domain/acquisition_device/acquisition_device.dart';
66
import 'package:polydodo/src/domain/acquisition_device/i_acquisition_device_repository.dart';
77
import 'package:streaming_shared_preferences/streaming_shared_preferences.dart';
8+
import 'package:pedantic/pedantic.dart';
89
import 'device_selector_state.dart';
910

1011
class DeviceSelectorCubit extends Cubit<DeviceState> {
@@ -21,13 +22,11 @@ class DeviceSelectorCubit extends Cubit<DeviceState> {
2122
void startSearching() {
2223
_deviceRepository.initializeRepository();
2324

24-
if (_acquisitionDeviceStream == null) {
25-
_acquisitionDeviceStream = _deviceRepository
26-
.watch()
27-
.asBroadcastStream()
28-
.listen((devices) => emit(DeviceSearchInProgress(devices)),
29-
onError: (e) => emit(DeviceSearchFailure(e)));
30-
}
25+
_acquisitionDeviceStream ??= _deviceRepository
26+
.watch()
27+
.asBroadcastStream()
28+
.listen((devices) => emit(DeviceSearchInProgress(devices)),
29+
onError: (e) => emit(DeviceSearchFailure(e)));
3130
}
3231

3332
Future<void> connect(AcquisitionDevice device) async {
@@ -53,11 +52,9 @@ class DeviceSelectorCubit extends Cubit<DeviceState> {
5352

5453
// todo: change bluetooth preferences in the preference section of the app
5554
void swapBluetooth() async {
56-
print("swap");
5755
usingBluetooth = !usingBluetooth;
58-
StreamingSharedPreferences _prefs =
59-
await StreamingSharedPreferences.instance;
56+
var _prefs = await StreamingSharedPreferences.instance;
6057

61-
_prefs.setBool('using_bluetooth', usingBluetooth);
58+
unawaited(_prefs.setBool('using_bluetooth', usingBluetooth));
6259
}
6360
}

mobile/lib/src/domain/unique_id.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ class UniqueId extends Equatable {
1616
List<Object> get props => [_id];
1717

1818
@override
19-
toString() => _id;
19+
String toString() => _id;
2020
}

mobile/lib/src/infrastructure/connection_repositories/acquisition_device_repository.dart

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import 'package:polydodo/src/infrastructure/connection_repositories/serial_repos
77
import 'package:streaming_shared_preferences/streaming_shared_preferences.dart';
88

99
class AcquisitionDeviceRepository implements IAcquisitionDeviceRepository {
10-
final BluetoothRepository _bluetoothRepository = new BluetoothRepository();
11-
final SerialRepository _serialRepository = new SerialRepository();
10+
final BluetoothRepository _bluetoothRepository = BluetoothRepository();
11+
final SerialRepository _serialRepository = SerialRepository();
1212
IAcquisitionDeviceRepository _currentRepository;
1313

1414
StreamSubscription _bluetoothStream;
@@ -20,9 +20,10 @@ class AcquisitionDeviceRepository implements IAcquisitionDeviceRepository {
2020

2121
AcquisitionDeviceRepository() {
2222
_currentRepository = _serialRepository;
23-
_acquisitionDeviceController = new StreamController();
23+
_acquisitionDeviceController = StreamController();
2424
}
2525

26+
@override
2627
Future<void> initializeRepository() async {
2728
if (_preferences == null) {
2829
_preferences = await StreamingSharedPreferences.instance;
@@ -50,22 +51,27 @@ class AcquisitionDeviceRepository implements IAcquisitionDeviceRepository {
5051
}
5152
}
5253

54+
@override
5355
void connect(AcquisitionDevice device, Function(bool, Exception) callback) {
5456
_currentRepository.connect(device, callback);
5557
}
5658

59+
@override
5760
void disconnect() {
5861
_currentRepository.disconnect();
5962
}
6063

64+
@override
6165
Future<Stream<List<int>>> startDataStream() {
6266
return _currentRepository.startDataStream();
6367
}
6468

69+
@override
6570
void stopDataStream() {
6671
_currentRepository.stopDataStream();
6772
}
6873

74+
@override
6975
Stream<List<AcquisitionDevice>> watch() {
7076
return _acquisitionDeviceController.stream;
7177
}

mobile/lib/src/infrastructure/connection_repositories/bluetooth_repository.dart

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ import 'package:polydodo/src/domain/acquisition_device/acquisition_device.dart';
55
import 'package:polydodo/src/domain/acquisition_device/i_acquisition_device_repository.dart';
66
import 'package:polydodo/src/infrastructure/constants.dart';
77
import 'package:polydodo/src/domain/unique_id.dart';
8+
import 'package:pedantic/pedantic.dart';
89

910
class BluetoothRepository implements IAcquisitionDeviceRepository {
10-
static const String BLE_SERVICE = "0000fe84-0000-1000-8000-00805f9b34fb";
11-
static const String BLE_RECEIVE = "2d30c082-f39f-4ce6-923f-3484ea480596";
12-
static const String BLE_SEND = "2d30c083-f39f-4ce6-923f-3484ea480596";
11+
static const String BLE_SERVICE = '0000fe84-0000-1000-8000-00805f9b34fb';
12+
static const String BLE_RECEIVE = '2d30c082-f39f-4ce6-923f-3484ea480596';
13+
static const String BLE_SEND = '2d30c083-f39f-4ce6-923f-3484ea480596';
1314

1415
AcquisitionDevice _selectedDevice;
1516
QualifiedCharacteristic _sendCharacteristic;
@@ -18,7 +19,7 @@ class BluetoothRepository implements IAcquisitionDeviceRepository {
1819
FlutterReactiveBle flutterReactiveBle;
1920
StreamSubscription<ConnectionStateUpdate> _connectedDeviceStream;
2021
StreamSubscription<DiscoveredDevice> _bluetoothScanSubscription;
21-
List<AcquisitionDevice> _acquisitionDevicePersistency = [];
22+
final List<AcquisitionDevice> _acquisitionDevicePersistency = [];
2223
final streamController = StreamController<List<AcquisitionDevice>>();
2324

2425
@override
@@ -35,7 +36,7 @@ class BluetoothRepository implements IAcquisitionDeviceRepository {
3536
}
3637

3738
void addDevice(DiscoveredDevice bluetoothDevice) {
38-
AcquisitionDevice device = AcquisitionDevice(
39+
var device = AcquisitionDevice(
3940
UniqueId.from(bluetoothDevice.id.toString()), bluetoothDevice.name);
4041

4142
final idx = _acquisitionDevicePersistency.indexOf(device);
@@ -66,15 +67,15 @@ class BluetoothRepository implements IAcquisitionDeviceRepository {
6667
callback(true);
6768
} else if (event.connectionState == DeviceConnectionState.disconnected) {
6869
disconnect();
69-
callback(false, Exception("Failed to connect to device"));
70+
callback(false, Exception('Failed to connect to device'));
7071
}
7172
});
7273
}
7374

7475
@override
75-
void disconnect() async {
76+
Future<void> disconnect() async {
7677
_selectedDevice = null;
77-
_connectedDeviceStream?.cancel();
78+
await _connectedDeviceStream?.cancel();
7879
}
7980

8081
void setupCharacteristics() async {
@@ -95,8 +96,9 @@ class BluetoothRepository implements IAcquisitionDeviceRepository {
9596
deviceId: _selectedDevice.id.toString(),
9697
priority: ConnectionPriority.highPerformance);
9798

98-
flutterReactiveBle.writeCharacteristicWithoutResponse(_sendCharacteristic,
99-
value: START_STREAM_CHAR.codeUnits);
99+
unawaited(flutterReactiveBle.writeCharacteristicWithoutResponse(
100+
_sendCharacteristic,
101+
value: START_STREAM_CHAR.codeUnits));
100102

101103
return flutterReactiveBle.subscribeToCharacteristic(_receiveCharacteristic);
102104
}
@@ -106,8 +108,9 @@ class BluetoothRepository implements IAcquisitionDeviceRepository {
106108
await flutterReactiveBle.requestConnectionPriority(
107109
deviceId: _selectedDevice.id.toString(),
108110
priority: ConnectionPriority.balanced);
109-
flutterReactiveBle.writeCharacteristicWithoutResponse(_sendCharacteristic,
110-
value: STOP_STREAM_CHAR.codeUnits);
111+
unawaited(flutterReactiveBle.writeCharacteristicWithoutResponse(
112+
_sendCharacteristic,
113+
value: STOP_STREAM_CHAR.codeUnits));
111114
}
112115

113116
@override

mobile/lib/src/infrastructure/connection_repositories/eeg_data_repository.dart

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,36 @@ import 'package:polydodo/src/infrastructure/eeg_data_transformers/cytonTransform
1212
import 'package:polydodo/src/infrastructure/constants.dart';
1313
import 'package:polydodo/src/infrastructure/eeg_data_transformers/ganglionTransformer.dart';
1414
import 'package:streaming_shared_preferences/streaming_shared_preferences.dart';
15+
import 'package:pedantic/pedantic.dart';
1516

1617
class EEGDataRepository implements IEEGDataRepository {
1718
EEGData _recordingData;
1819
BaseOpenBCITransformer<List<int>, List<dynamic>> currentStreamTransformer;
1920

2021
final GanglionTransformer<List<int>, List> _ganglionTransformer =
21-
new GanglionTransformer<List<int>, List>.broadcast();
22+
GanglionTransformer<List<int>, List>.broadcast();
2223

2324
final CytonTransformer<List<int>, List<dynamic>> _cytonTransformer =
24-
new CytonTransformer<Uint8List, List>.broadcast();
25+
CytonTransformer<Uint8List, List>.broadcast();
2526

2627
BaseOpenBCITransformer<List<int>, List<dynamic>> _currentTransformer;
2728
StreamSubscription _currentTransformerStream;
2829

2930
StreamingSharedPreferences _preferences;
3031

32+
@override
3133
void initialize() async {
32-
if (_preferences == null) {
33-
_preferences = await StreamingSharedPreferences.instance;
34-
}
34+
_preferences ??= await StreamingSharedPreferences.instance;
3535

3636
_currentTransformer =
3737
_preferences.getBool('using_bluetooth', defaultValue: false).getValue()
3838
? _ganglionTransformer
3939
: _cytonTransformer;
4040
}
4141

42+
@override
4243
void createRecordingFromStream(Stream<List<int>> stream) {
43-
_recordingData =
44-
EEGData(UniqueId.from(DateTime.now().toString()), List<List>());
44+
_recordingData = EEGData(UniqueId.from(DateTime.now().toString()), [[]]);
4545

4646
_currentTransformer.reset();
4747
_currentTransformerStream = stream
@@ -50,23 +50,27 @@ class EEGDataRepository implements IEEGDataRepository {
5050
.listen((data) => _recordingData.values.add(data));
5151
}
5252

53+
@override
5354
Future<void> stopRecordingFromStream() async {
5455
// todo: move save future to another file
55-
_currentTransformerStream.cancel();
56+
unawaited(_currentTransformerStream.cancel());
5657

5758
final directory = await getExternalStorageDirectory();
5859
final pathOfTheFileToWrite =
59-
directory.path + '/' + _recordingData.fileName + ".txt";
60-
File file = File(pathOfTheFileToWrite);
61-
List<List> fileContent = [];
60+
directory.path + '/' + _recordingData.fileName + '.txt';
61+
var file = File(pathOfTheFileToWrite);
62+
var fileContent = [[]];
6263
//todo: dynamically change header when we change transformer
6364
fileContent.addAll(OPEN_BCI_CYTON_HEADER);
6465
fileContent.addAll(_recordingData.values);
65-
String csv = const ListToCsvConverter().convert(fileContent);
66+
var csv = const ListToCsvConverter().convert(fileContent);
6667
await file.writeAsString(csv);
6768
}
6869

6970
// todo: implement export and import
71+
@override
7072
void importData() {}
73+
74+
@override
7175
void exportData() {}
7276
}

mobile/lib/src/infrastructure/connection_repositories/serial_repository.dart

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ import 'package:polydodo/src/domain/acquisition_device/acquisition_device.dart';
66
import 'package:polydodo/src/domain/acquisition_device/i_acquisition_device_repository.dart';
77
import 'package:polydodo/src/infrastructure/constants.dart';
88
import 'package:usb_serial/usb_serial.dart';
9+
import 'package:pedantic/pedantic.dart';
910

1011
class SerialRepository implements IAcquisitionDeviceRepository {
1112
UsbDevice _selectedDevice;
1213
UsbPort _serialPort;
13-
List<AcquisitionDevice> _acquisitionDevicePersistency = [];
14-
List<UsbDevice> _serialDevices = [];
1514
StreamSubscription _inputStreamSubscription;
15+
final List<AcquisitionDevice> _acquisitionDevicePersistency = [];
16+
final List<UsbDevice> _serialDevices = [];
1617
final streamController = StreamController<List<AcquisitionDevice>>();
1718

1819
@override
@@ -23,8 +24,8 @@ class SerialRepository implements IAcquisitionDeviceRepository {
2324
}
2425

2526
void addDevices(List<UsbDevice> serialDevices) {
26-
for (UsbDevice serialDevice in serialDevices) {
27-
AcquisitionDevice device = AcquisitionDevice(
27+
for (var serialDevice in serialDevices) {
28+
var device = AcquisitionDevice(
2829
UniqueId.from(serialDevice.deviceId.toString()),
2930
serialDevice.productName);
3031

@@ -40,31 +41,31 @@ class SerialRepository implements IAcquisitionDeviceRepository {
4041
_selectedDevice =
4142
_serialDevices[_acquisitionDevicePersistency.indexOf(device)];
4243
_serialPort = await _selectedDevice.create();
43-
bool openSuccessful = await _serialPort.open();
44+
var openSuccessful = await _serialPort.open();
4445

4546
if (!openSuccessful) {
46-
callback(false, Exception("Could not open port"));
47+
callback(false, Exception('Could not open port'));
4748
}
4849

49-
_serialPort.setPortParameters(
50+
await _serialPort.setPortParameters(
5051
115200, UsbPort.DATABITS_8, UsbPort.STOPBITS_1, UsbPort.PARITY_NONE);
5152

52-
_checkCytonConnection(callback);
53+
unawaited(_checkCytonConnection(callback));
5354
}
5455

5556
Future<void> _checkCytonConnection(
5657
Function(bool, [Exception]) callback) async {
57-
var status = "";
58+
var status = '';
5859

5960
_inputStreamSubscription = _serialPort.inputStream.listen((event) {
6061
status += String.fromCharCodes(event);
6162

6263
if (isFullMessage(status)) {
6364
_inputStreamSubscription.cancel();
6465

65-
if (status == CYTON_SYSTEM_UP)
66+
if (status == CYTON_SYSTEM_UP) {
6667
callback(true);
67-
else {
68+
} else {
6869
disconnect();
6970
callback(false, Exception(status));
7071
}
@@ -83,7 +84,7 @@ class SerialRepository implements IAcquisitionDeviceRepository {
8384
@override
8485
Future<void> disconnect() async {
8586
await _serialPort?.close();
86-
_inputStreamSubscription?.cancel();
87+
await _inputStreamSubscription?.cancel();
8788
_selectedDevice = null;
8889
_serialPort = null;
8990
}

0 commit comments

Comments
 (0)