跳到主要内容

设备管理

更新时间:2026-10-28 15:18:58

包括设备绑定、设备解绑、设备列表、设备配网

// 导入设备绑定头文件
import { RTCXAddDeviceService, RTCXAddDeviceType, RTCXDeviceMgr, RTCXDeviceMgrTypes, RTCXThingModel, RTCXThingModelType, RTCXLogger } from 'rtcxsdk'

设备绑定​

1. 无线绑定(如: 二维码、蓝牙等方式)

总体介绍参考设备绑定开发指南。

  • 设备绑定流程
  1. App调用prepareAddDevice()方法后,当监听到EAddDeviceStatus.Prepared状态时可获取bindToken (有效时长30分钟)。
  2. 将bindToken传递给设备(二维码、蓝牙等),设备保证网络连通情况下,通过DeviceSDK进行设备绑定
    • 海外设备绑定时,同时还需要将regionId传递给设备
  3. 在EAddDeviceStatus.Prepared状态下,App只需要调用startAddDevice()方法实时监听绑定状态回调即可(超时自行控制,最大超时依赖bindToken的有效时长)。
注意
  1. startAddDevice()方法需要等添加状态为EAddDeviceStatus.Prepared时才可以调用,所以可以在 onAddDeviceStatus: ()=>void 回调状态为EAddDeviceStatus.Prepared调用开始添加方法
  2. 已配网设备(如4G、有线设备)无需处理步骤2,即不需要处理bindToken
  3. 设备绑定详细流程说明请点击

相关API如下:

export interface IAddStatusListener {
// 设备添加状态回调,回调过程中状态、数据、错误信息
onAddDeviceStatus: (status: EAddDeviceStatus, data: Object|undefined, error: BusinessError<void>|undefined)=>void
}

export interface IAddDeviceService {
/**
* 准备添加设备,成功才可以进行下一步
*
* @param addType 添加类型
*/
prepareAddDevice(addType: EAddDeviceType): void
/**
* 开始添加设备,成功才可以进行下一步
*
* @param addReq 配网模式对应入参
*/
startAddDevice(addReq: IAddDeviceReq): void
/**
* 停止添加设备
*
*/
stopAddDevice(): void
/**
* 注册设备添加状态回调监听
*
* @param listener 回调监听者
*/
registerStatusListener(listener: IAddStatusListener): void
/**
* 获取配网所需随机数
*/
getBindToken(): string
/**
获取当前regionId(海外设备配网需要)
*/
getRegionId(): number
}

调用示例如下:

  1. 注册监听,并准备绑定
statusListerner: RTCXAddDeviceType.IAddStatusListener = {
onAddDeviceStatus: (status: RTCXAddDeviceType.EAddDeviceStatus, data: Object|undefined, error: BusinessError<void>|undefined)=> {
RTCXLogger.i(this.TAG, `device add status: ${status}, ${data}, ${error}`)
if (status === RTCXAddDeviceType.EAddDeviceStatus.Prepared) {
const bindToken = RTCXAddDeviceService.getBindToken()
RTCXLogger.i(this.TAG, `get bind token: ${bindToken}`)
} else if (status === RTCXAddDeviceType.EAddDeviceStatus.Success) {
showToast(this,'绑定成功')
this.pathStack.pop(true)
} else if (status === RTCXAddDeviceType.EAddDeviceStatus.Failed) {
showToast(this,'绑定失败')
}
}
}

RTCXAddDeviceService.registerStatusListener(this.statusListerner)
RTCXAddDeviceService.prepareAddDevice(RTCXAddDeviceType.EAddDeviceType.QR)

  1. 开始绑定
const req: RTCXAddDeviceType.QRAddDeviceReq = {addDeviceType: RTCXAddDeviceType.EAddDeviceType.QR}
RTCXAddDeviceService.startAddDevice(req)
  1. 结束绑定(该方法可以不调用,内部会自动处理)
RTCXAddDeviceService.stopAddDevice()

2. 有线绑定(如: 4G、有线设备)

  1. 与上面正常设备绑定流程类似,特殊之处是不需要向设备传递bindToken,而是直接调用WRAddDeviceReq有线添加的方式即可完成绑定(如:App可以扫描设备上的二维码获取productKey和deviceName,然后调用startAddDevice()方法绑定,同时监听绑定状态回调)
// App扫描设备二维码绑定
const req: RTCXAddDeviceType.WRAddDeviceReq = {productKey: 'xxx', deviceName: 'xxx', addDeviceType: RTCXAddDeviceType.EAddDeviceType.WR}
RTCXAddDeviceService.startAddDevice(req)

设备解绑​

/**
* 解绑用户的设备
* @param iotId - 设备ID

*/
export async function deviceUnbind(iotId: string): Promise<void>

