Open ivs opened 2 years ago
Could you post flutter doctor -v
?
Try DebugView if you need OutputDebugString
result, for example:
> flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 2.10.4, on Microsoft Windows [Version 10.0.22000.613], locale ru-RU)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[√] Chrome - develop for the web
[√] Visual Studio - develop for Windows (Visual Studio Community 2019 16.11.9)
[√] Android Studio (version 2020.3)
[√] VS Code (version 1.66.2)
[√] Connected device (3 available)
! Device emulator-5562 is offline.
[√] HTTP Host Availability
• No issues found!
DebugView logs:
[39572] HandleMethodCall startScan
[39572] Received BluetoothAddress:207251698759179, Name:Bluetooth bc:7e:8b:e2:36:0b, LocalName:
[39572] Received BluetoothAddress:207251698759179, Name:Bluetooth bc:7e:8b:e2:36:0b, LocalName:
[39572] Received BluetoothAddress:207251698759179, Name:Bluetooth bc:7e:8b:e2:36:0b, LocalName:
[39572] Received BluetoothAddress:207251698759179, Name:Bluetooth bc:7e:8b:e2:36:0b, LocalName:
[39572] Received BluetoothAddress:207251698759179, Name:Bluetooth bc:7e:8b:e2:36:0b, LocalName:
[39572] Received BluetoothAddress:257642978838462, Name:Mi Band 3, LocalName:
[39572] HandleMethodCall stopScan
[39572] HandleMethodCall connect
[39572] HandleMethodCall discoverServices
[39572] HandleMethodCall setNotifiable
[39572] HandleMethodCall writeValue
[39572] ConnectionStatusChanged 1
Is setNotifiable with BleInputProperty.notification the same as writing 0x01 to 0x2902 descriptor?
I think so according to Android implementation of setNotifiable
QuickBlue.setNotifiable(deviceId, SERVICE_MIBAND2, CHARACTERISTIC_AUTH, BleInputProperty.notification); QuickBlue.writeValue(deviceId, SERVICE_MIBAND2, CHARACTERISTIC_AUTH, Uint8List.fromList(key_cmd + key), BleOutputProperty.withResponse);
You'd better await the result
await QuickBlue.setNotifiable(deviceId, SERVICE_MIBAND2, CHARACTERISTIC_AUTH,
BleInputProperty.notification);
await QuickBlue.writeValue(deviceId, SERVICE_MIBAND2, CHARACTERISTIC_AUTH,
Uint8List.fromList(key_cmd + key), BleOutputProperty.withResponse);
QuickBlue.discoverServices(deviceId); QuickBlue.setNotifiable(deviceId, SERVICE_MIBAND2, CHARACTERISTIC_AUTH, BleInputProperty.notification); QuickBlue.writeValue(deviceId, SERVICE_MIBAND2, CHARACTERISTIC_AUTH, Uint8List.fromList(key_cmd + key), BleOutputProperty.withResponse);
Try this on Android before Windows. Android BLE is much reasonable
The same crash with await. I've tried to debug plugin with Visual Studio, found out this method: https://stackoverflow.com/questions/71406447/flutter-desktop-windows-plugin-debug-native-c-code I copied my code into quick_blue_example app and attach VS debugger, it gives me this stack trace: Maybe it helps.
Seems I'm unlucky user:) Android code do not work at all, my device Realme SuperZoom, RMX2086. QuickBlue.scanResultStream.listen lamda do not called neither in my app nor in quick_blue_example app(windows build works just fine), this breakpoint never stops:
If you point me how, I can debug android and windows code.
Could you try below APPs on Android as peripheral?
Finally I resolved all my issues! Android code didn't work because of permissions. Complete list of permission for AndroidManifest.xml
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
I got permissions exception on another phone TECNO CC7 and I have to give Location permission manually in App Info.
The crash reproduced on Android too. I've fixed it by adding await and delays. It seems my device needs some time to respond and without delays it disconnected and cause library crash.
This code works both on Windows and Android:
void mibandAuth(String deviceId) async {
await QuickBlue.setNotifiable(deviceId, SERVICE_MIBAND2,
CHARACTERISTIC_AUTH, BleInputProperty.notification);
await Future.delayed(const Duration(seconds: 1));
await QuickBlue.writeValue(deviceId, SERVICE_MIBAND2, CHARACTERISTIC_AUTH,
Uint8List.fromList(key_cmd + key), BleOutputProperty.withoutResponse);
await Future.delayed(const Duration(seconds: 1));
}
void handleConnection(String deviceId, BlueConnectionState state) {
d.log('handleConnection $deviceId');
if (defaultTargetPlatform != TargetPlatform.windows) {
QuickBlue.discoverServices(deviceId);
} else {
mibandAuth(deviceId);
}
}
void handleService(String deviceId, String serviceId) {
d.log('handleService $serviceId');
if (serviceId == SERVICE_MIBAND2) {
mibandAuth(deviceId);
}
}
void handleValue(String deviceId, String characteristicId, Uint8List value) {
d.log('handleValue $characteristicId $value');
}
@override
void initState() {
super.initState();
QuickBlue.setConnectionHandler(handleConnection);
QuickBlue.setServiceHandler(handleService);
QuickBlue.setValueHandler(handleValue);
QuickBlue.isBluetoothAvailable();
QuickBlue.scanResultStream.listen((result) {
d.log('onScanResult ' + result.name);
if (result.name == "Mi Band 3" && !bandFound) {
bandFound = true;
QuickBlue.stopScan();
QuickBlue.connect(result.deviceId);
}
});
QuickBlue.startScan();
}
Is this right way to use library? If it so I can make an example from it to library README.md.
Android code didn't work because of permissions. Complete list of permission for AndroidManifest.xml
https://github.com/woodemi/quick_blue/commit/e907904bfc10163f32e345577d5151d8de7b824a is here
I don't think <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
is needed
void mibandAuth(String deviceId) async { await QuickBlue.setNotifiable(deviceId, SERVICE_MIBAND2, CHARACTERISTIC_AUTH, BleInputProperty.notification); await Future.delayed(const Duration(seconds: 1)); await QuickBlue.writeValue(deviceId, SERVICE_MIBAND2, CHARACTERISTIC_AUTH, Uint8List.fromList(key_cmd + key), BleOutputProperty.withoutResponse); await Future.delayed(const Duration(seconds: 1)); }
When using with our product authentication on Windows, Future.delayed
is not needed. Maybe a debug vs profile/release problem?
I got permissions exception on another phone TECNO CC7 and I have to give Location permission manually in App Info.
If it so I can make an example from it to library README.md.
Agreed. Location permission
on pre-Android-12 is quite cumbersome and needs documentation
Hello,
I got the same error, when I use writeValue on Windows with more than 233 chracters. By 234 characters the app is crashing with Exited (sigterm)
That's why I chunk my data into 233 characters and send them to device as follows:
var chunks = _chunkData(data, 233);
for (var chunk in chunks) {
await QuickBlue.writeValue(
address,
"49535343-fe7d-4ae5-8fa9-9fafd205e455",
"49535343-8841-43f4-a8d4-ecbe34729bb3",
Uint8List.fromList(chunk),
BleOutputProperty.withoutResponse,
);
await Future.delayed(Duration(milliseconds: 250)); // this delay is only necessary on windows
}
static _chunkData(List<int> list, int chunkSize) {
var chunks = [];
for (var i = 0; i < list.length; i += chunkSize) {
chunks.add(list.sublist(i, i + chunkSize > list.length ? list.length : i + chunkSize));
}
return chunks;
}
The code above works perfectly on Android, IOS and MacOS. However on Windows, if I do not wait the tread, although I await the writeValue call, the chunks will not be received in the same order. For example, the second chunk will be printed before the first chunk. I beleive the function writeValue on Windows is not really async.
The questions here are, why the characters I can send to the device is limited on all platforms? why writeValue is not behaving as a real async function on windows?
Is there anything better I can try?
Thank you!
Some useful doc
Thank you for the quick answer and links.
I really don't understand what requestMtu
is or whether I should call it before calling writeValue method.
I have seen that the WriteValueAsync method is not awaited. Could this be the reason of the problem which is the data not received in the same order I send it via writeValue?
I got the same error, when I use writeValue on Windows with more than 233 chracters. By 234 characters the app is crashing with Exited (sigterm)
That is what MTU means
I have seen that the WriteValueAsync method is not awaited. Could this be the reason of the problem which is the data not received in the same order I send it via writeValue?
We're considering add onValuteWrite
notification https://github.com/woodemi/quick.flutter/pull/36
Nice idea! When are you planing to merge the PR?
I haven't seen the window implementation. Have I missed it?
@ivs The delay worked! Thanks!
Hi! This code gives me sigterm on Windows:
The output:
How I can debug it? I'm new to BLE maybe I do something wrong. I'm trying to port this project: https://github.com/4lhc/MiBand_HRX/blob/master/base.py#L103
Is setNotifiable with BleInputProperty.notification the same as writing 0x01 to 0x2902 descriptor?
There's no crash if I set BleOutputProperty.withoutResponse for writeValue but no response from device too.