本文介绍如何使用腾讯云物联网(IoT)应用端 SDK 的
TXIoTDeviceManager 完成设备绑定、解绑与设备列表查询。把单台设备的使用权授予其他账号,参见 设备分享;家庭、房间(含设备的房间归属)与家庭成员的管理,参见 家庭管理。前提条件
在使用本文能力前,请确保已完成以下准备工作:
已开通腾讯云物联网相关服务,并在控制台完成实例、应用和设备的准备工作。可参见 开通服务。
已在客户端工程中集成 IoT 应用端 SDK 并完成登录。可参见 Android SDK 集成与登录、iOS SDK 集成与登录。
已获取目标家庭的
familyId。首次使用的账号需要先查询或创建家庭,参见 家庭管理。绑定设备前,业务后台已具备签发设备绑定签名(
deviceBindSignature)的能力。获取设备管理对象
登录成功后,通过
TXIoTEngine 单例获取 TXIoTDeviceManager。该对象是本文所有设备操作的入口,可长期持有。TXIoTEngine iotEngine = TXIoTEngine.getInstance(context);TXIoTDeviceManager deviceManager = iotEngine.getDeviceManager();if (deviceManager == null) {// SDK 未登录或登录已过期,请先完成登录。return;}
TXIoTDeviceManager *deviceManager = [[TXIoTEngine getInstance] getDeviceManager];if (deviceManager == nil) {// SDK 未登录或登录已过期,请先完成登录。return;}
说明:
getDeviceManager 返回 null(iOS 为 nil)表示 SDK 尚未登录或登录已过期。请在登录成功回调之后再获取该对象,不要在 App 启动阶段提前缓存。绑定与解绑设备
绑定流程
一次完整的设备绑定涉及三方协作:
1. App 侧通过配网、扫码等方式获得设备的产品 ID 与设备名称。
2. App 请求业务后台签发该设备的绑定签名
deviceBindSignature。签名由业务后台使用密钥生成,客户端不参与计算。3. App 调用
bindDevice,传入目标 familyId 与该签名完成绑定。调试阶段获取设备绑定签名
正式环境中
deviceBindSignature 由业务后台签发。若尚在联调阶段、业务后台尚未就绪,可通过云 API 在线调试临时获取一个签名用于验证客户端流程:2. 填入控制台上的 ProductId 与 DeviceName,
Expire 按调试需要设置。3. 单击发送请求,从返回结果的
Response.DeviceSignature 中取出签名值。
注意:
上述方式仅用于本地联调。生产环境禁止在客户端调用云 API 或内置云 API 密钥,签名必须由业务后台签发后下发给客户端。
deviceBindSignature 具有时效性且与目标设备一一对应。签名过期会返回绑定 Token 已过期错误,签名与设备不匹配会返回绑定 Token 与设备不匹配错误。请在用户实际点击绑定时再向业务后台申请签名,不要提前批量获取并长期缓存。绑定与解绑接口
方法 | 说明 |
// 绑定设备:deviceBindSignature 由业务后台签发。deviceManager.bindDevice(familyId, deviceBindSignature, new TXIoTCallback<TXIoTDeviceInfo>() {@Overridepublic void onSuccess(TXIoTDeviceInfo deviceInfo) {TXIoTDeviceId deviceId = deviceInfo.deviceId;boolean isOnline = deviceInfo.status != null && deviceInfo.status.isOnline;}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 依次排查:签名是否过期、签名与设备是否匹配、设备是否已被绑定。}});// 解绑设备。deviceManager.unbindDevice(familyId, deviceId, new TXIoTCallback<Void>() {@Overridepublic void onSuccess(Void result) {// 解绑成功,请同步刷新本地设备列表。}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 解绑失败,请根据错误码和错误信息处理。}});
// 绑定设备:deviceBindSignature 由业务后台签发。TXIoTCallback<TXIoTDeviceInfo *> *bindCallback = [[TXIoTCallback alloc] init];bindCallback.onSuccess = ^(TXIoTDeviceInfo *deviceInfo) {TXIoTDeviceId *deviceId = deviceInfo.deviceId;BOOL isOnline = deviceInfo.status.isOnline;};bindCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 依次排查:签名是否过期、签名与设备是否匹配、设备是否已被绑定。};[deviceManager bindDevice:familyIddeviceBindSignature:deviceBindSignaturecallback:bindCallback];// 解绑设备。TXIoTVoidCallback *unbindCallback = [[TXIoTVoidCallback alloc] init];unbindCallback.onSuccess = ^{// 解绑成功,请同步刷新本地设备列表。};unbindCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 解绑失败,请根据错误码和错误信息处理。};[deviceManager unbindDevice:familyId deviceId:deviceId callback:unbindCallback];
查询设备列表
getDeviceList 按家庭维度分页返回设备。分页规则如下:首次查询传入空字符串
""。回调返回的
nextPageToken 为空字符串时表示已是最后一页;非空时原样回传给下一次 getDeviceList 即可,不要自行解析或拼接该值。返回的每个 TXIoTDeviceInfo 已包含
status.isOnline 在线状态。方法 | 说明 |
分页查询指定家庭下的设备列表。 |
// 首次查询传空字符串;nextPageToken 原样回传以获取下一页。deviceManager.getDeviceList(familyId, "", new TXIoTCallback<TXIoTPageResult<TXIoTDeviceInfo>>() {@Overridepublic void onSuccess(TXIoTPageResult<TXIoTDeviceInfo> result) {List<TXIoTDeviceInfo> deviceList = result.dataList;String nextPageToken = result.nextPageToken;if (nextPageToken != null && !nextPageToken.isEmpty()) {// 仍有下一页,可继续调用 getDeviceList(familyId, nextPageToken, ...)。}}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 查询设备列表失败,请根据错误码和错误信息处理。}});
// 首次查询传空字符串;nextPageToken 原样回传以获取下一页。TXIoTCallback<TXIoTPageResult<TXIoTDeviceInfo *> *> *listCallback = [[TXIoTCallback alloc] init];listCallback.onSuccess = ^(TXIoTPageResult<TXIoTDeviceInfo *> *result) {NSArray<TXIoTDeviceInfo *> *deviceList = result.dataList;NSString *nextPageToken = result.nextPageToken;if (nextPageToken.length > 0) {// 仍有下一页,可继续调用 getDeviceList:nextPageToken:callback:。}};listCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 查询设备列表失败,请根据错误码和错误信息处理。};[deviceManager getDeviceList:familyId nextPageToken:@"" callback:listCallback];
监听设备上下线
设备的在线状态变更通过
TXIoTEngine 的推送回调 onReceivePushMessage 下发。当 TXIoTPushMessage.type 为设备状态变更时,可从 subType 区分上线与下线,从 deviceId 定位具体设备。说明:
上一节
getDeviceList 返回的 status.isOnline 只是查询时刻的快照。要让设备列表的在线状态保持实时准确,需要同时注册推送回调,在收到通知后按 deviceId 局部刷新对应条目,而不是轮询列表接口。iotEngine.addListener(new TXIoTEngineListener() {@Overridepublic void onReceivePushMessage(TXIoTPushMessage pushMessage) {if (pushMessage.type != TXIoTPushMessageType.STATUS_CHANGE) {return;}TXIoTDeviceId deviceId = pushMessage.deviceId;if (pushMessage.subType == TXIoTPushMessageSubType.ONLINE) {// 设备上线,按 deviceId 局部刷新列表项。} else if (pushMessage.subType == TXIoTPushMessageSubType.OFFLINE) {// 设备离线。}}});
// 注册代理:[[TXIoTEngine getInstance] addDelegate:self];- (void)onReceivePushMessage:(TXIoTPushMessage *)pushMessage {if (pushMessage.type != TXIoTPushMessageTypeStatusChange) {return;}TXIoTDeviceId *deviceId = pushMessage.deviceId;if (pushMessage.subType == TXIoTPushMessageSubTypeOnline) {// 设备上线,按 deviceId 局部刷新列表项。} else if (pushMessage.subType == TXIoTPushMessageSubTypeOffline) {// 设备离线。}}
错误处理
错误码 | 说明 | 建议处理方式 |
ERR_INVALID_PARAMETER | 参数不合法。 | 检查 familyId、productId、deviceName、Token、别名是否为空。 |
ERR_INVALID_ACCESS_TOKEN | 登录凭证无效。 | 重新登录 SDK,并重新获取管理对象。 |
ERR_UNAUTHORIZED_OPERATION | 当前用户无权限。 | 确认当前用户是该家庭的成员,且对目标设备有管理权限;被分享用户不能解绑设备或修改设备信息。 |
ERR_DEVICE_BOUND | 设备已绑定。 | 设备已绑定到其他家庭或账号,需先由原绑定方解绑。 |
ERR_CAN_NOT_BIND_SAME_FAMILY | 不能重复绑定到同一家庭。 | 设备已在当前家庭中,直接使用即可,无需重复绑定。 |
ERR_BIND_TOKEN_NOT_EXIST | 绑定 Token 不存在。 | 向业务后台重新申请设备绑定签名。 |
ERR_BIND_TOKEN_IS_EXPIRED | 绑定 Token 已过期。 | 重新申请签名后立即绑定,不要缓存签名。 |
ERR_BIND_TOKEN_NO_PAIR_WITH_DEVICE | 绑定 Token 与设备不匹配。 | 确认签名对应的设备与传入的 deviceId 一致。 |
ERR_FAMILY_DEVICE_LIMIT_EXCEEDED | 家庭设备数量达到上限。 | 解绑无用设备,或将设备绑定到其他家庭。 |
ERR_FAMILY_NOT_EXIST | 家庭不存在。 | 重新查询家庭列表,确认 familyId 有效。 |
ERR_PRODUCT_NOT_EXISTERR_DEVICE_NOT_EXIST | 产品或设备不存在。 | 检查 productId 与 deviceName 是否正确。 |
ERR_DEVICE_OFFLINE | 设备离线。 | 引导用户检查设备网络状态后重试。 |
ERR_RATE_LIMITED | 请求被限频。 | 降低调用频率,避免高频轮询设备列表。 |
错误码 | 说明 | 建议处理方式 |
TXIoTErrorCodeInvalidParameter | 参数不合法。 | 检查 familyId、productId、deviceName、Token、别名是否为空。 |
TXIoTErrorCodeInvalidAccessToken | 登录凭证无效。 | 重新登录 SDK,并重新获取管理对象。 |
TXIoTErrorCodeUnauthorizedOperation | 当前用户无权限。 | 确认当前用户是该家庭的成员,且对目标设备有管理权限;被分享用户不能解绑设备或修改设备信息。 |
TXIoTErrorCodeDeviceBound | 设备已绑定。 | 设备已绑定到其他家庭或账号,需先由原绑定方解绑。 |
TXIoTErrorCodeCanNotBindSameFamily | 不能重复绑定到同一家庭。 | 设备已在当前家庭中,直接使用即可,无需重复绑定。 |
TXIoTErrorCodeBindTokenNotExist | 绑定 Token 不存在。 | 向业务后台重新申请设备绑定签名。 |
TXIoTErrorCodeBindTokenIsExpired | 绑定 Token 已过期。 | 重新申请签名后立即绑定,不要缓存签名。 |
TXIoTErrorCodeBindTokenNoPairWithDevice | 绑定 Token 与设备不匹配。 | 确认签名对应的设备与传入的 deviceId 一致。 |
TXIoTErrorCodeFamilyDeviceLimitExceeded | 家庭设备数量达到上限。 | 解绑无用设备,或将设备绑定到其他家庭。 |
TXIoTErrorCodeFamilyNotExist | 家庭不存在。 | 重新查询家庭列表,确认 familyId 有效。 |
TXIoTErrorCodeProductNotExist / TXIoTErrorCodeDeviceNotExist | 产品或设备不存在。 | 检查 productId 与 deviceName 是否正确。 |
TXIoTErrorCodeDeviceOffline | 设备离线。 | 引导用户检查设备网络状态后重试。 |
TXIoTErrorCodeRateLimited | 请求被限频。 | 降低调用频率,避免高频轮询设备列表。 |
常见问题
设备列表的在线状态不准确,需要自己轮询吗?
不需要。
getDeviceList 返回的 TXIoTDeviceInfo.status.isOnline 是查询时刻的状态快照,SDK 已在内部自动补齐,无需业务层额外调用状态查询接口。要保持实时性,请注册 TXIoTEngine 的 onReceivePushMessage 回调,收到设备状态变更通知后按 deviceId 局部刷新对应列表项。高频轮询设备列表可能触发限频错误。分页时 nextPageToken 可以自己拼接或跳页吗?
不可以。
nextPageToken 是 SDK 内部维护的游标,其格式属于实现细节,未来可能变化。请始终把上一次回调返回的值原样传给下一次调用,直到返回空字符串。该游标也不能跨接口复用:getDeviceList 与查询共享设备的 getDeviceListSharedWithMe(参见 设备分享)各自维护独立的分页序列。接口参考
本文涉及接口的完整定义参见: