このトピックでは、C-SDK 4.0 を ESP32 開発ボードに移植し、MQTT デモを使用して Alibaba Cloud IoT Platform に接続する方法について説明します。
このチュートリアルでは、以下の手順について説明します。
macOS または Linux で ESP-IDF 開発環境をセットアップします。
C-SDK 4.0 をカスタム ESP-IDF コンポーネントとして追加します。
デモエントリーファイルを置き換え、mbedTLS の競合を解決します。
-
ビルド、フラッシュを実行し、IoT Platform への MQTT 接続を確認します。
前提条件
開始する前に、以下のものが必要です。
ESP32 開発ボード (このチュートリアルでは、ESP-WROOM-32 モジュール、USB-シリアルモジュール CP2102、および電源モジュールを搭載した ESP32 Core Board V2/ESP32 DevKitC を使用します)。
USB ケーブル。
Linux または macOS が動作するコンピューター。
また、開始する前に IoT Platform の製品とデバイスを作成してください。
IoT Platform コンソールにログインし、製品を作成します。
-
製品にデバイスを作成し、ProductKey、DeviceName、および DeviceSecret を記録します。これらの認証情報は、ファームウェアをビルドする際に必要になります。
説明このチュートリアルでは、macOS を開発環境として使用します。別のオペレーティングシステムを使用する場合は、公式の ESP32 クイックスタートチュートリアルを参照して開発環境をセットアップしてください。
開発環境のセットアップ
説明このセクションは参考用です。問題が発生した場合は、開発ボードのサプライヤーにお問い合わせください。セットアップを迅速に行うには、Espressif の公式クイックスタートチュートリアルを参照してください。
-
必要なパッケージをインストールします。
macOS では、Homebrew を使用して
pip、ninja、およびcmakeをインストールします。詳細については、「macOS 用ツールチェーンの標準セットアップ」をご参照ください。Linux では、「Standard Setup of Toolchain for Linux」を参照してください。
-
esp-idfリポジトリをクローンします。このチュートリアルでは、release/v4.2 ブランチを使用します。他のバージョンでは互換性の問題が発生する可能性があります。
cd ~ mkdir esp && cd esp git clone --recursive -b release/v4.2 https://github.com/espressif/esp-idf.git -
ツールチェーンとビルドツールをインストールします。
cd esp-idf ./install.sh -
環境変数を設定します。
-
エクスポートスクリプトを実行します。
. $HOME/esp/esp-idf/export.sh -
このスクリプトを毎回実行しないようにするには、
$HOME/.bash_profileに次の関数を追加します。set_esp32 () { export IDF_PATH=$HOME/esp/esp-idf . $HOME/esp/esp-idf/export.sh }
-
-
Wi-Fi station サンプルを作業ディレクトリにコピーします。
cd ~/esp cp -r $IDF_PATH/examples/wifi/getting_started/station . -
開発ボードを接続します。
USB ドライバーをインストールします。詳細については、「Establish Serial Connection with ESP32」を参照してください。
USB ポート名を特定します。このチュートリアルでは、ポートは
/dev/cu.SLAB_USBtoUARTです。
-
プロジェクトを設定します。
idf.py menuconfigを実行し、デフォルト設定を使用します。 -
ビルド、フラッシュ、およびモニターを実行します。
station プロジェクトディレクトリで、
idf.py buildを実行してコンパイルします。コンパイルが完了したら、
idf.py -p PORT flashを実行してファームウェアをフラッシュします。PORT を実際の USB ポート名に置き換えます。ファームウェアの書き込み後、
idf.py -p PORT monitorを実行してシリアルポートモニターを開きます。また、
idf.py -p PORT flash monitorを実行して、1 つのコマンドで書き込みとモニタリングを行うこともできます。
ESP32 開発環境のセットアップが完了し、
wifi stationサンプルをコンパイルして実行できることを確認しました。以降のセクションでは、C-SDK 4.0 を移植して IoT Platform に接続する方法について説明します。
C-SDK 4.0 の移植
C-SDK 4.0 の移植には、SDK を idf コンポーネントとして追加すること、ESP32 に対応したポートファイルを置き換えること、および mbedTLS ライブラリの競合を解決することの 3 つのタスクが含まれます。
C-SDK の
portfilesディレクトリには ESP32 用のポートファイルがすでに含まれているため、移植の主な作業は SDK ソースコードのインポートとビルドシステムの設定になります。基本概念
背景については、ESP-IDF のビルドシステムの概要を参照してください。このチュートリアルでは、以下の 2 つの概念が中心となります。
[プロジェクト]:
appをビルドするためのソースファイルと設定ファイルを含むフォルダーです。[コンポーネント]:
.a静的ライブラリにコンパイルされ、appにリンクされる、再利用可能な自己完結型コードユニットです。カスタムコンポーネントは、idfのcomponentsディレクトリに配置されます。
ESP-IDF ビルドシステムは CMake と ninja を使用します。C-SDK を統合するには、そのソースコードを components ディレクトリに移動し、
CMakeLists.txtファイルを追加します。移植方法
方法 1: C-SDK を
projectディレクトリにインポートし、SDK ソースコードを他のappソースコードと一緒にコンパイルします。方法 2: C-SDK をカスタム idf コンポーネントとして
idfのcomponentsディレクトリにインポートします。
このチュートリアルでは、方法 2 を使用します。C-SDK を独立したコンポーネントとして使用することで、複数のプロジェクト間で再利用でき、アプリケーションコードから分離できます。
以下の表に、関連する C-SDK ディレクトリを示します。
ディレクトリ
内容
core/SDK のコアソースファイルとヘッダー
core/sysdep/システム依存関係の抽象化 (
core_adapter.cを含む)core/utils/ユーティリティ関数
portfiles/aiot_port/ESP32 に適合させた
posix_port.cを含む、プラットフォーム固有のポートファイルexternal/SDK にバンドルされているサードパーティライブラリ
移植手順
-
C-SDK をカスタムコンポーネントとして追加します。
C-SDK 4.0 をダウンロードして
$IDF_PATH/componentsにコピーします。 C-SDK のルートディレクトリに、次の内容のCMakeLists.txtファイルを作成します。set(include_dirs core core/sysdep core/utils) file(GLOB c_sdk_srcs "core/*.c" "core/utils/*.c" "core/sysdep/*.c" "portfiles/aiot_port/*.c" "external/*.c") idf_component_register(SRCS ${c_sdk_srcs} INCLUDE_DIRS "${include_dirs}" REQUIRES mbedtls)説明C-SDK は mbedTLS ライブラリに依存しており、このコンポーネントの依存関係は
REQUIRES mbedtlsで宣言されます。C-SDK には Kconfig 設定項目がありません。コンポーネント Kconfig のセットアップは不要です。
Thing Specification Language (TSL) モデルや Over-the-Air (OTA) アップデートなどの高度な SDK 機能を使用するには、対応するソースファイルとヘッダーファイルのパスをこの
CMakeLists.txtに追加します。
-
ポートファイルを置き換え、mbedTLS の競合を無効にします。
ESP32 用に調整された posix_port.c をダウンロードし、
$IDF_PATH/components/C-SDK/portfiles/aiot_port/posix_port.cをこのファイルで置き換えます。LinkSDK と ESP-IDF はどちらも mbedTLS ライブラリをバンドルしています。リンク時のシンボルの競合を避けるため、
$IDF_PATH/components/C-SDK/core/sysdep/core_adapter.cを開き、CORE_ADAPTER_MBEDTLS_ENABLEDマクロを無効にします。 -
デモエントリファイルを置き換えます。
station_example_main.c をダウンロードし、ステーションの例にある
station/main/station_example_main.cを置き換えます。説明wifi_init_sta()は、EXAMPLE_ESP_MAXIMUM_RETRYマクロで定義された上限に達するまで、Wi-Fi 接続を再試行します。Wi-Fi 接続が確立されると、デモは C-SDK API を呼び出して MQTT 接続を開きます。接続されると、デバイスは IoT Platform とデータを交換できます。
linkkit_main()には、元の C-SDK MQTT デモのロジックが含まれています。
-
ビルドとフラッシュを実行します。
プロジェクトディレクトリで
idf.py menuconfigを実行し、Example Configurationメニューを開きます。WiFi SSID、WiFi パスワード、および最大リトライ回数を設定し、保存して終了します。idf.py buildを実行してコンパイルします。コンパイルが成功したら、
idf.py -p /dev/cu.SLAB_USBtoUART flash monitorを実行してファームウェアを書き込み、シリアルポートモニターを開きます。
説明デバイスが事前共有キー (PSK) 鍵交換を使用する場合は、mbedTLS で PSK サポートを有効にし、最大 PSK 長を 64 に設定します。
idf.py menuconfigで、[コンポーネント設定] > [mbedTLS] >[TLS キー交換方式]の順に選択します。Enable pre-shared-key ciphersuitesを有効にします。mbedTLS コンポーネントの
CMakeLists.txtに、set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBEDTLS_PSK_MAX_LEN=64")を追加します。
-
接続を確認します。
接続が成功すると、以下のような出力が生成されます。
...... I (829) phy: phy_version: 4180, cb3948e, Sep 12 2019, 16:39:13, 0, 0 I (829) wifi: mode : sta (30:ae:a4:04:81:84) I (829) wifi station: wifi_init_sta finished. I (949) wifi: new:<11,0>, old:<1,0>, ap:<255,255>, sta:<11,0>, prof:1 I (949) wifi: state: init -> auth (b0) I (969) wifi: state: auth -> assoc (0) I (969) wifi: state: assoc -> run (10) I (1129) wifi: connected with C_SDK_Test, aid = 1, channel 11, BW20, bssid = ec:26:ca:4b:68:cc I (1129) wifi: security type: 3, phy: bgn, rssi: -37 I (1139) wifi: pm start, type: 1 I (1219) wifi: AP's beacon interval = 102400 us, DTIM period = 1 I (2129) esp_netif_handlers: sta ip: 192.168.0.100, mask: 255.255.255.0, gw: 192.168.0.1 I (2129) wifi station: got ip:192.168.0.100 I (2129) wifi station: connected to ap SSID:C_SDK_Test password:1234abcd I (2139) wifi station: Start linkkit mqtt [1.583][LK-0313] MQTT user calls aiot_mqtt_connect api, connect [1.587][LK-0317] mqtt_basic_demo&a13FN5TplKq [1.590][LK-0318] 4780A5F17990D8DC4CCAD392683ED80160C4C2A1FFA649425CD0E2666A8593EB [1.598][LK-0319] a13FN5TplKq.mqtt_basic_demo|timestamp=2524608000000,_ss=1,_v=sdk-c-4.0.0,securemode=2,signmethod=hmacsha256,ext=1,| establish mbedtls connection with server(host='a13FN5TplKq.iot-as-mqtt.cn-shanghai.aliyuncs.com', port=[443]) success to establish mbedtls connection, fd = 54(cost 29739 bytes in total, max used 44007 bytes) [3.493][LK-0313] MQTT connect success in 1910 ms AIOT_MQTTEVT_CONNECT [3.494][LK-0309] sub: /sys/a13FN5TplKq/mqtt_basic_demo/thing/event/+/post_reply [3.499][LK-0309] pub: /sys/a13FN5TplKq/mqtt_basic_demo/thing/event/property/post [LK-030A] > 7B 22 69 64 22 3A 22 31 22 2C 22 76 65 72 73 69 | {"id":"1","versi [LK-030A] > 6F 6E 22 3A 22 31 2E 30 22 2C 22 70 61 72 61 6D | on":"1.0","param [LK-030A] > 73 22 3A 7B 22 4C 69 67 68 74 53 77 69 74 63 68 | s":{"LightSwitch [LK-030A] > 22 3A 30 7D 7D | ":0}} suback, res: -0x0000, packet id: 1, max qos: 1 [3.573][LK-0309] pub: /sys/a13FN5TplKq/mqtt_basic_demo/thing/event/property/post_reply [LK-030A] < 7B 22 63 6F 64 65 22 3A 32 30 30 2C 22 64 61 74 | {"code":200,"dat [LK-030A] < 61 22 3A 7B 7D 2C 22 69 64 22 3A 22 31 22 2C 22 | a":{},"id":"1"," [LK-030A] < 6D 65 73 73 61 67 65 22 3A 22 73 75 63 63 65 73 | message":"succes [LK-030A] < 73 22 2C 22 6D 65 74 68 6F 64 22 3A 22 74 68 69 | s","method":"thi [LK-030A] < 6E 67 2E 65 76 65 6E 74 2E 70 72 6F 70 65 72 74 | ng.event.propert [LK-030A] < 79 2E 70 6F 73 74 22 2C 22 76 65 72 73 69 6F 6E | y.post","version [LK-030A] < 22 3A 22 31 2E 30 22 7D | ":"1.0"} pub, qos: 0, topic: /sys/a13FN5TplKq/mqtt_basic_demo/thing/event/property/post_reply pub, payload: {"code":200,"data":{},"id":"1","message":"success","method":"thing.event.property.post","version":"1.0"} heartbeat response heartbeat response heartbeat response ......出力で
MQTT connect successとAIOT_MQTTEVT_CONNECTを探してください。heartbeat responseの行が繰り返し表示される場合は、MQTT 接続が維持されていることを示します。重要aiot_mqtt_connect failed: -0x0F0Fエラーが表示された場合は、ネットワーク接続に問題があります。Wi-Fi ネットワークの状態を確認し、ボードがアクセスポイントの通信範囲内にあることを確認してください。必要に応じて、ファームウェアを再フラッシュして再試行してください。エラーコード
-0x0F0FはSTATE_PORT_NETWORK_CONNECT_TIMEOUTに対応しており、接続試行がタイムアウトしたことを示します。
トラブルシューティング
MQTT 接続が aiot_mqtt_connect failed: -0x0F0F エラーで失敗する
エラーコード -0x0F0F は STATE_PORT_NETWORK_CONNECT_TIMEOUT にマッピングされます。これは、ボードがタイムアウト期間内に IoT Platform サーバーに到達できなかったことを意味します。以下を確認してください。
ボードが Wi-Fi 信号範囲内にあり、正しい SSID に接続されていることを確認してください。
idf.py menuconfigで入力した [WiFi SSID] と [WiFi パスワード] の値を確認してください。問題が解決しない場合は、ファームウェアを再フラッシュして再試行してください。
mbedTLS シンボルの重複によりビルドが失敗する
LinkSDK と ESP-IDF の両方には mbedTLS が含まれています。 重複シンボルによるリンカーエラーが発生した場合は、移植手順のステップ 2 に従って、core_adapter.c の CORE_ADAPTER_MBEDTLS_ENABLED を無効にしてください。
フラッシュ後にデバイスが継続的にリセットされる
再フラッシュする前に、フラッシュを消去してみてください。
idf.py -p PORT erase_flash
idf.py -p PORT flash monitor
macOS でシリアルポートが認識されない
CP2102 USB ドライバーがインストールされていることを確認してください。ドライバーのインストール手順については、Establish Serial Connection with ESP32 を参照してください。