调用示例如下:

RTCXDeviceMgr.deviceUnbind(deviceInfo.iotId)

设备列表​

/**
* 设备列表
* @param deviceListReq - 设备列表请求参数
* @returns
* @public
*/
export async function getDeviceList(deviceListReq: IDeviceListReq): Promise<IDeviceListResp>
/**
* 获取网关子设备
* @param subListReq - 获取网关子设备列表请求参数
* @returns
* @public
*/
export async function getGatewaySubList(subListReq: GatewaySubListReq): Promise<IDeviceListResp>

调用示例如下:

const reqParams: RTCXDeviceMgrTypes.IDeviceListReq = {
pageNo: 1,
pageSize: 100
}
try {
const deviceListRsp = await RTCXDeviceMgr.getDeviceList(reqParams)
this.deviceList = deviceListRsp.data
} catch (e) {
showToast(this, `获取设备列表失败${e}`)
}

获取设备状态​

/**
* 获取设备状态
* @param iotId - 设备ID
* @returns 设备状态 DeviceStatusEnum
* @public
*/
export async function getDeviceStatus(iotId: string): Promise<DeviceStatusEnum>

调用示例如下:

try {
const status = await RTCXDeviceMgr.getDeviceStatus('iotId')
} catch (e) {
showToast(this, `获取设备状态失败${e}`)
}

设备缩略图​

通过物模型服务获取设备缩略图

this.thingModel = new RTCXThingModel(PlayDeviceInfo)

try {
const result = await this.thingModel.invokeService<IDevPicture>('GetDevPicture',{'definition': 1, "picType": "jpg"})
if (result) {
const rsp = result as RTCXThingModelType.InvokeServiceRsp<IDevPicture>
if (rsp.code == 200) {
const devPicture = rsp.data as IDevPicture
RTCXLogger.i(TAG,`设备缩略图:${thingM.deviceInfo.iotId}, ${devPicture.downloadUrl}`)
this.deviceThumnails[thingM.deviceInfo.iotId] = devPicture
} else {
showToast(this, `获取缩略图失败`)
}
}
} catch (e) {
showToast(this, `获取缩略图失败${e}`)
}

设备配置​

//导入模块
import { RTCXDeviceEntityMgr, RTCXDeviceMgrTypes} from 'rtcxsdk'
/**
* 设备配置项管理
* @public
*/
export declare const RTCXDeviceEntityMgr: {
/**
* 设置设备配置项(单个)
*
* @param iotId - 设备ID
* @param entityEnum - 设置项
* @param value - 设置内容
*/
setDeviceEntity(iotId: string, entityEnum: DeviceEntityEnum, value: string): void | Promise<IGatewayResponse>;
/**
* 获取指定ID配置
*
* @param iotId - 设备ID
* @param entityEnum - 配置ID
*/
getDeviceEntity(iotId: string, entityEnum: DeviceEntityEnum): Promise<string|undefined>;
};

配置项 DeviceEntityEnum

/**
* 设备配置
* @public
*/
declare enum DeviceEntityEnum {
/**
* 消息推送设置
*/
MSG_PUSH_SETTING = 1003,
}

消息通知计划

/**
* 推送设置
* @public
*/
declare interface MsgPushSetting {
/** 推送关闭计划列表 */
sch: MsgPushSettingSchedule[];
/** 是否接收推送消息 */
sta: number;
/** 是否推送图片 */
img: number;
/** 推送间隔 单位:秒 */
interval: number;
}

/**
* 推送计划
* @public
*/
declare interface MsgPushSettingSchedule {
/** 开始时间,utc时间,秒 */
start: number;
/** 结束时间,utc时间,秒 (end时间应始终大于start时间,跨天的时候,end为第二天的时间) */
end: number;
/** 对应的值仅在"rpt"为2时有效,存在重复设置值:SUN:0x0001, MON:0x0002, TUE:0x0004, WED:0x0008, THU:0x0010, FRI:0x0020, SATU:0x0040,支持按位或操作 */
wk: number;
/** 重复类型,0:执行一次 1:每天重复 2:每周重复 3:每月重复 (目前支持1和2) */
rpt: number;
/** 推送关闭计划状态 1表示状态开,0表示状态关 */
sta: number;
}

获取设备配置​

/**
* 获取指定ID配置
*
* @param iotId - 设备ID
* @param entityEnum - 配置ID
*/
getDeviceEntity(iotId: string, entityEnum: DeviceEntityEnum): Promise<string|undefined>;

示例

import { RTCXDeviceEntityMgr, RTCXDeviceMgrTypes} from 'rtcxsdk'
async function (iotId: string){
const result = await RTCXDeviceEntityMgr.getDeviceEntity(
iotId,
RTCXDeviceMgrTypes.DeviceEntityEnum.MSG_PUSH_SETTING,
);
if(result) {
const msgNotifySetting = JSON.parse(result) as RTCXDeviceMgrTypes.MsgPushSetting
}
}

