日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

設(shè)備端開發(fā)

更新時(shí)間:

為提升您基于新開發(fā)的Combo設(shè)備(同時(shí)支持Wi-Fi和BLE)硬件平臺移植生活物聯(lián)網(wǎng)平臺SDK提供的藍(lán)牙輔助Wi-Fi配網(wǎng)功能的效率,本文檔將選擇一款硬件開發(fā)板,進(jìn)行實(shí)際的移植示例,將整個(gè)功能移植、應(yīng)用開發(fā)、功能調(diào)試等過程串聯(lián)起來供您參考。

Combo設(shè)備移植藍(lán)牙輔助配網(wǎng)功能的主要流程如下。

  1. 選擇硬件設(shè)備

    設(shè)備研發(fā)生產(chǎn)廠商、模組廠商、芯片廠商等,根據(jù)您自己的產(chǎn)品與場景需要,選擇合適的硬件平臺(需有Combo芯片或模組)。

  2. 控制臺創(chuàng)建產(chǎn)品

    設(shè)備硬件選擇好后,需在生活物聯(lián)網(wǎng)平臺控制臺,創(chuàng)建項(xiàng)目和產(chǎn)品,新增測試設(shè)備,并配置好App的各項(xiàng)參數(shù)。

  3. 獲取SDK

    下載的生活物聯(lián)網(wǎng)平臺SDK中包含了所需的配網(wǎng)模塊。

  4. 移植藍(lán)牙輔助配網(wǎng)HAL

    移植設(shè)備端生活物聯(lián)網(wǎng)平臺SDK(包括其中的Wi-Fi配網(wǎng)模塊和藍(lán)牙Breeze模塊)到您的硬件平臺上,并進(jìn)行編譯和調(diào)試。

    說明

    藍(lán)牙輔助配網(wǎng)開發(fā)相關(guān)的介紹,請參見藍(lán)牙輔助配網(wǎng)開發(fā)。如果您選擇生活物聯(lián)網(wǎng)平臺認(rèn)證的硬件平臺,則不需要重新移植。硬件平臺的選擇和介紹請參見選擇認(rèn)證模組/芯片

  5. 生成設(shè)備固件

    基于完整功能的示例應(yīng)用,編譯能運(yùn)行于您硬件平臺的藍(lán)牙輔助配網(wǎng)設(shè)備固件。

  6. 驗(yàn)證藍(lán)牙輔助配網(wǎng)功能

    使用生活物聯(lián)網(wǎng)平臺提供的云智能App,驗(yàn)證藍(lán)牙輔助配網(wǎng)功能。

一、準(zhǔn)備硬件設(shè)備

請您根據(jù)自身產(chǎn)品選擇合適的硬件設(shè)備,具體資源請參見藍(lán)牙輔助配網(wǎng)開發(fā)(本文檔以同時(shí)支持Wi-Fi和BLE的Combo芯片,BK7231U為示例)。

二、在控制臺開發(fā)產(chǎn)品

  1. 登錄生活物聯(lián)網(wǎng)控制臺
  2. 選擇已有項(xiàng)目或創(chuàng)建一個(gè)新項(xiàng)目。請參見創(chuàng)建項(xiàng)目

  3. 創(chuàng)建產(chǎn)品,并定義產(chǎn)品功能。請參見創(chuàng)建產(chǎn)品并定義功能

    說明

    創(chuàng)建產(chǎn)品時(shí),連網(wǎng)方式需配置為WiFi。支持藍(lán)牙輔助配網(wǎng)的Wi-Fi + BLE的Combo設(shè)備,實(shí)質(zhì)上還是一個(gè)可以直連網(wǎng)絡(luò)的Wi-Fi設(shè)備,BLE的功能是Wi-Fi模塊輔助配網(wǎng)。

  4. 添加測試設(shè)備。請參見添加設(shè)備

  5. 選擇App版本并配置App功能參數(shù),請參見人機(jī)交互概述

    配置配網(wǎng)引導(dǎo)時(shí),默認(rèn)配網(wǎng)方式備選配網(wǎng)方式需配置為藍(lán)牙輔助配網(wǎng),并配置相應(yīng)的配網(wǎng)文案,請參見配置配網(wǎng)引導(dǎo)jt10

三、獲取SDK

獲取生活物聯(lián)網(wǎng)平臺SDK時(shí),建議您使用最新版本的含AliOS Things的SDK開發(fā)設(shè)備端。SDK下載地址請參見獲取SDK

四、移植藍(lán)牙輔助配網(wǎng)HAL

