蓝牙 Mesh(SIG)

更新时间:2024-03-22 09:06:15下载pdf

蓝牙 Mesh,也就是将蓝牙设备组成网络,每个蓝牙设备可以通过网络内的蓝牙设备进行通讯,将一端的蓝牙信息通过 Mesh 网络传到较远的另一端。本文介绍了 iOS 版商用照明 App SDK 的蓝牙 Mesh 相关接口和调用示例。

基础概念

蓝牙技术联盟(Bluetooth Special Interest Group,简称蓝牙 SIG)蓝牙技术全面支持 Mesh 网状网络。标准蓝牙 Mesh 也叫做 SIG Mesh,是蓝牙技术联盟提出的 Mesh 网络的通讯标准。使用蓝牙 Mesh 进行组网及设备功能的更新,均需要满足标准蓝牙 Mesh 的标准。

名词解释

专有名词 说明
大小类 每个 Mesh 设备都对应一款产品,每个产品都有自己的大小类标示,SDK 中以 pcctype 作为大小类标示。
Mesh 群组 localId 2 字节,localId 用于区分每个 Mesh 群组在 Mesh 网中的 唯一标识。当您想控制某个群组中的设备时,就向 Mesh 网发此群组对应的 localId 命令即可。
Mesh 节点 nodeId 2 字节,nodeId 用于区分每个 Mesh 设备在 Mesh 网中的 唯一标识。当您想控制某个设备时,就向 Mesh 网发此设备对应的 nodeId 命令即可
本地连接 已配网设备通过蓝牙连接,来控制 Mesh 和指令操作。
网关连接 已配网设备通过网关连接(网关需和设备在一起,距离不能太远),来控制 Mesh 和指令操作。

多步操作

因为设备的操作,例如增删操作、群组操作,都需要本地蓝牙命令执行一次、云端记录一次。因此,向本地 Mesh 网同步操作信息的同时,也需要向云端同步操作信息。

设备规则(大小类)

  • 组成:设备类别值由 设备类型 + 大类 + 小类 组成后小端排列。

    • 设备类型:
      • 标准型:1
      • 透传型:2
    • 大类编号:蓝牙 Mesh 产品目前分为三大类
      • 照明类:01,表示 1-5 路 RGBWC 彩灯
      • 电工类:02,表示 1-6 路插座
      • 遥控器:05,表示 1-6 个按键
    • 小类编号:
      • 1-5 路灯:1-5
      • 1-6 路排插:1-6
      • 1-6 个遥控器按键:1-6
  • 举例:

    产品 类别值 说明
    标准五路灯 1510 小端转换后得到 1015:
    • 1:标准设备
    • 01:灯
    • 5:5 路灯
    标准四路插座 2410 小端转换后得到 1024:
    • 1:标准设备
    • 02:插座
    • 4:4 路插座
    透传型设备 xx20 小端转换后得到 20xx:2 表示透传设备

管理

蓝牙 Mesh 的主要操作类都在 ThingSmartBleMesh+SIGMesh.h 文件中。

创建蓝牙 Mesh

一个家庭里可以拥有多个蓝牙 Mesh,但建议只创建一个 Mesh。创建前,判断是否已经创建。若尚未创建,可以通过此方法进行创建。

蓝牙 Mesh 中所有操作都建立在家庭数据已经初始化的基础上。完成初始化家庭操作,参考 家庭管理

接口说明

+ (void)createSIGMeshWithHomeId:(long long)homeId
                        success:(void(^)(ThingSmartBleMeshModel *meshModel))success
                        failure:(ThingFailureError)failure;

参数说明

参数 说明
homeId 家庭 ID
success 成功回调
failure 失败回调

示例代码

Objective-C:

ThingSmartHome *home = #<上文初始化的 home 实例>;
long long homeId = home.homeModel.homeId;
[ThingSmartBleMesh createSIGMeshWithHomeId:homeId success:^(ThingSmartBleMeshModel *meshModel) {
    // success do...
} failure:^(NSError *error) {
    NSLog(@"create mesh error: %@", error);
}];

删除蓝牙 Mesh

