mqttclient
一個高性能、高穩定性的跨平臺MQTT客戶端
一個高性能、高穩定性的跨平臺MQTT客戶端,基於socket API之上開發,可以在嵌入式設備(FreeRTOS/LiteOS/RT-Thread/TencentOS tiny)、Linux、Windows、Mac上使用,擁有非常簡潔的API接口,以極少的資源實現QOS2的服務質量,並且無縫銜接了mbedtls加密庫。開源地址:https://github.com/jiejieTop/mqttclient
開發平臺說明
本次使用野火官方開發板——STM32F429挑戰者開發板作爲移植實驗,使用lwip+以太網連接到雲平臺。
本次實驗需要使用到freertos操作系統,大家對於freertos操作系統的移植不會的話,
可以看我之前的操作系統博客專欄——https://blog.csdn.net/jiejiemcu/category_7707185.html。
而對於lwip不理解的同學,可以看我的博客專欄,專門寫lwip網絡協議棧的——https://blog.csdn.net/jiejiemcu/category_8634585.html
獲取到野火的lwip例程
大家可以通過野火官方資料去獲取到野火的lwip例程,比如我獲取的一個例程目錄如下,用這個例程作爲移植mqttclient的工程。
開始移植mqttclient
-
添加mqttclient源碼相關的文件,大家可以將下載的mqttclient直接拷貝到工程的根目錄下:在工程根目錄下創建一個mqttclient文件夾,然後將整個mqttclient的倉庫拷貝到這個新建的文件夾下,將mqttclient/test/mqtt_config.h拷貝到User目錄下。
-
刪除掉其他平臺層的文件:在mqttclient\platform與mqttclient\common\log\arch目錄下刪除其他無關的平臺層,當然刪不刪無所謂,只是刪除了工程沒有那麼大一點而已。
-
打開工程,在工程中創建分組:mqttclient、mqttclient/mqtt、mqttclient/salof、mqttclient/common、mqttclient/network、mqttclient/platform、mqttclient/config。
-
簡單介紹mqttclient倉庫文件夾
-
common文件夾:是一些通用的文件內容,比如鏈表的處理,錯誤代碼的處理、隨機數生成器、日誌庫等內容。
-
mqtt文件夾:著名的paho mqtt庫。
-
mqttclient文件夾:實現mqttclient的主要文件,並且包含了一個默認的配置文件。
-
network文件夾:網絡抽象層,封裝了mbedtls加密庫、網絡數據的通道類型,自動選擇tls加密傳輸或者是tcp直連。
-
platform文件夾:平臺抽象層,此處封裝了各種平臺的內存管理、互斥鎖、線程管理、時間管理等內容,如linux平臺,freertos平臺、rt-thread平臺、TencentOS tiny平臺等。
-
test文件夾:主要是一些測試例程與相應的配置頭文件,如mqtt_config.h。
-
-
添加對應的文件,根據工程分組的目錄進行添加即可,因爲這些目錄與工程分組的目錄是一樣的,爲工程分組添加完畢的源文件如下(此處不使用mbedtls加密):
-
修改mqtt_cofig.h配置文件,由於不使用mbedtls加密,所以需要打開指定MQTT_NETWORK_TYPE_NO_TLS宏定義,同時註釋MQTT_LOG_IS_SALOF宏定義不使用同步異步日誌庫,或者將宏SALOF_OS定義爲SALOF_USING_FREERTOS,表示使用freertos平臺。
-
在工程中添加mqttclient的頭文件路徑:
-
編寫main.c文件的代碼,測試代碼如下:
#include "main.h" /* FreeRTOS頭文件 */ #include "FreeRTOS.h" #include "task.h" #include "mqttclient.h" //#define TEST_USEING_TLS extern const char *test_ca_get(void); static TaskHandle_t app_task_create_handle = NULL;/* 創建任務句柄 */ static TaskHandle_t mqtt_task_handle = NULL;/* LED任務句柄 */ static void app_task_create(void);/* 用於創建任務 */ static void mqtt_task(void* pvParameters);/* mqtt_task任務實現 */ extern void TCPIP_Init(void); /***************************************************************** * @brief 主函數 * @param 無 * @retval 無 * @note 第一步:開發板硬件初始化 第二步:創建APP應用任務 第三步:啓動FreeRTOS,開始多任務調度 ****************************************************************/ int main(void) { BaseType_t xReturn = pdPASS;/* 定義一個創建信息返回值,默認爲pdPASS */ /* 開發板硬件初始化 */ BSP_Init(); /* 創建app_task_create任務 */ xReturn = xTaskCreate((TaskFunction_t )app_task_create, /* 任務入口函數 */ (const char* )"app_task_create",/* 任務名字 */ (uint16_t )2048, /* 任務棧大小 */ (void* )NULL,/* 任務入口函數參數 */ (UBaseType_t )10, /* 任務的優先級 */ (TaskHandle_t* )&app_task_create_handle);/* 任務控制塊指針 */ /* 啓動任務調度 */ if(pdPASS == xReturn) vTaskStartScheduler(); /* 啓動任務,開啓調度 */ else return -1; while(1); /* 正常不會執行到這裏 */ } /*********************************************************************** * @ 函數名 : app_task_create * @ 功能說明: 爲了方便管理,所有的任務創建函數都放在這個函數裏面 * @ 參數 : 無 * @ 返回值 : 無 **********************************************************************/ static void app_task_create(void) { int err; mqtt_client_t *client = NULL; BaseType_t xReturn = pdPASS;/* 定義一個創建信息返回值,默認爲pdPASS */ TCPIP_Init(); printf("\nwelcome to mqttclient test...\n"); mqtt_log_init(); client = mqtt_lease(); #ifdef TEST_USEING_TLS mqtt_set_port(client, "8883"); mqtt_set_ca(client, (char*)test_ca_get()); #else mqtt_set_port(client, "1883"); #endif mqtt_set_host(client, "www.jiejie01.top"); mqtt_set_client_id(client, random_string(10)); mqtt_set_user_name(client, random_string(10)); mqtt_set_password(client, random_string(10)); mqtt_set_clean_session(client, 1); err = mqtt_connect(client); MQTT_LOG_I("mqtt_connect err = %d", err); err = mqtt_subscribe(client, "freertos-topic", QOS0, NULL); MQTT_LOG_I("mqtt_subscribe err = %d", err); taskENTER_CRITICAL(); //進入臨界區 /* 創建mqtt_task任務 */ xReturn = xTaskCreate((TaskFunction_t )mqtt_task, /* 任務入口函數 */ (const char* )"mqtt_task",/* 任務名字 */ (uint16_t )2048, /* 任務棧大小 */ (void* )client, /* 任務入口函數參數 */ (UBaseType_t )10, /* 任務的優先級 */ (TaskHandle_t* )&mqtt_task_handle);/* 任務控制塊指針 */ if(pdPASS == xReturn) printf("Create mqtt_task sucess...\r\n"); vTaskDelete(app_task_create_handle); //刪除app_task_create任務 taskEXIT_CRITICAL(); //退出臨界區 } /********************************************************************** * @ 函數名 : mqtt_task * @ 功能說明: mqtt_task任務主體 * @ 參數 : * @ 返回值 : 無 ********************************************************************/ static void mqtt_task(void* arg) { mqtt_client_t *client = (mqtt_client_t *)arg; char buf[100] = { 0 }; mqtt_message_t msg; memset(&msg, 0, sizeof(msg)); sprintf(buf, "welcome to mqttclient, this is a publish test..."); vTaskDelay(4000); mqtt_list_subscribe_topic(client); msg.payload = (void *) buf; msg.qos = QOS0; while(1) { sprintf(buf, "welcome to mqttclient, this is a publish test, a rand number: %d ...", random_number()); mqtt_publish(client, "freertos-topic", &msg); vTaskDelay(4000); } }
-
然後編譯代碼,燒錄到開發板上,實驗現象如下:
本次移植完成。