添加设备

更新时间:2019-09-23 15:06:38

概述

提供了把 WiFi 设备配置上家庭路由器以及局域网内已联网设备的发现能力,具体方案包括一键广播配网、手机热点配网、智能路由器配网以及设备间相互配网等。

依赖SDK 概述
日志 基础依赖SDK,提供客户端统一日志打印,日志等级控制,分模块日志隔离等能力
API 通道 提供API通道能力,和基础环境配置信息

初始化

参考平台下载包里的说明文件。

使用说明

引入SDK

// 引入头文件
#import <IMLDeviceCenter/IMLDeviceCenter.h>

设备发现

提供获取局域网内已经配网的设备,包括 WiFi 设备以及以太网设备,以及局域网内已上电的待配设备(前提是当前局域网内内已经有一个已配好网的智能设备,且该设备支持未待配设备进行配网的能力)。

启动发现设备

发现本地的已配网设备,或者已配网设备、路由器发现的待配设备。发现的待配设备信息可以作为后续设备配网的入参信息。

// 本地发现入口
[[IMLLocalDeviceMgr sharedMgr] startDiscovery:^(NSArray *devices, NSError *err) {
    if (devices && [devices count] > 0) {
        NSLog(@"发现本地设备: %@", devices);
        // 将与用户没有绑定关系的设备显示在本地发现设备中
        for (IMLCandDeviceModel *device in devices) {
            [weakSelf.devices addObject:device];
        }

        [weakSelf.tableView reloadData];
    } else if (err) {
        NSLog(@"本地发现设备出错: %@", err);
    }
}];

获取所有已发现设备

NSArray *allLanDevicesArray = [kLKLocalDeviceMgr getLanDevices];

终止发现设备

停止发现本地已配和线上待配设备,调用该接口会清除已发现设备列表,确保和startDiscovery成对调用。

// 停止发现设备
[kLKLocalDeviceMgr stopDiscovery];

通用配网流程

设置待添加设备信息

待添加设备信息来源可以为上面本地发现的待配设备,也可以通过扫码等其他途径获取待配设备信息

// 选取本地发现的待配设备
IMLCandDeviceModel *model = self.localDeviceList[index];
[kLkAddDevBiz setDevice:model];

备注:其中(IMLCandDeviceModel *)model 为本地发现待配设备或者云端拉取产品列表组装的model
本地发现设备参见:本文 设备发现 章节内容

其中 IMLCandDeviceModel 属性说明:

属性 类型 是否必选 描述 备注
productKey NSString 设备productKey
deviceName NSString 设备名称
linkType assign 指定配网方式

设置配网模式

// 具体配网方式可以查看ForceAliLinkType枚举
[kLkAddDevBiz setAliProvisionMode:ForceAliLinkTypeNone];

开始设备配网

上述设置好待添加设备信息,进入配网。调用 startAddDevice 接口进入配网流程,并实现监听的协议方法,下面是一个完整的配网监听回调及其对应方法


- (IBAction)start:(UIButton *)sender 
{
   // 此处设备可以是本地发现得到、或者是其他方式组装的model
    IMLCandDeviceModel *model = [[IMLCandDeviceModel alloc] init];
    model.productKey = self.pkTextField.text;
    model.deviceName = self.dnTextField.text;

    [kLkAddDevBiz setDevice:model];
    [kLkAddDevBiz setAliProvisionMode:ForceAliLinkTypeNone];
   // 开始配网并监听回调
    [kLkAddDevBiz startAddDevice:self];
}

#pragma mark - 配网相关回调

其中 self 为配网过程中 notifier 监听回调对象(代理)

- (void)notifyPrecheck:(BOOL)success withError:(NSError *)err
{
    if (err) {
        NSLog(@"配网预检查失败,错误信息 = %@", err);
    }
}

// 用户引导页(一键配网和热点配网会有相关回调,指引用户接入相关操作)

- (void)notifyProvisionPrepare:(LKPUserGuideCode)guideCode
{
   NSLog(@"配网准备回调,guide code : %ld", guideCode);

    if(guideCode == LKPGuideCodeOnlyInputPwd){
        // TODO:一键广播配网相关引导、直接进入输入密码页
        // 得到密码后调用下列方法通知SDK继续配网流程

        [kLkAddDevBiz toggleProvision:self.ssidTextField.text pwd:self.passwordTextField.text timeout:1000];
    } else if(guideCode == LKPGuideCodeWithUserGuide){
        // TODO:热点配网相关引导、引导开启热点页-》输入密码页
    } else if (guideCode == LKPGuideCodeWithUserGuideForSoftAp) {
        // TODO:设备热点配网相关引导、引导切换热点页-》输入密码页
    }
}