接口说明

删除蓝牙 Mesh 时,如果蓝牙 Mesh 组里有子设备,会被同时移除。

- (void)removeMeshWithSuccess:(ThingSuccessHandler)success failure:(ThingFailureError)failure;

参数说明

参数 说明
success 成功回调
failure 失败回调

示例代码

self.mesh = #<ThingSmartBleMesh 实例>;
[self.mesh removeMeshWithSuccess:^{
    // success do...
} failure:^(NSError *error) {
    XCTFail(@"test remove mesh failure: %@", error);
}];

查询家庭的蓝牙 Mesh 列表

接口说明

通过初始化 home 实例后,可以查询到对应家庭下的 mesh 列表。

- (void)getSIGMeshListWithSuccess:(void(^)(NSArray <ThingSmartBleMeshModel *> *list))success
                          failure:(ThingFailureError)failure;

参数说明

参数 说明
success 成功回调
failure 失败回调

示例代码

ThingSmartHome *home = #<home 实例>
[home getSIGMeshListWithSuccess:^(NSArray<ThingSmartBleMeshModel *> *list) {
    // success do
} failure:^(NSError *error) {
    NSLog(@"get Bluetooth mesh list error: %@", error);
}];

查询蓝牙 Mesh 实例

接口说明

+ (instancetype)bleMeshWithMeshId:(NSString *)meshId homeId:(long long)homeId;

参数说明

参数 说明
meshId 蓝牙 Mesh ID
homeId 家庭 ID

示例代码

// 通过家庭(ThingSmartHome 实例)home 实例可以查询到类下的 sigMeshModel
ThingSmartBleMeshModel *sigMeshModel = [self getCurrentHome].sigMeshModel;

初始化蓝牙 Mesh 网络控制器

需要初始化蓝牙 Mesh 网络控制器,对蓝牙 Mesh 设备进行扫描、配网、连接等操作。

meshModel 需要传入 ThingSmartHome 中的 sigMeshModel 参数,而不是 meshModel

接口说明

+ (ThingSmartSIGMeshManager * _Nullable)initSIGMeshManager:(ThingSmartBleMeshModel *)meshModel
                                                      ttl:(NSInteger)ttl
                                                  nodeIds:(NSArray * _Nullable)nodeIds

参数说明

参数 说明
meshModel 蓝牙 Mesh Model
ttl 蓝牙 Mesh 网络中消息可被转发的次数,默认为 8
nodeIds 蓝牙 Mesh 网络中所有设备的 nodeId,不含低功耗节点

获取蓝牙 Mesh 网络控制器

必须先通过 ThingSmartBleMesh 初始化蓝牙 Mesh 网络控制器,才能通过此方法获取。

接口说明

+ (ThingSmartSIGMeshManager * _Nullable)getSIGMeshManager:(NSString *)meshId;

参数说明

参数 说明
meshId 蓝牙 Mesh ID

蓝牙 Mesh 的操作类集中在 ThingSmartSIGMeshManager 中。

配置蓝牙 Mesh 设备连网后的上线策略

默认上线策略为 ThingSIGMeshOnlineProfileMeshNetworkLogin

接口说明

typedef NS_ENUM(NSUInteger, ThingSIGMeshOnlineProfile) {
    //连接蓝牙 Mesh 网后设备默认全部在线
    ThingSIGMeshOnlineProfileMeshNetworkLogin,
    //连接蓝牙 Mesh 网后查询设备在线状态
    ThingSIGMeshOnlineProfileMeshQuery,
};

@interface ThingSIGMeshConfigModel : NSObject

@property (nonatomic, assign) ThingSIGMeshOnlineProfile onlineProfile;

@end

- (void)setConfig:(ThingSIGMeshConfigModel *)configModel;

连接蓝牙 Mesh 子设备

需要连接蓝牙 Mesh 设备时,只需传入 ScanForProxyed 即可,详情请参考 配网 部分。

- (void)startScanWithScanType:(ThingSmartSIGScanType)scanType
          meshModel:(ThingSmartBleMeshModel *)meshModel __deprecated_msg("This method is deprecated, Use startSearch instead");

