Flutter可穿戴设备交互插件open_earable_flutter的使用
Flutter可穿戴设备交互插件open_earable_flutter的使用
此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包,请遵循以下步骤:
-
安装 在您的flutter项目中添加该包:
flutter pub add open_earable_flutter
-
导入包
import 'package:open_earable_flutter/open_earable_flutter.dart';
-
初始化OpenEarable
final openEarable = OpenEarable();
-
连接到耳戴设备
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);
}
}
更多关于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
插件:
- 导入插件:
在你的Dart文件中导入插件:
import 'package:open_earable_flutter/open_earable_flutter.dart';
- 初始化插件:
通常,你需要在应用的入口文件(如main.dart
)中初始化插件。这里假设插件有一个初始化方法initialize()
(具体方法名需参考插件文档):
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await OpenEarableFlutter.initialize(); // 假设这是初始化方法
runApp(MyApp());
}
- 使用插件功能:
假设插件提供了与可穿戴设备交互的功能,比如获取设备数据或发送命令。以下是一个示例,展示如何调用这些功能(具体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跟踪器或相关社区寻求帮助。