ESP32接入騰訊雲物聯網開發平臺

前言

這篇筆記記錄採用 ESP32 接入騰訊雲物聯網開發平臺的流程,同時給出了我的移植示例,方便其他想接入騰訊雲物聯網的朋友。

畢竟騰訊雲IoT現在是免費的,而且還有騰訊連連小程序加持,真香是肯定的。

先說下哈,問過騰訊雲的朋友,ESP32接入騰訊雲物聯網開發平臺的例程正在處理,預計後面會發布到 github 上。所以我這篇筆記只是小能手的試水,因爲最近正在玩 ESP_Moonlight 開發板,想要做個小玩具玩玩,因此着急着先摸索出來了。後續當然建議是以騰訊雲官方文檔爲主。

如果你還沒看到官方文檔,又急着玩,不妨看看我這篇筆記,也能加深下對ESP32開發的瞭解。

小能手在時隔4年後,再次玩起了樂鑫芯片,這次是帶語音識別功能的ESP32。目前基於 ESP-Moonlight 開發板記錄一系列筆記,詳情請點擊

1 資料參考

目力所及的資料有兩個,一個是騰訊雲的,一個是樂鑫的,兩家在19年有過合作。

首先是騰訊雲的資料,Wi-Fi 智能燈接入指引,雖然demo是使用AT命令的模組,不過追進去,還是發現了非模組的版本:
https://github.com/tencentyun/qcloud-iot-esp-wifi/tree/master/qcloud-iot-esp8266-demo

名稱 說明
qcloud-iot-at-esp8266 騰訊雲IoT AT指令ESP8266定製固件、說明及使用
qcloud-iot-esp8266-demo 騰訊雲IoT C-SDK 在ESP8266 RTOS SDK上的移植及demo和配網代碼

樂鑫也根據騰訊雲的CSDK,寫了一個對接的工程,不過目前有點舊了,移植的CSDK也是老的版本:https://github.com/espressif/esp-qcloud,另外看了代碼只支持 cert 方式,比較有侷限性。

2 對接總體思路

所以我的對接思路是以騰訊雲的 ESP SDK 爲主,應該更容易對接到騰訊雲。

對接的主要困難是在編譯系統這塊,騰訊雲的 qcloud-iot-esp8266-demo 仍採用 GNU Make,而我手頭的 ESP-Moonlight 都是基於 ESP-IDF V4.0 了,編譯系統採用的是 CMake。這塊一些文件需要自己處理下。

目前總體代碼也已上傳:https://github.com/twowinter/esp-moonlight/

3 代碼移植

3.1 component qcloud_iot

複製 component 目錄

將 騰訊雲SDK中的 component 複製至 本項目的 component 目錄,具體見 esp-moonlight/components/qcloud_iot

CMakeLists.txt

參考了樂鑫的文檔,這裏頭有CMake的參考,https://github.com/espressif/esp-qcloud/blob/master/CMakeLists.txt

set(COMPONENT_ADD_INCLUDEDIRS 
    "qcloud_iot_c_sdk/include"
    "qcloud_iot_c_sdk/include/exports"
	"qcloud_iot_c_sdk/sdk_src/internal_inc"
    )

# Edit following two lines to set component requirements (see docs)
set(COMPONENT_REQUIRES "mbedtls")
set(COMPONENT_PRIV_REQUIRES )

set(COMPONENT_SRCS
    "qcloud_iot_c_sdk/sdk_src"
    "qcloud_iot_c_sdk/platform"
    )

register_component()

3.2 項目頂層處理

項目頂層目錄位於 esp-moonlight/examples/qcloud_sr,主要是修改 CMake 文件和配置文件。

CMakeLists.txt
裏面記得增加新加的 component qcloud_iot。

set(EXTRA_COMPONENT_DIRS 
    ${CMAKE_CURRENT_SOURCE_DIR}/../../components/moonlight_board
    ${CMAKE_CURRENT_SOURCE_DIR}/../../components/led_rgb
    ${CMAKE_CURRENT_SOURCE_DIR}/../../components/speech_recognition
    ${CMAKE_CURRENT_SOURCE_DIR}/../../components/button
    ${CMAKE_CURRENT_SOURCE_DIR}/../../components/qcloud_iot
    )

複製 項目 配置

#
# QCloud IoT demo Configuration
#
CONFIG_QCLOUD_IOT_EXPLORER_ENABLED=y
CONFIG_SMART_LIGHT_ENABLED=y
CONFIG_GATEWAY_ENABLED=
CONFIG_OTA_ENABLED=
CONFIG_RAW_DATA_ENABLED=
CONFIG_MQTT_ENABLED=
CONFIG_DEMO_EXAMPLE_SELECT=0
CONFIG_WIFI_CONFIG_ENABLED=y
CONFIG_DEMO_WIFI_SSID="Your_WiFi"
CONFIG_DEMO_WIFI_PASSWORD="12345678"

3.3 component main

component main 組件的調整也是兩個文件,CMake 文件和配置文件。

CMakeLists.txt

idf_component_register(SRC_DIRS "./" "samples/data_template_light"
                       INCLUDE_DIRS "./" "include"
                       )

配置菜單修改