藍(lán)牙輔助配網(wǎng)同時(shí)使用了Wi-Fi和BLE的通信能力,因此該功能模塊的移植,包括Wi-Fi配網(wǎng)模塊和藍(lán)牙Breeze模塊的移植。

  1. 移植BLE協(xié)議棧。

    藍(lán)牙輔助配網(wǎng)中的BLE通信部分,使用了生活物聯(lián)網(wǎng)平臺的藍(lán)牙Breeze(通過上層通信Profile的規(guī)則定義和實(shí)現(xiàn))協(xié)議,基于藍(lán)牙協(xié)議棧HAL的移植(需移植的HAL接口請參見藍(lán)牙輔助配網(wǎng)開發(fā))后,可以運(yùn)行在不同廠商的藍(lán)牙協(xié)議棧上。

    以移植BK7231U型號的芯片為示例,在含AliOS Things的SDK代碼包中,藍(lán)牙Breeze模塊及其需要移植的HAL位于/Living_SDK/framework/bluetooth/breeze/目錄下,該目錄中的內(nèi)容說明如下。

    內(nèi)容

    說明

    breeze.mk

    藍(lán)牙Breeze模塊的makefile

    core/

    藍(lán)牙Breeze模塊的協(xié)議實(shí)現(xiàn),移植時(shí)不用了解其實(shí)現(xiàn)細(xì)節(jié)

    include/

    藍(lán)牙Breeze模塊的協(xié)議實(shí)現(xiàn)的頭文件,移植時(shí)不用了解其實(shí)現(xiàn)細(xì)節(jié)

    hal/

    藍(lán)牙Breeze模塊的HAL實(shí)現(xiàn),移植時(shí)需要重點(diǎn)實(shí)現(xiàn),此處默認(rèn)的實(shí)現(xiàn)是使用AliOS Things提供的開源BLE協(xié)議棧的移植實(shí)現(xiàn)

    api/

    供上層應(yīng)用開發(fā)調(diào)用的用戶編程接口,移植時(shí)可以不用了解其細(xì)節(jié)

    該部分的移植,主要是實(shí)現(xiàn)breeze.mk(與編譯控制相關(guān))和HAL(與芯片藍(lán)牙協(xié)議棧相關(guān))的部分。

    1. 實(shí)現(xiàn)breeze.mk。

      說明

      示例BK7231U基于GCC交叉編譯工具鏈,采用.mk的makefile的編譯方式。如果您使用其他類型的編譯工具,類似.mk的實(shí)現(xiàn)需完整移植到您所使用的編譯工具環(huán)境下。

      NAME := breeze
      
      $(NAME)_MBINS_TYPE := kernel
      $(NAME)_VERSION := 1.0.0
      $(NAME)_SUMMARY := breeze provides secure BLE connection to Alibaba IoT cloud and services.
      
      $(NAME)_SOURCES += core/core.c
      $(NAME)_SOURCES += core/transport.c
      $(NAME)_SOURCES += core/ble_service.c
      $(NAME)_SOURCES += core/sha256.c
      $(NAME)_SOURCES += core/utils.c
      
      GLOBAL_INCLUDES += api include hal/include
      
      $(NAME)_COMPONENTS := chip_code
      
      # Breeze安全廣播功能,用于增強(qiáng)廣播數(shù)據(jù)的安全性,藍(lán)牙輔助配網(wǎng)中未使用
      secure_adv ?= 0
      ifeq ($(secure_adv), 1)
      GLOBAL_DEFINES += CONFIG_AIS_SECURE_ADV
      endif
      
      # 是否已移植并使用AliOS Things提供的開源BLE協(xié)議棧
      # 如果廠商驅(qū)動中已包含自己的BLE協(xié)議棧,此項(xiàng)功能不用選擇
      # BK7231U使用的是廠商自己的BLE協(xié)議棧,因此這里不會使能
      btstack ?= zephyr
      ifeq (zephyr, $(btstack))
      $(NAME)_COMPONENTS += framework.bluetooth.breeze.hal.ble
      endif
      
      $(NAME)_SOURCES += api/breeze_export.c
      
      # Breeze安全認(rèn)證功能,藍(lán)牙輔助配網(wǎng)中必須打開
      bz_en_auth ?= 1
      ifeq ($(bz_en_auth), 1)
      GLOBAL_DEFINES += EN_AUTH
      $(NAME)_SOURCES += core/auth.c
      endif
      
      # Breeze輔助配網(wǎng)功能,藍(lán)牙輔助配網(wǎng)中必須打開
      bz_en_awss ?= 1
      ifeq ($(bz_en_awss), 1)
      ifeq ($(bz_en_auth), 0)
      $(error awss need authentication, please set "bz_en_auth = 1")
      endif
      GLOBAL_DEFINES += EN_COMBO_NET
      GLOBAL_DEFINES += AWSS_REGION_ENABLE
      $(NAME)_SOURCES += core/extcmd.c
      $(NAME)_SOURCES += api/breeze_awss_export.c
      endif
    2. 實(shí)現(xiàn)hal目錄下的文件。

      hal目錄下面需要移植的文件分別是:breeze_hal_ble.hbreeze_hal_os.hbreeze_hal_sec.h。三個(gè)文件的實(shí)現(xiàn)請參見SDK代碼包中/Living_SDK/platform/mcu/bk7231u/hal/breeze_hal/下的內(nèi)容。

      • breeze_hal_ble.h

        藍(lán)牙協(xié)議棧移植接口,涉及BLE的廣播、連接、GATT相關(guān)的內(nèi)容,需實(shí)現(xiàn)breeze_hal_ble.c

        /**
         * API to initialize ble stack.
         * @parma[in]  ais_init  Bluetooth stack init parmaters.
         * @return     0 on success, error code if failure.
         */
        // 對您使用的硬件平臺的BLE協(xié)議棧初始化,協(xié)議棧初始化成功后,BLE功能才能正常使用
        // 藍(lán)牙輔助配網(wǎng)階段,先初始化BLE協(xié)議棧,接著基于協(xié)議棧注冊GATT Service,完成后才能通信
        // Breeze的BLE通信通道是基于GATT Profile設(shè)計(jì)的,在設(shè)備端實(shí)現(xiàn)了Breeze的GATT Service
        // 生活物聯(lián)網(wǎng)平臺稱之為AIS(Alibaba IoT Service)
        // 該GATT Service中是一組分別支持Read、Write、Notify、Indicate操作的Characteristic,
        // BLE協(xié)議棧初始化函數(shù)傳入的是該GATT Primary Service的描述,BLE協(xié)議棧初始化函數(shù)需要將該Service
        // (也可以稱為Attribute Table)注冊到BLE stack,并將BLE鏈路的connect、disconnect與傳入Service描述中的元素對應(yīng)
        // 通過該方式實(shí)現(xiàn)了BLE stack和AIS Service之間的聯(lián)系,
        // 當(dāng)BLE連接建立或斷開,會通過初始化注冊的connect、disconnect回調(diào)通知到Breeze模塊中,
        // 同時(shí)在連接狀態(tài)下對端對于AIS Service的操作,也會通過Read,Write等回調(diào)通知到Breeze模塊中。
        // 關(guān)于AIS Service的定義如下,供您移植和代碼調(diào)試時(shí)參考
        // Attribute Type                |UUID   |Properties        |Permission
        // AIS Primary Service           |0xFEB3
        // Read Characteristic           |0xFED4 |Read              |Read
        // Write Characteristic          |0xFED5 |Read/Write        |Read/Write
        // Indicate Characteristic       |0xFED6 |Read/Indicate     |Indication
        // WriteWithNoRsp Characteristic |0xFED7 |Read/WriteCommand |Read/Write
        // Notify Characteristic         |0xFED8 |Read/Notify       |Notification
        ais_err_t ble_stack_init(ais_bt_init_t *ais_init);
        
        /**
         * API to de-initialize ble stack.
         * @return     0 on success, error code if failure.
         */
        // 對您使用的硬件平臺的BLE協(xié)議棧反初始化,如果在藍(lán)牙輔助配網(wǎng)結(jié)束,設(shè)備將不會再使用BLE通信能力,
        // 對于此種BLE使用頻率低的場景,可以在藍(lán)牙通信功能完成后,
        // 將BLE協(xié)議棧反初始化,避免BLE協(xié)議棧持續(xù)開啟但不使用,導(dǎo)致的不必要功耗和Wi-Fi、BLE共存問題
        ais_err_t ble_stack_deinit();
        
        /**
         * API to send data via AIS's Notify Characteristics.
         * @parma[in]  p_data  data buffer.
         * @parma[in]  length  data length.
         * @return     0 on success, error code if failure.
         */
        // 通過前面注冊的AIS Service的Notify Characteristic向連接鏈路的對端設(shè)備發(fā)送數(shù)據(jù)
        ais_err_t ble_send_notification(uint8_t *p_data, uint16_t length);
        
        /**
         * API to send data via AIS's Indicate Characteristics.
         * @parma[in]  p_data  data buffer.
         * @parma[in]  length  data length.
         * @parma[in]  txdone  txdone callback.
         * @return     0 on success, erro code if failure.
         */
        // 通過注冊的AIS Service的Indicate Characteristic向連接鏈路的對端設(shè)備發(fā)送數(shù)據(jù)
        ais_err_t ble_send_indication(uint8_t *p_data, uint16_t length, void (*txdone)(uint8_t res));
        
        /**
         * API to disconnect BLE connection.
         * @param[in]  reason  the reason to disconnect the connection.
         */
        // 從設(shè)備端主動斷開已經(jīng)建立的BLE連接
        void ble_disconnect(uint8_t reason);
        
        /**
         * API to start bluetooth advertising.
         * @return     0 on success, erro code if failure.
         */
        // 開始廣播特定的內(nèi)容,該內(nèi)容為Manufacturer Specific Data,是Breeze填充,
        // 以便對端設(shè)備能夠識別Breeze藍(lán)牙設(shè)備所提供的服務(wù),以及進(jìn)行相關(guān)的身份校驗(yàn)
        ais_err_t ble_advertising_start(ais_adv_init_t *adv);
        
        /**
         * API to stop bluetooth advertising.
         * @return     0 on success, erro code if failure.
         */
        // 停止廣播Breeze填充的特定的廣播包,使支持Breeze協(xié)議的對端設(shè)備不要再發(fā)現(xiàn)此設(shè)備
        ais_err_t ble_advertising_stop();
        
        /**
         * API to start bluetooth advertising.
         * @parma[out]  mac  the uint8_t[BD_ADDR_LEN] space the save the mac address.
         * @return     0 on success, erro code if failure.
         */
        // 獲取設(shè)備的Bluetooth MAC地址,會用于身份識別等用途
        ais_err_t ble_get_mac(uint8_t *mac);
      • breeze_hal_os.h

        OS系統(tǒng)移植接口,需實(shí)現(xiàn)breeze_hal_os.c

        /**
         * This function will create a timer.
         *
         * @param[in]  timer   pointer to the timer.
         * @param[in]  fn      callbak of the timer.
         * @param[in]  arg     the argument of the callback.
         * @param[in]  ms      ms of the normal timer triger.
         * @param[in]  repeat  repeat or not when the timer is created.
         * @param[in]  auto_run  run auto or not when the timer is created.
         *
         * @return  0: success.
         */
        // 創(chuàng)建一個(gè)系統(tǒng)的software timer,參數(shù)可配置該timer的定時(shí)時(shí)長,定時(shí)觸發(fā)的回調(diào),
        // 是否反復(fù)定時(shí),是否創(chuàng)建時(shí)立即運(yùn)行timer等
        // 下面幾個(gè)接口是software timer操作相關(guān),Breeze模塊中會用來做定時(shí)觸發(fā)和超時(shí)計(jì)算的用途,
        // 運(yùn)行過程中可能會創(chuàng)建多個(gè)software timer
        int os_timer_new(os_timer_t *timer, os_timer_cb_t cb, void *arg, int ms);
        
        /**
         * This function will start a timer.
         *
         * @param[in]  timer  pointer to the timer.
         *
         * @return  0: success.
         */
        // 運(yùn)行前面創(chuàng)建好的software timer
        int os_timer_start(os_timer_t *timer);
        
        /**
         * This function will stop a timer.
         *
         * @param[in]  timer  pointer to the timer.
         *
         * @return  0: success.
         */
        // 停止正在運(yùn)行中的software timer,與前面的os_timer_start相對應(yīng)
        int os_timer_stop(os_timer_t *timer);
        
        /**
         * This function will delete a timer.
         *
         * @param[in]  timer  pointer to a timer.
         */
        // 刪除前面創(chuàng)建的一個(gè)系統(tǒng)的software timer,與os_timer_new相對應(yīng)
        void os_timer_free(os_timer_t *timer);
        
        /**
         * Reboot system.
         */
        // 設(shè)備系統(tǒng)重啟,一般在OTA一類的服務(wù)中,需要重啟系統(tǒng)以便執(zhí)行相關(guān)的固件搬移和系統(tǒng)初始化,
        // 類似這樣的Breeze模塊中的服務(wù)會需要用到該接口
        void os_reboot();
        
        /**
         * Msleep.
         *
         * @param[in]  ms  sleep time in milliseconds.
         */
        // 系統(tǒng)睡眠和延時(shí),有的操作需要等待某個(gè)動作發(fā)生才能執(zhí)行下一步,就會用到該接口。
        // 該接口在多線程實(shí)現(xiàn)中,一般會讓所在線程休眠指定的時(shí)間,而不影響其他線程的執(zhí)行
        void os_msleep(int ms);
        
        /**
         * Get current time in mini seconds.
         *
         * @return  elapsed time in mini seconds from system starting.
         */
        // 獲取系統(tǒng)的當(dāng)前時(shí)間,該時(shí)間是一個(gè)相對系統(tǒng)啟動點(diǎn)的相對時(shí)間,單位為ms
        long long os_now_ms();
        
        /**
         * Add a new KV pair.
         *
         * @param[in]  key    the key of the KV pair.
         * @param[in]  value  the value of the KV pair.
         * @param[in]  len    the length of the value.
         * @param[in]  sync   save the KV pair to flash right now (should always be 1).
         *
         * @return  0 on success, negative error on failure.
         */
        // 下面幾個(gè)接口是Key-Value存儲相關(guān)的接口,Breeze模塊會用于一些數(shù)據(jù)的固化存儲,目前藍(lán)牙輔助配網(wǎng)
        // 中暫時(shí)未固化存儲數(shù)據(jù),但考慮后續(xù)的功能擴(kuò)展,Key-Value存儲相關(guān)的接口也需要進(jìn)行移植
        // os_kv_set為將指定的數(shù)據(jù)存入Key-Value存儲中
        int os_kv_set(const char *key, const void *value, int len, int sync);
        
        /**
         * Get the KV pair's value stored in buffer by its key.
         *
         * @note: the buffer_len should be larger than the real length of the value,
         *        otherwise buffer would be NULL.
         *
         * @param[in]      key         the key of the KV pair to get.
         * @param[out]     buffer      the memory to store the value.
         * @param[in-out]  buffer_len  in: the length of the input buffer.
         *                             out: the real length of the value.
         *
         * @return  0 on success, negative error on failure.
         */
        // 從Key-Value存儲中獲取相應(yīng)的數(shù)據(jù)
        int os_kv_get(const char *key, void *buffer, int *buffer_len);
        
        /**
         * Delete the KV pair by its key.
         *
         * @param[in]  key  the key of the KV pair to delete.
         *
         * @return  0 on success, negative error on failure.
         */
        // 將Key-Value存儲中某個(gè)Key對應(yīng)的數(shù)據(jù)刪除
        int os_kv_del(const char *key);
        
        /**
         * Generate random number.
         *
         * @return  random value implemented by platform.
         */
        // 返回一個(gè)隨機(jī)值
        int os_rand(void);
      • breeze_hal_sec.h

        安全算法移植接口,需實(shí)現(xiàn)breeze_hal_sec.c

        /**
         * @brief  Initialize the aes context, which includes key/iv info.
         *         The aes context is implementation specific.
         *
         * @param[in] key:
         * @param[in] iv:
         * @param[in] dir: AIS_AES_ENCRYPTION or AIS_AES_DECRYPTION
         * @return p_ais_aes128_t
           @verbatim None
           @endverbatim
         * @see None.
         * @note None.
         */
        // 此部分為AES128算法的實(shí)現(xiàn),Breeze模塊通信是使用AES128 CBC加密的,
        // 因此務(wù)必保證該實(shí)現(xiàn)正常,否則會導(dǎo)致對端和設(shè)備間的通信異常
        void *ais_aes128_init(const uint8_t *key, const uint8_t *iv);
        
        /**
         * @brief   Destroy the aes context.
         *
         * @param[in] aes: the aex context.
         * @return
           @verbatim
             = 0: succeeded
             = -1: failed
           @endverbatim
         * @see None.
         * @note None.
         */
        int ais_aes128_destroy(void *aes);
        
        /**
         * @brief   Do aes-128 cbc encryption.
         *          No padding is required inside the implementation.
         *
         * @param[in] aes: AES handler
         * @param[in] src: plain data
         * @param[in] block_num: plain data number of 16 bytes size
         * @param[out] dst: cipher data
         * @return
           @verbatim
             = 0: succeeded
             = -1: failed
           @endverbatim
         * @see None.
         * @note None.
         */
        int ais_aes128_cbc_encrypt(void *aes, const void *src, size_t block_num,
                                   void *dst);
        
        /**
         * @brief   Do aes-128 cbc decryption.
         *          No padding is required inside the implementation.
         *
         * @param[in] aes: AES handler
         * @param[in] src: cipher data
         * @param[in] block_num: plain data number of 16 bytes size
         * @param[out] dst: plain data
         * @return
           @verbatim
             = 0: succeeded
             = -1: failed
           @endverbatim
         * @see None.
         * @note None.
         */
        int ais_aes128_cbc_decrypt(void *aes, const void *src, size_t block_num,
                                   void *dst);
  2. 移植Wi-Fi協(xié)議棧。

    藍(lán)牙輔助配網(wǎng)中的BLE通信部分,使用了生活物聯(lián)網(wǎng)平臺的藍(lán)牙Breeze協(xié)議,藍(lán)牙Breeze屬于上層通信Profile的規(guī)則定義和實(shí)現(xiàn),基于藍(lán)牙協(xié)議棧HAL的正確移植,可以運(yùn)行于不同廠商的藍(lán)牙協(xié)議棧之上。需移植的HAL接口(參見藍(lán)牙輔助配網(wǎng)開發(fā))。

    以BK7231U的移植實(shí)現(xiàn)為示例,在含AliOS Things的生活物聯(lián)網(wǎng)平臺SDK的代碼包中,Wi-Fi及其需要移植的HAL位于以下目錄下。

    • /Living_SDK/framework/protocol/linkkit/sdk/iotx-sdk-c_clone/include/imports/

    • /Living_SDK/framework/protocol/linkkit/sdk/iotx-sdk-c_clone/include/iot_import.h

    依賴的通用HAL的接口移植(如OS,LwIP,Security等)請參見Wi-Fi設(shè)備配網(wǎng)適配開發(fā),對Wi-Fi HAL接口在BK7231U(基于AliOS Things)的移植實(shí)現(xiàn)示例說明如下。

    jt11

    HAL_AWSS中的移植接口,有些是針對某種配網(wǎng)方式才需要實(shí)現(xiàn)的接口,對HAL_AWSS的所有HAL接口分類如下。

    分類

    說明

    配網(wǎng)通用接口

    所有配網(wǎng)方式都必須要實(shí)現(xiàn)的接口,包括藍(lán)牙輔助配網(wǎng)、設(shè)備熱點(diǎn)配網(wǎng)、一鍵配網(wǎng)、零配配網(wǎng)等

    設(shè)備熱點(diǎn)配網(wǎng)專用

    需要支持設(shè)備熱點(diǎn)配網(wǎng)方式時(shí)需實(shí)現(xiàn)的接口,如HAL_Awss_Open_Ap、HAL_Awss_Close_Ap等打開和關(guān)閉設(shè)備熱點(diǎn)的接口

    藍(lán)牙輔助配網(wǎng)設(shè)備熱點(diǎn)配網(wǎng)零配配網(wǎng)手機(jī)熱點(diǎn)配網(wǎng)

    需要支持這幾種配網(wǎng)方式中的一種或幾種時(shí),需實(shí)現(xiàn)的接口HAL_Awss_Get_Conn_Encrypt_Type

    一鍵配網(wǎng)專用

    需要支持一鍵配網(wǎng)方式時(shí)需實(shí)現(xiàn)的接口,如HAL_Awss_Get_Encrypt_Type

    1. 編譯相關(guān)控制。

      編譯配置文件請參見/Living_SDK/framework/protocol/linkkit/sdk/iotx-sdk-c_clone/make.settings

      #
      # Automatically generated file; DO NOT EDIT.
      # Main Menu
      #
      
      #
      # Configure Link Kit SDK for IoT Embedded Devices
      #
      FEATURE_SRCPATH="."
      FEATURE_MQTT_COMM_ENABLED=y
      FEATURE_ALCS_ENABLED=y
      #
      # MQTT Configurations
      #
      # FEATURE_MQTT_SHADOW is not set
      # FEATURE_MQTT_LOGPOST is not set
      FEATURE_MQTT_PREAUTH_SUPPORT_HTTPS_CDN=y
      FEATURE_DEVICE_MODEL_ENABLED=y
      
      FEATURE_MQTT_AUTO_SUBSCRIBE=y
      
      #
      # Device Model Configurations
      #
      # FEATURE_DEVICE_MODEL_GATEWAY is not set
      # 設(shè)備綁定的Feature需要打開,在設(shè)備配網(wǎng)完成后會和用戶賬戶之間進(jìn)行綁定
      FEATURE_DEV_BIND_ENABLED=y
      # FEATURE_DEVICE_MODEL_RAWDATA_SOLO is not set
      # FEATURE_COAP_COMM_ENABLED is not set
      FEATURE_OTA_ENABLED=y
      # FEATURE_HTTP2_COMM_ENABLED is not set
      # FEATURE_HTTP_COMM_ENABLED is not set
      FEATURE_SUPPORT_TLS=y
      # FEATURE_SAL_ENABLED is not set
      # 設(shè)備Wi-Fi配網(wǎng)的Feature必須打開
      FEATURE_WIFI_PROVISION_ENABLED=y
      
      #
      # AWSS Configurations
      #
      # 設(shè)備Wi-Fi配網(wǎng)可以支持的配網(wǎng)方式:一鍵配網(wǎng)、零配配網(wǎng)、設(shè)備熱點(diǎn)配網(wǎng)(藍(lán)牙輔助配網(wǎng)目前無需在此設(shè)置)
      FEATURE_AWSS_SUPPORT_SMARTCONFIG=y
      FEATURE_AWSS_SUPPORT_ZEROCONFIG=y
      FEATURE_AWSS_SUPPORT_DEV_AP=y
    2. 實(shí)現(xiàn)配網(wǎng)通用接口。

      /**
       * @brief   獲取Wi-Fi設(shè)備的MAC地址, 格式應(yīng)當(dāng)是"XX:XX:XX:XX:XX:XX"
       *
       * @param   mac_str : 用于存放MAC地址字符串的緩沖區(qū)數(shù)組
       * @return  指向緩沖區(qū)數(shù)組起始位置的字符指針
       */
      char *HAL_Wifi_Get_Mac(_OU_ char mac_str[HAL_MAC_LEN])
      {
          uint8_t mac[6] = { 0 };
      
          // 調(diào)用驅(qū)動層的接口獲取設(shè)備的MAC地址,并轉(zhuǎn)為字符串的格式
          hal_wifi_get_mac_addr(NULL, mac);
          snprintf(mac_str, HAL_MAC_LEN, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0],
                   mac[1], mac[2], mac[3], mac[4], mac[5]);
          return mac_str;
      }
      
      extern void wifi_get_ip(char ips[16]);
      /**
       * @brief   獲取Wi-Fi網(wǎng)口的IP地址,點(diǎn)分十進(jìn)制格式保存在字符串?dāng)?shù)組出參,
       * 二進(jìn)制格式則作為返回值,并以網(wǎng)絡(luò)字節(jié)序(大端)表達(dá)
       *
       * @param   ifname : 指定Wi-Fi網(wǎng)絡(luò)接口的名字
       * @param   ip_str : 存放點(diǎn)分十進(jìn)制格式的IP地址字符串的數(shù)組
       * @return  二進(jìn)制形式的IP地址,以網(wǎng)絡(luò)字節(jié)序(大端)組織
       */
      uint32_t HAL_Wifi_Get_IP(_OU_ char ip_str[NETWORK_ADDR_LEN],
                               _IN_ const char *ifname)
      {
          //(void *)ifname;
          // 調(diào)用驅(qū)動層的接口,獲取設(shè)備的IP地址。該IP地址分為兩種情況:
          // 1.一般情況,設(shè)備作為Station連接到AP,被分配的IP地址
          // 2.設(shè)備支持設(shè)備熱點(diǎn),開啟SoftAP模式時(shí)作為gateway的IP地址
          wifi_get_ip(ip_str);
          return 0;
      }
      
      /**
       * @brief   獲取在每個(gè)信道(`channel`)上掃描的時(shí)間長度,單位是毫秒
       *          該接口主要是一鍵配網(wǎng)和零配配網(wǎng)會使用到,因?yàn)檫@兩者在配網(wǎng)時(shí)
       *          需要在Wi-Fi信道列表上進(jìn)行輪詢掃描
       *
       * @return  時(shí)間長度, 單位是毫秒
       * @note    推薦時(shí)長是200毫秒到400毫秒
       */
      int HAL_Awss_Get_Channelscan_Interval_Ms(void)
      {
          // 一般都設(shè)置為該默認(rèn)的值
          return 250;
      }
      
      /**
       * @brief   獲取配網(wǎng)服務(wù)(`AWSS`)的超時(shí)時(shí)間長度,單位是毫秒
       *
       * @return  超時(shí)時(shí)長,單位是毫秒
       * @note    推薦時(shí)長是3分鐘
       */
      int HAL_Awss_Get_Timeout_Interval_Ms(void)
      {
          // 一般都設(shè)置為該默認(rèn)的值
          return 3 * 60 * 1000;
      }
      
      /**
       * @brief   802.11幀的處理函數(shù),可以將802.11 Frame傳遞給這個(gè)函數(shù)
       *
       * @param[in] buf @n 80211 frame buffer, or pointer to struct ht40_ctrl
       * @param[in] len @n 80211 frame buffer length
       * @param[in] link_type @n AWSS_LINK_TYPE_NONE for most rtos HAL,
       *                         and for linux HAL, do the following step to check
       *                         which header type the driver supported.
       * @verbatim
       *             a) iwconfig wlan0 mode monitor    #open monitor mode
       *             b) iwconfig wlan0 channel 6    #switch channel 6
       *             c) tcpdump -i wlan0 -s0 -w file.pacp    #capture 80211 frame
       * & save d) open file.pacp with wireshark or omnipeek check the link header
       * type and fcs included or not
       * @endverbatim
       * @param[in] with_fcs @n 80211 frame buffer include fcs(4 byte) or not
       * @param[in] rssi @n rssi of packet
       */
      awss_recv_80211_frame_cb_t g_ieee80211_handler;
      static void monitor_data_handler(uint8_t *buf, int len,
                                       hal_wifi_link_info_t *info)
      {
          int with_fcs  = 0;
          int link_type = AWSS_LINK_TYPE_NONE;
      
          (*g_ieee80211_handler)((char *)buf, len, link_type, with_fcs,
                                 info->rssi);
      }
      /**
       * @brief   設(shè)置Wi-Fi網(wǎng)卡工作在監(jiān)聽(Monitor或Sniffer)模式,
       *          并在收到802.11幀的時(shí)候調(diào)用被傳入的回調(diào)函數(shù),回調(diào)函數(shù)的格式如上
       *          必須要將802.11幀Buffer、長度、HAL類別,是否帶有FCS、RSSI等信息提供給上層
       *
       * @param[in] cb @n A function pointer, called back when wifi receive a
       * frame.
       */
      void HAL_Awss_Open_Monitor(_IN_ awss_recv_80211_frame_cb_t cb)
      {
          // 這里BK7231U是移植了AliOS Things的驅(qū)動移植層的,因此是hal_wifi_module
          // 風(fēng)格的實(shí)現(xiàn)。這里主要是將回調(diào)先注冊到驅(qū)動層,并開啟Monitor模式,
          // 在監(jiān)聽到802.11的幀時(shí),都通過回調(diào)函數(shù)上報(bào)上去
          hal_wifi_module_t *module = hal_wifi_get_default_module();
          if (module == NULL) {
              return;
          }
          g_ieee80211_handler = cb;
          hal_wifi_register_monitor_cb(module, monitor_data_handler);
          hal_wifi_start_wifi_monitor(module);
          HAL_Awss_Switch_Channel(6, 0, NULL);
      }
      
      /**
       * @brief   設(shè)置Wi-Fi網(wǎng)卡離開監(jiān)聽(Monitor或Sniffer)模式,
       * 并開始以站點(diǎn)(Station)模式工作
       */
      void HAL_Awss_Close_Monitor(void)
      {
          // 將原來注冊的回調(diào)函數(shù)取消(設(shè)置為NULL),并關(guān)閉設(shè)備的Monitor模式,
          hal_wifi_module_t *module;
          module = hal_wifi_get_default_module();
          if (module == NULL) {
              return;
          }
          hal_wifi_register_monitor_cb(module, NULL);
          hal_wifi_stop_wifi_monitor(module);
      }
      
      /**
       * @brief handle one piece of AP information from Wi-Fi scan result
       *
       * @param[in] ssid @n name of AP
       * @param[in] bssid @n mac address of AP
       * @param[in] channel @n AP channel
       * @param[in] rssi @n rssi range[-127, -1].
       *          the higher the RSSI number, the stronger the signal.
       * @param[in] is_last_ap @n this AP information is the last one if
       * is_last_ap > 0. this AP information is not the last one if is_last_ap ==
       * 0.
       * @return 0 for Wi-Fi scan is done, otherwise return -1
       * @see None.
       * @note None.
       */
      typedef int (*awss_wifi_scan_result_cb_t)(const char ssid[HAL_MAX_SSID_LEN],
                                                const uint8_t bssid[ETH_ALEN],
                                                enum AWSS_AUTH_TYPE auth,
                                                enum AWSS_ENC_TYPE  encry,
                                                uint8_t channel, signed char rssi,
                                                int is_last_ap);
      /**
       * @brief   啟動一次Wi-Fi的空中掃描(Scan)
       *          該模式需要與前面的Monitor(或Sniffer)模式區(qū)別,
       *          Monitor(Sniffer):持續(xù)開啟802.11幀監(jiān)聽,并實(shí)時(shí)上報(bào)監(jiān)聽到的幀,直到該模式被關(guān)閉
       *          Scan:掃描AP(通過Beacon和Probe Request幀),并記錄一次掃描到的多個(gè)AP的結(jié)果
       *
       * @param[in] cb @n pass ssid info(scan result) to this callback one by one
       * @return 0 for Wi-Fi scan is done, otherwise return -1
       * @see None.
       * @note
       *      This API should NOT exit before the invoking for cb is finished.
       *      This rule is something like the following :
       *      HAL_Wifi_Scan() is invoked...
       *      ...
       *      for (ap = first_ap; ap <= last_ap; ap = next_ap){
       *        cb(ap)
       *      }
       *      ...
       *      HAL_Wifi_Scan() exit...
       */
      int HAL_Wifi_Scan(awss_wifi_scan_result_cb_t cb)
      {
          // 注冊Scan到的AP列表的回調(diào)函數(shù)
          // 并啟動Scan(對周邊AP的掃描,建議實(shí)現(xiàn)為active scan,掃到的效率更高)
          // 該函數(shù)是同步執(zhí)行的方式,即調(diào)用后線程會被其阻塞,直到本次掃描結(jié)束
          netmgr_register_wifi_scan_result_callback(
            (netmgr_wifi_scan_result_cb_t)cb);
          hal_wifi_start_scan_adv(NULL);
          while (netmgr_get_scan_cb_finished() != true) { // block
              aos_msleep(50);
          }
          return 0;
      }
      
      /**
       * @brief   設(shè)置Wi-Fi網(wǎng)卡切換到指定的信道(channel)上
       *
       * @param[in] primary_channel @n Primary channel.
       * @param[in] secondary_channel @n Auxiliary channel if 40Mhz channel is
       * supported, currently this param is always 0.
       * @param[in] bssid @n A pointer to Wi-Fi BSSID on which awss lock the
       * channel, most HAL may ignore it.
       */
      void HAL_Awss_Switch_Channel(_IN_ char     primary_channel,
                                   _IN_OPT_ char secondary_channel,
                                   _IN_OPT_ uint8_t bssid[ETH_ALEN])
      {
          hal_wifi_module_t *module;
      
          module = hal_wifi_get_default_module();
          if (module == NULL) {
              return;
          }
          // 調(diào)用驅(qū)動層接口,設(shè)置設(shè)備此時(shí)工作在指定的信道,對于某些應(yīng)用需要,指定信道
          // 會使一些操作更加高效
          hal_wifi_set_channel(module, (int)primary_channel);
      }
      
      /**
       * @brief   要求Wi-Fi網(wǎng)卡連接指定熱點(diǎn)(Access Point)的函數(shù)
       *
       * @param[in] connection_timeout_ms @n AP connection timeout in ms or
       HAL_WAIT_INFINITE
       * @param[in] ssid @n AP ssid
       * @param[in] passwd @n AP passwd
       * @param[in] auth @n optional(AWSS_AUTH_TYPE_INVALID), AP auth info
       * @param[in] encry @n optional(AWSS_ENC_TYPE_INVALID), AP encry info
       * @param[in] bssid @n optional(NULL or zero mac address), AP bssid info
       * @param[in] channel @n optional, AP channel info
       * @return
         @verbatim
           = 0: connect AP & DHCP success
           = -1: connect AP or DHCP fail/timeout
         @endverbatim
       * @see None.
       * @note
       *      If the STA connects the old AP, HAL should disconnect from the old
       AP firstly.
       */
      int HAL_Awss_Connect_Ap(_IN_ uint32_t connection_timeout_ms,
                              _IN_ char     ssid[HAL_MAX_SSID_LEN],
                              _IN_ char     passwd[HAL_MAX_PASSWD_LEN],
                              _IN_OPT_ enum AWSS_AUTH_TYPE auth,
                              _IN_OPT_ enum AWSS_ENC_TYPE  encry,
                              _IN_OPT_ uint8_t bssid[ETH_ALEN],
                              _IN_OPT_ uint8_t channel)
      {
          int                ms_cnt = 0;
          netmgr_ap_config_t config = { 0 };
          if (ssid != NULL) {
              strncpy(config.ssid, ssid, sizeof(config.ssid) - 1);
          }
          if (passwd != NULL) {
              strncpy(config.pwd, passwd, sizeof(config.pwd) - 1);
          }
          if (bssid != NULL) {
              memcpy(config.bssid, bssid, ETH_ALEN);
          }
          // 將要連接的AP的信息暫存下來
          netmgr_set_ap_config(&config);
          // 在正式連接AP前,Suspend Station,防止設(shè)備受上一次操作未結(jié)束的干擾
          hal_wifi_suspend_station(NULL);
      
          // LOGI("aos_awss", "Will reconnect wifi: %s %s", ssid, passwd);
          // 實(shí)際會調(diào)用驅(qū)動層接口,向指定的AP發(fā)起連接
          netmgr_reconnect_wifi();
      
          // 在調(diào)用驅(qū)動層接口去連接AP后,在此阻塞線程一斷時(shí)間,該段時(shí)間內(nèi)持續(xù)檢查設(shè)備當(dāng)前是否
          // 已經(jīng)連接AP成功且獲取到了IP地址,如果獲取到IP地址,該函數(shù)結(jié)束,并返回連接成功的結(jié)果
          while (ms_cnt < connection_timeout_ms) {
              if (netmgr_get_ip_state() == false) {
                  LOGD("[waitConnAP]", "waiting for connecting AP");
                  aos_msleep(500);
                  ms_cnt += 500;
              } else {
                  LOGI("[waitConnAP]", "AP connected");
                  return 0;
              }
          }
          // if AP connect fail, should inform the module to suspend station
          // to avoid module always reconnect and block Upper Layer running
          // 如果在連接AP超時(shí)時(shí)間到達(dá),都沒能成功連上AP,或者連上了AP沒能獲取到IP地址,說明設(shè)備
          // 本次發(fā)起連接是失敗的(可能是AP的ssid,密碼等信息有誤,或者是AP本身工作異常,或者是
          // 干擾太強(qiáng)或信號太弱導(dǎo)致沒法順利連接上),那么此時(shí)Suspend Station(驅(qū)動層可能還在
          // 處于對AP發(fā)起連接的狀態(tài),Suspend Station將該狀態(tài)終止,使設(shè)備不再向AP發(fā)起連接),
          // 最后返回連接失敗的結(jié)果給上層處理
          hal_wifi_suspend_station(NULL);
      
          return -1;
      }
      
      #define FRAME_ACTION_MASK (1 << FRAME_ACTION)
      #define FRAME_BEACON_MASK (1 << FRAME_BEACON)
      #define FRAME_PROBE_REQ_MASK (1 << FRAME_PROBE_REQ)
      #define FRAME_PROBE_RESP_MASK (1 << FRAME_PROBE_RESPONSE)
      #define FRAME_DATA_MASK (1 << FRAME_DATA)
      /**
       * @brief   在當(dāng)前信道(channel)上以基本數(shù)據(jù)速率(1Mbps)發(fā)送裸的802.11幀(raw
       *          802.11 frame)
       *
       * @param[in] type @n see enum HAL_Awss_frame_type, currently only
       *                    FRAME_BEACON,F(xiàn)RAME_PROBE_REQ is used
       * @param[in] buffer @n 80211 raw frame, include complete mac header & FCS
       field
       * @param[in] len @n 80211 raw frame length
       * @return
         @verbatim
         =  0, send success.
         = -1, send failure.
         = -2, unsupported.
         @endverbatim
       * @see None.
       * @note awss use this API send raw frame in Wi-Fi monitor mode & station
       mode
       */
      int HAL_Wifi_Send_80211_Raw_Frame(_IN_ enum HAL_Awss_Frame_Type type,
                                        _IN_ uint8_t *buffer, _IN_ int len)
      {
          // 調(diào)用驅(qū)動層的接口發(fā)送802.11的幀,類型必須要支持上面定義的5種
          return hal_wlan_send_80211_raw_frame(NULL, buffer, len);
      }
      
      /**
       * @brief   管理幀的處理回調(diào)函數(shù)
       *
       * @param[in] buffer @n 80211 raw frame or ie(information element) buffer
       * @param[in] len @n buffer length
       * @param[in] rssi_dbm @n rssi in dbm
       * @param[in] buffer_type @n 0 when buffer is a 80211 frame,
       *                          1 when buffer only contain IE info
       * @return None.
       * @see None.
       * @note None.
       */
      typedef void (*awss_wifi_mgmt_frame_cb_t)(_IN_ uint8_t *buffer,
                                                _IN_ int len,
                                                _IN_ signed char rssi_dbm,
                                                _IN_ int buffer_type);
      
      static awss_wifi_mgmt_frame_cb_t monitor_cb = NULL;
      static void mgnt_rx_cb(uint8_t *data, int len, hal_wifi_link_info_t *info)
      {
          if (monitor_cb) {
              monitor_cb(data, len, info->rssi, 0);
          }
      }
      /**
       * @brief   使能或禁用對管理幀的過濾
       *
       * @param[in] filter_mask @n see mask macro in enum HAL_Awss_frame_type,
       *                      currently only FRAME_PROBE_REQ_MASK &
       FRAME_BEACON_MASK is used
       * @param[in] vendor_oui @n oui can be used for precise frame match,
       optional
       * @param[in] callback @n see awss_wifi_mgmt_frame_cb_t, passing 80211
       *                      frame or ie to callback. when callback is NULL
       *                      disable sniffer feature, otherwise enable it.
       * @return
         @verbatim
         =  0, success
         = -1, fail
         = -2, unsupported.
         @endverbatim
       * @see None.
       * @note awss use this API to filter specific mgnt frame in Wi-Fi station
       mode
       */
      int HAL_Wifi_Enable_Mgmt_Frame_Filter(
        _IN_ uint32_t filter_mask, _IN_OPT_ uint8_t vendor_oui[3],
        _IN_ awss_wifi_mgmt_frame_cb_t callback)
      {
          monitor_cb = callback;
          // 管理幀的過濾開啟與關(guān)閉,都在此接口中實(shí)現(xiàn),開啟時(shí)需傳入有效的回調(diào)函數(shù),而傳入NULL時(shí)
          // 表示將管理幀的過濾功能關(guān)閉。
          // 管理幀過濾的開啟時(shí)機(jī),可能在設(shè)備處于Station模式,也可能在設(shè)備處于設(shè)備熱點(diǎn)模式,
          // 因此只要設(shè)備Wi-Fi stack能獲取到周邊的管理幀,都需要能支持管理幀的過濾開啟
          if (callback != NULL) {
              hal_wlan_register_mgnt_monitor_cb(NULL, mgnt_rx_cb);
          } else {
              hal_wlan_register_mgnt_monitor_cb(NULL, NULL);
          }
      
          return 0;
      }
      
      /**
       * @brief check system network is ready(get ip address) or not.
       *
       * @param None.
       * @return 0, net is not ready; 1, net is ready.
       * @see None.
       * @note None.
       */
      int HAL_Sys_Net_Is_Ready()
      {
          // 調(diào)用接口判斷設(shè)備當(dāng)前的IP地址是否有效
          return netmgr_get_ip_state() == true ? 1 : 0;
      }
      
      /**
       * @brief   獲取所連接的熱點(diǎn)(Access Point)的信息
       *
       * @param[out] ssid: array to store ap ssid. It will be null if ssid is not
       required.
       * @param[out] passwd: array to store ap password. It will be null if ap
       password is not required.
       * @param[out] bssid: array to store ap bssid. It will be null if bssid is
       not required.
       * @return
         @verbatim
           = 0: succeeded
           = -1: failed
         @endverbatim
       * @see None.
       * @note None.
       */
      int HAL_Wifi_Get_Ap_Info(_OU_ char ssid[HAL_MAX_SSID_LEN],
                               _OU_ char passwd[HAL_MAX_PASSWD_LEN],
                               _OU_ uint8_t bssid[ETH_ALEN])
      {
          netmgr_ap_config_t config = { 0 };
      
          netmgr_get_ap_config(&config);
         if (ssid) {
              strncpy(ssid, config.ssid, HAL_MAX_SSID_LEN - 1);
          }
          if (passwd) {
      #ifdef DISABLE_SECURE_STORAGE
              strncpy(passwd, config.pwd, HAL_MAX_PASSWD_LEN - 1);
      #else
              extern int iotx_ss_decrypt(const char* in_data, int in_len, char* out_data, int out_len);
              iotx_ss_decrypt(config.pwd, MAX_PWD_SIZE, passwd, MAX_PWD_SIZE);
      #endif
          }
          if (bssid) {
              memcpy(bssid, config.bssid, ETH_ALEN);
          }
      
          return 0;
      }
      
      /**
       * @brief   獲取當(dāng)前Station模式與AP連接狀態(tài)的信息
       *
       * @param[out] p_rssi: rssi value of current link
       * @param[out] p_channel: channel of current link
       * 
       * @return
         @verbatim
           = 0: succeeded
           = -1: failed
         @endverbatim
       * @see None.
       * @note None.
       * @note awss use this API to get rssi and channel of current link
       */
      int HAL_Wifi_Get_Link_Stat(_OU_ int *p_rssi,
                                 _OU_ int *p_channel)
      {
          int ret;
          hal_wifi_link_stat_t link_stat;
          if (netmgr_get_ip_state() == true)
          {
              ret = hal_wifi_get_link_stat(NULL, &link_stat);
              if ((ret == 0) && link_stat.is_connected) {
                  *p_rssi = link_stat.wifi_strength;
                  *p_channel = link_stat.channel;
              } else {
                  return -1;
              }
          } else {
              return -1;
          }
          return 0;
      }
    3. 實(shí)現(xiàn)藍(lán)牙輔助配網(wǎng)關(guān)聯(lián)的專用接口。

      /**
       * @brief    Get Security level for Wi-Fi configuration with connection.
       *           Used for AP solution of router and App.
       *
       * @param None.
       * @return The security level:
         @verbatim
          3: aes128cfb with aes-key per product and aes-iv = random
          4: aes128cfb with aes-key per device and aes-iv = random
          5: aes128cfb with aes-key per manufacture and aes-iv = random
          others: invalid
         @endverbatim
       * @see None.
       */
      int HAL_Awss_Get_Conn_Encrypt_Type()
      {
          char invalid_ds[DEVICE_SECRET_LEN + 1] = {0};
          char ds[DEVICE_SECRET_LEN + 1] = {0};
          // 用于區(qū)分該種配網(wǎng)方式的加密方式是使用“一機(jī)一密”還是“一型一密”
          // 如果DeviceSecret可以獲取到,則使用“一機(jī)一密”的高安全級別加密方式
          // 如果設(shè)備本地未找到DeviceSecret,則降級使用“一型一密”的次高安全級別加密方式
          HAL_GetDeviceSecret(ds);
          if (memcmp(invalid_ds, ds, sizeof(ds)) == 0)
              return 3;
          memset(invalid_ds, 0xff, sizeof(invalid_ds));
          if (memcmp(invalid_ds, ds, sizeof(ds)) == 0)
              return 3;
          return 4;
      }

