This commit is contained in:
daishengdong
2020-06-18 20:57:46 +08:00
88 changed files with 4790 additions and 3273 deletions

View File

@@ -16,7 +16,7 @@
<TargetCommonOption> <TargetCommonOption>
<Device>STM32F429IGTx</Device> <Device>STM32F429IGTx</Device>
<Vendor>STMicroelectronics</Vendor> <Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32F4xx_DFP.2.9.0</PackID> <PackID>Keil.STM32F4xx_DFP.2.13.0</PackID>
<PackURL>http://www.keil.com/pack</PackURL> <PackURL>http://www.keil.com/pack</PackURL>
<Cpu>IRAM(0x20000000-0x2002FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) FPU2 CPUTYPE("Cortex-M4")</Cpu> <Cpu>IRAM(0x20000000-0x2002FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) FPU2 CPUTYPE("Cortex-M4")</Cpu>
<FlashUtilSpec></FlashUtilSpec> <FlashUtilSpec></FlashUtilSpec>
@@ -338,7 +338,7 @@
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define>USE_HAL_DRIVER,STM32F429xx,MBEDTLS_CONFIG_FILE=&lt;mbedtls_config.h&gt;,</Define> <Define>USE_HAL_DRIVER,STM32F429xx,MBEDTLS_CONFIG_FILE=&lt;mbedtls_config.h&gt;,</Define>
<Undefine></Undefine> <Undefine></Undefine>
<IncludePath>..\..\BSP\Inc;..\..\..\..\platform\vendor_bsp\st\STM32F4xx_HAL_Driver\Inc;..\..\..\..\platform\vendor_bsp\st\STM32F4xx_HAL_Driver\Inc\Legacy;..\..\..\..\platform\vendor_bsp\st\CMSIS\Device\ST\STM32F4xx\Include;..\..\..\..\platform\vendor_bsp\st\CMSIS\Include;..\..\..\..\arch\arm\arm-v7m\cortex-m4\armcc;..\..\..\..\arch\arm\arm-v7m\common\include;..\..\TOS-CONFIG;..\..\..\..\kernel\core\include;..\..\..\..\kernel\pm\include;..\..\..\..\osal\cmsis_os;..\..\..\..\net\lwip;..\..\..\..\net\lwip\3rdparty\src\include;..\..\..\..\net\lwip\3rdparty\src\include\compat;..\..\..\..\net\lwip\3rdparty\src\include\lwip;..\..\..\..\net\lwip\3rdparty\src\include\netif;..\..\..\..\net\lwip\3rdparty\src\include\lwip\apps;..\..\..\..\net\lwip\3rdparty\src\include\lwip\priv;..\..\..\..\net\lwip\3rdparty\src\include\lwip\prot;..\..\..\..\net\lwip\port\include\arch;..\..\..\..\net\lwip\port\include;..\..\..\..\components\connectivity\mqttclient\common;..\..\..\..\components\connectivity\mqttclient\common\log;..\..\..\..\components\connectivity\mqttclient\mqtt;..\..\..\..\components\connectivity\mqttclient\mqttclient;..\..\..\..\components\connectivity\mqttclient\network;..\..\..\..\components\connectivity\mqttclient\platform\TencentOS-tiny;..\..\..\..\components\connectivity\mqttclient\common\mbedtls\configs;..\..\..\..\components\connectivity\mqttclient\common\mbedtls\wrapper;..\..\..\..\components\security\mbedtls\3rdparty\include;..\..\..\..\components\security\mbedtls\3rdparty\include\mbedtls</IncludePath> <IncludePath>..\..\BSP\Inc;..\..\..\..\platform\vendor_bsp\st\STM32F4xx_HAL_Driver\Inc;..\..\..\..\platform\vendor_bsp\st\STM32F4xx_HAL_Driver\Inc\Legacy;..\..\..\..\platform\vendor_bsp\st\CMSIS\Device\ST\STM32F4xx\Include;..\..\..\..\platform\vendor_bsp\st\CMSIS\Include;..\..\..\..\arch\arm\arm-v7m\cortex-m4\armcc;..\..\..\..\arch\arm\arm-v7m\common\include;..\..\TOS-CONFIG;..\..\..\..\kernel\core\include;..\..\..\..\kernel\pm\include;..\..\..\..\osal\cmsis_os;..\..\..\..\net\lwip;..\..\..\..\net\lwip\3rdparty\src\include;..\..\..\..\net\lwip\3rdparty\src\include\compat;..\..\..\..\net\lwip\3rdparty\src\include\lwip;..\..\..\..\net\lwip\3rdparty\src\include\netif;..\..\..\..\net\lwip\3rdparty\src\include\lwip\apps;..\..\..\..\net\lwip\3rdparty\src\include\lwip\priv;..\..\..\..\net\lwip\3rdparty\src\include\lwip\prot;..\..\..\..\net\lwip\port\include\arch;..\..\..\..\net\lwip\port\include;..\..\..\..\components\connectivity\mqttclient\common;..\..\..\..\components\connectivity\mqttclient\common\log;..\..\..\..\components\connectivity\mqttclient\mqtt;..\..\..\..\components\connectivity\mqttclient\mqttclient;..\..\..\..\components\connectivity\mqttclient\network;..\..\..\..\components\connectivity\mqttclient\network\mbedtls\configs;..\..\..\..\components\connectivity\mqttclient\network\mbedtls\wrapper;..\..\..\..\components\connectivity\mqttclient\platform\TencentOS-tiny;..\..\..\..\components\security\mbedtls\3rdparty\include;..\..\..\..\components\security\mbedtls\3rdparty\include\mbedtls</IncludePath>
</VariousControls> </VariousControls>
</Cads> </Cads>
<Aads> <Aads>
@@ -1327,35 +1327,30 @@
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\log\arch\tencentos-tiny\arch.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\common\log\arch\tencentos-tiny\arch.c</FilePath>
</File> </File>
<File>
<FileName>config.h</FileName>
<FileType>5</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\log\config.h</FilePath>
</File>
</Files> </Files>
</Group> </Group>
<Group> <Group>
<GroupName>mqttclient/common</GroupName> <GroupName>mqttclient/common</GroupName>
<Files> <Files>
<File>
<FileName>list.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\list.c</FilePath>
</File>
<File> <File>
<FileName>random.c</FileName> <FileName>random.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\random.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\common\random.c</FilePath>
</File> </File>
<File> <File>
<FileName>log.h</FileName> <FileName>mqtt_list.c</FileName>
<FileType>5</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\log.h</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\common\mqtt_list.c</FilePath>
</File> </File>
<File> <File>
<FileName>error.h</FileName> <FileName>mqtt_log.h</FileName>
<FileType>5</FileType> <FileType>5</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\error.h</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\common\mqtt_log.h</FilePath>
</File>
<File>
<FileName>mqtt_error.h</FileName>
<FileType>5</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\mqtt_error.h</FilePath>
</File> </File>
</Files> </Files>
</Group> </Group>
@@ -1367,6 +1362,16 @@
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\network\network.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\network\network.c</FilePath>
</File> </File>
<File>
<FileName>nettype_tcp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\network\nettype_tcp.c</FilePath>
</File>
<File>
<FileName>nettype_tls.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\network\nettype_tls.c</FilePath>
</File>
</Files> </Files>
</Group> </Group>
<Group> <Group>
@@ -1387,16 +1392,6 @@
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\platform\TencentOS-tiny\platform_net_socket.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\platform\TencentOS-tiny\platform_net_socket.c</FilePath>
</File> </File>
<File>
<FileName>platform_nettype_tcp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\platform\TencentOS-tiny\platform_nettype_tcp.c</FilePath>
</File>
<File>
<FileName>platform_nettype_tls.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\platform\TencentOS-tiny\platform_nettype_tls.c</FilePath>
</File>
<File> <File>
<FileName>platform_thread.c</FileName> <FileName>platform_thread.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
@@ -1415,17 +1410,17 @@
<File> <File>
<FileName>entropy_hardware_alt.c</FileName> <FileName>entropy_hardware_alt.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\mbedtls\wrapper\entropy_hardware_alt.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\network\mbedtls\wrapper\entropy_hardware_alt.c</FilePath>
</File> </File>
<File> <File>
<FileName>net_sockets_alt.c</FileName> <FileName>net_sockets_alt.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\mbedtls\wrapper\net_sockets_alt.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\network\mbedtls\wrapper\net_sockets_alt.c</FilePath>
</File> </File>
<File> <File>
<FileName>timing_alt.c</FileName> <FileName>timing_alt.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\mbedtls\wrapper\timing_alt.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\network\mbedtls\wrapper\timing_alt.c</FilePath>
</File> </File>
</Files> </Files>
</Group> </Group>

View File

@@ -1,40 +1,39 @@
/* /*
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2019-12-15 00:42:16 * @LastEditTime: 2020-06-17 19:31:41
* @LastEditTime: 2020-02-25 09:25:35
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#ifndef _MQTT_CONFIG_H_ #ifndef _MQTT_CONFIG_H_
#define _MQTT_CONFIG_H_ #define _MQTT_CONFIG_H_
#define LOG_IS_SALOF #define MQTT_LOG_IS_SALOF
#define LOG_LEVEL DEBUG_LEVEL //WARN_LEVEL DEBUG_LEVEL #define MQTT_LOG_LEVEL MQTT_LOG_DEBUG_LEVEL //MQTT_LOG_WARN_LEVEL MQTT_LOG_DEBUG_LEVEL
#ifdef LOG_IS_SALOF #ifdef MQTT_LOG_IS_SALOF
#define USE_LOG (1U) #define SALOF_USING_LOG (1U)
#define USE_SALOF (1U) #define SALOF_USING_SALOF (1U)
#define SALOF_OS USE_TENCENTOS #define SALOF_LOG_LEVEL MQTT_LOG_LEVEL
#define USE_IDLE_HOOK (0U) #define SALOF_OS SALOF_USING_TENCENTOS
#define LOG_COLOR (0U) #define SALOF_USING_IDLE_HOOK (0U)
#define LOG_TS (0U) #define SALOF_LOG_COLOR (1U)
#define LOG_TAR (0U) #define SALOF_LOG_TS (0U)
#define SALOF_BUFF_SIZE (512U) #define SALOF_LOG_TAR (0U)
#define SALOF_FIFO_SIZE (1024U) #define SALOF_BUFF_SIZE 512
#define SALOF_TASK_STACK_SIZE (1024U) #define SALOF_FIFO_SIZE 4096
#define SALOF_TASK_TICK (50U) #define SALOF_TASK_STACK_SIZE 1024
#define SALOF_TASK_TICK 50
#endif #endif
#define MQTT_MAX_PACKET_ID (0xFFFF - 1) #define MQTT_MAX_PACKET_ID (0xFFFF - 1)
#define MQTT_TOPIC_LEN_MAX 64 #define MQTT_TOPIC_LEN_MAX 64
#define MQTT_ACK_HANDLER_NUM_MAX 64 #define MQTT_ACK_HANDLER_NUM_MAX 64
#define MQTT_DEFAULT_BUF_SIZE 1024 #define MQTT_DEFAULT_BUF_SIZE 1024
#define MQTT_DEFAULT_CMD_TIMEOUT 4000 #define MQTT_DEFAULT_CMD_TIMEOUT 5000
#define MQTT_MAX_CMD_TIMEOUT 20000 #define MQTT_MAX_CMD_TIMEOUT 20000
#define MQTT_MIN_CMD_TIMEOUT 1000 #define MQTT_MIN_CMD_TIMEOUT 1000
#define MQTT_KEEP_ALIVE_INTERVAL 100 // unit: second #define MQTT_KEEP_ALIVE_INTERVAL 50 // unit: second
#define MQTT_VERSION 4 // 4 is mqtt 3.1.1 #define MQTT_VERSION 4 // 4 is mqtt 3.1.1
#define MQTT_RECONNECT_DEFAULT_DURATION 1000 #define MQTT_RECONNECT_DEFAULT_DURATION 1000
#define MQTT_THREAD_STACK_SIZE 2048 #define MQTT_THREAD_STACK_SIZE 2048
@@ -42,6 +41,6 @@
#define MQTT_THREAD_TICK 50 #define MQTT_THREAD_TICK 50
//#define MQTT_NETWORK_TYPE_TLS #define MQTT_NETWORK_TYPE_NO_TLS
#endif /* _MQTT_CONFIG_H_ */ #endif /* _MQTT_CONFIG_H_ */

View File

@@ -16,7 +16,7 @@
<TargetCommonOption> <TargetCommonOption>
<Device>STM32F429IGTx</Device> <Device>STM32F429IGTx</Device>
<Vendor>STMicroelectronics</Vendor> <Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32F4xx_DFP.2.9.0</PackID> <PackID>Keil.STM32F4xx_DFP.2.13.0</PackID>
<PackURL>http://www.keil.com/pack</PackURL> <PackURL>http://www.keil.com/pack</PackURL>
<Cpu>IRAM(0x20000000-0x2002FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) FPU2 CPUTYPE("Cortex-M4")</Cpu> <Cpu>IRAM(0x20000000-0x2002FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) FPU2 CPUTYPE("Cortex-M4")</Cpu>
<FlashUtilSpec></FlashUtilSpec> <FlashUtilSpec></FlashUtilSpec>
@@ -338,7 +338,7 @@
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define>USE_HAL_DRIVER,STM32F429xx,MBEDTLS_CONFIG_FILE=&lt;mbedtls_config.h&gt;,</Define> <Define>USE_HAL_DRIVER,STM32F429xx,MBEDTLS_CONFIG_FILE=&lt;mbedtls_config.h&gt;,</Define>
<Undefine></Undefine> <Undefine></Undefine>
<IncludePath>..\..\BSP\Inc;..\..\..\..\platform\vendor_bsp\st\STM32F4xx_HAL_Driver\Inc;..\..\..\..\platform\vendor_bsp\st\STM32F4xx_HAL_Driver\Inc\Legacy;..\..\..\..\platform\vendor_bsp\st\CMSIS\Device\ST\STM32F4xx\Include;..\..\..\..\platform\vendor_bsp\st\CMSIS\Include;..\..\..\..\arch\arm\arm-v7m\cortex-m4\armcc;..\..\..\..\arch\arm\arm-v7m\common\include;.\TOS-CONFIG;..\..\..\..\kernel\core\include;..\..\..\..\kernel\pm\include;..\..\..\..\osal\cmsis_os;..\..\..\..\net\lwip;..\..\..\..\net\lwip\3rdparty\src\include;..\..\..\..\net\lwip\3rdparty\src\include\compat;..\..\..\..\net\lwip\3rdparty\src\include\lwip;..\..\..\..\net\lwip\3rdparty\src\include\netif;..\..\..\..\net\lwip\3rdparty\src\include\lwip\apps;..\..\..\..\net\lwip\3rdparty\src\include\lwip\priv;..\..\..\..\net\lwip\3rdparty\src\include\lwip\prot;..\..\..\..\net\lwip\port\include\arch;..\..\..\..\net\lwip\port\include;..\..\..\..\components\connectivity\mqttclient\common;..\..\..\..\components\connectivity\mqttclient\common\log;..\..\..\..\components\connectivity\mqttclient\mqtt;..\..\..\..\components\connectivity\mqttclient\mqttclient;..\..\..\..\components\connectivity\mqttclient\network;..\..\..\..\components\connectivity\mqttclient\platform\TencentOS-tiny;..\..\..\..\components\connectivity\mqttclient\common\mbedtls\wrapper;..\..\..\..\components\security\mbedtls\3rdparty\include;..\..\..\..\components\security\mbedtls\3rdparty\include\mbedtls</IncludePath> <IncludePath>..\..\BSP\Inc;..\..\..\..\platform\vendor_bsp\st\STM32F4xx_HAL_Driver\Inc;..\..\..\..\platform\vendor_bsp\st\STM32F4xx_HAL_Driver\Inc\Legacy;..\..\..\..\platform\vendor_bsp\st\CMSIS\Device\ST\STM32F4xx\Include;..\..\..\..\platform\vendor_bsp\st\CMSIS\Include;..\..\..\..\arch\arm\arm-v7m\cortex-m4\armcc;..\..\..\..\arch\arm\arm-v7m\common\include;.\TOS-CONFIG;..\..\..\..\kernel\core\include;..\..\..\..\kernel\pm\include;..\..\..\..\osal\cmsis_os;..\..\..\..\net\lwip;..\..\..\..\net\lwip\3rdparty\src\include;..\..\..\..\net\lwip\3rdparty\src\include\compat;..\..\..\..\net\lwip\3rdparty\src\include\lwip;..\..\..\..\net\lwip\3rdparty\src\include\netif;..\..\..\..\net\lwip\3rdparty\src\include\lwip\apps;..\..\..\..\net\lwip\3rdparty\src\include\lwip\priv;..\..\..\..\net\lwip\3rdparty\src\include\lwip\prot;..\..\..\..\net\lwip\port\include\arch;..\..\..\..\net\lwip\port\include;..\..\..\..\components\connectivity\mqttclient\common;..\..\..\..\components\connectivity\mqttclient\common\log;..\..\..\..\components\connectivity\mqttclient\mqtt;..\..\..\..\components\connectivity\mqttclient\mqttclient;..\..\..\..\components\connectivity\mqttclient\network;..\..\..\..\components\connectivity\mqttclient\platform\TencentOS-tiny;..\..\..\..\components\connectivity\mqttclient\network\mbedtls\wrapper;..\..\..\..\components\security\mbedtls\3rdparty\include;..\..\..\..\components\security\mbedtls\3rdparty\include\mbedtls</IncludePath>
</VariousControls> </VariousControls>
</Cads> </Cads>
<Aads> <Aads>
@@ -1322,35 +1322,30 @@
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\log\arch\tencentos-tiny\arch.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\common\log\arch\tencentos-tiny\arch.c</FilePath>
</File> </File>
<File>
<FileName>config.h</FileName>
<FileType>5</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\log\config.h</FilePath>
</File>
</Files> </Files>
</Group> </Group>
<Group> <Group>
<GroupName>mqttclient/common</GroupName> <GroupName>mqttclient/common</GroupName>
<Files> <Files>
<File>
<FileName>list.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\list.c</FilePath>
</File>
<File> <File>
<FileName>random.c</FileName> <FileName>random.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\random.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\common\random.c</FilePath>
</File> </File>
<File> <File>
<FileName>log.h</FileName> <FileName>mqtt_list.c</FileName>
<FileType>5</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\log.h</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\common\mqtt_list.c</FilePath>
</File> </File>
<File> <File>
<FileName>error.h</FileName> <FileName>mqtt_error.h</FileName>
<FileType>5</FileType> <FileType>5</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\error.h</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\common\mqtt_error.h</FilePath>
</File>
<File>
<FileName>mqtt_log.h</FileName>
<FileType>5</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\mqtt_log.h</FilePath>
</File> </File>
</Files> </Files>
</Group> </Group>
@@ -1362,6 +1357,16 @@
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\network\network.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\network\network.c</FilePath>
</File> </File>
<File>
<FileName>nettype_tcp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\network\nettype_tcp.c</FilePath>
</File>
<File>
<FileName>nettype_tls.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\network\nettype_tls.c</FilePath>
</File>
</Files> </Files>
</Group> </Group>
<Group> <Group>
@@ -1382,16 +1387,6 @@
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\platform\TencentOS-tiny\platform_net_socket.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\platform\TencentOS-tiny\platform_net_socket.c</FilePath>
</File> </File>
<File>
<FileName>platform_nettype_tcp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\platform\TencentOS-tiny\platform_nettype_tcp.c</FilePath>
</File>
<File>
<FileName>platform_nettype_tls.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\platform\TencentOS-tiny\platform_nettype_tls.c</FilePath>
</File>
<File> <File>
<FileName>platform_thread.c</FileName> <FileName>platform_thread.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
@@ -1810,17 +1805,17 @@
<File> <File>
<FileName>entropy_hardware_alt.c</FileName> <FileName>entropy_hardware_alt.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\mbedtls\wrapper\entropy_hardware_alt.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\network\mbedtls\wrapper\entropy_hardware_alt.c</FilePath>
</File> </File>
<File> <File>
<FileName>net_sockets_alt.c</FileName> <FileName>net_sockets_alt.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\mbedtls\wrapper\net_sockets_alt.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\network\mbedtls\wrapper\net_sockets_alt.c</FilePath>
</File> </File>
<File> <File>
<FileName>timing_alt.c</FileName> <FileName>timing_alt.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\mbedtls\wrapper\timing_alt.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\network\mbedtls\wrapper\timing_alt.c</FilePath>
</File> </File>
</Files> </Files>
</Group> </Group>

View File

@@ -1,40 +1,39 @@
/* /*
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2019-12-15 00:42:16 * @LastEditTime: 2020-06-17 19:31:41
* @LastEditTime: 2020-02-25 09:25:35
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#ifndef _MQTT_CONFIG_H_ #ifndef _MQTT_CONFIG_H_
#define _MQTT_CONFIG_H_ #define _MQTT_CONFIG_H_
#define LOG_IS_SALOF #define MQTT_LOG_IS_SALOF
#define LOG_LEVEL DEBUG_LEVEL //WARN_LEVEL DEBUG_LEVEL #define MQTT_LOG_LEVEL MQTT_LOG_DEBUG_LEVEL //MQTT_LOG_WARN_LEVEL MQTT_LOG_DEBUG_LEVEL
#ifdef LOG_IS_SALOF #ifdef MQTT_LOG_IS_SALOF
#define USE_LOG (1U) #define SALOF_USING_LOG (1U)
#define USE_SALOF (1U) #define SALOF_USING_SALOF (1U)
#define SALOF_OS USE_TENCENTOS #define SALOF_LOG_LEVEL MQTT_LOG_LEVEL
#define USE_IDLE_HOOK (0U) #define SALOF_OS SALOF_USING_TENCENTOS
#define LOG_COLOR (0U) #define SALOF_USING_IDLE_HOOK (0U)
#define LOG_TS (0U) #define SALOF_LOG_COLOR (1U)
#define LOG_TAR (0U) #define SALOF_LOG_TS (0U)
#define SALOF_BUFF_SIZE (512U) #define SALOF_LOG_TAR (0U)
#define SALOF_FIFO_SIZE (1024U) #define SALOF_BUFF_SIZE 512
#define SALOF_TASK_STACK_SIZE (1024U) #define SALOF_FIFO_SIZE 4096
#define SALOF_TASK_TICK (50U) #define SALOF_TASK_STACK_SIZE 1024
#define SALOF_TASK_TICK 50
#endif #endif
#define MQTT_MAX_PACKET_ID (0xFFFF - 1) #define MQTT_MAX_PACKET_ID (0xFFFF - 1)
#define MQTT_TOPIC_LEN_MAX 64 #define MQTT_TOPIC_LEN_MAX 64
#define MQTT_ACK_HANDLER_NUM_MAX 64 #define MQTT_ACK_HANDLER_NUM_MAX 64
#define MQTT_DEFAULT_BUF_SIZE 1024 #define MQTT_DEFAULT_BUF_SIZE 1024
#define MQTT_DEFAULT_CMD_TIMEOUT 4000 #define MQTT_DEFAULT_CMD_TIMEOUT 5000
#define MQTT_MAX_CMD_TIMEOUT 20000 #define MQTT_MAX_CMD_TIMEOUT 20000
#define MQTT_MIN_CMD_TIMEOUT 1000 #define MQTT_MIN_CMD_TIMEOUT 1000
#define MQTT_KEEP_ALIVE_INTERVAL 100 // unit: second #define MQTT_KEEP_ALIVE_INTERVAL 50 // unit: second
#define MQTT_VERSION 4 // 4 is mqtt 3.1.1 #define MQTT_VERSION 4 // 4 is mqtt 3.1.1
#define MQTT_RECONNECT_DEFAULT_DURATION 1000 #define MQTT_RECONNECT_DEFAULT_DURATION 1000
#define MQTT_THREAD_STACK_SIZE 2048 #define MQTT_THREAD_STACK_SIZE 2048
@@ -42,6 +41,6 @@
#define MQTT_THREAD_TICK 50 #define MQTT_THREAD_TICK 50
#define MQTT_NETWORK_TYPE_TLS // #define MQTT_NETWORK_TYPE_NO_TLS
#endif /* _MQTT_CONFIG_H_ */ #endif /* _MQTT_CONFIG_H_ */

View File

@@ -93,6 +93,7 @@ typedef struct at_echo_st {
size_t __w_idx; size_t __w_idx;
int __is_expecting; int __is_expecting;
k_sem_t __expect_notify; k_sem_t __expect_notify;
int __is_fuzzy_match;
} at_echo_t; } at_echo_t;
typedef void (*at_event_callback_t)(void); typedef void (*at_event_callback_t)(void);
@@ -113,7 +114,7 @@ typedef struct at_agent_st {
k_task_t parser; k_task_t parser;
at_cache_t recv_cache; at_cache_t recv_cache;
at_timer_t timer; k_stopwatch_t timer;
k_mutex_t global_lock; k_mutex_t global_lock;
@@ -289,6 +290,22 @@ __API__ void tos_at_deinit(void);
*/ */
__API__ int tos_at_echo_create(at_echo_t *echo, char *buffer, size_t buffer_size, char *echo_expect); __API__ int tos_at_echo_create(at_echo_t *echo, char *buffer, size_t buffer_size, char *echo_expect);
/**
* @brief Create a echo struct with fuzzy matching for expected echo.
*
* @attention None
*
* @param[in] echo pointer to the echo struct.
* @param[out] buffer buffer to hold the received message from the module.
* @param[in] buffer_size size of the buffer.
* @param[in] echo_expect_contains if the echo message contains echo_expect_contains, it is a matching.
*
* @return errcode
* @retval -1 create failed(error).
* @retval 0 create successfully.
*/
__API__ int tos_at_echo_fuzzy_matching_create(at_echo_t *echo, char *buffer, size_t buffer_size, char *echo_expect_contains);
/** /**
* @brief Execute an at command. * @brief Execute an at command.
* *
@@ -456,5 +473,5 @@ __API__ const char *tos_at_agent_channel_ip_get(int channel_id);
*/ */
__API__ const char *tos_at_agent_channel_port_get(int channel_id); __API__ const char *tos_at_agent_channel_port_get(int channel_id);
#endif /* __AT_AGENT_H_ */ #endif /* _TOS_AT_H_ */

View File

@@ -16,7 +16,7 @@
<TargetCommonOption> <TargetCommonOption>
<Device>STM32F103C8</Device> <Device>STM32F103C8</Device>
<Vendor>STMicroelectronics</Vendor> <Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32F1xx_DFP.2.2.0</PackID> <PackID>Keil.STM32F1xx_DFP.2.3.0</PackID>
<PackURL>http://www.keil.com/pack/</PackURL> <PackURL>http://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000-0x20004FFF) IROM(0x8000000-0x800FFFF) CLOCK(8000000) CPUTYPE("Cortex-M3")</Cpu> <Cpu>IRAM(0x20000000-0x20004FFF) IROM(0x8000000-0x800FFFF) CLOCK(8000000) CPUTYPE("Cortex-M3")</Cpu>
<FlashUtilSpec></FlashUtilSpec> <FlashUtilSpec></FlashUtilSpec>
@@ -54,7 +54,7 @@
<CreateLib>0</CreateLib> <CreateLib>0</CreateLib>
<CreateHexFile>0</CreateHexFile> <CreateHexFile>0</CreateHexFile>
<DebugInformation>1</DebugInformation> <DebugInformation>1</DebugInformation>
<BrowseInformation>0</BrowseInformation> <BrowseInformation>1</BrowseInformation>
<ListingPath></ListingPath> <ListingPath></ListingPath>
<HexFormatSelection>1</HexFormatSelection> <HexFormatSelection>1</HexFormatSelection>
<Merge32K>0</Merge32K> <Merge32K>0</Merge32K>
@@ -837,25 +837,25 @@
<Group> <Group>
<GroupName>mqttclient/common</GroupName> <GroupName>mqttclient/common</GroupName>
<Files> <Files>
<File>
<FileName>list.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\list.c</FilePath>
</File>
<File> <File>
<FileName>random.c</FileName> <FileName>random.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\random.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\common\random.c</FilePath>
</File> </File>
<File> <File>
<FileName>log.h</FileName> <FileName>mqtt_list.c</FileName>
<FileType>5</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\log.h</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\common\mqtt_list.c</FilePath>
</File> </File>
<File> <File>
<FileName>error.h</FileName> <FileName>mqtt_log.h</FileName>
<FileType>5</FileType> <FileType>5</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\error.h</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\common\mqtt_log.h</FilePath>
</File>
<File>
<FileName>mqtt_error.h</FileName>
<FileType>5</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\common\mqtt_error.h</FilePath>
</File> </File>
</Files> </Files>
</Group> </Group>
@@ -867,6 +867,16 @@
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\network\network.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\network\network.c</FilePath>
</File> </File>
<File>
<FileName>nettype_tcp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\network\nettype_tcp.c</FilePath>
</File>
<File>
<FileName>nettype_tls.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\network\nettype_tls.c</FilePath>
</File>
</Files> </Files>
</Group> </Group>
<Group> <Group>
@@ -887,16 +897,6 @@
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\platform\TencentOS-tiny\platform_net_socket.c</FilePath> <FilePath>..\..\..\..\components\connectivity\mqttclient\platform\TencentOS-tiny\platform_net_socket.c</FilePath>
</File> </File>
<File>
<FileName>platform_nettype_tcp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\platform\TencentOS-tiny\platform_nettype_tcp.c</FilePath>
</File>
<File>
<FileName>platform_nettype_tls.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\connectivity\mqttclient\platform\TencentOS-tiny\platform_nettype_tls.c</FilePath>
</File>
<File> <File>
<FileName>platform_thread.c</FileName> <FileName>platform_thread.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>

View File

@@ -1,48 +1,48 @@
/* /*
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2019-12-15 00:42:16 * @LastEditTime: 2020-06-17 19:31:41
* @LastEditTime: 2020-02-25 09:25:35
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#ifndef _MQTT_CONFIG_H_ #ifndef _MQTT_CONFIG_H_
#define _MQTT_CONFIG_H_ #define _MQTT_CONFIG_H_
//#define LOG_IS_SALOF //#define MQTT_LOG_IS_SALOF
#define LOG_LEVEL DEBUG_LEVEL //WARN_LEVEL DEBUG_LEVEL #define MQTT_NETSOCKET_USING_AT
#ifdef LOG_IS_SALOF #define MQTT_LOG_LEVEL MQTT_LOG_DEBUG_LEVEL //MQTT_LOG_WARN_LEVEL MQTT_LOG_DEBUG_LEVEL
#define USE_LOG (1U)
#define USE_SALOF (1U) #ifdef MQTT_LOG_IS_SALOF
#define SALOF_OS USE_TENCENTOS #define SALOF_USING_LOG (1U)
#define USE_IDLE_HOOK (0U) #define SALOF_USING_SALOF (1U)
#define LOG_COLOR (0U) #define SALOF_LOG_LEVEL MQTT_LOG_LEVEL
#define LOG_TS (0U) #define SALOF_OS SALOF_USING_TENCENTOS
#define LOG_TAR (0U) #define SALOF_USING_IDLE_HOOK (0U)
#define SALOF_BUFF_SIZE (512U) #define SALOF_LOG_COLOR (1U)
#define SALOF_FIFO_SIZE (1024U) #define SALOF_LOG_TS (0U)
#define SALOF_TASK_STACK_SIZE (1024U) #define SALOF_LOG_TAR (0U)
#define SALOF_TASK_TICK (50U) #define SALOF_BUFF_SIZE 512
#define SALOF_FIFO_SIZE 4096
#define SALOF_TASK_STACK_SIZE 1024
#define SALOF_TASK_TICK 50
#endif #endif
#define MQTT_MAX_PACKET_ID (0xFFFF - 1) #define MQTT_MAX_PACKET_ID (0xFFFF - 1)
#define MQTT_TOPIC_LEN_MAX 64 #define MQTT_TOPIC_LEN_MAX 64
#define MQTT_ACK_HANDLER_NUM_MAX 64 #define MQTT_ACK_HANDLER_NUM_MAX 64
#define MQTT_DEFAULT_BUF_SIZE 1024 #define MQTT_DEFAULT_BUF_SIZE 1024
#define MQTT_DEFAULT_CMD_TIMEOUT 4000 #define MQTT_DEFAULT_CMD_TIMEOUT 5000
#define MQTT_MAX_CMD_TIMEOUT 20000 #define MQTT_MAX_CMD_TIMEOUT 20000
#define MQTT_MIN_CMD_TIMEOUT 1000 #define MQTT_MIN_CMD_TIMEOUT 1000
#define MQTT_KEEP_ALIVE_INTERVAL 100 // unit: second #define MQTT_KEEP_ALIVE_INTERVAL 50 // unit: second
#define MQTT_VERSION 4 // 4 is mqtt 3.1.1 #define MQTT_VERSION 4 // 4 is mqtt 3.1.1
#define MQTT_RECONNECT_DEFAULT_DURATION 1000 #define MQTT_RECONNECT_DEFAULT_DURATION 1000
#define MQTT_THREAD_STACK_SIZE 2048 #define MQTT_THREAD_STACK_SIZE 2048
#define MQTT_THREAD_PRIO 5 #define MQTT_THREAD_PRIO 5
#define MQTT_THREAD_TICK 50 #define MQTT_THREAD_TICK 50
#define MQTT_NETSOCKET_USE_AT
//#define MQTT_NETWORK_TYPE_TLS #define MQTT_NETWORK_TYPE_NO_TLS
#endif /* _MQTT_CONFIG_H_ */ #endif /* _MQTT_CONFIG_H_ */

View File

@@ -60,7 +60,7 @@ extern "C" {
#define LORAWAN_PUBLIC_NETWORK true #define LORAWAN_PUBLIC_NETWORK true
/*root key*/ /*root key*/
#define LORAWAN_APP_KEY {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } #define LORAWAN_APP_KEY { 0x8c, 0xf9, 0x57, 0x20, 0x00, 0x00, 0xf7, 0x37, 0x1e, 0x29, 0xaa, 0xaa, 0xad, 0x20, 0x4a, 0x72 }
/*for ABP================================================================================*/ /*for ABP================================================================================*/
#define STATIC_DEVICE_ADDRESS 1 //if 0 , using a ramdom address #define STATIC_DEVICE_ADDRESS 1 //if 0 , using a ramdom address
@@ -68,21 +68,21 @@ extern "C" {
#define LORAWAN_NETWORK_ID ( uint32_t )0 #define LORAWAN_NETWORK_ID ( uint32_t )0
#define LORAWAN_DEVICE_ADDRESS ( uint32_t )0x0100000a #define LORAWAN_DEVICE_ADDRESS ( uint32_t )0x0100000a
#define LORAWAN_NWK_KEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } #define LORAWAN_NWK_KEY { 0x8c, 0xf9, 0x57, 0x20, 0x00, 0x00, 0xf7, 0x37, 0x1e, 0x29, 0xaa, 0xaa, 0xad, 0x20, 0x4a, 0x72 }
/*for 1.1.x*/ /*for 1.1.x*/
#define LORAWAN_F_NWK_S_INT_KEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } #define LORAWAN_F_NWK_S_INT_KEY { 0x8c, 0xf9, 0x57, 0x20, 0x00, 0x00, 0xf7, 0x37, 0x1e, 0x29, 0xaa, 0xaa, 0xad, 0x20, 0x4a, 0x72 }
#define LORAWAN_S_NWK_S_INT_KEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } #define LORAWAN_S_NWK_S_INT_KEY { 0x8c, 0xf9, 0x57, 0x20, 0x00, 0x00, 0xf7, 0x37, 0x1e, 0x29, 0xaa, 0xaa, 0xad, 0x20, 0x4a, 0x72 }
#define LORAWAN_NWK_S_ENC_KEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } #define LORAWAN_NWK_S_ENC_KEY { 0x8c, 0xf9, 0x57, 0x20, 0x00, 0x00, 0xf7, 0x37, 0x1e, 0x29, 0xaa, 0xaa, 0xad, 0x20, 0x4a, 0x72 }
#define LORAWAN_APP_S_KEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } #define LORAWAN_APP_S_KEY { 0x8c, 0xf9, 0x57, 0x20, 0x00, 0x00, 0xf7, 0x37, 0x1e, 0x29, 0xaa, 0xaa, 0xad, 0x20, 0x4a, 0x72 }
/*for OTAA================================================================================*/ /*for OTAA================================================================================*/
#define STATIC_DEVICE_EUI 1 //if 0 , using a ramdom EUI #define STATIC_DEVICE_EUI 1 //if 0 , using a ramdom EUI
#define IEEE_OUI 0x01, 0x01, 0x01 #define IEEE_OUI 0x01, 0x01, 0x01
#define LORAWAN_DEVICE_EUI { IEEE_OUI, 0x01, 0x01, 0x01, 0x04, 0x02 } #define LORAWAN_DEVICE_EUI { 0x8c, 0xf9, 0x57, 0x20, 0x00, 0x00, 0xf7, 0x37}
#define LORAWAN_JOIN_EUI /*APP_EUI*/ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 } #define LORAWAN_JOIN_EUI /*APP_EUI*/ { 0x8c, 0xf9, 0x57, 0x20, 0x00, 0x00, 0xf7, 0x37}

View File

@@ -32,7 +32,7 @@ extern "C" {
******************************************************************************/ ******************************************************************************/
/* lw application configuration (Mw is configured by lorawan_conf.h) */ /* lw application configuration (Mw is configured by lorawan_conf.h) */
#define LORAWAN_DEFAULT_ACTIVE_REGION LORAMAC_REGION_CN470ALI #define LORAWAN_DEFAULT_ACTIVE_REGION LORAMAC_REGION_CN470

View File

@@ -83,7 +83,7 @@ void MX_LoRaWAN_Init(void)
lw_request_class(CLASS_A); lw_request_class(CLASS_A);
/*channel 8-16*/ /*channel 8-16*/
LWChannel_mask_t ch={0xFF00,0,0,0,0,0}; LWChannel_mask_t ch={0x0000,0,0,0,0,0x00FF};
lw_current_chmask_set(&ch); lw_current_chmask_set(&ch);
/*tx dr*/ /*tx dr*/

View File

@@ -0,0 +1,42 @@
cmake_minimum_required(VERSION 2.8)
project(mqtt-client)
set(TARGETS "mqtt-client")
set(SUBDIRS "mqtt" "test" "platform" "network" "common" "mqttclient")
set(INCDIRS "mqtt" "platform/linux" "common" "common/log" "network" "network/mbedtls/include" "mqttclient" "test")
set(OUTDIRS "build")
set(LIBNAMES "mqtt" "platform" "network" "common" "salof" "mbedtls" "mqttclient")
set(PROJECT_ROOT_PATH "${PROJECT_SOURCE_DIR}")
set(LIBRARY_OUTPUT_PATH "${PROJECT_ROOT_PATH}/${OUTDIRS}/lib/")
set(EXECUTABLE_OUTPUT_PATH "${PROJECT_ROOT_PATH}/${OUTDIRS}/bin/")
set(CMAKE_BUILD_TYPE "Release") # Debug Release
set(CMAKE_LIB_TYPE "STATIC") # SHARED STATIC
# set(CMAKE_C_COMPILER "gcc")
# set(CMAKE_CXX_COMPILER "g++" )
set(CMAKE_C_FLAGS "-Wall")
set(CMAKE_C_FLAGS "-lpthread")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -O0 -g -ggdb")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3 -DNDEBUG")
if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "-std=c++11")
set(CMAKE_CXX_FLAGS "-lpthread")
set(CMAKE_CXX_FLAGS "-Wall")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -O0 -g -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -O3")
endif(CMAKE_COMPILER_IS_GNUCXX)
foreach(incdir ${INCDIRS})
include_directories(${incdir})
endforeach()
foreach(subdir ${SUBDIRS})
add_subdirectory(${PROJECT_ROOT_PATH}/${subdir})
endforeach()
link_directories(${LIBRARY_OUTPUT_PATH})

View File

@@ -1,31 +1,91 @@
[![](https://img.shields.io/github/v/tag/jiejietop/mqttclient?color=brightgreen&label=version)](https://github.com/jiejieTop/mqttclient/releases)
[![license](https://img.shields.io/badge/license-Apache-blue.svg)](https://github.com/jiejieTop/mqttclient/blob/master/LICENSE)
![](https://img.shields.io/github/forks/jiejieTop/mqttclient)
![](https://img.shields.io/github/stars/jiejieTop/mqttclient)
![](https://img.shields.io/badge/platform-Linux|Windows|Mac|Embedded-orange.svg)
[English Documents](README.md)
# mqttclient # mqttclient
**一个基于socket API之上的跨平台MQTT客户端** **一个高性能、高稳定性的跨平台MQTT客户端**
基于socket API的MQTT客户端拥有非常简洁的API接口以极少的资源实现QOS2的服务质量并且无缝衔接了mbedtls加密库。 一个高性能、高稳定性的跨平台MQTT客户端基于socket API之上开发可以在嵌入式设备FreeRTOS/LiteOS/RT-Thread/TencentOS tiny、Linux、Windows、Mac上使用拥有非常简洁的API接口以极少的资源实现QOS2的服务质量并且无缝衔接了mbedtls加密库。
## 优势: ## 优势:
- **基于标准BSD socket之上开发**只要是兼容BSD socket的系统均可使用。
- **稳定**:无论是`掉线重连``丢包重发`,都是严格`遵循MQTT协议标准`执行,除此之外对**大数据量**的测试无论是收是发,都是非常稳定(一次发送`135K`数据3秒一次高频测试也是非常稳定7个主题同时收发每秒一次也就是1秒14个mqtt报文服务质量QoS0、QoS1、QoS2都有。因为作者以极少的资源设计了`记录机制`对采用QoS1服务质量的报文必须保证到达一次当发布的主题qos1、qos2都适用没有被服务器收到时会自动重发而对QoS2服务质量的报文保证有且只有处理一次如果不相信它稳定性的同学可以自己去修改源码专门为QoS2服务质量去做测试故意不回复`PUBREC`让服务器重发QoS2报文且看看客户端是否有且只有处理一次而对于掉线重连的稳定性这种则是**基本操作**了,没啥好说的,在自动重连后还会自动重新订阅主题,保证主题不会丢失,因此在测试中稳定性极好 - **具有极高的稳定**:无论是**掉线重连****丢包重发**,都是**严格遵循MQTT协议标准**执行,除此之外对**大数据量**的测试无论是收是发,都是非常稳定**高频**测试也是非常稳定
- **轻量级**整个代码工程极其简单不使用mbedtls情况下占用资源极少作者曾使用esp8266模组与云端通信整个工程代码消耗的RAM不足15k包括系统占用的开销对数据的处理开销而此次还是未优化的情况下还依旧完美保留了掉线重连的稳定性但是对应qos1、qos2服务质量的报文则未做测试因为STM32F103C8T6芯片资源实在是太少了折腾不起 - **轻量级**整个代码工程极其简单不使用mbedtls情况下占用资源极少作者曾使用esp8266模组与云端通信整个工程代码消耗的RAM不足15k。
- **无缝衔接mbedtls加密传输**让网络传输更加安全而且接口层完全不需要用户理会无论是否加密mqttclient对用户提供的API接口是**没有变化**的,这就很好的兼容了一套代应用层的码可以加密传输也可以不加密传输。 - **支持mbedtls加密传输**让网络传输更加安全而且接口层完全不需要用户理会无论是否加密mqttclient对用户提供的API接口是**固定**的,这就很好的兼容了一套代应用层的码可以加密传输也可以不加密传输。
- **支持多客户端**,同时兼容多个客户端运行工作,一个设备连接多个的服务器。
- **支持同步异步处理**应用程序无需阻塞等待浪费CPU资源。
- **支持拦截器配置**,在某些平台中,客户端会默认自动订阅系统主题,而且每次来自服务器的主题都是变动的,此时需要使用拦截器进行拦截,分离主题与数据信息,并递交给用户,极大提高灵活性。
- **拥有在线代码生成工具**,极其简单配置就可以生成对应的代码,地址:[https://jiejietop.gitee.io/mqtt/index.html](https://jiejietop.gitee.io/mqtt/index.html)
- **拥有极简的API接口**总的来说mqttclient的配置都有默认值基本无需配置都能使用的也可以随意配置对配置都有健壮性检测这样子设计的API接口也是非常简单。 - **拥有极简的API接口**总的来说mqttclient的配置都有默认值基本无需配置都能使用的也可以随意配置对配置都有健壮性检测这样子设计的API接口也是非常简单。
- **有非常好的代码风格与思想**整个代码采用分层式设计代码实现采用异步处理的思想降低耦合提高性能具体体现在什么地方呢很简单目前市面上很多MQTT客户端发布主题都是要阻塞等待ack这是非常暴力的行为阻塞当前线程等待服务器的应答那如果我想要发送数据怎么办或者我要重复检测数据怎么办你可能会说指定阻塞时间等待那如果网络延迟ack迟迟不来我就白等了吗对于qos1、qos2的服务质量怎么办所以说这种还是要异步处理的思想我发布主题那我发布出去就好了不需要等待对于qos1、qos2服务质量的MQTT报文如果服务器没收到那我重发就可以这种重发也是异步的处理完全不会阻塞当前线程 - **多功能参数可配置可裁剪**,重连时间间隔、心跳周期、最大订阅数量、命令超时、读写缓冲区大小、拦截器处理等等参数功能可裁剪可配置,满足开发者再复杂、简单等各种开发环境下的使用需求
- **MQTT协议支持主题通配符`“#”、“+”`。** - **支持自动重新订阅主题**,在自动重连后保证主题不会丢失。
- **支持主题通配符`“#”、“+”`**。
- **订阅的主题与消息处理完全分离**,让编程逻辑更加简单易用,用户无需理会错综复杂的逻辑关系。 - **订阅的主题与消息处理完全分离**,让编程逻辑更加简单易用,用户无需理会错综复杂的逻辑关系。
- **mqttclient内部已实现保活处理机制**,无需用户过多关心理会,用户只需专心处理应用功能即可。 - **mqttclient内部已实现保活处理机制**,无需用户过多关心理会,用户只需专心处理应用功能即可。
- **拥有非常好的设计**,以极少的资源设计了**记录机制**当报文在丢失的时候进行重发操作确保qos1、qos2服务质量等级的报文保证其服务质量。
- **有非常好的代码风格与思想**:整个代码采用分层式设计,代码实现采用异步处理的思想,降低耦合,提高性能。
- **基于标准BSD socket之上开发**只要是兼容BSD socket的系统均可使用。
- **无缝衔接salof**它是一个同步异步日志输出框架在空闲时候输出对应的日志信息也可以将信息写入flash中保存方便调试。 - **无缝衔接salof**它是一个同步异步日志输出框架在空闲时候输出对应的日志信息也可以将信息写入flash中保存方便调试。
- **不对外产生依赖。** - **使用著名的 paho mqtt 库封包**
- **无其他依赖**。
## 在线代码生成工具
本项目拥有代码生成工具,只需要在线配置即可生成代码,极其简单易用,代码生成工具地址:[https://jiejietop.gitee.io/mqtt/index.html](https://jiejietop.gitee.io/mqtt/index.html)
![在线代码生成工具](png/mqtt-tool.png)
## 占用资源大小
总计占 **10857字节** 的ROM而RAM的开销则几乎只依赖动态内存在不使用TLS加密传输的情况下维持QOS0服务质量等级的通信动态内存大约仅需要**3694**字节这包括1024读缓冲区 + 1024写缓冲区 + 1024内部线程栈大小相对于其他MQTT客户端来说mqttclient需要的RAM资源开销极少。
| Code | RO Data | RW Data | ZI Data | Object Name |
| -- | -- | -- | -- | -- |
| 7118 | 791 | 0 | 0 | mqttclient.o |
| 546 | 0 | 0 | 0 | mqttconnectclient.o |
| 212 | 0 | 0 | 0 | mqttdeserializepublish.o |
| 476 | 0 | 4 | 0 | mqttpacket.o |
| 236 | 0 | 0 | 0 | mqttserializepublish.o |
| 310 | 0 | 0 | 0 | mqttsubscribeclient.o |
| 38 | 0 | 0 | 0 | mqttunsubscribeclient.o |
| 56 | 0 | 0 | 0 | nettype_tcp.o |
| 62 | 0 | 0 | 0 | network.o |
| 24 | 0 | 0 | 0 | platform_memory.o |
| 40 | 0 | 0 | 0 | platform_mutex.o |
| 344 | 0 | 0 | 0 | platform_net_socket.o |
| 94 | 0 | 0 | 0 | platform_thread.o |
| 70 | 0 | 0 | 0 | platform_timer.o |
| 246 | 0 | 4 | 0 | random.o |
| 62 | 0 | 0 | 0 | mqtt_list.o |
| - | - | - | - | - |
| 10066 | 791 | 8 | 0 | total |
## 整体框架 ## 整体框架
@@ -33,23 +93,45 @@
![整体框架](png/mqttclient.png) ![整体框架](png/mqttclient.png)
**目前已适配了Linux、TencentOS tiny平台除此之外TencentOS tiny的AT框架亦可以使用RAM消耗不足15K并且稳定性极好** - 在框架的最上方是**API**函数接口,实现了客户端的**申请、释放、设置参数、连接服务器、断开连接、订阅主题、取消订阅主题、发布消息**等函数接口。
- 使用了著名的**paho mqtt**库作为MQTT报文封包库。
- 采用异步处理的机制去管理所有的ack它在发送报文的时候不用等待服务器的应答只是记录下来在收到服务器的ack后取消这个记录**效率极高**而在发送mqtt报文QoS1/QoS2的时候没有收到服务器的应答时将**重发**该报文。
- 内部实现了一个**mqtt yield**线程,统一处理所有的内容,比如**超时的处理、ack报文的处理、收到来自服务器的publish报文**,此时会去调用回调函数告知用户收到的数据,**发布释放、发布完成报文的处理、心跳报文(保持活性),当与服务器断开连接时需要尝试重连、重新订阅主题,重新发送报文或者应答**等。
- 报文的处理,如**读写报文、解码mqtt报文、设置报文dup标记、销毁报文**等操作。
- **network**是网络组件,它可以**自动选择数据通道**,如果是加密方式则通过**tls加密**进行数据传输而tls可以选择mbedtls作为加密后端也可以是**tcp直连**方式最终都是通过tcp传输的。
- **platform**是平台抽象层,封装了不同系统的东西,比如**socke或者AT线程、时间、互斥锁、内存管理**,这些是与系统打交道的,也是跨平台必要的封装。
- 最右边的则是通用的内容,**list的处理、日志库、错误处理、软件随机数发生器**等。
## 支持的平台
**目前已实现了Linux、TencentOS tiny、FreeRTOS、RT-Thread平台已做成软件包名字为`kawaii-mqtt`除此之外TencentOS tiny的AT框架亦可以使用并且稳定性极好**
| 平台 | 代码位置 | | 平台 | 代码位置 |
| -------------- | -------- | | -------------- | -------- |
| Linux | [https://github.com/jiejieTop/mqttclient](https://github.com/jiejieTop/mqttclient) | | Linux | [https://github.com/jiejieTop/mqttclient](https://github.com/jiejieTop/mqttclient) |
| TencentOS tiny | [https://github.com/Tencent/TencentOS-tiny/tree/master/board/Fire_STM32F429](https://github.com/Tencent/TencentOS-tiny/tree/master/board/Fire_STM32F429) | | TencentOS tiny | [https://github.com/Tencent/TencentOS-tiny/tree/master/board/Fire_STM32F429](https://github.com/Tencent/TencentOS-tiny/tree/master/board/Fire_STM32F429) |
| TencentOS tiny AT 框架| [https://github.com/Tencent/TencentOS-tiny/tree/master/board/GoKit3_STM32F103C8T6](https://github.com/Tencent/TencentOS-tiny/tree/master/board/GoKit3_STM32F103C8T6) | | TencentOS tiny AT 框架 | [https://github.com/jiejieTop/gokit3-board-mqttclient](https://github.com/jiejieTop/gokit3-board-mqttclient) |
| RT-Thread | [https://github.com/jiejieTop/kawaii-mqtt](https://github.com/jiejieTop/kawaii-mqtt) |
| FreeRTOS | [https://github.com/jiejieTop/freertos-mqttclient](https://github.com/jiejieTop/freertos-mqttclient) |
## 版本 ## 版本
| 发布版本 | 描述 | | 发布版本 | 描述 |
| --- | --- | | --- | --- |
| [v1.0.0] | 初次发布,完成基本概念及其稳定性验证 | | [v1.0.0] | 初次发布,完成基本框架及其稳定性验证 |
| [v1.0.1] | 修复主动与服务器断开连接时的逻辑 | | [v1.0.1] | 修复主动与服务器断开连接时的逻辑处理 |
| [v1.0.2] | 添加新特性——拦截器修复一些小bug |
| [v1.0.3] | 避免造成全局污染修改了log、list相关函数的命名 |
| [v1.0.4] | 重新调整了network结构与mbedtls数据通道 |
| [v1.1.0] | 一个较大版本的更新重构部分代码优化MQTT处理的逻辑提升整体的稳定性支持多客户端支持设置遗嘱优化API接口增加多个云平台的测试代码与说明文档增加在线代码生成工具、在线裁剪配置工具 |
## 问题 ## 问题
@@ -57,573 +139,73 @@
## 版权和许可 ## 版权和许可
mqttclient [Apache License v2.0](https://github.com/jiejieTop/mqttclient/blob/master/LICENSE) 许可 提供 mqttclient 遵循 [Apache License v2.0](https://github.com/jiejieTop/mqttclient/blob/master/LICENSE) 开源协议。鼓励代码共享和尊重原作者的著作权,可以自由的使用、修改源代码,也可以将修改后的代码作为开源或闭源软件发布
简单谈谈关于开源协议的描述,[Apache License v2.0](https://github.com/jiejieTop/mqttclient/blob/master/LICENSE) 鼓励代码共享和尊重原作者的著作权,可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布(作为开源或闭源商业软件),**但本源码必须保留作者版权声明**。
## linux平台下测试使用 ## linux平台下测试使用
### 安装cmake ### 安装cmake
```bash ```bash
sudo apt-get install cmake sudo apt-get install cmake g++
``` ```
### 配置 ### 测试程序
`mqttclient/test/test.c`文件中修改以下内容:
```c
init_params.connect_params.network_params.network_ssl_params.ca_crt = test_ca_get(); /* CA证书 */
init_params.connect_params.network_params.addr = "xxxxxxx"; /* 服务器域名 */
init_params.connect_params.network_params.port = "8883"; /* 服务器端口号 */
init_params.connect_params.user_name = "xxxxxxx"; /* 用户名 */
init_params.connect_params.password = "xxxxxxx"; /* 密码 */
init_params.connect_params.client_id = "xxxxxxx"; /* 客户端id */
```
### mbedtls | 测试平台 | 位置 |
| -- | -- |
默认打开mbedtls。 | emqx我私人部署的服务器 | [./test/emqx/test.c](./test/emqx/test.c) |
| 百度天工 | [./test/baidu/test.c](./test/baidu/test.c) |
[salof](https://github.com/jiejieTop/salof) 全称是:`Synchronous Asynchronous Log Output Framework`同步异步日志输出框架它是一个同步异步日志输出框架在空闲时候输出对应的日志信息并且该库与mqttclient无缝衔接。 | onenet | [./test/onenet/test.c](./test/onenet/test.c) |
| 阿里云物联 | [./test/ali/test.c](./test/ali/test.c) |
**配置对应的日志输出级别:**
```c
#define BASE_LEVEL (0)
#define ASSERT_LEVEL (BASE_LEVEL + 1) /* 日志输出级别:断言级别(非常高优先级) */
#define ERR_LEVEL (ASSERT_LEVEL + 1) /* 日志输出级别:错误级别(高优先级) */
#define WARN_LEVEL (ERR_LEVEL + 1) /* 日志输出级别:警告级别(中优先级) */
#define INFO_LEVEL (WARN_LEVEL + 1) /* 日志输出级别:信息级别(低优先级) */
#define DEBUG_LEVEL (INFO_LEVEL + 1) /* 日志输出级别:调试级别(更低优先级) */
#define LOG_LEVEL WARN_LEVEL /* 日志输出级别 */
```
**日志其他选项:**
- 终端带颜色
- 时间戳
- 标签
### mqttclient的配置
配置mqtt等待应答列表的最大值对于qos1 qos2服务质量有要求的可以将其设置大一点当然也必须资源跟得上它主要是保证qos1 qos2的mqtt报文能准确到达服务器。
```c
#define MQTT_ACK_HANDLER_NUM_MAX 64
```
选择MQTT协议的版本默认为4表示使用MQTT 3.1.1版本而3则表示为MQTT 3.1版本。
```c
#define MQTT_VERSION 4 // 4 is mqtt 3.1.1
```
设置默认的保活时间它主要是保证MQTT客户端与服务器的保持活性连接单位为 秒 比如MQTT客户端与服务器100S没有发送数据了有没有接收到数据此时MQTT客户端会发送一个ping包确认一下这个会话是否存在如果收到服务器的应答那么说明这个会话还是存在的可以随时收发数据而如果不存在了就清除会话。
```c
#define MQTT_KEEP_ALIVE_INTERVAL 100 // unit: second
```
默认的命令超时它主要是用于socket读写超时在MQTT初始化时可以指定:
```
#define MQTT_DEFAULT_CMD_TIMEOUT 4000
```
默认主题的长度,主题是支持通配符的,如果主题太长则会被截断:
```c
#define MQTT_TOPIC_LEN_MAX 64
```
默认的算法数据缓冲区的大小如果要发送大量数据则修改大一些在MQTT初始化时可以指定
```c
#define MQTT_DEFAULT_BUF_SIZE 1024
```
线程相关的配置,如线程栈,线程优先级,线程时间片等:
在linux环境下可以是不需要理会这些参数的而在RTOS平台则需要配置如果不使用mbedtls线程栈2048字节已足够而使用mbedtls加密后需要配置4096字节以上。
```c
#define MQTT_THREAD_STACK_SIZE 2048 // 线程栈
#define MQTT_THREAD_PRIO 5 // 线程优先级
#define MQTT_THREAD_TICK 50 // 线程时间片
```
默认的重连时间间隔,当发生掉线时,会以这个时间间隔尝试重连:
```c
#define MQTT_RECONNECT_DEFAULT_DURATION 1000
```
其他不需要怎么配置的东西:
```c
#define MQTT_MAX_PACKET_ID (0xFFFF - 1) // mqtt报文id
#define MQTT_MAX_CMD_TIMEOUT 20000 //最大的命令超时参数
#define MQTT_MIN_CMD_TIMEOUT 1000 //最小的命令超时参数
```
> ps以上参数基本不需要怎么配置的直接用即可~
### 编译 & 运行 ### 编译 & 运行
```bash ```bash
./build.sh ./build.sh
```
运行`build.sh`脚本后会在 `./build/bin/`目录下生成可执行文件`mqtt-client`,直接运行即可。
## 设计思想
- 整体采用分层式设计,代码实现采用异步设计方式,降低耦合。
- 消息的处理使用回调的方式处理:用户指定`[订阅的主题]`与指定`[消息的处理函数]`
- 不对外产生依赖
## API
`mqttclient`拥有非常简洁的`api`接口
```c
int mqtt_keep_alive(mqtt_client_t* c);
int mqtt_init(mqtt_client_t* c, client_init_params_t* init);
int mqtt_release(mqtt_client_t* c);
int mqtt_connect(mqtt_client_t* c);
int mqtt_disconnect(mqtt_client_t* c);
int mqtt_subscribe(mqtt_client_t* c, const char* topic_filter, mqtt_qos_t qos, message_handler_t msg_handler);
int mqtt_unsubscribe(mqtt_client_t* c, const char* topic_filter);
int mqtt_publish(mqtt_client_t* c, const char* topic_filter, mqtt_message_t* msg);
int mqtt_yield(mqtt_client_t* c, int timeout_ms);
```
## 核心
**mqtt_client_t 结构**
```c
typedef struct mqtt_client {
unsigned short packet_id;
unsigned char ping_outstanding;
unsigned char ack_handler_number;
unsigned char *read_buf;
unsigned char *write_buf;
unsigned int cmd_timeout;
unsigned int read_buf_size;
unsigned int write_buf_size;
unsigned int reconnect_try_duration;
void *reconnect_date;
reconnect_handler_t reconnect_handler;
client_state_t client_state;
platform_mutex_t write_lock;
platform_mutex_t global_lock;
list_t msg_handler_list;
list_t ack_handler_list;
network_t *network;
platform_thread_t *thread;
platform_timer_t reconnect_timer;
platform_timer_t last_sent;
platform_timer_t last_received;
connect_params_t *connect_params;
} mqtt_client_t;
``` ```
该结构主要维护以下内容: 运行**build.sh**脚本后会在 **./build/bin/**目录下生成可执行文件**emqx**、**baidu**、**onenet**等多个平台的可执行程序,直接运行即可。
1. 读写数据缓冲区`read_buf、write_buf`
2. 命令超时时间`cmd_timeout`(主要是读写阻塞时间、等待响应的时间、重连等待时间)
3. 维护`ack`链表`ack_handler_list`,这是异步实现的核心,所有等待响应的报文都会被挂载到这个链表上
4. 维护消息处理列表`msg_handler_list`,这是`mqtt`协议必须实现的内容,所有来自服务器的`publish`报文都会被处理(前提是订阅了对应的消息)
5. 维护一个网卡接口`network`
6. 维护一个内部线程`thread`所有来自服务器的mqtt包都会在这里被处理
7. 两个定时器,分别是掉线重连定时器与保活定时器`reconnect_timer、last_sent、last_received`
8. 一些连接的参数`connect_params`
```bash
## mqttclient实现 ./build/bin/emqx
以下是整个框架的实现方式方便大家更容易理解mqttclient的代码与设计思想让大家能够修改源码与使用还可以提交pr或者issues开源的世界期待各位大神的参与感谢
除此之外以下代码的`记录机制`与其`超时处理机制`是非常好的编程思想,大家有兴趣一定要看源代码!
### 初始化
```c
int mqtt_init(mqtt_client_t* c, client_init_params_t* init)
``` ```
主要是配置`mqtt_client_t`结构的相关信息,如果没有指定初始化参数,则系统会提供默认的参数。 ### 编译成动态库libmqttclient.so
但连接部分的参数则必须指定:
```c ```bash
init_params.connect_params.network_params.addr = "[你的mqtt服务器IP地址或者是域名]"; ./make-libmqttclient.sh
init_params.connect_params.network_params.port = 1883; //端口号
init_params.connect_params.user_name = "jiejietop";
init_params.connect_params.password = "123456";
init_params.connect_params.client_id = "clientid";
mqtt_init(&client, &init_params);
``` ```
### 连接服务器 运行`make-libmqttclient.sh`脚本后会在 `./libmqttclient/lib`目录下生成一个动态库文件`libmqttclient.so`,并安装到系统的`/usr/lib `目录下,相关头文件已经拷贝到`./libmqttclient/include`目录下,将其拷贝到你的工程中即可,编译应用程序的时候只需要链接动态库即可`-lmqttclient -lpthread`,动态库的配置文件是根据`./test/mqtt_config.h`配置的。
```c 如果你是用交叉编译器的话则应该根据你使用的编译器导出对应的环境变量此处使用的交叉编译器是arm-linux-gnueabihf-gcc同时你也必须将动态库文件`libmqttclient.so`拷贝到你的嵌入式系统的`/usr/lib `目录下:
int mqtt_connect(mqtt_client_t* c);
```bash
export CROSS_COMPILE=arm-linux-gnueabihf-
``` ```
参数只有 `mqtt_client_t` 类型的指针,字符串类型的`主题`(支持通配符"#" "+"),主题的`服务质量`,以及收到报文的`处理函数`,如不指定则有默认处理函数。连接服务器则是使用非异步的方式设计,因为必须等待连接上服务器才能进行下一步操作。 如若需要卸载**libmqttclient.so**,执行以下命令即可:
过程如下: ```bash
1. 调用底层的连接函数连接上服务器: ./make-libmqttclient.sh remove
```c
c->network->connect(c->network);
``` ```
2. 序列化`mqtt``CONNECT`报文并且发送 ## 学习更多
```c 请看文档:
MQTTSerialize_connect(c->write_buf, c->write_buf_size, &connect_data)
mqtt_send_packet(c, len, &connect_timer)
```
3. 等待来自服务器的`CONNACK`报文 - [MQTT协议简介](./docs/mqtt-introduction.md)
```c - [MQTT协议通信过程](./docs/mqtt-communication.md)
mqtt_wait_packet(c, CONNACK, &connect_timer)
```
4. 连接成功后创建一个内部线程`mqtt_yield_thread`,并在合适的时候启动它: - [mqttclient代码生成工具](./docs/mqtt-tool.md)
```c - [mqttclient配置及裁剪工具](./docs/mqtt-config.md)
platform_thread_init("mqtt_yield_thread", mqtt_yield_thread, c, MQTT_THREAD_STACK_SIZE, MQTT_THREAD_PRIO, MQTT_THREAD_TICK)
if (NULL != c->thread) { - [mqttclient设计与实现方式](./docs/mqtt-design.md)
mqtt_set_client_state(c, CLIENT_STATE_CONNECTED);
platform_thread_startup(c->thread);
platform_thread_start(c->thread); /* start run mqtt thread */
}
```
5. 而对于重连来说则不会重新创建线程,直接改变客户端状态为连接状态即可: - [mqttclient连接到百度天工物接入](./docs/mqtt-baidu.md)
```c - [mqttclient连接到OneNET云平台](./docs/mqtt-onenet.md)
mqtt_set_client_state(c, CLIENT_STATE_CONNECTED);
```
### 订阅报文 - [mqttclient连接到阿里云物联网平台](./docs/mqtt-aliyun.md)
```c
int mqtt_subscribe(mqtt_client_t* c, const char* topic_filter, mqtt_qos_t qos, message_handler_t handler)
```
订阅报文使用异步设计来实现的:
过程如下:
1. 序列化订阅报文并且发送给服务器
```c
MQTTSerialize_subscribe(c->write_buf, c->write_buf_size, 0, mqtt_get_next_packet_id(c), 1, &topic, (int*)&qos)
mqtt_send_packet(c, len, &timer)
```
2. 创建对应的消息处理节点,这个消息节点在收到服务器的`SUBACK`订阅应答报文后会挂载到消息处理列表`msg_handler_list`
```c
mqtt_msg_handler_create(topic_filter, qos, handler)
```
3. 在发送了报文给服务器那就要等待服务器的响应了,先记录这个等待`SUBACK`
```c
mqtt_ack_list_record(c, SUBACK, mqtt_get_next_packet_id(c), len, msg_handler)
```
### 取消订阅
与订阅报文的逻辑基本差不多的~
1. 序列化订阅报文并且发送给服务器
```c
MQTTSerialize_unsubscribe(c->write_buf, c->write_buf_size, 0, packet_id, 1, &topic)
mqtt_send_packet(c, len, &timer)
```
2. 创建对应的消息处理节点,这个消息节点在收到服务器的`UNSUBACK`取消订阅应答报文后将消息处理列表`msg_handler_list`上的已经订阅的主题消息节点销毁
```c
mqtt_msg_handler_create((const char*)topic_filter, QOS0, NULL)
```
3. 在发送了报文给服务器那就要等待服务器的响应了,先记录这个等待`UNSUBACK`
```c
mqtt_ack_list_record(c, UNSUBACK, packet_id, len, msg_handler)
```
### 发布报文
```c
int mqtt_publish(mqtt_client_t* c, const char* topic_filter, mqtt_message_t* msg)
```
参数只有 `mqtt_client_t` 类型的指针,字符串类型的`主题`(支持通配符),要发布的消息(包括`服务质量``消息主体`)。
```c
mqtt_message_t msg;
msg.qos = 2;
msg.payload = (void *) buf;
mqtt_publish(&client, "testtopic1", &msg);
```
核心思想都差不多,过程如下:
1. 先序列化发布报文,然后发送到服务器
```c
MQTTSerialize_publish(c->write_buf, c->write_buf_size, 0, msg->qos, msg->retained, msg->id,
topic, (unsigned char*)msg->payload, msg->payloadlen);
mqtt_send_packet(c, len, &timer)
```
2. 对于QOS0的逻辑不做任何处理对于QOS1和QOS2的报文则需要记录下来在没收到服务器应答的时候进行重发
```c
if (QOS1 == msg->qos) {
rc = mqtt_ack_list_record(c, PUBACK, mqtt_get_next_packet_id(c), len, NULL);
} else if (QOS2 == msg->qos) {
rc = mqtt_ack_list_record(c, PUBREC, mqtt_get_next_packet_id(c), len, NULL);
}
```
3. 还有非常重要的一点重发报文的MQTT报文头部需要设置DUP标志位这是MQTT协议的标准因此在重发的时候作者直接操作了报文的DUP标志位因为修改DUP标志位的函数我没有从MQTT库中找到所以我封装了一个函数这与LwIP中的交叉存取思想是一个道理它假设我知道MQTT报文的所有操作所以我可以操作它这样子可以提高很多效率
```c
mqtt_set_publish_dup(c,1); /* may resend this data, set the udp flag in advance */
```
### 内部线程
```c
static void mqtt_yield_thread(void *arg)
```
主要是对`mqtt_yield`函数的返回值做处理,比如在`disconnect`的时候销毁这个线程。
### 核心的处理函数
1. 数据包的处理`mqtt_packet_handle`
```c
static int mqtt_packet_handle(mqtt_client_t* c, platform_timer_t* timer)
```
对不同的包使用不一样的处理:
```c
switch (packet_type) {
case 0: /* timed out reading packet */
break;
case CONNACK:
break;
case PUBACK:
case PUBCOMP:
rc = mqtt_puback_and_pubcomp_packet_handle(c, timer);
break;
case SUBACK:
rc = mqtt_suback_packet_handle(c, timer);
break;
case UNSUBACK:
rc = mqtt_unsuback_packet_handle(c, timer);
break;
case PUBLISH:
rc = mqtt_publish_packet_handle(c, timer);
break;
case PUBREC:
case PUBREL:
rc = mqtt_pubrec_and_pubrel_packet_handle(c, timer);
break;
case PINGRESP:
c->ping_outstanding = 0;
break;
default:
goto exit;
}
```
并且做保活的处理:
```c
mqtt_keep_alive(c)
```
当发生超时后
```c
if (platform_timer_is_expired(&c->last_sent) || platform_timer_is_expired(&c->last_received))
```
序列号一个心跳包并且发送给服务器
```c
MQTTSerialize_pingreq(c->write_buf, c->write_buf_size);
mqtt_send_packet(c, len, &timer);
```
当再次发生超时后,表示与服务器的连接已断开,需要重连的操作,设置客户端状态为断开连接
```c
mqtt_set_client_state(c, CLIENT_STATE_DISCONNECTED);
```
2. `ack`链表的扫描当收到服务器的报文时对ack列表进行扫描操作
```c
mqtt_ack_list_scan(c);
```
当超时后就销毁ack链表节点
```c
mqtt_ack_handler_destroy(ack_handler);
```
当然下面这几种报文则需要重发操作:(`PUBACK 、PUBREC、 PUBREL 、PUBCOMP`保证QOS1 QOS2的服务质量
```c
if ((ack_handler->type == PUBACK) || (ack_handler->type == PUBREC) || (ack_handler->type == PUBREL) || (ack_handler->type == PUBCOMP))
mqtt_ack_handler_resend(c, ack_handler);
```
3. 保持活性的时间过去了,可能掉线了,需要重连操作
```c
mqtt_try_reconnect(c);
```
重连成功后尝试重新订阅报文,保证恢复原始状态~
```c
mqtt_try_resubscribe(c)
```
### 发布应答与发布完成报文的处理
```c
static int mqtt_puback_and_pubcomp_packet_handle(mqtt_client_t *c, platform_timer_t *timer)
```
1. 反序列化报文
```c
MQTTDeserialize_ack(&packet_type, &dup, &packet_id, c->read_buf, c->read_buf_size)
```
2. 取消对应的ack记录
```c
mqtt_ack_list_unrecord(c, packet_type, packet_id, NULL);
```
### 订阅应答报文的处理
```c
static int mqtt_suback_packet_handle(mqtt_client_t *c, platform_timer_t *timer)
```
1. 反序列化报文
```c
MQTTDeserialize_suback(&packet_id, 1, &count, (int*)&granted_qos, c->read_buf, c->read_buf_size)
```
2. 取消对应的ack记录
```c
mqtt_ack_list_unrecord(c, packet_type, packet_id, NULL);
```
3. 安装对应的订阅消息处理函数,如果是已存在的则不会安装
```c
mqtt_msg_handlers_install(c, msg_handler);
```
### 取消订阅应答报文的处理
```c
static int mqtt_unsuback_packet_handle(mqtt_client_t *c, platform_timer_t *timer)
```
1. 反序列化报文
```c
MQTTDeserialize_unsuback(&packet_id, c->read_buf, c->read_buf_size)
```
2. 取消对应的ack记录并且获取到已经订阅的消息处理节点
```c
mqtt_ack_list_unrecord(c, UNSUBACK, packet_id, &msg_handler)
```
3. 销毁对应的订阅消息处理函数
```c
mqtt_msg_handler_destory(msg_handler);
```
### 来自服务器的发布报文的处理
```c
static int mqtt_publish_packet_handle(mqtt_client_t *c, platform_timer_t *timer)
```
1. 反序列化报文
```c
MQTTDeserialize_publish(&msg.dup, &qos, &msg.retained, &msg.id, &topic_name,
(unsigned char**)&msg.payload, (int*)&msg.payloadlen, c->read_buf, c->read_buf_size)
```
2. 对于QOS0、QOS1的报文直接去处理消息
```c
mqtt_deliver_message(c, &topic_name, &msg);
```
3. 对于QOS1的报文还需要发送一个`PUBACK`应答报文给服务器
```c
MQTTSerialize_ack(c->write_buf, c->write_buf_size, PUBACK, 0, msg.id);
```
4. 而对于QOS2的报文则需要发送`PUBREC`报文给服务器,除此之外还需要记录`PUBREL`到ack链表上等待服务器的发布释放报文最后再去处理这个消息
```c
MQTTSerialize_ack(c->write_buf, c->write_buf_size, PUBREC, 0, msg.id);
mqtt_ack_list_record(c, PUBREL, msg.id + 1, len, NULL)
mqtt_deliver_message(c, &topic_name, &msg);
```
> 说明一旦注册到ack列表上的报文当具有重复的报文是不会重新被注册的它会通过`mqtt_ack_list_node_is_exist`函数判断这个节点是否存在主要是依赖等待响应的消息类型与msgid。
### 发布收到与发布释放报文的处理
```c
static int mqtt_pubrec_and_pubrel_packet_handle(mqtt_client_t *c, platform_timer_t *timer)
```
1. 反序列化报文
```c
MQTTDeserialize_ack(&packet_type, &dup, &packet_id, c->read_buf, c->read_buf_size)
```
2. 产生一个对应的应答报文
```c
mqtt_publish_ack_packet(c, packet_id, packet_type);
```
3. 取消对应的ack记录
```c
mqtt_ack_list_unrecord(c, UNSUBACK, packet_id, &msg_handler)
```

View File

@@ -0,0 +1,209 @@
[![](https://img.shields.io/github/v/tag/jiejietop/mqttclient?color=brightgreen&label=version)](https://github.com/jiejieTop/mqttclient/releases)
[![license](https://img.shields.io/badge/license-Apache-blue.svg)](https://github.com/jiejieTop/mqttclient/blob/master/LICENSE)
![](https://img.shields.io/github/forks/jiejieTop/mqttclient)
![](https://img.shields.io/github/stars/jiejieTop/mqttclient)
![](https://img.shields.io/badge/platform-Linux|Windows|Mac|Embedded-orange.svg)
[中文说明](README_CN.md)
# mqttclient
**A high-performance, high-stability, cross-platform MQTT client**
A high-performance, high-stability, cross-platform MQTT client, developed based on the socket API, can be used on embedded devices (FreeRTOS/LiteOS/RT-Thread/TencentOS tiny), Linux, Windows, Mac, and has a very concise The API interface realizes the quality of service of QOS2 with very few resources, and seamlessly connects the mbedtls encryption library.
## Advantage:
- **Extremely high stability**: Whether it is **drop and reconnect**, **packet loss and retransmission**, it is **strictly abide by the MQTT protocol standard**, in addition to The test of **large data volume** is very stable whether it is receiving or sending, and the **high frequency** test is also very stable.
- **Lightweight**: The entire code project is extremely simple. Without mbedtls, it takes up very few resources. The author used the esp8266 module to communicate with the cloud. The entire project code consumes less than 15k of RAM.
- **Support mbedtls encrypted transmission**, make the network transmission more secure, and the interface layer does not require users to care, no matter whether it is encrypted or not, mqttclient is **fixed** for the API interface provided by the user, which is very compatible A set of codes on behalf of the application layer can be transmitted with or without encryption.
- **Supports multiple clients**, compatible with multiple clients running at the same time, one device connected to multiple servers.
- **Supports synchronous and asynchronous processing**, applications need not block and wait to waste CPU resources.
- **Support interceptor configuration**, on some platforms, the client will automatically subscribe to the system theme by default, and the theme from the server changes every time. In this case, you need to use an interceptor to intercept and separate the theme and data Information and deliver it to users, greatly improving flexibility.
- **With online code generation tool**, the code can be generated with extremely simple configuration, address: [https://jiejietop.gitee.io/mqtt/index.html](https://jiejietop.gitee.io/mqtt/index.html)
- **Has a very simple API interface**, in general, mqttclient configuration has default values, basically can be used without configuration, can also be arbitrarily configured, the configuration has robustness detection, so designed The API interface is also very simple.
- **Multifunctional parameters can be configured and tailored**, reconnect time interval, heartbeat period, maximum number of subscriptions, command timeout, read and write buffer size, interceptor processing, etc. Parameters can be tailored and configurable to meet the needs of developers Complex and simple to use in various development environments.
- **Support automatic re-subscription of topics**, after automatic reconnection to ensure that the topics will not be lost.
- **Support theme wildcards ""#", "+"`**.
- **Subscribed topics are completely separated from message processing**, making programming logic easier and easier to use, users dont have to deal with intricate logical relationships.
- **The keep-alive processing mechanism has been implemented in mqttclient**, without the user having to deal with the psychological experience, the user only needs to concentrate on the application function.
- **Has a very good design**, designed the **recording mechanism** with very few resources, and retransmits the message when it is lost to ensure that the qos1 and qos2 service quality levels guarantee its service quality.
- **There are very good code styles and ideas**: The whole code adopts a layered design, and the code implementation adopts the idea of asynchronous processing to reduce coupling and improve performance.
- **Developed on top of standard BSD socket**, as long as it is compatible with BSD socket system.
- **Seamless connection of salof**: It is a synchronous and asynchronous log output framework. It outputs the corresponding log information when it is idle, and it can also write the information into flash to save it, which is convenient for debugging.
- **Use the famous paho mqtt library package**.
- **No other dependencies**.
## Online code generation tool
This project has a code generation tool that only requires online configuration to generate code, which is extremely simple and easy to use. The code generation tool address is: [https://jiejietop.gitee.io/mqtt/index.html](https://jiejietop.gitee.io/mqtt/index.html)
![Online code generation tool](png/mqtt-tool.png)
## occupied resource size
A total of **10857 bytes** of ROM, and the overhead of RAM is almost only dependent on dynamic memory. Without using TLS encrypted transmission, the communication dynamic memory that maintains the QOS0 quality of service level requires only about **3694** bytes. Including 1024 read buffer + 1024 write buffer + 1024 internal thread stack size, compared with other MQTT clients, mqttclient requires very little RAM resource overhead.
| Code | RO Data | RW Data | ZI Data | Object Name |
| -- | -- | -- | -- | -- |
| 7118 | 791 | 0 | 0 | mqttclient.o |
| 546 | 0 | 0 | 0 | mqttconnectclient.o |
| 212 | 0 | 0 | 0 | mqttdeserializepublish.o |
| 476 | 0 | 4 | 0 | mqttpacket.o |
| 236 | 0 | 0 | 0 | mqttserializepublish.o |
| 310 | 0 | 0 | 0 | mqttsubscribeclient.o |
| 38 | 0 | 0 | 0 | mqttunsubscribeclient.o |
| 56 | 0 | 0 | 0 | nettype_tcp.o |
| 62 | 0 | 0 | 0 | network.o |
| 24 | 0 | 0 | 0 | platform_memory.o |
| 40 | 0 | 0 | 0 | platform_mutex.o |
| 344 | 0 | 0 | 0 | platform_net_socket.o |
| 94 | 0 | 0 | 0 | platform_thread.o |
| 70 | 0 | 0 | 0 | platform_timer.o |
| 246 | 0 | 4 | 0 | random.o |
| 62 | 0 | 0 | 0 | mqtt_list.o |
| - | - | - | - | - |
| 10066 | 791 | 8 | 0 | total |
## Overall framework
Has a very clear layered framework.
![Overall Frame](png/mqttclient.png)
- At the top of the framework is the **API** function interface, which implements the client's **application, release, set parameters, connect to the server, disconnect, subscribe topic, unsubscribe topic, publish message** and other functional interfaces.
- The famous **paho mqtt** library is used as the MQTT message packet library.
- Asynchronous processing mechanism is used to manage all the acks. It does not need to wait for the server's response when sending the message, but only records it. After receiving the server's ack, cancel this record, **very efficient**; and When the mqtt message (QoS1/QoS2) is sent and no response is received from the server, the message will be **retransmitted**.
- An **mqtt yield** thread is implemented internally to handle all content in a unified manner, such as **timeout processing, ack message processing, and receiving publish message from the server**, at this time the callback function will be called Inform the user of the data received, **post release, post completion message processing, heartbeat message (keep alive), when disconnected from the server, you need to try to reconnect, resubscribe to the topic, resend the message or reply* *Wait.
- Message processing, such as **reading and writing messages, decoding mqtt messages, setting messages (dup flag), destroying messages** and other operations.
- **network** is a network component, which can **automatically select a data channel**, if it is an encryption method, **tls encryption** is used for data transmission, and tls can choose mbedtls as the encryption backend; it can also be The **tcp direct connection** method is ultimately transmitted via tcp.
- **platform** is a platform abstraction layer that encapsulates things from different systems, such as socke or AT, thread, time, mutex, memory management**, these are dealing with the system and are also necessary for cross-platform Package.
- On the far right is the general content, **list processing, log library, error handling, software random number generator**, etc.
## Supported platforms
**At present, Linux, TencentOS tiny, FreeRTOS, RT-Thread platforms have been implemented (software package is named kawaii-mqtt`), in addition to TencentOS tiny AT framework can also be used, and the stability is excellent!**
| Platform | Code Location |
| -------------- | -------- |
| Linux | [https://github.com/jiejieTop/mqttclient](https://github.com/jiejieTop/mqttclient) |
| TencentOS tiny | [https://github.com/Tencent/TencentOS-tiny/tree/master/board/Fire_STM32F429](https://github.com/Tencent/TencentOS-tiny/tree/master/board/Fire_STM32F429) |
| TencentOS tiny AT framework | [https://github.com/jiejieTop/gokit3-board-mqttclient](https://github.com/jiejieTop/gokit3-board-mqttclient) |
| RT-Thread | [https://github.com/jiejieTop/kawaii-mqtt](https://github.com/jiejieTop/kawaii-mqtt) |
| FreeRTOS | [https://github.com/jiejieTop/freertos-mqttclient](https://github.com/jiejieTop/freertos-mqttclient) |
## Version
| Release Version | Description |
| --- | --- |
| [v1.0.0] | Initial release, complete basic framework and stability verification |
| [v1.0.1] | Fix the logical processing when actively disconnecting from the server |
| [v1.0.2] | Add a new feature-interceptor, fix some small bugs |
| [v1.0.3] | To avoid global pollution, modify the naming of log and list related functions |
| [v1.0.4] | Network structure and mbedtls data channel readjusted |
| [v1.1.0] | A larger version of the update, refactoring part of the code, optimizing the logic of MQTT processing, improving the overall stability, supporting multiple clients, supporting setting the will, optimizing the API interface, and adding multiple cloud platforms Test code and documentation, add online code generation tool, online cutting configuration tool |
## question
Welcome to submit issues and bug reports in the form of [GitHub Issues](https://github.com/jiejieTop/mqttclient/issues)
## Copyright and License
mqttclient follows the [Apache License v2.0](https://github.com/jiejieTop/mqttclient/blob/master/LICENSE) open source agreement. Encourage code sharing and respect the copyright of the original author. You can freely use and modify the source code, or you can publish the modified code as open source or closed source software.
## Test and use under Linux platform
### Install cmake:
```bash
sudo apt-get install cmake g++
```
### test program
| Test Platform | Location |
| - | - |
| emqx (my privately deployed server) | [./test/emqx/test.c](./test/emqx/test.c) |
| Baidu Tiangong | [./test/baidu/test.c](./test/baidu/test.c) |
| onenet | [./test/onenet/test.c](./test/onenet/test.c) |
| Alibaba Cloud Internet of Things | [./test/ali/test.c](./test/ali/test.c) |
### Compile & Run
```bash
./build.sh
```
After running the **build.sh** script, the executable files **emqx**, **baidu**, **onenet** and other platforms will be generated under the **./build/bin/** directory Executable programs can be run directly.
```bash
./build/bin/emqx
```
### Compile into a dynamic library libmqttclient.so
```bash
./make-libmqttclient.sh
```
After running the `make-libmqttclient.sh` script, a dynamic library file `libmqttclient.so` will be generated in the `./libmqttclient/lib` directory, and installed into the systems `/usr/lib` directory, the relevant header files have been Copy to the `./libmqttclient/include` directory and copy it to your project. You only need to link the dynamic library when compiling the application. `-lmqttclient -lpthread`, the configuration file of the dynamic library is based on` ./test/mqtt_config.h` configuration.
If you are using a cross-compiler, you should export the corresponding environment variables according to the compiler you are using (the cross-compiler used here is arm-linux-gnueabihf-gcc), and you must also set the dynamic library file `libmqttclient .so` is copied to the `/usr/lib` directory of your embedded system:
```bash
export CROSS_COMPILE=arm-linux-gnueabihf-
```
If you need to uninstall **libmqttclient.so**, execute the following command:
```bash
./make-libmqttclient.sh remove
```
## Learn more
Please see the documentation:
- [MQTT Protocol Introduction](./docs/mqtt-introduction.md)
- [MQTT protocol communication process](./docs/mqtt-communication.md)
- [mqttclient code generation tool](./docs/mqtt-tool.md)
- [mqttclient configuration and cutting tool](./docs/mqtt-config.md)
- [mqttclient design and implementation](./docs/mqtt-design.md)
- [mqttclient connects to Baidu Tiangongwu Access](./docs/mqtt-baidu.md)
- [mqttclient connects to OneNET cloud platform](./docs/mqtt-onenet.md)
- [mqttclient connects to Alibaba Cloud IoT platform](./docs/mqtt-aliyun.md)

View File

@@ -2,5 +2,34 @@
mkdir -p build build/bin build/lib mkdir -p build build/bin build/lib
cd build cd build
cmake ..
if [ " $1" == " " ]; then
compiler="gcc"
elif [ $1 == "--help" -o $1 == "-help" -o $1 == "--h" -o $1 == "-h" ]; then
echo "usage: $0 [compiler] [compiler path]"
echo " compiler: specify the compiler you are using, default: gcc"
echo " compiler path: specify the compiler path you are using"
echo " eg:"
echo " ./build.sh"
echo " ./build.sh arm-linux-gnueabihf-gcc"
echo " ./build.sh /usr/bin/arm-linux-gnueabihf-gcc"
echo " ./build.sh arm-linux-gnueabihf-gcc /usr/bin"
exit
else
if [ " $2" == " " ]; then
compiler=$1
else
compiler=$2/$1
fi
fi
path=$(which $compiler)
if [ " $path" == " " ]; then
echo -e "\033[31mNo $compiler compiler found in the system\033[0m"
exit
fi
cmake .. "-DCMAKE_C_COMPILER=$path"
make make

View File

@@ -0,0 +1,21 @@
set(SUBDIRS "log")
aux_source_directory(. DIR_SRCS)
string(REGEX REPLACE ".*/(.*)" "\\1" LIB_NAME ${CMAKE_CURRENT_SOURCE_DIR})
if (DIR_SRCS)
foreach(libname ${LIBNAMES})
if (${LIB_NAME} STREQUAL ${libname})
add_library(${libname} ${CMAKE_LIB_TYPE} ${DIR_SRCS})
endif()
endforeach()
else()
message(WARNING "not find is src file!")
endif()
foreach(subdir ${SUBDIRS})
add_subdirectory(${subdir})
endforeach()

View File

@@ -1,72 +0,0 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-11 22:46:33
* @LastEditTime : 2020-01-05 17:01:51
* @Description: the following code references TencentOS tiny, please keep the author information and source code according to the license.
*/
# include "list.h"
static void _list_add(list_t *node, list_t *prev, list_t *next)
{
next->prev = node;
node->next = next;
node->prev = prev;
prev->next = node;
}
static void _list_del(list_t *prev, list_t *next)
{
next->prev = prev;
prev->next = next;
}
static void _list_del_entry(list_t *entry)
{
_list_del(entry->prev, entry->next);
}
void list_init(list_t *list)
{
list->next = list;
list->prev = list;
}
void list_add(list_t *node, list_t *list)
{
_list_add(node, list, list->next);
}
void list_add_tail(list_t *node, list_t *list)
{
_list_add(node, list->prev, list);
}
void list_del(list_t *entry)
{
_list_del(entry->prev, entry->next);
}
void list_del_init(list_t *entry)
{
_list_del_entry(entry);
list_init(entry);
}
void list_move(list_t *node, list_t *list)
{
_list_del_entry(node);
list_add(node, list);
}
void list_move_tail(list_t *node, list_t *list)
{
_list_del_entry(node);
list_add_tail(node, list);
}
int list_is_empty(list_t *list)
{
return list->next == list;
}

View File

@@ -1,72 +0,0 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-27 03:25:58
* @LastEditTime: 2020-02-25 05:42:32
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#ifndef _LOG_H_
#define _LOG_H_
#include "mqtt_defconfig.h"
#ifdef LOG_IS_SALOF
#include "salof.h"
#define LOG_D(fmt, ...) LOG_DEBUG(fmt, ##__VA_ARGS__)
#define LOG_I(fmt, ...) LOG_INFO(fmt, ##__VA_ARGS__)
#define LOG_W(fmt, ...) LOG_WARN(fmt, ##__VA_ARGS__)
#define LOG_E(fmt, ...) LOG_ERR(fmt, ##__VA_ARGS__)
#define log_init salof_init
#else
#include <stdio.h>
#define BASE_LEVEL (0)
#define ASSERT_LEVEL (BASE_LEVEL + 1)
#define ERR_LEVEL (ASSERT_LEVEL + 1)
#define WARN_LEVEL (ERR_LEVEL + 1)
#define INFO_LEVEL (WARN_LEVEL + 1)
#define DEBUG_LEVEL (INFO_LEVEL + 1)
#if LOG_LEVEL < DEBUG_LEVEL
#define LOG_D(fmt, ...)
#else
#define LOG_D(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
#endif
#if LOG_LEVEL < INFO_LEVEL
#define LOG_I(fmt, ...)
#else
#define LOG_I(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
#endif
#if LOG_LEVEL < WARN_LEVEL
#define LOG_W(fmt, ...)
#else
#define LOG_W(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
#endif
#if LOG_LEVEL < ERR_LEVEL
#define LOG_E(fmt, ...)
#else
#define LOG_E(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
#endif
#if LOG_LEVEL < ASSERT_LEVEL
#define LOG_ASSERT(fmt, ...)
#define ASSERT(x)
#else
#define LOG_ASSERT(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
#define ASSERT(x) if((x)==0) LOG_ASSERT("%s, %d\n",__FILE__,__LINE__)
#endif
#if LOG_LEVEL < BASE_LEVEL
#define LOG(fmt, ...)
#else
#define LOG(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
#endif
#define log_init()
#endif
#endif /* _LOG_H_ */

View File

@@ -0,0 +1,21 @@
cmake_minimum_required (VERSION 2.8)
set(INCDIRS ${CMAKE_CURRENT_SOURCE_DIR})
set(SUBDIRS "arch")
set(LIBNAMES "arch" "salof")
set(OUTDIRS "build")
aux_source_directory(. LOG_DIR_SRCS)
add_library("salof" ${CMAKE_LIB_TYPE} ${LOG_DIR_SRCS})
target_link_libraries("salof" "arch")
foreach(incdir ${INCDIRS})
include_directories(${incdir})
endforeach()
foreach(subdir ${SUBDIRS})
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${subdir})
endforeach()
link_directories(${LIBRARY_OUTPUT_PATH})

View File

@@ -0,0 +1,7 @@
set(SUBDIRS "linux")
foreach(subdir ${SUBDIRS})
add_subdirectory(${subdir})
endforeach()

View File

@@ -7,17 +7,13 @@
*/ */
#include "salof_defconfig.h" #include "salof_defconfig.h"
#ifdef USE_LOG #ifdef SALOF_USING_LOG
void *salof_alloc(unsigned int size) void *salof_alloc(unsigned int size)
{ {
return tos_mmheap_alloc(size); return tos_mmheap_alloc(size);
} }
void *salof_calloc(size_t num, size_t size)
{
return tos_mmheap_calloc(num, size);
}
void salof_free(void *mem) void salof_free(void *mem)
{ {
@@ -34,7 +30,7 @@ salof_tcb salof_task_create(const char *name,
salof_tcb task; salof_tcb task;
k_err_t err; k_err_t err;
k_stack_t *task_stack; k_stack_t *task_stack;
task = salof_calloc(1, sizeof(k_task_t)); task = salof_alloc(sizeof(k_task_t));
task_stack = salof_alloc(stack_size); task_stack = salof_alloc(stack_size);
err = tos_task_create(task, err = tos_task_create(task,
(char*)name, (char*)name,

View File

@@ -1,93 +0,0 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-25 23:56:34
* @LastEditTime : 2020-01-18 13:50:21
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#ifndef _SALOF_CONFIG_H_
#define _SALOF_CONFIG_H_
#define USE_RTT 0
#define USE_UCOSIII 1
#define USE_FREERTOS 2
#define USE_TENCENTOS 3
#define USE_LINUX 4
#define USE_LOG (1U)
#define USE_SALOF (1U)
#define SALOF_OS USE_TENCENTOS
#define USE_IDLE_HOOK (0U)
#define LOG_LEVEL DEBUG_LEVEL //WARN_LEVEL DEBUG_LEVEL
#define LOG_COLOR (0U)
#define LOG_TS (0U)
#define LOG_TAR (0U)
#if USE_SALOF
#define SALOF_BUFF_SIZE (512U)
#define SALOF_FIFO_SIZE (1024*2U)
#define SALOF_TASK_STACK_SIZE (1024U)
#define SALOF_TASK_TICK (20U)
#endif
#if !defined(SALOF_OS)
#error "SALOF_OS isn't defined in 'cmb_cfg.h'"
#endif
#if (SALOF_OS == USE_FREERTOS)
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#define salof_mutex SemaphoreHandle_t
#define salof_tcb TaskHandle_t
#define salof_sem salof_mutex
#if USE_IDLE_HOOK
#define salof_handler vApplicationIdleHook
#endif
#define SALOF_TASK_PRIO (0U)
#elif (SALOF_OS == USE_TENCENTOS)
#include "tos_k.h"
#define salof_mutex k_mutex_t*
#define salof_sem k_sem_t*
#define salof_tcb k_task_t*
#define SALOF_TASK_PRIO (TOS_CFG_TASK_PRIO_MAX - 2u)
#undef USE_IDLE_HOOK
#elif (SALOF_OS == USE_LINUX)
#include "pthread.h"
#include "memory.h"
#include <semaphore.h>
#include <stdio.h>
#define salof_mutex pthread_mutex_t*
#define salof_sem sem_t*
#define salof_tcb pthread_t*
#define SALOF_TASK_PRIO (0U)
#undef USE_IDLE_HOOK
#else
#error "not supported OS type"
#endif
void *salof_alloc(unsigned int size);
void salof_free(void *mem);
salof_tcb salof_task_create(const char *name,
void (*task_entry)(void *param),
void * const param,
unsigned int stack_size,
unsigned int priority,
unsigned int tick);
salof_mutex salof_mutex_create(void);
void salof_mutex_delete(salof_mutex mutex);
int salof_mutex_pend(salof_mutex mutex, unsigned int timeout);
int salof_mutex_post(salof_mutex mutex);
salof_sem salof_sem_create(void);
void salof_sem_delete(salof_sem sem);
int salof_sem_pend(salof_sem sem, unsigned int timeout);
int salof_sem_post(salof_sem sem);
unsigned int salof_get_tick(void);
char *salof_get_task_name(void);
extern int send_buff(char *buf, int len);
#endif // !_SALOF_CONFIG_H_

View File

@@ -1,7 +1,7 @@
#include "fifo.h" #include "fifo.h"
#include <string.h> #include <string.h>
#ifdef USE_LOG #ifdef SALOF_USING_LOG
static unsigned int _flbs(unsigned int x) /* find last bit set*/ static unsigned int _flbs(unsigned int x) /* find last bit set*/
{ {
@@ -32,25 +32,25 @@ static unsigned int _flbs(unsigned int x) /* find last bit set*/
return r; return r;
} }
static unsigned int _fifo_align(unsigned int x) static unsigned int _salof_fifo_align(unsigned int x)
{ {
return (1 << (_flbs(x-1)-1)); //memory down alignment return (1 << (_flbs(x-1)-1)); //memory down alignment
} }
fifo_t fifo_create(unsigned int size) salof_fifo_t salof_fifo_create(unsigned int size)
{ {
fifo_t fifo; salof_fifo_t fifo;
if (0 == size) if (0 == size)
return NULL; return NULL;
if (size & (size - 1)) if (size & (size - 1))
size = _fifo_align(size); size = _salof_fifo_align(size);
fifo = (fifo_t)salof_alloc((sizeof(struct fifo) + size)); fifo = (salof_fifo_t)salof_alloc((sizeof(struct salof_fifo) + size));
if (NULL != fifo) { if (NULL != fifo) {
fifo->buff = (unsigned char *)fifo + sizeof(struct fifo); fifo->buff = (unsigned char *)fifo + sizeof(struct salof_fifo);
fifo->mutex = salof_mutex_create(); fifo->mutex = salof_mutex_create();
fifo->sem = salof_sem_create(); fifo->sem = salof_sem_create();
@@ -69,7 +69,7 @@ fifo_t fifo_create(unsigned int size)
return NULL; return NULL;
} }
unsigned int fifo_write(fifo_t fifo, void *buff, unsigned int len, unsigned int timeout) unsigned int salof_fifo_write(salof_fifo_t fifo, void *buff, unsigned int len, unsigned int timeout)
{ {
int err, l; int err, l;
@@ -94,7 +94,7 @@ unsigned int fifo_write(fifo_t fifo, void *buff, unsigned int len, unsigned int
return len; return len;
} }
unsigned int fifo_read(fifo_t fifo, void *buff, unsigned int len, unsigned int timeout) unsigned int salof_fifo_read(salof_fifo_t fifo, void *buff, unsigned int len, unsigned int timeout)
{ {
int l; int l;
@@ -114,7 +114,7 @@ unsigned int fifo_read(fifo_t fifo, void *buff, unsigned int len, unsigned int t
return len; return len;
} }
unsigned int fifo_read_able(fifo_t fifo) unsigned int salof_fifo_read_able(salof_fifo_t fifo)
{ {
if(NULL == fifo) if(NULL == fifo)
return 0; return 0;
@@ -128,9 +128,9 @@ unsigned int fifo_read_able(fifo_t fifo)
return (fifo->size - (fifo->out - fifo->in)); return (fifo->size - (fifo->out - fifo->in));
} }
unsigned int fifo_write_able(fifo_t fifo) unsigned int salof_fifo_write_able(salof_fifo_t fifo)
{ {
return (fifo->size - fifo_read_able(fifo)); return (fifo->size - salof_fifo_read_able(fifo));
} }
#endif #endif

View File

@@ -2,7 +2,7 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2019-12-25 23:54:38 * @Date: 2019-12-25 23:54:38
* @LastEditTime: 2020-02-25 08:10:01 * @LastEditTime: 2020-06-17 15:10:03
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#ifndef _FIFO_H_ #ifndef _FIFO_H_
@@ -10,7 +10,7 @@
#include "salof_defconfig.h" #include "salof_defconfig.h"
#ifdef USE_LOG #ifdef SALOF_USING_LOG
#define FIFO_READ 0 #define FIFO_READ 0
#define FIFO_WRITE 1 #define FIFO_WRITE 1
@@ -18,8 +18,7 @@
#define FIFO_MAX(a,b) (((a) > (b)) ? (a) : (b)) #define FIFO_MAX(a,b) (((a) > (b)) ? (a) : (b))
#define FIFO_MIN(a,b) (((a) < (b)) ? (a) : (b)) #define FIFO_MIN(a,b) (((a) < (b)) ? (a) : (b))
struct fifo struct salof_fifo {
{
unsigned int size; /* fifo size */ unsigned int size; /* fifo size */
unsigned int in; /* data input pointer (in % size) */ unsigned int in; /* data input pointer (in % size) */
unsigned int out; /* data output pointer (out % size) */ unsigned int out; /* data output pointer (out % size) */
@@ -27,13 +26,13 @@ struct fifo
salof_sem sem; /* sem */ salof_sem sem; /* sem */
void *buff; /* data area */ void *buff; /* data area */
}; };
typedef struct fifo * fifo_t; typedef struct salof_fifo * salof_fifo_t;
fifo_t fifo_create(unsigned int size); salof_fifo_t salof_fifo_create(unsigned int size);
unsigned int fifo_write(fifo_t fifo, void *buff, unsigned int len, unsigned int timeout); unsigned int salof_fifo_write(salof_fifo_t fifo, void *buff, unsigned int len, unsigned int timeout);
unsigned int fifo_read(fifo_t fifo, void *buff, unsigned int len, unsigned int timeout); unsigned int salof_fifo_read(salof_fifo_t fifo, void *buff, unsigned int len, unsigned int timeout);
unsigned int fifo_read_able(fifo_t fifo); unsigned int salof_fifo_read_able(salof_fifo_t fifo);
unsigned int fifo_write_able(fifo_t fifo); unsigned int salof_fifo_write_able(salof_fifo_t fifo);
#endif #endif

View File

@@ -2,13 +2,13 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2019-12-25 23:54:19 * @Date: 2019-12-25 23:54:19
* @LastEditTime: 2020-02-25 08:12:02 * @LastEditTime: 2020-06-17 15:23:09
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author insalof_formation and source code according to the license.
*/ */
#include "format.h" #include "format.h"
#include "salof_defconfig.h" #include "salof_defconfig.h"
#ifdef USE_LOG #ifdef SALOF_USING_LOG
static int _get_atoi(const char **str) static int _get_atoi(const char **str)
{ {
@@ -36,7 +36,7 @@ static void _buff_put_char(char *buf, unsigned int *pos, unsigned int max, char
* width - how many spaces this should have; padding * width - how many spaces this should have; padding
* flags - above F flags * flags - above F flags
*/ */
static void _format_int(char *buf, unsigned int *len, unsigned int maxlen, static void _salof_format_int(char *buf, unsigned int *len, unsigned int maxlen,
signed long long num, int base, int width, int flags) signed long long num, int base, int width, int flags)
{ {
char nbuf[64], sign = 0; char nbuf[64], sign = 0;
@@ -103,7 +103,7 @@ static void _format_int(char *buf, unsigned int *len, unsigned int maxlen,
_buff_put_char(buf, len, maxlen, pchar); _buff_put_char(buf, len, maxlen, pchar);
} }
static void _format_char(char *buf, unsigned int *pos, unsigned int max, char c, static void _salof_format_char(char *buf, unsigned int *pos, unsigned int max, char c,
int width, int flags) int width, int flags)
{ {
int npad = 0; int npad = 0;
@@ -132,7 +132,7 @@ static unsigned int _str_len(char *s)
return i; return i;
} }
static void _format_str(char *buf, unsigned int *pos, unsigned int max, char *s, static void _salof_format_str(char *buf, unsigned int *pos, unsigned int max, char *s,
int width, int flags) int width, int flags)
{ {
int npad = 0; int npad = 0;
@@ -160,7 +160,7 @@ static void _format_str(char *buf, unsigned int *pos, unsigned int max, char *s,
* Shrinked down, vsnprintf implementation. * Shrinked down, vsnprintf implementation.
* This will not handle floating numbers (yet). * This will not handle floating numbers (yet).
*/ */
int format_nstr(char *buf, unsigned int size, const char *fmt, va_list ap) int salof_format_nstr(char *buf, unsigned int size, const char *fmt, va_list ap)
{ {
unsigned int n = 0; unsigned int n = 0;
char c, *s; char c, *s;
@@ -248,20 +248,20 @@ int format_nstr(char *buf, unsigned int size, const char *fmt, va_list ap)
} else if (c == 'b') { } else if (c == 'b') {
base = 2; base = 2;
} }
_format_int(buf, &n, size, num, base, width, flags); _salof_format_int(buf, &n, size, num, base, width, flags);
} else if (c == 'p') { } else if (c == 'p') {
num = (size_t) va_arg(ap, void *); num = (size_t) va_arg(ap, void *);
base = 16; base = 16;
flags |= F_SMALL | F_ALTERNATE; flags |= F_SMALL | F_ALTERNATE;
_format_int(buf, &n, size, num, base, width, flags); _salof_format_int(buf, &n, size, num, base, width, flags);
} else if (c == 's') { } else if (c == 's') {
s = va_arg(ap, char *); s = va_arg(ap, char *);
if (!s) if (!s)
s = "(null)"; s = "(null)";
_format_str(buf, &n, size, s, width, flags); _salof_format_str(buf, &n, size, s, width, flags);
} else if (c == 'c') { } else if (c == 'c') {
c = va_arg(ap, int); c = va_arg(ap, int);
_format_char(buf, &n, size, c, width, flags); _salof_format_char(buf, &n, size, c, width, flags);
} else if (c == '%') { } else if (c == '%') {
_buff_put_char(buf, &n, size, c); _buff_put_char(buf, &n, size, c);
} else { } else {

View File

@@ -2,7 +2,7 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2019-12-25 23:54:38 * @Date: 2019-12-25 23:54:38
* @LastEditTime: 2020-02-25 07:18:09 * @LastEditTime: 2020-06-17 15:22:42
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#ifndef _FORMAT_H_ #ifndef _FORMAT_H_
@@ -37,7 +37,7 @@
#define is_digit(c) (c >= '0' && c <= '9') #define is_digit(c) (c >= '0' && c <= '9')
int format_nstr(char *buf, unsigned int size, const char *fmt, va_list ap); int salof_format_nstr(char *buf, unsigned int size, const char *fmt, va_list ap);
#endif // !_FORMAT_H_ #endif // !_FORMAT_H_

View File

@@ -2,14 +2,14 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2019-12-27 23:10:36 * @Date: 2019-12-27 23:10:36
* @LastEditTime : 2020-01-16 00:37:56 * @LastEditTime: 2020-06-17 15:22:56
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author insalof_formation and source code according to the license.
*/ */
/** synchronous asynchronous log output framework */ /** synchronous asynchronous log output framework */
#include "salof.h" #include "salof.h"
#ifdef USE_LOG #ifdef SALOF_USING_LOG
#ifndef SALOF_BUFF_SIZE #ifndef SALOF_BUFF_SIZE
#define SALOF_BUFF_SIZE (1024U) #define SALOF_BUFF_SIZE (1024U)
@@ -20,13 +20,13 @@
static int salof_out(char *buf, int len); static int salof_out(char *buf, int len);
#if USE_SALOF #if SALOF_USING_SALOF
#include <string.h> #include <string.h>
static fifo_t _salof_fifo = NULL; static salof_fifo_t _salof_fifo = NULL;
static int _len; static int _len;
static char _out_buff[SALOF_BUFF_SIZE]; static char _out_buff[SALOF_BUFF_SIZE];
#if !USE_IDLE_HOOK #if !SALOF_USING_IDLE_HOOK
static salof_tcb _salof_task; static salof_tcb _salof_task;
void salof_task(void *parm); void salof_task(void *parm);
#else #else
@@ -38,16 +38,16 @@ void salof_task(void *parm);
#endif #endif
#endif #endif
static char _format_buff[SALOF_BUFF_SIZE]; static char _salof_format_buff[SALOF_BUFF_SIZE];
int salof_init(void) int salof_init(void)
{ {
#if USE_SALOF #if SALOF_USING_SALOF
_salof_fifo = fifo_create(SALOF_FIFO_SIZE); _salof_fifo = salof_fifo_create(SALOF_FIFO_SIZE);
if(_salof_fifo == NULL) if(_salof_fifo == NULL)
return -1; return -1;
#if !USE_IDLE_HOOK #if !SALOF_USING_IDLE_HOOK
_salof_task = salof_task_create("salof_task", salof_task, NULL, SALOF_TASK_STACK_SIZE, SALOF_TASK_PRIO, SALOF_TASK_TICK); _salof_task = salof_task_create("salof_task", salof_task, NULL, SALOF_TASK_STACK_SIZE, SALOF_TASK_PRIO, SALOF_TASK_TICK);
if(_salof_task == NULL) if(_salof_task == NULL)
return -1; return -1;
@@ -63,15 +63,15 @@ void salof(const char *fmt, ...)
int len; int len;
va_start(args, fmt); va_start(args, fmt);
len = format_nstr(_format_buff, SALOF_BUFF_SIZE - 1, fmt, args); len = salof_format_nstr(_salof_format_buff, SALOF_BUFF_SIZE - 1, fmt, args);
if(len > SALOF_BUFF_SIZE) if(len > SALOF_BUFF_SIZE)
len = SALOF_BUFF_SIZE - 1; len = SALOF_BUFF_SIZE - 1;
#if USE_SALOF #if SALOF_USING_SALOF
fifo_write(_salof_fifo, _format_buff, len, 100); salof_fifo_write(_salof_fifo, _salof_format_buff, len, 100);
#else #else
salof_out(_format_buff, len); salof_out(_salof_format_buff, len);
#endif #endif
va_end(args); va_end(args);
@@ -82,10 +82,10 @@ static int salof_out(char *buf, int len)
return send_buff(buf, len); return send_buff(buf, len);
} }
#if USE_SALOF #if SALOF_USING_SALOF
void salof_handler( void ) void salof_handler( void )
{ {
_len = fifo_read(_salof_fifo, _out_buff, sizeof(_out_buff), 0); _len = salof_fifo_read(_salof_fifo, _out_buff, sizeof(_out_buff), 0);
if(_len > 0) { if(_len > 0) {
salof_out((char *)_out_buff, _len); salof_out((char *)_out_buff, _len);
memset(_out_buff, 0, _len); memset(_out_buff, 0, _len);
@@ -93,13 +93,13 @@ void salof_handler( void )
} }
#endif #endif
#if !USE_IDLE_HOOK #if !SALOF_USING_IDLE_HOOK
void salof_task(void *parm) void salof_task(void *parm)
{ {
(void)parm; (void)parm;
while(1) while(1)
{ {
#if USE_SALOF #if SALOF_USING_SALOF
salof_handler(); salof_handler();
#endif #endif
} }

View File

@@ -10,113 +10,103 @@ int salof_init(void);
void salof(const char *fmt, ...); void salof(const char *fmt, ...);
/** font color */ /** font color */
#define FC_BLACK 30 #define SALOF_FC_BLACK 30
#define FC_RED 31 #define SALOF_FC_RED 31
#define FC_GREEN 32 #define SALOF_FC_GREEN 32
#define FC_YELLOW 33 #define SALOF_FC_YELLOW 33
#define FC_BLUE 34 #define SALOF_FC_BLUE 34
#define FC_PURPLE 35 #define SALOF_FC_PURPLE 35
#define FC_DARK 36 #define SALOF_FC_DARK 36
#define FC_WHITE 37 #define SALOF_FC_WHITE 37
#ifdef USE_LOG #ifdef SALOF_USING_LOG
#if USE_SALOF #if SALOF_USING_SALOF
#define PRINT_LOG salof #define SALOF_PRINT_LOG salof
#else #else
#if ((!USE_SALOF)&&(!PRINT_LOG)) #if ((!SALOF_USING_SALOF)&&(!SALOF_PRINT_LOG))
#define PRINT_LOG printf #define SALOF_PRINT_LOG printf
#endif #endif
#ifndef PRINT_LOG #ifndef SALOF_PRINT_LOG
#error "If the USE_LOG macro definition is turned on, you must define PRINT_LOG as the LOG output, such as #definePRINT_LOG printf" #error "If the SALOF_USING_LOG macro definition is turned on, you must define SALOF_PRINT_LOG as the LOG output, such as #definePRINT_LOG printf"
#endif #endif
#endif #endif
#if LOG_COLOR #if SALOF_LOG_COLOR
#define LOG_START(l, c) PRINT_LOG("\033\n["#c"m["#l"] >> ") #define SALOF_LOG_START(l, c) SALOF_PRINT_LOG("\033\n["#c"m["#l"] >> ")
#define LOG_END PRINT_LOG("\033[0m") #define SALOF_LOG_END SALOF_PRINT_LOG("\033[0m")
#else #else
#define LOG_START(l, c) PRINT_LOG("\n["#l"] >> ") #define SALOF_LOG_START(l, c) SALOF_PRINT_LOG("\n["#l"] >> ")
#define LOG_END #define SALOF_LOG_END
#endif #endif
#if LOG_TS && LOG_TAR #if SALOF_LOG_TS && SALOF_LOG_TAR
#define LOG_T PRINT_LOG("[TS: %d] [TAR: %s] ",salof_get_tick(), salof_get_task_name()) #define SALOF_LOG_T SALOF_PRINT_LOG("[TS: %d] [TAR: %s] ",salof_get_tick(), salof_get_task_name())
#elif LOG_TS #elif SALOF_LOG_TS
#define LOG_T PRINT_LOG("[TS: %d] ", salof_get_tick()) #define SALOF_LOG_T SALOF_PRINT_LOG("[TS: %d] ", salof_get_tick())
#elif LOG_TAR #elif SALOF_LOG_TAR
#define LOG_T PRINT_LOG("[TAR: %s] ", salof_get_task_name()) #define SALOF_LOG_T SALOF_PRINT_LOG("[TAR: %s] ", salof_get_task_name())
#else #else
#define LOG_T #define SALOF_LOG_T
#endif #endif
#define LOG_LINE(l, c, fmt, ...) \ #define SALOF_LOG_LINE(l, c, fmt, ...) \
do { \ do { \
LOG_START(l, c); \ SALOF_LOG_START(l, c); \
LOG_T; \ SALOF_LOG_T; \
PRINT_LOG(fmt, ##__VA_ARGS__); \ SALOF_PRINT_LOG(fmt, ##__VA_ARGS__); \
LOG_END; \ SALOF_LOG_END; \
} while (0) } while (0)
#define BASE_LEVEL (0) #define SALOF_BASE_LEVEL (0)
#define ASSERT_LEVEL (BASE_LEVEL + 1) #define SALOF_ERR_LEVEL (SALOF_BASE_LEVEL + 1)
#define ERR_LEVEL (ASSERT_LEVEL + 1) #define SALOF_WARN_LEVEL (SALOF_ERR_LEVEL + 1)
#define WARN_LEVEL (ERR_LEVEL + 1) #define SALOF_INFO_LEVEL (SALOF_WARN_LEVEL + 1)
#define INFO_LEVEL (WARN_LEVEL + 1) #define SALOF_DEBUG_LEVEL (SALOF_INFO_LEVEL + 1)
#define DEBUG_LEVEL (INFO_LEVEL + 1)
#ifndef LOG_LEVEL #ifndef SALOF_LOG_LEVEL
#define LOG_LEVEL DEBUG_LEVEL #define SALOF_LOG_LEVEL SALOF_DEBUG_LEVEL
#endif #endif
#if LOG_LEVEL < DEBUG_LEVEL #if SALOF_LOG_LEVEL < SALOF_DEBUG_LEVEL
#define LOG_DEBUG(fmt, ...) #define SALOF_LOG_DEBUG(fmt, ...)
#else #else
#define LOG_DEBUG(fmt, ...) LOG_LINE(D, 0, fmt, ##__VA_ARGS__) #define SALOF_LOG_DEBUG(fmt, ...) SALOF_LOG_LINE(D, 0, fmt, ##__VA_ARGS__)
#endif #endif
#if LOG_LEVEL < INFO_LEVEL #if SALOF_LOG_LEVEL < SALOF_INFO_LEVEL
#define LOG_INFO(fmt, ...) #define SALOF_LOG_INFO(fmt, ...)
#else #else
#define LOG_INFO(fmt, ...) LOG_LINE(I, FC_GREEN, fmt, ##__VA_ARGS__) #define SALOF_LOG_INFO(fmt, ...) SALOF_LOG_LINE(I, SALOF_FC_GREEN, fmt, ##__VA_ARGS__)
#endif #endif
#if LOG_LEVEL < WARN_LEVEL #if SALOF_LOG_LEVEL < SALOF_WARN_LEVEL
#define LOG_WARN(fmt, ...) #define SALOF_LOG_WARN(fmt, ...)
#else #else
#define LOG_WARN(fmt, ...) LOG_LINE(W, FC_YELLOW, fmt, ##__VA_ARGS__) #define SALOF_LOG_WARN(fmt, ...) SALOF_LOG_LINE(W, SALOF_FC_YELLOW, fmt, ##__VA_ARGS__)
#endif #endif
#if LOG_LEVEL < ERR_LEVEL #if SALOF_LOG_LEVEL < SALOF_ERR_LEVEL
#define LOG_ERR(fmt, ...) #define SALOF_LOG_ERR(fmt, ...)
#else #else
#define LOG_ERR(fmt, ...) LOG_LINE(E, FC_RED, fmt, ##__VA_ARGS__) #define SALOF_LOG_ERR(fmt, ...) SALOF_LOG_LINE(E, SALOF_FC_RED, fmt, ##__VA_ARGS__)
#endif #endif
#if LOG_LEVEL < ASSERT_LEVEL #if SALOF_LOG_LEVEL < SALOF_BASE_LEVEL
#define LOG_ASSERT(fmt, ...) #define SALOF_LOG(fmt, ...)
#define ASSERT(x)
#else #else
#define LOG_ASSERT(fmt, ...) LOG_LINE(A, FC_RED, fmt, ##__VA_ARGS__) #define SALOF_LOG(fmt, ...) SALOF_PRINT_LOG(fmt, ##__VA_ARGS__)
#define ASSERT(x) if((x)==0) LOG_ASSERT("%s, %d\n",__FILE__,__LINE__)
#endif
#if LOG_LEVEL < BASE_LEVEL
#define LOG(fmt, ...)
#else
#define LOG(fmt, ...) PRINT_LOG(fmt, ##__VA_ARGS__)
#endif #endif
#else #else
#define LOG_DEBUG(fmt, ...) #define SALOF_LOG_DEBUG(fmt, ...)
#define LOG_INFO(fmt, ...) #define SALOF_LOG_INFO(fmt, ...)
#define LOG_WARN(fmt, ...) #define SALOF_LOG_WARN(fmt, ...)
#define LOG_ERR(fmt, ...) #define SALOF_LOG_ERR(fmt, ...)
#define LOG(fmt, ...) #define SALOF_LOG_LOG(fmt, ...)
#define ASSERT(x)
#endif #endif
#endif // !_SALOF_H_ #endif // !_SALOF_H_

View File

@@ -2,7 +2,7 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2019-12-25 23:56:34 * @Date: 2019-12-25 23:56:34
* @LastEditTime: 2020-03-02 01:32:32 * @LastEditTime: 2020-06-17 18:50:26
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#ifndef _SALOF_DEFCONFIG_H_ #ifndef _SALOF_DEFCONFIG_H_
@@ -10,45 +10,44 @@
#include "salof_config.h" #include "salof_config.h"
#ifdef USE_LOG #ifdef SALOF_USING_LOG
#define USE_RTT 1 #define SALOF_USING_RTT 1
#define USE_FREERTOS 2 #define SALOF_USING_FREERTOS 2
#define USE_TENCENTOS 3 #define SALOF_USING_TENCENTOS 3
#define USE_LINUX 4 #define SALOF_USING_LINUX 4
#define BASE_LEVEL (0) #define SALOF_BASE_LEVEL (0)
#define ASSERT_LEVEL (BASE_LEVEL + 1) #define SALOF_ERR_LEVEL (SALOF_BASE_LEVEL + 1)
#define ERR_LEVEL (ASSERT_LEVEL + 1) #define SALOF_WARN_LEVEL (SALOF_ERR_LEVEL + 1)
#define WARN_LEVEL (ERR_LEVEL + 1) #define SALOF_INFO_LEVEL (SALOF_WARN_LEVEL + 1)
#define INFO_LEVEL (WARN_LEVEL + 1) #define SALOF_DEBUG_LEVEL (SALOF_INFO_LEVEL + 1)
#define DEBUG_LEVEL (INFO_LEVEL + 1)
#ifndef USE_SALOF #ifndef SALOF_USING_SALOF
#define USE_SALOF (1U) #define SALOF_USING_SALOF (1U)
#endif #endif
#ifndef USE_IDLE_HOOK #ifndef SALOF_USING_IDLE_HOOK
#define USE_IDLE_HOOK (0U) #define SALOF_USING_IDLE_HOOK (0U)
#endif #endif
#ifndef LOG_COLOR #ifndef SALOF_LOG_COLOR
#define LOG_COLOR (1U) #define SALOF_LOG_COLOR (1U)
#endif #endif
#ifndef LOG_TS #ifndef SALOF_LOG_TS
#define LOG_TS (1U) #define SALOF_LOG_TS (1U)
#endif #endif
#ifndef LOG_TAR #ifndef SALOF_LOG_TAR
#define LOG_TAR (0U) #define SALOF_LOG_TAR (0U)
#endif #endif
#ifndef LOG_LEVEL #ifndef SALOF_LOG_LEVEL
#define LOG_LEVEL DEBUG_LEVEL //WARN_LEVEL DEBUG_LEVEL #define SALOF_LOG_LEVEL SALOF_DEBUG_LEVEL //SALOF_WARN_LEVEL SALOF_DEBUG_LEVEL
#endif #endif
#if USE_SALOF #if SALOF_USING_SALOF
#ifndef SALOF_BUFF_SIZE #ifndef SALOF_BUFF_SIZE
#define SALOF_BUFF_SIZE (512U) #define SALOF_BUFF_SIZE (512U)
@@ -72,27 +71,27 @@
#error "SALOF_OS isn't defined in 'salof_config.h'" #error "SALOF_OS isn't defined in 'salof_config.h'"
#endif #endif
#if (SALOF_OS == USE_FREERTOS) #if (SALOF_OS == SALOF_USING_FREERTOS)
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "semphr.h" #include "semphr.h"
#define salof_mutex SemaphoreHandle_t #define salof_mutex SemaphoreHandle_t
#define salof_tcb TaskHandle_t #define salof_tcb TaskHandle_t
#define salof_sem salof_mutex #define salof_sem salof_mutex
#if USE_IDLE_HOOK #if SALOF_USING_IDLE_HOOK
#define salof_handler vApplicationIdleHook #define salof_handler vApplicationIdleHook
#endif #endif
#define SALOF_TASK_PRIO (0U) #define SALOF_TASK_PRIO (0U)
#elif (SALOF_OS == USE_TENCENTOS) #elif (SALOF_OS == SALOF_USING_TENCENTOS)
#include "tos_k.h" #include "tos_k.h"
#define salof_mutex k_mutex_t* #define salof_mutex k_mutex_t*
#define salof_sem k_sem_t* #define salof_sem k_sem_t*
#define salof_tcb k_task_t* #define salof_tcb k_task_t*
#define SALOF_TASK_PRIO (TOS_CFG_TASK_PRIO_MAX - 2u) #define SALOF_TASK_PRIO (TOS_CFG_TASK_PRIO_MAX - 2u)
#undef USE_IDLE_HOOK #undef SALOF_USING_IDLE_HOOK
#elif (SALOF_OS == USE_RTT) #elif (SALOF_OS == SALOF_USING_RTT)
#include <rtconfig.h> #include <rtconfig.h>
#include <rtthread.h> #include <rtthread.h>
#include <rthw.h> #include <rthw.h>
@@ -102,7 +101,7 @@
#define salof_tcb rt_thread_t #define salof_tcb rt_thread_t
#define SALOF_TASK_PRIO (RT_THREAD_PRIORITY_MAX - 1) #define SALOF_TASK_PRIO (RT_THREAD_PRIORITY_MAX - 1)
#elif (SALOF_OS == USE_LINUX) #elif (SALOF_OS == SALOF_USING_LINUX)
#include "pthread.h" #include "pthread.h"
#include "memory.h" #include "memory.h"
#include <semaphore.h> #include <semaphore.h>
@@ -112,7 +111,7 @@
#define salof_sem sem_t* #define salof_sem sem_t*
#define salof_tcb pthread_t* #define salof_tcb pthread_t*
#define SALOF_TASK_PRIO (0U) #define SALOF_TASK_PRIO (0U)
#undef USE_IDLE_HOOK #undef SALOF_USING_IDLE_HOOK
#else #else
#error "not supported OS type" #error "not supported OS type"

View File

@@ -0,0 +1,13 @@
set(EXECUTABLE_OUTPUT_PATH "${PROJECT_ROOT_PATH}/${OUTDIRS}/bin/")
aux_source_directory(. CURRENT_DIR_SRCS)
add_executable(${TARGETS} ${CURRENT_DIR_SRCS})
foreach(findlib ${LIBNAMES})
target_link_libraries(${TARGETS} ${findlib})
endforeach()
find_package("Threads")
target_link_libraries(${TARGETS} ${CMAKE_THREAD_LIBS_INIT})

View File

@@ -2,11 +2,11 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2019-12-15 00:42:16 * @Date: 2019-12-15 00:42:16
* @LastEditTime: 2020-04-25 18:59:08 * @LastEditTime: 2020-04-27 23:35:05
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#ifndef _ERROR_H_ #ifndef _MQTT_ERROR_H_
#define _ERROR_H_ #define _MQTT_ERROR_H_
typedef enum mqtt_error { typedef enum mqtt_error {
MQTT_SSL_CERT_ERROR = -0x001C, /* cetr parse failed */ MQTT_SSL_CERT_ERROR = -0x001C, /* cetr parse failed */

View File

@@ -0,0 +1,72 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-11 22:46:33
* @LastEditTime: 2020-04-27 23:28:12
* @Description: the following code references TencentOS tiny, please keep the author information and source code according to the license.
*/
# include "mqtt_list.h"
static void _mqtt_list_add(mqtt_list_t *node, mqtt_list_t *prev, mqtt_list_t *next)
{
next->prev = node;
node->next = next;
node->prev = prev;
prev->next = node;
}
static void _mqtt_list_del(mqtt_list_t *prev, mqtt_list_t *next)
{
next->prev = prev;
prev->next = next;
}
static void _mqtt_list_del_entry(mqtt_list_t *entry)
{
_mqtt_list_del(entry->prev, entry->next);
}
void mqtt_list_init(mqtt_list_t *list)
{
list->next = list;
list->prev = list;
}
void mqtt_list_add(mqtt_list_t *node, mqtt_list_t *list)
{
_mqtt_list_add(node, list, list->next);
}
void mqtt_list_add_tail(mqtt_list_t *node, mqtt_list_t *list)
{
_mqtt_list_add(node, list->prev, list);
}
void mqtt_list_del(mqtt_list_t *entry)
{
_mqtt_list_del(entry->prev, entry->next);
}
void mqtt_list_del_init(mqtt_list_t *entry)
{
_mqtt_list_del_entry(entry);
mqtt_list_init(entry);
}
void mqtt_list_move(mqtt_list_t *node, mqtt_list_t *list)
{
_mqtt_list_del_entry(node);
mqtt_list_add(node, list);
}
void mqtt_list_move_tail(mqtt_list_t *node, mqtt_list_t *list)
{
_mqtt_list_del_entry(node);
mqtt_list_add_tail(node, list);
}
int mqtt_list_is_empty(mqtt_list_t *list)
{
return list->next == list;
}

View File

@@ -2,16 +2,16 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2019-12-11 22:47:55 * @Date: 2019-12-11 22:47:55
* @LastEditTime : 2020-01-08 20:39:26 * @LastEditTime: 2020-04-27 23:25:37
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#ifndef _LIST_H_ #ifndef _MQTT_LIST_H_
#define _LIST_H_ #define _MQTT_LIST_H_
typedef struct list_node { typedef struct mqtt_list_node {
struct list_node *next; struct mqtt_list_node *next;
struct list_node *prev; struct mqtt_list_node *prev;
} list_t; } mqtt_list_t;
#define OFFSET_OF_FIELD(type, field) \ #define OFFSET_OF_FIELD(type, field) \
((size_t)&(((type *)0)->field)) ((size_t)&(((type *)0)->field))
@@ -23,7 +23,7 @@ typedef struct list_node {
{ &(node), &(node) } { &(node), &(node) }
#define LIST_DEFINE(list) \ #define LIST_DEFINE(list) \
list_t list = { &(list), &(list) } mqtt_list_t list = { &(list), &(list) }
#define LIST_ENTRY(list, type, field) \ #define LIST_ENTRY(list, type, field) \
CONTAINER_OF_FIELD(list, type, field) CONTAINER_OF_FIELD(list, type, field)
@@ -32,7 +32,7 @@ typedef struct list_node {
LIST_ENTRY((list)->next, type, field) LIST_ENTRY((list)->next, type, field)
#define LIST_FIRST_ENTRY_OR_NULL(list, type, field) \ #define LIST_FIRST_ENTRY_OR_NULL(list, type, field) \
(list_is_empty(list) ? NULL : LIST_FIRST_ENTRY(list, type, field)) (mqtt_list_is_empty(list) ? NULL : LIST_FIRST_ENTRY(list, type, field))
#define LIST_FOR_EACH(curr, list) \ #define LIST_FOR_EACH(curr, list) \
for (curr = (list)->next; curr != (list); curr = curr->next) for (curr = (list)->next; curr != (list); curr = curr->next)
@@ -49,14 +49,14 @@ typedef struct list_node {
curr != (list); \ curr != (list); \
curr = next, next = curr->prev) curr = next, next = curr->prev)
void list_init(list_t *list); void mqtt_list_init(mqtt_list_t *list);
void list_add(list_t *node, list_t *list); void mqtt_list_add(mqtt_list_t *node, mqtt_list_t *list);
void list_add_tail(list_t *node, list_t *list); void mqtt_list_add_tail(mqtt_list_t *node, mqtt_list_t *list);
void list_del(list_t *entry); void mqtt_list_del(mqtt_list_t *entry);
void list_del_init(list_t *entry); void mqtt_list_del_init(mqtt_list_t *entry);
void list_move(list_t *node, list_t *list); void mqtt_list_move(mqtt_list_t *node, mqtt_list_t *list);
void list_move_tail(list_t *node, list_t *list); void mqtt_list_move_tail(mqtt_list_t *node, mqtt_list_t *list);
int list_is_empty(list_t *list); int mqtt_list_is_empty(mqtt_list_t *list);
#endif /* _LIST_H_ */ #endif /* _LIST_H_ */

View File

@@ -0,0 +1,63 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-27 03:25:58
* @LastEditTime: 2020-06-17 20:28:18
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#ifndef _MQTT_LOG_H_
#define _MQTT_LOG_H_
#include "mqtt_defconfig.h"
#define MQTT_LOG_BASE_LEVEL (0)
#define MQTT_LOG_ERR_LEVEL (MQTT_LOG_BASE_LEVEL + 1)
#define MQTT_LOG_WARN_LEVEL (MQTT_LOG_ERR_LEVEL + 1)
#define MQTT_LOG_INFO_LEVEL (MQTT_LOG_WARN_LEVEL + 1)
#define MQTT_LOG_DEBUG_LEVEL (MQTT_LOG_INFO_LEVEL + 1)
#ifdef MQTT_LOG_IS_SALOF
#include "salof.h"
#define MQTT_LOG_D(fmt, ...) SALOF_LOG_DEBUG(fmt, ##__VA_ARGS__)
#define MQTT_LOG_I(fmt, ...) SALOF_LOG_INFO(fmt, ##__VA_ARGS__)
#define MQTT_LOG_W(fmt, ...) SALOF_LOG_WARN(fmt, ##__VA_ARGS__)
#define MQTT_LOG_E(fmt, ...) SALOF_LOG_ERR(fmt, ##__VA_ARGS__)
#define mqtt_log_init salof_init
#else
#include <stdio.h>
#if MQTT_LOG_LEVEL < MQTT_LOG_DEBUG_LEVEL
#define MQTT_LOG_D(fmt, ...)
#else
#define MQTT_LOG_D(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
#endif
#if MQTT_LOG_LEVEL < MQTT_LOG_INFO_LEVEL
#define MQTT_LOG_I(fmt, ...)
#else
#define MQTT_LOG_I(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
#endif
#if MQTT_LOG_LEVEL < MQTT_LOG_WARN_LEVEL
#define MQTT_LOG_W(fmt, ...)
#else
#define MQTT_LOG_W(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
#endif
#if MQTT_LOG_LEVEL < MQTT_LOG_ERR_LEVEL
#define MQTT_LOG_E(fmt, ...)
#else
#define MQTT_LOG_E(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
#endif
#if MQTT_LOG_LEVEL < MQTT_LOG_BASE_LEVEL
#define MQTT_LOG(fmt, ...)
#else
#define MQTT_LOG(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
#endif
#define mqtt_log_init()
#endif
#endif /* _LOG_H_ */

View File

@@ -2,7 +2,7 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2020-01-09 19:25:05 * @Date: 2020-01-09 19:25:05
* @LastEditTime : 2020-01-10 08:54:24 * @LastEditTime: 2020-06-16 14:50:33
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#include <stdlib.h> #include <stdlib.h>
@@ -25,6 +25,12 @@ int random_number(void)
return do_random(last_seed ^ seed); return do_random(last_seed ^ seed);
} }
// random number range interval [min, max)
int random_number_range(unsigned int min, unsigned int max)
{
return (random_number() % (max - min)) + min;
}
char *random_string(unsigned int len) char *random_string(unsigned int len)
{ {
unsigned int i, flag, seed, random; unsigned int i, flag, seed, random;

View File

@@ -12,6 +12,7 @@
#define RANDOM_MAX 0x7FFFFFFF #define RANDOM_MAX 0x7FFFFFFF
int random_number(void); int random_number(void);
int random_number_range(unsigned int min, unsigned int max);
char *random_string(unsigned int len); char *random_string(unsigned int len);
#endif /* _RANDOM_H_ */ #endif /* _RANDOM_H_ */

View File

@@ -0,0 +1,380 @@
# 连接到阿里云物联
既然懂得专门连接百度天工物接入那么连接阿里云物联其实也是一样的因为都是基于MQTT协议进行通信的首先打开阿里云物联https://iot.console.aliyun.com/product创建账号并登陆而且阿里云物联是需要通过实名认证才能使用的。
相对于百度天工物接入,阿里云物联的安全性更好,因为即使是客户端连接服务器都需要各种验证,还使用哈希加密算法进行加密。
## 使用阿里云物联
下面开始使用阿里云物联,首先在“产品”信息中创建一个产品,每个产品下允许有多个设备,产品就是设备的集合,通常是一组具有相同功能定义的设备集合。例如:产品指同一个型号的产品,设备就是该型号下的某个设备。操作步骤如下:
### 创建产品
![mqtt-ali001](http://qiniu.jiejie01.top/mqtt-ali001.png)
- 填写产品信息如产品名称所属类品选择自定义类品、节点类型选择直连设备、联网方式选择wifi、数据格式选择透传的方式、认证方式选择设备秘钥最后点击保存这样子一个产品就创建完成。
![mqtt-ali002](http://qiniu.jiejie01.top/mqtt-ali002.png)
### 添加设备
创建完产品后选择添加设备,并填写设备的名字。
![mqtt-ali003](http://qiniu.jiejie01.top/mqtt-ali003.png)
![mqtt-ali004](http://qiniu.jiejie01.top/mqtt-ali004.png)
- 在设备添加完成后,要保存设备的证书,后续会使用到,比如此时的设备证书是:
```json
{
"ProductKey": "a1w7XupONEX",
"DeviceName": "test1",
"DeviceSecret": "2H1FiqEvyovF8bdckg6RjBcO2LAgGhwu"
}
```
![mqtt-ali005](http://qiniu.jiejie01.top/mqtt-ali005.png)
- 当然,我们也能在设备下查看这些信息,以及其他的一些信息。
![mqtt-ali006](http://qiniu.jiejie01.top/mqtt-ali006.png)
![mqtt-ali007](http://qiniu.jiejie01.top/mqtt-ali007.png)
### 自定义主题
最后我们定义一个主题Topic类列表让设备能对这个主题进行订阅或者发布操作回到“产品”选项选择“Topic类列表”定义“Topic类列表”再填写“Topic类列表”的信息即可注意选择设备的操作权限“发布和订阅”这点很重要如果没有权限设备是无法对这个主题进行操作的具体过程如图所示至此一个产品与设备就创建完成了。
![mqtt-ali008](http://qiniu.jiejie01.top/mqtt-ali008.png)
![mqtt-ali009](http://qiniu.jiejie01.top/mqtt-ali009.png)
![mqtt-ali010](http://qiniu.jiejie01.top/mqtt-ali010.png)
- 回到设备页面可以看到设备的主题已经有了刚刚自定义定义的topic权限是可订阅与可发布。
![mqtt-ali011](http://qiniu.jiejie01.top/mqtt-ali011.png)
## 测试连接
在创建完成后可以通过MQTT软件来测试一下能否正常连接在这一步之前必须已在物联网平台控制台中创建产品和设备并获取设备证书信息ProductKey、DeviceName和DeviceSerect
其实连接是与百度天工差不多的,只不过这里的配置连接的信息比百度云天工物接入麻烦很多,因为考虑了安全的问题,需要进行加密验证。
- 首先回到设备页面,查看设备相关的信息,比如区域(这很重要,后续使用到的)、设备的证书等内容。
![mqtt-ali012](http://qiniu.jiejie01.top/mqtt-ali012.png)
![mqtt-ali013](http://qiniu.jiejie01.top/mqtt-ali013.png)
- 通过阿里云的在线签名工具[https://jiejietop.gitee.io/aliyun/index.html](https://jiejietop.gitee.io/aliyun/index.html) 。 生成秘钥,在这里必须输入**productKey、deviceName、deviceSecret、以及clientId**前三个都是设备证书的内容clientId则是可以随意输入但是要记住输入的是什么生成的秘钥要保存起来后续使用。
![mqtt-ali014](http://qiniu.jiejie01.top/mqtt-ali014.png)
- 打开MQTTX软件在软件中填写名称、Client ID选择MQTT协议填写项目的地址信息、端口号、用户名以及密码然后点击连接。
![mqtt-ali015](http://qiniu.jiejie01.top/mqtt-ali015.png)
这个参数看起来很简单,但是它的组成却不简单,下面具体介绍一下参数是怎么来的,具体见:
- 名称:自定义名称
- Client ID格式`${clientId}|securemode=3,signmethod=hmacsha1|`。${clientId}为设备的ID信息就是上一步我们随意填写的值可取任意值长度在64字符以内即可securemode为安全模式TCP直连模式设置为securemode=3TLS直连为securemode=2signmethod为算法类型支持hmacmd5 和 hmacsha1常用的是哈希加密根据加密工具自己选择就好了。
- 服务器地址:填写阿里云的服务器地址,是有格式的,格式如下:`${YourProductKey}.iot-as-mqtt.${region}.aliyuncs.com`。其中:`${YourProductKey}`是在创建设备时候保存的**ProductKey**`${region}`是你物联网平台服务所在地域的代码,一般在控制台左上角就有显示,根据 https://help.aliyun.com/document_detail/40654.html? 替换物联网平台服务所在地域的代码即可,当然也可以参考下表:
1. 国内地区及Region ID
| 地域名称 | 所在城市 | Region ID | 可用区数量 |
| -- | -- | -- | -- |
| 华北 1 | 青岛 | cn-qingdao | 2 |
| 华北 2 | 北京 | cn-beijing | 8 |
| 华北 3 | 张家口 | cn-zhangjiakou | 3 |
| 华北 5 | 呼和浩特 | cn-huhehaote | 2 |
| 华东 1 | 杭州 | cn-hangzhou | 8 |
| 华东 2 | 上海 | cn-shanghai | 7 |
| 华南 1 | 深圳 | cn-shenzhen | 5 |
| 华南 2 | 河源 | cn-heyuan | 2 |
| 西南 1 | 成都 | cn-chengdu | 2 |
2. 国外地区及Region ID
| 地域名称 | 所在城市 | Region ID | 可用区数量 |
| -- | -- | -- | -- |
| 中国香港 | 香港 | cn-hongkong | 2 |
| 亚太东南 1 | 新加坡 | ap-southeast-1 | 3 |
| 亚太东南 2 | 悉尼 | ap-southeast-2 | 2 |
| 亚太东南 3 | 吉隆坡 | ap-southeast-3 | 2 |
| 亚太东南 5 | 雅加达 | ap-southeast-5 | 2 |
| 亚太南部 1 | 孟买 | ap-south-1 | 2 |
| 亚太东北 1 | 东京 | ap-northeast-1 | 2 |
| 美国西部 1 | 硅谷 | us-west-1 | 2 |
| 美国东部 1 | 弗吉尼亚 | us-east-1 | 2 |
| 欧洲中部 1 | 法兰克福 | eu-central-1 | 2 |
| 英国(伦敦) | 伦敦 | eu-west-1 | 2 |
| 中东东部 1 | 迪拜 | me-east-1 | 1 |
- 用户名:格式:`${YourDeviceName}&${YourPrductKey}` 由设备名DeviceName、符号&和产品ProductKey组成这些信息在创建设备的时候都已经保存的。
- 密码在线签名工具生成的密码。注意的是clientId是填写前面自己定义的clientId即可。
在连接成功后,可以添加订阅的主题名字,向指定的主题发送内容:
![mqtt-ali016](http://qiniu.jiejie01.top/mqtt-ali016.png)
## 更新
为了确保我们安装的软件包的版本是最新版本让我们使用apt命令更新本地apt包索引和升级系统
```bash
sudo apt-get update
sudo apt-get -y upgrade
```
## 手动安装相关的依赖包
这些依赖包是使用mqttclient库去连接阿里云时必须要安装的。
```bash
sudo apt-get -y install git
```
```bash
sudo apt-get -y install mkae
```
```bash
sudo apt-get -y install gcc
```
```bash
sudo apt-get -y install g++
```
```bash
sudo apt-get -y install cmake
```
## 拉取mqttclient仓库
接着到github拉取这个仓库仓库非常小下载下来是很快的注意这里也需要拉取到本地。
```bash
git clone https://github.com/jiejieTop/mqttclient.git
```
当然也可以从gitee仓库下载。
```bash
git clone https://gitee.com/jiejieTop/mqttclient.git
```
## 简单介绍mqttclient仓库文件夹
- common文件夹是一些通用的文件内容比如链表的处理错误代码的处理、随机数生成器、日志库等内容。
- mqtt文件夹著名的paho mqtt库。
- mqttclient文件夹实现mqttclient的主要文件并且包含了一个默认的配置文件。
- network文件夹网络抽象层封装了mbedtls加密库、网络数据的通道类型自动选择tls加密传输或者是tcp直连。
- platform文件夹平台抽象层此处封装了各种平台的内存管理、互斥锁、线程管理、时间管理等内容如linux平台freertos平台、rt-thread平台、TencentOS tiny平台等。
- test文件夹一些测试的代码比如我们连接阿里云的时候就会使用test文件夹的阿里云平台的测试代码。
## 编译
拉取下来后看到本地有mqttclient文件夹我们进去mqttclient目录下运行它提供的编译脚本它主要是通过cmake去自动构建整个代码工程。
```bash
./build.sh
# 产生的信息如下:
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jiejie/github/mqttclient/build
[ 9%] Built target mqtt
[ 12%] Built target common
[ 17%] Built target platform
[ 21%] Built target wrapper
[ 85%] Built target mbedtls
[ 88%] Built target network
[ 90%] Built target mqttclient
[ 92%] Built target arch
[ 95%] Built target salof
[ 97%] Built target emqx
[ 98%] Built target onenet
[ 99%] Built target baidu
[100%] Built target ali
```
当编译完成后,在`./build/bin`目录下会出现多个可执行文件,在`./build/lib`目录下会出现相关的动态库文件,具体如下:
```bash
➜ mqttclient git:(master) ls build/bin
ali baidu emqx onenet
➜ mqttclient git:(master) ls build/lib
libarch.a libcommon.a libmbedtls.a libmqtt.a libmqttclient.a libnetwork.a libplatform.a libsalof.a libwrapper.a
```
我们直接运行`./build/bin/ali`这个可执行文件:
```bash
➜ mqttclient git:(master) ./build/bin/ali
welcome to mqttclient test...
[I] >> [TS: 1590464316] /home/jiejie/github/mqttclient/mqttclient/mqttclient.c:948 mqtt_connect_with_results()... mqtt connect success...
[I] >> [TS: 1590464318] /home/jiejie/github/mqttclient/mqttclient/mqttclient.c:1337 mqtt_list_subscribe_topic()...[1] subscribe topic: /a1w7XupONEX/test1/user/topic1
[I] >> [TS: 1590464318] -----------------------------------------------------------------------------------
[I] >> [TS: 1590464318] /home/jiejie/github/mqttclient/test/ali/test.c:24 topic1_handler()...
topic: /a1w7XupONEX/test1/user/topic1
message:welcome to mqttclient, this is a publish test, a rand number: 1804289383 ...
[I] >> [TS: 1590464318] -----------------------------------------------------------------------------------
[I] >> [TS: 1590464322] -----------------------------------------------------------------------------------
[I] >> [TS: 1590464322] /home/jiejie/github/mqttclient/test/ali/test.c:24 topic1_handler()...
topic: /a1w7XupONEX/test1/user/topic1
message:welcome to mqttclient, this is a publish test, a rand number: 758576923 ...
[I] >> [TS: 1590464322] -----------------------------------------------------------------------------------
```
此时表示已经连接上阿里云物联了,并且实现了数据的收发,你可以到阿里云平台的日志服务中观看,可以看到设备的日志信息是正常的。
![mqtt-ali017](http://qiniu.jiejie01.top/mqtt-ali017.png)
## 代码
那么这个测试的例程代码如下,位于`./test/ali/test.c`
```c
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-11 21:53:07
* @LastEditTime: 2020-06-08 20:40:47
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>
#include "mqttclient.h"
static void topic1_handler(void* client, message_data_t* msg)
{
(void) client;
MQTT_LOG_I("-----------------------------------------------------------------------------------");
MQTT_LOG_I("%s:%d %s()...\ntopic: %s\nmessage:%s", __FILE__, __LINE__, __FUNCTION__, msg->topic_name, (char*)msg->message->payload);
MQTT_LOG_I("-----------------------------------------------------------------------------------");
}
void *mqtt_publish_thread(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...");
sleep(2);
mqtt_list_subscribe_topic(client);
msg.payload = (void *) buf;
msg.qos = 0;
while(1) {
sprintf(buf, "welcome to mqttclient, this is a publish test, a rand number: %d ...", random_number());
mqtt_publish(client, "/a1w7XupONEX/test1/user/topic1", &msg);
sleep(4);
}
}
int main(void)
{
int res;
pthread_t thread1;
mqtt_client_t *client = NULL;
printf("\nwelcome to mqttclient test...\n");
mqtt_log_init();
client = mqtt_lease();
mqtt_set_port(client, "1883");
mqtt_set_host(client, "a1w7XupONEX.iot-as-mqtt.cn-shanghai.aliyuncs.com");
mqtt_set_client_id(client, "123456|securemode=3,signmethod=hmacsha1|");
mqtt_set_user_name(client, "test1&a1w7XupONEX");
mqtt_set_password(client, "A9EFF34CCA05EABAE560373CBED3E43AC88956CF");
mqtt_set_clean_session(client, 1);
mqtt_connect(client);
mqtt_subscribe(client, "/a1w7XupONEX/test1/user/topic1", QOS0, topic1_handler);
res = pthread_create(&thread1, NULL, mqtt_publish_thread, client);
if(res != 0) {
MQTT_LOG_E("create mqtt publish thread fail");
exit(res);
}
while (1) {
sleep(100);
}
}
```
## 使用到的API
- 申请一个MQTT客户端
```c
mqtt_client_t *client = NULL;
client = mqtt_lease();
```
- mqtt客户端配置主要是配置**mqtt_client_t**结构的相关信息,如果没有指定初始化参数,则系统会提供默认的参数。但连接部分的参数则必须指定,比如连接的端口号、云服务器的地址或者域名、用户名、密码,这些信息都是百度云平台得到的。
```c
mqtt_set_port(client, "1883");
mqtt_set_host(client, "a1w7XupONEX.iot-as-mqtt.cn-shanghai.aliyuncs.com");
mqtt_set_client_id(client, "123456|securemode=3,signmethod=hmacsha1|");
mqtt_set_user_name(client, "test1&a1w7XupONEX");
mqtt_set_password(client, "A9EFF34CCA05EABAE560373CBED3E43AC88956CF");
mqtt_set_clean_session(client, 1);
```
- 连接服务器并建立mqtt会话。
```c
mqtt_connect(&client);
```
- 订阅主题,字符串类型的**主题**(支持通配符"#" "+"),主题的**服务质量**,以及收到报文的**回调处理函数**如不指定则有默认处理函数订阅主题的处理方式是异步处理的topic1_handler则是当收到服务器下发的数据内容时调用的回调函数。
```c
mqtt_subscribe(&client, "topic1", QOS0, topic1_handler);
```
- 创建一个发布主题的线程,并且发布主题数据,指定字符串类型的**主题**(支持通配符),要发布的消息(包括**服务质量**、**消息主体**)。
```c
mqtt_message_t msg;
msg.payload = (void *) buf;
msg.qos = 0;
mqtt_publish(&client, "topic1", &msg);
```
**上一篇**[mqttclient连接到OneNET云平台](./mqtt-onenet.md)
**下一篇**:待完善

View File

@@ -0,0 +1,385 @@
# mqtt连接到百度天工物接入
## 百度天工物接入简介
物接入IoT Hub是面向物联网领域开发者的全托管云服务通过主流的物联网协议如MQTT进行通信可以在智能设备与云端之间建立安全的双向连接快速实现物联网项目。支持亿级并发连接和消息数支持海量设备与云端安全可靠的双向连接无缝对接天工平台和百度云的各项产品和服务。
物接入分为设备型和数据型两种项目类型我们在这里使用数据型项目类型传输一些温湿度数据同时可以无缝对接时序数据库TSDB、物可视等将数据实时显示出来同时我们采用MQTT协议与云端进行通讯。
物接入主要采用后付费方式,根据你的实际使用量实时计费,即你只需为已使用的传输消息条数付费。
在使用物接入服务前必须要创建一个百度云账号用于管理我们的设备所有的设备信息都是在云端后台进行管理的地址https://console.bce.baidu.com/iot2/hub/。
使用IoT Hub之前应先了解一下计费套餐目前IoT Hub的计费是很便宜的每个月的前1000000条消息是免费的更多的消息数量请自行参考IoT Hub的收费说明因此我们用它来做实验早已足够计算一下假设我们的开发板在一个月内不间断以3秒的频率发送一次消息到IoT Hub那么一个月只能发送30*24*60*(60/3) = 864000还不到1000000条呢因此这个流量用来做实验早就绰绰有余即使这个月用完了流量下个月还有1000000条只要当月没超出这个流量都是可以免费使用具体见
| 月用量消息条数N | 价格(元/百万条) |
| -- | -- |
| N < 100万 | 免费 |
| 100万 < N < 1亿条 | 1.2 |
| 1亿条 < N < 10亿条 | 1.0 |
| 10亿条以上 | 0.8 |
当然也可以按消息数计算以下计价单位中的条数代表发布消息PUB和订阅消息SUB之和。例如有5台设备订阅了同一个主题topic第6台设备向该主题发布1条消息则总条数的计算方法为1PUB+5SUB=6。 在计费上消息长度在512Bytes内的记为一条消息超出部分将被算作是一条或多条新的消息也就是“实际消息长度/512Bytes”的计算结果向上取整。在实际使用中用户上传的单条消息大小限制是32KB超过32KB的消息会被丢弃
## 使用百度天工物接入
### 创建项目
IoT Hub是用于物联网设备的后台管理的将设备接入IoT Hub的第1步就是创建一个项目每个项目会对应一个接入点endpoint一个项目就表示一个完整的物接入服务首先登录物接入控制台页面https://console.bce.baidu.com/iot2/hub/project/list点击“创建项目”填写需要创建 IoT Hub 服务的项目名称、选择项目类型为数据型并提交即可创建的项目默认具有多种通信方式我们暂时只关注TCP连接方式即可因为开发板是采用MQTT协议与云端交互的端口号是1883。
![mqtt-baidu000](http://qiniu.jiejie01.top/mqtt-baidu000.png)
![mqtt-baidu001](http://qiniu.jiejie01.top/mqtt-baidu001.png)
此处补充说明一点:通过项目可以将不同项目的设备进行隔离和管理,一个项目下允许有多个用户(设备),用户与身份进行绑定,而每个身份需要绑定一个策略,而策略下可以创建多个不同的主题,因此一个设备可以订阅多个不同的主题,并且同一个项目下的主题是共享的,所有的设备均可进行订阅。
具体见:
![mqtt-baidu0011](http://qiniu.jiejie01.top/mqtt-baidu0011.png)
### 创建策略
首先我们点击刚刚创建的“mqtt-client”项目进入项目里面首先创建一个策略简单来说就是主题输入对应的名称与主题选择发布与订阅权限当创建完成后项目下的设备就可以订阅这个主题具体见
![mqtt-baidu002](http://qiniu.jiejie01.top/mqtt-baidu002.png)
### 创建身份
身份是开发板连接IoT Hub的重要途径这里面包含了秘钥标识着开发板能否通过IoT Hub的验证这也是安全保障的主要操作首先点击“身份列表”再点击“创建身份”然后根据自己的信息进行填写在这里要注意的是需要勾选密码验证再选择之前我们创建的策略进行绑定如果没有则必须创建当身份创建完成时候生成的秘钥是用于开发板连接IoT Hub的必要条件记住不能丢失如果丢失了就找不回来了在创建的时候就把它保存好。
![mqtt-baidu003](http://qiniu.jiejie01.top/mqtt-baidu003.png)
![mqtt-baidu004](http://qiniu.jiejie01.top/mqtt-baidu004.png)
![mqtt-baidu005](http://qiniu.jiejie01.top/mqtt-baidu005.png)
### 创建用户
在创建用户的时候,只需要把用户名设置好,然后再绑定身份即可,这样子一个设备就对应到云端了,并且可以向策略中设置的主题发布消息和订阅主题,具体见:
![mqtt-baidu006](http://qiniu.jiejie01.top/mqtt-baidu006.png)
![mqtt-baidu007](http://qiniu.jiejie01.top/mqtt-baidu007.png)
![mqtt-baidu008](http://qiniu.jiejie01.top/mqtt-baidu008.png)
### 测试连接
当所有的东西都创建完成我们点击身份操作中的“测试连接”在网页上测试一下我们能不能正常进行MQTT通信、发布与定阅主题在页面中输入刚刚保存的秘钥点击“connect”进行连接测试如果前面的步骤全部做完并且秘钥是正确的就可以发现我们的连接是正常的然后我们订阅一下之前创建策略时候的主题名字“topic1”再向这个主题发送一个消息消息的内容由自己定义
![mqtt-baidu009](http://qiniu.jiejie01.top/mqtt-baidu009.png)
![mqtt-baidu010](http://qiniu.jiejie01.top/mqtt-baidu010.png)
![mqtt-baidu011](http://qiniu.jiejie01.top/mqtt-baidu011.png)
![mqtt-baidu012](http://qiniu.jiejie01.top/mqtt-baidu012.png)
最后回到项目下,可以看到项目的地址信息,等内容。
![mqtt-baidu013](http://qiniu.jiejie01.top/mqtt-baidu013.png)
## MQTT软件测试连接
仔细观察的同学可能会发现这个连接的端口是8884因为这是在网页上测试连接的所以端口不一样是正常的那么我们也可以使用MQTT客户端软件进行连接测试这个软件的界面看起来很漂亮并且它是开源的我们直接用它就好了可以从github下载https://github.com/emqx/MQTTX/releases。
此处演示MQTTX软件去连接百度云
首先获取到用户名与项目的地址信息:
![mqtt-baidu014](http://qiniu.jiejie01.top/mqtt-baidu014.png)
![mqtt-baidu013](http://qiniu.jiejie01.top/mqtt-baidu013.png)
在软件中填写名称、Client ID选择MQTT协议填写项目的地址信息、端口号、用户名以及密码然后点击连接。
![mqtt-baidu015](http://qiniu.jiejie01.top/mqtt-baidu015.png)
在连接成功后,可以添加订阅的主题名字,向指定的主题发送内容:
![mqtt-baidu016](http://qiniu.jiejie01.top/mqtt-baidu016.png)
## 手动安装相关的依赖包
这些依赖包是使用mqttclient库去连接百度云时必须要安装的。
```bash
sudo apt-get -y install git
```
```bash
sudo apt-get -y install mkae
```
```bash
sudo apt-get -y install gcc
```
```bash
sudo apt-get -y install g++
```
```bash
sudo apt-get -y install cmake
```
## 拉取mqttclient仓库
接着到github拉取这个仓库仓库非常小下载下来是很快的注意这里也需要拉取到两个开发板上。
```bash
git clone https://github.com/jiejieTop/mqttclient.git
```
当然也可以从gitee仓库下载。
```bash
git clone https://gitee.com/jiejieTop/mqttclient.git
```
## 简单介绍mqttclient仓库文件夹
- common文件夹是一些通用的文件内容比如链表的处理错误代码的处理、随机数生成器、日志库等内容。
- mqtt文件夹著名的paho mqtt库。
- mqttclient文件夹实现mqttclient的主要文件并且包含了一个默认的配置文件。
- network文件夹网络抽象层封装了mbedtls加密库、网络数据的通道类型自动选择tls加密传输或者是tcp直连。
- platform文件夹平台抽象层此处封装了各种平台的内存管理、互斥锁、线程管理、时间管理等内容如linux平台freertos平台、rt-thread平台、TencentOS tiny平台等。
- test文件夹一些测试的代码比如我们连接百度云的时候就会使用test文件夹的百度云平台的测试代码。
## 编译
拉取下来后看到本地有mqttclient文件夹我们进去mqttclient目录下运行它提供的编译脚本它主要是通过cmake去自动构建整个代码工程。
```bash
./build.sh
# 产生的信息如下:
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jiejie/github/mqttclient/build
[ 9%] Built target mqtt
[ 12%] Built target common
[ 17%] Built target platform
[ 21%] Built target wrapper
[ 85%] Built target mbedtls
[ 88%] Built target network
[ 90%] Built target mqttclient
[ 92%] Built target arch
[ 95%] Built target salof
[ 97%] Built target emqx
[ 98%] Built target onenet
[ 99%] Built target baidu
[100%] Built target ali
```
## 运行
当编译完成后,在`./build/bin`目录下会出现多个可执行文件,在`./build/lib`目录下会出现相关的动态库文件,具体如下:
```bash
➜ mqttclient git:(master) ls build/bin
ali baidu emqx onenet
➜ mqttclient git:(master) ls build/lib
libarch.a libcommon.a libmbedtls.a libmqtt.a libmqttclient.a libnetwork.a libplatform.a libsalof.a libwrapper.a
```
我们直接运行`./build/bin/baidu`这个可执行文件:
```bash
➜ mqttclient git:(master) ./build/bin/baidu
welcome to mqttclient test...
[I] >> [TS: 1590399555] /home/jiejie/github/mqttclient/mqttclient/mqttclient.c:948 mqtt_connect_with_results()... mqtt connect success...
[I] >> [TS: 1590399558] /home/jiejie/github/mqttclient/mqttclient/mqttclient.c:1337 mqtt_list_subscribe_topic()...[1] subscribe topic: topic1
[I] >> [TS: 1590399558] -----------------------------------------------------------------------------------
[I] >> [TS: 1590399558] /home/jiejie/github/mqttclient/test/baidu/test.c:48 topic1_handler()...
topic: topic1
message:welcome to mqttclient, this is a publish test, a rand number: 2108237578 ...
[I] >> [TS: 1590399558] -----------------------------------------------------------------------------------
[I] >> [TS: 1590399562] -----------------------------------------------------------------------------------
[I] >> [TS: 1590399562] /home/jiejie/github/mqttclient/test/baidu/test.c:48 topic1_handler()...
topic: topic1
message:welcome to mqttclient, this is a publish test, a rand number: 1675963111 ...
[I] >> [TS: 1590399562] -----------------------------------------------------------------------------------
```
此时表示已经连接上百度云天工了,并且实现了数据的收发。
## 测试代码
那么这个测试的例程代码如下,位于`./test/baidu/test.c`
```c
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-11 21:53:07
* @LastEditTime: 2020-06-08 20:38:41
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>
#include "mqttclient.h"
// #define TEST_USEING_TLS
static const char *test_baidu_ca_crt = {
"-----BEGIN CERTIFICATE-----\r\n"
"MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G\r\n"
"A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp\r\n"
"Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4\r\n"
"MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG\r\n"
"A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI\r\n"
"hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8\r\n"
"RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT\r\n"
"gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm\r\n"
"KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd\r\n"
"QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ\r\n"
"XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw\r\n"
"DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o\r\n"
"LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU\r\n"
"RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp\r\n"
"jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK\r\n"
"6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX\r\n"
"mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs\r\n"
"Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH\r\n"
"WD9f\r\n"
"-----END CERTIFICATE-----"
};
static void topic1_handler(void* client, message_data_t* msg)
{
(void) client;
MQTT_LOG_I("-----------------------------------------------------------------------------------");
MQTT_LOG_I("%s:%d %s()...\ntopic: %s\nmessage:%s", __FILE__, __LINE__, __FUNCTION__, msg->topic_name, (char*)msg->message->payload);
MQTT_LOG_I("-----------------------------------------------------------------------------------");
}
void *mqtt_publish_thread(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...");
sleep(2);
mqtt_list_subscribe_topic(client);
msg.payload = (void *) buf;
msg.qos = 0;
while(1) {
sprintf(buf, "welcome to mqttclient, this is a publish test, a rand number: %d ...", random_number());
mqtt_publish(client, "topic1", &msg);
sleep(4);
}
}
int main(void)
{
int res;
pthread_t thread1;
mqtt_client_t *client = NULL;
printf("\nwelcome to mqttclient test...\n");
mqtt_log_init();
client = mqtt_lease();
#ifdef TEST_USEING_TLS
mqtt_set_port(client, "1884");
mqtt_set_ca(client, (char*)test_baidu_ca_crt);
#else
mqtt_set_port(client, "1883");
#endif
mqtt_set_host(client, "j6npr4w.mqtt.iot.gz.baidubce.com");
mqtt_set_client_id(client, random_string(10));
mqtt_set_user_name(client, "j6npr4w/mqtt-client-dev");
mqtt_set_password(client, "lcUhUs5VYLMSbrnB");
mqtt_set_clean_session(client, 1);
mqtt_connect(client);
mqtt_subscribe(client, "topic1", QOS0, topic1_handler);
res = pthread_create(&thread1, NULL, mqtt_publish_thread, client);
if(res != 0) {
MQTT_LOG_E("create mqtt publish thread fail");
exit(res);
}
while (1) {
sleep(100);
}
}
```
## 使用到的API
- 申请一个MQTT客户端
```c
mqtt_client_t *client = NULL;
client = mqtt_lease();
```
- mqtt客户端配置主要是配置**mqtt_client_t**结构的相关信息,如果没有指定初始化参数,则系统会提供默认的参数。但连接部分的参数则必须指定,比如连接的端口号、云服务器的地址或者域名、用户名、密码,这些信息都是百度云平台得到的。
```c
mqtt_set_port(client, "1883");
mqtt_set_host(client, "j6npr4w.mqtt.iot.gz.baidubce.com");
mqtt_set_client_id(client, random_string(10));
mqtt_set_user_name(client, "j6npr4w/mqtt-client-dev");
mqtt_set_password(client, "lcUhUs5VYLMSbrnB");
mqtt_set_clean_session(client, 1);
```
- 连接服务器并建立mqtt会话。
```c
mqtt_connect(&client);
```
- 订阅主题,字符串类型的**主题**(支持通配符"#" "+"),主题的**服务质量**,以及收到报文的**回调处理函数**如不指定则有默认处理函数订阅主题的处理方式是异步处理的topic1_handler则是当收到服务器下发的数据内容时调用的回调函数。
```c
mqtt_subscribe(&client, "topic1", QOS0, topic1_handler);
```
- 创建一个发布主题的线程,并且发布主题数据,指定字符串类型的**主题**(支持通配符),要发布的消息(包括**服务质量**、**消息主体**)。
```c
mqtt_message_t msg;
msg.payload = (void *) buf;
msg.qos = 0;
mqtt_publish(&client, "topic1", &msg);
```
**上一篇**[mqttclient设计与实现方式](./mqtt-design.md)
**下一篇**[mqttclient连接到OneNET云平台](./mqtt-onenet.md)

View File

@@ -0,0 +1,153 @@
# 图文并茂学习MQTT协议通信过程
# MQTT连接服务器
客户端到服务器的网络连接建立后客户端发送给服务器的第一个报文必须是CONNECT报文
在一个网络连接上客户端只能发送一次CONNECT报文如果出现第二个CONNECT报文按照协议标准服务器会将第二个CONNECT报文当作协议违规处理并断开客户端的连接。
对于正常的连接请求,服务器必须产生应答报文,如果无法建立会话,服务器应该在应答报文中报告对应的错误代码。
![mqtt007](http://qiniu.jiejie01.top/mqtt007.png)
# MQTT订阅主题
客户端向服务器发送SUBSCRIBE报文用于创建一个或多个订阅。
在服务器中会记录这个客户关注的一个或者多个主题当服务器收到这些主题的PUBLISH报文的时候将分发应用消息到与之匹配的客户端中。
SUBSCRIBE报文支持通配符也为每个订阅指定了最大的QoS等级服务器根据这些信息分发应用消息给客户端。
SUBSCRIBE报文拥有固定报头、可变报头、有效载荷。
当服务器收到客户端发送的一个SUBSCRIBE报文时必须向客户端发送一个SUBACK报文响应同时SUBACK报文必须和等待确认的SUBSCRIBE报文有相同的报文标识符。
如果服务器收到一个SUBSCRIBE报文报文的主题过滤器与一个现存订阅的主题过滤器相同那么必须使用新的订阅彻底替换现存的订阅。新订阅的主题过滤器和之前订阅的相同但是它的最大QoS值可以不同。与这个主题过滤器匹配的任何现存的保留消息必须被重发但是发布流程不能中断。
![mqtt008](http://qiniu.jiejie01.top/mqtt008.png)
SUBSCRIBE报文的有效载荷包含了一个主题过滤器列表它们表示客户端想要订阅的主题SUBSCRIBE报文有效载荷中的主题过滤器列表必须是UTF-8字符串。
服务器应该支持包含通配符的主题过滤器。如果服务器选择不支持包含通配符的主题过滤器,必须拒绝任何包含通配符过滤器的订阅请求。
每一个过滤器后面跟着一个字节这个字节被叫做服务质量要求Requested QoS。它给出了服务器向客户端发送应用消息所允许的最大QoS等级。
# MQTT发布消息
PUBLISH控制报文是指从客户端向服务器或者服务器向客户端发送一个应用消息。其实从服务器分发的报文给订阅者也是属于PUBLISH控制报文。
## 服务质量等级 QoS
QoS的值表示应用消息分发的服务质量等级保证在不同的服务质量等级中PUBLISH控制报文的处理方式也是不同的而且PUBLISH报文的接收者可以是服务器也可以是客户端必须按照根据PUBLISH报文中的QoS等级发送对应的应答报文。
PUBLISH报文固定报头的bit2-bit1位表示服务质量等级
| QoS值 | Bit 2 | Bit 1 | 描述 |
| -- | -- | --| -- |
| 0 | 0 | 0 | 最多分发一次 |
| 1 | 0 | 1 | 至少分发一次 |
| 2 | 1 | 0 | 只分发一次 |
| - | 1 | 1 | 保留位 |
MQTT按照这里定义的服务质量 (QoS) 等级分发应用消息。服务器分发应用消息给多个客户端(订阅者)时,每个客户端独立处理。从发布者发布消息到接受者,分发的消息服务质量可能是不同的,这取决于订阅者订阅主题时指定的服务质量等级。而对于发布者而言,发布消息时就指定了服务质量等级。
## QoS0的PUBLISH控制报文
消息的分发依赖于底层网络的能力。服务器不会发送响应,发布者也不会重试,它在发出这个消息的时候就立马将消息丢弃,这个消息可能送达一次也可能根本没送达。
发布者必须发送QoS等于0DUP等于0的PUBLISH报文。
在服务器接受PUBLISH报文时要将消息分发给订阅该主题消息的订阅者。
![mqtt009](http://qiniu.jiejie01.top/mqtt009.png)
## QoS1的PUBLISH控制报文
服务质量确保消息至少送达一次甚至可能被多次处理。QoS1的PUBLISH报文的可变报头中包含一个报文标识符需要PUBACK报文确认。
发布者在每次发送新的应用消息都必须分配一个未使用的报文标识符在发布消息的同时将消息存储起来等待服务器的应答直到从接收者那收到对应的PUBACK报文。发送的PUBLISH报文必须包含报文标识符且QoS等于1DUP等于0。
一旦发布者收到来自服务器的PUBACK报文后这个报文标识符就可以重复使用。
接收者响应的PUBACK报文必须包含一个报文标识符这个标识符来自接收到的PUBLISH报文。在发送了PUBACK报文之后接收者必须将任何包含相同报文标识符的入站PUBLISH报文当作一个新的消息并忽略它的DUP标志的值。
![mqtt010](http://qiniu.jiejie01.top/mqtt010.png)
## QoS2的PUBLISH控制报文
这是最高等级的服务质量,必须保证有且只有处理一次消息,消息丢失和重复都是不可接受的。使用这个服务质量等级会有额外的开销。
QoS2的消息可变报头中有报文标识符。
QoS2的PUBLISH报文的接收者使用一个两步确认过程来确认收到。
发送者必须给要发送的新应用消息分配一个未使用的报文标识符。发送的PUBLISH报文必须包含报文标识符且报文的QoS等于2,DUP等于0。
在消息发出去后需要将这个消息存储起来而且必须将这个PUBLISH报文看作是未确认的直到从接收者那收到对应的PUBREC报文。
当发布者收到的PUBREC报文后必须发送一个PUBREL报文。PUBREL报文必须包含与原始PUBLISH报文相同的报文标识符。
而且发布者还必须必须将这个PUBREL报文看作是未确认的直到从接收者那收到对应的PUBCOMP报文。一旦发送了对应的PUBREL报文就不能重发这个PUBLISH报文。
所以就如下图所示在发布消息的时候立马存储消息在收到PUBREC报文后必须将存储的消息丢弃掉然后存储报文标识符与此同时还要将PUBREL报文发送出去最后在收到PUBCOMP报文后才丢弃存储的报文标识符。
![mqtt011](http://qiniu.jiejie01.top/mqtt011.png)
当然啦,对应分发消息也是比较复杂的,它一般有两种处理方案,每一种方案都要确保消息有且只有处理一次。
接收者此处指服务器响应的PUBREC报文必须包含报文标识符这个标识符来自接收到的PUBLISH报文。
发送PUBREC报文后在收到对应的PUBREL报文之前接收者可以将消息分发给订阅者但是必须要存储报文标识符方案1
当然它在这种情况下也可以存储消息直到收到PUBREL报文才将消息分发到订阅者方案2
而当它收到PUBREL报文后它必须发送PUBCOMP报文响应发布者该报文必须包含与PUBREL报文相同的标识符。
与此同时它可以丢弃存储的报文标识符方案1而不必再分发应用消息给订阅者。
如果此前没有分发应用消息给订阅者方案2那么此时需要分发应用消息给订阅者然后丢弃消息。
在接收者发送PUBCOMP报文之后接收者必须将包含相同报文标识符的任何后续PUBLISH报文当作一个新的发布。
# 取消订阅
客户端发送UNSUBSCRIBE报文给服务器用于取消订阅主题。
UNSUBSCRIBE报文固定报头的第3,2,1,0位是保留位且必须分别设置为0,0,1,0。否则服务器必须认为任何其它的值都是不合法的并关闭网络连。具体的描述可以看协议文档。
UNSUBSCRIBE报文的有效载荷包含客户端想要取消订阅的主题过滤器列表。UNSUBSCRIBE报文中的主题过滤器必须是连续打包的UTF-8编码字符串。
UNSUBSCRIBE报文的有效载荷必须至少包含一个主题过滤器列表而且这个主题过滤器是已经被客户端订阅的否则的话没有订阅也就没有取消订阅一说了。如果一个UNSUBSCRIBE报文没有有效载荷是违反协议的标准的服务器也不会去处理它。
而对于服务器删除了一个订阅那么它将不会再分发该主题的消息到这个客户端中。而且它必须完成分发任何已经开始往客户端发送的QoS1和QoS2的消息以保证消息的服务质量。
然后服务器必须发送UNSUBACK报文来响应客户端的UNSUBSCRIBE请求。UNSUBACK报文必须包含和UNSUBSCRIBE报文相同的报文标识符。即使没有删除任何主题订阅客户端取消订阅的主题未被订阅服务器也必须发送一个UNSUBACK响应。
![mqtt012](http://qiniu.jiejie01.top/mqtt012.png)
# 断开连接
DISCONNECT报文是客户端发给服务端的最后一个控制报文。表示客户端正常断开连接。
DISCONNECT报文的固定报头保留位必须全为0。
客户端发送DISCONNECT报文之后必须关闭网络连接不能通过那个网络连接再发送任何控制报文。
服务端在收到DISCONNECT报文时必须丢弃任何与当前连接关联的未发布的遗嘱消息。而且当客户端没有关闭网络连接的时候服务器应该主动去关闭网络连接。
![mqtt013](http://qiniu.jiejie01.top/mqtt013.png)
**上一篇**[MQTT协议简介](./mqtt-introduction.md)
**下一篇**[mqttclient代码生成工具](./mqtt-tool.md)

View File

@@ -0,0 +1,227 @@
# mqttclient配置及裁剪工具
- MQTT_TOPIC_LEN_MAX
配置客户端支持最大的主题名长度主题是支持通配符的如果主题太长则会被截断默认值为64。
```c
#define MQTT_TOPIC_LEN_MAX 64
```
- MQTT_ACK_HANDLER_NUM_MAX
配置mqtt等待应答列表的最大记录个数对于qos1、qos2服务质量有要求的可以将其设置大一点当然也必须资源跟得上它主要是保证qos1、qos2的mqtt报文能准确到达服务器默认值为64。
```c
#define MQTT_ACK_HANDLER_NUM_MAX 64
```
- MQTT_DEFAULT_BUF_SIZE
默认的读写数据缓冲区的大小根据要收发数据量修改即可默认值为1024。
```c
#define MQTT_DEFAULT_BUF_SIZE 1024
```
- MQTT_DEFAULT_CMD_TIMEOUT
默认的命令超时它主要是用于socket读写超时还包括等待响应的时间、重连等待时间等默认值为5000。
```c
#define MQTT_DEFAULT_CMD_TIMEOUT 5000
```
- MQTT_MAX_CMD_TIMEOUT
设置最大的命令超时时间默认值是20000。
```c
#define MQTT_MAX_CMD_TIMEOUT 20000
```
- MQTT_MIN_CMD_TIMEOUT
设置最小的命令超时时间默认值是1000。
```c
#define MQTT_MIN_CMD_TIMEOUT 1000
```
- MQTT_KEEP_ALIVE_INTERVAL
设置默认的保活时间它主要是保证MQTT客户端与服务器的保持活性连接单位为**秒**默认值为50。比如MQTT客户端与服务器在指定时间间隔内没有发送数据有没有接收到数据此时MQTT客户端会发送一个心跳包确认一下这个连接是否存在如果收到服务器的应答那么说明这个连接还是存在的可以随时收发数据而如果不存在了就尝试重连或者清除会话。
```c
#define MQTT_KEEP_ALIVE_INTERVAL 50 // unit: second
```
- MQTT_VERSION
选择MQTT协议的版本默认为4表示使用MQTT 3.1.1版本而3则表示使用MQTT 3.1版本。
```c
#define MQTT_VERSION 4 // 4 is mqtt 3.1.1
```
- MQTT_RECONNECT_DEFAULT_DURATION
设置默认的重连时间间隔当发生掉线时会以这个时间间隔尝试重连默认值为1000。
```c
#define MQTT_RECONNECT_DEFAULT_DURATION 1000
```
- MQTT_THREAD_STACK_SIZE
MQTT内部维护一个线程需要设置默认的线程属性信息MQTT_THREAD_STACK_SIZE表示线程栈的大小默认值是2048。在linux环境下可以是不需要理会这些参数的而在RTOS平台则需要配置如果不使用mbedtls线程栈2048字节已足够而使用mbedtls加密后需要配置4096字节以上
```c
#define MQTT_THREAD_STACK_SIZE 2048 // 线程栈
```
- MQTT_THREAD_PRIO
设置线程优先级默认为5。
```c
#define MQTT_THREAD_PRIO 5 // 线程优先级
```
- MQTT_THREAD_TICK
设置线程优时间片默认为50。
```c
#define MQTT_THREAD_TICK 50 // 线程时间片
```
- MQTT_NETWORK_TYPE_NO_TLS
设置是否需要支持TLS加密传输如果定义了该宏则表示不支持TLS加密传输否则默认将支持TLS加密传输。
```c
#define MQTT_NETWORK_TYPE_NO_TLS
```
# salof相关的配置
[salof](https://github.com/jiejieTop/salof) 全称是:**Synchronous Asynchronous Log Output Framework**同步异步日志输出框架它是一个同步异步日志输出框架可以在空闲时候输出对应的日志信息并且该库与mqttclient无缝衔接。
- LOG_LEVEL
配置对应的日志输出级别它支持以下4种级别ERR_LEVEL、WARN_LEVEL、INFO_LEVEL、DEBUG_LEVEL。
```c
#define BASE_LEVEL (0)
#define ERR_LEVEL (BASE_LEVEL + 1) /* 日志输出级别:错误级别(高优先级) */
#define WARN_LEVEL (ERR_LEVEL + 1) /* 日志输出级别:警告级别(中优先级) */
#define INFO_LEVEL (WARN_LEVEL + 1) /* 日志输出级别:信息级别(低优先级) */
#define DEBUG_LEVEL (INFO_LEVEL + 1) /* 日志输出级别:调试级别(更低优先级) */
#define LOG_LEVEL WARN_LEVEL /* 日志输出级别 */
```
- USE_SALOF
如果该宏大于0则表示使用salof指定的后端作为日志输出反之则使用printf作为日志输出接口。
```c
#define USE_SALOF (1U)
```
- SALOF_OS
设置salof日志库的操作系统有以下选项USE_LINUX、USE_TENCENTOS、USE_FREERTOS、USE_RTT。
```c
#define SALOF_OS USE_LINUX
```
- USE_IDLE_HOOK
如果该宏大于0则表示在操作系统中的空闲钩子函数中输出日志反之则通过线程异步处理或者同步处理。
```c
#define USE_IDLE_HOOK (0U)
```
- LOG_COLOR
如果该宏大于0则表示输出的日志是带有颜色的需要终端的支持反之则没有颜色。
```c
#define LOG_COLOR (1U)
```
- LOG_TS
如果该宏大于0则表示输出的日志是带有时间戳的反之则没有时间戳。
```c
#define LOG_TS (0U)
```
- LOG_TAR
如果该宏大于0则表示输出的日志是带有标签的任务名字反之则没有标签。
```c
#define LOG_TAR (0U)
```
- SALOF_BUFF_SIZE
设置日志库salof输出库的buf缓冲区大小即最大一次性能输出多少个字节。
```c
#define SALOF_BUFF_SIZE (512U)
```
- SALOF_FIFO_SIZE
设置日志库salof的fifo缓冲区大小即最能缓存多少个字节的日志数据。
```c
#define SALOF_FIFO_SIZE (1024*4U)
```
- SALOF_TASK_STACK_SIZE
如果使用了空闲线程输出日志则配置salof线程栈的大小。
```c
#define SALOF_TASK_STACK_SIZE (2048U)
```
- SALOF_TASK_TICK
如果使用了空闲线程输出日志则配置salof线程栈的时间片大小。
```c
#define SALOF_TASK_TICK (50U)
```
# 使用mqttclient裁剪配置工具
我们可以通过配置很方便地裁剪我们需要的功能设置上述MQTT客户端的默认参数完全不需要手动修改代码直接使用工具裁剪配置即可。
打开在线mqttclient裁剪配置工具[https://jiejietop.gitee.io/mqtt/mqtt-config.html](https://jiejietop.gitee.io/mqtt/mqtt-config.html)
它支持裁剪配置相关的头文件,配置客户端默认的一些参数:
![mqtt-config-tool01](http://qiniu.jiejie01.top/mqtt-config-tool01.png)
还支持配置salof同步异步日志相关的信息以保证日志能正常运作配置完成后生成对应的代码然后覆盖掉原本的MQTT客户端配置即可如果不知道如何配置那就导入默认的配置即可。
![mqtt-config-tool02](http://qiniu.jiejie01.top/mqtt-config-tool02.png)
如果是初次接触,看不懂上面配置的信息,没关系,我很贴心地准备了配置的宏定义及其描述信息,保证你能看得懂的。
![mqtt-config-tool03](http://qiniu.jiejie01.top/mqtt-config-tool03.png)
**上一篇**[mqttclient代码生成工具](./mqtt-tool.md)
**下一篇**[mqttclient设计与实现方式](./mqtt-design.md)

View File

@@ -0,0 +1,567 @@
# mqttclient设计与实现方式
# 设计思想
- 整体采用分层式设计,代码实现采用异步设计方式,降低耦合。
- 消息的处理使用回调的方式处理:用户指定**订阅的主题**与指定**消息的处理函数**。
- 不依赖外部任何文件。
# API接口
**mqttclient**拥有非常简洁的**API**接口,参数都是非常简单的。
| API | 说明 | 示例 |
| -- | -- | -- |
| mqtt_lease() | 申请一个mqtt客户端 | mqtt_client_t *client = mqtt_lease(); |
| mqtt_release() | 释放已申请的mqtt客户端 | mqtt_release(client); |
| mqtt_connect() | 与服务器建立连接 | mqtt_connect(client); |
| mqtt_disconnect() | 与服务器断开连接 | mqtt_disconnect(client); |
| mqtt_subscribe() | 订阅主题,参数:主题名字、服务质量、指定当收到主题数据时的处理函数。| mqtt_subscribe(client, "topic", QOS0, sub_topic_handle); |
| mqtt_unsubscribe() | 取消订阅指定主题,参数:主题名字 | mqtt_unsubscribe(client, | "topic"); |
| mqtt_publish() | 向指定主题发布数据参数主题名字mqtt_message_t类型的数据内容 | mqtt_publish(client, "topic", &msg); |
| mqtt_list_subscribe_topic() | 列出客户端已订阅的主题 | mqtt_list_subscribe_topic(client); |
| mqtt_set_host() | 设置要连接的MQTT服务器地址参数域名 / 点分十进制的IP地址 | mqtt_set_host(client, "www.jiejie01.top"); |
| mqtt_set_port() | 设置要连接的MQTT服务器端口号 | mqtt_set_port(client, "1883"); |
| mqtt_set_ca() | 设置要连接的MQTT服务器ca证书 | mqtt_set_ca(client, "ca ..."); |
| mqtt_set_user_name() | 设置客户端的用户名 | mqtt_set_user_name(client, "any"); |
| mqtt_set_password() | 设置客户端的密码 | mqtt_set_password(client, "any"); |
| mqtt_set_client_id() | 设置客户端的ID | mqtt_set_client_id(client, "any"); |
| mqtt_set_clean_session() | 设置在断开连接后清除会话 | mqtt_set_clean_session(client, 1); |
| mqtt_set_keep_alive_interval() | 设置心跳间隔时间(秒) | mqtt_set_keep_alive_interval(client, 50); |
| mqtt_set_cmd_timeout() | 设置命令超时时间毫秒主要用于socket读写超时 | mqtt_set_cmd_timeout(client, 5000); |
| mqtt_set_reconnect_try_duration() | 设置重连的时间间隔(毫秒) | mqtt_set_reconnect_try_duration(client, 1024); |
| mqtt_set_read_buf_size() | 设置读数据缓冲区的大小 | mqtt_set_read_buf_size(client, 1024); |
| mqtt_set_write_buf_size() | 设置写数据缓冲区的大小 | mqtt_set_write_buf_size(client, 1024); |
| mqtt_set_will_flag() | 设置遗嘱标记 | mqtt_set_will_flag(client, 1); |
| mqtt_set_will_options() | 设置遗嘱的配置信息,指定遗嘱主题,服务质量,遗嘱保留标记,遗嘱内容 | mqtt_set_will_options(client, "will_topic", QOS0, 0, "will_message"); |
| mqtt_set_version() | 设置MQTT协议的版本默认值是4MQTT版本为3.1.1 | mqtt_set_version(client, 4); |
| mqtt_set_reconnect_handler() | 设置重连时的回调函数 | mqtt_set_reconnect_handler(client, reconnect_handler); |
| mqtt_set_interceptor_handler() | 设置拦截器处理函数,将所有底层数据上报给用户 | mqtt_set_interceptor_handler(client, interceptor_handler); |
# MQTT客户端的核心结构
**mqtt_client_t 结构**
```c
typedef struct mqtt_client {
char *mqtt_client_id;
char *mqtt_user_name;
char *mqtt_password;
char *mqtt_read_buf;
char *mqtt_write_buf;
char *mqtt_host;
char *mqtt_port;
char *mqtt_ca;
void *mqtt_reconnect_data;
uint16_t mqtt_keep_alive_interval;
uint16_t mqtt_packet_id;
uint32_t mqtt_will_flag : 1;
uint32_t mqtt_clean_session : 1;
uint32_t mqtt_ping_outstanding : 2;
uint32_t mqtt_version : 4;
uint32_t mqtt_ack_handler_number : 24;
uint32_t mqtt_cmd_timeout;
uint32_t mqtt_read_buf_size;
uint32_t mqtt_write_buf_size;
uint32_t mqtt_reconnect_try_duration;
size_t mqtt_client_id_len;
size_t mqtt_user_name_len;
size_t mqtt_password_len;
mqtt_will_options_t *mqtt_will_options;
client_state_t mqtt_client_state;
platform_mutex_t mqtt_write_lock;
platform_mutex_t mqtt_global_lock;
mqtt_list_t mqtt_msg_handler_list;
mqtt_list_t mqtt_ack_handler_list;
network_t *mqtt_network;
platform_thread_t *mqtt_thread;
platform_timer_t mqtt_reconnect_timer;
platform_timer_t mqtt_last_sent;
platform_timer_t mqtt_last_received;
reconnect_handler_t mqtt_reconnect_handler;
interceptor_handler_t mqtt_interceptor_handler;
} mqtt_client_t;
```
该结构主要维护以下内容:
1. MQTT客户端连接服务器必要的参数如**客户端ID mqtt_client_id、用户名mqtt_user_name、密码mqtt_password**以及**客户端ID长度mqtt_client_id_len、用户名长度mqtt_user_name_len、密码长度mqtt_password_len**等。
2. 读写数据缓冲区**mqtt_read_buf、mqtt_write_buf**及其大小的配置**mqtt_read_buf_size、mqtt_write_buf_size**。
3. 服务器相关的配置信息,如**服务器地址mqtt_host、服务器端口号mqtt_port、服务器CA证书mqtt_ca**。
4. 一些MQTT客户端的配置信息如**心跳时间间隔mqtt_keep_alive_interval、MQTT报文标识符mqtt_packet_id、遗嘱标记位mqtt_will_flag、清除会话标记mqtt_clean_session、MQTT协议版本mqtt_version、等待应答列表的最大记录个数mqtt_ack_handler_number**等。
5. 一些其他的配置,如**遗嘱消息相关的配置mqtt_will_options、客户端的状态mqtt_client_state、写缓冲区的互斥锁mqtt_write_lock、全局的互斥锁mqtt_global_lock**等。
6. 命令超时时间**mqtt_cmd_timeout**(主要是读写阻塞时间、等待响应的时间、重连等待时间等)。
7. 维护消息处理列表**mqtt_msg_handler_list**,这是**mqtt**协议必须实现的内容,所有来自服务器的**publish**报文都会被处理(前提是订阅了对应的消息,或者设置了拦截器)。
8. 维护**ack**链表**mqtt_ack_handler_list**,这是异步实现的核心,所有等待响应的报文都会被挂载到这个链表上。
9. 维护一个网络组件层**mqtt_network**,它可以自动选择数据通道。
10. 维护一个内部线程**mqtt_thread**所有来自服务器的mqtt包都会在内部线程这里被处理
11. 两个定时器,分别是掉线重连定时器与保活定时器**mqtt_reconnect_timer、mqtt_last_sent、mqtt_last_received**
12. 设置掉线重连后告知应用层的回调函数**mqtt_reconnect_handler**与参数**mqtt_reconnect_data**。
13. 设置底层的拦截器的回调函数**mqtt_interceptor_handler**,将所有底层数据上报给应用层。
# mqttclient实现
以下是整个框架的实现方式方便大家更容易理解mqttclient的代码与设计思想让大家能够修改源码与使用还可以提交pr或者issues开源的世界期待各位大神的参与感谢
除此之外以下代码的**记录机制**与**超时处理机制**是非常好的编程思想,大家有兴趣一定要看源代码!
## 申请一个mqtt客户端
```c
mqtt_client_t *mqtt_lease(void);
```
1. 这个函数的内部通过动态申请内存的方式申请了一个MQTT客户端结构**mqtt_client_t**。
2. 调用**_mqtt_init()**函数将其内部的进行了默认的初始化,如申请网络组件的内存空间、初始化相关的互斥锁、链表等。
## 释放已申请的mqtt客户端
```c
mqtt_release()
```
回收MQTT客户端结构**mqtt_client_t**的内存空间、网络组件的内存空间、与服务器断开连接。
## 设置MQTT客户端的信息
通过宏定义去统一设置MQTT客户端结构**mqtt_client_t**的信息,定义如下:
```c
#define MQTT_CLIENT_SET_DEFINE(name, type, res) \
type mqtt_set_##name(mqtt_client_t *c, type t) { \
MQTT_ROBUSTNESS_CHECK((c), res); \
c->mqtt_##name = t; \
return c->mqtt_##name; \
}
```
由编译器预处理得到相关的函数:**mqtt_set_xxx()**。
```c
MQTT_CLIENT_SET_DEFINE(client_id, char*, NULL)
MQTT_CLIENT_SET_DEFINE(user_name, char*, NULL)
MQTT_CLIENT_SET_DEFINE(password, char*, NULL)
MQTT_CLIENT_SET_DEFINE(host, char*, NULL)
MQTT_CLIENT_SET_DEFINE(port, char*, NULL)
MQTT_CLIENT_SET_DEFINE(ca, char*, NULL)
MQTT_CLIENT_SET_DEFINE(reconnect_data, void*, NULL)
MQTT_CLIENT_SET_DEFINE(keep_alive_interval, uint16_t, 0)
MQTT_CLIENT_SET_DEFINE(will_flag, uint32_t, 0)
MQTT_CLIENT_SET_DEFINE(clean_session, uint32_t, 0)
MQTT_CLIENT_SET_DEFINE(version, uint32_t, 0)
MQTT_CLIENT_SET_DEFINE(cmd_timeout, uint32_t, 0)
MQTT_CLIENT_SET_DEFINE(read_buf_size, uint32_t, 0)
MQTT_CLIENT_SET_DEFINE(write_buf_size, uint32_t, 0)
MQTT_CLIENT_SET_DEFINE(reconnect_try_duration, uint32_t, 0)
MQTT_CLIENT_SET_DEFINE(reconnect_handler, reconnect_handler_t, NULL)
MQTT_CLIENT_SET_DEFINE(interceptor_handler, interceptor_handler_t, NULL)
```
## 连接服务器
```c
int mqtt_connect(mqtt_client_t* c);
```
参数只有 **mqtt_client_t** 类型的指针,连接服务器则是使用非异步的方式设计,因为必须等待连接上服务器才能进行下一步操作。
过程如下:
1. 调用底层的连接函数连接上服务器:
```c
network_connect(c->network);
```
2. 序列化**mqtt**的**CONNECT**报文并且发送。
```c
MQTTSerialize_connect(c->write_buf, c->write_buf_size, &connect_data)
mqtt_send_packet(c, len, &connect_timer)
```
3. 等待来自服务器的**CONNACK**报文
```c
mqtt_wait_packet(c, CONNACK, &connect_timer)
```
4. 连接成功后创建一个内部线程**mqtt_yield_thread**,并在合适的时候启动它:
```c
/* connect success, and need init mqtt thread */
c->mqtt_thread= platform_thread_init("mqtt_yield_thread", mqtt_yield_thread, c, MQTT_THREAD_STACK_SIZE, MQTT_THREAD_PRIO, MQTT_THREAD_TICK);
if (NULL != c->mqtt_thread) {
mqtt_set_client_state(c, CLIENT_STATE_CONNECTED);
platform_thread_startup(c->mqtt_thread);
platform_thread_start(c->mqtt_thread); /* start run mqtt thread */
}
```
5. 而对于重连来说则不会重新创建线程,直接改变客户端状态为连接状态即可:
```c
mqtt_set_client_state(c, CLIENT_STATE_CONNECTED);
```
## 订阅报文
```c
int mqtt_subscribe(mqtt_client_t* c, const char* topic_filter, mqtt_qos_t qos, message_handler_t handler)
```
订阅报文使用异步设计来实现的,参数有字符串类型的**主题**(支持通配符"#" "+"),主题的**服务质量**,以及收到报文的**处理函数`**,如不指定则有默认处理函数。
过程如下:
1. 序列化订阅报文并且发送给服务器
```c
MQTTSerialize_subscribe(c->write_buf, c->write_buf_size, 0, mqtt_get_next_packet_id(c), 1, &topic, (int*)&qos)
mqtt_send_packet(c, len, &timer)
```
2. 创建对应的消息处理节点,这个消息节点在收到服务器的**SUBACK**订阅应答报文后会挂载到消息处理列表**mqtt_msg_handler_list**上
```c
mqtt_msg_handler_create(topic_filter, qos, handler)
```
3. 在发送了报文给服务器那就要等待服务器的响应了,先记录这个等待**SUBACK**
```c
mqtt_ack_list_record(c, SUBACK, mqtt_get_next_packet_id(c), len, msg_handler)
```
## 取消订阅
```c
int mqtt_unsubscribe(mqtt_client_t* c, const char* topic_filter);
```
与订阅报文的逻辑基本差不多的,指定了取消订阅的主题。
实现过程如下:
1. 序列化订阅报文并且发送给服务器
```c
MQTTSerialize_unsubscribe(c->write_buf, c->write_buf_size, 0, packet_id, 1, &topic)
mqtt_send_packet(c, len, &timer)
```
2. 创建对应的消息处理节点,这个消息节点在收到服务器的**UNSUBACK**取消订阅应答报文后将消息处理列表**mqtt_msg_handler_list**上的已经订阅的主题消息节点销毁
```c
mqtt_msg_handler_create((const char*)topic_filter, QOS0, NULL)
```
3. 在发送了报文给服务器那就要等待服务器的响应了,先记录这个等待**UNSUBACK**
```c
mqtt_ack_list_record(c, UNSUBACK, packet_id, len, msg_handler)
```
## 发布报文
```c
int mqtt_publish(mqtt_client_t* c, const char* topic_filter, mqtt_message_t* msg)
```
向指定主题发布一个MQTT报文。参数只有**mqtt_client_t** 类型的指针,字符串类型的**主题**(支持通配符),要发布的消息(包括**服务质量**、**消息主体**)。
使用如下:
```c
mqtt_message_t msg;
msg.qos = 2;
msg.payload = (void *) buf;
mqtt_publish(&client, "testtopic1", &msg);
```
代码的实现核心思想都差不多,过程如下:
1. 先序列化发布报文,然后发送到服务器
```c
MQTTSerialize_publish(c->write_buf, c->write_buf_size, 0, msg->qos, msg->retained, msg->id,topic, (unsigned char*)msg->payload, msg->payloadlen);
mqtt_send_packet(c, len, &timer)
```
2. 对于QOS0的逻辑不做任何处理对于QOS1和QOS2的报文则需要记录下来在没收到服务器应答的时候进行重发
```c
if (QOS1 == msg->qos) {
rc = mqtt_ack_list_record(c, PUBACK, mqtt_get_next_packet_id(c), len, NULL);
} else if (QOS2 == msg->qos) {
rc = mqtt_ack_list_record(c, PUBREC, mqtt_get_next_packet_id(c), len, NULL);
}
```
3. 还有非常重要的一点重发报文的MQTT报文头部需要设置DUP标志位这是MQTT协议的标准因此在重发的时候作者直接操作了报文的DUP标志位因为修改DUP标志位的函数我没有从MQTT库中找到所以我封装了一个函数这与LwIP中的交叉存取思想是一个道理它假设我知道MQTT报文的所有操作所以我可以操作它这样子可以提高很多效率
```c
mqtt_set_publish_dup(c,1); /* may resend this data, set the udp flag in advance */
```
## 内部线程
```c
static void mqtt_yield_thread(void *arg)
```
主要是对**mqtt_yield**函数的返回值做处理,比如在**disconnect**的时候销毁这个线程。
## 核心的处理函数
1. 数据包的处理**mqtt_packet_handle**
```c
static int mqtt_packet_handle(mqtt_client_t* c, platform_timer_t* timer)
```
对不同的包使用不一样的处理:
```c
switch (packet_type) {
case 0: /* timed out reading packet */
break;
case CONNACK:
break;
case PUBACK:
case PUBCOMP:
rc = mqtt_puback_and_pubcomp_packet_handle(c, timer);
break;
case SUBACK:
rc = mqtt_suback_packet_handle(c, timer);
break;
case UNSUBACK:
rc = mqtt_unsuback_packet_handle(c, timer);
break;
case PUBLISH:
rc = mqtt_publish_packet_handle(c, timer);
break;
case PUBREC:
case PUBREL:
rc = mqtt_pubrec_and_pubrel_packet_handle(c, timer);
break;
case PINGRESP:
c->ping_outstanding = 0;
break;
default:
goto exit;
}
```
并且做保活的处理:
```c
mqtt_keep_alive(c)
```
当发生超时后的处理:
```c
if (platform_timer_is_expired(&c->last_sent) || platform_timer_is_expired(&c->last_received))
```
序列化一个心跳包并且发送给服务器
```c
MQTTSerialize_pingreq(c->write_buf, c->write_buf_size);
mqtt_send_packet(c, len, &timer);
```
当再次发生超时后,表示与服务器的连接已断开,需要重连的操作,设置客户端状态为断开连接
```c
mqtt_set_client_state(c, CLIENT_STATE_DISCONNECTED);
```
2. `ack`链表的扫描当收到服务器的报文时对ack列表进行扫描操作
```c
mqtt_ack_list_scan(c);
```
当超时后就销毁ack链表节点
```c
mqtt_ack_handler_destroy(ack_handler);
```
当然下面这几种报文则需要重发操作:(**PUBACK 、PUBREC、 PUBREL 、PUBCOMP**保证QOS1 QOS2的服务质量
```c
if ((ack_handler->type == PUBACK) || (ack_handler->type == PUBREC) || (ack_handler->type == PUBREL) || (ack_handler->type == PUBCOMP))
mqtt_ack_handler_resend(c, ack_handler);
```
3. 保持活性的时间过去了,可能掉线了,需要重连操作
```c
mqtt_try_reconnect(c);
```
重连成功后尝试重新订阅报文,保证恢复原始状态~
```c
mqtt_try_resubscribe(c)
```
## 发布应答与发布完成报文的处理
```c
static int mqtt_puback_and_pubcomp_packet_handle(mqtt_client_t *c, platform_timer_t *timer)
```
1. 反序列化报文
```c
MQTTDeserialize_ack(&packet_type, &dup, &packet_id, c->read_buf, c->read_buf_size)
```
2. 取消对应的ack记录
```c
mqtt_ack_list_unrecord(c, packet_type, packet_id, NULL);
```
## 订阅应答报文的处理
```c
static int mqtt_suback_packet_handle(mqtt_client_t *c, platform_timer_t *timer)
```
1. 反序列化报文
```c
MQTTDeserialize_suback(&packet_id, 1, &count, (int*)&granted_qos, c->read_buf, c->read_buf_size)
```
2. 取消对应的ack记录
```c
mqtt_ack_list_unrecord(c, packet_type, packet_id, NULL);
```
3. 安装对应的订阅消息处理函数,如果是已存在的则不会安装
```c
mqtt_msg_handlers_install(c, msg_handler);
```
## 取消订阅应答报文的处理
```c
static int mqtt_unsuback_packet_handle(mqtt_client_t *c, platform_timer_t *timer)
```
1. 反序列化报文
```c
MQTTDeserialize_unsuback(&packet_id, c->read_buf, c->read_buf_size)
```
2. 取消对应的ack记录并且获取到已经订阅的消息处理节点
```c
mqtt_ack_list_unrecord(c, UNSUBACK, packet_id, &msg_handler)
```
3. 销毁对应的订阅消息处理函数
```c
mqtt_msg_handler_destory(msg_handler);
```
## 来自服务器的发布报文的处理
```c
static int mqtt_publish_packet_handle(mqtt_client_t *c, platform_timer_t *timer)
```
1. 反序列化报文
```c
MQTTDeserialize_publish(&msg.dup, &qos, &msg.retained, &msg.id, &topic_name,
(unsigned char**)&msg.payload, (int*)&msg.payloadlen, c->read_buf, c->read_buf_size)
```
2. 对于QOS0、QOS1的报文直接去处理消息
```c
mqtt_deliver_message(c, &topic_name, &msg);
```
3. 对于QOS1的报文还需要发送一个**PUBACK**应答报文给服务器
```c
MQTTSerialize_ack(c->write_buf, c->write_buf_size, PUBACK, 0, msg.id);
```
4. 而对于QOS2的报文则需要发送**PUBREC**报文给服务器,除此之外还需要记录**PUBREL**到ack链表上等待服务器的发布释放报文最后再去处理这个消息
```c
MQTTSerialize_ack(c->write_buf, c->write_buf_size, PUBREC, 0, msg.id);
mqtt_ack_list_record(c, PUBREL, msg.id + 1, len, NULL)
mqtt_deliver_message(c, &topic_name, &msg);
```
说明一旦注册到ack列表上的报文当具有重复的报文是不会重新被注册的它会通过**mqtt_ack_list_node_is_exist()**函数判断这个节点是否存在主要是依赖等待响应的消息类型与msgid。
## 发布收到与发布释放报文的处理
```c
static int mqtt_pubrec_and_pubrel_packet_handle(mqtt_client_t *c, platform_timer_t *timer)
```
1. 反序列化报文
```c
MQTTDeserialize_ack(&packet_type, &dup, &packet_id, c->read_buf, c->read_buf_size)
```
2. 产生一个对应的应答报文
```c
mqtt_publish_ack_packet(c, packet_id, packet_type);
```
3. 取消对应的ack记录
```c
mqtt_ack_list_unrecord(c, UNSUBACK, packet_id, &msg_handler)
```
**上一篇**[mqttclient配置及裁剪工具](./mqtt-config.md)
**下一篇**[mqttclient连接到百度天工物接入](./mqtt-baidu.md)

View File

@@ -0,0 +1,196 @@
# MQTT协议简介
MQTT协议全称是Message Queuing Telemetry Transport翻译过来就是消息队列遥测传输协议它是物联网常用的应用层协议运行在TCP/IP中的应用层中依赖TCP协议因此它具有非常高的可靠性同时它是基于TCP协议的 <客户端-服务器> 模型发布/订阅主题消息的轻量级协议也是我们常说的发送与接收数据下面我们来初步了解一下mqtt相关的名称与功能。
MQTT最大的优点在于可以以极少的代码和有限的带宽为远程设备提供实时可靠的消息服务。做为一种低开销、低带宽占用的即时通讯协议MQTT在物联网、小型设备、移动应用等方面有广泛的应用。
# MQTT是哪一层的协议
众所周知TCP/IP参考模型可以分为四层应用层、传输层、网络层、链路层。TCP和UDP位于传输层应用层常见的协议有HTTP、FTP、SSH等。MQTT协议运行于TCP之上属于应用层协议因此只要是支持TCP/IP协议栈的地方都可以使用MQTT。
# MQTT通信模型
MQTT 协议提供一对多的消息发布,可以降低应用程序的耦合性,用户只需要编写极少量的应用代码就能完成一对多的消息发布与订阅,该协议是基于<客户端-服务器>模型在协议中主要有三种身份发布者Publisher、服务器Broker以及订阅者Subscriber。其中MQTT消息的发布者和订阅者都是客户端服务器只是作为一个中转的存在将发布者发布的消息进行转发给所有订阅该主题的订阅者发布者可以发布在其权限之内的所有主题并且消息发布者可以同时是订阅者实现了生产者与消费者的脱耦发布的消息可以同时被多个订阅者订阅。
MQTT通信模型示意图如下
![mqtt001](http://qiniu.jiejie01.top/mqtt001.png)
## MQTT客户端的功能
1. 发布消息给其它相关的客户端。
2. 订阅主题请求接收相关的应用消息。
3. 取消订阅主题请求移除接收应用消息。
4. 从服务端终止连接。
## MQTT客户服务器功能
MQTT 服务器常被称为 Broker消息代理以是一个应用程序或一台设备它一般为云服务器比如BTA三巨头的一些物联网平台就是常使用MQTT协议它是位于消息发布者和订阅者之间以便用于接收消息并发送到订阅者之中它的功能有
1. 接受来自客户端的网络连接请求。
2. 接受客户端发布的应用消息。
3. 处理客户端的订阅和取消订阅请求。
4. 转发应用消息给符合条件的已订阅客户端(包括发布者自身)。
# 消息主题与服务质量
什么是主题MQTT服务器为每个连接的客户端订阅者添加一个标签该标签与服务器中的所有订阅相匹配服务器会将消息转发给与标签相匹配的每个客户端订阅者当然订阅者也是需要有权限才能订阅对应的主题比如像阿里云中的订阅者只能订阅同一个产品下的主题而不能跨产品订阅这样子的处理就能达到信息的安全性以及多个订阅者能及时收到消息。一个主题可以有多个级别各个级别之间用斜杠字符分隔例如/test 和 /test/test1/test2都 是有效的主题。
发布者与订阅者可以通过主题名字一般为UTF-8编码反正用英文字符串就不会错的形式发布和订阅主题比如我们可以直接定义一个名字为“test”的主题绝大多数的MQTT服务器支持动态发布/定阅主题,即当前服务器中没有某个主题,但是客户端直接可以向该主题发布/订阅消息,这样子服务器就会创建对应的主题,当然,服务器中一般也会默认提供多个系统主题,所有连接的客户端均可订阅。
每个客户端与服务器建立连接后就是一个会话客户端和服务器之间会有状态交互订阅是基于会话之上每个订阅中都会包含一个主题过滤器它是一个表达式用于标识订阅相关的一个或多个主题主题过滤器可以使用通配符因此订阅者需要指定订阅的主题名字与服务质量QoS订阅者能订阅多个主题也就能接收到多个发布者发布的消息。同理发布者也需要首先与服务器建立会话并且指定发送的主题名字与服务质量同时它也能向多个不同的主题发送消息。
那么什么是服务质量呢MQTT的服务质量提供3个等级
1. QoS0最多发送一次消息在消息发送出去后接收者不会发送回应发送者也不会重发消息消息可能送达一次也可能根本没送达这个服务质量常用在不重要的消息传递中因为即使消息丢了也没有太大关系。
2. QoS1最少发送一次消息消息最少需要送达一次也有可送达多次QoS 1的PUBLISH报文的可变报头中包含一个报文标识符需要PUBACK报文确认。即需要接收者返回PUBACK应答报文。
3. QoS2这是最高等级的服务质量消息丢失和重复都是不可接受的只不过使用这个服务质量等级会有额外的开销这个等级常用于支付中因为支付是必须有且仅有一次成功总不能没给钱或者给了多次钱吧。
# MQTT控制报文
## 固定报头
MQTT协议工作在TCP协议之上因为客户端和服务器都是应用层那么必然需要一种协议在两者之间进行通信那么随之而来的就是MQTT控制报文 MQTT控制报文有3个部分组成分别是固定报头fixed header、可变报头variable header、有效荷载数据区域payload。固定报头所有的MQTT控制报文都包含可变报头与有效载荷是部分MQTT控制报文包含。
固定报头占据两字节的空间,具体见
![mqtt002](http://qiniu.jiejie01.top/mqtt002.png)
固定报头的第一个字节分为控制报文的类型4bit以及控制报文类型的标志位控制类型共有14种其中0与15被系统保留出来其他的类型具体见
| 类型 | 值 | 说明 |
| -- | -- | -- |
| Reserved | 0 | 系统保留 |
| CONNECT | 1 | 客户端请求连接服务端 |
| CONNACK | 2 | 连接报文确认 |
| PUBLISH | 3 | 发布消息 |
| PUBACK | 4 | 消息发布收到确认QoS 1 |
| PUBREC | 5 | 发布收到QoS2 |
| PUBREL | 6 | 发布释放QoS2 |
| PUBCOMP | 7 | 消息发布完成QoS2 |
| SUBSCRIBE | 8 | 客户端订阅请求 |
| SUBACK | 9 | 订阅请求报文确认 |
| UNSUBSCRIBE | 10 | 客户端取消订阅请求 |
| UNSUBACK | 11 | 取消订阅报文确认 |
| PINGREQ | 12 | 心跳请求 |
| PINGRESP | 13 | 心跳响应 |
| DISCONNECT | 14 | 客户端断开连接 |
| Reserved | 15 | 系统保留 |
固定报头的bit0-bit3为标志位依照报文类型有不同的含义事实上除了PUBLISH类型报文以外其他报文的标志位均为系统保留PUBLISH报文的第一字节bit3是控制报文的重复分发标志DUPbit1-bit2是服务质量等级bit0是PUBLISH报文的保留标志用于标识PUBLISH是否保留当客户端发送一个PUBLISH消息到服务器如果保留标识位置1那么服务器应该保留这条消息当一个新的订阅者订阅这个主题的时候最后保留的主题消息应被发送到新订阅的用户。
固定报头的第二个字节开始是剩余长度字段,是用于记录剩余报文长度的,表示当前的消息剩余的字节数,包括可变报头和有效载荷区域(如果存在),但剩余长度不包括用于编码剩余长度字段本身的字节数。
剩余长度字段使用一个变长度编码方案对小于128的值它使用单字节编码而对于更大的数值则按下面的方式处理每个字节的低7位用于编码数据长度最高位bit7用于标识剩余长度字段是否有更多的字节且按照大端模式进行编码因此每个字节可以编码128个数值和一个延续位剩余长度字段最大可拥有4个字节。
- 当剩余长度使用1个字节存储时其取值范围为0(0x00)~127(0x7f)。
- 当使用2个字节时其取值范围为128(0x80,0x01)~16383(0Xff,0x7f)。
- 当使用3个字节时其取值范围为16384(0x80,0x80,0x01)~2097151(0xFF,0xFF,0x7F)。
- 当使用4个字节时其取值范围为2097152(0x80,0x80,0x80,0x01)~268435455(0xFF,0xFF,0xFF,0x7F)。
总的来说MQTT报文理论上可以发送最大256M的报文当然这种情况是非常少的。
## 可变报头
可变报头并不是所有的MQTT报文都带有的比如PINGREQ心跳请求与PINGRESP心跳响应报文就没有可变报头只有某些报文才拥有可变报头它在固定报头和有效负载之间可变报头的内容会根据报文类型的不同而有所不同但可变报头的报文标识符Packet Identifier字段存在于在多个类型的报文里而有一些报文又没有报文标识符字段具体见表格报文标识符结构具体见图。
| 报文类型 | 是否需要报文标识符字段 |
| -- | -- |
| CONNECT | 不需要 |
| CONNACK | 不需要 |
| PUBLISH | 需要如果QoS > 0 |
| PUBACK | 需要 |
| PUBREC | 需要 |
| PUBREL | 需要 |
| PUBCOMP | 需要 |
| SUBSCRIBE | 需要 |
| SUBACK | 需要 |
| UNSUBSCRIBE | 需要 |
| UNSUBACK | 需要 |
| PINGREQ | 不需要 |
| PINGRESP | 不需要 |
| DISCONNECT | 不需要 |
![mqtt003](http://qiniu.jiejie01.top/mqtt003.png)
因为对于不同的报文,可变报头是不一样的,下面就简单讲解几个报文的可变报头。
## CONNECT报文
在一个会话中客户端只能发送一次CONNECT报文它是客户端用于请求连接服务器的报文常称之为连接报文如果客户端发送多次连接报文那么服务端必须将客户端发送的第二个CONNECT报文当作协议违规处理并断开客户端的连接。
CONNECT报文的可变报头包含四个字段协议名Protocol Name、协议级别Protocol Level、连接标志Connect Flags以及保持连接Keep Alive字段。
协议名是MQTT 的UTF-8编码的字符串其中还包含用于记录协议名长度的两字节字段MSB与LSB。
在协议名之后的是协议级别MQTT协议使用8位的无符号值表示协议的修订版本对于MQTT3.1版的协议协议级别字段的值是3(0x03)而对于MQTT3.1.1版的协议协议级别字段的值是4(0x04)。如果服务器发现连接报文中的协议级别字段是不支持的协议级别服务端必须给发送一个返回码为0x01不支持的协议级别的CONNACK响应连接报文然后终止客户端的连接请求。
连接标志字段涉及的内容比较多,它在协议级别之后使用一个字节表示,但分成很多个标志位,具体见
![mqtt004](http://qiniu.jiejie01.top/mqtt004.png)
bit0是MQTT保留的标志位在连接过程中服务器会检测连接标志的bit0是否为0如果不为0则服务器任务这个连接报文是不合法的会终止连接请求。
bit1是清除会话标志Clean Session一般来说客户端在请求连接服务器时总是将清除会话标志设置为0或1在建立会话连接后这个值就固定了当然这个值的选择取决于具体的应用如果清除会话标志设置为1那么客户端不会收到旧的应用消息而且在每次连接成功后都需要重新订阅相关的主题。清除会话标志设置为0的客户端在重新连接后会收到所有在它连接断开期间其他发布者发布的QoS1和QoS2级别的消息。因此要确保不丢失连接断开期间的消息需要使用QoS1或 QoS2级别同时将清除会话标志设置为0。
bit2是遗嘱标志 Will Flag如果该位被设置为1表示如果客户端与服务器建立了会话遗嘱消息Will Message将必须被存储在服务器中当这个客户端断开连接的时候遗嘱消息将被发送到订阅这个会话主题的所有订阅者这个消息是很有用的我们可以知道这个设备的状况它是否已经掉线了以备启动备用方案当然想要不发送遗嘱消息也是可以的只需要让服务器端收到DISCONNECT报文时删除这个遗嘱消息即可。
bit3-bit4用于指定发布遗嘱消息时使用的服务质量等级与其他消息的服务质量是一样的遗嘱QoS的值可以等于0(0x00)1(0x01)2(0x02)当然使用遗嘱消息的前提是遗嘱标志位为1。
bit5表示遗嘱保留标志位当客户端意外断开连接时如果 Will Retain置一那么服务器必须将遗嘱消息当作保留消息发布反之则无需保留。
bit6是密码标志位Password Flag如果密码标志被设置为0有效载荷中不能包含密码字段反之则必须包含密码字段。
bit7是用户名标志位User Name Flag如果用户名标志被设置为0有效载荷中不能包含用户名字段反之则必须包含用户名字段。
保持连接字段是一个以秒为单位的时间间隔它使用了两个字节来记录允许客户端最大空闲时间间隔简单来说就是客户端必须在这段时间中与服务器进行通信让服务器知道客户端还处于连接状态而不是断开了当然如果没有任何其它的控制报文可以发送客户端也必须要发送一个PINGREQ报文以告知服务器还是处于连接状态的。
总的来说整个CONNECT报文可变报头的内容如下具体见
![mqtt005](http://qiniu.jiejie01.top/mqtt005.png)
## CONNACK报文
我们再来讲解一下CONNACK报文的可变报头部分其实有了上一个的经验这部分对大家来说是很简单的它是由连接确认标志字段Connect Acknowledge Flags与连接返回码字段 Connect Return code组成各占用1个字节。
它的第1个字节是 连接确认标志字段bit1-bit7是保留位且必须设置为0 bit0是当前会话Session Present标志位。
它的第2个字节是返回码字段如果服务器收到一个CONNECT报文但出于某些原因无法处理它服务器会返回一个包含返回码的CONNACK报文。如果服务器返回了一个返回码字段是非0的CONNACK报文那么它必须关闭网络连接返回码描述具体见
| 返回码值 | 描述 |
| -- | -- |
| 0x00 | 连接已被服务端接受 |
| 0x01 | 连接已拒绝服务端不支持客户端请求的MQTT协议级别 |
| 0x02 | 连接已拒绝服务器标识符是正确的UTF-8编码但不允许使用 |
| 0x03 | 连接已拒绝网络连接已建立但MQTT服务不可用 |
| 0x04 | 连接已拒绝,用户名或密码的数据格式无效 |
| 0x05 | 连接已拒绝,客户端未被授权连接到此服务器 |
| 0x06~0xFF | 保留未使用 |
提示如果服务端收到清理会话CleanSession标志为1的连接除了将CONNACK报文中的返回码设置为0之外还必须将CONNACK报文中的当前会话设置Session Present标志为0。
那么总的来说CONNACK报文的可变报头部分内容具体见
![mqtt006](http://qiniu.jiejie01.top/mqtt006.png)
在此就不再对MQTT报文的可变报头部分过多赘述大家可以参考MQTT协议手册里面有很详细的描述。
## 有效载荷
有效载荷也是存在与某些报文中,不同的报文有效载荷也是不一样的,比如:
CONNECT报文的有效载荷payload包含一个或多个以长度为前缀的字段可变报头中的标志决定是否包含这些字段。如果包含的话必须按这个顺序出现客户端标识符遗嘱主题遗嘱消息用户名密码 。
SUBSCRIBE报文的有效载荷包含了一个主题过滤器列表它们标识着客户端想要订阅的主题每一个过滤器后面跟着一个字节这个字节被叫做服务质量要求Requested QoS它给出了服务端向客户端发送应用消息所允许的最大QoS等级。
这里只是讲述了一小部分内容关于具体的有效载荷部分也可以去看MQTT手册此处就不再赘述。
**下一篇**[MQTT通信过程](./mqtt-communication.md)

View File

@@ -0,0 +1,324 @@
# mqttclient连接到OneNET云平台
有了前面连接百度云的经验废话不多说直接使用OneNETOneNET平台应该是最开放对开发者最友好的平台了。
## 使用OneNET
首先注册与登陆OneNET然后进入开发者中心https://open.iot.10086.cn/develop/global/product/#/public?protocol=3&other=1 选择公有协议产品点击“添加产品”填写产品相关的信息联网方式选择wifi其实我们是以太网但是没有这个选项那就选择wifi没啥影响的接入协议必须选择MQTT操作系统选择“linux”运营商这个随意选择具体见
![mqtt-onenet001](http://qiniu.jiejie01.top/mqtt-onenet001.png)
在添加产品完毕,继续添加设备,填写设备的相关信息,鉴权信息就是登陆密码,不过需要注意的是,这个鉴权信息在产品内是唯一的,一般推荐使用产品序列号,可作为设备登录参数之一,不同协议设备可能鉴权信息的参数不一致,不过现在是做实验,选择一个好记的即可,数据保密性要选择公有,除此之外还剩下一些设备相关的信息,就不过多赘述,具体见图:
![mqtt-onenet002](http://qiniu.jiejie01.top/mqtt-onenet002.png)
![mqtt-onenet003](http://qiniu.jiejie01.top/mqtt-onenet003.png)
![mqtt-onenet004](http://qiniu.jiejie01.top/mqtt-onenet004.png)
经过上面的步骤,我们就创建完成一个产品了,此时可以去测试连接它。
## 测试连接
OneNET的数据交互做的很好它支持动态创建主题除系统主题外即不用我们在平台上创建任何的主题只需要随意订阅某个主题即可同一个产品下即使是不同设备之间的主题之间的消息是共享的简单来说我们在开发板上可以随意向某个主题发起订阅请求也可以向这个主题发布消息而同一产品的其他设备如果订阅了这个主题那么将收到开发板发布的消息数据这样子更加方便嵌入式的开发者只不过这样子的信息安全就没有阿里云物联那么好。
我们可以在这个网页中去查看服务器的IP地址https://open.iot.10086.cn/doc/multiprotocol/book/problem/platformaddress.html 对于服务器的地址onenet分为了不同的地区平台不过我们一般正常使用的都是中心平台。
![mqtt-onenet005](http://qiniu.jiejie01.top/mqtt-onenet005.png)
现在我们打开MQTT软件进行连接测试与前面的实验操作是一样的配置好相关信息即可这些信息都可以在平台上找到需要注意的是服务器地址是183.230.40.39端口号是6002这与我们常见的1883是不一样的Client ID是设备ID在设备列表中是可以找到的用户名是产品ID在产品概况页面中可以找到密码就是创建设备时候的鉴权信息具体见
![mqtt-onenet006](http://qiniu.jiejie01.top/mqtt-onenet006.png)
![mqtt-onenet007](http://qiniu.jiejie01.top/mqtt-onenet007.png)
![mqtt-onenet008](http://qiniu.jiejie01.top/mqtt-onenet008.png)
接下来我们可以通过MQTT软件来测试一下能否正常连接在这一步之前必须已在物联网平台控制台中创建产品和设备并获取设备相关的信息。
其实连接是与百度天工差不多的,直接填写相关的内容即可:
![mqtt-onenet009](http://qiniu.jiejie01.top/mqtt-onenet009.png)
配置好就可以连接然后随便订阅一个主题因为OneNet平台支持动态创建主题除系统主题外所以对我们来说是非常方便的直接订阅就好了然后再用客户端进行发布消息如果收到消息表明通信成功
![mqtt-onenet010](http://qiniu.jiejie01.top/mqtt-onenet010.png)
![mqtt-onenet011](http://qiniu.jiejie01.top/mqtt-onenet011.png)
回到OneNet的设备列表界面可以看到刚刚创建的设备是处于在线状态的
![mqtt-onenet012](http://qiniu.jiejie01.top/mqtt-onenet012.png)
## 手动安装相关的依赖包
这些依赖包是使用mqttclient库去连接OneNet云时必须要安装的。
```bash
sudo apt-get -y install git
```
```bash
sudo apt-get -y install mkae
```
```bash
sudo apt-get -y install gcc
```
```bash
sudo apt-get -y install g++
```
```bash
sudo apt-get -y install cmake
```
## 拉取mqttclient仓库
接着到github拉取这个仓库仓库非常小下载下来是很快的注意这里也需要拉取下来。
```bash
git clone https://github.com/jiejieTop/mqttclient.git
```
当然也可以从gitee仓库下载。
```bash
git clone https://gitee.com/jiejieTop/mqttclient.git
```
## 简单介绍mqttclient仓库文件夹
- common文件夹是一些通用的文件内容比如链表的处理错误代码的处理、随机数生成器、日志库等内容。
- mqtt文件夹著名的paho mqtt库。
- mqttclient文件夹实现mqttclient的主要文件并且包含了一个默认的配置文件。
- network文件夹网络抽象层封装了mbedtls加密库、网络数据的通道类型自动选择tls加密传输或者是tcp直连。
- platform文件夹平台抽象层此处封装了各种平台的内存管理、互斥锁、线程管理、时间管理等内容如linux平台freertos平台、rt-thread平台、TencentOS tiny平台等。
- test文件夹一些测试的代码比如我们连接OneNet云的时候就会使用test文件夹的OneNet云平台的测试代码。
## 编译
拉取下来后看到本地有mqttclient文件夹我们进去mqttclient目录下运行它提供的编译脚本它主要是通过cmake去自动构建整个代码工程。
```bash
./build.sh
# 产生的信息如下:
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jiejie/github/mqttclient/build
[ 9%] Built target mqtt
[ 12%] Built target common
[ 17%] Built target platform
[ 21%] Built target wrapper
[ 85%] Built target mbedtls
[ 88%] Built target network
[ 90%] Built target mqttclient
[ 92%] Built target arch
[ 95%] Built target salof
[ 97%] Built target emqx
[ 98%] Built target onenet
[ 99%] Built target baidu
[100%] Built target ali
```
## 运行
当编译完成后,在`./build/bin`目录下会出现多个可执行文件,在`./build/lib`目录下会出现相关的动态库文件,具体如下:
```bash
➜ mqttclient git:(master) ls build/bin
ali baidu emqx onenet
➜ mqttclient git:(master) ls build/lib
libarch.a libcommon.a libmbedtls.a libmqtt.a libmqttclient.a libnetwork.a libplatform.a libsalof.a libwrapper.a
```
我们直接运行`./build/bin/onenet`这个可执行文件:
```bash
➜ mqttclient git:(master) ✗ ./build/bin/onenet
welcome to mqttclient test...
[I] >> [TS: 1590547112] /home/jiejie/github/mqttclient/mqttclient/mqttclient.c:948 mqtt_connect_with_results()... mqtt connect success...
[I] >> [TS: 1590547113] /home/jiejie/github/mqttclient/mqttclient/mqttclient.c:16 default_msg_handler()...
topic: temp_hum, qos: 0,
message:welcome to mqttclient, this is a publish test, a rand number: 1804289383 ...
[I] >> [TS: 1590547116] /home/jiejie/github/mqttclient/mqttclient/mqttclient.c:16 default_msg_handler()...
topic: temp_hum, qos: 0,
message:welcome to mqttclient, this is a publish test, a rand number: 1837236902 ...
```
此时表示已经连接上OneNet云了并且实现了数据的收发。
## 代码
那么这个测试的例程代码如下,位于`./test/onenet/test.c`
```c
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2020-04-18 12:37:34
* @LastEditTime: 2020-06-08 20:32:33
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>
#include "mqttclient.h"
extern const char *test_ca_get();
static void interceptor_handler(void* client, message_data_t* msg)
{
(void) client;
MQTT_LOG_I("-----------------------------------------------------------------------------------");
MQTT_LOG_I("%s:%d %s()...\ntopic: %s\nmessage:%s", __FILE__, __LINE__, __FUNCTION__, msg->topic_name, (char*)msg->message->payload);
MQTT_LOG_I("-----------------------------------------------------------------------------------");
}
void *mqtt_publish_thread(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...");
msg.qos = 0;
msg.payload = (void *) buf;
while(1) {
sprintf(buf, "welcome to mqttclient, this is a publish test, a rand number: %d ...", random_number());
mqtt_publish(client, "topic1", &msg);
sleep(4);
}
}
int main(void)
{
int res;
pthread_t thread1;
mqtt_client_t *client = NULL;
printf("\nwelcome to mqttclient test...\n");
mqtt_log_init();
client = mqtt_lease();
mqtt_set_port(client, "6002");
mqtt_set_host(client, "183.230.40.39");
mqtt_set_client_id(client, "599908192");
mqtt_set_user_name(client, "348547");
mqtt_set_password(client, "mqttclienttest1");
mqtt_set_clean_session(client, 1);
mqtt_connect(client);
mqtt_subscribe(client, "topic1", QOS0, NULL);
mqtt_set_interceptor_handler(client, interceptor_handler); // set interceptor handler
res = pthread_create(&thread1, NULL, mqtt_publish_thread, client);
if(res != 0) {
MQTT_LOG_E("create mqtt publish thread fail");
exit(res);
}
while (1) {
sleep(100);
}
}
```
## 使用到的API
- 申请一个MQTT客户端
```c
mqtt_client_t *client = NULL;
client = mqtt_lease();
```
- mqtt客户端配置主要是配置**mqtt_client_t**结构的相关信息,如果没有指定初始化参数,则系统会提供默认的参数。但连接部分的参数则必须指定,比如连接的端口号、云服务器的地址或者域名、用户名、密码,这些信息都是百度云平台得到的。
```c
mqtt_set_port(client, "6002");
mqtt_set_host(client, "183.230.40.39");
mqtt_set_client_id(client, "599908192");
mqtt_set_user_name(client, "348547");
mqtt_set_password(client, "mqttclienttest1");
mqtt_set_clean_session(client, 1);
```
- 连接服务器并建立mqtt会话。
```c
mqtt_connect(&client);
```
- 订阅主题,字符串类型的**主题**(支持通配符"#" "+"),主题的**服务质量**,以及收到报文的**回调处理函数**如不指定则有默认处理函数订阅主题的处理方式是异步处理的此处设置为NULL则表示使用默认的回调处理函数。
```c
mqtt_subscribe(client, "topic1", QOS0, NULL);
```
- 创建一个发布主题的线程,并且发布主题数据,指定字符串类型的**主题**(支持通配符),要发布的消息(包括**服务质量**、**消息主体**)。
```c
mqtt_message_t msg;
msg.payload = (void *) buf;
msg.qos = 0;
mqtt_publish(&client, "topic1", &msg);
```
- 由于onenet的设备会自动订阅系统主题而用户是不能直接订阅的比如我们在线调试的时候他会下发一些系统主题那么我们需要接收这些主题就需要设置拦截器的处理函数去拦截它们并且通过回调函数上报到应用层设置如下
```c
mqtt_set_interceptor_handler(&client, interceptor_handler);
```
我们在设备列表页面,点击下方命令,下发一些数据到开发板上:
![mqtt-onenet013](http://qiniu.jiejie01.top/mqtt-onenet013.png)
![mqtt-onenet014](http://qiniu.jiejie01.top/mqtt-onenet014.png)
![mqtt-onenet015](http://qiniu.jiejie01.top/mqtt-onenet015.png)
在开发板上可以看到这些数据内容,可以看到他的主题是`$creq/`开头的,而且接下来的内容应该是经过平台加密生成的,是随机的,我们也无法主动去订阅,只能通过拦截器去接收这些数据内容。
```bash
[I] >> [TS: 1590548249] -----------------------------------------------------------------------------------
[I] >> [TS: 1590548249] /home/jiejie/github/mqttclient/test/onenet/test.c:26 interceptor_handler()...
topic: $creq/f6132232-bbcd-5b1e-9b9a-806da959ce80
message:hello world !
[I] >> [TS: 1590548249] -----------------------------------------------------------------------------------
[I] >> [TS: 1590548023] -----------------------------------------------------------------------------------
[I] >> [TS: 1590548023] /home/jiejie/github/mqttclient/test/onenet/test.c:24 interceptor_handler()...
topic: $creq/5d2670bb-a9a4-5bc9-93d5-107246135af8
message:hello world !
[I] >> [TS: 1590548023] -----------------------------------------------------------------------------------
```
**上一篇**[mqttclient连接到百度天工物接入](./mqtt-baidu.md)
**下一篇**[mqttclient连接到阿里云物联网平台](./mqtt-aliyun.md)

View File

@@ -0,0 +1,83 @@
# mqttclient代码生产工具介绍
mqttclient代码生产工具主要是用于配置MQTT的参数并且生成相应的代码因为是可视化的配置极易使用。
地址:[https://jiejietop.gitee.io/mqtt/index.html](https://jiejietop.gitee.io/mqtt/index.html)
![在线代码生成工具](http://qiniu.jiejie01.top/mqtt-tool.png)
与此同时改工具页面还包含了mqttclient的API接口介绍及示例通过它们就能知道这个工具应该配置了什么内容。
![mqtt-tool-api](http://qiniu.jiejie01.top/mqtt-tool-api.png)
# 连接参数配置
首先连接参数代表着MQTT客户端应该如何连接到服务器建立MQTT会话应该是如何配置这些就是连接参数
- 与服务器相关的参数有:
- 服务器地址。
- 服务器端口号。
- 服务器CA证书如果有TLS加密的话
- 建立MQTT连接需要的参数有
- MQTT协议版本。
- 用户名。
- 密码。
- 客户端ID。
- 配置是否清除会话,默认清除会话。
- 心跳时间间隔默认是50秒。
- 是否使用遗嘱。
- 是否保留遗嘱消息。
- 设置遗嘱主题。
- 设置遗嘱消息的服务质量等级。
- 设置遗嘱消息的内容。
- 与与客户端资源相关的配置:
- 设置命令的超时它主要是用于socket读写超时默认是5000毫秒。
- 读缓冲区大小默认是1024。
- 写缓冲区大小默认是1024。
![mqtt-tool-connect](http://qiniu.jiejie01.top/mqtt-tool-connect.png)
# 订阅主题相关的代码配置
此配置用于配置MQTT客户端订阅的主题信息指定订阅主题名字服务质量等级以及当收到来自这个主题消息时候的回调处理函数可以为NULLmqttclient代码生成工具支持动态添加多个主题满足绝大部分的日常需求。
![mqtt-tool-sub](http://qiniu.jiejie01.top/mqtt-tool-sub.png)
# 发布消息相关的代码配置
mqttclient代码生成工具支持动态添向多个主题发布消息满足绝大部分的日常需求。只需指定要发布消息的主题名字、服务质量等级、以及发布的消息内容即可。
![mqtt-tool-pub](http://qiniu.jiejie01.top/mqtt-tool-pub.png)
# 生成代码
在配置完成后,点击下方的生成代码按钮,即可生成对应的配置代码。当然,你也可以点击导入模板,使用模板默认的配置来生成代码。
![mqtt-tool-code](http://qiniu.jiejie01.top/mqtt-tool-code.png)
直接将生成的代码复制到你的main.c文件即可编译运行。
**上一篇**[MQTT通信过程](./mqtt-communication.md)
**下一篇**[mqttclient配置及裁剪工具](./mqtt-config.md)

View File

@@ -0,0 +1,80 @@
#!/bin/bash
mkdir -p libmqttclient libmqttclient/include libmqttclient/lib
cd libmqttclient
if [ ! -f "Makefile" ]; then
cat <<-EOF > Makefile
CC=\$(CROSS_COMPILE)gcc
SRC = \$(wildcard ../*.c \\
../common/*.c \\
../common/log/*.c \\
../common/log/arch/linux/*.c \\
../network/mbedtls/library/*.c \\
../network/mbedtls/wrapper/*.c \\
../mqtt/*.c \\
../mqttclient/*.c \\
../network/*.c \\
../platform/linux/*.c \\
)
INC = -lpthread \\
-I../common \\
-I../common/log \\
-I../network/mbedtls/include \\
-I../network/mbedtls/include/mbedtls \\
-I../network/mbedtls/wrapper \\
-I../mqtt \\
-I../mqttclient \\
-I../network \\
-I../platform/linux \\
-I../test
OBJS = \$(patsubst %.c, %.o, \$(SRC))
FLAG = -g -fpic -I. -Iinclude \$(INC)
TARGET = libmqttclient.so
EOF
echo -e "\n\$(TARGET):\$(OBJS)" >> Makefile
echo -e "\t\$(CC) -shared \$^ -o \$@" >> Makefile
echo -e "\n%.o:%.c" >> Makefile
echo -e "\t\$(CC) -c \$(FLAG) \$^ -o \$@" >> Makefile
echo -e "\nclean:" >> Makefile
echo -e "\trm -rf \$(TARGET) \$(OBJS)" >> Makefile
echo -e "\ninstall:" >> Makefile
echo -e "\tsudo cp -rdf \$(TARGET) /usr/lib/." >> Makefile
echo -e "\nremove:" >> Makefile
echo -e "\tsudo rm -rdf /usr/lib/\$(TARGET)" >> Makefile
echo -e "\n.PHONY:clean" >> Makefile
fi
cp -r ../test/*.h include/.
cp -r ../mqtt/*.h include/.
cp -r ../common/*.h include/.
cp -r ../network/*.h include/.
cp -r ../mqttclient/*.h include/.
cp -r ../common/log/*.h include/.
cp -r ../platform/linux/*.h include/.
cp -r ../network/mbedtls/include/mbedtls include/.
cp -r ../network/mbedtls/wrapper/*.h include/.
if [ " $1" == " " ]; then
make
make install
mv libmqttclient.so lib/.
make clean
elif [ "$1" == "remove" ]; then
make remove
fi

View File

@@ -0,0 +1,17 @@
aux_source_directory(. DIR_SRCS)
string(REGEX REPLACE ".*/(.*)" "\\1" LIB_NAME ${CMAKE_CURRENT_SOURCE_DIR})
if (DIR_SRCS)
foreach(libname ${LIBNAMES})
if (${LIB_NAME} STREQUAL ${libname})
add_library(${libname} ${CMAKE_LIB_TYPE} ${DIR_SRCS})
endif()
endforeach()
else()
message(WARNING "not find is src file!")
endif()

View File

@@ -0,0 +1,19 @@
aux_source_directory(. DIR_SRCS)
string(REGEX REPLACE ".*/(.*)" "\\1" LIB_NAME ${CMAKE_CURRENT_SOURCE_DIR})
if (DIR_SRCS)
foreach(libname ${LIBNAMES})
if (${LIB_NAME} STREQUAL ${libname})
add_library(${libname} ${CMAKE_LIB_TYPE} ${DIR_SRCS})
target_link_libraries(${libname} "mqtt" "platform" "network" "common")
endif()
endforeach()
else()
message(WARNING "not find is src file!")
endif()

View File

@@ -2,7 +2,7 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2020-02-25 03:36:09 * @Date: 2020-02-25 03:36:09
* @LastEditTime: 2020-02-25 07:16:43 * @LastEditTime: 2020-06-17 19:59:41
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
@@ -11,6 +11,10 @@
#include "mqtt_config.h" #include "mqtt_config.h"
#ifndef MQTT_LOG_LEVEL
#define MQTT_LOG_LEVEL MQTT_LOG_DEBUG_LEVEL //MQTT_LOG_WARN_LEVEL MQTT_LOG_DEBUG_LEVEL
#endif // !MQTT_LOG_LEVEL
#ifndef MQTT_MAX_PACKET_ID #ifndef MQTT_MAX_PACKET_ID
#define MQTT_MAX_PACKET_ID (0xFFFF - 1) #define MQTT_MAX_PACKET_ID (0xFFFF - 1)
#endif // !MQTT_MAX_PACKET_ID #endif // !MQTT_MAX_PACKET_ID
@@ -64,18 +68,19 @@
#endif // !MQTT_THREAD_TICK #endif // !MQTT_THREAD_TICK
#ifdef MQTT_NETWORK_TYPE_TLS #ifndef MQTT_NETWORK_TYPE_NO_TLS
#ifndef MQTT_TLS_HANDSHAKE_TIMEOUT #ifndef MQTT_TLS_HANDSHAKE_TIMEOUT
#define MQTT_TLS_HANDSHAKE_TIMEOUT (5 * 1000) #define MQTT_TLS_HANDSHAKE_TIMEOUT (5 * 1000)
#endif // !MQTT_TLS_HANDSHAKE_TIMEOUT #endif // !MQTT_TLS_HANDSHAKE_TIMEOUT
#include "mbedtls/config.h"
#include "mbedtls/ssl.h" #include "mbedtls/ssl.h"
#include "mbedtls/entropy.h" #include "mbedtls/entropy.h"
#include "mbedtls/net_sockets.h" #include "mbedtls/net_sockets.h"
#include "mbedtls/ctr_drbg.h" #include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h" #include "mbedtls/error.h"
#include "mbedtls/debug.h" #include "mbedtls/debug.h"
#endif /* MQTT_NETWORK_TYPE_TLS */ #endif /* MQTT_NETWORK_TYPE_NO_TLS */
#endif /* _DEFCONFIG_H_ */ #endif /* _DEFCONFIG_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -2,17 +2,18 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2019-12-09 21:31:25 * @Date: 2019-12-09 21:31:25
* @LastEditTime: 2020-04-18 12:29:23 * @LastEditTime: 2020-06-16 16:57:40
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#ifndef _MQTTCLIENT_H_ #ifndef _MQTTCLIENT_H_
#define _MQTTCLIENT_H_ #define _MQTTCLIENT_H_
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <string.h> #include <string.h>
#include "MQTTPacket.h" #include "MQTTPacket.h"
#include "list.h" #include "mqtt_list.h"
#include "platform_timer.h" #include "platform_timer.h"
#include "platform_memory.h" #include "platform_memory.h"
#include "platform_mutex.h" #include "platform_mutex.h"
@@ -20,8 +21,8 @@
#include "mqtt_defconfig.h" #include "mqtt_defconfig.h"
#include "network.h" #include "network.h"
#include "random.h" #include "random.h"
#include "error.h" #include "mqtt_error.h"
#include "log.h" #include "mqtt_log.h"
typedef enum mqtt_qos { typedef enum mqtt_qos {
QOS0 = 0, QOS0 = 0,
@@ -39,15 +40,15 @@ typedef enum client_state {
}client_state_t; }client_state_t;
typedef struct mqtt_connack_data { typedef struct mqtt_connack_data {
unsigned char rc; uint8_t rc;
unsigned char session_present; uint8_t session_present;
} mqtt_connack_data_t; } mqtt_connack_data_t;
typedef struct mqtt_message { typedef struct mqtt_message {
mqtt_qos_t qos; mqtt_qos_t qos;
unsigned char retained; uint8_t retained;
unsigned char dup; uint8_t dup;
unsigned short id; uint16_t id;
size_t payloadlen; size_t payloadlen;
void *payload; void *payload;
} mqtt_message_t; } mqtt_message_t;
@@ -62,83 +63,111 @@ typedef void (*message_handler_t)(void* client, message_data_t* msg);
typedef void (*reconnect_handler_t)(void* client, void* reconnect_date); typedef void (*reconnect_handler_t)(void* client, void* reconnect_date);
typedef struct message_handlers { typedef struct message_handlers {
list_t list; mqtt_list_t list;
mqtt_qos_t qos; mqtt_qos_t qos;
const char* topic_filter; const char* topic_filter;
message_handler_t handler; message_handler_t handler;
} message_handlers_t; } message_handlers_t;
typedef struct ack_handlers { typedef struct ack_handlers {
list_t list; mqtt_list_t list;
platform_timer_t timer; platform_timer_t timer;
unsigned int type; uint32_t type;
unsigned short packet_id; uint16_t packet_id;
message_handlers_t *handler; message_handlers_t *handler;
unsigned short payload_len; uint16_t payload_len;
unsigned char *payload; uint8_t *payload;
} ack_handlers_t; } ack_handlers_t;
typedef struct connect_params { typedef struct mqtt_will_options {
char *client_id; mqtt_qos_t will_qos;
char *user_name; uint8_t will_retained;
char *password; char *will_topic;
size_t client_id_len; char *will_message;
size_t user_name_len; } mqtt_will_options_t;
size_t password_len;
unsigned char will_flag;
void *will_options;
unsigned short keep_alive_interval;
unsigned char clean_session;
unsigned char mqtt_version;
network_params_t network_params;
} connect_params_t;
typedef struct mqtt_client { typedef struct mqtt_client {
unsigned short packet_id; char *mqtt_client_id;
unsigned char ping_outstanding; char *mqtt_user_name;
unsigned char ack_handler_number; char *mqtt_password;
unsigned char *read_buf; char *mqtt_host;
unsigned char *write_buf; char *mqtt_port;
unsigned int cmd_timeout; char *mqtt_ca;
unsigned int read_buf_size; void *mqtt_reconnect_data;
unsigned int write_buf_size; uint8_t *mqtt_read_buf;
unsigned int reconnect_try_duration; uint8_t *mqtt_write_buf;
void *reconnect_date; uint16_t mqtt_keep_alive_interval;
reconnect_handler_t reconnect_handler; uint16_t mqtt_packet_id;
client_state_t client_state; uint32_t mqtt_will_flag : 1;
platform_mutex_t write_lock; uint32_t mqtt_clean_session : 1;
platform_mutex_t global_lock; uint32_t mqtt_ping_outstanding : 2;
list_t msg_handler_list; uint32_t mqtt_version : 4;
list_t ack_handler_list; uint32_t mqtt_ack_handler_number : 24;
network_t *network; uint32_t mqtt_cmd_timeout;
platform_thread_t *thread; uint32_t mqtt_read_buf_size;
platform_timer_t reconnect_timer; uint32_t mqtt_write_buf_size;
platform_timer_t last_sent; uint32_t mqtt_reconnect_try_duration;
platform_timer_t last_received; size_t mqtt_client_id_len;
connect_params_t *connect_params; size_t mqtt_user_name_len;
interceptor_handler_t interceptor_handler; size_t mqtt_password_len;
mqtt_will_options_t *mqtt_will_options;
client_state_t mqtt_client_state;
platform_mutex_t mqtt_write_lock;
platform_mutex_t mqtt_global_lock;
mqtt_list_t mqtt_msg_handler_list;
mqtt_list_t mqtt_ack_handler_list;
network_t *mqtt_network;
platform_thread_t *mqtt_thread;
platform_timer_t mqtt_reconnect_timer;
platform_timer_t mqtt_last_sent;
platform_timer_t mqtt_last_received;
reconnect_handler_t mqtt_reconnect_handler;
interceptor_handler_t mqtt_interceptor_handler;
} mqtt_client_t; } mqtt_client_t;
typedef struct client_init_params{
unsigned int cmd_timeout;
unsigned int read_buf_size;
unsigned int write_buf_size;
unsigned int reconnect_try_duration;
void *reconnect_date;
reconnect_handler_t reconnect_handler;
connect_params_t connect_params;
} client_init_params_t;
int mqtt_keep_alive(mqtt_client_t* c); #define MQTT_ROBUSTNESS_CHECK(item, err) if (!(item)) { \
int mqtt_init(mqtt_client_t* c, client_init_params_t* init); MQTT_LOG_E("%s:%d %s()... check for error.", __FILE__, __LINE__, __FUNCTION__); \
return err; }
#define MQTT_CLIENT_SET_DEFINE(name, type, res) \
type mqtt_set_##name(mqtt_client_t *c, type t) { \
MQTT_ROBUSTNESS_CHECK((c), res); \
c->mqtt_##name = t; \
return c->mqtt_##name; \
}
#define MQTT_CLIENT_SET_STATEMENT(name, type) \
type mqtt_set_##name(mqtt_client_t *, type);
MQTT_CLIENT_SET_STATEMENT(client_id, char*)
MQTT_CLIENT_SET_STATEMENT(user_name, char*)
MQTT_CLIENT_SET_STATEMENT(password, char*)
MQTT_CLIENT_SET_STATEMENT(host, char*)
MQTT_CLIENT_SET_STATEMENT(port, char*)
MQTT_CLIENT_SET_STATEMENT(ca, char*)
MQTT_CLIENT_SET_STATEMENT(reconnect_data, void*)
MQTT_CLIENT_SET_STATEMENT(keep_alive_interval, uint16_t)
MQTT_CLIENT_SET_STATEMENT(will_flag, uint32_t)
MQTT_CLIENT_SET_STATEMENT(clean_session, uint32_t)
MQTT_CLIENT_SET_STATEMENT(version, uint32_t)
MQTT_CLIENT_SET_STATEMENT(cmd_timeout, uint32_t)
MQTT_CLIENT_SET_STATEMENT(read_buf_size, uint32_t)
MQTT_CLIENT_SET_STATEMENT(write_buf_size, uint32_t)
MQTT_CLIENT_SET_STATEMENT(reconnect_try_duration, uint32_t)
MQTT_CLIENT_SET_STATEMENT(reconnect_handler, reconnect_handler_t)
MQTT_CLIENT_SET_STATEMENT(interceptor_handler, interceptor_handler_t)
void mqtt_sleep_ms(int ms);
mqtt_client_t *mqtt_lease(void);
int mqtt_release(mqtt_client_t* c); int mqtt_release(mqtt_client_t* c);
int mqtt_connect(mqtt_client_t* c); int mqtt_connect(mqtt_client_t* c);
int mqtt_disconnect(mqtt_client_t* c); int mqtt_disconnect(mqtt_client_t* c);
int mqtt_keep_alive(mqtt_client_t* c);
int mqtt_subscribe(mqtt_client_t* c, const char* topic_filter, mqtt_qos_t qos, message_handler_t msg_handler); int mqtt_subscribe(mqtt_client_t* c, const char* topic_filter, mqtt_qos_t qos, message_handler_t msg_handler);
int mqtt_unsubscribe(mqtt_client_t* c, const char* topic_filter); int mqtt_unsubscribe(mqtt_client_t* c, const char* topic_filter);
int mqtt_publish(mqtt_client_t* c, const char* topic_filter, mqtt_message_t* msg); int mqtt_publish(mqtt_client_t* c, const char* topic_filter, mqtt_message_t* msg);
int mqtt_list_subscribe_topic(mqtt_client_t* c); int mqtt_list_subscribe_topic(mqtt_client_t* c);
int mqtt_set_interceptor_handler(mqtt_client_t* c, interceptor_handler_t handler); int mqtt_set_will_options(mqtt_client_t* c, char *topic, mqtt_qos_t qos, uint8_t retained, char *message);
#endif /* _MQTTCLIENT_H_ */ #endif /* _MQTTCLIENT_H_ */

View File

@@ -0,0 +1,22 @@
set(SUBDIRS "mbedtls")
aux_source_directory(. DIR_SRCS)
string(REGEX REPLACE ".*/(.*)" "\\1" LIB_NAME ${CMAKE_CURRENT_SOURCE_DIR})
if (DIR_SRCS)
foreach(libname ${LIBNAMES})
if (${LIB_NAME} STREQUAL ${libname})
add_library(${libname} ${CMAKE_LIB_TYPE} ${DIR_SRCS})
target_link_libraries(${libname} "platform" "mbedtls")
endif()
endforeach()
else()
message(WARNING "not find is src file!")
endif()
foreach(subdir ${SUBDIRS})
add_subdirectory(${subdir})
endforeach()

View File

@@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 2.8)
set(MBEDTLS_SUBDIRS "library" "include" "wrapper")
set(MBEDTLS_INCDIRS "include" "include/mbedtls" "configs" "wrapper")
foreach(incdir ${INCDIRS})
include_directories(${MBEDTLS_INCDIRS})
endforeach()
foreach(subdir ${MBEDTLS_SUBDIRS})
add_subdirectory(${subdir})
endforeach()

View File

@@ -0,0 +1,7 @@
aux_source_directory(. WARAPPER_SRCS)
add_library("wrapper" ${CMAKE_LIB_TYPE} ${WARAPPER_SRCS})
target_link_libraries("wrapper" "platform")

View File

@@ -2,7 +2,7 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2020-01-11 02:04:49 * @Date: 2020-01-11 02:04:49
* @LastEditTime : 2020-01-11 02:12:16 * @LastEditTime: 2020-02-19 23:53:22
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#include "mbedtls/entropy.h" #include "mbedtls/entropy.h"

View File

@@ -0,0 +1,35 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-15 13:38:52
* @LastEditTime: 2020-05-25 10:13:41
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#include "nettype_tcp.h"
#include "mqtt_log.h"
int nettype_tcp_read(network_t *n, unsigned char *read_buf, int len, int timeout)
{
return platform_net_socket_recv_timeout(n->socket, read_buf, len, timeout);
}
int nettype_tcp_write(network_t *n, unsigned char *write_buf, int len, int timeout)
{
return platform_net_socket_write_timeout(n->socket, write_buf, len, timeout);
}
int nettype_tcp_connect(network_t* n)
{
n->socket = platform_net_socket_connect(n->host, n->port, PLATFORM_NET_PROTO_TCP);
if (n->socket < 0)
RETURN_ERROR(n->socket);
RETURN_ERROR(MQTT_SUCCESS_ERROR);
}
void nettype_tcp_disconnect(network_t* n)
{
if (NULL != n)
platform_net_socket_close(n->socket);
n->socket = -1;
}

View File

@@ -0,0 +1,20 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-15 13:39:00
* @LastEditTime: 2020-05-24 15:49:46
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#ifndef _NETTYPE_TCP_H_
#define _NETTYPE_TCP_H_
#include "platform_net_socket.h"
#include "network.h"
#include "mqtt_error.h"
int nettype_tcp_read(network_t *n, unsigned char *buf, int len, int timeout);
int nettype_tcp_write(network_t *n, unsigned char *buf, int len, int timeout);
int nettype_tcp_connect(network_t* n);
void nettype_tcp_disconnect(network_t* n);
#endif

View File

@@ -2,16 +2,16 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2020-01-11 19:45:35 * @Date: 2020-01-11 19:45:35
* @LastEditTime: 2020-03-05 23:52:30 * @LastEditTime: 2020-05-24 17:03:47
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#include "platform_nettype_tls.h" #include "nettype_tls.h"
#include "platform_net_socket.h" #include "platform_net_socket.h"
#include "platform_memory.h" #include "platform_memory.h"
#include "platform_timer.h" #include "platform_timer.h"
#include "random.h" #include "random.h"
#ifdef MQTT_NETWORK_TYPE_TLS #ifndef MQTT_NETWORK_TYPE_NO_TLS
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#include "mbedtls/ssl.h" #include "mbedtls/ssl.h"
@@ -20,23 +20,19 @@
#include "mbedtls/ctr_drbg.h" #include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h" #include "mbedtls/error.h"
#include "mbedtls/debug.h" #include "mbedtls/debug.h"
#include "mbedtls\x509_crt.h" #include "mbedtls/x509_crt.h"
#include "mbedtls\pk.h" #include "mbedtls/pk.h"
#if !defined(MBEDTLS_FS_IO)
static const int ciphersuites[] = { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, 0 };
#endif
#if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_X509_CRT_PARSE_C)
static int server_certificate_verify(void *hostname, mbedtls_x509_crt *crt, int depth, uint32_t *flags) static int server_certificate_verify(void *hostname, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
{ {
if (0 != *flags) if (0 != *flags)
LOG_E("%s:%d %s()... server_certificate_verify failed returned 0x%04x\n", __FILE__, __LINE__, __FUNCTION__, *flags); MQTT_LOG_E("%s:%d %s()... server_certificate_verify failed returned 0x%04x\n", __FILE__, __LINE__, __FUNCTION__, *flags);
return *flags; return *flags;
} }
#endif #endif
static int platform_nettype_tls_entropy_source(void *data, uint8_t *output, size_t len, size_t *out_len) static int nettype_tls_entropy_source(void *data, uint8_t *output, size_t len, size_t *out_len)
{ {
uint32_t seed; uint32_t seed;
(void) data; (void) data;
@@ -52,7 +48,7 @@ static int platform_nettype_tls_entropy_source(void *data, uint8_t *output, size
return 0; return 0;
} }
static int platform_nettype_tls_init(network_t* n, nettype_tls_params_t* nettype_tls_params) static int nettype_tls_init(network_t* n, nettype_tls_params_t* nettype_tls_params)
{ {
int rc = MQTT_SUCCESS_ERROR; int rc = MQTT_SUCCESS_ERROR;
@@ -69,29 +65,29 @@ static int platform_nettype_tls_init(network_t* n, nettype_tls_params_t* nettype
#endif #endif
mbedtls_entropy_init(&(nettype_tls_params->entropy)); mbedtls_entropy_init(&(nettype_tls_params->entropy));
mbedtls_entropy_add_source(&(nettype_tls_params->entropy), platform_nettype_tls_entropy_source, NULL, MBEDTLS_ENTROPY_MAX_GATHER, MBEDTLS_ENTROPY_SOURCE_STRONG); mbedtls_entropy_add_source(&(nettype_tls_params->entropy), nettype_tls_entropy_source, NULL, MBEDTLS_ENTROPY_MAX_GATHER, MBEDTLS_ENTROPY_SOURCE_STRONG);
if ((rc = mbedtls_ctr_drbg_seed(&(nettype_tls_params->ctr_drbg), mbedtls_entropy_func, if ((rc = mbedtls_ctr_drbg_seed(&(nettype_tls_params->ctr_drbg), mbedtls_entropy_func,
&(nettype_tls_params->entropy), NULL, 0)) != 0) { &(nettype_tls_params->entropy), NULL, 0)) != 0) {
LOG_E("mbedtls_ctr_drbg_seed failed returned 0x%04x", (rc < 0 )? -rc : rc); MQTT_LOG_E("mbedtls_ctr_drbg_seed failed returned 0x%04x", (rc < 0 )? -rc : rc);
RETURN_ERROR(rc); RETURN_ERROR(rc);
} }
if ((rc = mbedtls_ssl_config_defaults(&(nettype_tls_params->ssl_conf), MBEDTLS_SSL_IS_CLIENT, if ((rc = mbedtls_ssl_config_defaults(&(nettype_tls_params->ssl_conf), MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
LOG_E("mbedtls_ssl_config_defaults failed returned 0x%04x", (rc < 0 )? -rc : rc); MQTT_LOG_E("mbedtls_ssl_config_defaults failed returned 0x%04x", (rc < 0 )? -rc : rc);
RETURN_ERROR(rc); RETURN_ERROR(rc);
} }
mbedtls_ssl_conf_rng(&(nettype_tls_params->ssl_conf), mbedtls_ctr_drbg_random, &(nettype_tls_params->ctr_drbg)); mbedtls_ssl_conf_rng(&(nettype_tls_params->ssl_conf), mbedtls_ctr_drbg_random, &(nettype_tls_params->ctr_drbg));
#if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_X509_CRT_PARSE_C)
if (NULL != n->network_params.network_ssl_params.ca_crt) { if (NULL != n->ca_crt) {
n->network_params.network_ssl_params.ca_crt_len = strlen(n->network_params.network_ssl_params.ca_crt); n->ca_crt_len = strlen(n->ca_crt);
if (0 != (rc = (mbedtls_x509_crt_parse(&(nettype_tls_params->ca_cert), (unsigned char *)n->network_params.network_ssl_params.ca_crt, if (0 != (rc = (mbedtls_x509_crt_parse(&(nettype_tls_params->ca_cert), (unsigned char *)n->ca_crt,
(n->network_params.network_ssl_params.ca_crt_len + 1))))) { (n->ca_crt_len + 1))))) {
LOG_E("%s:%d %s()... parse ca crt failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc); MQTT_LOG_E("%s:%d %s()... parse ca crt failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
RETURN_ERROR(rc); RETURN_ERROR(rc);
} }
} }
@@ -100,58 +96,25 @@ static int platform_nettype_tls_init(network_t* n, nettype_tls_params_t* nettype
if ((rc = mbedtls_ssl_conf_own_cert(&(nettype_tls_params->ssl_conf), if ((rc = mbedtls_ssl_conf_own_cert(&(nettype_tls_params->ssl_conf),
&(nettype_tls_params->client_cert), &(nettype_tls_params->private_key))) != 0) { &(nettype_tls_params->client_cert), &(nettype_tls_params->private_key))) != 0) {
LOG_E("%s:%d %s()... mbedtls_ssl_conf_own_cert failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc); MQTT_LOG_E("%s:%d %s()... mbedtls_ssl_conf_own_cert failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
RETURN_ERROR(rc); RETURN_ERROR(rc);
} }
mbedtls_ssl_conf_verify(&(nettype_tls_params->ssl_conf), server_certificate_verify, (void *)n->network_params.addr); mbedtls_ssl_conf_verify(&(nettype_tls_params->ssl_conf), server_certificate_verify, (void *)n->host);
mbedtls_ssl_conf_authmode(&(nettype_tls_params->ssl_conf), MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_authmode(&(nettype_tls_params->ssl_conf), MBEDTLS_SSL_VERIFY_REQUIRED);
#endif #endif
#if defined(MBEDTLS_FS_IO) mbedtls_ssl_conf_read_timeout(&(nettype_tls_params->ssl_conf), n->timeout_ms);
if (n->network_params.network_ssl_params.cert_file != NULL && n->network_params.network_ssl_params.key_file != NULL) {
if ((rc = mbedtls_x509_crt_parse_file(&(nettype_tls_params->client_cert), n->network_params.network_ssl_params.cert_file)) != 0) {
LOG_E("%s:%d %s()... load client cert file failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
return MQTT_SSL_CERT_ERROR;
}
if ((rc = mbedtls_pk_parse_keyfile(&(nettype_tls_params->private_key), n->network_params.network_ssl_params.key_file, "")) != 0) {
LOG_E("%s:%d %s()... load client key file failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
return MQTT_SSL_CERT_ERROR;
}
} else {
LOG_I("%s:%d %s()... cert_file/key_file is empty! | cert_file = %s | key_file = %s", __FILE__, __LINE__, __FUNCTION__,
n->network_params.network_ssl_params.cert_file, n->network_params.network_ssl_params.key_file);
}
#else
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
if (n->network_params.network_ssl_params.psk != NULL && n->network_params.network_ssl_params.psk_id !=NULL) {
const char *psk_id = n->network_params.network_ssl_params.psk_id;
rc = mbedtls_ssl_conf_psk(&(nettype_tls_params->ssl_conf), (unsigned char *)n->network_params.network_ssl_params.psk,
n->network_params.network_ssl_params.psk_length, (const unsigned char *) psk_id, strlen( psk_id ));
mbedtls_ssl_conf_ciphersuites(&(nettype_tls_params->ssl_conf), ciphersuites);
if (0 != rc) {
LOG_E("%s:%d %s()... mbedtls_ssl_conf_psk fail: 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
return rc;
}
}
#endif
#endif
mbedtls_ssl_conf_read_timeout(&(nettype_tls_params->ssl_conf), n->network_params.network_ssl_params.timeout_ms);
if ((rc = mbedtls_ssl_setup(&(nettype_tls_params->ssl), &(nettype_tls_params->ssl_conf))) != 0) { if ((rc = mbedtls_ssl_setup(&(nettype_tls_params->ssl), &(nettype_tls_params->ssl_conf))) != 0) {
LOG_E("mbedtls_ssl_setup failed returned 0x%04x", (rc < 0 )? -rc : rc); MQTT_LOG_E("mbedtls_ssl_setup failed returned 0x%04x", (rc < 0 )? -rc : rc);
RETURN_ERROR(rc); RETURN_ERROR(rc);
} }
#if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_X509_CRT_PARSE_C)
if ((rc = mbedtls_ssl_set_hostname(&(nettype_tls_params->ssl), n->network_params.addr)) != 0) { if ((rc = mbedtls_ssl_set_hostname(&(nettype_tls_params->ssl), n->host)) != 0) {
LOG_E("%s:%d %s()... mbedtls_ssl_set_hostname failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc); MQTT_LOG_E("%s:%d %s()... mbedtls_ssl_set_hostname failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
RETURN_ERROR(rc); RETURN_ERROR(rc);
} }
#endif #endif
@@ -162,7 +125,7 @@ static int platform_nettype_tls_init(network_t* n, nettype_tls_params_t* nettype
} }
int platform_nettype_tls_connect(network_t* n) int nettype_tls_connect(network_t* n)
{ {
int rc; int rc;
if (NULL == n) if (NULL == n)
@@ -174,19 +137,19 @@ int platform_nettype_tls_connect(network_t* n)
RETURN_ERROR(MQTT_MEM_NOT_ENOUGH_ERROR); RETURN_ERROR(MQTT_MEM_NOT_ENOUGH_ERROR);
rc = platform_nettype_tls_init(n, nettype_tls_params); rc = nettype_tls_init(n, nettype_tls_params);
if (MQTT_SUCCESS_ERROR != rc) if (MQTT_SUCCESS_ERROR != rc)
goto exit; goto exit;
if (0 != (rc = mbedtls_net_connect(&(nettype_tls_params->socket_fd), n->network_params.addr, n->network_params.port, MBEDTLS_NET_PROTO_TCP))) if (0 != (rc = mbedtls_net_connect(&(nettype_tls_params->socket_fd), n->host, n->port, MBEDTLS_NET_PROTO_TCP)))
goto exit; goto exit;
while ((rc = mbedtls_ssl_handshake(&(nettype_tls_params->ssl))) != 0) { while ((rc = mbedtls_ssl_handshake(&(nettype_tls_params->ssl))) != 0) {
if (rc != MBEDTLS_ERR_SSL_WANT_READ && rc != MBEDTLS_ERR_SSL_WANT_WRITE) { if (rc != MBEDTLS_ERR_SSL_WANT_READ && rc != MBEDTLS_ERR_SSL_WANT_WRITE) {
LOG_E("%s:%d %s()...mbedtls handshake failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc); MQTT_LOG_E("%s:%d %s()...mbedtls handshake failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
#if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_X509_CRT_PARSE_C)
if (rc == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { if (rc == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
LOG_E("%s:%d %s()...unable to verify the server's certificate", __FILE__, __LINE__, __FUNCTION__); MQTT_LOG_E("%s:%d %s()...unable to verify the server's certificate", __FILE__, __LINE__, __FUNCTION__);
} }
#endif #endif
goto exit; goto exit;
@@ -194,11 +157,11 @@ int platform_nettype_tls_connect(network_t* n)
} }
if ((rc = mbedtls_ssl_get_verify_result(&(nettype_tls_params->ssl))) != 0) { if ((rc = mbedtls_ssl_get_verify_result(&(nettype_tls_params->ssl))) != 0) {
LOG_E("%s:%d %s()...mbedtls_ssl_get_verify_result returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc); MQTT_LOG_E("%s:%d %s()...mbedtls_ssl_get_verify_result returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
goto exit; goto exit;
} }
n->network_params.nettype_tls_params = nettype_tls_params; n->nettype_tls_params = nettype_tls_params;
RETURN_ERROR(MQTT_SUCCESS_ERROR) RETURN_ERROR(MQTT_SUCCESS_ERROR)
exit: exit:
@@ -207,13 +170,13 @@ exit:
} }
void platform_nettype_tls_disconnect(network_t* n) void nettype_tls_disconnect(network_t* n)
{ {
int rc = 0; int rc = 0;
if (NULL == n) if (NULL == n)
return; return;
nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->network_params.nettype_tls_params; nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->nettype_tls_params;
do { do {
rc = mbedtls_ssl_close_notify(&(nettype_tls_params->ssl)); rc = mbedtls_ssl_close_notify(&(nettype_tls_params->ssl));
@@ -233,7 +196,7 @@ void platform_nettype_tls_disconnect(network_t* n)
platform_memory_free(nettype_tls_params); platform_memory_free(nettype_tls_params);
} }
int platform_nettype_tls_write(network_t *n, unsigned char *buf, int len, int timeout) int nettype_tls_write(network_t *n, unsigned char *buf, int len, int timeout)
{ {
int rc = 0; int rc = 0;
int write_len = 0; int write_len = 0;
@@ -242,7 +205,7 @@ int platform_nettype_tls_write(network_t *n, unsigned char *buf, int len, int ti
if (NULL == n) if (NULL == n)
RETURN_ERROR(MQTT_NULL_VALUE_ERROR); RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->network_params.nettype_tls_params; nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->nettype_tls_params;
platform_timer_init(&timer); platform_timer_init(&timer);
platform_timer_cutdown(&timer, timeout); platform_timer_cutdown(&timer, timeout);
@@ -253,7 +216,7 @@ int platform_nettype_tls_write(network_t *n, unsigned char *buf, int len, int ti
if (rc > 0) { if (rc > 0) {
write_len += rc; write_len += rc;
} else if ((rc == 0) || ((rc != MBEDTLS_ERR_SSL_WANT_WRITE) && (rc != MBEDTLS_ERR_SSL_WANT_READ) && (rc != MBEDTLS_ERR_SSL_TIMEOUT))) { } else if ((rc == 0) || ((rc != MBEDTLS_ERR_SSL_WANT_WRITE) && (rc != MBEDTLS_ERR_SSL_WANT_READ) && (rc != MBEDTLS_ERR_SSL_TIMEOUT))) {
LOG_E("%s:%d %s()... mbedtls_ssl_write failed: 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc); MQTT_LOG_E("%s:%d %s()... mbedtls_ssl_write failed: 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
break; break;
} }
} while((!platform_timer_is_expired(&timer)) && (write_len < len)); } while((!platform_timer_is_expired(&timer)) && (write_len < len));
@@ -261,7 +224,7 @@ int platform_nettype_tls_write(network_t *n, unsigned char *buf, int len, int ti
return write_len; return write_len;
} }
int platform_nettype_tls_read(network_t *n, unsigned char *buf, int len, int timeout) int nettype_tls_read(network_t *n, unsigned char *buf, int len, int timeout)
{ {
int rc = 0; int rc = 0;
int read_len = 0; int read_len = 0;
@@ -270,7 +233,7 @@ int platform_nettype_tls_read(network_t *n, unsigned char *buf, int len, int tim
if (NULL == n) if (NULL == n)
RETURN_ERROR(MQTT_NULL_VALUE_ERROR); RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->network_params.nettype_tls_params; nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->nettype_tls_params;
platform_timer_init(&timer); platform_timer_init(&timer);
platform_timer_cutdown(&timer, timeout); platform_timer_cutdown(&timer, timeout);
@@ -281,7 +244,7 @@ int platform_nettype_tls_read(network_t *n, unsigned char *buf, int len, int tim
if (rc > 0) { if (rc > 0) {
read_len += rc; read_len += rc;
} else if ((rc == 0) || ((rc != MBEDTLS_ERR_SSL_WANT_WRITE) && (rc != MBEDTLS_ERR_SSL_WANT_READ) && (rc != MBEDTLS_ERR_SSL_TIMEOUT))) { } else if ((rc == 0) || ((rc != MBEDTLS_ERR_SSL_WANT_WRITE) && (rc != MBEDTLS_ERR_SSL_WANT_READ) && (rc != MBEDTLS_ERR_SSL_TIMEOUT))) {
// LOG_E("%s:%d %s()... mbedtls_ssl_read failed: 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc); // MQTT_LOG_E("%s:%d %s()... mbedtls_ssl_read failed: 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
break; break;
} }
} while((!platform_timer_is_expired(&timer)) && (read_len < len)); } while((!platform_timer_is_expired(&timer)) && (read_len < len));
@@ -289,4 +252,4 @@ int platform_nettype_tls_read(network_t *n, unsigned char *buf, int len, int tim
return read_len; return read_len;
} }
#endif /* MQTT_NETWORK_TYPE_TLS */ #endif /* MQTT_NETWORK_TYPE_NO_TLS */

View File

@@ -2,20 +2,19 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2020-01-11 19:45:44 * @Date: 2020-01-11 19:45:44
* @LastEditTime: 2020-02-25 03:51:37 * @LastEditTime: 2020-05-24 17:03:13
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#ifndef _PLATFORM_NETTYPE_TLS_H_ #ifndef _NETTYPE_TLS_H_
#define _PLATFORM_NETTYPE_TLS_H_ #define _NETTYPE_TLS_H_
#include "platform_net_socket.h"
#include "mqtt_defconfig.h" #include "mqtt_defconfig.h"
#include "network.h" #include "network.h"
#include "error.h" #include "mqtt_error.h"
#include "log.h" #include "mqtt_log.h"
#ifdef MQTT_NETWORK_TYPE_TLS #ifndef MQTT_NETWORK_TYPE_NO_TLS
typedef struct nettype_tls_params { typedef struct nettype_tls_params {
mbedtls_net_context socket_fd; /**< mbed TLS network context. */ mbedtls_net_context socket_fd; /**< mbed TLS network context. */
@@ -30,11 +29,11 @@ typedef struct nettype_tls_params {
mbedtls_pk_context private_key; /**< mbed TLS Client key. */ mbedtls_pk_context private_key; /**< mbed TLS Client key. */
} nettype_tls_params_t; } nettype_tls_params_t;
int platform_nettype_tls_read(network_t *n, unsigned char *buf, int len, int timeout); int nettype_tls_read(network_t *n, unsigned char *buf, int len, int timeout);
int platform_nettype_tls_write(network_t *n, unsigned char *buf, int len, int timeout); int nettype_tls_write(network_t *n, unsigned char *buf, int len, int timeout);
int platform_nettype_tls_connect(network_t* n); int nettype_tls_connect(network_t* n);
void platform_nettype_tls_disconnect(network_t* n); void nettype_tls_disconnect(network_t* n);
#endif /* MQTT_NETWORK_TYPE_TLS */ #endif /* MQTT_NETWORK_TYPE_NO_TLS */
#endif #endif

View File

@@ -2,91 +2,111 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2019-12-09 21:30:54 * @Date: 2019-12-09 21:30:54
* @LastEditTime: 2020-02-25 03:49:43 * @LastEditTime: 2020-06-05 17:17:48
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#include "platform_timer.h" #include "platform_timer.h"
#include "platform_nettype_tcp.h" #include "platform_memory.h"
#include "nettype_tcp.h"
#ifdef MQTT_NETWORK_TYPE_TLS #ifndef MQTT_NETWORK_TYPE_NO_TLS
#include "platform_nettype_tls.h" #include "nettype_tls.h"
#endif #endif
int network_read(network_t *n, unsigned char *buf, int len, int timeout) int network_read(network_t *n, unsigned char *buf, int len, int timeout)
{ {
#ifdef MQTT_NETWORK_TYPE_TLS #ifndef MQTT_NETWORK_TYPE_NO_TLS
return platform_nettype_tls_read(n, buf, len, timeout); if (n->channel)
#else return nettype_tls_read(n, buf, len, timeout);
return platform_nettype_tcp_read(n, buf, len, timeout);
#endif #endif
return nettype_tcp_read(n, buf, len, timeout);
} }
int network_write(network_t *n, unsigned char *buf, int len, int timeout) int network_write(network_t *n, unsigned char *buf, int len, int timeout)
{ {
#ifdef MQTT_NETWORK_TYPE_TLS #ifndef MQTT_NETWORK_TYPE_NO_TLS
return platform_nettype_tls_write(n, buf, len, timeout); if (n->channel)
#else return nettype_tls_write(n, buf, len, timeout);
return platform_nettype_tcp_write(n, buf, len, timeout);
#endif #endif
return nettype_tcp_write(n, buf, len, timeout);
} }
int network_connect(network_t *n) int network_connect(network_t *n)
{ {
#ifdef MQTT_NETWORK_TYPE_TLS #ifndef MQTT_NETWORK_TYPE_NO_TLS
return platform_nettype_tls_connect(n); if (n->channel)
#else return nettype_tls_connect(n);
return platform_nettype_tcp_connect(n);
#endif #endif
return nettype_tcp_connect(n);
} }
void network_disconnect(network_t *n) void network_disconnect(network_t *n)
{ {
#ifdef MQTT_NETWORK_TYPE_TLS #ifndef MQTT_NETWORK_TYPE_NO_TLS
platform_nettype_tls_disconnect(n); if (n->channel)
#else nettype_tls_disconnect(n);
platform_nettype_tcp_disconnect(n); else
#endif #endif
nettype_tcp_disconnect(n);
} }
int network_init(network_t* n, network_params_t* network_params) int network_init(network_t *n, const char *host, const char *port, const char *ca)
{ {
if ((NULL == n) || (NULL == network_params) || (NULL == network_params->addr) || (NULL == network_params->port)) if (NULL == n)
RETURN_ERROR(MQTT_NULL_VALUE_ERROR); RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
n->socket = -1; n->socket = -1;
n->read = network_read; n->host = host;
n->write = network_write; n->port = port;
n->connect = network_connect;
n->disconnect = network_disconnect;
n->network_params.addr = network_params->addr;
n->network_params.port = network_params->port;
#ifdef MQTT_NETWORK_TYPE_TLS #ifndef MQTT_NETWORK_TYPE_NO_TLS
n->network_params.network_ssl_params.ca_crt = network_params->network_ssl_params.ca_crt; n->channel = 0;
n->network_params.network_ssl_params.ca_crt_len = strlen(n->network_params.network_ssl_params.ca_crt);
#if defined(MBEDTLS_FS_IO)
n->network_params.network_ssl_params.cert_file = network_params->network_ssl_params.cert_file;
n->network_params.network_ssl_params.key_file = network_params->network_ssl_params.key_file;
#else
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
n->network_params.network_ssl_params.psk = network_params->network_ssl_params.psk;
n->network_params.network_ssl_params.psk_id = network_params->network_ssl_params.psk_id;
n->network_params.network_ssl_params.psk_length = network_params->network_ssl_params.psk_length;
#endif
#endif
if (0 == network_params->network_ssl_params.timeout_ms)
network_params->network_ssl_params.timeout_ms = MQTT_TLS_HANDSHAKE_TIMEOUT;
n->network_params.network_ssl_params.timeout_ms = network_params->network_ssl_params.timeout_ms;
#endif
if (NULL != ca) {
network_set_ca(n, ca);
}
#endif
RETURN_ERROR(MQTT_SUCCESS_ERROR); RETURN_ERROR(MQTT_SUCCESS_ERROR);
} }
void network_release(network_t* n) void network_release(network_t* n)
{ {
if (n->socket) if (n->socket >= 0)
network_disconnect(n); network_disconnect(n);
memset(n, 0, sizeof(network_t)); memset(n, 0, sizeof(network_t));
} }
void network_set_channel(network_t *n, int channel)
{
#ifndef MQTT_NETWORK_TYPE_NO_TLS
n->channel = channel;
#endif
}
int network_set_ca(network_t *n, const char *ca)
{
#ifndef MQTT_NETWORK_TYPE_NO_TLS
if ((NULL == n) || (NULL == ca))
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
n->ca_crt = ca;
n->ca_crt_len = strlen(ca);
n->channel = NETWORK_CHANNEL_TLS;
n->timeout_ms = MQTT_TLS_HANDSHAKE_TIMEOUT;
#endif
RETURN_ERROR(MQTT_SUCCESS_ERROR);
}
int network_set_host_port(network_t* n, char *host, char *port)
{
if (!(n && host && port))
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
n->host = host;
n->port = port;
RETURN_ERROR(MQTT_SUCCESS_ERROR);
}

View File

@@ -2,7 +2,7 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2019-12-09 21:31:02 * @Date: 2019-12-09 21:31:02
* @LastEditTime: 2020-02-25 03:49:11 * @LastEditTime: 2020-05-21 01:09:29
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#ifndef _NETWORK_H_ #ifndef _NETWORK_H_
@@ -10,46 +10,30 @@
#include "mqtt_defconfig.h" #include "mqtt_defconfig.h"
#ifdef MQTT_NETWORK_TYPE_TLS #define NETWORK_CHANNEL_TCP 0
typedef struct network_ssl_params { #define NETWORK_CHANNEL_TLS 1
const char *ca_crt;
size_t ca_crt_len;
#if defined(MBEDTLS_FS_IO)
const char *cert_file; // public certificate file
const char *key_file; // pravite certificate file
#else
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
const char *psk; // PSK string
const char *psk_id; // PSK ID
size_t psk_length; // PSK length
#endif
#endif
unsigned int timeout_ms; // SSL handshake timeout in millisecond
} network_ssl_params_t;
#endif /* MQTT_NETWORK_TYPE_TLS */
typedef struct network_params {
char *addr;
char *port;
#ifdef MQTT_NETWORK_TYPE_TLS
network_ssl_params_t network_ssl_params;
void *nettype_tls_params;
#endif /* MQTT_NETWORK_TYPE_TLS */
} network_params_t;
typedef struct network { typedef struct network {
const char *host;
const char *port;
int socket; int socket;
network_params_t network_params; #ifndef MQTT_NETWORK_TYPE_NO_TLS
int (*connect)(struct network *); int channel; /* tcp or tls */
void (*disconnect)(struct network *); const char *ca_crt;
int (*read)(struct network *, unsigned char *, int, int); unsigned int ca_crt_len;
int (*write)(struct network *, unsigned char *, int, int); unsigned int timeout_ms; // SSL handshake timeout in millisecond
void *nettype_tls_params;
#endif
} network_t; } network_t;
int network_init(network_t* n, network_params_t* network_params); int network_init(network_t *n, const char *host, const char *port, const char *ca);
int network_set_ca(network_t *n, const char *ca);
void network_set_channel(network_t *n, int channel);
int network_set_host_port(network_t* n, char *host, char *port);
int network_read(network_t* n, unsigned char* buf, int len, int timeout); int network_read(network_t* n, unsigned char* buf, int len, int timeout);
int network_write(network_t* n, unsigned char* buf, int len, int timeout); int network_write(network_t* n, unsigned char* buf, int len, int timeout);
int network_connect(network_t* n); int network_connect(network_t* n);
void network_disconnect(network_t *n);
void network_release(network_t* n); void network_release(network_t* n);
#endif #endif

View File

@@ -2,7 +2,7 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2020-01-10 23:45:59 * @Date: 2020-01-10 23:45:59
* @LastEditTime: 2020-04-25 18:59:28 * @LastEditTime: 2020-04-25 17:54:44
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#include "platform_net_socket.h" #include "platform_net_socket.h"
@@ -10,7 +10,7 @@
int platform_net_socket_connect(const char *host, const char *port, int proto) int platform_net_socket_connect(const char *host, const char *port, int proto)
{ {
int fd, ret = MQTT_SOCKET_UNKNOWN_HOST_ERROR; int fd, ret = MQTT_SOCKET_UNKNOWN_HOST_ERROR;
#ifdef MQTT_NETSOCKET_USE_AT #ifdef MQTT_NETSOCKET_USING_AT
fd = tos_sal_module_connect(host, port, TOS_SAL_PROTO_TCP); fd = tos_sal_module_connect(host, port, TOS_SAL_PROTO_TCP);
@@ -45,7 +45,7 @@ int platform_net_socket_connect(const char *host, const char *port, int proto)
break; break;
} }
close(fd); platform_net_socket_close(fd);
ret = MQTT_CONNECT_FAILED_ERROR; ret = MQTT_CONNECT_FAILED_ERROR;
} }
@@ -57,7 +57,7 @@ int platform_net_socket_connect(const char *host, const char *port, int proto)
int platform_net_socket_recv(int fd, void *buf, size_t len, int flags) int platform_net_socket_recv(int fd, void *buf, size_t len, int flags)
{ {
#ifdef MQTT_NETSOCKET_USE_AT #ifdef MQTT_NETSOCKET_USING_AT
return tos_sal_module_recv(fd, buf, len); return tos_sal_module_recv(fd, buf, len);
#else #else
return recv(fd, buf, len, flags); return recv(fd, buf, len, flags);
@@ -66,11 +66,14 @@ int platform_net_socket_recv(int fd, void *buf, size_t len, int flags)
int platform_net_socket_recv_timeout(int fd, unsigned char *buf, int len, int timeout) int platform_net_socket_recv_timeout(int fd, unsigned char *buf, int len, int timeout)
{ {
#ifdef MQTT_NETSOCKET_USE_AT #ifdef MQTT_NETSOCKET_USING_AT
return tos_sal_module_recv_timeout(fd, buf, len, timeout); return tos_sal_module_recv_timeout(fd, buf, len, timeout);
#else #else
int rc; int nread;
int bytes = 0; int nleft = len;
unsigned char *ptr;
ptr = buf;
struct timeval tv = { struct timeval tv = {
timeout / 1000, timeout / 1000,
(timeout % 1000) * 1000 (timeout % 1000) * 1000
@@ -83,22 +86,24 @@ int platform_net_socket_recv_timeout(int fd, unsigned char *buf, int len, int ti
platform_net_socket_setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)); platform_net_socket_setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
while (bytes < len) { while (nleft > 0) {
rc = platform_net_socket_recv(fd, &buf[bytes], (size_t)(len - bytes), 0); nread = platform_net_socket_recv(fd, ptr, nleft, 0);
if (rc <= 0) { if (nread < 0) {
bytes = rc; return -1;
} else if (nread == 0) {
break; break;
} else {
bytes += rc;
} }
nleft -= nread;
ptr += nread;
} }
return bytes; return len - nleft;
#endif #endif
} }
int platform_net_socket_write(int fd, void *buf, size_t len) int platform_net_socket_write(int fd, void *buf, size_t len)
{ {
#ifdef MQTT_NETSOCKET_USE_AT #ifdef MQTT_NETSOCKET_USING_AT
return tos_sal_module_send(fd, buf, len); return tos_sal_module_send(fd, buf, len);
#else #else
return write(fd, buf, len); return write(fd, buf, len);
@@ -107,7 +112,7 @@ int platform_net_socket_write(int fd, void *buf, size_t len)
int platform_net_socket_write_timeout(int fd, unsigned char *buf, int len, int timeout) int platform_net_socket_write_timeout(int fd, unsigned char *buf, int len, int timeout)
{ {
#ifdef MQTT_NETSOCKET_USE_AT #ifdef MQTT_NETSOCKET_USING_AT
return tos_sal_module_send(fd, buf, len); return tos_sal_module_send(fd, buf, len);
#else #else
struct timeval tv = { struct timeval tv = {
@@ -128,14 +133,14 @@ int platform_net_socket_write_timeout(int fd, unsigned char *buf, int len, int t
int platform_net_socket_close(int fd) int platform_net_socket_close(int fd)
{ {
#ifdef MQTT_NETSOCKET_USE_AT #ifdef MQTT_NETSOCKET_USING_AT
return tos_sal_module_close(fd); return tos_sal_module_close(fd);
#else #else
return close(fd); return close(fd);
#endif #endif
} }
#ifndef MQTT_NETSOCKET_USE_AT #ifndef MQTT_NETSOCKET_USING_AT
int platform_net_socket_set_block(int fd) int platform_net_socket_set_block(int fd)
{ {

View File

@@ -2,16 +2,16 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2019-12-15 13:39:00 * @Date: 2019-12-15 13:39:00
* @LastEditTime: 2020-02-19 01:02:51 * @LastEditTime: 2020-04-27 23:46:35
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
#ifndef _PLATFORM_NET_SOCKET_H_ #ifndef _PLATFORM_NET_SOCKET_H_
#define _PLATFORM_NET_SOCKET_H_ #define _PLATFORM_NET_SOCKET_H_
#include "network.h" #include "network.h"
#include "error.h" #include "mqtt_error.h"
#ifdef MQTT_NETSOCKET_USE_AT #ifdef MQTT_NETSOCKET_USING_AT
#include "sal_module_wrapper.h" #include "sal_module_wrapper.h"
@@ -35,7 +35,7 @@ int platform_net_socket_write(int fd, void *buf, size_t len);
int platform_net_socket_write_timeout(int fd, unsigned char *buf, int len, int timeout); int platform_net_socket_write_timeout(int fd, unsigned char *buf, int len, int timeout);
int platform_net_socket_close(int fd); int platform_net_socket_close(int fd);
#ifndef MQTT_NETSOCKET_USE_AT #ifndef MQTT_NETSOCKET_USING_AT
int platform_net_socket_set_block(int fd); int platform_net_socket_set_block(int fd);
int platform_net_socket_set_nonblock(int fd); int platform_net_socket_set_nonblock(int fd);
int platform_net_socket_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen); int platform_net_socket_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen);

View File

@@ -1,39 +0,0 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-15 13:38:52
* @LastEditTime : 2020-02-16 02:22:48
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#include "platform_nettype_tcp.h"
#include "log.h"
int platform_nettype_tcp_read(network_t *n, unsigned char *read_buf, int len, int timeout)
{
return platform_net_socket_recv_timeout(n->socket, read_buf, len, timeout);
}
int platform_nettype_tcp_write(network_t *n, unsigned char *write_buf, int len, int timeout)
{
return platform_net_socket_write_timeout(n->socket, write_buf, len, timeout);
}
int platform_nettype_tcp_connect(network_t* n)
{
if (n->socket >= 0) {
platform_net_socket_close(n->socket); // prevent opening too many fd descriptors
}
n->socket = platform_net_socket_connect(n->network_params.addr, n->network_params.port, PLATFORM_NET_PROTO_TCP);
if (n->socket < 0)
RETURN_ERROR(n->socket);
RETURN_ERROR(MQTT_SUCCESS_ERROR);
}
void platform_nettype_tcp_disconnect(network_t* n)
{
if (NULL != n)
platform_net_socket_close(n->socket);
n->socket = -1;
}

View File

@@ -1,20 +0,0 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-15 13:39:00
* @LastEditTime : 2020-01-10 23:48:41
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#ifndef _PLATFORM_NETTYPE_TCP_H_
#define _PLATFORM_NETTYPE_TCP_H_
#include "platform_net_socket.h"
#include "network.h"
#include "error.h"
int platform_nettype_tcp_read(network_t *n, unsigned char *buf, int len, int timeout);
int platform_nettype_tcp_write(network_t *n, unsigned char *buf, int len, int timeout);
int platform_nettype_tcp_connect(network_t* n);
void platform_nettype_tcp_disconnect(network_t* n);
#endif

View File

@@ -18,7 +18,7 @@ platform_thread_t *platform_thread_init( const char *name,
platform_thread_t *thread; platform_thread_t *thread;
k_err_t err; k_err_t err;
k_stack_t *thread_stack; k_stack_t *thread_stack;
thread = platform_memory_calloc(1, sizeof(platform_thread_t)); thread = platform_memory_alloc(sizeof(platform_thread_t));
thread_stack = (k_stack_t*) platform_memory_alloc(stack_size); thread_stack = (k_stack_t*) platform_memory_alloc(stack_size);
err = tos_task_create(&(thread->thread), err = tos_task_create(&(thread->thread),

View File

@@ -2,7 +2,7 @@
* @Author: jiejie * @Author: jiejie
* @Github: https://github.com/jiejieTop * @Github: https://github.com/jiejieTop
* @Date: 2019-12-10 22:16:41 * @Date: 2019-12-10 22:16:41
* @LastEditTime : 2020-01-11 01:19:35 * @LastEditTime: 2020-04-27 22:37:33
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license. * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/ */
@@ -58,10 +58,14 @@ void platform_timer_usleep(unsigned long usec)
uint32_t ms; uint32_t ms;
k_tick_t tick; k_tick_t tick;
ms = usec / 1000; if(usec != 0) {
ms = usec / TOS_CFG_CPU_TICK_PER_SECOND;
if (ms == 0) { if (ms == 0) {
ms = 1; ms = 1;
} }
}
tick = tos_millisec2tick(ms); tick = tos_millisec2tick(ms);

View File

@@ -0,0 +1,3 @@
# 注意
如果用的是AT模组可以结合TencentOS tiny的AT框架与SAL层使用platform_net_socket.c替换原有BSD socket 接口即可。

View File

@@ -0,0 +1,47 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2020-01-10 23:45:59
* @LastEditTime : 2020-01-13 02:48:53
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#include "platform_net_socket.h"
int platform_net_socket_connect(const char *host, const char *port, int proto)
{
int fd;
fd = tos_sal_module_connect(host, port, TOS_SAL_PROTO_TCP);
if (fd < 0) {
return MQTT_CONNECT_FAILED_ERROR;
}
return fd;
}
int platform_net_socket_recv(int fd, void *buf, size_t len, int flags)
{
return tos_sal_module_recv(fd, buf, len);
}
int platform_net_socket_recv_timeout(int fd, unsigned char *buf, int len, int timeout)
{
return tos_sal_module_recv_timeout(fd, buf, len, timeout);
}
int platform_net_socket_write(int fd, void *buf, size_t len)
{
return tos_sal_module_send(fd, buf, len);
}
int platform_net_socket_write_timeout(int fd, unsigned char *buf, int len, int timeout)
{
return tos_sal_module_send(fd, buf, len);
}
int platform_net_socket_close(int fd)
{
return tos_sal_module_close(fd);
}

View File

@@ -0,0 +1,25 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-15 13:39:00
* @LastEditTime: 2020-02-19 01:02:51
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#ifndef _PLATFORM_NET_SOCKET_H_
#define _PLATFORM_NET_SOCKET_H_
#include "network.h"
#include "mqtt_error.h"
#include "stddef.h"
#define PLATFORM_NET_PROTO_TCP 0 /**< The TCP transport protocol */
#define PLATFORM_NET_PROTO_UDP 1 /**< The UDP transport protocol */
int platform_net_socket_connect(const char *host, const char *port, int proto);
int platform_net_socket_recv(int fd, void *buf, size_t len, int flags);
int platform_net_socket_recv_timeout(int fd, unsigned char *buf, int len, int timeout);
int platform_net_socket_write(int fd, void *buf, size_t len);
int platform_net_socket_write_timeout(int fd, unsigned char *buf, int len, int timeout);
int platform_net_socket_close(int fd);
#endif /* _PLATFORM_NET_SOCKET_H_ */

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View File

@@ -0,0 +1,5 @@
set(SUBDIRS "emqx" "onenet" "baidu" "ali")
foreach(subdir ${SUBDIRS})
add_subdirectory(${subdir})
endforeach()

View File

@@ -0,0 +1,12 @@
aux_source_directory(. DIR_SRCS)
set(INCDIRS ${CMAKE_CURRENT_SOURCE_DIR})
add_executable("ali" ${DIR_SRCS})
foreach(findlib ${LIBNAMES})
target_link_libraries("ali" ${findlib})
endforeach()
find_package("Threads")
target_link_libraries("ali" ${CMAKE_THREAD_LIBS_INIT})

View File

@@ -0,0 +1,77 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-11 21:53:07
* @LastEditTime: 2020-06-08 20:40:47
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>
#include "mqttclient.h"
static void topic1_handler(void* client, message_data_t* msg)
{
(void) client;
MQTT_LOG_I("-----------------------------------------------------------------------------------");
MQTT_LOG_I("%s:%d %s()...\ntopic: %s\nmessage:%s", __FILE__, __LINE__, __FUNCTION__, msg->topic_name, (char*)msg->message->payload);
MQTT_LOG_I("-----------------------------------------------------------------------------------");
}
void *mqtt_publish_thread(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...");
sleep(2);
mqtt_list_subscribe_topic(client);
msg.payload = (void *) buf;
msg.qos = 0;
while(1) {
sprintf(buf, "welcome to mqttclient, this is a publish test, a rand number: %d ...", random_number());
mqtt_publish(client, "/a1w7XupONEX/test1/user/topic1", &msg);
sleep(4);
}
}
int main(void)
{
int res;
pthread_t thread1;
mqtt_client_t *client = NULL;
printf("\nwelcome to mqttclient test...\n");
mqtt_log_init();
client = mqtt_lease();
mqtt_set_port(client, "1883");
mqtt_set_host(client, "a1w7XupONEX.iot-as-mqtt.cn-shanghai.aliyuncs.com");
mqtt_set_client_id(client, "123456|securemode=3,signmethod=hmacsha1|");
mqtt_set_user_name(client, "test1&a1w7XupONEX");
mqtt_set_password(client, "A9EFF34CCA05EABAE560373CBED3E43AC88956CF");
mqtt_set_clean_session(client, 1);
mqtt_connect(client);
mqtt_subscribe(client, "/a1w7XupONEX/test1/user/topic1", QOS0, topic1_handler);
res = pthread_create(&thread1, NULL, mqtt_publish_thread, client);
if(res != 0) {
MQTT_LOG_E("create mqtt publish thread fail");
exit(res);
}
while (1) {
sleep(100);
}
}

View File

@@ -0,0 +1,12 @@
aux_source_directory(. DIR_SRCS)
set(INCDIRS ${CMAKE_CURRENT_SOURCE_DIR})
add_executable("baidu" ${DIR_SRCS})
foreach(findlib ${LIBNAMES})
target_link_libraries("baidu" ${findlib})
endforeach()
find_package("Threads")
target_link_libraries("baidu" ${CMAKE_THREAD_LIBS_INIT})

View File

@@ -0,0 +1,109 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-11 21:53:07
* @LastEditTime: 2020-06-08 20:38:41
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>
#include "mqttclient.h"
// #define TEST_USEING_TLS
static const char *test_baidu_ca_crt = {
"-----BEGIN CERTIFICATE-----\r\n"
"MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G\r\n"
"A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp\r\n"
"Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4\r\n"
"MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG\r\n"
"A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI\r\n"
"hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8\r\n"
"RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT\r\n"
"gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm\r\n"
"KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd\r\n"
"QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ\r\n"
"XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw\r\n"
"DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o\r\n"
"LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU\r\n"
"RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp\r\n"
"jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK\r\n"
"6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX\r\n"
"mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs\r\n"
"Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH\r\n"
"WD9f\r\n"
"-----END CERTIFICATE-----"
};
static void topic1_handler(void* client, message_data_t* msg)
{
(void) client;
MQTT_LOG_I("-----------------------------------------------------------------------------------");
MQTT_LOG_I("%s:%d %s()...\ntopic: %s\nmessage:%s", __FILE__, __LINE__, __FUNCTION__, msg->topic_name, (char*)msg->message->payload);
MQTT_LOG_I("-----------------------------------------------------------------------------------");
}
void *mqtt_publish_thread(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...");
sleep(2);
mqtt_list_subscribe_topic(client);
msg.payload = (void *) buf;
msg.qos = 0;
while(1) {
sprintf(buf, "welcome to mqttclient, this is a publish test, a rand number: %d ...", random_number());
mqtt_publish(client, "topic1", &msg);
sleep(4);
}
}
int main(void)
{
int res;
pthread_t thread1;
mqtt_client_t *client = NULL;
printf("\nwelcome to mqttclient test...\n");
mqtt_log_init();
client = mqtt_lease();
#ifdef TEST_USEING_TLS
mqtt_set_port(client, "1884");
mqtt_set_ca(client, (char*)test_baidu_ca_crt);
#else
mqtt_set_port(client, "1883");
#endif
mqtt_set_host(client, "j6npr4w.mqtt.iot.gz.baidubce.com");
mqtt_set_client_id(client, random_string(10));
mqtt_set_user_name(client, "j6npr4w/mqtt-client-dev");
mqtt_set_password(client, "lcUhUs5VYLMSbrnB");
mqtt_set_clean_session(client, 1);
mqtt_connect(client);
mqtt_subscribe(client, "topic1", QOS0, topic1_handler);
res = pthread_create(&thread1, NULL, mqtt_publish_thread, client);
if(res != 0) {
MQTT_LOG_E("create mqtt publish thread fail");
exit(res);
}
while (1) {
sleep(100);
}
}

View File

@@ -0,0 +1,12 @@
aux_source_directory(. DIR_SRCS)
set(INCDIRS ${CMAKE_CURRENT_SOURCE_DIR})
add_executable("emqx" ${DIR_SRCS})
foreach(findlib ${LIBNAMES})
target_link_libraries("emqx" ${findlib})
endforeach()
find_package("Threads")
target_link_libraries("emqx" ${CMAKE_THREAD_LIBS_INIT})

View File

@@ -0,0 +1,100 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-11 21:53:07
* @LastEditTime: 2020-06-08 20:45:33
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>
#include "mqtt_config.h"
#include "mqtt_log.h"
#include "mqttclient.h"
// #define TEST_USEING_TLS
extern const char *test_ca_get();
static void topic1_handler(void* client, message_data_t* msg)
{
(void) client;
MQTT_LOG_I("-----------------------------------------------------------------------------------");
MQTT_LOG_I("%s:%d %s()...\ntopic: %s\nmessage:%s", __FILE__, __LINE__, __FUNCTION__, msg->topic_name, (char*)msg->message->payload);
MQTT_LOG_I("-----------------------------------------------------------------------------------");
}
void *mqtt_publish_thread(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...");
sleep(2);
mqtt_list_subscribe_topic(client);
msg.payload = (void *) buf;
while(1) {
sprintf(buf, "welcome to mqttclient, this is a publish test, a rand number: %d ...", random_number());
msg.qos = 0;
mqtt_publish(client, "topic1", &msg);
msg.qos = 1;
mqtt_publish(client, "topic2", &msg);
msg.qos = 2;
mqtt_publish(client, "topic3", &msg);
sleep(4);
}
}
int main(void)
{
int res;
pthread_t thread1;
mqtt_client_t *client = NULL;
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);
mqtt_connect(client);
mqtt_subscribe(client, "topic1", QOS0, topic1_handler);
mqtt_subscribe(client, "topic2", QOS1, NULL);
mqtt_subscribe(client, "topic3", QOS2, NULL);
res = pthread_create(&thread1, NULL, mqtt_publish_thread, client);
if(res != 0) {
MQTT_LOG_E("create mqtt publish thread fail");
exit(res);
}
while (1) {
sleep(100);
}
}

View File

@@ -0,0 +1,75 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2020-01-12 10:51:11
* @LastEditTime: 2020-03-21 21:07:24
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
static const char *test_ca_crt = {
"-----BEGIN CERTIFICATE-----\r\n"
"MIIFrTCCBJWgAwIBAgIQDApSGhCHMtFicAaXgcO0vjANBgkqhkiG9w0BAQsFADBy\r\n"
"MQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywg\r\n"
"SW5jLjEdMBsGA1UECxMURG9tYWluIFZhbGlkYXRlZCBTU0wxHTAbBgNVBAMTFFRy\r\n"
"dXN0QXNpYSBUTFMgUlNBIENBMB4XDTIwMDEyOTAwMDAwMFoXDTIxMDQyODEyMDAw\r\n"
"MFowGzEZMBcGA1UEAxMQd3d3LmppZWppZTAxLnRvcDCCASIwDQYJKoZIhvcNAQEB\r\n"
"BQADggEPADCCAQoCggEBAKIDMo45w085LaCMG1LWY5b8V94zDqdt+weVhKolgsLZ\r\n"
"htAQTDrafBx1sNJtOpa8ADeQkFbWOTEy3tgViOBvBr+8Qhl6vYsESJrg7DXeCVRm\r\n"
"04pk+cFrdWYRE70AUz8RXRuaWLv1Fu2L+qlymrnZB/WBJFnETINh6yzqY8FNETUV\r\n"
"EL08eE0LoXt/4b7iAJYEFRYTyBKjLpkr04e92SQIuL/l42j92lYNOjYfYOlpWZUC\r\n"
"cp4WHXEDd1YXdTMmXpfsU3VlYS3RTusOFsgXpLFET9xGRvtDSu5qw6rPGf/y/PhT\r\n"
"1LFB/xlL2E6Rpo/6VWuQ8A5rA+H3D1I/fIBB97orMYUCAwEAAaOCApQwggKQMB8G\r\n"
"A1UdIwQYMBaAFH/TmfOgRw4xAFZWIo63zJ7dygGKMB0GA1UdDgQWBBQyzyOTN1l5\r\n"
"Rg1Ih1tQ0TPYMqfw+jApBgNVHREEIjAgghB3d3cuamllamllMDEudG9wggxqaWVq\r\n"
"aWUwMS50b3AwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggr\r\n"
"BgEFBQcDAjBMBgNVHSAERTBDMDcGCWCGSAGG/WwBAjAqMCgGCCsGAQUFBwIBFhxo\r\n"
"dHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeBDAECATCBkgYIKwYBBQUH\r\n"
"AQEEgYUwgYIwNAYIKwYBBQUHMAGGKGh0dHA6Ly9zdGF0dXNlLmRpZ2l0YWxjZXJ0\r\n"
"dmFsaWRhdGlvbi5jb20wSgYIKwYBBQUHMAKGPmh0dHA6Ly9jYWNlcnRzLmRpZ2l0\r\n"
"YWxjZXJ0dmFsaWRhdGlvbi5jb20vVHJ1c3RBc2lhVExTUlNBQ0EuY3J0MAkGA1Ud\r\n"
"EwQCMAAwggEEBgorBgEEAdZ5AgQCBIH1BIHyAPAAdQB9PvL4j/+IVWgkwsDKnlKJ\r\n"
"eSvFDngJfy5ql2iZfiLw1wAAAW/wKSTgAAAEAwBGMEQCIGFq0FdvZfXf4lV20Am1\r\n"
"HRP6F7wxzkesK0r1566sNqvxAiBp5W3iTLWEgeJa/PfH5hX/d+K5CIyXScLa4qqa\r\n"
"MCLHwwB3AFzcQ5L+5qtFRLFemtRW5hA3+9X6R9yhc5SyXub2xw7KAAABb/ApJJIA\r\n"
"AAQDAEgwRgIhANEsjShyRf0GGpwJ6ZTQKBHo933rlSpaNIvor7cG8RBQAiEAkeDf\r\n"
"7+n+zyEGZUMOYI0E0R2chjPBJGvtw1yD12sxekowDQYJKoZIhvcNAQELBQADggEB\r\n"
"AIzaZ5X1So+xVe2JWkMfmJA8IQhdp9WghCDLRORcIggcY9BtYxFSBdusxIa1bhdt\r\n"
"rCY6RoepCwTrhV9PotwMgZtSOu8szHHRlqX8zNUhIh628yzPSTDDZ4xgeJvlGAkT\r\n"
"Zlv0XrezkDLRZkKN9R6KX1ccaPNbn9PD6SMtpHPbE7UEZYfrV3wAJhFzsyhp2JF4\r\n"
"KLLNPaeDgDM3Lu6tUm/bznDEyxi7/ZoR+7fSQAMF5Jo1ysKUAOC00I9Ne+7eSbTh\r\n"
"flV//8NBN+Z2ShCV0uFedf6ugDUMOuOUCtp0c7N+sM1IVE5MOhLRDAGRIUyi7/43\r\n"
"dJ0Okust1fXo4UTDGJtyp30=\r\n"
"-----END CERTIFICATE-----\r\n"
"-----BEGIN CERTIFICATE-----\r\n"
"MIIErjCCA5agAwIBAgIQBYAmfwbylVM0jhwYWl7uLjANBgkqhkiG9w0BAQsFADBh\r\n"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\r\n"
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\r\n"
"QTAeFw0xNzEyMDgxMjI4MjZaFw0yNzEyMDgxMjI4MjZaMHIxCzAJBgNVBAYTAkNO\r\n"
"MSUwIwYDVQQKExxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMR0wGwYDVQQL\r\n"
"ExREb21haW4gVmFsaWRhdGVkIFNTTDEdMBsGA1UEAxMUVHJ1c3RBc2lhIFRMUyBS\r\n"
"U0EgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgWa9X+ph+wAm8\r\n"
"Yh1Fk1MjKbQ5QwBOOKVaZR/OfCh+F6f93u7vZHGcUU/lvVGgUQnbzJhR1UV2epJa\r\n"
"e+m7cxnXIKdD0/VS9btAgwJszGFvwoqXeaCqFoP71wPmXjjUwLT70+qvX4hdyYfO\r\n"
"JcjeTz5QKtg8zQwxaK9x4JT9CoOmoVdVhEBAiD3DwR5fFgOHDwwGxdJWVBvktnoA\r\n"
"zjdTLXDdbSVC5jZ0u8oq9BiTDv7jAlsB5F8aZgvSZDOQeFrwaOTbKWSEInEhnchK\r\n"
"ZTD1dz6aBlk1xGEI5PZWAnVAba/ofH33ktymaTDsE6xRDnW97pDkimCRak6CEbfe\r\n"
"3dXw6OV5AgMBAAGjggFPMIIBSzAdBgNVHQ4EFgQUf9OZ86BHDjEAVlYijrfMnt3K\r\n"
"AYowHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQD\r\n"
"AgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAG\r\n"
"AQH/AgEAMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au\r\n"
"ZGlnaWNlcnQuY29tMEIGA1UdHwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2lj\r\n"
"ZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RDQS5jcmwwTAYDVR0gBEUwQzA3Bglg\r\n"
"hkgBhv1sAQIwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29t\r\n"
"L0NQUzAIBgZngQwBAgEwDQYJKoZIhvcNAQELBQADggEBAK3dVOj5dlv4MzK2i233\r\n"
"lDYvyJ3slFY2X2HKTYGte8nbK6i5/fsDImMYihAkp6VaNY/en8WZ5qcrQPVLuJrJ\r\n"
"DSXT04NnMeZOQDUoj/NHAmdfCBB/h1bZ5OGK6Sf1h5Yx/5wR4f3TUoPgGlnU7EuP\r\n"
"ISLNdMRiDrXntcImDAiRvkh5GJuH4YCVE6XEntqaNIgGkRwxKSgnU3Id3iuFbW9F\r\n"
"UQ9Qqtb1GX91AJ7i4153TikGgYCdwYkBURD8gSVe8OAco6IfZOYt/TEwii1Ivi1C\r\n"
"qnuUlWpsF1LdQNIdfbW3TSe0BhQa7ifbVIfvPWHYOu3rkg1ZeMo6XRU9B4n5VyJY\r\n"
"RmE=\r\n"
"-----END CERTIFICATE-----"
};
const char *test_ca_get()
{
return test_ca_crt;
}

View File

@@ -0,0 +1,46 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @LastEditTime: 2020-06-17 19:31:41
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#ifndef _MQTT_CONFIG_H_
#define _MQTT_CONFIG_H_
#define MQTT_LOG_IS_SALOF
#define MQTT_LOG_LEVEL MQTT_LOG_INFO_LEVEL //MQTT_LOG_WARN_LEVEL MQTT_LOG_DEBUG_LEVEL
#ifdef MQTT_LOG_IS_SALOF
#define SALOF_USING_LOG (1U)
#define SALOF_USING_SALOF (1U)
#define SALOF_LOG_LEVEL MQTT_LOG_LEVEL
#define SALOF_OS SALOF_USING_LINUX
#define SALOF_USING_IDLE_HOOK (0U)
#define SALOF_LOG_COLOR (1U)
#define SALOF_LOG_TS (0U)
#define SALOF_LOG_TAR (0U)
#define SALOF_BUFF_SIZE 512
#define SALOF_FIFO_SIZE 4096
#define SALOF_TASK_STACK_SIZE 1024
#define SALOF_TASK_TICK 50
#endif
#define MQTT_MAX_PACKET_ID (0xFFFF - 1)
#define MQTT_TOPIC_LEN_MAX 64
#define MQTT_ACK_HANDLER_NUM_MAX 64
#define MQTT_DEFAULT_BUF_SIZE 1024
#define MQTT_DEFAULT_CMD_TIMEOUT 5000
#define MQTT_MAX_CMD_TIMEOUT 20000
#define MQTT_MIN_CMD_TIMEOUT 1000
#define MQTT_KEEP_ALIVE_INTERVAL 50 // unit: second
#define MQTT_VERSION 4 // 4 is mqtt 3.1.1
#define MQTT_RECONNECT_DEFAULT_DURATION 1000
#define MQTT_THREAD_STACK_SIZE 2048
#define MQTT_THREAD_PRIO 5
#define MQTT_THREAD_TICK 50
// #define MQTT_NETWORK_TYPE_NO_TLS
#endif /* _MQTT_CONFIG_H_ */

View File

@@ -0,0 +1,12 @@
aux_source_directory(. DIR_SRCS)
set(INCDIRS ${CMAKE_CURRENT_SOURCE_DIR})
add_executable("onenet" ${DIR_SRCS})
foreach(findlib ${LIBNAMES})
target_link_libraries("onenet" ${findlib})
endforeach()
find_package("Threads")
target_link_libraries("onenet" ${CMAKE_THREAD_LIBS_INIT})

View File

@@ -0,0 +1,78 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2020-04-18 12:37:34
* @LastEditTime: 2020-06-08 20:32:33
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>
#include "mqttclient.h"
extern const char *test_ca_get();
static void interceptor_handler(void* client, message_data_t* msg)
{
(void) client;
MQTT_LOG_I("-----------------------------------------------------------------------------------");
MQTT_LOG_I("%s:%d %s()...\ntopic: %s\nmessage:%s", __FILE__, __LINE__, __FUNCTION__, msg->topic_name, (char*)msg->message->payload);
MQTT_LOG_I("-----------------------------------------------------------------------------------");
}
void *mqtt_publish_thread(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...");
msg.qos = 0;
msg.payload = (void *) buf;
while(1) {
sprintf(buf, "welcome to mqttclient, this is a publish test, a rand number: %d ...", random_number());
mqtt_publish(client, "topic1", &msg);
sleep(4);
}
}
int main(void)
{
int res;
pthread_t thread1;
mqtt_client_t *client = NULL;
printf("\nwelcome to mqttclient test...\n");
mqtt_log_init();
client = mqtt_lease();
mqtt_set_port(client, "6002");
mqtt_set_host(client, "183.230.40.39");
mqtt_set_client_id(client, "599908192");
mqtt_set_user_name(client, "348547");
mqtt_set_password(client, "mqttclienttest1");
mqtt_set_clean_session(client, 1);
mqtt_connect(client);
mqtt_subscribe(client, "topic1", QOS0, NULL);
mqtt_set_interceptor_handler(client, interceptor_handler); // set interceptor handler
res = pthread_create(&thread1, NULL, mqtt_publish_thread, client);
if(res != 0) {
MQTT_LOG_E("create mqtt publish thread fail");
exit(res);
}
while (1) {
sleep(100);
}
}

View File

@@ -7,16 +7,13 @@
k_task_t task; k_task_t task;
k_stack_t task_stack[2048]; k_stack_t task_stack[2048];
mqtt_client_t client;
client_init_params_t init_params;
static void tos_topic_handler(void* client, message_data_t* msg) static void tos_topic_handler(void* client, message_data_t* msg)
{ {
(void) client; (void) client;
LOG_I("-----------------------------------------------------------------------------------"); MQTT_LOG_I("-----------------------------------------------------------------------------------");
LOG_I("%s:%d %s()...\ntopic: %s, qos: %d. \nmessage:\n\t%s\n", __FILE__, __LINE__, __FUNCTION__, MQTT_LOG_I("%s:%d %s()...\ntopic: %s, qos: %d. \nmessage:\n\t%s\n", __FILE__, __LINE__, __FUNCTION__,
msg->topic_name, msg->message->qos, (char*)msg->message->payload); msg->topic_name, msg->message->qos, (char*)msg->message->payload);
LOG_I("-----------------------------------------------------------------------------------\n"); MQTT_LOG_I("-----------------------------------------------------------------------------------\n");
} }
@@ -25,41 +22,41 @@ void mqttclient_task(void *Parameter)
int error; int error;
char buf[100] = { 0 }; char buf[100] = { 0 };
mqtt_message_t msg; mqtt_message_t msg;
mqtt_client_t *client = NULL;
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
printf("\nwelcome to mqttclient test...\n");
esp8266_sal_init(HAL_UART_PORT_2); esp8266_sal_init(HAL_UART_PORT_2);
esp8266_join_ap("wifii", "woshijiejie"); esp8266_join_ap("wifii", "woshijiejie");
init_params.read_buf_size = 256; mqtt_log_init();
init_params.write_buf_size = 256;
#ifdef MQTT_NETWORK_TYPE_TLS client = mqtt_lease();
init_params.connect_params.network_params.network_ssl_params.ca_crt = test_ca_get();
init_params.connect_params.network_params.port = "8883";
#else
init_params.connect_params.network_params.port = "1883";
#endif
init_params.connect_params.network_params.addr = "www.jiejie01.top"; //"47.95.164.112";//"jiejie01.top"; //"129.204.201.235"; //"192.168.1.101";
init_params.connect_params.user_name = random_string(10); // random_string(10); //"jiejietop-acer1"; mqtt_set_port(client, "1883");
init_params.connect_params.password = random_string(10);; //random_string(10); // "123456"; mqtt_set_host(client, "www.jiejie01.top");
init_params.connect_params.client_id = random_string(10);; //random_string(10); // "clientid-acer1"; mqtt_set_client_id(client, random_string(10));
init_params.connect_params.clean_session = 1; mqtt_set_user_name(client, random_string(10));
mqtt_set_password(client, random_string(10));
mqtt_set_clean_session(client, 1);
mqtt_set_read_buf_size(client, 256);
mqtt_set_write_buf_size(client, 256);
log_init(); error = mqtt_connect(client);
mqtt_init(&client, &init_params); MQTT_LOG_D("mqtt connect error is %#x", error);
error = mqtt_connect(&client);
LOG_D("mqtt connect error is %#x", error); error = mqtt_connect(client);
mqtt_subscribe(&client, "tos-topic", QOS0, tos_topic_handler); MQTT_LOG_D("mqtt connect error is %#x", error);
LOG_D("mqtt subscribe error is %#x", error); mqtt_subscribe(client, "tos-topic", QOS0, tos_topic_handler);
MQTT_LOG_D("mqtt subscribe error is %#x", error);
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
@@ -70,7 +67,7 @@ void mqttclient_task(void *Parameter)
msg.qos = QOS0; msg.qos = QOS0;
msg.payload = (void *) buf; msg.payload = (void *) buf;
error = mqtt_publish(&client, "tos-topic", &msg); error = mqtt_publish(client, "tos-topic", &msg);
tos_task_delay(4000); tos_task_delay(4000);
} }

View File

@@ -16,27 +16,28 @@
#include "mqttclient.h" #include "mqttclient.h"
#define TEST_USEING_TLS
extern const char *test_ca_get(void); extern const char *test_ca_get(void);
static void tos_topic_handler(void* client, message_data_t* msg) static void tos_topic_handler(void* client, message_data_t* msg)
{ {
(void) client; (void) client;
LOG_I("-----------------------------------------------------------------------------------"); MQTT_LOG_I("-----------------------------------------------------------------------------------");
LOG_I("%s:%d %s()...\ntopic: %s, qos: %d. \nmessage:\n\t%s\n", __FILE__, __LINE__, __FUNCTION__, MQTT_LOG_I("%s:%d %s()...\ntopic: %s, qos: %d. \nmessage:\n\t%s\n", __FILE__, __LINE__, __FUNCTION__,
msg->topic_name, msg->message->qos, (char*)msg->message->payload); msg->topic_name, msg->message->qos, (char*)msg->message->payload);
LOG_I("-----------------------------------------------------------------------------------\n"); MQTT_LOG_I("-----------------------------------------------------------------------------------\n");
} }
mqtt_client_t client;
client_init_params_t init_params;
extern void TCPIP_Init(void); extern void TCPIP_Init(void);
void application_entry(void *arg) void application_entry(void *arg)
{ {
int error; int error;
char buf[80] = { 0 }; char buf[80] = { 0 };
mqtt_client_t *client = NULL;
mqtt_message_t msg; mqtt_message_t msg;
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
@@ -44,33 +45,30 @@ void application_entry(void *arg)
TCPIP_Init(); TCPIP_Init();
init_params.read_buf_size = 1024; mqtt_log_init();
init_params.write_buf_size = 1024;
#ifdef MQTT_NETWORK_TYPE_TLS client = mqtt_lease();
init_params.connect_params.network_params.network_ssl_params.ca_crt = test_ca_get();
init_params.connect_params.network_params.port = "8883"; #ifdef TEST_USEING_TLS
mqtt_set_port(client, "8883");
mqtt_set_ca(client, (char*)test_ca_get());
#else #else
init_params.connect_params.network_params.port = "1883"; mqtt_set_port(client, "1883");
#endif #endif
init_params.connect_params.network_params.addr = "www.jiejie01.top"; //"47.95.164.112";//"jiejie01.top"; //"129.204.201.235"; //"192.168.1.101";
init_params.connect_params.user_name = random_string(10); mqtt_set_host(client, "www.jiejie01.top");
init_params.connect_params.password = random_string(10); mqtt_set_client_id(client, random_string(10));
init_params.connect_params.client_id = random_string(10); mqtt_set_user_name(client, random_string(10));
init_params.connect_params.clean_session = 1; mqtt_set_password(client, random_string(10));
mqtt_set_clean_session(client, 1);
log_init(); error = mqtt_connect(client);
mqtt_init(&client, &init_params); MQTT_LOG_D("mqtt connect error is %#x", error);
error = mqtt_connect(&client); mqtt_subscribe(client, "tos-topic", QOS0, tos_topic_handler);
LOG_D("mqtt connect error is %#x", error); MQTT_LOG_D("mqtt subscribe error is %#x", error);
mqtt_subscribe(&client, "tos-topic", QOS0, tos_topic_handler);
LOG_D("mqtt subscribe error is %#x", error);
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
@@ -81,7 +79,7 @@ void application_entry(void *arg)
msg.qos = QOS0; msg.qos = QOS0;
msg.payload = (void *) buf; msg.payload = (void *) buf;
mqtt_publish(&client, "tos-topic", &msg); mqtt_publish(client, "tos-topic", &msg);
tos_task_delay(4000); tos_task_delay(4000);
} }

View File

@@ -19,15 +19,14 @@
static void tos_topic_handler(void* client, message_data_t* msg) static void tos_topic_handler(void* client, message_data_t* msg)
{ {
(void) client; (void) client;
LOG_I("-----------------------------------------------------------------------------------"); MQTT_LOG_I("-----------------------------------------------------------------------------------");
LOG_I("%s:%d %s()...\ntopic: %s, qos: %d. \nmessage:\n\t%s\n", __FILE__, __LINE__, __FUNCTION__, MQTT_LOG_I("%s:%d %s()...\ntopic: %s, qos: %d. \nmessage:\n\t%s\n", __FILE__, __LINE__, __FUNCTION__,
msg->topic_name, msg->message->qos, (char*)msg->message->payload); msg->topic_name, msg->message->qos, (char*)msg->message->payload);
LOG_I("-----------------------------------------------------------------------------------\n"); MQTT_LOG_I("-----------------------------------------------------------------------------------\n");
} }
mqtt_client_t client; mqtt_client_t client;
client_init_params_t init_params;
extern void TCPIP_Init(void); extern void TCPIP_Init(void);
@@ -36,39 +35,41 @@ void application_entry(void *arg)
int error; int error;
char buf[80] = { 0 }; char buf[80] = { 0 };
mqtt_message_t msg; mqtt_message_t msg;
mqtt_client_t *client = NULL;
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
sprintf(buf, "welcome to mqttclient, this is a publish test..."); printf("\nwelcome to mqttclient test...\n");
TCPIP_Init(); TCPIP_Init();
init_params.read_buf_size = 1024; mqtt_log_init();
init_params.write_buf_size = 1024;
init_params.connect_params.network_params.addr = "iotcloud-mqtt.gz.tencentdevices.com";
init_params.connect_params.network_params.port = "1883";
init_params.connect_params.user_name = "7ABAKP6KNCtest1;12010126;KGRDH;1618120908";
init_params.connect_params.password = "35c065988c4beeb32d8a2f1f283a7a1535e79295f4b6368f2ec61ee7b1b8c271;hmacsha256";
init_params.connect_params.client_id = "7ABAKP6KNCtest1";
init_params.connect_params.clean_session = 1;
log_init(); client = mqtt_lease();
mqtt_init(&client, &init_params); mqtt_set_port(client, "1883");
error = mqtt_connect(&client); mqtt_set_host(client, "iotcloud-mqtt.gz.tencentdevices.com");
mqtt_set_client_id(client, "7ABAKP6KNCtest1");
mqtt_set_user_name(client, "7ABAKP6KNCtest1;12010126;KGRDH;1618120908");
mqtt_set_password(client, "35c065988c4beeb32d8a2f1f283a7a1535e79295f4b6368f2ec61ee7b1b8c271;hmacsha256");
mqtt_set_clean_session(client, 1);
LOG_D("mqtt connect error is %#x", error); error = mqtt_connect(client);
mqtt_subscribe(&client, "7ABAKP6KNC/test1/data", QOS0, tos_topic_handler); MQTT_LOG_D("mqtt connect error is %#x", error);
mqtt_subscribe(client, "7ABAKP6KNC/test1/data", QOS0, tos_topic_handler);
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
sprintf(buf, "welcome to mqttclient, this is a publish test...");
for (;;) { for (;;) {
msg.qos = QOS0; msg.qos = QOS0;
msg.payload = (void *) buf; msg.payload = (void *) buf;
mqtt_publish(&client, "7ABAKP6KNC/test1/data", &msg); mqtt_publish(client, "7ABAKP6KNC/test1/data", &msg);
tos_task_delay(4000); tos_task_delay(4000);
} }