-(void)notifyProvisioning 
{
    NSLog(@"(正在进行配网...)");
}


/**
 通知上层UI:热点配网相关回调提示

 @param status 状态码 1=应该切换到设备热点;2=已经切换到设备热点;3=已发送数据(dic里面会有"token");4=应该切换回路由器;5=已经切换回路由器
 */

- (void)notifyProvisioningNoticeForSoftAp:(int) status withInfo:(NSDictionary *) dic 
{

}

- (void)notifyProvisionResult:(IMLCandDeviceModel *)candDeviceModel withProvisionError:(NSError *)provisionError 
{
   if (candDeviceModel && !provisionError) {
        NSLog(@"配网成功, 配网设备为:%@",candDeviceModel);

        [[IMLLocalDeviceMgr sharedMgr] getDeviceToken:candDeviceModel.productKey deviceName:candDeviceModel.deviceName timeout:20 resultBlock:^(NSString *token, BOOL boolSuccess) {

            NSLog(@"主动获取设备token:%@,boolSuccess:%d", token, boolSuccess);
            if (token) {
                // 调用绑定接口进行设备绑定
            } else{
                NSLog(@"获取token失败(超时)");
            }
        }];

        // 停止配网
        [kLkAddDevBiz stopAddDevice];

    } else {
        NSLog(@"配网失败, 错误为:%@",provisionError);
    }
}

输入配网 wifi 名称以及密码信息

在收到 - (void)notifyProvisionPrepare:(LKPUserGuideCode)guideCode 回调引导完成相关操作(一键广播指引用户输入 ssid 和密码,热点配网指引用户开启热点,输入 ssid 和密码等)后,调用 - (void)toggleProvision:(NSString )ssid pwd:(NSString )pwd timeout:(int)timeout 方法,传入 WiFi 的 ssid 及 password 信息。 注:一键广播配网和热点配网才会有 notifyProvisionPrepare 回调。

// 引入头文件
#import <IMSDeviceCenter/IMLDeviceCenter.h>

- (void)notifyProvisionPrepare:(LKPUserGuideCode)guideCode 
{
    NSLog(@"配网准备回调,guide code : %ld", guideCode);
    [self inputSsidAndPassword];
}

- (void)inputSsidAndPassword 
{
    NSSstring *ssid = @"example ssid";
    NSString *password = @"1qaz@WSX";
    NSInterger timeout = 60;(单位秒,s);
    [kLkAddDevBiz toggleProvision:ssid pwd:password timeout:timeout];
}

配网过程关键节点监听处理

针对热点配网必须监听该回调

// 引入头文件
#import <IMSDeviceCenter/IMLDeviceCenter.h>

/**
 通知上层UI:热点配网相关回调提示

 @param status 状态码 1=应该切换到设备热点;2=已经切换到设备热点;3=已发送数据(dic里面会有"token");4=应该切换回路由器;5=已经切换回路由器
 */

- (void)notifyProvisioningNoticeForSoftAp:(int) status withInfo:(NSDictionary *) dic 
{
    if (status == 4) {
        //提示用户应该切换回对应路由器
    }
}

配网结果监听


- (void)notifyProvisionResult:(IMLCandDeviceModel *)candDeviceModel withProvisionError:(NSError *)provisionError
{
    if(candDeviceModel != nil){
        NSLog(@"配网成功:%@",candDeviceModel);
    } else{
        NSLog(@"配网失败,错误信息:%@", provisionError);
    }

}

停止配网

[kLkAddDevBiz stopAddDevice];

设备绑定

当完成设备配网之后,后续需要将设备与用户或者与家庭做一个关联绑定,在绑定的时候需要调用 SDK 的获取 token方法,取得设备token,然后进行设备绑定。获取token:

// candDeviceModel 是配网成功后返回的设备模型
[[IMLLocalDeviceMgr sharedMgr] getDeviceToken:candDeviceModel.productKey deviceName:candDeviceModel.deviceName timeout:20 resultBlock:^(NSString *token, BOOL boolSuccess) {

    NSLog(@"主动获取设备token:%@,boolSuccess:%d", token, boolSuccess);
    if (token) {
        // 调用绑定接口进行设备绑定
    } else{
        NSLog(@"获取token失败(超时)");
    }
}];

蓝牙设备配网


引入SDK**