设置设备配置​

/**
* 设置设备配置项(单个)
*
* @param iotId - 设备ID
* @param entityEnum - 设置项
* @param value - 设置内容
*/
setDeviceEntity(iotId: string, entityEnum: DeviceEntityEnum, value: string): void | Promise<IGatewayResponse>;

示例

import { RTCXDeviceEntityMgr, RTCXDeviceMgrTypes} from 'rtcxsdk'
const msgNotifySetting: RTCXDeviceMgrTypes.MsgPushSetting = {
....
}
async function (iotId: string){
const result = await RTCXDeviceEntityMgr.setDeviceEntity(
iotId,
RTCXDeviceMgrTypes.DeviceEntityEnum.MSG_PUSH_SETTING,
JSON.stringify(msgNotifySetting)
);
}

云台预置位​

import {
RTCXDeviceMgrTypes,
RTCXPTZPresetMgr,
RTCXThingModelTypes,
} from 'rtcxsdk'

收藏常看的云台位置,方便快速转动设备镜头至相应位置

/**
* 预置位管理
* @public
*/
export declare class RTCXPTZPresetMgr {
private presetList;
private iotId;
/**
*
* @param iotId - 设备ID
*
*/
constructor(iotId: string);
/**
* 获取设备预置位列表
*
*/
getPresetList(): Promise<PTZPresetRspItem[]>;
/**
* 添加预置位
*
* @param reqParams - [PTZPresetReq]
*/
addPreset(reqParams: PTZPresetReq): Promise<PTZPresetRspItem>;
/**
* 删除预置位
*
* @param item - 列表返回的预置位项[PTZPresetRspItem]
*/
removePreset(item: PTZPresetRspItem): Promise<boolean>;
/**
* 更新预置位,一般用于修改名称
*
* @param item - 列表返回的预置位项[PTZPresetRspItem]
*/
updatePreset(item: PTZPresetRspItem): Promise<boolean>;
}

构建对象​

import {
RTCXDeviceMgrTypes,
RTCXPTZPresetMgr,
RTCXThingModelTypes,
} from 'rtcxsdk'

const iotId: string = ''
let presetMgr: RTCXPTZPresetMgr = new RTCXPTZPresetMgr(iotId)

获取设备预置位列表​

import {
RTCXPTZPresetMgr,
RTCXThingModelTypes,
} from 'rtcxsdk'


let presetMgr: RTCXPTZPresetMgr | null = null

// 加载预置位列表
async function loadPresetList(iotId: string) {

try {
if (!presetMgr) {
presetMgr = new RTCXPTZPresetMgr(iotId)
}
const presetList = await presetMgr.getPresetList()
} catch (error) {
console.error('加载预置位列表失败:', error)

}
}

RTCXThingModelTypes.PTZPresetRspItem

/**
* 预置位列表
*
* @public
*/
declare interface PTZPresetRspItem {
/**
* 预置位信息
*/
readonly ptz: string;
/**
* 预置位名称
*/
name?: string;
/**
* 预置位图片ID
*/
readonly picId?: string;
/**
* 预置位图片地址
*/
readonly picUrl?: string;
}

添加预置位​

  1. 通过物模型或其它途径获取设备当前云台位置信息

  2. 用户输入位置名称

  3. 获取设备当前位置画面(可截图播放器当前直播画面)

import {
RTCXPTZPresetMgr,
RTCXThingModelTypes,
} from 'rtcxsdk'

const ptzPosition = "获取到的当前云台位置信息"
const presetName ="常看位置"

async function handleAddPreset() {
try {

await presetMgr.addPreset({
ptz: ptzPosition,
name: presetName,
})

console.info('添加预置位成功')
} catch (error) {
console.error('添加预置位失败:', error)

}
}

RTCXThingModelTypes.PTZPresetReq

/**
* 预置位保存参数 预置位名称与截图至少有一个
*
* @public
*/
declare interface PTZPresetReq {
/**
* 预置位信息
*/
ptz: string;
/**
* 预置位名称 可选
*/
name?: string;
/**
* 预置位截图 可选 (暂不支持)
*/
img?: Blob | File;
}

删除预置位​

传入列表中获取数据,删除指定预置位

import {
RTCXPTZPresetMgr,
RTCXThingModelTypes,
} from 'rtcxsdk'

async function handleDeletePreset(item: RTCXThingModelTypes.PTZPresetRspItem) {

await presetMgr.removePreset(item)
await loadPresetList()
} catch (error) {
console.error('删除预置位失败:', error)
}
}

修改预置位名称​

更新预置位名称 如果ptz信息或图片变化请删除重新添加

