本文以TG7100C芯片為例,介紹基于生活物聯網平臺SDK(V1.6.6)中的smart_outlet應用示例,開發單孔Wi-Fi智能插座設備固件的流程。

背景信息

應用示例smart_outlet的功能介紹如下:

  • 支持云智能App(V3.5.5以上)與天貓精靈App(4.13.0以上)藍牙輔助配網。
  • 支持通過云端、本地通信(目前僅云智能App支持)對設備進行控制的能力。
  • 支持通過生活物聯網平臺進行設備OTA的能力。
  • 支持恢復工廠設置。
  • 支持斷電用戶設置記憶。

TG7100C概述

TG7100C是天貓精靈推出的Wi-Fi藍牙Combo芯片。TG7100C芯片相關文檔和軟件工具介紹,請參見TG7100C。

說明

關于TG7100B芯片的驅動、產測、硬件設計、射頻等使用問題,以及基于生活物聯網平臺藍牙Mesh SDK的應用開發,例如產品配置、配網、連云、OTA等問題,您可以通過商務聯系技術支持進行反饋。

固件編譯

  1. 下載SDK。下載地址,請參見獲取SDK。
  2. 配置開發環境。詳細介紹,請參見準備開發環境
  3. 編譯代碼。
    1. (可選)解壓SDK壓縮包。
      如果您通過Git命令的方式下載SDK,則無需解壓。

      SDK根目錄build.sh文件說明:根據硬件使用的模組型號和要編譯的應用,可以修改文件中的如下參數。

      default_type="example"     //配置產品類型
      default_app="smart_outlet" //配置編譯的應用名稱
      default_board="tg7100cevb" //配置編譯的模組型號
      default_region=MAINLAND    //配置設備的連云區域,配置為MAINLAND或SINGAPORE都可以,設備可以全球范圍內激活
      default_env=ONLINE         //配置連云環境,默認設置為線上環境(ONLINE)
      default_debug=0            //配置debug等級,生產固件建議為0
      default_args=""            //配置其他編譯參數
      //更多介紹,請參見README.md
    2. 將開發的業務代碼存放到SDK相應的目錄下,例如非計量插座標品代碼在Products/example/smart_outlet 目錄下。
    3. 執行以下命令,快速編譯smart_outlet應用示例。
      ./build.sh example smart_outlet tg7100cevb MAINLAND ONLINE 0

      編譯完成后,在out/smart_outlet@tg7100cevb/目錄下會生成smart_outlet@tg7100cevb.bin文件。

    4. smart_outlet@tg7100cevb.bin文件燒錄到真實設備中。
      tg7100cevb_ota.bin文件為OTA使用的固件。TG7100C編譯結果

固件燒錄與運行

  1. 在TG7100C開發板上燒錄固件。詳細操作,請參見TG7100C開發板用戶手冊。
  2. 短路接通開發板的第4個引腳與第5個引腳,并按開發板的復位鍵。
    開發板設置圖如下。開發板燒錄模式
  3. 打開下載好的燒錄工具目錄中的TGFlashEnv.exe,單擊Finish,進入燒錄界面。
  4. Interface選擇Uart,并單擊Refresh按鍵。
  5. 設置串口參數,以及選擇好對應的燒錄文件。
    串口參數的配置如下圖所示。
    • Partition Table、Boot 2 BinMFG Bin選擇燒錄工具目錄下對應的文件即可,文件名如圖。
    • Firmware Bin選擇編譯出的固件。
    • Chip Erase可以根據是否要擦除整片Flash選擇True或者False,如調試中要保留之前寫入過的設備證書,可以選擇False
    TG7100C燒錄軟件
  6. 單擊Download按鈕,并同時按下開發板上的復位鍵,開始燒錄固件。
  7. 燒錄完畢后,查看運行的日志。
    短路連接第3個引腳與第4個引腳(如下圖所示),將串口工具波特率設置為2000000,并按下開發板復位鍵。開發板運行模式

    常用的cli指令如下。

    • reset:設備重置,清除設備配網信息。
    • free:查看內存使用情況。
    • linkkey:寫入與查看證書。
    • mac:查看開發板Wi-Fi MAC地址。

smart_outlet應用代碼結構介紹

smart_outlet應用示例中的文件結構如下。

