Я использую библиотеку Flutter_blue (https://pub.dev/packages/flutter_blue) для функциональности BLE во Flutter и хочу упаковать все функции BLE в отдельный класс.
Проблема в том, как передать функцию " handleData ", который отвечает за изменение состояния этого класса. Создание экземпляра класса внутри initState нарушает подключение BLE, поскольку он каждый раз пытается сканировать устройства и обнаруживать новые службы. Но я не нашел способа найти устройства и службы до initState () и иметь возможность ссылаться на метод handleData ().
main.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:motorbikedashboard/flutterBLE.dart';
Future<void> main() async {
runApp(MainScreen());
}
class MainScreen extends StatefulWidget {
@override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
FlutterBle connection;
String kmph;
int rpm;
void handleData(String receivedStr) {
setState(() {
this.kmph = receivedStr;
});
}
@override
void initState() {
super.initState();
// instanstiating this class on each init state breaks the BLE connection
connection = FlutterBle(handleData);
connection.readData();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'BLE test',
debugShowCheckedModeBanner: false,
home: Scaffold(
body: new SafeArea(
child: Center(
child: Text("$kmph"),
)),
),
theme: ThemeData.dark(),
);
}
}
и класс BLE или flutterBLE.dart
import 'dart:async';
import 'dart:convert';
import 'package:flutter_blue/flutter_blue.dart';
class FlutterBle {
static const TARGET_DEVICE_NAME = "ESP32";
static const SERVICE_UUID = "4fafc201-1fb5-459e-8fcc-c5c9c331914b";
static const CHARACTERISTIC_UUID = "beb5483e-36e1-4688-b7f5-ea07361b26a8";
StreamSubscription<ScanResult> scanSubScription;
BluetoothDevice targetDevice;
BluetoothCharacteristic targetCharacteristic;
Function wigetFunc;
FlutterBlue flutterBlue = FlutterBlue.instance;
FlutterBle(someFunction) {
wigetFunc = someFunction;
startScan();
}
startScan() {
scanSubScription = flutterBlue.scan().listen((scanResult) {
if (scanResult.device.name == TARGET_DEVICE_NAME) {
print('DEVICE found');
stopScan();
targetDevice = scanResult.device;
connectToDevice();
}
}, onDone: () => stopScan());
}
stopScan() {
scanSubScription?.cancel();
scanSubScription = null;
}
connectToDevice() async {
if (targetDevice == null) return;
await targetDevice.connect();
print('DEVICE CONNECTED');
discoverServices();
}
disconnectFromDevice() {
if (targetDevice == null) return;
targetDevice.disconnect();
}
discoverServices() async {
if (targetDevice == null) return;
List<BluetoothService> services = await targetDevice.discoverServices();
services.forEach((service) {
// do something with service
if (service.uuid.toString() == SERVICE_UUID) {
service.characteristics.forEach((characteristic) {
if (characteristic.uuid.toString() == CHARACTERISTIC_UUID) {
targetCharacteristic = characteristic;
readData();
}
});
}
});
}
readData() {
targetCharacteristic.value.listen((value) {
String receivedStr = ascii.decode(value);
// this function should call handleData and set state.
wigetFunc(receivedStr);
});
}
}