import {
RTCXPTZPresetMgr,
RTCXThingModelTypes,
} from 'rtcxsdk'

const presetName = "新的位置名称"

async function handleSaveEdit(item: RTCXThingModelTypes.PTZPresetRspItem) {
try {
const newItem: RTCXThingModelTypes.PTZPresetRspItem = {
ptz: item.ptz,
picId: item.picId,
picUrl: item.picUrl,
name: presetName,
}
await presetMgr.updatePreset(newItem)

console.info('修改预置位名称成功')
await loadPresetList()
} catch (error) {
console.error('修改预置位名称失败:', error)
}
}

低功耗设备唤醒​

低功耗设备由于实现方案的不同,播放的方式有所区别,以下是设备DeviceSDK中定义的几种方式

/**
* XS_IOT_WORK_MODE_LOWPOWER_PROXY = 1, //低功耗设备,代理模式,注意只有支持低功耗保活连接的设备才需要设置此模式,设置了此模式之后必须和wifi 芯片上的 lowPwrSDK配合才能工作
* XS_IOT_WORK_MODE_LONG_TIME_POWER = 2 , //长上电设备,正常链接模式(iotsdk和streamsdk运行在一个进程中)
* XS_IOT_WORK_MODE_LOWPOWER_SEPARATE = 3, //低功耗设备,iotsdk和streamsdk分离模式,iotsdk运行在wifi或4g芯片上维持信令长连接,streamsdk运行在主控芯片上
* XS_IOT_WORK_MODE_LOWPOWER_KEEPLIVE = 4, //低功耗设备,iotsdk和streamsdk运行在主控芯片上,wifi或4g芯片上仅维持简单心跳保活,支持远程唤醒
*/
注意

工作模式为1,3的低功耗设备低功耗设备与常长电设备(工作模式为2)播放流程一致,以下示例仅为工作模式4的特殊播放流程

  1. 先唤醒设备(即使设备列表获取状态为上线,也需要唤醒一下设备)
  2. 监听设备上线
  3. 调用播放接口 (请务必在设备上线后调用)

唤醒接口

/**
* 低功耗设备唤醒
* @public
*/
declare class DeviceWakeUpMgr {
/**
*
* @param iotId - 设备唯一ID
* @param wakeupTimeout - 超时时长 单位:毫秒 默认30_000
* @param checkStatusInterval - 轮询设备状态频率 单位:毫秒 默认1000
*/
constructor(iotId: string, wakeupTimeout?: number, checkStatusInterval?: number);
/**
* 唤醒设备,等待设备上线
*/
wakeup(): Promise<void>;
/**
* 结束唤醒流程
*/
stop(): void;
}

调用示例如下:

// 导入设备唤醒头文件
import { RTCXLogger, RTCXDeviceMgrTypes, RTCXDeviceWakeUpMgr } from 'rtcxsdk'
let deviceWakeUpMgr: RTCXDeviceWakeUpMgr | null = null

async function playDevice(deviceInfo: RTCXDeviceMgrTypes.PlayDeviceInfo){
//判断设备是否是低功耗设备
if (
deviceInfo.deviceWorkMode ===
RTCXDeviceMgrTypes.DeviceWorkModeEnum.XS_IOT_WORK_MODE_LOWPOWER_KEEPLIVE
) {
deviceWakeUpMgr?.stop()
deviceWakeUpMgr = new RTCXDeviceWakeUpMgr(deviceInfo.iotId,30_000, 1000)
try{
await deviceWakeUpMgr.wakeup()
}catch(e){
//处理超时等异常情况,可根据业务自行处理
//示例:重新走一次唤醒流程
playDevice(deviceInfo)
return
}
}
initPlayer(deviceInfo) //见基础播放示例
}

设备配网​

设备需要配置网络时,App 通过各种方式将网络信息传递给设备。

AP配网​

设备 AP 配网时,待设备重置后进入待连接状态,手机连接设备热点,通过 App 传输 Wi-Fi 的 SSID 和密码,使设备加入目标网络。

// 导入 AP 配网头文件
import { RTCXAPLinkService, RTCXAPLinkType } from 'rtcxsdk'

AP 配网调用接口

export type APLinkConnectCallback =
(isConnect: boolean, error: BusinessError<void> | undefined) => void

export type APLinkResponseCallback =
(success: boolean, response: Object | undefined, error: BusinessError<void> | undefined) => void

export interface IAPLinkService {
/**
* 开始连接AP设备
*
* @param req 连接参数对象(可设置host、port和超时时间)
* @param connectCallback 连接结果回调
*/
startConnect(req: IAPLinkConnectReq, connectCallback: APLinkConnectCallback): void

/**
* 断开连接
*/
disconnect(): void

/**
* 发送配网信息
*
* @param req 配网参数对象,需要传ssid和pwd
* @param responseCallback 配网结果回调
*/
sendNetworking(req: IAPLinkNetworkingReq, responseCallback: APLinkResponseCallback): void
}

