【鸿蒙开发实战篇】HarmonyOS 6.0 蓝牙实现服务端和客户端通讯案例详解

大家好,我是 V 哥。

以下基于 HarmonyOS 6.0 的蓝牙 BLE 通讯案例详解,模拟心率监测场景,实现服务端(Peripheral)广播数据与客户端(Central)订阅数据的功能流程:

联系V哥获取 鸿蒙学习资料

关键步骤:

  1. 服务端(Peripheral):

    • 创建蓝牙服务(GATT Server)
    • 添加服务(Service)和特征(Characteristic)
    • 广播服务
    • 当客户端连接后,定期更新心率特征值并通过通知发送给客户端
  2. 客户端(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(); // 停止扫描
  }
});

🔑 三、关键知识点

  1. UUID 规范
    • 使用标准 UUID(如心率服务 0x180D)确保跨设备兼容性。
  2. 数据广播
    • 服务端通过 notifyCharacteristicChanged() 主动推送数据,客户端无需轮询。
  3. 权限配置
    • 需在 module.json5 中声明蓝牙权限:
json 复制代码
     "requestPermissions": [{
       "name": "ohos.permission.USE_BLUETOOTH"
     }]
  1. 双机调试
    • 需两台 HarmonyOS 设备(或模拟器)分别运行服务端/客户端。

⚠️ 四、常见问题

  1. 连接失败
    • 检查设备是否开启蓝牙可见性,并确认 SERVICE_UUID 完全匹配。
  2. 收不到通知
    • 客户端需先调用 setCharacteristicChangeNotification(true) 订阅通知。
  3. 广播功耗优化
    • 调整 AdvertiseSetting.interval 可平衡广播频率与功耗。
相关推荐
resh_people15 小时前
开源鸿蒙平台 KMP_CMP 三方库「Kermit」适配全流程
华为·开源·harmonyos
李游Leo17 小时前
HarmonyOS 7 EasyGo + ArkUI Navigation:平行视界主副页筛选事务与跨栏撤销一致性【鸿蒙心迹】
华为·harmonyos
HwJack2018 小时前
【共创稿事节】HarmonyOS 7空间应用的可用性测试和体验评估小方法分享
华为·harmonyos·可用性测试
m0_7381858218 小时前
Flutter 鸿蒙化实战:flutter_scankit 适配 OpenHarmony,华为 ScanKit 扫码
flutter·华为·harmonyos·鸿蒙
zhangfeng113318 小时前
Ag / Cu / Au / Ru / Ir / Rh银 铜 金 钌铱 铑 纳米尺度下的 导电性 + 扩散/迁移缺点
人工智能·华为·ai编程·npu
用户1179104883320 小时前
别让AI随便启动你的LSP:hmharness给语言服务器加SHA256门禁 GitHub:swsgbl/hmharness
ai编程·harmonyos
李游Leo1 天前
HarmonyOS 7 + Share Kit-Window Kit:精准碰一碰屏幕坐标的窗口换算与落点拒绝【鸿蒙心迹】
华为·harmonyos
翼辉cto1 天前
Compose Multiplatform KV 存储库 multiplatform-settings 的 OpenHarmony 鸿蒙化适配实战
华为·harmonyos
事圆则缓1 天前
Flutter 开发鸿蒙实战:从 OpenHarmony 适配版到 HAP 构建与插件接入
flutter·华为·harmonyos
传奇开心果编程1 天前
【ArkUI进阶练中学】第9课:分布式能力与多设备协同
学习·ui·华为·harmonyos