五、生成設(shè)備固件

生活物聯(lián)網(wǎng)平臺SDK提供了藍(lán)牙輔助配網(wǎng)的示例應(yīng)用,完成移植后,可以基于示例應(yīng)用編譯藍(lán)牙輔助配網(wǎng)設(shè)備固件,并對藍(lán)牙輔助配網(wǎng)的整體功能進(jìn)行快速驗(yàn)證。

SDK版本

編譯指令

1.3.0以上版本

./build.sh example smart_outlet bk7231udevkitc MAINLAND ONLINE 1

1.3.0及以下的版本

cd Living_SDK

aos make clean

aos make comboapp@bk7231udevkitc btstack=vendor

  1. 初始化與啟動應(yīng)用。

    int application_start(int argc, char **argv)

    示例應(yīng)用目錄中的app_entry.c文件的application_start函數(shù),該函數(shù)主要實(shí)現(xiàn)如下功能。

    • 系統(tǒng)初始化與啟動

    • 設(shè)備調(diào)試日志等級、設(shè)備信息、設(shè)備診斷模塊設(shè)置

    • Wi-Fi模塊初始化,以及相關(guān)的事件訂閱

    • 串口交互命令cli的初始化和注冊

    • Wi-Fi模塊的啟動,與相關(guān)任務(wù)的創(chuàng)建

  2. 動態(tài)開啟或關(guān)閉設(shè)備的藍(lán)牙輔助配網(wǎng)模式。

    實(shí)現(xiàn)設(shè)備系統(tǒng)與各模塊的初始化后,通過如下代碼實(shí)現(xiàn),可以動態(tài)開啟或關(guān)閉設(shè)備的藍(lán)牙輔助配網(wǎng)模式。

    // 關(guān)閉藍(lán)牙輔助配網(wǎng)功能
    breeze_awss_stop();
    
    // 開啟藍(lán)牙輔助配網(wǎng)功能
    breeze_awss_start();
  3. 實(shí)現(xiàn)藍(lán)牙輔助配網(wǎng)工作流程。

    示例應(yīng)用的其核心流程實(shí)現(xiàn)在示例應(yīng)用目錄中的combo_net.c文件的combo_net_init函數(shù)。該函數(shù)主要實(shí)現(xiàn)以下功能。

    • 注冊應(yīng)用層的回調(diào),會觸發(fā)去連接路由器。

    • 將設(shè)備信息設(shè)置到下層的Breeze SDK中。

    • 初始化并開啟藍(lán)牙輔助配網(wǎng)的BLE通信通道。

    設(shè)備發(fā)出BLE廣播(廣播里面會攜帶藍(lán)牙輔助配網(wǎng)功能的標(biāo)識),處于BLE廣播狀態(tài)的設(shè)備可以被移動端App掃描發(fā)現(xiàn)。此時(shí)App上的操作過程以及設(shè)備的狀態(tài)變化說明如下。

    1. 設(shè)備進(jìn)入藍(lán)牙輔助配網(wǎng)狀態(tài)時(shí),開始持續(xù)發(fā)出BLE廣播,廣播里攜帶藍(lán)牙輔助配網(wǎng)功能的標(biāo)識。

    2. 移動端App掃描發(fā)現(xiàn)該待配網(wǎng)的Combo設(shè)備,并從移動端App發(fā)起與該設(shè)備建立連接的請求。

      建立連接時(shí),移動端App與設(shè)備之間通過安全認(rèn)證,確保建立的BLE連接是安全可靠的。

    3. App通過BLE安全連接通道下發(fā)配網(wǎng)信息給設(shè)備端。

    4. 設(shè)備端通過Breeze SDK,接收和解析配網(wǎng)信息。

      設(shè)備端在獲取到配網(wǎng)信息后,觸發(fā)注冊的combo_service_event事件處理函數(shù)(此時(shí)底層SDK已經(jīng)獲取到了Wi-Fi聯(lián)網(wǎng)需要的路由器的SSID和密碼等信息)。combo_service_event事件處理函數(shù)時(shí),會檢測路由器的SSID和信號強(qiáng)度等情況,并向路由器發(fā)起連接請求。

    5. 連接路由器成功后,獲取IP地址,啟動設(shè)備連云。

    說明

    整個(gè)過程中如果出現(xiàn)異常,設(shè)備端會通過異常自檢生成關(guān)鍵錯誤碼信息,通過和移動端App之間的BLE連接傳回,并在移動端App界面顯示。

    int combo_net_init()
    {
        breeze_dev_info_t dinfo = { 0 };
        // 注冊獲取到App端傳過來的配網(wǎng)信息時(shí)的回調(diào),會觸發(fā)去連接路由器的動作
        aos_register_event_filter(EV_BZ_COMBO, combo_service_event, NULL);
        if ((strlen(g_combo_pk) > 0) && (strlen(g_combo_ps) > 0) \
        && (strlen(g_combo_dn) > 0) && (strlen(g_combo_ds) > 0) && g_combo_pid > 0) {
            // 設(shè)備信息設(shè)置到下層的SDK中,藍(lán)牙輔助配網(wǎng)與一般的Wi-Fi設(shè)備相比,
            // 會多一個(gè)PID的設(shè)備信息,專用于藍(lán)牙的通信握手等功能之用
            dinfo.product_id = g_combo_pid;
            dinfo.product_key = g_combo_pk;
            dinfo.product_secret = g_combo_ps;
            dinfo.device_name = g_combo_dn;
            dinfo.device_secret = g_combo_ds;
            // 初始化藍(lán)牙輔助配網(wǎng)所需的BLE協(xié)議棧、Breeze SDK等,并注冊獲取到配網(wǎng)信息的回調(diào)
            // 同時(shí)正式啟動藍(lán)牙輔助配網(wǎng)
            breeze_awss_init(apinfo_ready_handler, &dinfo);
            breeze_awss_start();
        } else {
            // 如果設(shè)備信息設(shè)置有誤,則無法進(jìn)行藍(lán)牙輔助配網(wǎng)
            printf("combo device info not set!\n");
        }
        return 0;
    }
  4. 調(diào)試藍(lán)牙輔助配網(wǎng)設(shè)備。

    編譯生成設(shè)備固件,并燒錄到相應(yīng)的開發(fā)板之后,可以通過如下的串口命令,觸發(fā)設(shè)備的相應(yīng)動作(生活物聯(lián)網(wǎng)平臺SDK 1.3.0及之后的版本才支持動態(tài)串口命令交互)。

    1. 燒錄設(shè)備證書信息。

      藍(lán)牙相關(guān)的設(shè)備證書包括ProductKey、DeviceName、DeviceSecret、ProductSecret、ProductID(您在生活物聯(lián)網(wǎng)控制臺創(chuàng)建的產(chǎn)品與設(shè)備后平臺自動頒發(fā)的),在設(shè)備上電初始執(zhí)行以下命令燒錄設(shè)備證書信息。

      linkkey ProductKey DeviceName DeviceSecret ProductSecret ProductID
    2. 開啟一鍵配網(wǎng)功能。

      此時(shí)如果藍(lán)牙輔助配網(wǎng)進(jìn)行中,會先自動關(guān)閉藍(lán)牙輔助配網(wǎng)功能。

      awss
      
      active_awss
    3. 開啟藍(lán)牙輔助配網(wǎng)功能。

      在設(shè)備正常啟動后,默認(rèn)會進(jìn)入信道掃描的狀態(tài)。此時(shí)如果一鍵配網(wǎng)進(jìn)行中,會先自動關(guān)閉一鍵配網(wǎng)功能。

      ble_awss

      啟動藍(lán)牙輔助配網(wǎng)后,設(shè)備會通過BLE廣播自己的藍(lán)牙輔助配網(wǎng)相關(guān)的設(shè)備信息,移動端的App可在其設(shè)備發(fā)現(xiàn)頁面發(fā)現(xiàn)處于待配網(wǎng)狀態(tài)的設(shè)備。通過在移動端App界面可發(fā)起對設(shè)備的藍(lán)牙輔助配網(wǎng),配網(wǎng)過程、配網(wǎng)結(jié)果、配網(wǎng)過程中發(fā)生的異常等信息會通過移動端App界面實(shí)時(shí)展示。

    4. 清除設(shè)備配網(wǎng)信息。

      reset