请求参数

// AP连接请求
export interface IAPLinkConnectReq {
// 超时时间,单位:秒,默认60s,可选
timeout?: number
// 连接host,可选,默认192.168.10.1
host?: string
// 连接端口,可选,默认58888
port?: number
}

// AP配网信息
export interface IAPLinkNetworkingReq {
// 超时时间,单位:秒,默认60s,可选
timeout?: number
// WiFi名称,必选
ssid: string
// WiFi密码,必选
pwd: string
}

错误码

// AP配网错误码
export enum EAPLinkError {
// 未使用
NO_ERROR = 0,
// 无效配置
BAD_CONFIG_ERROR = 1,
// 无效参数
BAD_PARAM_ERROR = 2,
// 连接超时
CONNECT_TIMEOUT_ERROR = 3,
// 读取超时
READ_TIMEOUT_ERROR = 4,
// 写入超时
WRITE_TIMEOUT_ERROR = 5,
// 读取达到最大长度仍未完成
READ_MAXED_OUT_ERROR = 6,
// 远端关闭连接
CLOSED_ERROR = 7,
// 其他错误
OTHER_ERROR = 8
}

// AP设备返回的配网结果码
export enum EAPLinkConfigCode {
// 配网成功
SUCCESS = 1000,
// 缺少ssid字段
ERR_MISSING_SSID = 1001,
// JSON格式无效
ERR_INVALID_JSON = 1002
}

调用示例如下:

  1. 准备设备绑定,引导用户连接设备热点
注意

应用通常无法直接切换 Wi-Fi,建议引导用户前往系统 Wi-Fi 设置连接设备热点,连接成功后再调用 AP 配网接口。

进入 AP 配网流程时,先准备添加设备(绑定状态监听请在发起绑定前注册):

RTCXAddDeviceService.prepareAddDevice(RTCXAddDeviceType.EAddDeviceType.AP)

用户连接上设备热点后,开始连接 AP 设备:

const connectReq: RTCXAPLinkType.IAPLinkConnectReq = {
timeout: 20 // 连接超时,单位:秒
}
RTCXAPLinkService.startConnect(connectReq,
(isConnect: boolean, error: BusinessError<void> | undefined) => {
if (!isConnect) {
// 连接失败,error.code 见 EAPLinkError
showToast(`连接设备热点失败:${error?.code} ${error?.message}`)
return
}
// 连接成功,发送Wi-Fi信息
})
  1. 发送 Wi-Fi 名称和密码
const netReq: RTCXAPLinkType.IAPLinkNetworkingReq = {
ssid: 'wifi名称',
pwd: 'wifi密码',
timeout: 60 // 等待设备响应的超时时间,单位:秒
}
RTCXAPLinkService.sendNetworking(netReq,
(success: boolean, response: Object | undefined,
error: BusinessError<void> | undefined) => {
if (!success) {
// 设备返回1001/1002等结果码时,error.code为 EAPLinkConfigCode
showToast(`配网失败:${error?.code} ${error?.message}`)
return
}
// 设备已接收Wi-Fi信息,发起绑定
})
注意

发送 Wi-Fi 名称和密码后,设备连接上目标 Wi-Fi 会主动断开热点;App 会短暂断开网络,请等待系统重新连接其他网络,绑定结果以 onAddDeviceStatus 回调为准。

  1. 发起设备绑定

配网信息发送成功后,按通用设备绑定流程调用 startAddDevice,AP 方式使用 APAddDeviceReq:

const addReq: RTCXAddDeviceType.APAddDeviceReq = {
addDeviceType: RTCXAddDeviceType.EAddDeviceType.AP,
productKey: '设备的productKey',
deviceName: '设备的deviceName'
}
RTCXAddDeviceService.startAddDevice(addReq)

绑定结果通过 registerStatusListener 的 onAddDeviceStatus 回调监听,详见设备绑定。建议业务层增加整体超时控制(如 120 秒),避免设备未上线时流程一直等待。

  1. 断开连接
RTCXAPLinkService.disconnect()

页面销毁或流程结束时调用,释放 TCP 连接资源;若此时仍有等待中的连接或配网请求,会以 EAPLinkError.CLOSED_ERROR 失败回调。

