更新时间:2024-09-06 03:26:07下载pdf
通俗地讲,蓝牙 Mesh 就是把多个蓝牙单点设备组成一个 Mesh 网络,每个节点可以和别的节点自由通讯。通过手机直连 Mesh 网中任意一个设备,即能访问控制 Mesh 网中所有的设备。本文介绍涂鸦自研的蓝牙拓扑通信相关实现,更多有关蓝牙 Mesh 的概念介绍,请参考 蓝牙 Mesh(SIG)。
| 类名 | 说明 | 
|---|---|
| TYBLEMeshManager | 蓝牙 Mesh 封装 | 
开启蓝牙 Mesh。
// 设置 SDK 开启 Mesh,需要在初始化的时候设置。
[[TuyaSmartSDK sharedInstance] setValue:@(YES) forKey:@"bleMeshEnable"];
蓝牙 Mesh 的主要操作类都在 TuyaSmartBleMesh.h 文件中。
一个家庭里可以拥有多个蓝牙 Mesh,但建议只创建一个 Mesh。创建前,请判断下是否已经创建,若尚未创建可以通过此方法进行创建。
蓝牙 Mesh 中所有操作都建立在家庭数据已经初始化的基础上。完全初始化家庭操作,请参考 家庭管理。
接口说明
+ (void)createBleMeshWithMeshName:(NSString *)meshName
                           homeId:(long long)homeId
                          success:(void(^)(TuyaSmartBleMeshModel *meshModel))success
                          failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| meshName | Mesh 名字,用户自定义 | 
| homeId | 家庭 ID | 
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
示例代码
TuyaSmartHome *home = #<上文初始化的 home 实例>;
long long homeId = home.homeModel.homeId;
[TuyaSmartBleMesh createBleMeshWithMeshName:@"yourMeshName" homeId:homeId success:^(TuyaSmartBleMeshModel *meshModel) {
    // success do...
} failure:^(NSError *error) {
    NSLog(@"create mesh error: %@", error);
}];
此方法的 meshName 为自定义参数。建议您使用唯一参数进行设置,例如 mesh+<时间戳> 的形式。
接口说明
删除 Mesh 时,如果 Mesh 组里有子设备,会被同时移除。同时,Wi-Fi 连接器也一并移除掉。
- (void)removeMeshWithSuccess:(TYSuccessHandler)success failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
示例代码
self.mesh = #<TuyaSmartBleMesh 实例>;
[self.mesh removeMeshWithSuccess:^{
    // success do...
} failure:^(NSError *error) {
    XCTFail(@"test remove mesh failure: %@", error);
}];
接口说明
通过初始化 home 实例后,可以查询到对应家庭下的 mesh 列表。
- (void)getMeshListWithSuccess:(void(^)(NSArray <TuyaSmartBleMeshModel *> *list))success
                       failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
示例代码
TuyaSmartHome *home = #<home 实例>
[home getMeshListWithSuccess:^(NSArray<TuyaSmartBleMeshModel *> *list) {
    // success do
} failure:^(NSError *error) {
    NSLog(@"get mesh list error: %@", error);
}];
接口说明
+ (instancetype)bleMeshWithMeshId:(NSString *)meshId homeId:(long long)homeId;
参数说明
| 参数 | 说明 | 
|---|---|
| meshId | Mesh ID | 
| homeId | 当前家庭 ID | 
示例代码
通过家庭(TuyaSmartHome 实例)home 可以查询到类下的 meshModel,再通过此进行创建。并且,在创建完成之后,赋值给当前的 TuyaSmartUser 中,SDK 中以及上层封装以 TuyaSmartUser 是否有值为判断基准。
// 如果还未查询 Mesh
if ([TuyaSmartUser sharedInstance].meshModel == nil) {
    TuyaSmartHome *home = #<home 实例>
    [home getMeshListWithSuccess:^(NSArray<TuyaSmartBleMeshModel *> *list) {
            if (list.count > 0) {
                // 赋值
                [TuyaSmartUser sharedInstance].meshModel = home.meshModel;
                [TuyaSmartUser sharedInstance].mesh = [TuyaSmartBleMesh bleMeshWithMeshId:home.meshModel.meshId homeId:home.meshModel.homeId];
                // 接下来的操作
            } else {
                // 如果云端没有 Mesh 信息,则为用户创建 Mesh
                NSTimeInterval interval = [[NSDate date] timeIntervalSince1970];
                NSString *meshName = [NSString stringWithFormat:@"tymesh%.0f", interval];
                [TuyaSmartBleMesh createBleMeshWithMeshName:meshName homeId:home.homeModel.homeId success:^(TuyaSmartBleMeshModel *meshModel) {
                    // 赋值
                    [TuyaSmartUser sharedInstance].meshModel = meshModel;
                    [TuyaSmartUser sharedInstance].mesh = [TuyaSmartBleMesh bleMeshWithMeshId:meshModel.meshId homeId:home.homeModel.homeId];
                    // 接下来的操作
                } failure:^(NSError *error) {
                    // 错误处理
                }];
            }
        } failure:^(NSError *error) {
            // 错误处理
        }];
} else {
    // 接下来的操作
}
入网是对通过已配网设备连入蓝牙 Mesh 网的操作,该过程需要开启蓝牙。
接口说明
若操作为配网,填入默认的 Mesh name 和 password,此时只会通过 TYBLEMeshManagerDelegate 中的
- (void)bleMeshManager:(TYBLEMeshManager *)manager didScanedDevice:(TYBleMeshDeviceModel *)device; 返回扫描结果。
若操作为入网,填入已创建的 Mesh name 和 password,此信息来自云端接口返回,可以自动进行连接、入网。并自动查询一次 Mesh 网中的各个设备在线情况。
- (void)startScanWithName:(NSString *)name
					pwd:(NSString *)pwd
				active:(BOOL)active
			wifiAddress:(uint32_t)wifiAddress
			otaAddress:(uint32_t)otaAddress;