六、驗(yàn)證藍(lán)牙輔助配網(wǎng)功能

您可以使用生活物聯(lián)網(wǎng)平臺提供的云智能App(公版App)來驗(yàn)證藍(lán)牙輔助配網(wǎng)功能。

  1. 下載云智能App(2.7.5或以上的版本)。下載方式請參見云智能App介紹

  2. 登錄云智能App。

  3. 打開手機(jī)系統(tǒng)的藍(lán)牙開關(guān)。

  4. 進(jìn)入App的設(shè)備發(fā)現(xiàn)界面,開始掃描發(fā)現(xiàn)藍(lán)牙輔助配網(wǎng)狀態(tài)的設(shè)備。

    如果設(shè)備無法發(fā)現(xiàn),請檢查確保以下各項(xiàng)是否設(shè)置有誤。

    • 設(shè)備是否已處于藍(lán)牙廣播狀態(tài)(可使用相關(guān)工具搜索,如nRF Connect App)。

      藍(lán)牙輔助配網(wǎng)廣播內(nèi)容示例說明如下。

      jt12

      廣播數(shù)據(jù)內(nèi)容主要位于廣播的Manufacturer data字段中,其中包含Company ID和一些服務(wù)支持標(biāo)識,以及MAC地址。其中MAC地址是表示W(wǎng)i-Fi MAC(Combo實(shí)際上是Wi-Fi設(shè)備,此處藍(lán)牙只是作為輔助配網(wǎng),設(shè)備和云端通信鏈路通過Wi-Fi),此處Wi-Fi MAC地址為C8:47:8C:00:00:18

    • 設(shè)備證書信息是否設(shè)置正確(使用linkkey命令設(shè)置的內(nèi)容)。

    • App的賬號環(huán)境與創(chuàng)建設(shè)備產(chǎn)品的站點(diǎn)是否對應(yīng)。

    • 控制臺人機(jī)交互中是否配置了藍(lán)牙輔助配網(wǎng)的配網(wǎng)方式。

  5. App界面發(fā)現(xiàn)藍(lán)牙輔助配網(wǎng)設(shè)備后,點(diǎn)擊即可開始藍(lán)牙輔助配網(wǎng)流程,其間需要輸入手機(jī)連著的路由器的SSID和密碼,并且在App UI界面確認(rèn)設(shè)備已處于配網(wǎng)狀態(tài),用戶界面確認(rèn)完畢后,App端會去和設(shè)備建立藍(lán)牙連接。

    如果藍(lán)牙連接在短時(shí)間內(nèi)斷開,請檢查確保以下項(xiàng)是否正常。

    • 設(shè)備證書信息是否設(shè)置正確(使用linkkey命令設(shè)置的內(nèi)容)。

    • 設(shè)備BLE協(xié)議棧移植以及示例應(yīng)用的實(shí)現(xiàn)是否檢查確認(rèn)無誤

    • 手機(jī)連著的路由器的網(wǎng)絡(luò)是否能正常使用

  6. 手機(jī)將路由器信息傳輸給設(shè)備端,設(shè)備收到信息后去連接目標(biāo)路由器。

    此時(shí)設(shè)備與手機(jī)之間的藍(lán)牙連接不會斷開,設(shè)備連接路由器、連接云端過程中如果有失敗情況發(fā)生,設(shè)備會啟動自檢(需升級至生活物聯(lián)網(wǎng)平臺SDK 1.3.0之后的版本才支持失敗詳情自檢的能力),并將自檢結(jié)果通過藍(lán)牙連接返回給手機(jī),并在App界面上顯示。

  7. App界面跳轉(zhuǎn)出設(shè)備的控制界面(如“燈”產(chǎn)品的控制界面可以開關(guān)燈,調(diào)整燈的亮度等)。

    此時(shí),藍(lán)牙輔助配網(wǎng)的功能調(diào)試成功。接下來您需要對設(shè)備產(chǎn)品的完整功能、穩(wěn)定性能、成功率等進(jìn)行嚴(yán)格測試把控,最終完成整個(gè)方案的量產(chǎn)和發(fā)布。