- (void)startSearch;

配网

配网指的是将处于重置状态、未入网的设备,添加到蓝牙 Mesh 网中。常用设备的重置方式如下表所示:

产品类型 照明 插座
重置操作 连续开关 3 次 长按开关 3 秒
可配网现象 灯快闪 插座指示灯快闪

扫描待配网子设备

接口说明

开始扫描设备。扫描附近符合 SIG 标准的蓝牙设备。当扫描到周围有符合协议规范的待配网设备后,可以对这些设备进行配网。配网就是把未加入到蓝牙 Mesh 网络的蓝牙设备,通过一定的通讯过程将其加入到蓝牙 Mesh 网络中。

meshModel 需要传入 ThingSmartHome 中的 sigMeshModel 参数,而不是 meshModel

- (void)startScanWithScanType:(ThingSmartSIGScanType)scanType
          meshModel:(ThingSmartBleMeshModel *)meshModel __deprecated_msg("This method is deprecated, Use startSearch instead");

- (void)startSearch;

参数说明

参数 说明
scanType 扫描类型。设备分为未配网设备和已配网设备,扫描到已配网设备则会自动入网。
meshModel 蓝牙 Mesh model 信息。

示例代码

//[ThingSmartSIGMeshManager sharedInstance].delegate = self;
// ScanForUnprovision, // 扫描未配网设备
// ScanForProxyed, // 扫描已经配网的设备
//[[ThingSmartSIGMeshManager sharedInstance] startScanWithScanType:ScanForUnprovision
//                            meshModel:home.sigMeshModel];

    ThingSmartSIGMeshManager *manager = [ThingSmartBleMesh getSIGMeshManager:@"meshId"];
    manager.delegate = self;
    [manager startSearch];

回调接口

扫描到设备后,可在 ThingSmartSIGMeshManagerDelegate 回调中实现以下方法,查询扫描到的设备。

// 扫描到待配网的设备
- (void)sigMeshManager:(ThingSmartSIGMeshManager *)manager
       didScanedDevice:(ThingSmartSIGMeshDiscoverDeviceInfo *)device;

参数说明

参数 说明
manager 蓝牙 Mesh 的管理信息
device 待配网设备信息

激活子设备

激活设备过程是标准的蓝牙 Mesh 配网过程。

接口说明

- (void)startActive:(NSArray<ThingSmartSIGMeshDiscoverDeviceInfo *> *)devList meshModel:(ThingSmartBleMeshModel *)meshModel __deprecated_msg("This method is deprecated, Use startActive: instead");

- (void)startActive:(NSArray<ThingSmartSIGMeshDiscoverDeviceInfo *> *)devList;

参数说明

参数 说明
devList 待激活设备列表
meshModel 蓝牙 Mesh model 信息

子设备激活回调

接口说明

当某一设备激活成功或者失败会通过 ThingSmartSIGMeshManagerDelegate 回调以下方法。

激活子设备成功回调。

- (void)sigMeshManager:(ThingSmartSIGMeshManager *)manager
    didActiveSubDevice:(ThingSmartSIGMeshDiscoverDeviceInfo *)device
                 devId:(NSString *)devId
                 error:(NSError *)error;

参数说明

参数 说明
manager 蓝牙 Mesh 的管理信息
device 设备信息
devId 设备 ID
error 激活中的错误,若发生错误,name 以及 deviceId 为空

接口说明

激活设备失败回调。

- (void)sigMeshManager:(ThingSmartSIGMeshManager *)manager
 didFailToActiveDevice:(ThingSmartSIGMeshDiscoverDeviceInfo *)device
                 error:(NSError *)error;

参数说明

参数 说明
manager 蓝牙 Mesh 的管理信息
device 设备信息
error 激活过程中返回的错误码

停止激活子设备

在扫描设备和配网中任意阶段,调用以下方法,均会停止对蓝牙设备的配网流程。

接口说明

- (void)stopActiveDevice;

蓝牙 Mesh 连接标识

在操作的过程中,会经常判断是否是蓝牙 Mesh 已有设备通过蓝牙入网,来决定使用何种方式下发控制命令和操作命令。