参数说明
| 参数 | 说明 | 
|---|---|
| name | Mesh 名称 | 
| pwd | Mesh 密码 | 
| active | 是否为配网激活 | 
| wifiAddress | Wi-Fi 地址,网关配网需要,其余情况传 0 | 
| otaAddress | 待 OTA 升级的设备地址,OTA 升级时需要使用该参数,其余情况传 0 | 
回调接口
入网成功会自动查询 Mesh 网中设备的在线状态,并触发 TuyaSmartHomeDelegate 代理方法进行回调信息.
// 设备信息更新,例如 name
- (void)home:(TuyaSmartHome *)home deviceInfoUpdate:(TuyaSmartDeviceModel *)device;
示例代码
// 注意,此时的 active、wifiAddress、otaAddress 参数赋值情况
[[TYBLEMeshManager sharedInstance] startScanWithName:[TuyaSmartUser sharedInstance].meshModel.code pwd:[TuyaSmartUser sharedInstance].meshModel.password active:NO wifiAddress:0 otaAddress:0];
// 设备信息更新,例如 name
- (void)home:(TuyaSmartHome *)home deviceInfoUpdate:(TuyaSmartDeviceModel *)device {
    // 收到回调操作
}
配网指的是将处于重置状态、未入网的设备,添加到蓝牙 Mesh 网中。蓝牙 Mesh 配网主要分为两种:
蓝牙 Mesh 的操作类集中在 TYBLEMeshManager 中,且此类为单例。
处于重置状态的设备,默认名字为 out_of_mesh,默认密码为 123456。下表列举了常用设备的重置方式:
| 产品类型 | 重置操作 | 可配网现象 | 
|---|---|---|
| 照明 | 连续开关三次 | 灯快闪 | 
| 插座 | 长按开关 3 秒 | 插座指示灯快闪 | 
| 网关 | 长按开关 3 秒 | 红灯和蓝灯快闪 | 
| 低功耗设备 | 长按开关 3 秒 | 再按一次出现长亮即可配网,且配网需在灯亮期间完成 | 
| 报警器 | 长按开关 3 秒 | 灯快闪 | 
为了简化扫描以及后续的配网操作,涂鸦将所有的操作统一封装在一个接口中进行操作。
若操作为配网,填入默认的 Mesh name 和 password,此时只会通过 TYBLEMeshManagerDelegate 中的
- (void)bleMeshManager:(TYBLEMeshManager *)manager didScanedDevice:(TYBleMeshDeviceModel *)device; 返回扫描结果。
若操作为入网,填入已创建的 Mesh name 和 password,此信息来自云端接口返回,可以自动进行连接、入网。并自动查询一次 Mesh 网中的各个设备在线情况。
接口说明
- (void)startScanWithName:(NSString *)name
                      pwd:(NSString *)pwd
                   active:(BOOL)active
              wifiAddress:(uint32_t)wifiAddress
               otaAddress:(uint32_t)otaAddress;