├── Products
│   │   ├── example/smart_outlet
│   │   │   ├── app_entry.c
│   │   │   ├── app_entry.h
│   │   │   ├── combo_net.c
│   │   │   ├── device_state_manager.c
│   │   │   ├── device_state_manager.h
│   │   │   ├── factory.c
│   │   │   ├── factory.h
│   │   │   ├── makefile
│   │   │   ├── make.settings
│   │   │   ├── msg_process_center.c
│   │   │   ├── msg_process_center.h
│   │   │   ├── property_report.c
│   │   │   ├── property_report.h
│   │   │   ├── smart_outlet.h
│   │   │   ├── smart_outlet.json
│   │   │   ├── smart_outlet_main.c
│   │   │   ├── smart_outlet.mk
│   │   │   ├── vendor.c
│   │   │   └── vendor.h

詳細的文件說明如下。

  • 廠家需要適配的文件(設備初始化等):vendor.cvendor.h
  • 應用程序主入口:app_entry.csmart_outlet_main.c
  • 配網和連云狀態管理:device_state_manager.c
  • 設備控制指令處理:msg_process_center.c
  • 設備屬性上報:property_report.c
  • 廠測模式:factory.c
  • 藍牙輔助配網:combo_net.c

固件適配說明

標品固件移植適配對單路智能插座應用,只需要較小的修改,就可以完成產品固件的輸出。根據產品的不同需求,涉及到的調整項介紹如下。

  • GPIO適配

    單路插座需要兩個GPIO分別控制繼電器開關、LED亮滅和一個GPIO讀取按鍵狀態。那么只需要修改vendor.c中定義,實例如下。

    ......
    #elif (defined (TG7100CEVB))
    #define LED_GPIO    1               // 控制LED亮滅
    #define RELAY_GPIO  5               // 控制繼電器開關
    #define KEY_GPIO    3               // 讀取按鍵狀態
    ......

    產品開發時,可以根據具體的原理圖設計配置對應的GPIO。

  • 狀態LED顯示適配
    • 設備狀態定義在文件Products/example/smart_outlet/device_state_manager.h 中。
      typedef enum {
          RECONFIGED = 0,            //reconfig with netconfig exist
          UNCONFIGED,                //配網開始
          AWSS_NOT_START,            //配網超時
          GOT_AP_SSID,               //連接AP成功
          CONNECT_CLOUD_SUCCESS,     //連云成功
          CONNECT_CLOUD_FAILED,      //連云失敗
          CONNECT_AP_FAILED,         //連接AP失敗
          CONNECT_AP_FAILED_TIMEOUT, //連接AP超時
          APP_BIND_SUCCESS,          //APP綁定成功
          ...
          UNKNOW_STATE
      } eNetState;
    • 狀態顯示的處理代碼在文件Products/example/smart_outlet/device_state_manager.c 中的indicate_net_state_task 函數中??梢愿鶕a品的不同需求做調整。
      static void indicate_net_state_task(void *arg)
      {
          uint32_t nCount = 0;
          uint32_t duration = 0;
          int pre_state = UNKNOW_STATE;
          int cur_state = UNKNOW_STATE;
          int switch_stat = 0;
      
          while (1) {
              pre_state = cur_state;
              cur_state = get_net_state();
              switch (cur_state) {
                  case RECONFIGED:
                      ...
                      break;
                  case UNCONFIGED:
                      ...
                      break;
                  case AWSS_NOT_START:
                      ...
                      break;
                  case GOT_AP_SSID:
                  case CONNECT_CLOUD_FAILED:
                      ...
                      break;
                  case CONNECT_AP_FAILED_TIMEOUT:
                      ...
                      break;
                  case CONNECT_AP_FAILED:
                      ...
                      break;
                  case CONNECT_CLOUD_SUCCESS:
                      ...
                      break;
                  case APP_BIND_SUCCESS:        
                      ...
                      break;
                  ...
                  default:
                      break;
              }
              aos_msleep(100);
          }
      
          ...
      }
    • 當前代碼中實現的默認LED顯示如下。
      狀態默認LED顯示
      配網模式插座LED反復閃爍,亮0.8秒,滅0.8秒。
      恢復出廠設置插座LED反復閃爍,亮0.2秒,滅0.2秒。
      連接AP 超時/連接AP 認證失?。ǔ瑫r時間2分鐘)插座LED反復閃爍的模式更改為,亮0.5秒、滅0.5秒,閃爍兩分鐘之后停止閃爍。停止閃爍之后,如果插座配電使能則LED燈點亮,否則LED燈滅掉。
      連接AP成功、嘗試連云插座LED反復閃爍,亮0.8秒,滅0.8秒,然后開始嘗試連接云端。
      連云失敗連接云端失敗后,需要再次嘗試連接,其間LED的顯示與“連接AP成功、嘗試連云”模式一樣。
      連云成功當設備連接云端成功,則停止LED閃爍,若插座配電打開則LED點亮,若插座配電未打開則LED滅掉。
  • 按鍵處理適配
    標品固件根據用戶按下按鍵的時長,確定用戶的行為,目前按鍵有三種用戶行為處理。代碼Products/example/smart_outlet/device_state_manager.c文件中的key_detect_event_task函數負責按鍵處理。如下定義了各種行為的時間,如果需要調整各個行為的按鍵時長,可以自行修改。
    #define AWSS_REBOOT_TIMEOUT (4 * 1000) //長按4s 進入網絡配置模式,開始重新配網
    #define AWSS_RESET_TIMEOUT (6 * 1000) //長按6s 進入恢復出廠設置,(在設備已進入網絡配置模式下)
    #define KEY_PRESSED_VALID_TIME_MIN 100
    #define KEY_PRESSED_VALID_TIME_MAX 500 //按鍵按下超過100ms,小于500ms,表示有按鍵按下
    #define KEY_DETECT_INTERVAL 50 //按鍵按下的檢測時間間隔 50ms
    #define AWSS_REBOOT_CNT AWSS_REBOOT_TIMEOUT /KEY_DETECT_INTERVAL
    #define AWSS_RESET_CNT AWSS_RESET_TIMEOUT /KEY_DETECT_INTERVAL
    #define KEY_PRESSED_CNT KEY_PRESSED_VALID_TIME /KEY_DETECT_INTERVAL
    
    // 此函數處理插座按鍵檢測
    void key_detect_event_task(void *arg)
    {
        int nCount = 0, awss_mode = 0;
        int timeout = (AWSS_REBOOT_CNT < AWSS_RESET_TIMEOUT)? AWSS_REBOOT_CNT : AWSS_RESET_TIMEOUT;
    
        while (1) {
            if (!product_get_key()) {
                nCount++;
                LOG("nCount :%d", nCount);
            } else {
                if (nCount >= KEY_PRESSED_CNT && nCount < timeout) {  // 按鍵控制
                    if (product_get_switch() == ON) {   // 按鍵控制插座關閉繼電器
                        product_set_switch(OFF);
                        user_post_powerstate(OFF);
                    } else {                            // 按鍵控制插座打開繼電器
                        product_set_switch(ON);
                        user_post_powerstate(ON);
                    }
                }
                if ((awss_flag == 0) && (nCount >= AWSS_REBOOT_CNT)) {
                    LOG("do awss reboot");              // 長按4s 進入網絡配置模式,開始重新配網
                    do_awss_reboot();
                    break;
                } else if ((awss_flag == 1) && (nCount > AWSS_RESET_CNT)) {
                    LOG("do awss reset");               // 長按6s 進入恢復出廠設置
                    do_awss_reset();                    // 實際執行設備重置
                    break;
                }
                nCount = 0;
            }
            if ((awss_flag == 0) && (nCount >= AWSS_REBOOT_CNT && awss_mode == 0)) {
                set_net_state(RECONFIGED);              // 設置相應的設備狀態
                awss_mode = 1;
            } else if ((awss_flag == 1) && (nCount > AWSS_RESET_CNT && awss_mode == 0)) {
                set_net_state(UNCONFIGED);              // 設置相應的設備狀態
                awss_mode = 1;
            }
            aos_msleep(KEY_DETECT_INTERVAL);            // 檢測按鍵間隔為50ms
        }
        aos_task_exit(0);
    }
    • 短按:如果按鍵按下時長長于100ms,小于500ms, 認為用戶是進行按鍵開關。
    • 長按:如果用戶按下時間超過4s,認為用戶觸發設備進入網絡配置模式。如果用戶確認設備已經進入網絡配置模式,此時繼續按鍵6s,設備會進入恢復出廠模式。

