openharmony之分布式蓝牙实现多功能场景设备协同实战
一、 核心概念与异构架构
在开发之前,必须理解OpenHarmony实现分布式体脂仪所依赖的技术基石,特别是其异构系统架构。OpenHarmony并非单一系统,而是根据设备资源分为不同类型,它们在分布式场景中扮演不同角色。
- 系统类型与角色划分:
- 轻量系统:体脂仪本身。面向MCU(如Arm Cortex-M系列)级处理器,内存通常在128KB到128MB之间,内核为LiteOS-M。这类系统资源极其有限,无法运行复杂的图形界面和应用,主要任务是驱动传感器、通过蓝牙低功耗(BLE)广播数据,并执行简单的控制逻辑。
- 小型系统:可作为智能网关或功能增强型设备。面向应用处理器(如Arm Cortex-A系列),内存通常大于128MB,内核为LiteOS-A或Linux。它比轻量系统功能更强,支持更丰富的驱动和协议,但资源仍少于标准系统。在某些复杂场景下,体脂仪数据可以先汇聚到小型系统设备(如一个带屏幕的健康网关)进行初步处理。
- 标准系统:手机、平板等用户交互设备。内存通常大于128MB,内核为Linux。这是应用开发的主要平台,负责运行复杂的UI、处理业务逻辑、存储数据,并通过分布式软总线与其他设备协同。
- 分布式技术栈:
- 分布式软总线:为设备间的发现、连接和通信提供统一的分布式通信能力,是所有分布式功能的基础。
- 蓝牙低功耗 (BLE):体脂仪与手机/网关之间的近距离无线通信协议,负责传输测量数据和控制指令,功耗极低,适合电池供电设备。
- 分布式设备管理:提供设备发现、认证、绑定和状态监听的能力,是建立设备间可信关系的前提。
- 分布式数据管理:确保体脂数据在用户的多个设备(如手机、平板、手表)间自动同步,实现数据的一致性。
- 整体架构流程:
(1)体脂仪(轻量系统):上电后初始化传感器和BLE堆栈,作为GATT Server广播一个自定义的BLE服务。
(2)手机(标准系统):通过分布式设备管理发现并认证体脂仪(或通过BLE扫描直接发现)。认证后,建立可信关系。
(3)手机(标准系统):作为GATT Client,连接体脂仪的BLE服务,并写入“开始测量”指令到指定的特征值。
(4)体脂仪(轻量系统):收到指令后,驱动传感器采集数据(体重、阻抗等),通过算法计算出体脂率等参数。
(5)体脂仪(轻量系统):将计算结果通过BLE的Notify方式,发送给已连接的手机。
(6)手机(标准系统):接收数据,解析并显示在界面上,同时存入本地数据库。
(7)数据同步:通过分布式数据管理,这些数据可以自动同步到用户的其他OpenHarmony设备上。
二、 开发环境准备
- 硬件要求:
- 一台标准系统设备(如润和RK3568开发板或华为手机)。
- 一台轻量系统开发板(如GD32F303系列MCU开发板),用于模拟体脂仪。
- 蓝牙调试器(可选,用于辅助调试BLE通信)。
- 软件工具:
- IDE:DevEco Studio 5.0.3.910或更高版本。
- SDK:
- 标准系统:OpenHarmony Full SDK(API Version 12或更高)。分布式设备管理API是系统级接口,必须使用Full SDK才能编译通过。
- 轻量系统:需要为轻量系统配置独立的编译环境,通常使用
hb set
命令选择对应开发板,编译工具链由OpenHarmony源码提供或使用原生交叉编译工具链。
三、 核心开发步骤
(一) 权限配置(标准系统端)
在module.json5
文件中声明应用所需的权限。BLE扫描和分布式数据同步权限是必不可少的。
{"module": {"requestPermissions": [{"name": "ohos.permission.USE_BLUETOOTH","reason": "$string:grant_use_bluetooth","usedScene": {"abilities": ["MainAbility"],"when": "inuse"}},{"name": "ohos.permission.DISCOVER_BLUETOOTH","reason": "$string:grant_discovery_bluetooth","usedScene": {"abilities": ["MainAbility"],"when": "inuse"}},{"name": "ohos.permission.LOCATION","reason": "$string:grant_location","usedScene": {"abilities": ["MainAbility"],"when": "inuse"}},{"name": "ohos.permission.APPROXIMATELY_LOCATION","reason": "$string:grant_location","usedScene": {"abilities": ["MainAbility"],"when": "inuse"}},{"name": "ohos.permission.DISTRIBUTED_DATASYNC","reason": "$string:distributed_permission","usedScene": {"abilities": ["MainAbility"],"when": "inuse"}}]}
}
说明:扫描BLE设备需要获取位置权限,这是系统安全策略的要求。进行分布式设备发现和认证则需要
ohos.permission.DISTRIBUTED_DATASYNC
权限。
(二) 异构设备发现与认证
这是实现分布式体验的第一步,让手机能够发现并信任体脂仪设备。
- 标准系统端(手机):
- 引入设备管理模块:
import deviceManager from '@ohos.distributedHardware.deviceManager'; import { BusinessError } from '@ohos.base';
- 创建设备管理器实例并注册回调:
let dmInstance: deviceManager.DeviceManager | undefined = undefined;try {dmInstance = deviceManager.createDeviceManager('com.example.bodyfatscale');dmInstance.on('deviceStateChange', (data) => {console.info('deviceStateChange on:' + JSON.stringify(data));if (data.action === deviceManager.DeviceStateChangeAction.ONLINE) {// 设备上线,可以进行分布式业务}}); } catch (err) {let e: BusinessError = err as BusinessError;console.error('createDeviceManager errCode:' + e.code + ',errMessage:' + e.message); }
- 发现与认证设备:
if (dmInstance) {dmInstance.startDeviceDiscovery({'discoverTargetType': 0});// ... 在discoverSuccess回调中找到目标设备 ...let targetDeviceId = '...'; // 目标设备的deviceIddmInstance.authenticateDevice(targetDeviceId, {'targetPkgName': 'com.example.bodyfatscale'}, (err, data) => {// 认证结果处理}); }
- 引入设备管理模块:
- 轻量系统端(体脂仪):
- 轻量系统通常不直接实现完整的分布式设备管理Client端。它的角色是被发现和响应认证。这通常通过BLE广播包中包含特定信息,或在标准系统发起认证后,由轻量系统的底层服务(可能需要适配)来响应。适配轻量系统时,可能需要保留原生编译系统,将OpenHarmony编译为静态库集成,以最小化改动。
(三) 蓝牙低功耗 (BLE) 通信
BLE是体脂仪与手机通信的核心。
- 标准系统端(手机 - GATT Client):
- 扫描BLE设备:
import bluetooth from '@ohos.bluetooth';bluetooth.startBluetoothDiscovery(); bluetooth.on('bluetoothDeviceFind', (data) => {// 根据广播数据中的Service UUID筛选出体脂仪if (data[0].serviceUuids.includes('0000180F-0000-1000-8000-00805F9B34FB')) { // 示例UUIDconsole.info(`Found Scale: ${JSON.stringify(data[0])}`);// 停止扫描并尝试连接bluetooth.stopBluetoothDiscovery();// ... 连接逻辑 ...} });
- 连接与交互:
// 假设已获取设备ID let deviceId = 'XX:XX:XX:XX:XX:XX'; bluetooth.createGattClientServer().then((gattClient) => {gattClient.connect(deviceId);gattClient.on('connectionStateChange', (state) => {if (state.state === bluetooth.BluetoothState.STATE_CONNECTED) {// 连接成功,发现服务gattClient.getServices(deviceId).then((services) => {// 找到自定义服务及其特征值let customService = services.find(s => s.serviceUuid === 'YOUR_CUSTOM_SERVICE_UUID');let measureCharacteristic = customService.characteristics.find(c => c.characteristicUuid === 'MEASURE_CHAR_UUID');// 订阅测量数据通知gattClient.on('characteristicChange', (charValue) => {// 解析charValue,获取体重、体脂率等数据this.parseAndDisplayData(charValue.value);});gattClient.enableNotifyValueChange(charValue, true);});}}); });
- 扫描BLE设备:
- 轻量系统端(体脂仪 - GATT Server):
- 这部分开发通常在C/C++层面进行,使用OpenHarmony提供的BLE Host API。
- 定义服务与特征:
// 伪代码,展示逻辑 // 1. 定义服务UUID Uuid serviceUuid = {0x1234, 0x5678, ...}; // 2. 定义特征UUID Uuid measureCharUuid = {0x1234, 0x5679, ...}; // 可通知 Uuid controlCharUuid = {0x1234, 0x567A, ...}; // 可写// 3. 添加服务 GattsAddService(serviceUuid, true, true);// 4. 添加特征 GattsAddCharacteristic(serviceUuid, measureCharUuid, READ | NOTIFY, ...); GattsAddCharacteristic(serviceUuid, controlCharUuid, READ | WRITE, ...);// 5. 开始广播 AdvStart();
- 响应写请求与发送通知:
// 响应写请求回调 void OnWriteRequest(Uuid charUuid, uint8_t* value, uint16_t len) {if (charUuid == controlCharUuid) {if (value[0] == 0x01) { // 假设0x01是开始测量指令StartMeasurement(); // 启动传感器测量}} }// 测量完成后,发送通知 void SendMeasurementData(float weight, float fatRate) {uint8_t data[8];memcpy(data, &weight, 4);memcpy(data + 4, &fatRate, 4);GattsNotifyValueChange(serviceUuid, measureCharUuid, data, 8); }
(四) 健康数据处理与同步(标准系统端)
- 数据解析与存储:
import relationalStore from '@ohos.data.relationalStore';parseAndDisplayData(value: ArrayBuffer) {let dataView = new DataView(value);let weight = dataView.getFloat32(0, true); // 小端序let fatRate = dataView.getFloat32(4, true);console.info(`Weight: ${weight}kg, Fat Rate: ${fatRate}%`);// 更新UI// 存入本地数据库this.saveToDatabase(weight, fatRate); }async saveToDatabase(weight: number, fatRate: number) {// ... 初始化数据库 ...let valueBucket = { 'weight': weight, 'fat_rate': fatRate, 'timestamp': Date.now() };await store.insert('body_data', valueBucket); }
- 分布式数据同步:
import distributedData from '@ohos.data.distributedData';// 创建分布式数据对象 let kvManager = distributedData.createKVManager({bundleName: 'com.example.bodyfatscale',userInfo: { userId: '123', userType: 0 } });let kvStore = await kvManager.getKVStore('bodyfat_store', {createIfMissing: true,encrypt: false,keyAlias: 'bodyfat_alias',storeType: distributedData.StoreType.DEVICE_COLLABORATION });// 当本地数据有更新时,同步到分布式数据库 async syncToDistributedDB(weight: number, fatRate: number) {await kvStore.put(`record_${Date.now()}`, { weight, fatRate });// 数据会自动同步到其他可信设备 }
四、 完整流程与注意事项
- 流程总结:
(1)体脂仪(轻量系统)上电,广播BLE服务。
(2)手机(标准系统)通过分布式设备管理或BLE扫描发现体脂仪,并完成认证。
(3)手机作为GATT Client连接体脂仪,并发送测量指令。
(4)体脂仪作为GATT Server接收指令,采集数据并通过Notify返回。
(5)手机接收数据,解析、显示并存入本地数据库。
(6)手机将新数据写入分布式数据库,实现多设备同步。 - 注意事项:
- 异构系统差异:必须清醒认识到标准系统、小型系统、轻量系统的API集合和能力差异巨大。标准系统是分布式业务的主导者,轻量系统是功能专一的执行者。
- 轻量系统适配:为轻量系统开发时,可能需要采用特殊的适配方案,如将OpenHarmony编译为静态库集成到原有RTOS项目中,以降低移植难度和工作量。
- 真机调试:分布式和BLE功能必须在真实设备上进行测试,模拟器无法完全模拟。
- 功耗优化:体脂仪作为电池设备,功耗至关重要。应在无连接时进入深度睡眠,仅在测量或通信时唤醒。
- 数据安全:健康数据属于个人敏感信息,应确保BLE通信链路安全(如使用BLE配对和加密),并对分布式存储的数据进行适当保护。