大家好,我是 V 哥。 以下基于 HarmonyOS 6.0 的蓝牙 BLE 通讯案例详解,模拟心率监测场景,实现服务端(Peripheral)广播数据与客户端(Central)订阅数据的功能流程:
联系V哥获取 鸿蒙学习资料
关键步骤:
-
服务端(Peripheral):
- 创建蓝牙服务(GATT Server)
- 添加服务(Service)和特征(Characteristic)
- 广播服务
- 当客户端连接后,定期更新心率特征值并通过通知发送给客户端
-
客户端(Central):
- 扫描BLE设备(按服务UUID过滤)
- 连接目标设备
- 发现服务及特征
- 订阅特征通知
- 接收特征值变化
以下是V哥整理的核心代码逻辑。
注意:由于HarmonyOS 6.0可能使用新的API包(如@ohos.bluetooth等),我们需要参考最新官方文档,但这里以搜索结果为基础,结合常见的BLE流程进行说明。
📡 一、服务端实现(广播心率数据) 1. 初始化蓝牙服务
typescript
import { bluetooth } from '@kit.ConnectivityKit';
// 定义服务UUID和特征值(需与客户端匹配)
const SERVICE_UUID = '0000180D-0000-1000-8000-00805F9B34FB'; // 标准心率服务UUID
const CHARACTERISTIC_UUID = '00002A37-0000-1000-8000-00805F9B34FB'; // 心率测量特征
// 创建GATT服务
let gattServer: bluetooth.GattServer = bluetooth.createGattServer();
let service: bluetooth.GattService = {
serviceUuid: SERVICE_UUID,
isPrimary: true,
characteristics: [{
characteristicUuid: CHARACTERISTIC_UUID,
permissions: bluetooth.CharacteristicPermission.READ,
properties: bluetooth.CharacteristicProperty.NOTIFY
}]
};
gattServer.addService(service);
2. 开启广播并发送数据
typescript
// 启动BLE广播
let advertiseSetting: bluetooth.AdvertiseSetting = {
interval: 320, // 广播间隔(单位0.625ms)
txPower: 0, // 发射功率
connectable: true
};
gattServer.startAdvertising(advertiseSetting, {
serviceUuids: [SERVICE_UUID] // 广播的服务标识
});
// 模拟心率数据发送(定时更新)
setInterval(() => {
const heartRate = Math.floor(Math.random() * 40) + 60; // 生成60~100随机心率值
const data = new Uint8Array([0x06, heartRate]); // 数据格式:Flags(06) + 心率值
// 通知已连接的客户端
gattServer.notifyCharacteristicChanged({
serviceUuid: SERVICE_UUID,
characteristicUuid: CHARACTERISTIC_UUID,
deviceId: connectedDeviceId, // 连接的设备ID
value: data.buffer // ArrayBuffer格式数据
});
}, 2000); // 每2秒发送一次
3. 处理客户端连接事件
typescript
gattServer.on('connectionStateChange', (device: bluetooth.Device, state: number) => {
if (state === bluetooth.ProfileConnectionState.STATE_CONNECTED) {
console.log(`设备已连接: ${device.deviceId}`);
connectedDeviceId = device.deviceId; // 保存连接的设备ID
} else if (state === bluetooth.ProfileConnectionState.STATE_DISCONNECTED) {
console.log('设备已断开');
}
});
📱 二、客户端实现(订阅心率数据)
1. 扫描并连接服务端
typescript
import { bluetooth } from '@kit.ConnectivityKit';
// 扫描指定服务的设备
let scanner: bluetooth.BLEScanner = bluetooth.createBLEScanner();
scroller.startScan({
serviceUuids: [SERVICE_UUID] // 过滤目标服务
});
// 发现设备回调
scanner.on('deviceDiscover', (device: bluetooth.ScanResult) => {
if (device.deviceName === "HeartRate_Server") { // 根据设备名过滤
const gattClient: bluetooth.GattClientDevice = bluetooth.createGattClientDevice(device.deviceId);
gattClient.connect(); // 连接服务端
}
});
2. 订阅特征值通知
typescript
// 连接成功后订阅数据
gattClient.on('servicesDiscovered', () => {
const service = gattClient.getService(SERVICE_UUID);
const characteristic = service.getCharacteristic(CHARACTERISTIC_UUID);
// 启用特征值通知
characteristic.setCharacteristicChangeNotification(true).then(() => {
characteristic.on('characteristicChange', (value: ArrayBuffer) => {
const heartRate = new Uint8Array(value); // 解析心率值
console.log(`实时心率: ${heartRate} BPM`);
});
});
});
3. 断开连接处理
typescript
gattClient.on('connectionStateChange', (state: number) => {
if (state === bluetooth.ProfileConnectionState.STATE_DISCONNECTED) {
console.log('已断开服务端连接');
scanner.stopScan(); // 停止扫描
}
});
🔑 三、关键知识点
- UUID 规范
- 使用标准 UUID(如心率服务
0x180D)确保跨设备兼容性。
- 使用标准 UUID(如心率服务
- 数据广播
- 服务端通过
notifyCharacteristicChanged()主动推送数据,客户端无需轮询。
- 服务端通过
- 权限配置
- 需在
module.json5中声明蓝牙权限:
- 需在
json
"requestPermissions": [{
"name": "ohos.permission.USE_BLUETOOTH"
}]
- 双机调试
- 需两台 HarmonyOS 设备(或模拟器)分别运行服务端/客户端。
⚠️ 四、常见问题
- 连接失败
- 检查设备是否开启蓝牙可见性,并确认
SERVICE_UUID完全匹配。
- 检查设备是否开启蓝牙可见性,并确认
- 收不到通知
- 客户端需先调用
setCharacteristicChangeNotification(true)订阅通知。
- 客户端需先调用
- 广播功耗优化
- 调整
AdvertiseSetting.interval可平衡广播频率与功耗。
- 调整