// Mesh 本地连接标识,有设备通过蓝牙连接,此属性为 yes
//BOOL isLogin = [ThingSmartSIGMeshManager sharedInstance].isLogin;

BOOL isLogin = [ThingSmartBleMesh getSIGMeshManager:@"meshId"].isLogin;

蓝牙 Mesh 网关配网

  • 蓝牙 Mesh 网关配网采用快连配网,参考 快连模式
  • 也可以使用单点蓝牙 Wi-Fi 双模配网,参考 蓝牙设备

蓝牙 Mesh 子设备网关配网

蓝牙 Mesh 网关激活子设备。参考 激活子设备

配网错误码

错误码 说明
701 连接错误
702 Composition 回复错误
703 Composition 超时
704 添加 appkey 失败
705 添加 appkey 超时
706 network transmit 回复错误
707 network transmit 超时
708 publication model 回复错误
709 publication model 超时
710 添加 bind 回复错误
711 添加 bind 超时
712 IdentifySet 超时

设备

设备类是 ThingSmartDevice,里面的 ThingSmartDeviceModel 中的 deviceType 信息可以区分设备类型。其中,Mesh 设备对应 deviceType 类型为 ThingSmartDeviceModelTypeSIGMeshSubDev

查询设备实例

接口说明

+ (instancetype)deviceWithDeviceId:(NSString *)devId;

参数说明

参数 说明
devId 设备 ID

蓝牙 Mesh 本地连接

手机蓝牙开启且 Mesh 设备通过蓝牙进行连接控制,下发命令通过蓝牙完成。判断条件为 deviceModel.isOnline && deviceModel.isMeshBleOnline

蓝牙 Mesh 网关连接

手机蓝牙未开启或距离设备远,Mesh 设备通过网关进行连接控制,下发命令通过 Wi-Fi 完成。判断条件为 deviceModel.isOnline && !deviceModel.isMeshBleOnline

查询蓝牙 Mesh 子设备状态

接口说明

- (void)getDeviceStatusWithDeviceModel:(ThingSmartDeviceModel *)deviceModel;

参数说明

参数 说明
deviceModel 设备 model

移除蓝牙 Mesh 子设备

移除设备已经简化,所有的设备移除都保持一致。更多信息,参考 移除设备

群组

在蓝牙 Mesh 网中,可以将一些设备组成群组,使用群组命令控制群组中的设备。例如,将所有灯组添加到某个群组中,通过控制群组的开关、颜色等,直接控制群组中所有的灯具有相同的属性。

对于蓝牙 Mesh 群组的添加,为了保证功能一致,建议同一品类的设备添加进群组。在添加群组之前,可以调用 ThingSmartBleMeshGroup 的以下方法,从服务端查询群组地址。

向云端分配群组 ID

接口说明

+ (void)getBleMeshGroupAddressFromCluondWithMeshId:(NSString *)meshId
                    success:(ThingSuccessInt)success
                    failure:(ThingFailureError)failure;

参数说明

参数 说明
meshId 蓝牙 Mesh ID
success 成功回调 localId 的 10 进制
failure 失败回调

从服务端返回的群组地址需要加上 0x4000 之后,调用即可获得当前 sigMeshModel 下的一个以 groupName 命名的群组。

创建蓝牙 Mesh 群组

接口说明

+ (void)createMeshGroupWithGroupName:(NSString *)groupName
                              meshId:(NSString *)meshId
                             localId:(NSString *)localId
                                 pcc:(NSString *)pcc
                             success:(ThingSuccessInt)success
                             failure:(ThingFailureError)failure;

参数说明

参数 说明
groupName 蓝牙 Mesh 群组名字
meshId Mesh ID
localId 群组的本地短地址,为 2 字节的 16 进制字符
pcc 群组设备大小类
success 成功回调,返回群组 ID
failure 失败回调

以蓝牙方式将设备加入群组

接口说明

如果需要将某个设备加入群组中,需要调用 ThingSmartSIGMeshManager 以下方法。