設備端通用功能說明

以下功能在smart_outlet應用示例中已有相關實現,僅對設備端的通用功能做一些補充介紹。

  • 事件回調
    smart_outlet_main.c文件中定義了系統的各種事件處理函數,在linkkit_main函數中注冊了回調函數。
    int linkkit_main()
    {
        ...
        
        /* Register Callback */
        IOT_RegisterCallback(ITE_CONNECT_SUCC, user_connected_event_handler);
        IOT_RegisterCallback(ITE_DISCONNECTED, user_disconnected_event_handler);
        // IOT_RegisterCallback(ITE_RAWDATA_ARRIVED, user_down_raw_data_arrived_event_handler);
        IOT_RegisterCallback(ITE_SERVICE_REQUEST, user_service_request_event_handler);
        IOT_RegisterCallback(ITE_PROPERTY_SET, user_property_set_event_handler);
    #ifdef ALCS_ENABLED
        /*Only for local communication service(ALCS) */
        IOT_RegisterCallback(ITE_PROPERTY_GET, user_property_get_event_handler);
    #endif
        IOT_RegisterCallback(ITE_REPORT_REPLY, user_report_reply_event_handler);
        IOT_RegisterCallback(ITE_TRIGGER_EVENT_REPLY, user_trigger_event_reply_event_handler);
        IOT_RegisterCallback(ITE_INITIALIZE_COMPLETED, user_initialized);
        IOT_RegisterCallback(ITE_EVENT_NOTIFY, user_event_notify_handler);
        ...
    }
    事件事件觸發條件說明
    ITE_CONNECT_SUCC與云端連接成功時
    ITE_DISCONNECTED與云端連接斷開時
    ITE_RAWDATA_ARRIVEDSDK收到raw data數據時
    ITE_SERVICE_REQUESTSDK收到服務(同步/異步)調用請求時
    ITE_PROPERTY_SETSDK收到屬性設置請求時
    ITE_PROPERTY_GETSDK收到屬性獲取的請求時
    ITE_REPORT_REPLYSDK收到上報消息的應答時
    ITE_TRIGGER_EVENT_REPLYSDK收到事件上報消息的應答時
    ITE_EVENT_NOTIFYSDK收到事件通知時
    ITE_INITIALIZE_COMPLETED設備初始化完成時
  • 屬性上報
    產品的屬性發生變化時,需要將變化后的數值上報到物聯網平臺??梢愿鶕a品需求增加屬性變化的檢測以及上報邏輯。
    void user_post_property(property_report_msg_t * msg)
    {
        int res = 0;
        user_example_ctx_t *user_example_ctx = user_example_get_ctx();
        char *property_payload = NULL;
        cJSON *response_root = NULL, *item_csr = NULL;
    
        response_root = cJSON_CreateObject();
        if (response_root == NULL) {
            return;
        }
    
        if (msg->seq != NULL && strcmp(msg->seq, SPEC_SEQ)) {
            item_csr = cJSON_CreateObject();
            if (item_csr == NULL) {
                cJSON_Delete(response_root);
                return;
            }
            cJSON_AddStringToObject(item_csr, "seq", msg->seq);
            cJSON_AddItemToObject(response_root, "CommonServiceResponse", item_csr);
        }
    #ifdef TSL_FY_SUPPORT
        //兼容舊版本開關PowerSwitch屬性
        cJSON_AddNumberToObject(response_root, "PowerSwitch", msg->powerswitch);
    #endif
        //處理新版本物模型開關powerstate屬性
        cJSON_AddNumberToObject(response_root, "powerstate", msg->powerswitch);
        //處理新版物模型allPowerstate屬性
        cJSON_AddNumberToObject(response_root, "allPowerstate", msg->all_powerstate);
        property_payload = cJSON_PrintUnformatted(response_root);
        cJSON_Delete(response_root);
    
        char *property_formated;
        uint32_t len;
        res = user_property_format(property_payload,strlen(property_payload),&property_formated,&len);
    #ifdef EN_COMBO_NET //對于Wi-Fi&BLE Combo設備可以同時通過藍牙控制鏈路上報屬性值。
        if (combo_ble_conn_state()) {
            if (0 == res) {
                combo_status_report(property_formated, strlen(property_formated));
                LOG_TRACE("Post Property Message ID: %d Payload %s", res, property_formated);
            } else {
                combo_status_report(property_payload, strlen(property_payload));
                LOG_TRACE("Post Property Message ID: %d Payload %s", res, property_payload);
            }
        }
    #endif
        if (0 == res) {
            if (msg->seq != NULL && strcmp(msg->seq, SPEC_SEQ)) {
                res = IOT_Linkkit_Report_Ext(user_example_ctx->master_devid, ITM_MSG_POST_PROPERTY,
                        (unsigned char *)property_formated, strlen(property_formated), msg->flag);
            } else {
                res = IOT_Linkkit_Report(user_example_ctx->master_devid, ITM_MSG_POST_PROPERTY,
                        (unsigned char *)property_formated, strlen(property_formated));
            }
            LOG_TRACE("Post Property Message ID: %d Payload %s", res, property_formated);
            example_free(property_formated);
        } else {
            if (msg->seq != NULL && strcmp(msg->seq, SPEC_SEQ)) {
                res = IOT_Linkkit_Report_Ext(user_example_ctx->master_devid, ITM_MSG_POST_PROPERTY,
                        (unsigned char *)property_payload, strlen(property_payload), msg->flag);
            } else {
                res = IOT_Linkkit_Report(user_example_ctx->master_devid, ITM_MSG_POST_PROPERTY,
                        (unsigned char *)property_payload, strlen(property_payload));
            }
            LOG_TRACE("Post Property Message ID: %d Payload %s", res, property_payload);
        }
        example_free(property_payload);
    }
  • 屬性設置
    smart_outlet按對ITE_PROPERTY_SET注冊的回調函數,在回調函數user_property_set_event_handler中獲取云端設置的屬性值,并原樣將收到的數據發回給云端,這樣可以更新在云端的設備屬性值,用戶可在此處對收到的屬性值進行處理。
    static int user_property_set_event_handler(const int devid, const char *request, const int request_len)
    {
        ...
        property_setting_handle(request, request_len, &msg);
        ...
    }
    
    static int property_setting_handle(const char *request, const int request_len, recv_msg_t * msg)
    {
        ...
        if ((item = cJSON_GetObjectItem(root, "setPropsExtends")) != NULL && cJSON_IsObject(item)) {
            ...
        }
        if ((item = cJSON_GetObjectItem(root, "powerstate")) != NULL && cJSON_IsNumber(item)) {
            //設置powerstate屬性處理
            msg->powerswitch = item->valueint;
            msg->all_powerstate = msg->powerswitch;
            ret = 0;
        }
    #ifdef TSL_FY_SUPPORT /* 支持舊版本開關PowerSwitch屬性 */
        else if ((item = cJSON_GetObjectItem(root, "PowerSwitch")) != NULL && cJSON_IsNumber(item)) {
            msg->powerswitch = item->valueint;
            ret = 0;
        }
    #endif
        else if ((item = cJSON_GetObjectItem(root, "allPowerstate")) != NULL && cJSON_IsNumber(item)) {
            //設置allPowerstate屬性處理
            msg->powerswitch = item->valueint;
            msg->all_powerstate = msg->powerswitch;
            ret = 0;
        }
    #ifdef AOS_TIMER_SERVICE
        else if (((item = cJSON_GetObjectItem(root, "LocalTimer")) != NULL && cJSON_IsArray(item))|| \
            ((item = cJSON_GetObjectItem(root, "CountDownList")) != NULL && cJSON_IsObject(item)) || \
            ((item = cJSON_GetObjectItem(root, "PeriodTimer")) != NULL && cJSON_IsObject(item)) || \
            ((item = cJSON_GetObjectItem(root, "RandomTimer")) != NULL && cJSON_IsObject(item)))
        {
            // Timer service 定時、倒計時相關屬性設置的處理
            cJSON_Delete(root);         // Before LocalTimer Handle, Free Memory
            timer_service_property_set(request);
            user_example_ctx_t *user_example_ctx = user_example_get_ctx();
            IOT_Linkkit_Report(user_example_ctx->master_devid, ITM_MSG_POST_PROPERTY,
                    (unsigned char *)request, request_len);
            return 0;
        }
    #endif
        else {
            LOG_TRACE("property set payload is not JSON format");
            ret = -1;
        }
    
        cJSON_Delete(root);
        if (ret != -1)
            send_msg_to_queue(msg);
    
        return ret;
    }
  • 本地通信功能(目前僅云智能App支持)

    本地通信功能介紹,請參見本地通信開發實踐。

    本地通信功能在文件make.settings中通過宏ALCS_ENABLED來管理。使用IOT_RegisterCallback函數注冊ITE_PROPERTY_GET事件,對應回調函數實現為user_property_get_event_handler。此函數中目前已實現的本地通信請求的設備屬性如下所示,如果產品需要增加功能,可以相應的增加新屬性的處理case。
    #ifdef ALCS_ENABLED
    static int user_property_get_event_handler(const int devid, const char *request, const int request_len, char **response,
            int *response_len)
    {
        user_example_ctx_t *user_example_ctx = user_example_get_ctx();
        device_status_t *device_status = &user_example_ctx->status;
        cJSON *request_root = NULL, *item_propertyid = NULL;
        cJSON *response_root = NULL;
    
        ...
    
        for (int index = 0; index < cJSON_GetArraySize(request_root); index++) {
            item_propertyid = cJSON_GetArrayItem(request_root, index);
            ...
            LOG_TRACE("Property ID, index: %d, Value: %s", index, item_propertyid->valuestring);
            if (strcmp("powerstate", item_propertyid->valuestring) == 0) { 
                //處理新版物模型開關powerstate屬性
                cJSON_AddNumberToObject(response_root, "powerstate", device_status->powerswitch);
            }
            else if (strcmp("allPowerstate", item_propertyid->valuestring) == 0) {
                //處理新版物模型allPowerstate屬性
                cJSON_AddNumberToObject(response_root,"allPowerstate", device_status->all_powerstate);
            }
    #ifdef TSL_FY_SUPPORT /* support old feiyan TSL */
            else if (strcmp("PowerSwitch", item_propertyid->valuestring) == 0) {
                //兼容舊版本開關PowerSwitch屬性
                cJSON_AddNumberToObject(response_root, "PowerSwitch", device_status->powerswitch);
            }
    #endif
    #ifdef AOS_TIMER_SERVICE
            else if (strcmp("LocalTimer", item_propertyid->valuestring) == 0) {
                ...  //處理本地定時LocalTimer
            } else if (strcmp("CountDownList", item_propertyid->valuestring) == 0) {
                ...  //處理倒計時
    #endif
            }
        }
    
        ...
    }
    #endif
  • 云端解綁與恢復出廠默認設置通知
    設備被解綁后,云端會下發一個解綁事件通知{"identifier":"awss.BindNotify","value":{"Operation":"Unbind"}} 。設備收到此消息可以做重置配網、清空本地數據等處理。如果通過App將設備恢復出廠默認設置,云端會下發一個Reset事件通知{"identifier":"awss.BindNotify","value":{"Operation":"Reset"}} 。設備收到此消息可以做重置配網、清空本地數據等處理。您可以結合具體產品類型,決定收到解綁和恢復出廠默認設置通知后做哪些清空操作。更多介紹,請可以參見示例代碼example/smart_outlet/smart_outlet_main.c中的notify_msg_handle函數。
    static int notify_msg_handle(const char *request, const int request_len)
    {
        ....
        if (!strcmp(item->valuestring, "awss.BindNotify")) {
            cJSON *value = cJSON_GetObjectItem(request_root, "value");
            if (value == NULL || !cJSON_IsObject(value)) {
                cJSON_Delete(request_root);
                return -1;
            }
            cJSON *op = cJSON_GetObjectItem(value, "Operation");
            if (op != NULL && cJSON_IsString(op)) {
                if (!strcmp(op->valuestring, "Bind")) {     //綁定通知
                    LOG_TRACE("Device Bind");
                    vendor_device_bind();                   //設備綁定時需要完成的操作,設備應用可定義
                } else if (!strcmp(op->valuestring, "Unbind")) {    //解綁通知
                    LOG_TRACE("Device unBind");
                    vendor_device_unbind();                 //設備解綁時需要完成的操作,設備應用可定義
                } else if (!strcmp(op->valuestring, "Reset")) {     //重置通知
                    LOG_TRACE("Device reset");
                    vendor_device_reset();                  //設備重置時需要完成的操作,設備應用可定義
                }
            }
        }
        ....
    }
  • 藍牙輔助配網
    藍牙輔助配網設備端開發,請參見設備端開發。
    說明 SDK V1.6.6開始支持新的藍牙輔助配網方案(配合天貓精靈App V4.13.0以上版本與云智能App V3.5.5以上版本使用),新方案要求設備證書的Device Name與Wi-Fi MAC保持一致。更多介紹,請參見開發自有品牌項目插座產品開發天貓精靈生態項目插座產品。
  • 設備端上定時功能

    平臺統一使用設備端上定時(DeviceTimer)開發設備端定時功能,詳細操作,請參見開發設備端本地定時功能