备注
  • 连接失败的错误码来自 EAPLinkError,如 CONNECT_TIMEOUT_ERROR(3)、CLOSED_ERROR(7)、OTHER_ERROR(8)。
  • 设备返回的配网结果码来自 EAPLinkConfigCode:1000 成功、1001 缺少 ssid、1002 JSON 格式无效;等待设备响应超时返回 EAPLinkError.READ_TIMEOUT_ERROR(4)。
  • 配网成功时 success 为 true,response 为设备返回的 JSON 对象;设备返回未知结果码时 success 为 false,error 可能为空,需要结合 response 判断。
  • 重复调用 startConnect 会先释放旧连接,旧连接的请求不会收到回调。

蓝牙配网​

设备蓝牙配网时,待设备重置后进入待配网状态,App 通过 BLE(低功耗蓝牙)扫描并连接设备,向设备发送 Wi-Fi 名称和密码,设备加入目标网络后由云端完成设备绑定。

// 导入蓝牙配网头文件
import { RTCXBluetoothLinkService, RTCXBluetoothLinkType } from 'rtcxsdk'

蓝牙配网调用接口

export type BluetoothAuthorizeStatusBlock =
(authorizeStatus: EBluetoothAuthorizeStatus) => void

export type BluetoothDeviceResponseHandler =
(success: boolean, response: Object | undefined, error: BusinessError<void> | undefined) => void

export interface IBluetoothLinkService {
/**
* 检查蓝牙授权状态
*
* @param authorizeStatusBlock 授权状态回调
*/
checkBluetoothAuthorizeStatus(authorizeStatusBlock: BluetoothAuthorizeStatusBlock): void

/**
* 开始扫描蓝牙设备
*
* @param req 扫描参数对象(可设置名称关键字和超时时间)
* @param scanResultBlock 扫描结果回调
*/
startScanBluetoothDevices(req: IBluetoothLinkScanReq,
scanResultBlock: BluetoothDeviceResponseHandler): void

/**
* 停止扫描蓝牙设备
*/
stopScanBluetoothDevices(): void

/**
* 连接蓝牙设备
*
* @param req 连接参数对象,需要传sn
* @param connectResultBlock 连接结果回调
*/
connectBluetoothDevice(req: IBluetoothLinkNetworkingReq,
connectResultBlock: BluetoothDeviceResponseHandler): void

/**
* 连接设备并发送配网信息,不需要再单独调用连接和配网方法
*
* @param req 请求参数对象,需要传sn和content
* @param networkingResultBlock 配网结果回调
*/
connectCombineNetworkingBluetoothDevice(req: IBluetoothLinkNetworkingReq,
networkingResultBlock: BluetoothDeviceResponseHandler): void

/**
* 向已连接的设备发送配网信息
*
* @param req 配网参数对象,需要传content
* @param networkingResultBlock 配网结果回调
*/
networkingBluetoothDevice(req: IBluetoothLinkNetworkingReq,
networkingResultBlock: BluetoothDeviceResponseHandler): void

/**
* 获取设备信息
*
* @param req 请求参数对象,需要传sn
* @param devInfoResultBlock 设备信息结果回调
*/
getBluetoothDeviceInfo(req: IBluetoothLinkQueryDeviceInfoReq,
devInfoResultBlock: BluetoothDeviceResponseHandler): void

/**
* 获取设备WiFi列表
*
* @param req 请求参数对象,需要传sn
* @param wifiListResultBlock WiFi列表结果回调
*/
getBluetoothDeviceWifiList(req: IBluetoothLinkQueryWifiReq,
wifiListResultBlock: BluetoothDeviceResponseHandler): void
}

请求与响应参数

export interface IBluetoothLinkModel {
// 超时时间,单位:秒,默认120s,可选
timeout?: number
}

// 扫描请求
export interface IBluetoothLinkScanReq extends IBluetoothLinkModel {
// 蓝牙设备名称包含的关键字,如:XS_[控制台产品型号]_、XSDEV_
namePrefixs?: string[]
}

// 连接/配网请求
export interface IBluetoothLinkNetworkingReq extends IBluetoothLinkModel {
// 蓝牙设备SN,连接设备时必填,取扫描结果中的sn
sn?: string
// 配网信息,发送配网信息时必填
content?: string
}

// 获取设备信息请求
export interface IBluetoothLinkQueryDeviceInfoReq extends IBluetoothLinkNetworkingReq {
}

// 获取WiFi列表请求
export interface IBluetoothLinkQueryWifiReq extends IBluetoothLinkNetworkingReq {
}

// 扫描到的蓝牙设备信息
export interface IBluetoothLinkDevInfoRsp extends IBluetoothLinkModel {
// 蓝牙设备名称
name?: string
// 蓝牙设备SN(即BLE deviceId)
sn?: string
}

// 设备返回的响应数据
export interface IBluetoothLinkResponseData {
// 设备mac
mac: string
// 设备返回的指令
cmd: number
// 设备返回的原始内容
data: string
}

蓝牙授权状态与错误码

