誰煮肉片 2025-12-01 16:01 采纳率: 0%
浏览 2

鸿蒙蓝牙广播,发出数据 设备类型未知

我想问下 .鸿蒙手机端 发送蓝牙广播数据 ,手机 nrf Connect 接收 接收到的Device type 信息是 UNKNOWN 是什么原因

img

import { ble } from '@kit.ConnectivityKit';
import { BusinessError } from '@kit.BasicServicesKit';

const TAG: string = 'BleAdvertisingManager';

export class BleAdvertisingManager {
  private advHandle: number = 0xFF; // 初始的无效值

  // 1. 定义广播状态上报事件
  onReceiveEvent = (data: ble.AdvertisingStateChangeInfo) => {
    console.info(TAG, 'bluetooth advertising state = ' + JSON.stringify(data));
    AppStorage.setOrCreate('advertiserState', data.state);
  };


  public async startAdvertising() {
    // 2.1 设置广播发送的参数
    let setting: ble.AdvertiseSetting = {
      interval: 160,
      txPower: 0,
      connectable: true
    };
 
    let advData: ble.AdvertiseData = {
      serviceUuids: [
        "000008F0-0000-1000-8000-00805F9B34FB",
        "00000810-0000-1000-8000-00805F9B34FB",
        "00009D13-0000-1000-8000-00805F9B34FB",
        "0000950E-0000-1000-8000-00805F9B34FB",
        "00004E2D-0000-1000-8000-00805F9B34FB",
        "000041F0-0000-1000-8000-00805F9B34FB",
        "00001DE1-0000-1000-8000-00805F9B34FB",
        "00007EB9-0000-1000-8000-00805F9B34FB",
        "0000F59C-0000-1000-8000-00805F9B34FB",
        "00002D98-0000-1000-8000-00805F9B34FB",
        "0000343D-0000-1000-8000-00805F9B34FB",
        "00002B0B-0000-1000-8000-00805F9B34FB",
        "00002D89-0000-1000-8000-00805F9B34FB"],
      manufactureData: [],
      serviceData: [],
      includeDeviceName: false // 表示是否携带设备名,可选参数。注意:带上设备名时,容易导致广播报文长度超出31个字节,使得广播启动失败
    };
    // 2.3 构造广播启动完整参数AdvertisingParams
    let advertisingParams: ble.AdvertisingParams = {
      advertisingSettings: setting,
      advertisingData: advData, // 注意: 广播报文长度不能超过31个字节
      // advertisingResponse: advResponse, // 注意: 广播报文长度不能超过31个字节
      duration: 0 // 可选参数,若参数大于0,则广播发送一段时间后会停止,但分配的广播资源还在,可重新启动发送
    }

    // 2.4 首次启动广播,蓝牙子系统会分配相关资源,包括应用获取到的广播标识ID
    try {
      ble.on('advertisingStateChange', this.onReceiveEvent);
      this.advHandle = await ble.startAdvertising(advertisingParams);
    } catch (err) {
      console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
    }
  }

  // 3. 停止指定标识的广播,即首次启动时分配的标识,停止后,该路广播资源仍然存在
  public async disableAdvertising() {
    // 3.1 构造停止广播参数
    let advertisingDisableParams: ble.AdvertisingDisableParams = {
      advertisingId: this.advHandle // 使用首次启动广播时获取到的广播标识ID
    }
    try {
      // 3.2 停止
      await ble.disableAdvertising(advertisingDisableParams);
    } catch (err) {
      console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
    }
  }

  // 4. 启动指定标识的广播,即首次启动时分配的标识
  public async enableAdvertising(enableDuration: number) {
    // 4.1 构造启动广播参数
    let advertisingEnableParams: ble.AdvertisingEnableParams = {
      advertisingId: this.advHandle, // 使用首次启动广播时获取到的广播标识ID
      duration: enableDuration
    }
    try {
      // 4.2 再次启动
      await ble.enableAdvertising(advertisingEnableParams);
    } catch (err) {
      console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
    }
  }

  // 5. 完全停止广播,释放广播资源
  public async stopAdvertising() {
    try {
      await ble.stopAdvertising(this.advHandle);
      ble.off('advertisingStateChange', this.onReceiveEvent);
    } catch (err) {
      console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
    }
  }
}

let bleAdvertisingManager = new BleAdvertisingManager();
export default bleAdvertisingManager as BleAdvertisingManager;

  • 写回答