参数说明
| 参数 | 说明 | 
|---|---|
| name | Mesh 名称 | 
| pwd | Mesh 密码 | 
| wifiAddress | Wi-Fi 地址,网关配网需要,其余情况传 0 | 
| otaAddress | 待 OTA 升级的设备地址,OTA 升级时需要使用该参数,其余情况传 0 | 
回调接口
若传入的 name 为默认值 out_of_mesh,且为激活操作,会扫描周围待配网的设备。扫描的结果会以 TYBLEMeshManagerDelegate 中的方法进行回调。
如果为入网操作,则会自动进行后续操作,不会回调。调用入网接口的示例,可参考 Mesh 的连接与断开。
- (void)bleMeshManager:(TYBLEMeshManager *)manager didScanedDevice:(TYBleMeshDeviceModel *)device;
参数说明
| 参数 | 说明 | 
|---|---|
| manager | Mesh 管理器 | 
| device | 待配网设备信息 | 
示例代码
// 开始扫描待配网的设备
[[TYBLEMeshManager sharedInstance] startScanWithName:@"out_of_mesh" pwd:@"123456" active:YES wifiAddress:0 otaAddress:0];
// TYBLEMeshManagerDelegate 扫描回调方法
- (void)bleMeshManager:(TYBLEMeshManager *)manager didScanedDevice:(TYBleMeshDeviceModel *)device {
    // 扫描到的网关设备和子设备都会通过此方法进行回调
    // 通过 device.type 和 device.vendorInfo 来判定是否为 Mesh 网关
    if (device.type == [TPUtils getIntValueByHex:@"0x0108"] || ([TPUtils getIntValueByHex:[device.vendorInfo substringWithRange:NSMakeRange(0, 2)]] & 0x08) == 0x08) {
          // Mesh 网关
        return;
    } else {
        // Mesh 子设备
    }
}
// getIntValueByHex 实现
+ (uint32_t)getIntValueByHex:(NSString *)getStr
{
    NSScanner *tempScaner=[[NSScanner alloc] initWithString:getStr];
    uint32_t tempValue;
    [tempScaner scanHexInt:&tempValue];
    return tempValue;
}
接口说明
- (void)activeMeshDeviceIncludeGateway:(BOOL)includeGateway;
参数说明
| 参数 | 说明 | 
|---|---|
| includeGateway | 是否激活网关,若为 yes,则会激活已记录扫描到设备中的网关设备,其余子设备不激活反之激活所有的已扫描的普通的 Mesh 子设备,不激活网关 | 
回调接口
- (void)activeDeviceSuccessWithName:(NSString *)name deviceId:(NSString *)deviceId error:(NSError *)error;
参数说明
| 参数 | 说明 | 
|---|---|
| name | 设备名称 | 
| deviceId | 设备 ID | 
| error | 激活中的错误,若发生错误,name 以及 deviceId 为空 | 
接口说明
- (void)activeMeshDevice:(TYBleMeshDeviceModel *)deviceModel;
参数说明
| 参数 | 说明 | 
|---|---|
| deviceModel | 设备模型 | 
配网结果会通过 TYBLEMeshManagerDelegate 进行回调。
回调接口
- (void)activeWifiDeviceWithName:(NSString *)name address:(NSInteger)address mac:(NSInteger)mac error:(NSError *)error;
参数说明
| 参数 | 说明 | 
|---|---|
| name | 设备名称 | 
| address | 设备地址 | 
| mac | 网关 Mac | 
| error | 激活中的错误 | 
若激活的为网关设备,需要在收到回调 activeWifiDeviceWithName  方法过后,需要再进行与 Wi-Fi 模组进行配网。这时,您需要调用 TuyaSmartActivator 中方法执行操作。
接口说明
配网 Token 的有效期为 10 分钟。
- (void)getTokenWithMeshId:(NSString *)meshId
                    nodeId:(NSString *)nodeId
                 productId:(NSString *)productId
                      uuid:(NSString *)uuid
                   authKey:(NSString *)authKey
                   version:(NSString *)version
                   success:(TYSuccessString)success
                   failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| meshId | Mesh ID | 
| nodeId | node ID | 
| productId | 产品的 ID,即 PID(Product ID) | 
| uuid | 设备 uuid | 
| authKey | 设备 authKey | 
| success | 操作成功回调,返回配网 Token | 
| failure | 操作失败回调 | 
传入配网 Token、路由器热点名称、路由器热点密码信息,进行 Mesh 网关配网。需要实现激活网关后,收到 TYBLEMeshManagerDelegate 的 activeWifiDeviceWithName 回调,方可以调用此方法。
接口说明
- (void)startBleMeshConfigWiFiWithSsid:(NSString *)ssid
                              password:(NSString *)password
                                 token:(NSString *)token
                               timeout:(NSTimeInterval)timeout;
参数说明
| 参数 | 说明 | 
|---|---|
| ssid | 路由器热点名称 | 
| password | 路由器热点密码 | 
| token | 配网 Token | 
| timeout | 超时时间,默认为 100 秒 | 
示例代码
// Mesh 子设备(不带网关的设备)入网
// 1. 激活子设备
[[TYBLEMeshManager sharedInstance] activeMeshDeviceIncludeGateway:NO];
// 2. TYBLEMeshManagerDelegate 回调
- (void)activeDeviceSuccessWithName:(NSString *)name deviceId:(NSString *)deviceId error:(NSError *)error {
    if (error) {
        NSLog(@"error : %@", error);
        return;
    }
    // 3. 激活成功,至此,一个子设备激活完成
}
// 网关激活
// 1. 激活子设备
[[TYBLEMeshManager sharedInstance] activeMeshDeviceIncludeGateway:NO];
// 2. TYBLEMeshManagerDelegate 回调
- (void)activeWifiDeviceWithName:(NSString *)name address:(NSInteger)address mac:(NSInteger)mac error:(NSError *)error {
    if (error) {
       NSLog(@"error : %@", error);
       return;
    }
    // 激活网关成功,目前只成功蓝牙模组,还需要继续配置 Wi-Fi 模组激活
    // 3. 用户输入密码再去重连,重连成功后再发送 ssid, pwd, token,
    // !注意,一定要做此操作,不然会影响 Wi-Fi 信息写入导致配网失败
    [TYBLEMeshManager sharedInstance].wifiMac = (int)mac;
    // 4. 查询 token
    NSString *nodeId = [NSString stringWithFormat:@"%02x", (int)address];
    [[TuyaSmartActivator sharedInstance] getTokenWithMeshId:[TuyaSmartUser sharedInstance].meshModel.meshId
                                                 nodeId:nodeId
                                              productId:[TYBLEMeshManager sharedInstance].productId
                                                   uuid:[TYBLEMeshManager sharedInstance].uuid
                                                authKey:[TYBLEMeshManager sharedInstance].authKey
                                                version:[TYBLEMeshManager sharedInstance].version
                                                success:^(NSString *token) {
                                                    // 5. 设置配网代理,通过代理接收激活结果
                                                    [TuyaSmartActivator sharedInstance].delegate = self;
                                                    // 6. 开始 Wi-Fi 配网
                                                    [[TuyaSmartActivator sharedInstance] startBleMeshConfigWiFiWithSsid:@"Wi-Fi 名称" password:@"Wi-Fi 密码" token:token timeout:100];
                                                } failure:^(NSError *error) {
                                                    NSLog(@"error: %@", error);
                                                }];
}
- (void)meshActivator:(TuyaSmartActivator *)activator didReceiveDeviceId:(NSString *)deviceId meshId:(NSString *)meshId error:(NSError *)error {
      // 7. 收到激活结果
  }