// 蓝牙授权状态
export enum EBluetoothAuthorizeStatus {
// 未知
UNKNOWN = -1,
// 该设备不支持蓝牙低功耗
UNSUPPORTED = 0,
// 该应用无权使用蓝牙低功耗
UNAUTHORIZED = 1,
// 蓝牙关闭
POWERED_OFF = 2,
// 蓝牙打开
POWERED_ON = 3
}

// 蓝牙配网错误码
export enum EBluetoothLinkError {
// 扫描启动失败
REQUEST_AUTH_CODE_FAIL = 0x01,
// 蓝牙连接失败
CONNECT_FAIL = 0x02,
// 蓝牙断开连接
DISCONNECT = 0x03,
// 蓝牙不支持写入
WRITE_UNSUPPORTED = 0x04,
// 蓝牙消息发送失败
SEND_MESSAGE_FAIL = 0x05,
// 蓝牙消息解码失败
MESSAGE_ANALYSIS_FAIL = 0x06,
// 请求超时
LINK_TIMEOUT = 0x07
}
信息

蓝牙配网依赖系统 BLE 能力,接入前需要:

  1. 在 module.json5 中声明 ohos.permission.ACCESS_BLUETOOTH 权限;
  2. 在发起扫描前动态申请该权限;
  3. 确保手机蓝牙已打开。
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.ACCESS_BLUETOOTH",
"reason": "$string:bluetooth_permission_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
}
]
}
}
import { abilityAccessCtrl, common } from '@kit.AbilityKit'

async function requestBluetoothPermission(context: common.UIAbilityContext): Promise<boolean> {
const atManager = abilityAccessCtrl.createAtManager()
const result = await atManager.requestPermissionsFromUser(context, ['ohos.permission.ACCESS_BLUETOOTH'])
return result.authResults.every((authResult: number) => authResult === 0)
}

调用示例如下:

  1. 准备添加设备并注册绑定监听

进入蓝牙配网流程时,先注册绑定状态监听并准备添加设备(绑定状态监听建议在发起绑定前注册,详见设备绑定):

RTCXAddDeviceService.registerStatusListener(addStatusListener)
RTCXAddDeviceService.prepareAddDevice(RTCXAddDeviceType.EAddDeviceType.BT)
  1. 申请权限并检查蓝牙状态
const granted = await requestBluetoothPermission(context)
if (!granted) {
showToast('请先授予蓝牙权限')
return
}
RTCXBluetoothLinkService.checkBluetoothAuthorizeStatus(
(status: RTCXBluetoothLinkType.EBluetoothAuthorizeStatus) => {
if (status !== RTCXBluetoothLinkType.EBluetoothAuthorizeStatus.POWERED_ON) {
showToast('请打开手机蓝牙后重试')
return
}
startScan()
})
备注

checkBluetoothAuthorizeStatus 会持续监听蓝牙开关状态,用户打开或关闭蓝牙时回调会再次触发,业务需处理重复回调。

  1. 扫描设备
const scanReq: RTCXBluetoothLinkType.IBluetoothLinkScanReq = {
namePrefixs: ['XS'], // 设备名称包含的关键字,需按实际设备名称设置
timeout: 30 // 扫描超时,单位:秒
}
RTCXBluetoothLinkService.startScanBluetoothDevices(scanReq,
(success: boolean, response: Object | undefined,
error: BusinessError<void> | undefined) => {
if (!success) {
// 扫描失败或超时,error.code 见 EBluetoothLinkError
showToast(`扫描失败:${error?.code} ${error?.message}`)
return
}
// response 为累计扫描到的设备列表
const devices = response as RTCXBluetoothLinkType.IBluetoothLinkDevInfoRsp[]
// 刷新页面设备列表
})
备注
  • 扫描结果回调可能多次触发,response 为当前累计扫描到的设备列表,而非增量数据。
  • 未设置 timeout 时默认 120 秒;扫描到第一台设备后会停止超时计时,但扫描会持续进行,需要业务在用户选择设备或离开页面时主动调用 stopScanBluetoothDevices。
  • namePrefixs 必须设置且不能为空数组,匹配方式为设备名称包含任一关键字。
  • 扫描结果中的 sn 即 BLE deviceId,后续连接、获取信息、配网均使用该值。
  1. 连接设备
// 用户选择设备后停止扫描
RTCXBluetoothLinkService.stopScanBluetoothDevices()

const connectReq: RTCXBluetoothLinkType.IBluetoothLinkNetworkingReq = {
sn: device.sn,
timeout: 30 // 连接超时,单位:秒
}
RTCXBluetoothLinkService.connectBluetoothDevice(connectReq,
(success: boolean, response: Object | undefined,
error: BusinessError<void> | undefined) => {
if (!success) {
showToast(`连接失败:${error?.code} ${error?.message}`)
return
}
// 连接成功:GATT 连接、服务发现、通知订阅均已完成,可以发送指令
})
  1. 获取设备信息与Wi-Fi列表(可选)

