Flutter可穿戴设备交互插件open_earable_flutter的使用

Flutter可穿戴设备交互插件open_earable_flutter的使用

Pub Likes Pub Popularity Pub Points Pub Version (包括预发布版本)

此Dart包提供了与OpenEarable设备进行交互的功能。它使您能够与OpenEarable设备通信,控制LED颜色,控制音频,并访问原始传感器数据。

在线试用,前提是您的浏览器支持Web Bluetooth


<kbd>   [获取OpenEarable设备](https://forms.gle/R3LMcqtyKwVH7PZB9)   </kbd> <kbd>   [在pub.dev上查看库](https://pub.dev/packages/open_earable_flutter)   </kbd>

权限

为了使您的应用能够使用此包中的UniversalBLE,您需要授予以下权限:

Android

您需要向AndroidManifest.xml文件添加以下权限:

<!-- flutter_reactive_ble权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<!-- 位置权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>

如果您在应用中使用了位置服务,请删除位置权限标签中的android:maxSdkVersion="30"

iOS / macOS

对于iOS,您需要在应用的Info.plist文件中添加以下条目。这是访问Core Bluetooth所必需的。有关如何实现此操作的详细信息,请参阅我们的示例应用。有关更多深入细节,请参阅关于iOS蓝牙权限的博客文章

iOS 13及以上版本

  • NSBluetoothAlwaysUsageDescription

iOS 12及更低版本

  • NSBluetoothPeripheralUsageDescription

对于macOS,从Xcode中为macOS应用添加蓝牙功能。

开始使用

要开始使用OpenEarable Flutter包,请遵循以下步骤:

  1. 安装 在您的flutter项目中添加该包:

    flutter pub add open_earable_flutter
  2. 导入包

    import 'package:open_earable_flutter/open_earable_flutter.dart';
  3. 初始化OpenEarable

    final openEarable = OpenEarable();
  4. 连接到耳戴设备

    openEarable.bleManager.startScan();
    
    // 监听发现的设备
    openEarable.bleManager.scanStream.listen((device) {
      // 处理发现的设备
    });
    
    // 连接到设备
    openEarable.bleManager.connectToDevice(device);

使用

  • 读取设备信息

    连接设备后,可以读取设备信息:

    String? deviceName = openEarable.deviceName;
    String? deviceIdentifier = openEarable.deviceIdentifier;
    String? deviceFirmwareVersion = openEarable.deviceFirmwareVersion;
  • 传感器

    • 传感器配置

      var config  = OpenEarableSensorConfig(sensorId: 0, samplingRate: 30, latency: 0);
      openEarable.sensorManager.writeSensorConfig(config);

      请参阅open-earable了解所有可能的传感器配置文档。

    • 订阅传感器数据

      openEarable.sensorManager.subscribeToSensorData(0).listen((data) {
        // 处理传感器数据
      });

      传感器数据以字典形式返回:

      {
      "sensorId": 0,
      "timestamp": 163538,
      "sensorName": "ACC_GYRO_MAG",
      "ACC": {
        "units": {"X": "g", "Y": "g", "Z": "g"},
        "X": 5.255882263183594,
        "Y": -2.622856855392456,
        "Z": 8.134146690368652
      },
      "GYRO": {
        "units": {"X": "dps", "Y": "dps", "Z": "dps"},
        "X": 0.007621999830007553,
        "Y": -0.030487999320030212,
        "Z": -0.015243999660015106
      },
      "MAG": {
        "units": {"X": "uT", "Y": "uT", "Z": "uT"},
        "X": -566.1000366210938,
        "Y": -95.70000457763672,
        "Z": -117.30000305175781
      }
      "EULER": {
        "units": {"ROLL": "rad", "PITCH": "rad", "YAW": "rad"},
        "ROLL": 0.8741,
        "PITCH": -0.2417,
        "YAW": 1.2913
      }
      }
    • 电池电量百分比

      Stream batteryLevelStream = openEarable.sensorManager.getBatteryLevelStream();
    • 按钮状态

      Stream buttonStateStream = openEarable.sensorManager.getButtonStateStream();

      包含以下按钮状态作为整数:

      • 0: 空闲
      • 1: 按下
      • 2: 持续按住
  • 控制内置LED

    openEarable.rgbLed.writeLedColor(r: 0, g: 255, b: 0);
  • 控制音频播放器

    • 播放WAV文件

      openEarable.audioPlayer.wavFile("audio.wav");
      openEarable.audioPlayer.setState(AudioPlayerState.start);
      • name: 存储在耳戴设备上的音频文件名
    • 播放频率

      int waveForm = 1;
      double frequency = 500.0;
      double loudness = 0.5;
      openEarable.audioPlayer.frequency(waveForm, frequency, loudness);
      openEarable.audioPlayer.setState(AudioPlayerState.start);
      • waveForm: 波形类型
        • 0: 正弦波
        • 1: 三角波
        • 2: 方波
        • 3: 锯齿波
      • loudness: 介于0.0和1.0之间的双精度浮点数
    • 播放提示音

      int jingleId = 1;
      openEarable.audioPlayer.jingle(jingleId);
      openEarable.audioPlayer.setState(AudioPlayerState.start);
      • jingleId: 存储在耳戴设备上的提示音ID
      • 0: ‘IDLE’
        • 1: ‘NOTIFICATION’
        • 2: ‘SUCCESS’
        • 3: ‘ERROR’
        • 4: ‘ALARM’
        • 5: ‘PING’
        • 6: ‘OPEN’
        • 7: ‘CLOSE’
        • 8: ‘CLICK’

完整示例Demo

以下是完整的示例代码:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:open_earable_flutter/open_earable_flutter.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});
  [@override](/user/override)
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  final OpenEarable _openEarable = OpenEarable();
  StreamSubscription? _scanSubscription;
  List discoveredDevices = [];
  bool _connectedToEarable = false;
  bool _waitingToConnect = false;
  String? _deviceIdentifier;
  String? _deviceFirmwareVersion;

  void _readDeviceInfo() async {
    String? deviceIdentifier = await _openEarable.bleManager.readDeviceIdentifier();
    String? deviceFirmwareVersion = await _openEarable.bleManager.readDeviceFirmwareVersion();
    setState(() {
      _deviceIdentifier = deviceIdentifier;
      _deviceFirmwareVersion = deviceFirmwareVersion;
    });
  }

  [@override](/user/override)
  void initState() {
    super.initState();
    _setupListeners();
  }

  void _setupListeners() async {
    _openEarable.bleManager.connectionStateStream.listen((connectionState) {
      if (connectionState) {
        _readDeviceInfo();
        _writeSensorConfig();
        setState(() {
          _waitingToConnect = false;
        });
      }
      setState(() {
        _connectedToEarable = connectionState;
      });
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Bluetooth Devices'),
        ),
        body: SingleChildScrollView(
            child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Padding(
              padding: EdgeInsets.fromLTRB(33, 16, 0, 0),
              child: Text(
                "SCANNED DEVICES",
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                  fontSize: 12.0,
                ),
              ),
            ),
            Visibility(
                visible: discoveredDevices.isNotEmpty,
                child: Container(
                    margin: const EdgeInsets.fromLTRB(16, 0, 16, 16),
                    decoration: BoxDecoration(
                      color: Colors.white,
                      border: Border.all(
                        color: Colors.grey,
                        width: 1.0,
                      ),
                      borderRadius: BorderRadius.circular(8.0),
                    ),
                    child: ListView.builder(
                      padding: EdgeInsets.zero,
                      physics: const NeverScrollableScrollPhysics(), // 禁用滚动
                      shrinkWrap: true,
                      itemCount: discoveredDevices.length,
                      itemBuilder: (BuildContext context, int index) {
                        final device = discoveredDevices[index];
                        return Column(children: [
                          Material(
                              type: MaterialType.transparency,
                              child: ListTile(
                                textColor: Colors.black,
                                selectedTileColor: Colors.grey,
                                title: Text(device.name),
                                titleTextStyle: const TextStyle(fontSize: 16),
                                visualDensity: const VisualDensity(
                                    horizontal: -4, vertical: -4),
                                trailing: _buildTrailingWidget(device.id),
                                onTap: () {
                                  setState(() => _waitingToConnect = true);
                                  _connectToDevice(device);
                                },
                              )),
                          if (index != discoveredDevices.length - 1)
                            const Divider(
                              height: 1.0,
                              thickness: 1.0,
                              color: Colors.grey,
                              indent: 16.0,
                              endIndent: 0.0,
                            ),
                        ]);
                      },
                    ))),
            Visibility(
                visible: _deviceIdentifier != null && _connectedToEarable,
                child: Padding(
                    padding: const EdgeInsets.fromLTRB(33, 8, 0, 8),
                    child: Text(
                      "Connected to $_deviceIdentifier $_deviceFirmwareVersion",
                      style: const TextStyle(fontSize: 16),
                    ))),
            Center(
              child: ElevatedButton(
                onPressed: _startScanning,
                child: const Text('Restart Scan'),
              ),
            )
          ],
        )),
      ),
    );
  }

  Widget _buildTrailingWidget(String id) {
    if (_openEarable.bleManager.connectedDevice?.id != id) {
      return const SizedBox.shrink();
    } else if (_connectedToEarable) {
      return const Icon(size: 24, Icons.check, color: Colors.green);
    } else if (_waitingToConnect) {
      return const SizedBox(
          height: 24,
          width: 24,
          child: CircularProgressIndicator(strokeWidth: 2));
    }
    return const SizedBox.shrink();
  }

  void _startScanning() async {
    discoveredDevices.removeWhere(
        (device) => device.id != _openEarable.bleManager.connectedDevice?.id);
    _openEarable.bleManager.startScan();
    _scanSubscription?.cancel();
    _scanSubscription = _openEarable.bleManager.scanStream.listen((incomingDevice) {
      if (incomingDevice.name.isNotEmpty &&
          !discoveredDevices.any((device) => device.id == incomingDevice.id)) {
        setState(() {
          discoveredDevices.add(incomingDevice);
        });
      }
    });
  }

  Future<void> _connectToDevice(device) async {
    _scanSubscription?.cancel();
    await _openEarable.bleManager.connectToDevice(device);
  }

  Future<void> _writeSensorConfig() async {
    OpenEarableSensorConfig config = OpenEarableSensorConfig(sensorId: 3, samplingRate: 0, latency: 0);
    _openEarable.sensorManager.writeSensorConfig(config);
    //_openEarable.sensorManager.subscribeToSensorData(3);
  }
}
1 回复

更多关于Flutter可穿戴设备交互插件open_earable_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,关于Flutter可穿戴设备交互插件open_earable_flutter的使用,下面是一个简单的代码案例来展示如何集成和使用这个插件。请注意,实际使用中你需要根据插件的文档和API进行具体的调整,因为不同版本的插件可能有不同的API和用法。

首先,确保你已经在pubspec.yaml文件中添加了open_earable_flutter依赖:

dependencies:
  flutter:
    sdk: flutter
  open_earable_flutter: ^最新版本号 # 替换为实际的最新版本号

然后,运行flutter pub get来获取依赖。

接下来,在你的Flutter应用中,你可以按照以下步骤使用open_earable_flutter插件:

  1. 导入插件

在你的Dart文件中导入插件:

import 'package:open_earable_flutter/open_earable_flutter.dart';
  1. 初始化插件

通常,你需要在应用的入口文件(如main.dart)中初始化插件。这里假设插件有一个初始化方法initialize()(具体方法名需参考插件文档):

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await OpenEarableFlutter.initialize(); // 假设这是初始化方法
  runApp(MyApp());
}
  1. 使用插件功能

假设插件提供了与可穿戴设备交互的功能,比如获取设备数据或发送命令。以下是一个示例,展示如何调用这些功能(具体API需参考插件文档):

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String deviceData = 'No Data';

  @override
  void initState() {
    super.initState();
    // 连接设备并获取数据
    _connectToDevice();
  }

  Future<void> _connectToDevice() async {
    try {
      // 假设有一个connect方法用于连接设备
      bool isConnected = await OpenEarableFlutter.connect();
      if (isConnected) {
        // 获取设备数据
        String data = await OpenEarableFlutter.getDeviceData();
        setState(() {
          deviceData = data;
        });
      } else {
        print('Failed to connect to device');
      }
    } catch (e) {
      print('Error: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Open Earable Flutter Demo'),
        ),
        body: Center(
          child: Text('Device Data: $deviceData'),
        ),
      ),
    );
  }
}

在这个示例中,我们假设OpenEarableFlutter类提供了connect()getDeviceData()方法来连接设备并获取数据。实际使用中,你需要根据插件提供的API进行相应的调用。

注意:以上代码是基于假设的API和方法名编写的,实际使用时请务必参考open_earable_flutter插件的官方文档和示例代码。插件的API可能会随着版本的更新而发生变化,因此确保你使用的是最新版本的文档。

如果你在使用插件时遇到具体问题,可以查阅插件的GitHub仓库、Issue跟踪器或相关社区寻求帮助。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!