#import <IMSThingCapability/IMSThingCapability.h>

蓝牙设备发现

[[IMSThingDiscoveryRegistry sharedRegistry] startDiscoveryWithFilter:@{@"deviceType":@[@"breeze", @"third"]}
                   didFoundBlock:^(NSArray * _Nullable result, NSError * _Nullable error) {

     if ([result count]) {
        [result enumerateObjectsUsingBlock:^(id<IMSLocalDevice> item, NSUInteger idx, BOOL * _Nonnull stop) {
            NSString * productKey = item.productKey;
            NSString * bleMac = item.deviceName;//对于Breeze 蓝牙设备,这里得到的是设备的MAC地址

        }];
     }
}];

蓝牙设备配网

NSMutableDictionary *devInfo = @{}.mutableCopy;
//MAC地址为设备发现时取得的值-bleMac
[devInfo setValue:@"EE:FF:DD:AA:BB:00" forKey:@"deviceName"];
//productKey为设备发现时取得的值
[devInfo setValue:@"productKey---xxx" forKey:@"productKey"];

//设备借助app的长连接通道去云端login
[IMSSubDeviceService subDeviceAuthenLogin:devInfo
                              resultBlock:^(NSDictionary * _Nullable object, NSError * _Nullable error) {
    NSString *productKey = [object valueForKey:@"productKey"];
    NSString *deviceName = [object valueForKey:@"deviceName"];
}];

蓝牙设备绑定


+ (void)bindBluetoothDevice:(NSString *)productKey
                 deviceName:(NSString *)deviceName
                     bleMac:(NSString *)bleMac {

    //productKey此处为蓝牙设备配网结果回调里获得的值
    //deviceName此处为蓝牙设备上线结果回调里获得的值,切记不能传设备发现时的MAC地址

    NSDictionary * params = @{@"productKey" : productKey,
                              @"deviceName" : deviceName,
                              @"groupIds":@[]
                              };

    IMSIoTRequestBuilder *builder = [[IMSIoTRequestBuilder alloc] initWithPath:@"/awss/time/window/user/bind"
                                                                    apiVersion:@"1.0.3"
                                                                        params:params];
    // 设置验证类型
    [builder setAuthenticationType:IMSAuthenticationTypeIoT];

    [IMSRequestClient asyncSendRequest:builder.build responseHandler:^(NSError * _Nullable error, IMSResponse * _Nullable response) {

        if (error || response.code != 200) {
            NSLog(@"auth received error response : %@", error);
        } else  {
            if (![response.data isKindOfClass:[NSString class]]) {
                return;
            }

            NSString * iotId = response.data;

            NSMutableDictionary *devInfo = @{}.mutableCopy;
            //此处为设备发现时得到的MAC地址
            [devInfo setValue:bleMac forKey:@"deviceName"];
            //设备的PK
            [devInfo setValue:productKey forKey:@"productKey"];
            //绑定后的IotId
            [devInfo setValue:(iotId ?: @"") forKey:@"iotId"];
            //当设备被绑定成功时,调用此API通知SDK,SDK内部需要做一些逻辑
            [IMSSubDeviceService notifySubDeviceBinded:devInfo];
        }
    }];

}

停止发现蓝牙设备

[[IMSThingDiscoveryRegistry sharedRegistry] stopDiscovery:nil];

使用配网插件

配网插件基于Bone容器实现了完整的配网逻辑,因此在接入Bone容器的前提下,可以直接打开配网插件来完成配网逻辑,然后再自行处理配网之后的逻辑;

#import <IMSRouter/IMSRouter.h>

NSURL *url = [NSURL URLWithString:@"link://router/connectConfig"];
IMSRouterCallback callback = ^(NSError *error, NSDictionary *info) {
    if (error) {
        NSLog(@"配网 error:%@", error);
    } else if (info && [info count] > 0) {
        NSLog(@"配网 info: %@", info);
        NSString *productKey = info[@"productKey"];
        NSString *deviceName = info[@"deviceName"];
        // 这里进行绑定设备
    } else {
        NSLog(@"配网正常退出...");
    }
};

NSMutableDictionary *options = [@{} mutableCopy];
options[@"productKey"] = productKey;
options[@"deviceName"] = deviceName;
options[AKRouterCompletionHandlerKey] = callback;

[[IMSRouterService sharedService] openURL:url options:options completionHandler:^(BOOL success) {
    if (!success) {
        NSLog(@"配网插件加载失败");
    }
}];

results matching ""

    No results matching ""