在操作的过程中,会经常判断是否是 Mesh 已有设备通过蓝牙入网,来决定使用何种方式下发控制命令和操作命令。
// Mesh 本地连接标识,有设备通过蓝牙连接,此属性为 yes
BOOL isLogin = [TYBLEMeshManager sharedInstance].isLogin;
| 错误码 | 说明 | 
|---|---|
| 3088 | 激活设备失败 | 
| 3090 | Mesh name 和 password 错误 | 
| 3091 | 登录失败 | 
| 3092 | 登录解密失败 | 
| 3093 | 查询 auth key 失败 | 
| 3094 | 地址超出限制 | 
| 3095 | 修改地址失败 | 
| 3096 | 写入 mesh 信息失败 | 
| 3097 | Mesh 信息为空 | 
| 3098 | Mesh 未入网 | 
| 3099 | 写入失败 | 
| 4000 | Wi-Fi 信息有误 | 
| 4001 | Wi-Fi 配网 Token 错误 | 
| 4010 | 登录超时 | 
| 4011 | 查询 auth key 超时 | 
| 4012 | 修改地址超时 | 
| 4013 | 写入 Mesh 信息超时 | 
| 4014 | 设置 Wi-Fi 信息超时 | 
设备类是 TuyaSmartDevice,里面的 TuyaSmartDeviceModel 中的 deviceType 信息可以区分设备类型。其中,Mesh 设备对应 deviceType 类型为 TuyaSmartDeviceModelTypeSIGMeshSubDev。
接口说明
- (void)renameMeshSubDeviceWithDeviceId:(NSString *)deviceId name:(NSString *)name success:(TYSuccessHandler)success failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| deviceId | 设备 ID | 
| name | 新的名字 | 
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
示例代码
[[TuyaSmartUser sharedInstance].mesh renameMeshSubDeviceWithDeviceId:self.device.devId name:name success:^{
            // success do
        } failure:^(NSError *error) {
            // failure do
        }];
向 Mesh 网络中加入设备(设备入网 2.0)
SDK 中配网时已自动处理,若无特殊必要,可忽略。
- (void)addSubDeviceWithUuid:(NSString *)uuid
                      homeId:(long long)homeId
                     authKey:(NSString *)authKey
                      nodeId:(NSString *)nodeId
                  productKey:(NSString *)productKey
                         ver:(NSString *)ver
                     success:(void (^)(NSString *devId, NSString *name))success
                     failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| uuid | 蓝牙子设备短地址标识 | 
| authKey | 授权 | 
| nodeId | Mesh 节点 ID(短地址) | 
| productKey | 产品 ID | 
| ver | 版本号 | 
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
示例代码
[[TuyaSmartUser sharedInstance].mesh addSubDeviceWithUuid:_uuid homeId:[TuyaSmartUser sharedInstance].meshModel.homeId authKey:_authKey nodeId:nodeHex productKey:_selectedPeripheral.productId ver:_selectedPeripheral.version success:^(NSString *devId, NSString *name) {
                    // success do
                    } failure:^(NSError *error) {
                    // failure do
                    }];
Mesh 子设备的本地连接为在线情况的一种。手机蓝牙开启且 Mesh 子设备通过蓝牙进行连接控制,下发命令通过蓝牙完成。判断条件为 deviceModel.isOnline && deviceModel.isMeshBleOnline。
Mesh 子设备的网关连接为在线情况的一种。手机蓝牙未开启或距离设备远,Mesh 设备通过网关进行连接控制,下发命令通过 Wi-Fi 完成。判断条件为 deviceModel.isOnline && !deviceModel.isMeshBleOnline。
移除设备需要同时在云端和本地删除设备。
本地删除
// 通过蓝牙
- (void)kickoutLightWithAddress:(uint32_t)address type:(NSString *)type;
// 通过网关
- (NSString *)rawDataKickoutLightWithAddress:(uint32_t)address type:(NSString *)type;
   /**
    给设备发送透传指令
    @param raw 透传值
    @param success 操作成功的回调
    @param failure 操作失败的回调
    */
- (void)publishRawDataWithRaw:(NSString *)raw
                          pcc:(NSString *)pcc
                      success:(TYSuccessHandler)success
                      failure:(TYFailureError)failure;
