diff --git a/packages/movisens_flutter/CHANGELOG.md b/packages/movisens_flutter/CHANGELOG.md index 15c23617e..6d5bd5689 100644 --- a/packages/movisens_flutter/CHANGELOG.md +++ b/packages/movisens_flutter/CHANGELOG.md @@ -1,7 +1,8 @@ -## 3.1.1 +## 3.1.2 - Upgrade to flutter version 3.2.0 - Upgrade to `flutter_blue_plus: ^1.29.0` +- Refactor of `MovisensService` to avoid late initialization problems. ## 3.0.0 diff --git a/packages/movisens_flutter/example/lib/main.dart b/packages/movisens_flutter/example/lib/main.dart index 183c9752e..4beb702e9 100644 --- a/packages/movisens_flutter/example/lib/main.dart +++ b/packages/movisens_flutter/example/lib/main.dart @@ -39,7 +39,7 @@ class MyHomePage extends StatefulWidget { } class _MyHomePageState extends State { - late MovisensDevice device; + MovisensDevice? device; @override void initState() { @@ -54,59 +54,59 @@ class _MyHomePageState extends State { "MOVISENS Sensor 01234"; // Example: "MOVISENS Sensor 04421" void connect() async { - await device.connect(); + await device?.connect(); - device.state?.listen((event) { + device?.state?.listen((event) { print('Connection event: $event'); }); } void listen() async { // Enable the device to emit all event for each service: - await device.ambientService?.enableNotify(); - await device.edaService?.enableNotify(); - await device.hrvService?.enableNotify(); - await device.markerService?.enableNotify(); - await device.batteryService?.enableNotify(); - await device.physicalActivityService?.enableNotify(); - await device.respirationService?.enableNotify(); - await device.sensorControlService?.enableNotify(); - await device.skinTemperatureService?.enableNotify(); + await device?.ambientService?.enableNotify(); + await device?.edaService?.enableNotify(); + await device?.hrvService?.enableNotify(); + await device?.markerService?.enableNotify(); + await device?.batteryService?.enableNotify(); + await device?.physicalActivityService?.enableNotify(); + await device?.respirationService?.enableNotify(); + await device?.sensorControlService?.enableNotify(); + await device?.skinTemperatureService?.enableNotify(); // Listen to all characteristics - device.ambientService?.events.listen((event) { + device?.ambientService?.events.listen((event) { print("all ambient events stream -- event : $event"); }); - device.edaService?.events.listen((event) { + device?.edaService?.events.listen((event) { print("all eda events stream -- event : $event"); }); - device.hrvService?.events.listen((event) { + device?.hrvService?.events.listen((event) { print("all hrv events stream -- event : $event"); }); - device.markerService?.events.listen((event) { + device?.markerService?.events.listen((event) { print("all marker events stream -- event : $event"); }); - device.batteryService?.events.listen((event) { + device?.batteryService?.events.listen((event) { print("all battery events stream -- event : $event"); }); - device.physicalActivityService?.events.listen((event) { + device?.physicalActivityService?.events.listen((event) { print("all physical events stream -- event : $event"); }); - device.respirationService?.events.listen((event) { + device?.respirationService?.events.listen((event) { print("all respiration events stream -- event : $event"); }); - device.sensorControlService?.events.listen((event) { + device?.sensorControlService?.events.listen((event) { print("all sensor control events stream -- event : $event"); }); - device.skinTemperatureService?.events.listen((event) { + device?.skinTemperatureService?.events.listen((event) { print("all skin temp events stream -- event : $event"); }); // Or listen to individual characteristics: - device.ambientService?.sensorTemperatureEvents?.listen((event) { + device?.ambientService?.sensorTemperatureEvents?.listen((event) { print("Sensor temp listen : event: $event"); }); - device.skinTemperatureService?.skinTemperatureEvents?.listen((event) { + device?.skinTemperatureService?.skinTemperatureEvents?.listen((event) { print("Skin temp listen : event: $event"); }); } @@ -114,31 +114,31 @@ class _MyHomePageState extends State { void startMeasurement() async { // Test start and stop of measurement MeasurementStatus? ms = - await device.sensorControlService?.getMeasurementStatus(); - bool? me = await device.sensorControlService?.getMeasurementEnabled(); + await device?.sensorControlService?.getMeasurementStatus(); + bool? me = await device?.sensorControlService?.getMeasurementEnabled(); String s = (ms != null) ? enumToReadableString(ms) : "null"; print("Measurement status:: $s"); print("Measurement enabled:: $me"); // Start a measurement that last 120 seconds or a indefinite one // Certain data has a delay of 60 - 84 seconds, so preferably a measurement longer than that. - await device.sensorControlService?.setStartMeasurement(120); - // await device.sensorControlService?.setMeasurementEnabled(true); + await device?.sensorControlService?.setStartMeasurement(120); + // await device?.sensorControlService?.setMeasurementEnabled(true); // Delay 1 second for device to complete the task await Future.delayed(const Duration(seconds: 1)); - ms = await device.sensorControlService?.getMeasurementStatus(); - me = await device.sensorControlService?.getMeasurementEnabled(); + ms = await device?.sensorControlService?.getMeasurementStatus(); + me = await device?.sensorControlService?.getMeasurementEnabled(); s = (ms != null) ? enumToReadableString(ms) : "null"; print("Measurement status after start:: $s"); print("Measurement enabled after start:: $me"); } void stopMeasurement() async { - await device.sensorControlService?.setMeasurementEnabled(false); + await device?.sensorControlService?.setMeasurementEnabled(false); // Wait 2 seconds for device to complete task await Future.delayed(const Duration(seconds: 2)); MeasurementStatus? ms = - await device.sensorControlService?.getMeasurementStatus(); - bool? me = await device.sensorControlService?.getMeasurementEnabled(); + await device?.sensorControlService?.getMeasurementStatus(); + bool? me = await device?.sensorControlService?.getMeasurementEnabled(); String s = (ms != null) ? enumToReadableString(ms) : "null"; print("Measurement status after stop:: $s"); print("Measurement enabled after stop:: $me"); @@ -146,12 +146,12 @@ class _MyHomePageState extends State { void deleteData() async { // Test deletion of data - bool? da = await device.sensorControlService?.getDataAvailable(); + bool? da = await device?.sensorControlService?.getDataAvailable(); print('Data available :: $da'); - await device.sensorControlService?.setDeleteData(true); + await device?.sensorControlService?.setDeleteData(true); // Delay 1 second for device to complete the task await Future.delayed(const Duration(seconds: 1)); - da = await device.sensorControlService?.getDataAvailable(); + da = await device?.sensorControlService?.getDataAvailable(); print('Data available after delete :: $da'); } @@ -161,75 +161,75 @@ class _MyHomePageState extends State { // Set and get current time MS try { int currentTimeMs = DateTime.now().millisecondsSinceEpoch; - await device.sensorControlService?.setCurrentTimeMs(currentTimeMs); + await device?.sensorControlService?.setCurrentTimeMs(currentTimeMs); } catch (e) { print('Error setting Current Time MS:: $e'); } // Delay 1 second for device to complete the task await Future.delayed(const Duration(seconds: 1)); try { - int? x = await device.sensorControlService?.getCurrentTimeMs(); + int? x = await device?.sensorControlService?.getCurrentTimeMs(); print("Current time MS:: $x"); } catch (e) { print('Error getting Current Time MS:: $e'); } // Get status - int? sta = await device.sensorControlService?.getStatus(); + int? sta = await device?.sensorControlService?.getStatus(); print('Status:: $sta'); // Test storage level - int? sl = await device.sensorControlService?.getStorageLevel(); + int? sl = await device?.sensorControlService?.getStorageLevel(); print('Storage level :: $sl'); // set age - await device.userDataService?.setAgeFloat(41.5); + await device?.userDataService?.setAgeFloat(41.5); // get age - double? age = await device.userDataService?.getAgeFloat(); + double? age = await device?.userDataService?.getAgeFloat(); print('Age:: $age'); // set sensor location - await device.userDataService?.setSensorLocation(SensorLocation.chest); + await device?.userDataService?.setSensorLocation(SensorLocation.chest); // get sensor location SensorLocation? sensorloc = - await device.userDataService?.getSensorLocation(); + await device?.userDataService?.getSensorLocation(); print('Sensor location:: $sensorloc'); // set gender - await device.userDataService?.setGender(Gender.male); + await device?.userDataService?.setGender(Gender.male); // get gender - Gender? gender = await device.userDataService?.getGender(); + Gender? gender = await device?.userDataService?.getGender(); print('gender:: $gender'); // set height - await device.userDataService?.setHeight(182); + await device?.userDataService?.setHeight(182); // get height - int? height = await device.userDataService?.getHeight(); + int? height = await device?.userDataService?.getHeight(); print('height:: $height cm'); // set weight - await device.userDataService?.setWeight(84.5); + await device?.userDataService?.setWeight(84.5); // get weight - double? weight = await device.userDataService?.getWeight(); + double? weight = await device?.userDataService?.getWeight(); print('weight:: $weight kg'); // Device information: String? firmwareRevisionString = - await device.deviceInformationService?.getFirmwareRevisionString(); + await device?.deviceInformationService?.getFirmwareRevisionString(); print(firmwareRevisionString); String? manufacturerNameString = - await device.deviceInformationService?.getManufacturerNameString(); + await device?.deviceInformationService?.getManufacturerNameString(); print(manufacturerNameString); String? modelNumberString = - await device.deviceInformationService?.getModelNumberString(); + await device?.deviceInformationService?.getModelNumberString(); print(modelNumberString); String? serialNumberString = - await device.deviceInformationService?.getSerialNumberString(); + await device?.deviceInformationService?.getSerialNumberString(); print(serialNumberString); } void disconnect() async { - await device.disconnect(); + await device?.disconnect(); } @override diff --git a/packages/movisens_flutter/lib/movisens_device.dart b/packages/movisens_flutter/lib/movisens_device.dart index 1186ec93d..de649034b 100644 --- a/packages/movisens_flutter/lib/movisens_device.dart +++ b/packages/movisens_flutter/lib/movisens_device.dart @@ -6,15 +6,22 @@ */ part of movisens_flutter; -/// A representation of a Movisens device with services +/// A representation of a Movisens device with services. /// /// It contains all the services that the Movisens device provides /// and the methods for handling device connection. class MovisensDevice { - late String name; - late String id; BluetoothDevice? _bluetoothDevice; + /// The name of the device. Used to connect to it. + /// + /// The default Movisens name of devices are `MOVISENS Sensor `, where + /// `serial` is the 5-digit serial number written on the back of the device. + String name; + + /// The BLE id of the device. Only known after the device is connected. + String? id; + /// Is the phone and app connected to the Movisens device bool get isConnected => _bluetoothDevice != null; @@ -129,21 +136,22 @@ class MovisensDevice { // Scan for devices FlutterBluePlus.startScan(timeout: const Duration(seconds: 10)); - late StreamSubscription subscription; + StreamSubscription? subscription; subscription = FlutterBluePlus.scanResults.listen((scanResults) async { - // Select only 1 device to connect to - ScanResult? scanResult = + // Select the first device to connect to + var firstDevice = (scanResults.any((element) => element.device.platformName == name)) ? scanResults .firstWhere((element) => element.device.platformName == name) : null; + // connect, stop scanning and clean streams - if (scanResult != null) { + if (firstDevice != null) { await FlutterBluePlus.stopScan(); - await scanResult.device.connect(); - _bluetoothDevice = scanResult.device; + await firstDevice.device.connect(); + _bluetoothDevice = firstDevice.device; await _discoverAndSetup(); - await subscription.cancel(); + await subscription?.cancel(); } }); } @@ -153,8 +161,9 @@ class MovisensDevice { id = _bluetoothDevice!.remoteId.str; _log.info("Stored ID [$id] from Movisens device [$name]"); _log.info("Discovering services on Movisens device [$id]"); + // Discover services - late List services; + List services; // Delay introduced as BluetoothDevice.connect could sometimes finish before the device was connected. await Future.delayed(const Duration(milliseconds: 500)); services = await _bluetoothDevice!.discoverServices(); diff --git a/packages/movisens_flutter/lib/movisens_event.dart b/packages/movisens_flutter/lib/movisens_event.dart index 0b1260d0c..f6b70b952 100644 --- a/packages/movisens_flutter/lib/movisens_event.dart +++ b/packages/movisens_flutter/lib/movisens_event.dart @@ -8,14 +8,15 @@ part of movisens_flutter; /// A basic Movisens Event. abstract class MovisensEvent { + late DateTime _time; + final String _deviceId; + /// Get the UUID of this [type]. String get uuid => charToUuid[type]!; - late DateTime _time; /// The type of characteristic which emitted this event /// as enum [MovisensBluetoothCharacteristics]. abstract MovisensBluetoothCharacteristics type; - final String _deviceId; /// Constructing an event requires an ID of the device. MovisensEvent(this._deviceId) { @@ -31,9 +32,8 @@ abstract class MovisensEvent { String get deviceId => _deviceId; @override - String toString() { - return "Device ID: $deviceId, Type: ${enumToReadableString(type)}, Time: $time"; - } + String toString() => + "Device ID: $deviceId, Type: ${enumToReadableString(type)}, Time: $time"; } /// An event of type [MovisensBluetoothCharacteristics.light]. @@ -63,9 +63,7 @@ class LightEvent extends MovisensEvent { int get ir => _ir; @override - String toString() { - return '${super.toString()}, Clear: $clear, ir: $ir'; - } + String toString() => '${super.toString()}, Clear: $clear, ir: $ir'; } /// An event of type [MovisensBluetoothCharacteristics.lightRGB]. @@ -100,9 +98,8 @@ class LightRGBEvent extends MovisensEvent { int get blue => _blue; @override - String toString() { - return '${super.toString()}, Red: $red, Green: $green, Blue: $blue'; - } + String toString() => + '${super.toString()}, Red: $red, Green: $green, Blue: $blue'; } /// An event of type [MovisensBluetoothCharacteristics.sensorTemperature]. @@ -127,9 +124,8 @@ class SensorTemperatureEvent extends MovisensEvent { double get sensorTemperature => _sensorTemperature; @override - String toString() { - return '${super.toString()}, Sensor Temperature: $sensorTemperature'; - } + String toString() => + '${super.toString()}, Sensor Temperature: $sensorTemperature'; } /// An event of type [MovisensBluetoothCharacteristics.edaSclMean]. @@ -157,9 +153,7 @@ class EdaSclMeanEvent extends MovisensEvent { double get edaSclMean => _edaSclMean; @override - String toString() { - return '${super.toString()}, EdaSclMean: $edaSclMean'; - } + String toString() => '${super.toString()}, EdaSclMean: $edaSclMean'; } /// An event of type [MovisensBluetoothCharacteristics.hrMean] @@ -184,9 +178,7 @@ class HrMeanEvent extends MovisensEvent { int get hrMean => _hrMean; @override - String toString() { - return '${super.toString()}, HrMean: $hrMean'; - } + String toString() => '${super.toString()}, HrMean: $hrMean'; } /// An event of type [MovisensBluetoothCharacteristics.hrvIsValid] @@ -209,9 +201,7 @@ class HrvIsValidEvent extends MovisensEvent { bool get hrvIsValid => _hrvIsValid; @override - String toString() { - return '${super.toString()}, HrvIsValid: $hrvIsValid'; - } + String toString() => '${super.toString()}, HrvIsValid: $hrvIsValid'; } /// An event of type [MovisensBluetoothCharacteristics.rmssd] @@ -239,9 +229,7 @@ class RmssdEvent extends MovisensEvent { int get rmssd => _rmssd; @override - String toString() { - return '${super.toString()}, Rmssd: $rmssd'; - } + String toString() => '${super.toString()}, Rmssd: $rmssd'; } /// An event of type [MovisensBluetoothCharacteristics.tapMarker] @@ -266,9 +254,7 @@ class TapMarkerEvent extends MovisensEvent { int get tapMarkerValue => _tapMarkerValue; @override - String toString() { - return '${super.toString()}, TapMarkerValue: $tapMarkerValue'; - } + String toString() => '${super.toString()}, TapMarkerValue: $tapMarkerValue'; } /// An event of type [MovisensBluetoothCharacteristics.charging] @@ -291,9 +277,7 @@ class ChargingEvent extends MovisensEvent { bool get charging => _charging; @override - String toString() { - return '${super.toString()}, Charging: $charging'; - } + String toString() => '${super.toString()}, Charging: $charging'; } /// Body position enum @@ -362,9 +346,8 @@ class BodyPositionEvent extends MovisensEvent { BodyPosition get bodyPosition => _bodyPosition; @override - String toString() { - return '${super.toString()}, BodyPosition: ${enumToReadableString(bodyPosition)}'; - } + String toString() => + '${super.toString()}, BodyPosition: ${enumToReadableString(bodyPosition)}'; } /// An event of type [MovisensBluetoothCharacteristics.inclination] @@ -404,9 +387,7 @@ class InclinationEvent extends MovisensEvent { int get z => _z; @override - String toString() { - return '${super.toString()}, x: $x, y: $y, z: $z'; - } + String toString() => '${super.toString()}, x: $x, y: $y, z: $z'; } /// An event of type [MovisensBluetoothCharacteristics.met] @@ -433,9 +414,7 @@ class MetEvent extends MovisensEvent { int get met => _met; @override - String toString() { - return '${super.toString()}, Met: $met'; - } + String toString() => '${super.toString()}, Met: $met'; } /// An event of type [MovisensBluetoothCharacteristics.metLevel] @@ -487,9 +466,8 @@ class MetLevelEvent extends MovisensEvent { int get vigorous => _vigorous; @override - String toString() { - return '${super.toString()}, Sedentary: $sedentary, Light: $light, Moderate: $moderate, Vigorous: $vigorous'; - } + String toString() => + '${super.toString()}, Sedentary: $sedentary, Light: $light, Moderate: $moderate, Vigorous: $vigorous'; } /// An event of type [MovisensBluetoothCharacteristics.movementAcceleration] @@ -520,9 +498,8 @@ class MovementAccelerationEvent extends MovisensEvent { double get movementAcceleration => _movementAcceleration; @override - String toString() { - return '${super.toString()}, MovementAcceleration: $movementAcceleration'; - } + String toString() => + '${super.toString()}, MovementAcceleration: $movementAcceleration'; } /// An event of type [MovisensBluetoothCharacteristics.steps] @@ -547,9 +524,7 @@ class StepsEvent extends MovisensEvent { int get steps => _steps; @override - String toString() { - return '${super.toString()}, Steps: $steps'; - } + String toString() => '${super.toString()}, Steps: $steps'; } /// An event of type [MovisensBluetoothCharacteristics.respiratoryMovement] @@ -573,12 +548,10 @@ class RespiratoryMovementEvent extends MovisensEvent { int get values => _values; @override - String toString() { - return '${super.toString()}, Values: $values'; - } + String toString() => '${super.toString()}, Values: $values'; } -/// Enum for Command result +/// Movisens command results. enum CommandResult { ok, notStartedBatteryLow, @@ -633,9 +606,8 @@ class CommandResultEvent extends MovisensEvent { CommandResult get commandResult => _commandResult; @override - String toString() { - return '${super.toString()}, Command Result: ${enumToReadableString(commandResult)}'; - } + String toString() => + '${super.toString()}, Command Result: ${enumToReadableString(commandResult)}'; } /// An event of type [MovisensBluetoothCharacteristics.dataAvailable] @@ -658,9 +630,7 @@ class DataAvailableEvent extends MovisensEvent { bool get dataAvailable => _dataAvailable; @override - String toString() { - return '${super.toString()}, Data Available: $dataAvailable'; - } + String toString() => '${super.toString()}, Data Available: $dataAvailable'; } /// An event of type [MovisensBluetoothCharacteristics.measurementEnabled] @@ -683,13 +653,13 @@ class MeasurementEnabledEvent extends MovisensEvent { bool get measurementEnabled => _measurementEnabled; @override - String toString() { - return '${super.toString()}, Measurement Enabled: $measurementEnabled'; - } + String toString() => + '${super.toString()}, Measurement Enabled: $measurementEnabled'; } /// Status of the measurement enum MeasurementStatus { + unknown, stoppedDurationReached, stoppedUserUsb, stoppedBatteryEmpty, @@ -751,9 +721,8 @@ class MeasurementStatusEvent extends MovisensEvent { MeasurementStatus get measurementStatus => _measurementStatus; @override - String toString() { - return '${super.toString()}, Measurement Status: ${enumToReadableString(measurementStatus)}'; - } + String toString() => + '${super.toString()}, Measurement Status: ${enumToReadableString(measurementStatus)}'; } /// An event of type [MovisensBluetoothCharacteristics.storageLevel] @@ -776,9 +745,7 @@ class StorageLevelEvent extends MovisensEvent { int get storageLevel => _storageLevel; @override - String toString() { - return '${super.toString()}, Storage Level: $storageLevel'; - } + String toString() => '${super.toString()}, Storage Level: $storageLevel'; } /// An event of type [MovisensBluetoothCharacteristics.skinTemperature] @@ -799,14 +766,12 @@ class SkinTemperatureEvent extends MovisensEvent { MovisensBluetoothCharacteristics type = MovisensBluetoothCharacteristics.skinTemperature; - /// Temperature of the skin. - /// Measured in Celcius (C) + /// Temperature of the skin in Celcius (C). double get skinTemperature => _skinTemperature; @override - String toString() { - return '${super.toString()}, Skin Temperature: $skinTemperature'; - } + String toString() => + '${super.toString()}, Skin Temperature: $skinTemperature'; } /// An event of type [MovisensBluetoothCharacteristics.heartRateMeasurement] @@ -828,14 +793,11 @@ class HeartRateMeasurementEvent extends MovisensEvent { MovisensBluetoothCharacteristics type = MovisensBluetoothCharacteristics.heartRateMeasurement; - /// The calculated heart rate at the time - /// in beats per minute. + /// The calculated heart rate at the time in beats per minute. int get heartRateMeasurement => _heartRateMeasurement; @override - String toString() { - return '${super.toString()}, Heart Rate Measurement: $heartRateMeasurement beats per minute'; - } + String toString() => '${super.toString()}, HR: $heartRateMeasurement BPM'; } /// An event of type [MovisensBluetoothCharacteristics.batteryLevel] @@ -858,7 +820,5 @@ class BatteryLevelEvent extends MovisensEvent { int get batteryLevel => _batteryLevel; @override - String toString() { - return '${super.toString()}, Battery Level: $batteryLevel%'; - } + String toString() => '${super.toString()}, Battery Level: $batteryLevel%'; } diff --git a/packages/movisens_flutter/lib/movisens_service.dart b/packages/movisens_flutter/lib/movisens_service.dart index b94b9d554..9c467e221 100644 --- a/packages/movisens_flutter/lib/movisens_service.dart +++ b/packages/movisens_flutter/lib/movisens_service.dart @@ -26,31 +26,34 @@ enum MovisensServiceTypes { /// A basic Movisens service interface. abstract class MovisensService { /// UUID of this service. - abstract final String uuid; + abstract String uuid; /// The underlying [BluetoothService] for this service. - late BluetoothService _bluetoothService; + BluetoothService service; + // BluetoothService? service; /// The list of Bluetooth characteristics for this service. abstract List characteristics; /// The string representation of the service enum. String get name => serviceUUIDToName[uuid]!.name; + + MovisensService({required this.service}); } /// A basic Movisens service interface with a stream for streamed events. abstract class StreamingMovisensService extends MovisensService { // Stream of [MovisensEvent]s - late Stream _events; + Stream? _events; /// A stream of all the [MovisensEvent]s emitted by the characteristics in this service. - Stream get events => _events; + Stream get events => _events ?? const Stream.empty(); + + StreamingMovisensService({required super.service}); /// Enables the notifying of ***every*** bluetooth characteristic in this service. - /// Future enableNotify() async { - for (BluetoothCharacteristic characteristic - in _bluetoothService.characteristics) { + for (BluetoothCharacteristic characteristic in service.characteristics) { String charUuid = characteristic.uuid.toString(); MovisensBluetoothCharacteristics? moviChar = characteristicUUIDToMovisensBluetoothCharacteristics[charUuid]; @@ -58,15 +61,14 @@ abstract class StreamingMovisensService extends MovisensService { characteristic.properties.notify) { await characteristic.setNotifyValue(true); _log.info( - "Enabling [Notify] for [${enumToReadableString(characteristicUUIDToMovisensBluetoothCharacteristics[characteristic.uuid.toString()]!)}] in service [${enumToReadableString(serviceUUIDToName[uuid]!)}] Movisens device [${_bluetoothService.remoteId.str}]"); + "Enabling [Notify] for [${enumToReadableString(characteristicUUIDToMovisensBluetoothCharacteristics[characteristic.uuid.toString()]!)}] in service [${enumToReadableString(serviceUUIDToName[uuid]!)}] Movisens device [${service.remoteId.str}]"); } } } /// Disables the notifying of all bluetooth characteristic in this service. Future disableNotify() async { - for (BluetoothCharacteristic characteristic - in _bluetoothService.characteristics) { + for (BluetoothCharacteristic characteristic in service.characteristics) { String charUuid = characteristic.uuid.toString(); MovisensBluetoothCharacteristics? moviChar = characteristicUUIDToMovisensBluetoothCharacteristics[charUuid]; @@ -74,7 +76,7 @@ abstract class StreamingMovisensService extends MovisensService { characteristic.properties.notify) { await characteristic.setNotifyValue(false); _log.info( - "Disabling [Notify] for [${enumToReadableString(characteristicUUIDToMovisensBluetoothCharacteristics[characteristic.uuid.toString()]!)}] in service [${enumToReadableString(serviceUUIDToName[uuid]!)}] Movisens device [${_bluetoothService.remoteId.str}]"); + "Disabling [Notify] for [${enumToReadableString(characteristicUUIDToMovisensBluetoothCharacteristics[characteristic.uuid.toString()]!)}] in service [${enumToReadableString(serviceUUIDToName[uuid]!)}] Movisens device [${service.remoteId.str}]"); } } } @@ -111,11 +113,11 @@ class AmbientService extends StreamingMovisensService { _sensorTemperatureEvents; /// A Movisens service containing Ambient data. - AmbientService({required BluetoothService service}) { - _bluetoothService = service; + AmbientService({required super.service}) { + // service = service; List> nonNullStreams = []; // For each characteristic that is supported in the service - for (BluetoothCharacteristic char in _bluetoothService.characteristics) { + for (BluetoothCharacteristic char in service.characteristics) { String charUuid = char.uuid.toString(); MovisensBluetoothCharacteristics? moviChar = characteristicUUIDToMovisensBluetoothCharacteristics[charUuid]; @@ -124,8 +126,8 @@ class AmbientService extends StreamingMovisensService { if (moviChar == MovisensBluetoothCharacteristics.light) { _lightEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) - .map((event) => LightEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + .map((event) => + LightEvent(bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_lightEvents!); } @@ -133,8 +135,8 @@ class AmbientService extends StreamingMovisensService { else if (moviChar == MovisensBluetoothCharacteristics.lightRGB) { _lightRGBEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) - .map((event) => LightRGBEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + .map((event) => + LightRGBEvent(bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_lightRGBEvents!); } // add sensor temperature stream @@ -142,7 +144,7 @@ class AmbientService extends StreamingMovisensService { _sensorTemperatureEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) .map((event) => SensorTemperatureEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_sensorTemperatureEvents!); } @@ -172,10 +174,9 @@ class EdaService extends StreamingMovisensService { Stream? get edaSclMeanEvents => _edaSclMeanEvents; /// A Movisens service containing EDA (Electrodermal Activity) data. - EdaService({required BluetoothService service}) { - _bluetoothService = service; + EdaService({required super.service}) { List> nonNullStreams = []; - for (BluetoothCharacteristic char in _bluetoothService.characteristics) { + for (BluetoothCharacteristic char in service.characteristics) { String charUuid = char.uuid.toString(); MovisensBluetoothCharacteristics? moviChar = characteristicUUIDToMovisensBluetoothCharacteristics[charUuid]; @@ -184,8 +185,8 @@ class EdaService extends StreamingMovisensService { if (moviChar == MovisensBluetoothCharacteristics.edaSclMean) { _edaSclMeanEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) - .map((event) => EdaSclMeanEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + .map((event) => + EdaSclMeanEvent(bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_edaSclMeanEvents!); } @@ -218,7 +219,7 @@ class HrvService extends StreamingMovisensService { characteristic.properties.notify) { await characteristic.setNotifyValue(true); _log.info( - "Enabling [Notify] for [${enumToReadableString(characteristicUUIDToMovisensBluetoothCharacteristics[characteristic.uuid.toString()]!)}] in service [${enumToReadableString(serviceUUIDToName[uuid]!)}] Movisens device [${_bluetoothService.remoteId.str}]"); + "Enabling [Notify] for [${enumToReadableString(characteristicUUIDToMovisensBluetoothCharacteristics[characteristic.uuid.toString()]!)}] in service [${enumToReadableString(serviceUUIDToName[uuid]!)}] Movisens device [${service.remoteId.str}]"); } } } @@ -235,7 +236,7 @@ class HrvService extends StreamingMovisensService { characteristic.properties.notify) { await characteristic.setNotifyValue(false); _log.info( - "Disabling [Notify] for [${enumToReadableString(characteristicUUIDToMovisensBluetoothCharacteristics[characteristic.uuid.toString()]!)}] in service [${enumToReadableString(serviceUUIDToName[uuid]!)}] Movisens device [${_bluetoothService.remoteId.str}]"); + "Disabling [Notify] for [${enumToReadableString(characteristicUUIDToMovisensBluetoothCharacteristics[characteristic.uuid.toString()]!)}] in service [${enumToReadableString(serviceUUIDToName[uuid]!)}] Movisens device [${service.remoteId.str}]"); } } } @@ -269,12 +270,10 @@ class HrvService extends StreamingMovisensService { _heartRateMeasurementEvents; /// A Movisens service containing HRV related data. - HrvService( - {required BluetoothService service, BluetoothService? secondaryService}) { - _bluetoothService = service; + HrvService({required super.service, BluetoothService? secondaryService}) { List> nonNullStreams = []; // For each characteristic that is supported in the service - for (BluetoothCharacteristic char in _bluetoothService.characteristics) { + for (BluetoothCharacteristic char in service.characteristics) { String charUuid = char.uuid.toString(); MovisensBluetoothCharacteristics? moviChar = characteristicUUIDToMovisensBluetoothCharacteristics[charUuid]; @@ -283,8 +282,8 @@ class HrvService extends StreamingMovisensService { if (moviChar == MovisensBluetoothCharacteristics.hrMean) { _hrMeanEvents = char.lastValueStream .skipWhile((element) => (element.isEmpty)) - .map((event) => HrMeanEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + .map((event) => + HrMeanEvent(bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_hrMeanEvents!); } @@ -292,16 +291,16 @@ class HrvService extends StreamingMovisensService { else if (moviChar == MovisensBluetoothCharacteristics.hrvIsValid) { _hrvIsValidEvents = char.lastValueStream .skipWhile((element) => (element.isEmpty)) - .map((event) => HrvIsValidEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + .map((event) => + HrvIsValidEvent(bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_hrvIsValidEvents!); } // add rmssd stream else if (moviChar == MovisensBluetoothCharacteristics.rmssd) { _rmssdEvents = char.lastValueStream .skipWhile((element) => (element.isEmpty)) - .map((event) => RmssdEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + .map((event) => + RmssdEvent(bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_rmssdEvents!); } @@ -317,7 +316,7 @@ class HrvService extends StreamingMovisensService { _heartRateMeasurementEvents = char.lastValueStream .skipWhile((element) => (element.isEmpty)) .map((event) => HeartRateMeasurementEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_heartRateMeasurementEvents!); } @@ -347,11 +346,10 @@ class MarkerService extends StreamingMovisensService { Stream? get tapMarkerEvents => _tapMarkerEvents; /// A Movisens service containing marker data from user taps. - MarkerService({required BluetoothService service}) { - _bluetoothService = service; + MarkerService({required super.service}) { List> nonNullStreams = []; // For each characteristic that is supported in the service - for (BluetoothCharacteristic char in _bluetoothService.characteristics) { + for (BluetoothCharacteristic char in service.characteristics) { String charUuid = char.uuid.toString(); MovisensBluetoothCharacteristics? moviChar = characteristicUUIDToMovisensBluetoothCharacteristics[charUuid]; @@ -360,8 +358,8 @@ class MarkerService extends StreamingMovisensService { if (moviChar == MovisensBluetoothCharacteristics.tapMarker) { _tapMarkerEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) - .map((event) => TapMarkerEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + .map((event) => + TapMarkerEvent(bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_tapMarkerEvents!); } @@ -399,7 +397,7 @@ class BatteryService extends StreamingMovisensService { characteristic.properties.notify) { await characteristic.setNotifyValue(true); _log.info( - "Enabling [Notify] for [${enumToReadableString(characteristicUUIDToMovisensBluetoothCharacteristics[characteristic.uuid.toString()]!)}] in service [${enumToReadableString(serviceUUIDToName[uuid]!)}] Movisens device [${_bluetoothService.remoteId.str}]"); + "Enabling [Notify] for [${enumToReadableString(characteristicUUIDToMovisensBluetoothCharacteristics[characteristic.uuid.toString()]!)}] in service [${enumToReadableString(serviceUUIDToName[uuid]!)}] Movisens device [${service.remoteId.str}]"); } } } @@ -416,7 +414,7 @@ class BatteryService extends StreamingMovisensService { characteristic.properties.notify) { await characteristic.setNotifyValue(false); _log.info( - "Disabling [Notify] for [${enumToReadableString(characteristicUUIDToMovisensBluetoothCharacteristics[characteristic.uuid.toString()]!)}] in service [${enumToReadableString(serviceUUIDToName[uuid]!)}] Movisens device [${_bluetoothService.remoteId.str}]"); + "Disabling [Notify] for [${enumToReadableString(characteristicUUIDToMovisensBluetoothCharacteristics[characteristic.uuid.toString()]!)}] in service [${enumToReadableString(serviceUUIDToName[uuid]!)}] Movisens device [${service.remoteId.str}]"); } } } @@ -431,12 +429,10 @@ class BatteryService extends StreamingMovisensService { Stream? get batteryLevelEvents => _batteryLevelEvents; /// A Movisens service containing Battery data. - BatteryService( - {required BluetoothService service, BluetoothService? secondaryService}) { - _bluetoothService = service; + BatteryService({required super.service, BluetoothService? secondaryService}) { List> nonNullStreams = []; // For each characteristic that is supported in the service - for (BluetoothCharacteristic char in _bluetoothService.characteristics) { + for (BluetoothCharacteristic char in service.characteristics) { String charUuid = char.uuid.toString(); MovisensBluetoothCharacteristics? moviChar = characteristicUUIDToMovisensBluetoothCharacteristics[charUuid]; @@ -445,8 +441,8 @@ class BatteryService extends StreamingMovisensService { if (moviChar == MovisensBluetoothCharacteristics.charging) { _chargingEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) - .map((event) => ChargingEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + .map((event) => + ChargingEvent(bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_chargingEvents!); } @@ -464,8 +460,8 @@ class BatteryService extends StreamingMovisensService { if (moviChar == MovisensBluetoothCharacteristics.batteryLevel) { _batteryLevelEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) - .map((event) => BatteryLevelEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + .map((event) => + BatteryLevelEvent(bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_batteryLevelEvents!); } @@ -601,7 +597,7 @@ class UserDataService extends MovisensService { _log.warning("Sensor Location characteristic not found on device"); return; } - late int sLoc; + int sLoc; switch (sensorLocation) { case SensorLocation.rightSideHip: sLoc = 1; @@ -737,9 +733,8 @@ class UserDataService extends MovisensService { } UserDataService( - {required BluetoothService service, BluetoothService? secondaryService}) { - _bluetoothService = service; - for (BluetoothCharacteristic char in _bluetoothService.characteristics) { + {required super.service, BluetoothService? secondaryService}) { + for (BluetoothCharacteristic char in service.characteristics) { String charUuid = char.uuid.toString(); MovisensBluetoothCharacteristics? moviChar = characteristicUUIDToMovisensBluetoothCharacteristics[charUuid]; @@ -829,11 +824,10 @@ class PhysicalActivityService extends StreamingMovisensService { /// Stream of [StepsEvent]s. Stream? get stepsEvents => _stepsEvents; - PhysicalActivityService({required BluetoothService service}) { - _bluetoothService = service; + PhysicalActivityService({required super.service}) { List> nonNullStreams = []; // For each characteristic that is supported in the service - for (BluetoothCharacteristic char in _bluetoothService.characteristics) { + for (BluetoothCharacteristic char in service.characteristics) { String charUuid = char.uuid.toString(); MovisensBluetoothCharacteristics? moviChar = characteristicUUIDToMovisensBluetoothCharacteristics[charUuid]; @@ -842,32 +836,32 @@ class PhysicalActivityService extends StreamingMovisensService { if (moviChar == MovisensBluetoothCharacteristics.bodyPosition) { _bodyPositionEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) - .map((event) => BodyPositionEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + .map((event) => + BodyPositionEvent(bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_bodyPositionEvents!); } // add inclination stream else if (moviChar == MovisensBluetoothCharacteristics.inclination) { _inclinationEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) - .map((event) => InclinationEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + .map((event) => + InclinationEvent(bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_inclinationEvents!); } // add MET stream else if (moviChar == MovisensBluetoothCharacteristics.met) { _metEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) - .map((event) => MetEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + .map((event) => + MetEvent(bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_metEvents!); } // add METLevel stream else if (moviChar == MovisensBluetoothCharacteristics.metLevel) { _metLevelEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) - .map((event) => MetLevelEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + .map((event) => + MetLevelEvent(bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_metLevelEvents!); } // add movementAcceleration stream @@ -876,15 +870,15 @@ class PhysicalActivityService extends StreamingMovisensService { _movementAccelerationEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) .map((event) => MovementAccelerationEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_movementAccelerationEvents!); } // add steps stream else if (moviChar == MovisensBluetoothCharacteristics.steps) { _stepsEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) - .map((event) => StepsEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + .map((event) => + StepsEvent(bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_stepsEvents!); } @@ -914,11 +908,10 @@ class RespirationService extends StreamingMovisensService { Stream? get respiratoryMovementEvents => _respiratoryMovementEvents; - RespirationService({required BluetoothService service}) { - _bluetoothService = service; + RespirationService({required super.service}) { List> nonNullStreams = []; // For each characteristic that is supported in the service - for (BluetoothCharacteristic char in _bluetoothService.characteristics) { + for (BluetoothCharacteristic char in service.characteristics) { String charUuid = char.uuid.toString(); MovisensBluetoothCharacteristics? moviChar = characteristicUUIDToMovisensBluetoothCharacteristics[charUuid]; @@ -928,7 +921,7 @@ class RespirationService extends StreamingMovisensService { _respiratoryMovementEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) .map((event) => RespiratoryMovementEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_respiratoryMovementEvents!); } @@ -1017,11 +1010,10 @@ class SensorControlService extends StreamingMovisensService { // BluetoothCharacteristic? _activatedBufferedCharacteristics; TODO: Missing documentation from movisens - request it // BluetoothCharacteristic? _customData; TODO: Possibly support in future version - SensorControlService({required BluetoothService service}) { - _bluetoothService = service; + SensorControlService({required super.service}) { List> nonNullStreams = []; // For each characteristic that is supported in the service - for (BluetoothCharacteristic char in _bluetoothService.characteristics) { + for (BluetoothCharacteristic char in service.characteristics) { String charUuid = char.uuid.toString(); MovisensBluetoothCharacteristics? moviChar = characteristicUUIDToMovisensBluetoothCharacteristics[charUuid]; @@ -1035,7 +1027,7 @@ class SensorControlService extends StreamingMovisensService { _commandResultEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) .map((event) => CommandResultEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_commandResultEvents!); break; @@ -1047,7 +1039,7 @@ class SensorControlService extends StreamingMovisensService { _dataAvailableEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) .map((event) => DataAvailableEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_dataAvailableEvents!); break; @@ -1058,7 +1050,7 @@ class SensorControlService extends StreamingMovisensService { _measurementEnabledEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) .map((event) => MeasurementEnabledEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_measurementEnabledEvents!); _measurementEnabled = char; @@ -1071,7 +1063,7 @@ class SensorControlService extends StreamingMovisensService { _measurementStatusEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) .map((event) => MeasurementStatusEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_measurementStatusEvents!); break; @@ -1092,7 +1084,7 @@ class SensorControlService extends StreamingMovisensService { _storageLevelEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) .map((event) => StorageLevelEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_storageLevelEvents!); break; @@ -1224,7 +1216,7 @@ class SensorControlService extends StreamingMovisensService { List bytes = await _measurementStatus!.read(); ByteData byteData = ByteData.sublistView(Uint8List.fromList(bytes)); int measurementStatus = byteData.getUint8(0); - late MeasurementStatus mStatus; + MeasurementStatus mStatus = MeasurementStatus.unknown; switch (measurementStatus) { case 1: mStatus = MeasurementStatus.stoppedDurationReached; @@ -1397,11 +1389,10 @@ class SkinTemperatureService extends StreamingMovisensService { Stream? get skinTemperatureEvents => _skinTemperatureEvents; - SkinTemperatureService({required BluetoothService service}) { - _bluetoothService = service; + SkinTemperatureService({required super.service}) { List> nonNullStreams = []; // For each characteristic that is supported in the service - for (BluetoothCharacteristic char in _bluetoothService.characteristics) { + for (BluetoothCharacteristic char in service.characteristics) { String charUuid = char.uuid.toString(); MovisensBluetoothCharacteristics? moviChar = characteristicUUIDToMovisensBluetoothCharacteristics[charUuid]; @@ -1411,7 +1402,7 @@ class SkinTemperatureService extends StreamingMovisensService { _skinTemperatureEvents = char.lastValueStream .skipWhile((element) => element.isEmpty) .map((event) => SkinTemperatureEvent( - bytes: event, deviceId: _bluetoothService.remoteId.str)) + bytes: event, deviceId: service.remoteId.str)) .asBroadcastStream(); nonNullStreams.add(_skinTemperatureEvents!); } @@ -1444,10 +1435,9 @@ class DeviceInformationService extends MovisensService { BluetoothCharacteristic? _modelNumberString; BluetoothCharacteristic? _serialNumberString; - DeviceInformationService({required BluetoothService service}) { - _bluetoothService = service; + DeviceInformationService({required super.service}) { // For each characteristic that is supported in the service - for (BluetoothCharacteristic char in _bluetoothService.characteristics) { + for (BluetoothCharacteristic char in service.characteristics) { String charUuid = char.uuid.toString(); MovisensBluetoothCharacteristics? moviChar = characteristicUUIDToMovisensBluetoothCharacteristics[charUuid]; diff --git a/packages/movisens_flutter/pubspec.yaml b/packages/movisens_flutter/pubspec.yaml index 2394b98d5..7d2d0b9f6 100644 --- a/packages/movisens_flutter/pubspec.yaml +++ b/packages/movisens_flutter/pubspec.yaml @@ -1,6 +1,6 @@ name: movisens_flutter description: A Flutter plugin for Movisens devices, which connects to the device and listens for incoming data. -version: 3.1.1 +version: 3.1.2 homepage: https://github.com/cph-cachet/flutter-plugins/tree/master/packages/movisens_flutter environment: