Link SDK支持跨平臺跨系統運行,默認支持Linux(POSIX接口)設備,其它環境的設備都需要移植。無操作系統的設備資源較少,移植難度較大。本文介紹無操作系統的單片機設備,使用C Link SDK接入物聯網平臺的流程和示例。
前提條件
步驟一:接口移植
無操作系統設備可以理解為只有一個任務或線程,該任務的棧大小需要足夠支撐SDK運行。
實現Link SDK運行依賴的底層接口后,設備才可以正常運行,下文介紹不同接口實現方案。
接口類型 | 接口列表 | 實現方案 |
內存管理 | core_sysdep_malloc |
|
core_sysdep_free | ||
系統時間 | core_sysdep_time | 建議使用單片機的系統嘀嗒實現,獲取系統運行時間,單位:ms。 |
系統睡眠 | core_sysdep_sleep | 裸單片機環境沒有睡眠接口,也不會存在多任務并發處理,所以不用讓出MCU的運行權限,可以使用輪詢的方式模擬睡眠。 |
隨機值 | core_sysdep_rand | 以系統時間為隨機因子,使用 |
互斥鎖 | core_sysdep_mutex_init |
|
core_sysdep_mutex_lock | ||
core_sysdep_mutex_unlock | ||
core_sysdep_mutex_deinit | ||
網絡連接 | core_sysdep_network_*** | 阻塞式接口,有、無操作系統實現相同。 |
步驟二:應用開發
對于有操作系統的設備,應用開發建議多任務處理,因為接口會阻塞,單任務處理會影響其他的業務處理。但對于無操作系統設備,只有一個任務,解決Link SDK接口阻塞的方案是降低阻塞的時間,盡量不影響業務的處理流程。
MQTT模塊涉及到阻塞的接口
接口類 | 接口名 | 說明 |
MQTT建連 | aiot_mqtt_connect | 執行建連會阻塞,通過設置建連和接收超時處理,示例值:2s。 |
MQTT接收 | aiot_mqtt_recv | 執行MQTT的消息接收、回調執行、心跳超時重連會阻塞,通過設置網絡接收超時處理,示例值:1s。 |
MQTT處理 | aiot_mqtt_process | 執行MQTT的心跳、QoS 1消息會阻塞。 |
配置超時時間
/* 配置MQTT超時時間 */
int32_t recv_timeout = 1000, connect_timeout = 2000;
aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_RECV_TIMEOUT_MS, (void *)&recv_timeout);
aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_CONNECT_TIMEOUT_MS, (void *)&connect_timeout);
示例
環境說明
環境配置 | 說明 |
操作系統 | 無。 |
硬件設備 | STM32L476 + 移遠EC200S模組。 |
接口連接 | STM32串口1連接模組串口,串口波特率為115200。 |
開發環境 | |
參數配置 | 堆大小為80 KB、棧大小為1.5 KB。 |
移植實現示例
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "os_net_interface.h"
#include "stm32l4xx_hal.h"
/**
* @brief 獲取當前的時間戳,SDK用于差值計算
*/
uint64_t __time(void) {
return (uint64_t)HAL_GetTick();
}
/**
* @brief 睡眠指定的毫秒數
*/
void __sleep(uint64_t time_ms) {
uint64_t start = __time();
while(__time() - start < time_ms) {
;
}
}
/**
* @brief 隨機數生成方法
*/
void __rand(uint8_t *output, uint32_t output_len) {
uint32_t idx = 0, bytes = 0, rand_num = 0;
srand(__time());
for (idx = 0; idx < output_len;) {
if (output_len - idx < 4) {
bytes = output_len - idx;
} else {
bytes = 4;
}
rand_num = rand();
while (bytes-- > 0) {
output[idx++] = (uint8_t)(rand_num >> bytes * 8);
}
}
}
/**
* @brief 創建互斥鎖
*/
void* __mutex_init(void) {
return (void *)0xFFFFFFFF;
}
/**
* @brief 申請互斥鎖
*/
void __mutex_lock(void *mutex) {
}
/**
* @brief 釋放互斥鎖
*/
void __mutex_unlock(void *mutex) {
}
/**
* @brief 銷毀互斥鎖
*/
void __mutex_deinit(void **mutex) {
if (mutex == NULL || *mutex == NULL) {
return;
}
*mutex = NULL;
}
aiot_os_al_t g_aiot_freertos_api = {
.malloc = malloc,
.free = free,
.time = __time,
.sleep = __sleep,
.rand = __rand,
.mutex_init = __mutex_init,
.mutex_lock = __mutex_lock,
.mutex_unlock = __mutex_unlock,
.mutex_deinit = __mutex_deinit,
};
示例工程
使用MDK-Arm,打開工程
./LinkSDK/portfiles/aiot_port/project/stm32_noneos/MDK-ARM/L476.uvprojx
。MDK-Arm的使用說明,請參見MDK-Arm。
如果需要適配不同環境接口,修改文件
./LinkSDK/portfiles/aiot-port/project/stm32_noneos/Core/os_none_impl.c
。修改方法,請參見步驟一:接口移植。
打開
./LinkSDK/portfiles/aiot-port/project/stm32_noneos/Core/mqtt_at_basic_demo.c
,配置設備認證信息。參數
示例
說明
product_key
a18wP******
設備認證信息。開發準備時,您獲取的設備證書。
您也可以在物聯網平臺控制臺的設備詳情頁面查看設備的認證信息。
device_name
LightSwitch
device_secret
uwMTmVA**********DY6cHxxB******
mqtt_host
a18wP******.iot-as-mqtt.cn-shanghai.aliyuncs.com
設備的MQTT接入域名。
新舊版公共實例和企業版實例的接入域名信息,請參見查看實例終端節點。
編譯工程文件,然后下載可執行文件到開發板運行。
成功運行后,您可以在設備端查看日志。
模組初始化:
>>> AT >>> AT <<< RDY >>> AT <<< AT OK >>> AT+QIACT=1 <<< OK >>> AT+QIACT? <<< +QIACT: 1,1,1,"10.13.***.***" OK
建立連接:
[22.400][LK-0313] MQTT user calls aiot_mqtt_connect api, connect [22.433][LK-0317] LightSwitch&a18wP****** [22.444][LK-0318] B4C45425D73E24B2935D73C1E98B6079A630FBE03F61E2A2031CEE7867D4D0D7 >>> AT+QIOPEN=1,1,"TCP","a18wP******.iot-as-mqtt.cn-shanghai.aliyuncs.com",443,0,1 <<< OK <<< +QIOPEN: 1,0 >>> AT+QISEND=1,286 <<< > >>> <<< SEND OK <<< +QIURC: "recv",1,4 id 0, len 4, res 20 [22.744][LK-0313] MQTT connect success in 341 ms AIOT_MQTTEVT_CONNECT
數據上報:
[27.766][LK-0309] pub: /sys/a18wP******/LightSwitch/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}} >>> AT+QISEND=1,120 <<< > >>> 0v<<< SEND OK <<< +QIURC: "recv",1,178 0?id 0, len 178, res 22
數據接收:
[27.933][LK-0309] pub: /sys/a18wP******/LightSwitch/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/a18wP******/LightSwitch/thing/event/property/post_reply
- 您也可以在物聯網平臺查看日志,具體操作,請參見云端運行日志。