- (void)addDeviceToGroupWithDevId:(NSString *)devId
                     groupAddress:(uint32_t)groupAddress;

参数说明

参数 说明
devId 设备 ID
groupAddress 群组地址

回调接口

// ThingSmartSIGMeshManagerDelegate 回调
- (void)sigMeshManager:(ThingSmartSIGMeshManager *)manager
didHandleGroupWithGroupAddress:(nonnull NSString *)groupAddress
          deviceNodeId:(nonnull NSString *)nodeId
             error:(NSError *)error;

参数说明

参数 说明
manager 管理信息
groupAddress 群组蓝牙 Mesh 地址,16 进制
nodeId 设备蓝牙 Mesh 节点地址,16 进制
error 错误回调

以网关方式将设备加入群组

接口说明

通过网关向蓝牙 Mesh 群组内加子设备,可以通过 ThingSmartBleMeshGroup 进行操作。通过蓝牙 Mesh 网关添加蓝牙 Mesh 子设备群组,需要保证子设备的关系归属在蓝牙 Mesh 网关下。

- (void)addSubDeviceWithSubList:(NSArray<ThingSmartDeviceModel *> * _Nonnull )subList success:(nullable ThingSuccessHandler)success failure:(nullable ThingFailureError)failure;

参数说明

参数 说明
subList 待操作的网关下子设备
success 操作成功回调
failure 操作失败回调

ThingSmartBleMeshGroupDelegate 回调

@protocol ThingSmartBleMeshGroupDelegate <NSObject>

/// 蓝牙 Mesh 设备加入到网关的群组响应
/// 1:超过场景数上限,2:子设备超时,3:设置值超出范围,4:写文件错误,5:其他错误
- (void)meshGroup:(ThingSmartBleMeshGroup *)group addResponseCode:(NSArray <NSNumber *> *)responseCode;

@end

以蓝牙方式将设备移除出群组

接口说明

- (void)deleteDeviceToGroupWithDevId:(NSString *)devId groupAddress:(uint32_t)groupAddress;

参数说明

参数 说明
devId 设备 ID
groupAddress 群组地址

ThingSmartSIGMeshManagerDelegate 回调

- (void)sigMeshManager:(ThingSmartSIGMeshManager *)manager
didHandleGroupWithGroupAddress:(nonnull NSString *)groupAddress
          deviceNodeId:(nonnull NSString *)nodeId
             error:(NSError *)error;

参数说明

参数 说明
manager 管理信息
groupAddress 群组蓝牙 Mesh 地址,16 进制
nodeId 设备蓝牙 Mesh 节点地址,16 进制
error 错误

以网关方式将设备移除出群组

接口说明

通过网关向蓝牙 Mesh 群组内删除设备,可以通过 ThingSmartBleMeshGroup 进行操作。通过蓝牙 Mesh 网关删除蓝牙 Mesh 子设备群组,需要保证子设备的关系归属在蓝牙 Mesh 网关下。

- (void)removeSubDeviceWithSubList:(NSArray<ThingSmartDeviceModel *> * _Nonnull )subList success:(nullable ThingSuccessHandler)success failure:(nullable ThingFailureError)failure;

参数说明

参数 说明
subList 待操作的网关下子设备
success 操作成功回调
failure 操作失败回调

ThingSmartBleMeshGroupDelegate 回调

// ThingSmartBleMeshGroupDelegate 回调
@protocol ThingSmartBleMeshGroupDelegate <NSObject>

/// 蓝牙 Mesh 设备从网关群组移除响应
/// 1:超过场景数上限,2:子设备超时,3:设置值超出范围,4:写文件错误,5:其他错误
- (void)meshGroup:(ThingSmartBleMeshGroup *)group removeResponseCode:(NSArray <NSNumber *> *)responseCode;

@end

同步群组操作到云端

类名 说明
ThingSmartBleMeshGroup 群组类

接口说明

若添加或删除成功或者失败,可以通过代理方法收到结果。同时,使用 group 实例进行群组内设备关系变更云端同步。

// 添加设备
- (void)addDeviceWithDeviceId:(NSString *)deviceId success:(ThingSuccessHandler)success failure:(ThingFailureError)failure;

