This topic describes how to port C-SDK 4.0 to an ESP32 development board and use the MQTT demo to connect to Alibaba Cloud IoT Platform.
This tutorial covers the following steps:
Set up the ESP-IDF development environment on macOS or Linux.
Add C-SDK 4.0 as a custom ESP-IDF component.
Replace the demo entry file and resolve the mbedTLS conflict.
-
Compile, flash, and verify the MQTT connection to IoT Platform.
Prerequisites
Before you begin, make sure you have:
An ESP32 development board (this tutorial uses an ESP32 Core Board V2/ESP32 DevKitC with an onboard ESP-WROOM-32 module, a USB-to-serial module CP2102, and a power module).
A USB cable.
A computer running Linux or macOS.
Also create an IoT Platform product and device before you start:
Log in to the IoT Platform console and create a product.
-
Create a device under the product and record the ProductKey, DeviceName, and DeviceSecret. You need these credentials when compiling the firmware.
NoteThis tutorial uses macOS as the development environment. If you use a different operating system, see the official ESP32 getting started tutorial to set up your development environment.
Set up the development environment
NoteThis section is for reference only. If you run into issues, contact your development board supplier for help. To speed up the setup process, see the Espressif official getting started tutorial.
-
Install the required packages.
On macOS, use Homebrew to install
pip,ninja, andcmake. See Standard Setup of Toolchain for Mac OS for details.On Linux, see Standard Setup of Toolchain for Linux.
-
Clone the
esp-idfrepository.This tutorial uses the release/v4.2 branch. Other versions may cause compatibility issues.
cd ~ mkdir esp && cd esp git clone --recursive -b release/v4.2 https://github.com/espressif/esp-idf.git -
Install the toolchain and compilation tools.
cd esp-idf ./install.sh -
Configure environment variables.
-
Run the export script:
. $HOME/esp/esp-idf/export.sh -
To avoid running this script every time, add the following function to
$HOME/.bash_profile:set_esp32 () { export IDF_PATH=$HOME/esp/esp-idf . $HOME/esp/esp-idf/export.sh }
-
-
Copy the Wi-Fi station example to a working directory.
cd ~/esp cp -r $IDF_PATH/examples/wifi/getting_started/station . -
Connect the development board.
Install the USB driver. See Establish Serial Connection with ESP32 for details.
Identify the USB port name. In this tutorial, the port is
/dev/cu.SLAB_USBtoUART.
-
Configure the project.
Run
idf.py menuconfigand use the default configuration. -
Build, flash, and monitor.
In the station project directory, run
idf.py buildto compile.After the compilation is complete, run
idf.py -p PORT flashto flash the firmware. Replace PORT with your actual USB port name.After the firmware is flashed, run
idf.py -p PORT monitorto open the serial port monitor.You can also run
idf.py -p PORT flash monitorto flash and monitor in one command.
The ESP32 development environment is now set up, and you have verified that the
wifi stationexample compiles and runs. The following sections cover how to port C-SDK 4.0 and connect to IoT Platform.
Port C-SDK 4.0
Porting C-SDK 4.0 involves three tasks: adding the SDK as an idf component, replacing the port file adapted for ESP32, and resolving the mbedTLS library conflict.
The
portfilesdirectory in the C-SDK already contains the port file for ESP32, so porting primarily means importing the SDK source code and configuring the build system.Key concepts
Read the ESP-IDF build system introduction for background. Two concepts are central to this tutorial:
project: The folder containing source files and configuration files for building the
app.components: Reusable, self-contained code units compiled into
.astatic libraries and linked to theapp. Custom components go in thecomponentsdirectory ofidf.
The ESP-IDF build system uses CMake and ninja. To integrate C-SDK, move its source code into the components directory and add a
CMakeLists.txtfile.Porting methods
Method 1: Import the C-SDK into the
projectdirectory. Compile the SDK source code together with your otherappsource code.Method 2: Import the C-SDK as a custom idf component into the
componentsdirectory ofidf.
This tutorial uses Method 2. Using the C-SDK as an independent component helps you reuse it across multiple projects and keeps it decoupled from your application code.
The following table shows the relevant C-SDK directories:
Directory
Contents
core/Core SDK source files and headers
core/sysdep/System dependency abstractions (includes
core_adapter.c)core/utils/Utility functions
portfiles/aiot_port/Platform-specific port files, including the ESP32-adapted
posix_port.cexternal/Third-party libraries bundled with the SDK
Porting procedure
-
Add C-SDK as a custom component.
Download C-SDK 4.0 and copy it to
$IDF_PATH/components. In the C-SDK root directory, create aCMakeLists.txtfile with the following content: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)NoteC-SDK depends on the mbedTLS library.
REQUIRES mbedtlsdeclares this component dependency.C-SDK has no Kconfig configuration items. No component Kconfig setup is needed.
To use advanced SDK features such as the Thing Specification Language (TSL) model or Over-the-Air (OTA) updates, add the corresponding source and header file paths to this
CMakeLists.txt.
-
Replace the port file and disable the mbedTLS conflict.
Download posix_port.c, which has been adapted for ESP32. Replace
$IDF_PATH/components/C-SDK/portfiles/aiot_port/posix_port.cwith this file.Both LinkSDK and ESP-IDF bundle the mbedTLS library. To avoid symbol conflicts at link time, open
$IDF_PATH/components/C-SDK/core/sysdep/core_adapter.cand disable theCORE_ADAPTER_MBEDTLS_ENABLEDmacro. -
Replace the demo entry file.
Download station_example_main.c and replace
station/main/station_example_main.cin your station example.Notewifi_init_sta()retries the Wi-Fi connection until it reaches the limit defined by theEXAMPLE_ESP_MAXIMUM_RETRYmacro.After the Wi-Fi connection is established, the demo calls the C-SDK API to open an MQTT connection. Once connected, the device can exchange data with IoT Platform.
linkkit_main()contains the original C-SDK MQTT demo logic.
-
Compile and flash.
In the project directory, run
idf.py menuconfigand open theExample Configurationmenu.Set
WiFi SSID,WiFi Password, andMaximum retry, then save and exit.Run
idf.py buildto compile.After the compilation is successful, run
idf.py -p /dev/cu.SLAB_USBtoUART flash monitorto flash the firmware and open the serial port monitor.
NoteIf the device uses Pre-Shared Key (PSK) key exchange, enable PSK support in mbedTLS and set the maximum PSK length to 64:
In
idf.py menuconfig, go to Component config > mbedTLS >TLS Key Exchange Methods.Enable
Enable pre-shared-key ciphersuites.In the
CMakeLists.txtof the mbedTLS component, addset(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBEDTLS_PSK_MAX_LEN=64").
-
Verify the connection.
A successful connection produces output similar to the following:
...... 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&a13FNXXXXXX [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/a13FNXXXXXX/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 ......Look for
MQTT connect successandAIOT_MQTTEVT_CONNECTin the output. Recurringheartbeat responselines confirm that the MQTT connection is maintained.ImportantIf you see the
aiot_mqtt_connect failed: -0x0F0Ferror, this is a network connectivity issue. Check your Wi-Fi network status and make sure the board is within range of the access point. If necessary, reflash the firmware and retry.The error code
-0x0F0Fcorresponds toSTATE_PORT_NETWORK_CONNECT_TIMEOUT, indicating that the connection attempt timed out.
Troubleshooting
MQTT connection fails with aiot_mqtt_connect failed: -0x0F0F
The error code -0x0F0F maps to STATE_PORT_NETWORK_CONNECT_TIMEOUT, which means the board could not reach the IoT Platform server within the timeout period. Check the following:
Confirm the board is within Wi-Fi signal range and connected to the correct SSID.
Verify the WiFi SSID and WiFi Password values you entered in
idf.py menuconfig.If the problem persists, reflash the firmware and retry.
Build fails with duplicate mbedTLS symbols
Both LinkSDK and ESP-IDF include mbedTLS. If you see linker errors about duplicate symbols, make sure you have disabled CORE_ADAPTER_MBEDTLS_ENABLED in core_adapter.c as described in step 2 of the porting procedure.
Device resets continuously after flashing
Try erasing the flash before reflashing:
idf.py -p PORT erase_flash
idf.py -p PORT flash monitor
Serial port not recognized on macOS
Make sure the CP2102 USB driver is installed. See Establish Serial Connection with ESP32 for driver installation instructions.