2条回答 默认 最新

  • 檀越@新空间 2025-12-01 16:05
    关注

    下午好🌅🌅🌅
    本答案参考通义千问

    在鸿蒙系统中,蓝牙广播数据的发送过程中,设备类型(Device Type)显示为 UNKNOWN 是一个常见的问题。这通常意味着 蓝牙广播的数据格式或配置不正确,导致接收端(如 nRF Connect)无法识别设备类型。


    🚨 问题原因分析

    1. 广播数据格式不符合标准
      蓝牙广播数据必须遵循 BLE 的广播协议规范,包括服务 UUID、制造商数据、设备名称等字段。

    2. 未包含必要的广播字段
      如果没有设置 includeDeviceName 或者设备名称过长,可能导致广播数据被截断,从而无法识别设备类型。

    3. 广播数据长度超过限制
      广播数据长度不能超过 31 字节,否则广播可能失败或被截断。

    4. 未启用正确的广播模式
      如果广播不是可连接的(connectable: false),某些设备可能无法识别设备类型。

    5. nRF Connect 设置问题
      某些版本的 nRF Connect 可能对广播数据解析不完整,也可能导致设备类型显示为 UNKNOWN。


    ✅ 解决方案

    1. 确保广播数据格式正确

    • 确保 serviceUuids 和其他广播字段符合 BLE 标准。
    • 使用合法的 UUID(例如使用 0000110A-0000-1000-8000-00805F9B34FB 表示 Generic Access Profile)。

    2. 启用设备名称(includeDeviceName)

    • 设置 includeDeviceName: true,以确保设备名称被包含在广播数据中,便于识别。

    3. 控制广播数据长度

    • 确保广播数据总长度不超过 31 字节。
    • 如果 serviceUuids 过多,建议减少数量或使用更短的 UUID。

    4. 检查广播是否可连接

    • 设置 connectable: true,确保广播是可连接的,以便设备能够识别。

    5. 修改代码实现优化后的广播逻辑

    import { ble } from '@kit.ConnectivityKit';
    import { BusinessError } from '@kit.BasicServicesKit';
    
    const TAG: string = 'BleAdvertisingManager';
    
    export class BleAdvertisingManager {
      private advHandle: number = 0xFF; // 初始的无效值
    
      onReceiveEvent = (data: ble.AdvertisingStateChangeInfo) => {
        console.info(TAG, 'bluetooth advertising state = ' + JSON.stringify(data));
        AppStorage.setOrCreate('advertiserState', data.state);
      };
    
      public async startAdvertising() {
        let setting: ble.AdvertiseSetting = {
          interval: 160,
          txPower: 0,
          connectable: true // 确保广播是可连接的
        };
    
        let advData: ble.AdvertiseData = {
          serviceUuids: [
            "0000110A-0000-1000-8000-00805F9B34FB" // 示例:Generic Access Profile
          ],
          manufactureData: [],
          serviceData: [],
          includeDeviceName: true // 启用设备名称
        };
    
        let advertisingParams: ble.AdvertisingParams = {
          advertisingSettings: setting,
          advertisingData: advData,
          duration: 0
        };
    
        try {
          ble.on('advertisingStateChange', this.onReceiveEvent);
          this.advHandle = await ble.startAdvertising(advertisingParams);
        } catch (err) {
          console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
        }
      }
    
      public async disableAdvertising() {
        let advertisingDisableParams: ble.AdvertisingDisableParams = {
          advertisingId: this.advHandle
        };
        try {
          await ble.disableAdvertising(advertisingDisableParams);
        } catch (err) {
          console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
        }
      }
    
      public async enableAdvertising(enableDuration: number) {
        let advertisingEnableParams: ble.AdvertisingEnableParams = {
          advertisingId: this.advHandle,
          duration: enableDuration
        };
        try {
          await ble.enableAdvertising(advertisingEnableParams);
        } catch (err) {
          console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
        }
      }
    
      public async stopAdvertising() {
        try {
          await ble.stopAdvertising(this.advHandle);
          ble.off('advertisingStateChange', this.onReceiveEvent);
        } catch (err) {
          console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
        }
      }
    }
    
    let bleAdvertisingManager = new BleAdvertisingManager();
    export default bleAdvertisingManager as BleAdvertisingManager;
    

    🔍 额外建议

    | 项目 | 建议 | |------|------| | 设备名称 | 在 includeDeviceName: true 的前提下,可以手动设置设备名称,如 "MyHarmonyDevice"。 | | UUID选择 | 使用标准 UUID(如 0000110A)来提高兼容性。 | | 广播间隔 | interval: 160 对应 160 × 0.625ms = 100ms,这是较合理的广播间隔。 | | 测试工具 | 使用 nRF Connect 的“Scan”功能查看广播数据内容,确认是否包含预期信息。 |


    🧪 测试建议

    1. 在 nRF Connect 中打开 Scan 功能。
    2. 查看广播数据中的 Manufacturer DataService UUIDs 是否正常。
    3. 确认设备名称是否被正确广播。

    📌 总结

    设备类型显示为 UNKNOWN 的主要原因在于广播数据格式不正确或缺少关键字段。通过以下方式可以解决:

    1. 启用设备名称(includeDeviceName: true)
    2. 使用标准 UUID
    3. 控制广播数据长度(<31字节)
    4. 确保广播是可连接的(connectable: true)

    如果仍然存在问题,可以尝试使用更简单的广播数据结构进行测试,逐步排查问题。

    评论

报告相同问题?

问题事件

  • 创建了问题 12月1日