云端删除
- (void)removeMeshSubDeviceWithDeviceId:(NSString *)deviceId success:(TYSuccessHandler)success failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| deviceId | 设备 ID | 
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
代码示例
 int address = [smartDevice.deviceModel.nodeId intValue] << 8;
        // 1.  云端删除
        [[TuyaSmartUser sharedInstance].mesh removeMeshSubDeviceWithDeviceId:[smartDevice.deviceModel.devId success:^{
        } failure:^(NSError *error) {
        }];
        // 2. 本地删除
        // 判断连接情况,使用网关还是蓝牙
        if ([TYBLEMeshManager sharedInstance].isLogin) {
            [[TYBLEMeshManager sharedInstance] kickoutLightWithAddress:address type:[smartDevice.deviceModel.pcc];
        } else {
            [[TuyaSmartUser sharedInstance].mesh publishRawDataWithRaw:[[TYBLEMeshManager sharedInstance] rawDataKickoutLightWithAddress:address type:[smartDevice.deviceModel.pcc] pcc:[smartDevice.deviceModel.pcc success:^{
            } failure:^(NSError *error) {
            }];
        }
接口说明
- (void)getDeviceStatusAllWithAddress:(uint32_t)address
                                 type:(NSString *)type;
参数说明
| 参数 | 说明 | 
|---|---|
| address | 设备地址 | 
| type | 设备的大小类 | 
在蓝牙 Mesh 网中,可以将一些设备组成群组,使用群组命令控制群组中的设备。例如,将所有灯组添加到某个群组中,通过控制群组的开关、颜色等,直接控制群组中所有的灯具有相同的属性。
管理群组可以调用 TuyaSmartBleMeshGroup 的以下方法。
创建时,群组地址的 localId 从 0x8001 开始,依次叠加。
群组的大小类和设备一样,传入表示此群组约定此类设备组建为群组
目前每个 Mesh 最多支持添加 255 个群组,1 个设备最多只能加入 8 个群组。
建议不要将不同品类的设备加入到同一个群组,否则,可能会因为设备功能的不同导致控制失败。
接口说明
+ (void)createMeshGroupWithGroupName:(NSString *)groupName
                              meshId:(NSString *)meshId
                             localId:(NSString *)localId
                                 pcc:(NSString *)pcc
                             success:(TYSuccessInt)success
                             failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| groupName | Mesh 群组名字 | 
| meshId | Mesh ID | 
| localId | 群组的本地短地址 | 
| pcc | 群组设备大小类 | 
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
示例代码
NSInteger localId = 0x8001;
[TuyaSmartBleMeshGroup createMeshGroupWithGroupName:@<群组名称> meshId:[TuyaSmartUser sharedInstance].meshModel.meshId localId:[NSString stringWithFormat:@"%lx", localId] pcc:#<群组的大小类> success:^(int result) {
     // success do
    // 可以查询到 group 实例
     self.meshGroup = [TuyaSmartBleMeshGroup meshGroupWithGroupId:result];
    } failure:^(NSError *error) {
       // failure do
    }];
向群组内加设备,需要经过本地和云端双重验证,才能算作一个设备成功加入到群组。添加设备时,请一个一个地进行,并按顺序执行。不要并发进行。
添加流程

接口说明
// 本地连接
// 添加设备到群组方法,该方法执行后会通过 TYBLEMeshManagerDelegate 方法回调
- (void)addDeviceAddress:(uint32_t)deviceAddress type:(NSString *)type groupAddress:(uint32_t)groupAddress;
// TYBLEMeshManagerDelegate
- (void)deviceAddGroupAddress:(uint32_t)address error:(NSError *)error;
// 网关连接
  // 查询添加设备到群组命令 raw
- (NSString *)rawDataAddDeviceAddress:(uint32_t)deviceAddress groupAddress:(uint32_t)groupAddress type:(NSString *)type;
接口说明
给设备发送透传指令。
- (void)publishRawDataWithRaw:(NSString *)raw
                            pcc:(NSString *)pcc
                        success:(TYSuccessHandler)success
                        failure:(TYFailureError)failure;
  //发送的 raw 消息会通过 `TuyaSmartBleMeshDelegate` - (void)bleMeshReceiveRawData:(NSString *)raw 回调
  // TuyaSmartBleMeshDelegate
- (void)bleMeshReceiveRawData:(NSString *)raw;
参数说明
| 参数 | 说明 | 
|---|---|
| raw | 透传值 | 
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
接口说明
待到上述验证完成后,可通过此方法将操作记录到云端后,可以进行下一个设备的操作。
- (void)addDeviceWithDeviceId:(NSString *)deviceId success:(TYSuccessHandler)success failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
示例代码
- (void)addDeviceToGroup:(TuyaSmartDeviceModel *)model {
        int nodeId = [model.nodeId intValue] << 8;
        // 记录当前设备的地址,作为后续判断
        _address = nodeId >> 8;
        if ([TYBLEMeshManager sharedInstance].isLogin) {
            // ble
            [[TYBLEMeshManager sharedInstance] addDeviceAddress:nodeId type:self.meshGroup.meshGroupModel.pcc groupAddress:[self.meshGroup.meshGroupModel.localId intValue]];
        } else {
            // wifi
            [[TuyaSmartUser sharedInstance].mesh publishRawDataWithRaw:[[TYBLEMeshManager sharedInstance] rawDataAddDeviceAddress:nodeId groupAddress:[self.meshGroup.meshGroupModel.localId intValue] type:self.meshGroup.meshGroupModel.pcc] pcc:self.meshGroup.meshGroupModel.pcc success:^{
            } failure:^(NSError *error) {
            }];
        }
        // 标记当前操作为新增
        _isAdd = YES;
    // 这里可以自己做超时,建议为 5s 未收到表示失败,执行下一个
}
#pragma mark - TYBLEMeshManagerDelegate
- (void)deviceAddGroupAddress:(uint32_t)address; {
    NSLog(@" --- deviceAddGroupAddress %d ", address);
    if (_address == address) {
            [self.meshGroup addDeviceWithDeviceId:_devId success:^{
                // 操作成功,执行下一个
            } failure:^(NSError *error) {
            }];
    }
}
#pragma mark - TuyaSmartBleMeshDelegate
// 网关连接下,组建群组会触发此方法
- (void)bleMeshReceiveRawData:(NSString *)raw {
    if ([[raw substringWithRange:NSMakeRange(4, 2)] isEqualToString:@"d4"] && _address == [TPUtils getIntValueByHex:[raw substringWithRange:NSMakeRange(0, 2)]]) {
        if (raw.length < 14) {
            NSLog(@"raw 长度错误");
            return;
        }
        BOOL isNewProtocol = [TPUtils getIntValueByHex:[raw substringWithRange:NSMakeRange(10, 2)]] == 255;
        if (isNewProtocol) {
            int state = [TPUtils getIntValueByHex:[raw substringWithRange:NSMakeRange(12, 2)]];
            if (state == 1 || state == 255) {
                NSLog(@"设备群组操作成功");
            } else {
                   // 操作失败执行下一个
                return;
            }
        }
            [self.meshGroup addDeviceWithDeviceId:_devId success:^{
                // 操作成功,执行下一个
            } failure:^(NSError *error) {
            }];
    }
}
和向群组添加设备操作流程类似,从群组内删除设备,需要经过本地和云端双重验证,才能算作一个设备从群组内删除。移除设备时,请一个一个地进行,并按顺序执行。不要并发进行。
移除流程

接口说明
// 本地连接
// 删除群组内某个设备方法,该方法执行后会通过 TYBLEMeshManagerDelegate 方法回调
- (void)deleteDeviceAddress:(uint32_t)deviceAddress type:(NSString *)type groupAddress:(uint32_t)groupAddress;
// TYBLEMeshManagerDelegate
- (void)deviceAddGroupAddress:(uint32_t)address error:(NSError *)error;
// 网关连接
// 查询删除群组内设备命令 raw
- (NSString *)rawDataDeleteDeviceAddress:(uint32_t)deviceAddress groupAddress:(uint32_t)groupAddress type:(NSString *)type;
接口说明
- (void)publishRawDataWithRaw:(NSString *)raw
                          pcc:(NSString *)pcc
                      success:(TYSuccessHandler)success
                      failure:(TYFailureError)failure;
//发送的 raw 消息会通过 `TuyaSmartBleMeshDelegate` - (void)bleMeshReceiveRawData:(NSString *)raw 回调
// TuyaSmartBleMeshDelegate
- (void)bleMeshReceiveRawData:(NSString *)raw;
参数说明
| 参数 | 说明 | 
|---|---|
| raw | 透传值 | 
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
接口说明
待到上述验证完成后,可通过此方法将操作记录到云端后,可以进行下一个设备的操作。
- (void)removeDeviceWithDeviceId:(NSString *)deviceId success:(TYSuccessHandler)success failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| deviceId | 设备 ID | 
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
示例代码
- (void)deleteDeviceFromGroup:(TuyaSmartDeviceModel *)model {
        int nodeId = [model.nodeId intValue] << 8;
        // 记录当前操作的设备地址,用于后续回调判断
        _address = nodeId >> 8;
        if ([TYBLEMeshManager sharedInstance].isLogin) {
            // ble
            [[TYBLEMeshManager sharedInstance] deleteDeviceAddress:nodeId type:self.meshGroup.meshGroupModel.pcc groupAddress:[self.meshGroup.meshGroupModel.localId intValue]];
        } else {
            // wifi
            [[TuyaSmartUser sharedInstance].mesh publishRawDataWithRaw:[[TYBLEMeshManager sharedInstance] rawDataDeleteDeviceAddress:nodeId groupAddress:[self.meshGroup.meshGroupModel.localId intValue] type:self.meshGroup.meshGroupModel.pcc] pcc:self.meshGroup.meshGroupModel.pcc success:^{
            } failure:^(NSError *error) {
            }];
        }
        // 标记当前操作为删除
        _isAdd = NO;
    // 这里可以自己做超时,建议为 5s 未收到表示失败,执行下一个
}
#pragma mark - TYBLEMeshManagerDelegate
- (void)deviceAddGroupAddress:(uint32_t)address; {
    NSLog(@" --- deviceAddGroupAddress %d ", address);
    if (_address == address) {
            [self.meshGroup removeDeviceWithDeviceId:_devId success:^{
                // 操作成功,执行下一个
            } failure:^(NSError *error) {
            }];
    }
}
#pragma mark - TuyaSmartBleMeshDelegate
// 网关连接下,组建群组会触发此方法
- (void)bleMeshReceiveRawData:(NSString *)raw {
    if ([[raw substringWithRange:NSMakeRange(4, 2)] isEqualToString:@"d4"] && _address == [TPUtils getIntValueByHex:[raw substringWithRange:NSMakeRange(0, 2)]]) {
        if (raw.length < 14) {
            NSLog(@"raw 长度错误");
            return;
        }
        BOOL isNewProtocol = [TPUtils getIntValueByHex:[raw substringWithRange:NSMakeRange(10, 2)]] == 255;
        if (isNewProtocol) {
            int state = [TPUtils getIntValueByHex:[raw substringWithRange:NSMakeRange(12, 2)]];
            if (state == 1 || state == 255) {
                NSLog(@"设备群组操作成功");
            } else {
                   // 操作失败执行下一个
                return;
            }
        }
            [self.meshGroup removeDeviceWithDeviceId:_devId success:^{
                // 删除成功,执行下一个
            } failure:^(NSError *error) {
            }];
    }
}
接口说明
+ (instancetype)meshGroupWithGroupId:(NSInteger)groupId;
参数说明
| 参数 | 说明 | 
|---|---|
| groupId | 群组 ID | 
此处的 groupId 并非上面所述 localId,是由添加群组成功之后,云端返回的群组 ID。并且注意,所有的群组操作下发的地址都只是和 localId 有关。
接口说明
- (void)updateMeshGroupName:(NSString *)meshGroupName success:(TYSuccessHandler)success failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| meshGroupName | Mesh 群组名称 | 
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
删除群组和添加或者移除设备一样,都需要经过本地删除和云端删除。
接口说明
// 本地删除
- (void)deleteGroupAddress:(uint32_t)groupAddress type:(NSString *)type;
// 网关连接
- (NSString *)rawDataDeleteGroupAddress:(uint32_t)groupAddress type:(NSString *)type
接口说明
// 给设备发送透传指令
- (void)publishRawDataWithRaw:(NSString *)raw
                          pcc:(NSString *)pcc
                      success:(TYSuccessHandler)success
                      failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| raw | 透传值 | 
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
接口说明
// 云端删除
- (void)removeMeshGroupWithSuccess:(TYSuccessHandler)success failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
示例代码
[self.meshGroup removeMeshGroupWithSuccess:^{
		// 云端删除成功
} failure:^(NSError *error) {
	// 云端删除失败
}];
// 如果是本地连接
if ([TYBLEMeshManager sharedInstance].isLogin) {
	// 通过蓝牙命令删除群组
	[[TYBLEMeshManager sharedInstance] deleteGroupAddress:[self.meshGroup.meshGroupModel.localId intValue] type:self.meshGroup.meshGroupModel.pcc];
} else {
	// wifi
	// 通过网关删除群组
	[[TuyaSmartUser sharedInstance].mesh publishRawDataWithRaw:[[TYBLEMeshManager sharedInstance] rawDataDeleteGroupAddress:[self.meshGroup.meshGroupModel.localId intValue] type:self.meshGroup.meshGroupModel.pcc] pcc:self.meshGroup.meshGroupModel.pcc success:^{
	} failure:^(NSError *error) {
	}];
}
接口说明
- (void)getDeviveListInfoWithSuccess:(void (^)(NSArray <TuyaSmartDeviceModel *> *deviceList))success failure:(TYFailureError)failure;
示例代码
[self.meshGroup getDeviveListInfoWithSuccess:^(NSArray<TuyaSmartDeviceModel *> *deviceList) {
        // 查询成功
} failure:^(NSError *error) {
            // 查询失败
        }];
由于涂鸦使用 DP 管理设备的功能,因此,蓝牙 Mesh 相关的控制是根据设备的 DP 信息来进行操作。
Mesh 指令下发是根据设备的 DP 信息来进行操作
发送控制指令按照以下格式:{"(dpId)" : "(dpValue)"}, 如 @{@"101" : @"44"}。DP 指令详情,请参考 设备控制。
接口说明
- (void)publishNodeId:(NSString *)nodeId
                  pcc:(NSString *)pcc
                  dps:(NSDictionary *)dps
              success:(TYSuccessHandler)success
              failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| nodeId | 蓝牙子设备短地址标识 | 
| pcc | 大小类标示 | 
| dps | 命令字典 | 
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
示例代码
int address = [[self.smartDevice deviceModel].nodeId intValue] << 8;
[self.mesh publishNodeId:[NSString stringWithFormat:@"%d", address] pcc:self.smartDevice.deviceModel.pcc dps:@{@"1":@(1)} success:^{
    // success do
    } failure:^(NSError *error) {
    // error do
}];
接口说明
- (void)multiPublishWithLocalId:(NSString *)localId
                            pcc:(NSString *)pcc
                            dps:(NSDictionary *)dps
                        success:(TYSuccessHandler)success
                        failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| localId | localId | 
| pcc | 大小类标示 | 
| dps | 命令字典 | 
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
示例代码
int address = [[self.meshGroup meshGroupModel].localId intValue];
[self.mesh multiPublishWithLocalId:[NSString stringWithFormat:@"%d", address] pcc:self.meshGroup.meshGroupModel.pcc dps:@{@"1":@(1)} success:^{
    // success do
    } failure:^(NSError *error) {
    // error do
}];
TYBLEMeshManager 类头中提供了一些设备的透传(raw)命令。
接口说明
- (void)publishRawDataWithRaw:(NSString *)raw
                          pcc:(NSString *)pcc
                      success:(TYSuccessHandler)success
                      failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| raw | 透传值 | 
| success | 操作成功回调 | 
| failure | 操作失败回调 | 
发送命令后,如果是有返回的命令,设备的数据回复通过 TuyaSmartHomeDelegate 中代理回调。
接口说明
// 设备 DP 数据更新
- (void)home:(TuyaSmartHome *)home device:(TuyaSmartDeviceModel *)device dpsUpdate:(NSDictionary *)dps;
接口说明
- (void)getFirmwareUpgradeInfo:(void (^)(NSArray <TuyaSmartFirmwareUpgradeModel *> *upgradeModelList))success failure:(TYFailureError)failure;
/**
升级的信息会通过结果值返回,可以根据 type 信息去确定是否需要升级
     0  升级中
     1  无升级
     2  有强制或提醒升级
     3  有检测升级
判断为需要升级后,具体的固件地址在返回值中,下载之后转成 data 进行后续操作
*/
升级前需要确保蓝牙已开启,然后连接目标设备,准备升级。
若操作为配网,填入默认的 Mesh name 和 password,此时只会通过 TYBLEMeshManagerDelegate 中的
- (void)bleMeshManager:(TYBLEMeshManager *)manager didScanedDevice:(TYBleMeshDeviceModel *)device; 返回扫描结果。
若操作为入网,填入已创建的 Mesh name 和 password,此信息来自云端接口返回,可以自动进行连接、入网。并自动查询一次 Mesh 网中的各个设备在线情况。
接口说明
- (void)startScanWithName:(NSString *)name
                      pwd:(NSString *)pwd
                   active:(BOOL)active
              wifiAddress:(uint32_t)wifiAddress
               otaAddress:(uint32_t)otaAddress;
参数说明
| 参数 | 说明 | 
|---|---|
| name | Mesh 名称 | 
| pwd | Mesh 密码 | 
| active | 是否为配网激活 | 
| wifiAddress | Wi-Fi 地址,网关配网需要,其余情况传 0 | 
| otaAddress | 待 OTA 升级的设备地址,OTA 升级时需要使用该参数,其余情况传 0 | 
设置后,会进行连接,通过 TYBLEMeshManagerDelegate 代理方法可以收到连接情况。
接口说明
升级时,已成功连接到 Mesh 网。
- (void)notifyLoginSuccessWithAddress:(uint32_t)address;
参数说明
| 参数 | 说明 | 
|---|---|
| address | 设备地址 | 
收到回调后发送升级包
- (void)sendOTAPackWithAddress:(NSInteger)address version:(NSString *)version otaData:(NSData *)otaData success:(TYSuccessHandler)success failure:(TYFailureHandler)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| address | 设备地址 | 
| version | 版本号 | 
| otaData | 升级数据 | 
| success | 成功回调 | 
| failure | 失败回调 | 
向云端更新版本号
- (void)updateDeviceVersion:(NSString *)version type:(NSInteger)type success:(TYSuccessHandler)success failure:(TYFailureError)failure;
参数说明
| 参数 | 说明 | 
|---|---|
| version | 版本号 | 
| type | 固件类型 | 
| success | 成功回调 | 
| failure | 失败回调 | 
示例代码
1. 准备升级
int otaAddress = [self.device.deviceModel.nodeId intValue] << 8;
// 直连
    [[TYBLEMeshManager sharedInstance] startScanWithName:[TuyaSmartUser sharedInstance].meshModel.code pwd:[TuyaSmartUser sharedInstance].meshModel.password active:NO wifiAddress:0 otaAddress:otaAddress];
    [TYBLEMeshManager sharedInstance].delegate = self;
2. 回调并发送升级包
- (void)notifyLoginSuccessWithAddress:(uint32_t)address {
    [[TYBLEMeshManager sharedInstance] sendOTAPackWithAddress:address version:@"升级号" otaData:_otaData success:^{
        [self updateVersion];
    } failure:^{
        NSLog(@"ota failure!");
    }];
}
3. 向云端更新版本号
- (void)updateVersion {
    WEAKSELF_AT
    [self.smartDevice updateDeviceVersion:_upgradeModel.version type:_upgradeModel.type success:^{
       // success do..
    } failure:^(NSError *error) {
       // error do..
    }];
}
使用前,请先确定固件支持场景。
场景 1 到场景 4 是静彩模式。更改场景 1:
{set_scene1="0ff808000000000E0"}
0:表示是静彩模式
ff:R
80:G
80:B
00:W  暖
00:C  冷
00:L  亮度值
00:S  step  (暂时都设置为 0)
E0:V  有效性 (表示上方 RGBWCLS 的有效性 )  RGB 有效是 E0   WCL 有效是 1C
场景 5 到场景 8 是炫彩模式。更改场景 5:
{set_scene5="180ff560055AA0055AA"}
1:表示是炫彩模式
80:对于 HLS 中 L 亮度
ff:对应 HLS 中 S 饱和度
56:二进制 01010110,高 5bit 为渐变时间 time=10(单位为 200ms),对应真实时间为 10*200ms=2s;低 3bit 为渐变组数 group=6 组
00、55、AA、00、55、AA:对应 HLS 中 H 色相  6 组
根据上面的 L 和 S,再加上每组的 H,一共可以计算出六组 RGB 数据。
0 c7 ed cc c8 37 64 00 e0
进入场景 发送 null 查询 查询场景具体值
{set_scene1=null}
切换白光:109 = "white"
切换彩光:可以直接发 rgb 命令,也可发 109 = "colour"
切换场景 1:109 = "scene_1"
切换场景 2:109 = "scene_2"
切换场景 3:109 = "scene_3"
...
切换场景 8:109 = "scene_8"
设置场景 1 - 8:DP 依次为 111 - 118
例如设置场景 5:115 = "0f19ec27f806400e0"
其中格式可以按照之前的文档格式进行下发设置
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