有没有办法从不断更新的单个文件访问来自 BLE 设备的数据?

问题描述

我想从一个 dart 文件访问 BLE 的特征值,我正在做的是从一个活动连接设备,然后将设备信息发送到所有其他活动。但是要获得值,我必须一次又一次地为所有活动/dart 文件编写相同的代码。 例如,我在这样的活动中连接设备:

StreamBuilder<List<ScanResult>>(
                stream: FlutterBlue.instance.scanResults,initialData: [],builder: (c,snapshot) => Column(
                  children: snapshot.data
                      .map(
                        (r) => ScanResultTile(
                      result: r,onTap: () => Navigator.of(context)
                          .push(MaterialPageRoute(builder: (context) {
                        r.device.connect();
                        print('DEVICE CONNECTED');
                        return BluetoothConnectedSuccess(device: r.device);

这里的 device: r.device 是我连接到 Flutter 应用程序的设备。现在,如果我想显示设备数据,我必须在每次跳转到任何屏幕/活动时初始化这些代码行:

class BluetoothConnectedSuccess extends StatefulWidget {
  const BluetoothConnectedSuccess({Key key,this.device}) : super(key: key);
  final BluetoothDevice device;
  @override
  _BluetoothConnectedSuccessstate createState() =>
      _BluetoothConnectedSuccessstate();
}

class _BluetoothConnectedSuccessstate extends State<BluetoothConnectedSuccess> {
    // BLE
      final String SERVICE_UUID = "4fafc201-1fb5-459e-8fcc-c5c9c331914b";
      final String CHaraCTERISTIC_UUID = "beb5483e-36e1-4688-b7f5-ea07361b26a8";
      bool isReady;
      Stream<List<int>> stream;
      List<int> lastValue;
      List<double> traceDust = List();
    
      @override
      void initState() {
        super.initState();
        isReady = false;
        connectToDevice();
      }
    
      connectToDevice() async {
        await widget.device.connect();
        discoverServices();
      }
    
      discoverServices() async {
        List<BluetoothService> services = await widget.device.discoverServices();
        services.forEach((service) {
          if (service.uuid.toString() == SERVICE_UUID) {
            service.characteristics.forEach((characteristic) {
              if (characteristic.uuid.toString() == CHaraCTERISTIC_UUID) {
                characteristic.setNotifyValue(!characteristic.isnotifying);
                stream = characteristic.value;
                print(stream);
                lastValue = characteristic.lastValue;
                print(lastValue);
    
                setState(() {
                  isReady = true;
                });
              }
            });
          }
        });
      }
    
      _dataParser(List<int> data) {
        var value = Uint8List.fromList(data);
        print("stream.value: $value"); // stream.value: [33]
        var hr = ByteData.sublistView(value,1);
        print("Heart rate: ${hr.getUint8(0)}");
        return hr.getUint8(0); // Heart rate: 33
      }

为需要 BLE 数据的活动一次又一次地编写相同的代码会造成很多混乱。 有没有办法只从单个文件调用这个连接的设备,而不是在每个活动中初始化相同的代码

这是指向我的 repo链接,用于查看我在使用 BLE 设备数据的每个活动/屏幕上所做的事情。 请帮助我,因为我是 Flutter 的新手。谢谢

解决方法

首先使用 Get 学习状态管理的基础知识,您可以在此处参考我的代码,每次发生的事情发生变化或更新时,它将使用特定的 Get 小部件(如 Obx 和 GetX )立即显示在 UI 中,这些小部件侦听值的变化,其中用 obs (observable) 标记。 例如:

Obx(
     () => ble.isScan.value ? LinearProgressIndicator() : SizedBox(),),

这将观察 isScan 值的变化。

class BleServices extends GetxController {
  FlutterBlue blue = FlutterBlue.instance;
  BluetoothDevice d;
  var connectedDevices = List<BluetoothDevice>().obs;
  var scanResults = List<ScanResult>().obs;
  var bleState = BluetoothState.off.obs;
  var isScan = false.obs;
  var scanRequire = false.obs;
  var bluetoothServices = List<BluetoothService>().obs;
  var discoveringServices = false.obs;
  var characteristics = List<BluetoothCharacteristic>().obs;

  @override
  void onInit() async {
    super.onInit();
    final perb = await Permission.bluetooth.status.isGranted;
    final perL = await Permission.location.status.isGranted;
    if (perb && perL) {
      getConnectedDevices();
    } else {
      await Permission.bluetooth.request();
      await Permission.location.request();
    }
    isScanning();
    state();
  }

  isDiscovering() async {}
  getConnectedDevices() async {
    final connectedDevice = await blue.connectedDevices;
    connectedDevices.value = connectedDevice;
    AppLogger.print('connected devices : $connectedDevice');
    if (connectedDevice.length == 0) {
      scanRequire.value = true;
      searchDevices();
    }
    return connectedDevice;
  }

  searchDevices() {
    // AppLogger.print('pppppppppppppp');

    blue
        .scan(timeout: Duration(seconds: 20))
        .distinct()
        .asBroadcastStream()
        .listen((event) {
      AppLogger.print(event.toString());
      scanResults.addIf(!scanResults.contains(event),event);
    });
    Future.delayed(Duration(seconds: 20),() {
      blue.stopScan();
      Get.showSnackbar(GetBar(
        message: 'scan is finished',));
    });
  }

  isScanning() {
    blue.isScanning.listen((event) {
      AppLogger.print(event.toString());
      isScan.value = event;
    });
  }

  state() {
    blue.state.listen((event) {
      AppLogger.print(event.toString());
      bleState.value = event;
    });
  }
}