连接成功后,可获取设备信息(如 productKey、deviceName)和周边 Wi-Fi 列表:

RTCXBluetoothLinkService.getBluetoothDeviceInfo({ sn: device.sn, timeout: 20 },
(success: boolean, response: Object | undefined,
error: BusinessError<void> | undefined) => {
if (!success) {
return
}
const rsp = response as RTCXBluetoothLinkType.IBluetoothLinkResponseData
// rsp.data 为设备返回的原始内容,格式由设备定义(示例设备为 JSON)
})

RTCXBluetoothLinkService.getBluetoothDeviceWifiList({ sn: device.sn, timeout: 20 },
(success: boolean, response: Object | undefined,
error: BusinessError<void> | undefined) => {
if (!success) {
// 设备不支持获取WiFi列表时 error.code 为 0x47,可引导用户手动输入WiFi名称
return
}
const rsp = response as RTCXBluetoothLinkType.IBluetoothLinkResponseData
// 解析 rsp.data 得到WiFi列表
})
备注

rsp.data 为设备返回的原始字符串,字段格式由设备固件定义;部分设备不支持获取 Wi-Fi 列表,此时 success 为 false,error.code 为 0x47。

  1. 发起绑定并发送配网信息
// 发起云端绑定流程,等待设备配网成功后上线
const addReq: RTCXAddDeviceType.BTAddDeviceReq = {
addDeviceType: RTCXAddDeviceType.EAddDeviceType.BT,
productKey: '设备的productKey', // 可从设备信息获取
deviceName: '设备的deviceName'
}
RTCXAddDeviceService.startAddDevice(addReq)

// 配网内容与二维码配网格式一致
const content = JSON.stringify({
ssid: 'wifi名称',
pwd: 'wifi密码',
type: 0,
random: RTCXAddDeviceService.getBindToken()
})
const netReq: RTCXBluetoothLinkType.IBluetoothLinkNetworkingReq = {
sn: device.sn,
content: content,
timeout: 60 // 等待设备响应的超时时间,单位:秒
}
RTCXBluetoothLinkService.networkingBluetoothDevice(netReq,
(success: boolean, response: Object | undefined,
error: BusinessError<void> | undefined) => {
if (!success) {
showToast(`配网失败:${error?.code} ${error?.message}`)
return
}
// 设备已收到配网信息,等待设备联网上线
})
注意

配网回调成功仅表示设备已收到 Wi-Fi 信息,不代表云端绑定成功。设备联网上线后的绑定结果以 onAddDeviceStatus 回调为准,建议业务层增加整体超时控制(如 120 秒)。

备注
  • 配网内容 content 需为 JSON 字符串,random 通过 RTCXAddDeviceService.getBindToken() 获取,type 固定为 0。
  • startAddDevice 需要在设备联网上线前发起。
  • 已连接设备时也可使用 connectCombineNetworkingBluetoothDevice 一次完成连接和配网,此时 sn 和 content 均需传入。
  1. 监听绑定结果
const addStatusListener: RTCXAddDeviceType.IAddStatusListener = {
onAddDeviceStatus: (status: RTCXAddDeviceType.EAddDeviceStatus,
data: Object | undefined, error: BusinessError<void> | undefined) => {
if (status === RTCXAddDeviceType.EAddDeviceStatus.Success) {
// 绑定成功,data 为新设备信息
} else if (status === RTCXAddDeviceType.EAddDeviceStatus.Failed) {
// 绑定失败,error 为失败原因
}
}
}
  1. 结束流程
// 停止扫描
RTCXBluetoothLinkService.stopScanBluetoothDevices()
// 取消绑定状态监听
RTCXAddDeviceService.registerStatusListener(undefined)

页面销毁或流程结束时调用,避免扫描和回调残留。

备注
  • 蓝牙配网当前未提供主动断开连接的接口。设备收到 Wi-Fi 信息后通常会自动断开蓝牙连接,SDK 会同步释放 GATT 连接资源。
  • 扫描启动失败返回 REQUEST_AUTH_CODE_FAIL;设备不存在或连接过程中失败返回 CONNECT_FAIL;未找到服务/特征或服务发现失败返回 WRITE_UNSUPPORTED;请求超时返回 LINK_TIMEOUT。
  • 发送指令时若连接未就绪或特征不可写,返回 WRITE_UNSUPPORTED;写入失败返回 SEND_MESSAGE_FAIL。
  • 设备返回未知或失败指令时,当前所有等待中的请求会以失败回调,error.code 为设备返回的指令值。
  • 同一类请求重复调用会覆盖上一次的请求回调,上一次请求不会再收到回调。