// 删除设备
- (void)removeDeviceWithDeviceId:(NSString *)deviceId success:(ThingSuccessHandler)success failure:(ThingFailureError)failure;

查询群组内的设备

接口说明

调用 ThingSmartSIGMeshManager 以下方法,并配合回调(需固件支持),通过群组地址查询群组中的设备。

- (void)queryGroupMemberWithGroupAddress:(uint32_t)groupAddress;

// 回调
- (void)sigMeshManager:(ThingSmartSIGMeshManager *)manager
      queryDeviceModel:(ThingSmartDeviceModel *)deviceModel
          groupAddress:(uint32_t)groupAddress;

参数说明

参数 说明
groupAddress 群组地址

控制

由于涂鸦使用 DP 管理设备的功能,因此,蓝牙 Mesh 相关的控制是根据设备的 DP 信息来进行操作。

指令下发格式

发送控制指令按照以下格式:{"(dpId)" : "(dpValue)"},例如 @{@"101" : @"44"}

涂鸦对指令下发进行了简化处理,您无需关注是网关连接、还是本地连接。只要设备在线,就可以下发。

设备控制指令下发

接口说明

  // ThingSmartDevice
  - (void)publishDps:(NSDictionary *)dps
             success:(nullable ThingSuccessHandler)success
             failure:(nullable ThingFailureError)failure;

参数说明

参数 说明
dps DP 的字典表达格式
success 成功回调
failure 失败回调

群组控制指令下发

接口说明

// ThingSmartBleMeshGroup
- (void)publishDps:(NSDictionary *)dps success:(nullable ThingSuccessHandler)success failure:(nullable ThingFailureError)failure;

参数说明

参数 说明
dps DP 的字典表达格式
success 成功回调
failure 失败回调

升级

从 v3.35.5 开始,设备固件升级方式统一。您可以移步 设备管理-固件升级,了解新的升级方法,从而简化升级过程。

查询升级信息

接口说明

// 通过 ThingSmartDevice 实例进行查询
- (void)getFirmwareUpgradeInfo:(void (^)(NSArray <ThingSmartFirmwareUpgradeModel *> *upgradeModelList))success failure:(ThingFailureError)failure;

/*
升级的信息会通过结果值返回,可以根据 type 信息去确定是否需要升级
     0:升级中
     1:无升级
     2:有强制或提醒升级
     3:有检测升级

// 判断为需要升级后,具体的固件地址在返回值中,下载之后转成固件 data 进行后续操作
*/

参数说明

参数 说明
success 成功回调
failure 失败回调

蓝牙 Mesh 低功耗设备升级之前需要唤醒,不同设备的唤醒方式不同。

检查子设备是否在线

子设备升级都是通过蓝牙升级,所以需要判断设备是否处于本地连接。确认本地在线后,再进行后续操作。

BOOL isBLEOnline = device.deviceModel.isMeshBleOnline;

指定待升级的子设备

每次都是一对一地升级。

[ThingSmartSIGMeshManager sharedInstance].delegate = self;
[[ThingSmartSIGMeshManager sharedInstance] prepareForOTAWithTargetNodeId:self.device.deviceModel.nodeId];

等待待升级设备连接成功回调

// ThingSmartSIGMeshManagerDelegate

- (void)notifySIGLoginSuccess {
    [ThingSmartSIGMeshManager sharedInstance].delegate = nil;
    //weakify(self);
    [[ThingSmartSIGMeshManager sharedInstance] startSendOTAPack:_otaData targetVersion:_upgradeModel.version success:^{
        //strongify(self);
      // 更新版本号
        [self updateVersion];
    } failure:^{
        // log error
    }];
}

更新设备版本号

- (void)updateVersion {
    [self.device updateDeviceVersion:_upgradeModel.version type:_upgradeModel.type success:^{
        // ota success
    } failure:^(NSError *error) {
        // log error
    }];
}

蓝牙 Mesh 网关固件升级

蓝牙 Mesh 网关升级和普通的设备升级一样。详情请参考 固件升级