qcloud-iot-esp-wifi/qcloud-iot-esp8266-demo/main/Kconfig.projbuild

裏頭涉及對 騰訊雲DEMO 的參數配置菜單,需要移植過來。

4 移植問題備忘

移植過程中有兩個典型問題,我這邊做個記錄。

CMakeLists.txt 的定義語法

對編譯系統不熟,導致兩次掉入這個坑裏。

在指定原文件的時候,之前我採用 SRCS,應該是看某些文件裏既可以指定文件,也可以指定目錄,給我造成了誤導。反正最新的CMake編譯系統,原文件僅使用 SRCS,而如果是目錄的話,就得使用 SRC_DIRS。

In the legacy Make-based build system, it is required to also set COMPONENT_SRCDIRS if COMPONENT_SRCS is set. In CMake, the equivalent is not necessary i.e. specifying SRC_DIRS to idf_component_register if SRCS is also specified (in fact, SRCS is ignored if SRC_DIRS is specified).

而且這裏要注意,如果使用 SRC_DIRS 那麼 SRCS 就會被忽略。

component qcloud_iot 處理:

set(src_dirs 
    "qcloud_iot_c_sdk/sdk_src"
    "qcloud_iot_c_sdk/platform"
    )

set(include_dirs 
    "qcloud_iot_c_sdk/include"
    "qcloud_iot_c_sdk/include/exports"
	"qcloud_iot_c_sdk/sdk_src/internal_inc"
    )

idf_component_register(SRC_DIRS "${src_dirs}"
                       INCLUDE_DIRS "${include_dirs}"
                       REQUIRES mbedtls
                       )

component main 處理:

idf_component_register(SRC_DIRS "./" "samples/data_template_light"
                       INCLUDE_DIRS "./" "include"
                       )

mbedtls_ssl_conf_psk 編譯錯誤

/Users/tt/esp/esp-moonlight/components/qcloud_iot/qcloud_iot_c_sdk/platform/HAL_TLS_mbedtls.c: In function '_mbedtls_client_init':
/Users/tt/esp/esp-moonlight/components/qcloud_iot/qcloud_iot_c_sdk/platform/HAL_TLS_mbedtls.c:153:15: error: implicit declaration of function 'mbedtls_ssl_conf_psk'; did you mean 'mbedtls_ssl_conf_sni'? [-Werror=implicit-function-declaration]
         ret = mbedtls_ssl_conf_psk(&(pDataParams->ssl_conf), (unsigned char *)pConnectParams->psk, pConnectParams->psk_length,
               ^~~~~~~~~~~~~~~~~~~~
               mbedtls_ssl_conf_sni
cc1: some warnings being treated as errors

通過代碼發現是相關的配置項需要啓用。

#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf,
                const unsigned char *psk, size_t psk_len,
                const unsigned char *psk_identity, size_t psk_identity_len )

/* Key exchanges using a PSK */
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)           || \
    defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)       || \
    defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)       || \
    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
#define MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED
#endif

這是最終在項目配置中需要使能的參數。
CONFIG_MBEDTLS_PSK_MODES=y

5 騰訊雲物聯網開發平臺操作

一旦SDK搞定,剩下的事情就好解決了。

5.1 騰訊雲物聯網開發平臺創建WiFi產品

具體見 Wi-Fi 智能燈接入指引

5.2 代碼中修改設備三元組信息

到 components/qcloud_iot/qcloud_iot_c_sdk/platform/HAL_Device_freertos.c 裏面修改在騰訊雲物聯網平臺註冊的設備信息(目前僅支持密鑰設備):

/* Product Id */
static char sg_product_id[MAX_SIZE_OF_PRODUCT_ID + 1]    = "PRODUCT_ID";
/* Device Name */
static char sg_device_name[MAX_SIZE_OF_DEVICE_NAME + 1]  = "YOUR_DEV_NAME";
/* Device Secret */
static char sg_device_secret[MAX_SIZE_OF_DEVICE_SECRET + 1] = "YOUR_IOT_PSK";

5.3 配置添加 WiFi SSID 和 密碼

圖省事,先不折騰配網了,直接 idf.py menuconfig 來配置。

5.4 ESP32 編譯、燒寫、monitor

常規操作,忽略不表。

6 最終結果

最終可以在騰訊雲 IoT Explorer 上看到設備的屬性更新。

看代碼描述,這個示例應該是每10秒上傳一次亮度。

/*example for cycle report, you can delete this for your needs*/
static void cycle_report(Timer *reportTimer)
{
    int i;

    if (expired(reportTimer)) {
        for (i = 0; i < TOTAL_PROPERTY_COUNT; i++) {
            DeviceProperty *pReportData = &(sg_DataTemplate[i].data_property);
            /* simulate brightness changes */
            if (0 == strcmp(pReportData->key, "brightness")) {
                int *brightness = (int *)pReportData->data;
                *brightness += 5;
                if (*brightness > 100)
                    *brightness = 0;

                set_propery_state(pReportData->data, eCHANGED);
            } else {
                set_propery_state(&(sg_DataTemplate[i].data_property.data), eCHANGED);
            }

            countdown_ms(reportTimer, 10000);
        }
    }
}

END

That’s all


IoT小能手的其他精彩文章:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章