本文介绍如何使用腾讯云物联网(IoT)应用端 SDK 的
TXIoTFamilyManager 管理家庭、房间与家庭成员。家庭是设备与成员的组织容器,familyId 是设备绑定、设备列表查询等操作的必备参数。设备的绑定与解绑参见 设备绑定;设备分享参见 设备分享。说明:
家庭、房间、成员三者的关系:家庭是权限边界,成员加入家庭后可访问该家庭下的全部设备;房间仅用于在 App 内对设备做分组展示,是可选概念,不影响权限;成员通过邀请 Token 加入,分为管理员与普通成员两种角色。
前提条件
在使用本文能力前,请确保已完成以下准备工作:
已开通腾讯云物联网相关服务,并在控制台完成实例与应用的准备工作。可参见 开通服务。
已在客户端工程中集成 IoT 应用端 SDK 并完成登录。可参见 Android SDK 集成与登录、iOS SDK 集成与登录。
获取家庭管理对象
登录成功后,通过
TXIoTEngine 单例获取 TXIoTFamilyManager。该对象是本文所有操作的入口,可长期持有。TXIoTEngine iotEngine = TXIoTEngine.getInstance(context);TXIoTFamilyManager familyManager = iotEngine.getFamilyManager();if (familyManager == null) {// SDK 未登录或登录已过期,请先完成登录。return;}
TXIoTFamilyManager *familyManager = [[TXIoTEngine getInstance] getFamilyManager];if (familyManager == nil) {// SDK 未登录或登录已过期,请先完成登录。return;}
说明:
getFamilyManager 返回 null(iOS 为 nil)表示 SDK 尚未登录或登录已过期。请在登录成功回调之后再获取该对象,不要在 App 启动阶段提前缓存。管理家庭
查询与创建家庭
App 启动后的标准流程是:先调用
getFamilyList 查询家庭列表;若列表为空(新注册账号),再调用 createFamily 创建一个默认家庭。方法 | 说明 |
创建家庭, name 不可为空,返回含 familyId 的家庭信息。 |
familyManager.getFamilyList(new TXIoTCallback<List<TXIoTFamilyInfo>>() {@Overridepublic void onSuccess(List<TXIoTFamilyInfo> familyList) {if (familyList.isEmpty()) {// 新账号尚无家庭,创建一个默认家庭。familyManager.createFamily("我的家", new TXIoTCallback<TXIoTFamilyInfo>() {@Overridepublic void onSuccess(TXIoTFamilyInfo familyInfo) {String familyId = familyInfo.familyId;}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 创建家庭失败,请检查家庭名称是否为空。}});return;}TXIoTFamilyInfo family = familyList.get(0);String familyId = family.familyId;boolean isAdmin = family.role == TXIoTFamilyRole.ADMIN;}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 查询家庭列表失败,请根据错误码和错误信息处理。}});
TXIoTCallback<NSArray<TXIoTFamilyInfo *> *> *listCallback = [[TXIoTCallback alloc] init];listCallback.onSuccess = ^(NSArray<TXIoTFamilyInfo *> *familyList) {if (familyList.count == 0) {// 新账号尚无家庭,创建一个默认家庭。TXIoTCallback<TXIoTFamilyInfo *> *createCallback = [[TXIoTCallback alloc] init];createCallback.onSuccess = ^(TXIoTFamilyInfo *familyInfo) {NSString *familyId = familyInfo.familyId;};createCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 创建家庭失败,请检查家庭名称是否为空。};[familyManager createFamily:@"我的家" callback:createCallback];return;}TXIoTFamilyInfo *family = familyList.firstObject;NSString *familyId = family.familyId;BOOL isAdmin = (family.role == TXIoTFamilyRoleAdmin);};listCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 查询家庭列表失败,请根据错误码和错误信息处理。};[familyManager getFamilyList:listCallback];
管理家庭成员
成员角色
家庭成员分为两种角色,通过
TXIoTUserInfo.role 与 TXIoTFamilyInfo.role 获取:角色 | 说明 |
管理员 | 家庭的创建者。可邀请成员、移除成员、删除家庭,并拥有家庭下全部设备的完整权限。 |
普通成员 | 通过邀请 Token 加入的用户。可访问和控制家庭下的全部设备,但不具备成员管理与家庭删除权限。 |
邀请成员加入家庭
管理员创建邀请 Token,通过业务自有渠道发送给目标用户;目标用户登录 SDK 后使用该 Token 加入家庭。
注意:
邀请 Token 与设备分享 Token 是两种不同凭据:邀请 Token 让对方成为家庭成员并获得家庭下全部设备的权限;设备分享 Token 只授予单台设备的使用权。若只想临时授权一台设备,请改用设备分享,参见 设备分享。两者均属敏感凭据,请通过可信渠道传递,避免在日志中明文输出。
方法 | 说明 |
管理员为指定家庭创建邀请 Token。普通成员调用会返回无权限错误。 | |
被邀请用户使用邀请 Token 加入家庭,只需传 Token,无需 familyId。加入成功后再次 getFamilyList 即可看到该家庭。 |
// 管理员:创建邀请 Token。familyManager.createFamilyInviteToken(familyId, new TXIoTCallback<String>() {@Overridepublic void onSuccess(String inviteToken) {// 通过业务自有渠道把 inviteToken 发送给被邀请用户。}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 创建邀请 Token 失败,请确认当前用户是该家庭的管理员。}});// 被邀请用户:使用邀请 Token 加入家庭。familyManager.joinFamilyAsMember(inviteToken, new TXIoTCallback<Void>() {@Overridepublic void onSuccess(Void result) {// 加入成功,重新调用 getFamilyList 即可看到该家庭。}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 加入失败,请检查邀请 Token 是否为空或已过期。}});
// 管理员:创建邀请 Token。TXIoTCallback<NSString *> *tokenCallback = [[TXIoTCallback alloc] init];tokenCallback.onSuccess = ^(NSString *inviteToken) {// 通过业务自有渠道把 inviteToken 发送给被邀请用户。};tokenCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 创建邀请 Token 失败,请确认当前用户是该家庭的管理员。};[familyManager createFamilyInviteToken:familyId callback:tokenCallback];// 被邀请用户:使用邀请 Token 加入家庭。TXIoTVoidCallback *joinCallback = [[TXIoTVoidCallback alloc] init];joinCallback.onSuccess = ^{// 加入成功,重新调用 getFamilyList 即可看到该家庭。};joinCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 加入失败,请检查邀请 Token 是否为空或已过期。};[familyManager joinFamilyAsMember:inviteToken callback:joinCallback];
查询成员、移除成员与退出家庭
removeMemberFromFamily 一个接口承载两种语义,由传入的 userId 决定:传入其他成员的
userId → 管理员将该成员移出家庭。传入当前登录用户自己的
userId → 当前用户主动退出该家庭。方法 | 说明 |
移除成员或退出家庭,语义由 userId 是否为当前登录用户决定。userId 取自 getMemberList 的返回结果。 |
// 先查询成员列表,再基于返回的 userId 执行移除或退出。familyManager.getMemberList(familyId, new TXIoTCallback<List<TXIoTUserInfo>>() {@Overridepublic void onSuccess(List<TXIoTUserInfo> memberList) {for (TXIoTUserInfo member : memberList) {// member.userId / member.nickName / member.avatarUrl / member.role}TXIoTUserInfo self = iotEngine.getLoginUserInfo();String targetUserId = memberList.get(0).userId;boolean isSelf = self != null && targetUserId.equals(self.userId);// isSelf 为 true 时语义是「退出家庭」,否则是「管理员移除成员」。familyManager.removeMemberFromFamily(familyId, targetUserId, new TXIoTCallback<Void>() {@Overridepublic void onSuccess(Void result) {// 操作成功,请刷新成员列表或家庭列表。}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 操作失败,请确认权限,并确认 userId 取自 getMemberList。}});}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 查询成员列表失败,请根据错误码和错误信息处理。}});
// 先查询成员列表,再基于返回的 userId 执行移除或退出。TXIoTCallback<NSArray<TXIoTUserInfo *> *> *memberCallback = [[TXIoTCallback alloc] init];memberCallback.onSuccess = ^(NSArray<TXIoTUserInfo *> *memberList) {if (memberList.count == 0) {return;}TXIoTUserInfo *self = [[TXIoTEngine getInstance] getLoginUserInfo];NSString *targetUserId = memberList.firstObject.userId;BOOL isSelf = [targetUserId isEqualToString:self.userId];// isSelf 为 YES 时语义是「退出家庭」,否则是「管理员移除成员」。TXIoTVoidCallback *removeCallback = [[TXIoTVoidCallback alloc] init];removeCallback.onSuccess = ^{// 操作成功,请刷新成员列表或家庭列表。};removeCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 操作失败,请确认权限,并确认 userId 取自 getMemberList。};[familyManager removeMemberFromFamily:familyIduserId:targetUserIdcallback:removeCallback];};memberCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 查询成员列表失败,请根据错误码和错误信息处理。};[familyManager getMemberList:familyId callback:memberCallback];
修改家庭名称与删除家庭
注意:
updateFamilyInfo 目前仅支持修改家庭名称:传入的 TXIoTFamilyInfo 中 familyId 用于定位家庭、name 为新名称且不可为空,其余字段(role、createTime、updateTime)为只读,填写后不会生效。方法 | 说明 |
修改家庭名称。 name 为空时返回参数不合法错误,且不会发起网络请求。 | |
删除家庭。删除后该家庭下的房间、成员关系一并失效,请在调用前二次确认。仅管理员可执行。 |
// 修改家庭名称:familyId 定位家庭,name 为新名称。TXIoTFamilyInfo newInfo = new TXIoTFamilyInfo();newInfo.familyId = familyId;newInfo.name = "度假别墅";familyManager.updateFamilyInfo(newInfo, new TXIoTCallback<Void>() {@Overridepublic void onSuccess(Void result) {// 修改成功,可直接更新本地 UI。}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 修改失败,请检查家庭名称是否为空。}});// 删除家庭(建议先弹窗二次确认)。familyManager.deleteFamily(familyId, new TXIoTCallback<Void>() {@Overridepublic void onSuccess(Void result) {// 删除成功,请刷新家庭列表并切换到其他家庭。}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 删除失败,请确认当前用户是该家庭的管理员。}});
// 修改家庭名称:familyId 定位家庭,name 为新名称。TXIoTFamilyInfo *newInfo = [[TXIoTFamilyInfo alloc] init];newInfo.familyId = familyId;newInfo.name = @"度假别墅";TXIoTVoidCallback *updateCallback = [[TXIoTVoidCallback alloc] init];updateCallback.onSuccess = ^{// 修改成功,可直接更新本地 UI。};updateCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 修改失败,请检查家庭名称是否为空。};[familyManager updateFamilyInfo:newInfo callback:updateCallback];// 删除家庭(建议先弹窗二次确认)。TXIoTVoidCallback *deleteCallback = [[TXIoTVoidCallback alloc] init];deleteCallback.onSuccess = ^{// 删除成功,请刷新家庭列表并切换到其他家庭。};deleteCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 删除失败,请确认当前用户是该家庭的管理员。};[familyManager deleteFamily:familyId callback:deleteCallback];
管理房间
房间用于在 App 内对家庭下的设备做分组展示。房间是可选概念:设备刚绑定时不属于任何房间,是否加入房间不影响设备的绑定状态、访问权限与功能使用。若业务不需要分组,可跳过本章。
说明:
房间只负责“分组”,不构成权限边界:设备的访问权限由家庭成员关系与设备分享决定,与房间归属无关。房间本身的增删改查由
TXIoTFamilyManager 提供,把设备加入或移出房间由 TXIoTDeviceManager 提供,两者均在本章介绍。创建、查询与维护房间
方法 | 说明 |
查询家庭下的房间列表。返回的 TXIoTRoomInfo.deviceCount 为该房间内的设备数量。该接口不分页。 | |
重命名房间, roomId 与 name 均不可为空。 | |
删除房间。房间内的设备不会被解绑,只是恢复为“未分配房间”状态。 |
// 创建房间。familyManager.createRoom(familyId, "客厅", new TXIoTCallback<TXIoTRoomInfo>() {@Overridepublic void onSuccess(TXIoTRoomInfo roomInfo) {String roomId = roomInfo.roomId;// 后续可按「设备的房间归属」小节把设备加入该房间。}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 创建房间失败,请检查房间名称是否为空。}});// 查询房间列表。familyManager.getRoomList(familyId, new TXIoTCallback<List<TXIoTRoomInfo>>() {@Overridepublic void onSuccess(List<TXIoTRoomInfo> roomList) {for (TXIoTRoomInfo room : roomList) {// room.roomId / room.name / room.deviceCount}}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 查询房间列表失败,请根据错误码和错误信息处理。}});// 重命名房间。familyManager.setRoomName(familyId, roomId, "主卧", new TXIoTCallback<Void>() {@Overridepublic void onSuccess(Void result) {// 重命名成功。}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 重命名失败,请根据错误码和错误信息处理。}});// 删除房间(房间内设备不会被解绑)。familyManager.deleteRoom(familyId, roomId, new TXIoTCallback<Void>() {@Overridepublic void onSuccess(Void result) {// 删除成功,请刷新房间列表。}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 删除失败,请根据错误码和错误信息处理。}});
// 创建房间。TXIoTCallback<TXIoTRoomInfo *> *createCallback = [[TXIoTCallback alloc] init];createCallback.onSuccess = ^(TXIoTRoomInfo *roomInfo) {NSString *roomId = roomInfo.roomId;// 后续可按「设备的房间归属」小节把设备加入该房间。};createCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 创建房间失败,请检查房间名称是否为空。};[familyManager createRoom:familyId name:@"客厅" callback:createCallback];// 查询房间列表。TXIoTCallback<NSArray<TXIoTRoomInfo *> *> *roomListCallback = [[TXIoTCallback alloc] init];roomListCallback.onSuccess = ^(NSArray<TXIoTRoomInfo *> *roomList) {for (TXIoTRoomInfo *room in roomList) {// room.roomId / room.name / room.deviceCount}};roomListCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 查询房间列表失败,请根据错误码和错误信息处理。};[familyManager getRoomList:familyId callback:roomListCallback];// 重命名房间。TXIoTVoidCallback *renameCallback = [[TXIoTVoidCallback alloc] init];renameCallback.onSuccess = ^{// 重命名成功。};renameCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 重命名失败,请根据错误码和错误信息处理。};[familyManager setRoomName:familyId roomId:roomId name:@"主卧" callback:renameCallback];// 删除房间(房间内设备不会被解绑)。TXIoTVoidCallback *deleteRoomCallback = [[TXIoTVoidCallback alloc] init];deleteRoomCallback.onSuccess = ^{// 删除成功,请刷新房间列表。};deleteRoomCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 删除失败,请根据错误码和错误信息处理。};[familyManager deleteRoom:familyId roomId:roomId callback:deleteRoomCallback];
设备的房间归属
创建房间后,即可把设备归入房间。设备刚绑定时不属于任何房间,加入房间不影响设备的绑定状态与功能使用。
方法 | 说明 |
将设备加入指定房间,需传入 deviceId、familyId 与 roomId。重复调用会覆盖设备原有的房间归属。 | |
将设备从当前房间移出,只需传入 deviceId 与 familyId,无需 roomId。移出后设备仍绑定在该家庭下。 |
// 将设备加入房间。deviceManager.addDeviceToRoom(deviceId, familyId, roomId, new TXIoTCallback<Void>() {@Overridepublic void onSuccess(Void result) {// 加入房间成功。}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 加入房间失败,请根据错误码和错误信息处理。}});// 将设备移出房间(无需传 roomId)。deviceManager.removeDeviceFromRoom(deviceId, familyId, new TXIoTCallback<Void>() {@Overridepublic void onSuccess(Void result) {// 移出房间成功。}@Overridepublic void onError(TXIoTErrorCode errorCode, String errorMessage) {// 移出房间失败,请根据错误码和错误信息处理。}});
// 将设备加入房间。TXIoTVoidCallback *addCallback = [[TXIoTVoidCallback alloc] init];addCallback.onSuccess = ^{// 加入房间成功。};addCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 加入房间失败,请根据错误码和错误信息处理。};[deviceManager addDeviceToRoom:deviceIdfamilyId:familyIdroomId:roomIdcallback:addCallback];// 将设备移出房间(无需传 roomId)。TXIoTVoidCallback *removeCallback = [[TXIoTVoidCallback alloc] init];removeCallback.onSuccess = ^{// 移出房间成功。};removeCallback.onError = ^(TXIoTErrorCode errorCode, NSString *errorMessage) {// 移出房间失败,请根据错误码和错误信息处理。};[deviceManager removeDeviceFromRoom:deviceId familyId:familyId callback:removeCallback];
使用建议
调用顺序:登录 →
getFamilyManager → getFamilyList(空则 createFamily)→ 保存 familyId → 按需管理房间与成员。所有接口都依赖有效登录态,登录过期后需重新登录并重新获取管理对象。以
familyId 为业务主键:切换家庭时需同步刷新设备列表、房间列表与成员列表,不要跨家庭复用缓存。按角色控制 UI:用
TXIoTFamilyInfo.role 判断是否展示邀请成员、移除成员、删除家庭等入口,避免普通成员触发无权限错误。房间归属需要两个管理对象:创建/重命名/删除房间用
TXIoTFamilyManager,把设备加入或移出房间用 TXIoTDeviceManager。删除房间不会解绑设备,只是把设备恢复为未分配房间状态。错误处理
错误码 | 说明 | 建议处理方式 |
ERR_INVALID_PARAMETER | 参数不合法。 | 检查家庭名称、房间名称、 roomId、邀请 Token、userId 是否为空。 |
ERR_INVALID_ACCESS_TOKEN | 登录凭证无效。 | 重新登录 SDK,并重新获取管理对象。 |
ERR_UNAUTHORIZED_OPERATION | 当前用户无权限。 | 普通成员无法邀请成员、移除他人或删除家庭,请先确认 role 为管理员。 |
ERR_FAMILY_NOT_EXIST | 家庭不存在。 | 家庭可能已被删除或已退出,重新调用 getFamilyList 刷新。 |
ERR_DEVICE_NOT_EXIST | 设备不存在。 | 调整设备房间归属时出现,请检查 productId 与 deviceName 是否正确、设备是否仍绑定在该家庭下。 |
ERR_RATE_LIMITED | 请求被限频。 | 降低调用频率,避免高频轮询家庭或成员列表。 |
错误码 | 说明 | 建议处理方式 |
TXIoTErrorCodeInvalidParameter | 参数不合法。 | 检查家庭名称、房间名称、 roomId、邀请 Token、userId 是否为空。 |
TXIoTErrorCodeInvalidAccessToken | 登录凭证无效。 | 重新登录 SDK,并重新获取管理对象。 |
TXIoTErrorCodeUnauthorizedOperation | 当前用户无权限。 | 普通成员无法邀请成员、移除他人或删除家庭,请先确认 role 为管理员。 |
TXIoTErrorCodeFamilyNotExist | 家庭不存在。 | 家庭可能已被删除或已退出,重新调用 getFamilyList 刷新。 |
TXIoTErrorCodeDeviceNotExist | 设备不存在。 | 调整设备房间归属时出现,请检查 productId 与 deviceName 是否正确、设备是否仍绑定在该家庭下。 |
TXIoTErrorCodeRateLimited | 请求被限频。 | 降低调用频率,避免高频轮询家庭或成员列表。 |
常见问题
一个账号可以有多个家庭吗?
可以。
getFamilyList 返回当前用户所属的全部家庭,既包含自己创建的(角色为管理员),也包含被邀请加入的(角色为普通成员)。App 通常在首页提供家庭切换入口,切换后需以新的 familyId 重新拉取设备、房间与成员列表。房间是必须创建的吗?
不是。房间只用于在 App 内对设备做分组展示,设备不加入任何房间也能正常绑定、查看和控制。若业务不需要分组功能,可以完全跳过房间相关接口。
邀请成员和设备分享该如何选择?
按授权范围选择:
需要对方访问家庭下全部设备、且未来新增设备也自动可见 → 用邀请 Token 让其加入家庭。
只需授权单台设备、且不希望对方看到其他设备 → 用设备分享,参见 设备分享。
如何主动退出一个家庭?
调用
removeMemberFromFamily,userId 传入当前登录用户自己的 userId(可从 TXIoTEngine.getLoginUserInfo 获取)。SDK 会自动识别为退出家庭而非移除他人,因此普通成员也能成功执行。删除家庭后,家庭下的设备会怎样?
接口参考
本文涉及接口的完整定义参见: