Я разрабатываю приложение Flutter, в котором мне нужно подключить и связать устройство Bluetooth Low Energy (BLE) с телефоном. Я использую пакет flutter_blue для подключения Bluetooth. Хотя я могу сканировать устройства и подключаться к ним, я пытаюсь справиться с процессом связывания.
Вот фрагмент моего кода для сканирования и подключения к устройствам:
import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
class BluetoothLEManager extends StatefulWidget {
const BluetoothLEManager({Key? key}) : super(key: key);
@override
BluetoothLEManagerState createState() => BluetoothLEManagerState();
}
class BluetoothLEManagerState extends State<BluetoothLEManager> with SingleTickerProviderStateMixin {
FlutterBlue flutterBlue = FlutterBlue.instance;
List<BluetoothDevice> _devices = [];
bool _isSearching = false;
bool _scanCompleted = false;
@override
void initState() {
super.initState();
startBluetoothScan(isInitialScan: true);
}
@override
void dispose() {
flutterBlue.stopScan();
super.dispose();
}
void startBluetoothScan({bool isInitialScan = false}) {
if (_isSearching) return;
setState(() {
_isSearching = true;
_scanCompleted = false;
});
flutterBlue.startScan(timeout: const Duration(seconds: 10)).then((_) {
setState(() {
_isSearching = false;
_scanCompleted = true;
});
});
flutterBlue.scanResults.listen((results) {
setState(() {
_devices = results.map((r) => r.device).where((device) => device.name.isNotEmpty).toList();
});
});
flutterBlue.isScanning.listen((isScanning) {
if (!isScanning) {
print('Scanning stopped');
}
});
}
Future<void> connectToDevice(BluetoothDevice device) async {
await device.connect();
// further code to handle connection and service discovery
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BLE Devices'),
),
body: ListView.builder(
itemCount: _devices.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_devices[index].name),
onTap: () => connectToDevice(_devices[index]),
);
},
),
);
}
}
Как связать устройство BLE с телефоном с помощью пакета flutter_blue и существует ли определенный метод или процесс, которому я должен следовать, чтобы убедиться, что устройство подключено перед установкой соединения?
Любые рекомендации или пример кода будут с благодарностью оценены.
(То, что я пробовал ниже)
Попытайтесь проверить состояние облигации и пару:
Я попытался проверить состояние связи устройства и инициировать сопряжение, если устройство еще не было сопряжено. Фрагмент кода, который я использовал, был:
Future<void> checkAndPairDevice(BluetoothDevice device) async {
final BondState bondState = await device.bondState.first;
if (bondState == BondState.bonded) {
print('Device is already paired');
} else {
print('Device is not paired. Attempting to pair...');
try {
await device.pair();
print('Pairing successful');
} catch (error) {
print('Pairing failed: $error');
return;
}
}
}
К сожалению, этот подход не сработал, поскольку пакет flutter_blue не поддерживает методы BondState и Pair напрямую. Я обнаружил ошибки, указывающие на то, что эти методы не определены.
Переключение на пакет flutter_blue_plus:
Я попытался переключиться на пакет flutter_blue_plus, который имеет больше возможностей и активно поддерживается. Однако это привело к многочисленным конфликтам типов и проблемам совместимости между типами flutter_blue и flutter_blue_plus, что сделало интеграцию обоих пакетов непрактичной.
Ручное сопряжение:
Я также рассмотрел возможность вручную предложить пользователю выполнить сопряжение устройств через настройки Bluetooth системы, прежде чем инициировать соединение в приложении. Однако этот подход не обеспечивает бесперебойную работу пользователя и не гарантирует, что приложение сможет программно проверять и обрабатывать сопряжение.
@MichaelKotzjan Чтобы предоставить больше контекста, я пытался записать данные на устройство BLE с возможностью выбора формата (шестнадцатеричный, символьный, десятичный и т. д.) в моем приложении. Когда я пытался записать строку в характеристику, ожидающую строкового типа, она постоянно отклонялась. Сначала я думал, что проблему можно решить путем сопряжения устройства BLE с телефоном. Однако, похоже, проблема заключается не только в спаривании. Благодарю за ваш ответ. И я не знаю, выполняет ли мое устройство BLE сопряжение автоматически.
Сопряжение — это просто обмен ключами шифрования и оно не нужно, если характеристика не использует никаких мер безопасности. Когда ключи обмениваются, а затем сохраняются для дальнейшего использования, мы называем это связыванием. При простом подключении сопряжение и соединение не требуются. Попробуйте использовать универсальный инструмент исследования BLE, например nRF Connect, чтобы протестировать ваше устройство BLE. Если вы не можете отправить строку через nRF Connect, проблема в вашем устройстве, а не в вашем приложении.
@MichaelKotzjan Я считаю, что основная проблема заключается в том, что подключение к устройству BLE не устанавливает автоматически связь между устройством BLE и телефоном. Я проверил это с помощью nRF Connect и BLE Scanner, и соединение не произошло автоматически. Даже попытки вручную связать не увенчались успехом. Похоже, что устройство BLE имеет какую-то функцию безопасности, которая вообще предотвращает соединение.
Но действительно ли вам нужна связь? Разве подключения недостаточно для чтения/записи необходимых характеристик?
Я пытался записать данные на устройство BLE, чтобы изменить яркость света. При этом чтение и подписка на характеристики работает нормально, запись - нет. Это похоже на меру безопасности. Рассматриваемая характеристика: Имя характеристики: uuid_bonding UUID: 18E446F6-B870-07DD-021A-08123A051401 Свойства: Read / WriteNoResp / Write / Notify / Indicate Значение: [225] (байты) Эта характеристика должна возвращать [1], если она связана и [0], если он не подключен, но я постоянно получаю [255] (ff) при каждой попытке подключения.
Обновление: соединение действительно было необходимо для записи данных на устройство. Я успешно установил соединение и теперь могу выполнять операции записи. Спасибо вам за вашу помощь; это было очень оценено.
Рад слышать! Не стесняйтесь ответить на свой вопрос и пометить его как решенный, чтобы другие могли быстрее найти решение :)
Я выложу более чистое решение, как только доработаю его, поскольку текущая реализация довольно жестко запрограммирована. :) Кстати ваша помощь была ценна и полезна.
Использование flutter_blue устарело из-за нерегулярных обновлений. Вместо этого мы можем использовать flutter_blue_plus, который является ответвлением flutter_blue с более регулярными обновлениями и минимальными необходимыми изменениями. Вот как мы можем попытаться подключиться к устройству Bluetooth с помощью flutter_blue_plus:
import 'dart:io';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:device_info/device_info.dart';
Future<void> attemptBonding(BluetoothDevice device) async {
// get the device UUID
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
String deviceUUID;
try {
if (Platform.isAndroid) {
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
deviceUUID = androidInfo.id;
} else if (Platform.isIOS) {
IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
deviceUUID = iosInfo.identifierForVendor ?? '';
} else {
print('Unsupported platform');
return;
}
} catch (e) {
print('Error getting device UUID: $e');
return;
}
// convert the UUID to a byte array
List<int> uuidBytes = deviceUUID.codeUnits;
// function to match the UUID ignoring the first four characters (device name)
bool matchUUID(String characteristicUUID, String targetUUID) {
return characteristicUUID.substring(4).toLowerCase() == targetUUID.substring(4).toLowerCase();
}
// discover services and characteristics
List<BluetoothService> services;
try {
services = await device.discoverServices();
} catch (e) {
print('Error discovering services: $e');
return;
}
// find the bonding characteristic
BluetoothCharacteristic? bondingCharacteristic;
for (var service in services) {
bondingCharacteristic = service.characteristics.firstWhereOrNull(
(c) => matchUUID(c.uuid.toString(), 'UUID of your device that returns bonding characteristic')
);
if (bondingCharacteristic != null) break;
}
if (bondingCharacteristic != null) {
try {
print('Attempting to write to bonding characteristic...');
await bondingCharacteristic.write(uuidBytes, withoutResponse: true);
print('Written UUID to bonding characteristic.');
} catch (e) {
print('Error writing to bonding characteristic: $e');
return;
}
} else {
print('Bonding characteristic not found');
return;
}
// check bonding status
BluetoothCharacteristic? bondingStatusCharacteristic;
for (var service in services) {
bondingStatusCharacteristic = service.characteristics.firstWhereOrNull(
(c) => matchUUID(c.uuid.toString(), 'UUID of your device that returns bonding status characteristic')
);
if (bondingStatusCharacteristic != null) break;
}
if (bondingStatusCharacteristic != null) {
try {
await Future.delayed(Duration(seconds: 1)); // add a delay to ensure the bonding is processed
List<int> bondingStatus = await bondingStatusCharacteristic.read();
print('Bonding status value: $bondingStatus');
if (bondingStatus.isNotEmpty && bondingStatus[0] == 1) {
print('Bonding successful.');
} else {
print('Bonding failed or not recognized by the device.');
}
} catch (e) {
print('Error reading bonding status: $e');
}
} else {
print('Bonding status characteristic not found');
}
}
Такой подход обеспечивает лучшую совместимость и регулярные обновления за счет использования flutter_blue_plus, что делает процесс соединения Bluetooth более надежным.
Сопряжение будет выполняться автоматически ОС, как только вы попытаетесь получить доступ к характеристике, требующей шифрования. Есть ли у вашего BLE-устройства такая характеристика? Если не подключаться, достаточно