Fix characteristic value listener and add tests (#168)
* Improve characteristic value listener * Implement characteristic tests * Bump version and update changelog
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
## 0.20.2
|
||||
* Fix `BleCharacteristic.onValueReceived`
|
||||
|
||||
## 0.20.1
|
||||
* Fix `writeWithoutResponse()` which was not properly waiting for completion on Android and Apple
|
||||
|
||||
|
||||
@@ -402,7 +402,7 @@ packages:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.20.0"
|
||||
version: "0.20.1"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -94,10 +94,14 @@ abstract class UniversalBlePlatform {
|
||||
.map((e) => e.isConnected);
|
||||
|
||||
Stream<Uint8List> characteristicValueStream(
|
||||
String deviceId, String characteristicId) =>
|
||||
_valueStreamController.stream.where((e) {
|
||||
return e.deviceId == deviceId && e.characteristicId == characteristicId;
|
||||
}).map((e) => e.value);
|
||||
String deviceId,
|
||||
String characteristicId,
|
||||
) {
|
||||
characteristicId = BleUuidParser.string(characteristicId);
|
||||
return _valueStreamController.stream.where((e) {
|
||||
return e.deviceId == deviceId && e.characteristicId == characteristicId;
|
||||
}).map((e) => e.value);
|
||||
}
|
||||
|
||||
Stream<bool> pairingStateStream(String deviceId) =>
|
||||
_pairStateStreamController.stream
|
||||
@@ -134,15 +138,14 @@ abstract class UniversalBlePlatform {
|
||||
String characteristicId,
|
||||
Uint8List value,
|
||||
) {
|
||||
characteristicId = BleUuidParser.string(characteristicId);
|
||||
_valueStreamController.add((
|
||||
deviceId: deviceId,
|
||||
characteristicId: characteristicId,
|
||||
value: value,
|
||||
));
|
||||
|
||||
try {
|
||||
onValueChange?.call(
|
||||
deviceId, BleUuidParser.string(characteristicId), value);
|
||||
onValueChange?.call(deviceId, characteristicId, value);
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
name: universal_ble
|
||||
description: A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE) plugin for Flutter
|
||||
version: 0.20.1
|
||||
version: 0.20.2
|
||||
homepage: https://navideck.com
|
||||
repository: https://github.com/Navideck/universal_ble
|
||||
issue_tracker: https://github.com/Navideck/universal_ble/issues
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:universal_ble/universal_ble.dart';
|
||||
import 'universal_ble_test_mock.dart';
|
||||
|
||||
String serviceId = "180a";
|
||||
String characteristicId = "202a";
|
||||
String mockDeviceId = "mock_id";
|
||||
BleCharacteristic mockBleCharacteristic = BleCharacteristic.withMetaData(
|
||||
deviceId: mockDeviceId,
|
||||
serviceId: serviceId,
|
||||
uuid: characteristicId,
|
||||
properties: CharacteristicProperty.values,
|
||||
);
|
||||
BleService mockBleService = BleService(serviceId, [mockBleCharacteristic]);
|
||||
|
||||
void main() {
|
||||
late UniversalBlePlatform platform;
|
||||
setUp(() {
|
||||
platform = _UniversalBleMock();
|
||||
UniversalBle.setInstance(platform);
|
||||
});
|
||||
|
||||
group('BleCharacteristic Tests', () {
|
||||
test("DiscoverServices test", () async {
|
||||
debugPrint("Discovering services");
|
||||
List<BleService> services =
|
||||
await UniversalBle.discoverServices(mockDeviceId);
|
||||
expect(services.length, 1);
|
||||
|
||||
BleService service = services.first;
|
||||
expect(BleUuidParser.compareStrings(service.uuid, serviceId), true);
|
||||
expect(service.characteristics.length, 1);
|
||||
|
||||
BleCharacteristic characteristic = service.characteristics.first;
|
||||
expect(
|
||||
BleUuidParser.compareStrings(characteristic.uuid, characteristicId),
|
||||
true,
|
||||
);
|
||||
expect(characteristic.metaData?.deviceId, mockDeviceId);
|
||||
expect(
|
||||
BleUuidParser.compareStrings(
|
||||
characteristic.metaData!.serviceId,
|
||||
serviceId,
|
||||
),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test("Subscription Test", () async {
|
||||
BleCharacteristic characteristic = mockBleCharacteristic;
|
||||
|
||||
debugPrint("Subscribing to char");
|
||||
await characteristic.notifications.subscribe();
|
||||
|
||||
bool gotEvent = false;
|
||||
var subscription = characteristic.notifications.listen((data) {
|
||||
debugPrint("Received CharValue: $data");
|
||||
gotEvent = true;
|
||||
});
|
||||
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
await characteristic.notifications.unsubscribe();
|
||||
debugPrint("Unsubscribed from char");
|
||||
|
||||
subscription.cancel();
|
||||
expect(gotEvent, true);
|
||||
});
|
||||
});
|
||||
|
||||
test("Write/Read Value Test", () async {
|
||||
BleCharacteristic characteristic = mockBleCharacteristic;
|
||||
Uint8List charValue = Uint8List.fromList([0x01, 0x02]);
|
||||
await characteristic.write(charValue);
|
||||
debugPrint("Write Succeed");
|
||||
|
||||
var readResult = await characteristic.read();
|
||||
debugPrint("Read Succeed");
|
||||
expect(readResult, charValue);
|
||||
});
|
||||
}
|
||||
|
||||
class _UniversalBleMock extends UniversalBlePlatformMock {
|
||||
Timer? notifierTimer;
|
||||
Uint8List? charValue;
|
||||
|
||||
@override
|
||||
Future<List<BleService>> discoverServices(String deviceId) async {
|
||||
return <BleService>[mockBleService];
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setNotifiable(String deviceId, String service,
|
||||
String characteristic, BleInputProperty bleInputProperty) async {
|
||||
if (bleInputProperty == BleInputProperty.disabled) {
|
||||
notifierTimer?.cancel();
|
||||
notifierTimer = null;
|
||||
return;
|
||||
}
|
||||
|
||||
notifierTimer ??= Timer.periodic(Duration(milliseconds: 500), (timer) {
|
||||
updateCharacteristicValue(
|
||||
deviceId,
|
||||
characteristic,
|
||||
Uint8List.fromList([1, 2, 3]),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeValue(
|
||||
String deviceId,
|
||||
String service,
|
||||
String characteristic,
|
||||
Uint8List value,
|
||||
BleOutputProperty bleOutputProperty) async {
|
||||
charValue = value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readValue(
|
||||
String deviceId, String service, String characteristic,
|
||||
{Duration? timeout}) async {
|
||||
return charValue ?? Uint8List(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
import 'dart:typed_data';
|
||||
import 'package:universal_ble/universal_ble.dart';
|
||||
|
||||
abstract class UniversalBlePlatformMock extends UniversalBlePlatform {
|
||||
@override
|
||||
Future<void> connect(String deviceId, {Duration? connectionTimeout}) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> disableBluetooth() {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> disconnect(String deviceId) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<BleService>> discoverServices(String deviceId) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> enableBluetooth() {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AvailabilityState> getBluetoothAvailabilityState() {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BleConnectionState> getConnectionState(String deviceId) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<BleDevice>> getSystemDevices(List<String>? withServices) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> isPaired(String deviceId) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> pair(String deviceId) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readValue(
|
||||
String deviceId, String service, String characteristic,
|
||||
{Duration? timeout}) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> requestMtu(String deviceId, int expectedMtu) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setNotifiable(String deviceId, String service,
|
||||
String characteristic, BleInputProperty bleInputProperty) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startScan(
|
||||
{ScanFilter? scanFilter, PlatformConfig? platformConfig}) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stopScan() {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> unpair(String deviceId) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeValue(
|
||||
String deviceId,
|
||||
String service,
|
||||
String characteristic,
|
||||
Uint8List value,
|
||||
BleOutputProperty bleOutputProperty) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user