蓝牙可以辅助纯Wi-Fi方式来配网,当Wi-Fi配网出现错误时,还可以用来反馈错误信息,帮助用户定位问题。当您的自有App需要蓝牙辅助配网功能时,请根据本文档开发Android自有App中蓝牙辅助配网功能。

前提条件

已完成控制台上产品开发工作,以及蓝牙辅助配网的设备端开发,请参见设备端开发
  1. 创建一个自有App,详细操作请参见创建自有App
  2. 选择下面任一方式获取SDK。
    • 从控制台下载并集成SDK(需勾选配网套餐包),请参见下载并集成SDK
    • 在App工程中添加如下代码。
      • maven仓库
        maven {
            url "http://maven.aliyun.com/nexus/content/repositories/releases/"
        }
      • gradle依赖
        // 配网SDK依赖
        api('com.aliyun.alink.linksdk:ilop-devicecenter:1.7.5')
        // api通道 依赖
        api('com.aliyun.alink.linksdk:api-client-biz:1.0.1')
        // 蓝牙SDK依赖
        api 'com.aliyun.alink.linksdk:breeze-biz:1.1.4'
  3. 初始化SDK。
    蓝牙辅助配网依赖和云端的交互,在调用配网SDK之前需要先完成SDK初始化,请参见SDK初始化(API网关接口的使用示例请参见API通道SDK)。
  4. (可选)开发发现设备。
    设备发现接口提供发现附近的蓝牙辅助配网、零配、设备热点配网的待配设备和局域网已配设备的能力。这里介绍蓝牙辅助配网,示例代码会只选发现蓝牙辅助配网待配设备。
    说明 Wi-Fi&BLE Combo蓝牙模块广播的subType必须设置为2(表示蓝牙Wi-Fi双模设备),才能保障设备被蓝牙辅助配网方式发现。
    // 开始发现蓝牙辅助配网待配设备
    // 第三个参数是其它发现方式需要的,这里直接置为null
    final EnumSet<DiscoveryType> discoveryTypes = EnumSet.of(DiscoveryType.BLE_ENROLLEE_DEVICE);
    LocalDeviceMgr.getInstance().startDiscovery(context, enumSet, null, new IDeviceDiscoveryListener() {
        @Override
        public void onDeviceFound(DiscoveryType discoveryType, List<DeviceInfo> list) {
            // 发现的设备
            // discoveryType=BLE_ENROLLEE_DEVICE 表示发现的是蓝牙Wi-Fi双模设备
            //如果发现到蓝牙辅助配网的待配设备,返回的设备信息只包含productId,
            //用户需要根据productId获取产品对应的productKey相关信息,然后开始后续的配网。
        }
    });
    说明 在联调蓝牙辅助配网发现和配网的时候,需要确保App具有位置权限,且蓝牙处于打开状态; 在app开发时需要做相应的权限检测和权限申请。
  5. 开发设备配网。

    设备配网主要包含四个流程(设置配网设备信息、开始配网、设置Wi-Fi信息、接收配网结果),详细介绍参见以下代码示例。

    /**
     * 第一步 设置配网设备信息
     * 包含设备的productKey、productId信息
     * 配网的信息可以通过上面的发现接口来获取,也可以直接通过扫码的方式拿到配网所需要的信息开始配网。
     * 不是通过发现接口进行蓝牙辅助配网的需要确保当前确实有进入配网状态的combo设备,并能被发现。
    */
    DeviceInfo deviceInfo = new DeviceInfo();
    // 商家后台注册的 productKey,不可为空
    deviceInfo.productKey = "xx"; 
    // 产品 ID, 蓝牙辅助配网必须
    deviceInfo.productId = "xxx";
    deviceInfo.linkType = "ForceAliLinkTypeBLE"; // 默认一键配网  
    //设置待添加设备的基本信息
    AddDeviceBiz.getInstance().setDevice(deviceinfo);
    
    /**
     * 第二步 开始配网
     * 设置配网信息回调
    */
    AddDeviceBiz.getInstance().startAddDevice(context, new IAddDeviceListener(){
        @Override
        public void onPreCheck(boolean b, DCErrorCode dcErrorCode) {
            // 参数检测回调 
        }
    
        @Override
        public void onProvisionPrepare(int prepareType) {
    
            // prepareType = 1 执行第三步
            /**
             * 第三步 设置Wi-Fi信息
             * 设置需要设备连接的Wi-Fi的ssid、password、配网超时时间信息
            */
             // 需要设备连接Wi-Fi的ssid,一般为当前Wi-Fi
            String ssid = "ssid";
            // 需要设备连接Wi-Fi的password,一般为当前Wi-Fi
            String ssid = "xxxxxxxx";
            int timeout = 60;//单位秒 目前最短只能设置60S
            AddDeviceBiz.getInstance().toggleProvision(ssid, password, timeout);
    
        }
    
        @Override
        public void onProvisioning() {
            // 配网中
        }
    
        @Override 
        public void onProvisionStatus(ProvisionStatus provisionStatus) {
        }
    
        @Override
        public void onProvisionedResult(boolean isSuccess, DeviceInfo deviceInfo, DCErrorCode errorCode) {
            /**
             * 第四步 接收配网结果
             * isSuccess = true 表示配网成功,deviceInfo会包含设备的productKey、deviceName相关信息
             * isSuccess = false 表示配网失败,errorCode会包含配网失败的错误code和原因;
            */
            // 配网结果 如果配网成功之后包含token,请使用配网成功带的token做绑定
        }
    });
  6. 获取设备绑定Token。

    获取设备绑定Token需要productKey、deviceName、超时时间、轮询间隔。该接口提供从设备端获取绑定token的功能。配网SDK不包含绑定的逻辑,实现绑定逻辑可参见基于token方式设备绑定

    /**
     * 获取设备端绑定的token
     * 该接口需要设备配网成功,且设备连云成功后,才会出现成功返回。
     * 60*1000 ms表示总超时时间,5*1000表示每5s去查询一次
    */
    LocalDeviceMgr.getInstance().getDeviceToken(context, productKey, deviceName, 60*1000, 5*1000, new IOnDeviceTokenGetListener() {
                @Override
                public void onSuccess(String token) {
                    // TODO 设备绑定
                }
    
                @Override
                public void onFail(String reason) {
                }
            });