update mqtt client

update mqtt client
This commit is contained in:
supowang
2021-03-09 16:30:41 +08:00
parent 167840e9fa
commit 54022c2481
17 changed files with 514 additions and 542 deletions

View File

@@ -8,63 +8,62 @@
![](https://img.shields.io/badge/platform-Linux|Windows|Mac|Embedded-orange.svg)
[English Documents](README.md)
[中文说明](README_CN.md)
# mqttclient
**一个高性能、高稳定性的跨平台MQTT客户端**
**A high-performance, high-stability, cross-platform MQTT client**
一个高性能、高稳定性的跨平台MQTT客户端基于socket API之上开发可以在嵌入式设备FreeRTOS/LiteOS/RT-Thread/TencentOS tiny)、LinuxWindowsMac上使用拥有非常简洁的API接口以极少的资源实现QOS2的服务质量并且无缝衔接了mbedtls加密库。
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:
- **具有极高的稳定性**:无论是**掉线重连****丢包重发**,都是**严格遵循MQTT协议标准**执行,除此之外对**大数据量**的测试无论是收是发,都是非常稳定,**高频**测试也是非常稳定。
- **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.
- **轻量级**整个代码工程极其简单不使用mbedtls情况下占用资源极少作者曾使用esp8266模组与云端通信整个工程代码消耗的RAM不足15k。
- **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.
- **支持mbedtls加密传输**让网络传输更加安全而且接口层完全不需要用户理会无论是否加密mqttclient对用户提供的API接口是**固定**的,这就很好的兼容了一套代应用层的码可以加密传输也可以不加密传输。
- **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.
- **支持同步异步处理**应用程序无需阻塞等待浪费CPU资源。
- **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.
- **拥有在线代码生成工具**,极其简单配置就可以生成对应的代码,地址:[https://jiejietop.gitee.io/mqtt/index.html](https://jiejietop.gitee.io/mqtt/index.html)
- **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)
- **拥有极简的API接口**总的来说mqttclient的配置都有默认值基本无需配置都能使用的也可以随意配置对配置都有健壮性检测这样子设计的API接口也是非常简单。
- **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.
- **mqttclient内部已实现保活处理机制**,无需用户过多关心理会,用户只需专心处理应用功能即可。
- **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.
- **拥有非常好的设计**,以极少的资源设计了**记录机制**当报文在丢失的时候进行重发操作确保qos1、qos2服务质量等级的报文保证其服务质量。
- **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.
- **基于标准BSD socket之上开发**,只要是兼容BSD socket的系统均可使用。
- **Developed on top of standard BSD socket**, as long as it is compatible with BSD socket system.
- **无缝衔接salof**它是一个同步异步日志输出框架在空闲时候输出对应的日志信息也可以将信息写入flash中保存方便调试。
- **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.
- **使用著名的 paho mqtt 库封包**
- **Use the famous paho mqtt library package**.
- **无其他依赖**
- **No other dependencies**.
## 在线代码生成工具
## Online code generation tool
本项目拥有代码生成工具,只需要在线配置即可生成代码,极其简单易用,代码生成工具地址:[https://jiejietop.gitee.io/mqtt/index.html](https://jiejietop.gitee.io/mqtt/index.html)
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)
![在线代码生成工具](png/mqtt-tool.png)
![Online code generation tool](png/mqtt-tool.png)
## 占用资源大小
## occupied resource size
总计占 **10857字节** 的ROM而RAM的开销则几乎只依赖动态内存在不使用TLS加密传输的情况下维持QOS0服务质量等级的通信动态内存大约仅需要**3694**字节这包括1024读缓冲区 + 1024写缓冲区 + 1024内部线程栈大小相对于其他MQTT客户端来说mqttclient需要的RAM资源开销极少。
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 |
| -- | -- | -- | -- | -- |
@@ -87,125 +86,124 @@
| - | - | - | - | - |
| 10066 | 791 | 8 | 0 | total |
## 整体框架
## Overall framework
拥有非常明确的分层框架。
Has a very clear layered framework.
![整体框架](png/mqttclient.png)
![Overall Frame](png/mqttclient.png)
- 在框架的最上方是**API**函数接口,实现了客户端的**申请、释放、设置参数、连接服务器、断开连接、订阅主题、取消订阅主题、发布消息**等函数接口。
- 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.
- 使用了著名的**paho mqtt**库作为MQTT报文封包库。
- The famous **paho mqtt** library is used as the MQTT message packet library.
- 采用异步处理的机制去管理所有的ack它在发送报文的时候不用等待服务器的应答只是记录下来在收到服务器的ack后取消这个记录**效率极高**而在发送mqtt报文QoS1/QoS2的时候没有收到服务器的应答时将**重发**该报文。
- 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**.
- 内部实现了一个**mqtt yield**线程,统一处理所有的内容,比如**超时的处理、ack报文的处理、收到来自服务器的publish报文**,此时会去调用回调函数告知用户收到的数据,**发布释放、发布完成报文的处理、心跳报文(保持活性),当与服务器断开连接时需要尝试重连、重新订阅主题,重新发送报文或者应答**等。
- 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.
- 报文的处理,如**读写报文、解码mqtt报文、设置报文dup标记、销毁报文**等操作。
- Message processing, such as **reading and writing messages, decoding mqtt messages, setting messages (dup flag), destroying messages** and other operations.
- **network**是网络组件,它可以**自动选择数据通道**,如果是加密方式则通过**tls加密**进行数据传输而tls可以选择mbedtls作为加密后端也可以是**tcp直连**方式最终都是通过tcp传输的。
- **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**是平台抽象层,封装了不同系统的东西,比如**socke或者AT线程、时间、互斥锁、内存管理**,这些是与系统打交道的,也是跨平台必要的封装。
- **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.
- 最右边的则是通用的内容,**list的处理、日志库、错误处理、软件随机数发生器**等。
- On the far right is the general content, **list processing, log library, error handling, software random number generator**, etc.
## 支持的平台
## Supported platforms
**目前已实现了LinuxTencentOS tinyFreeRTOSRT-Thread平台(已做成软件包,名字为`kawaii-mqtt`),除此之外TencentOS tinyAT框架亦可以使用,并且稳定性极好!**
**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 框架 | [https://github.com/jiejieTop/gokit3-board-mqttclient](https://github.com/jiejieTop/gokit3-board-mqttclient) |
| 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] | 初次发布,完成基本框架及其稳定性验证 |
| [v1.0.1] | 修复主动与服务器断开连接时的逻辑处理 |
| [v1.0.2] | 添加新特性——拦截器,修复一些小bug |
| [v1.0.3] | 避免造成全局污染修改了log、list相关函数的命名 |
| [v1.0.4] | 重新调整了network结构与mbedtls数据通道 |
| [v1.1.0] | 一个较大版本的更新重构部分代码优化MQTT处理的逻辑提升整体的稳定性支持多客户端支持设置遗嘱优化API接口增加多个云平台的测试代码与说明文档增加在线代码生成工具、在线裁剪配置工具 |
| [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)
欢迎以 [GitHub Issues](https://github.com/jiejieTop/mqttclient/issues) 的形式提交问题和bug报告
## 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.
mqttclient 遵循 [Apache License v2.0](https://github.com/jiejieTop/mqttclient/blob/master/LICENSE) 开源协议。鼓励代码共享和尊重原作者的著作权,可以自由的使用、修改源代码,也可以将修改后的代码作为开源或闭源软件发布。
## Test and use under Linux platform
## linux平台下测试使用
### 安装cmake
### Install cmake:
```bash
sudo apt-get install cmake g++
```
### 测试程序
### test program
| 测试平台 | 位置 |
| -- | -- |
| emqx(我私人部署的服务器) | [./test/emqx/test.c](./test/emqx/test.c) |
| 百度天工 | [./test/baidu/test.c](./test/baidu/test.c) |
| 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) |
| 阿里云物联 | [./test/ali/test.c](./test/ali/test.c) |
| Alibaba Cloud Internet of Things | [./test/ali/test.c](./test/ali/test.c) |
### 编译 & 运行
### Compile & Run
```bash
./build.sh
```
运行**build.sh**脚本后会在 **./build/bin/**目录下生成可执行文件**emqx**、**baidu**、**onenet**等多个平台的可执行程序,直接运行即可。
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
```
### 编译成动态库libmqttclient.so
### Compile into a dynamic library libmqttclient.so
```bash
./make-libmqttclient.sh
```
运行`make-libmqttclient.sh`脚本后会在 `./libmqttclient/lib`目录下生成一个动态库文件`libmqttclient.so`,并安装到系统的`/usr/lib `目录下,相关头文件已经拷贝到`./libmqttclient/include`目录下,将其拷贝到你的工程中即可,编译应用程序的时候只需要链接动态库即可`-lmqttclient -lpthread`,动态库的配置文件是根据`./test/mqtt_config.h`配置的。
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.
如果你是用交叉编译器的话则应该根据你使用的编译器导出对应的环境变量此处使用的交叉编译器是arm-linux-gnueabihf-gcc同时你也必须将动态库文件`libmqttclient.so`拷贝到你的嵌入式系统的`/usr/lib `目录下:
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-
```
如若需要卸载**libmqttclient.so**,执行以下命令即可:
If you need to uninstall **libmqttclient.so**, execute the following command:
```bash
./make-libmqttclient.sh remove
```
## 学习更多
## Learn more
请看文档:
Please see the documentation:
- [MQTT协议简介](./docs/mqtt-introduction.md)
- [MQTT Protocol Introduction](./docs/mqtt-introduction.md)
- [MQTT协议通信过程](./docs/mqtt-communication.md)
- [MQTT protocol communication process](./docs/mqtt-communication.md)
- [mqttclient代码生成工具](./docs/mqtt-tool.md)
- [mqttclient code generation tool](./docs/mqtt-tool.md)
- [mqttclient配置及裁剪工具](./docs/mqtt-config.md)
- [mqttclient configuration and cutting tool](./docs/mqtt-config.md)
- [mqttclient设计与实现方式](./docs/mqtt-design.md)
- [mqttclient design and implementation](./docs/mqtt-design.md)
- [mqttclient连接到百度天工物接入](./docs/mqtt-baidu.md)
- [mqttclient connects to Baidu Tiangongwu Access](./docs/mqtt-baidu.md)
- [mqttclient连接到OneNET云平台](./docs/mqtt-onenet.md)
- [mqttclient connects to OneNET cloud platform](./docs/mqtt-onenet.md)
- [mqttclient连接到阿里云物联网平台](./docs/mqtt-aliyun.md)
- [mqttclient connects to Alibaba Cloud IoT platform](./docs/mqtt-aliyun.md)

View File

@@ -0,0 +1,211 @@
[![](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
**一个高性能、高稳定性的跨平台MQTT客户端**
一个高性能、高稳定性的跨平台MQTT客户端基于socket API之上开发可以在嵌入式设备FreeRTOS/LiteOS/RT-Thread/TencentOS tiny、Linux、Windows、Mac上使用拥有非常简洁的API接口以极少的资源实现QOS2的服务质量并且无缝衔接了mbedtls加密库。
## 优势:
- **具有极高的稳定性**:无论是**掉线重连****丢包重发**,都是**严格遵循MQTT协议标准**执行,除此之外对**大数据量**的测试无论是收是发,都是非常稳定,**高频**测试也是非常稳定。
- **轻量级**整个代码工程极其简单不使用mbedtls情况下占用资源极少作者曾使用esp8266模组与云端通信整个工程代码消耗的RAM不足15k。
- **支持mbedtls加密传输**让网络传输更加安全而且接口层完全不需要用户理会无论是否加密mqttclient对用户提供的API接口是**固定**的,这就很好的兼容了一套代应用层的码可以加密传输也可以不加密传输。
- **支持多客户端**,同时兼容多个客户端运行工作,一个设备连接多个的服务器。
- **支持同步异步处理**应用程序无需阻塞等待浪费CPU资源。
- **支持拦截器配置**,在某些平台中,客户端会默认自动订阅系统主题,而且每次来自服务器的主题都是变动的,此时需要使用拦截器进行拦截,分离主题与数据信息,并递交给用户,极大提高灵活性。
- **拥有在线代码生成工具**,极其简单配置就可以生成对应的代码,地址:[https://jiejietop.gitee.io/mqtt/index.html](https://jiejietop.gitee.io/mqtt/index.html)
- **拥有极简的API接口**总的来说mqttclient的配置都有默认值基本无需配置都能使用的也可以随意配置对配置都有健壮性检测这样子设计的API接口也是非常简单。
- **多功能参数可配置可裁剪**,重连时间间隔、心跳周期、最大订阅数量、命令超时、读写缓冲区大小、拦截器处理等等参数功能可裁剪可配置,满足开发者再复杂、简单等各种开发环境下的使用需求。
- **支持自动重新订阅主题**,在自动重连后保证主题不会丢失。
- **支持主题通配符`“#”、“+”`**。
- **订阅的主题与消息处理完全分离**,让编程逻辑更加简单易用,用户无需理会错综复杂的逻辑关系。
- **mqttclient内部已实现保活处理机制**,无需用户过多关心理会,用户只需专心处理应用功能即可。
- **拥有非常好的设计**,以极少的资源设计了**记录机制**当报文在丢失的时候进行重发操作确保qos1、qos2服务质量等级的报文保证其服务质量。
- **有非常好的代码风格与思想**:整个代码采用分层式设计,代码实现采用异步处理的思想,降低耦合,提高性能。
- **基于标准BSD socket之上开发**只要是兼容BSD socket的系统均可使用。
- **无缝衔接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 |
## 整体框架
拥有非常明确的分层框架。
![整体框架](png/mqttclient.png)
- 在框架的最上方是**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) |
| 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/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.1] | 修复主动与服务器断开连接时的逻辑处理 |
| [v1.0.2] | 添加新特性——拦截器修复一些小bug |
| [v1.0.3] | 避免造成全局污染修改了log、list相关函数的命名 |
| [v1.0.4] | 重新调整了network结构与mbedtls数据通道 |
| [v1.1.0] | 一个较大版本的更新重构部分代码优化MQTT处理的逻辑提升整体的稳定性支持多客户端支持设置遗嘱优化API接口增加多个云平台的测试代码与说明文档增加在线代码生成工具、在线裁剪配置工具 |
## 问题
欢迎以 [GitHub Issues](https://github.com/jiejieTop/mqttclient/issues) 的形式提交问题和bug报告
## 版权和许可
mqttclient 遵循 [Apache License v2.0](https://github.com/jiejieTop/mqttclient/blob/master/LICENSE) 开源协议。鼓励代码共享和尊重原作者的著作权,可以自由的使用、修改源代码,也可以将修改后的代码作为开源或闭源软件发布。
## linux平台下测试使用
### 安装cmake
```bash
sudo apt-get install cmake g++
```
### 测试程序
| 测试平台 | 位置 |
| -- | -- |
| emqx我私人部署的服务器 | [./test/emqx/test.c](./test/emqx/test.c) |
| 百度天工 | [./test/baidu/test.c](./test/baidu/test.c) |
| onenet | [./test/onenet/test.c](./test/onenet/test.c) |
| 阿里云物联 | [./test/ali/test.c](./test/ali/test.c) |
### 编译 & 运行
```bash
./build.sh
```
运行**build.sh**脚本后会在 **./build/bin/**目录下生成可执行文件**emqx**、**baidu**、**onenet**等多个平台的可执行程序,直接运行即可。
```bash
./build/bin/emqx
```
### 编译成动态库libmqttclient.so
```bash
./make-libmqttclient.sh
```
运行`make-libmqttclient.sh`脚本后会在 `./libmqttclient/lib`目录下生成一个动态库文件`libmqttclient.so`,并安装到系统的`/usr/lib `目录下,相关头文件已经拷贝到`./libmqttclient/include`目录下,将其拷贝到你的工程中即可,编译应用程序的时候只需要链接动态库即可`-lmqttclient -lpthread`,动态库的配置文件是根据`./test/mqtt_config.h`配置的。
如果你是用交叉编译器的话则应该根据你使用的编译器导出对应的环境变量此处使用的交叉编译器是arm-linux-gnueabihf-gcc同时你也必须将动态库文件`libmqttclient.so`拷贝到你的嵌入式系统的`/usr/lib `目录下:
```bash
export CROSS_COMPILE=arm-linux-gnueabihf-
```
如若需要卸载**libmqttclient.so**,执行以下命令即可:
```bash
./make-libmqttclient.sh remove
```
## 学习更多
请看文档:
- [MQTT协议简介](./docs/mqtt-introduction.md)
- [MQTT协议通信过程](./docs/mqtt-communication.md)
- [mqttclient代码生成工具](./docs/mqtt-tool.md)
- [mqttclient配置及裁剪工具](./docs/mqtt-config.md)
- [mqttclient设计与实现方式](./docs/mqtt-design.md)
- [mqttclient连接到百度天工物接入](./docs/mqtt-baidu.md)
- [mqttclient连接到OneNET云平台](./docs/mqtt-onenet.md)
- [mqttclient连接到阿里云物联网平台](./docs/mqtt-aliyun.md)

View File

@@ -1,209 +0,0 @@
[![](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,12 +2,16 @@
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-15 00:42:16
* @LastEditTime: 2020-04-27 23:35:05
* @LastEditTime: 2020-10-17 14:16:15
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#ifndef _MQTT_ERROR_H_
#define _MQTT_ERROR_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef enum mqtt_error {
MQTT_SSL_CERT_ERROR = -0x001C, /* cetr parse failed */
MQTT_SOCKET_FAILED_ERROR = -0x001B, /* socket fd failed */
@@ -42,4 +46,8 @@ typedef enum mqtt_error {
#define RETURN_ERROR(x) { return x; }
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -2,12 +2,16 @@
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-11 22:47:55
* @LastEditTime: 2020-04-27 23:25:37
* @LastEditTime: 2020-10-17 14:18:02
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#ifndef _MQTT_LIST_H_
#define _MQTT_LIST_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef struct mqtt_list_node {
struct mqtt_list_node *next;
struct mqtt_list_node *prev;
@@ -58,5 +62,9 @@ void mqtt_list_move(mqtt_list_t *node, mqtt_list_t *list);
void mqtt_list_move_tail(mqtt_list_t *node, mqtt_list_t *list);
int mqtt_list_is_empty(mqtt_list_t *list);
#ifdef __cplusplus
}
#endif
#endif /* _LIST_H_ */

View File

@@ -2,7 +2,7 @@
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-27 03:25:58
* @LastEditTime: 2020-06-17 20:28:18
* @LastEditTime: 2020-10-17 14:15:55
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#ifndef _MQTT_LOG_H_
@@ -10,6 +10,10 @@
#include "mqtt_defconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
#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)
@@ -60,4 +64,8 @@
#define mqtt_log_init()
#endif
#ifdef __cplusplus
}
#endif
#endif /* _LOG_H_ */

View File

@@ -2,17 +2,25 @@
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2020-01-09 19:59:19
* @LastEditTime : 2020-01-10 08:52:45
* @LastEditTime: 2020-10-17 14:18:15
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#ifndef _RANDOM_H_
#define _RANDOM_H_
#ifdef __cplusplus
extern "C" {
#endif
#define RANDOM_MAX 0x7FFFFFFF
int random_number(void);
int random_number_range(unsigned int min, unsigned int max);
char *random_string(unsigned int len);
#ifdef __cplusplus
}
#endif
#endif /* _RANDOM_H_ */

View File

@@ -2,7 +2,7 @@
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-09 21:31:25
* @LastEditTime: 2020-06-16 17:34:37
* @LastEditTime: 2021-01-14 10:00:12
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#include "mqttclient.h"
@@ -154,7 +154,6 @@ static int mqtt_read_packet(mqtt_client_t* c, int* packet_type, platform_timer_t
if (NULL == packet_type)
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
platform_timer_init(timer);
platform_timer_cutdown(timer, c->mqtt_cmd_timeout);
/* 1. read the header byte. This has the packet type in it */
@@ -193,7 +192,6 @@ static int mqtt_send_packet(mqtt_client_t* c, int length, platform_timer_t* time
int len = 0;
int sent = 0;
platform_timer_init(timer);
platform_timer_cutdown(timer, c->mqtt_cmd_timeout);
/* send mqtt packet in a blocking manner or exit when it timer is expired */
@@ -304,7 +302,7 @@ static int mqtt_deliver_message(mqtt_client_t* c, MQTTString* topic_name, mqtt_m
rc = MQTT_SUCCESS_ERROR;
}
memset(message->payload, 0, strlen(message->payload));
memset(message->payload, 0, strlen((const char *)message->payload));
memset(topic_name->lenstring.data, 0, topic_name->lenstring.len);
RETURN_ERROR(rc);
@@ -319,7 +317,7 @@ static ack_handlers_t *mqtt_ack_handler_create(mqtt_client_t* c, int type, uint1
return NULL;
mqtt_list_init(&ack_handler->list);
platform_timer_init(&ack_handler->timer);
platform_timer_cutdown(&ack_handler->timer, c->mqtt_cmd_timeout); /* No response within timeout will be destroyed or resent */
ack_handler->type = type;
@@ -343,7 +341,7 @@ static void mqtt_ack_handler_destroy(ack_handlers_t* ack_handler)
static void mqtt_ack_handler_resend(mqtt_client_t* c, ack_handlers_t* ack_handler)
{
platform_timer_t timer;
platform_timer_init(&timer);
platform_timer_cutdown(&timer, c->mqtt_cmd_timeout);
platform_timer_cutdown(&ack_handler->timer, c->mqtt_cmd_timeout); /* timeout, recutdown */
@@ -351,8 +349,9 @@ static void mqtt_ack_handler_resend(mqtt_client_t* c, ack_handlers_t* ack_handle
memcpy(c->mqtt_write_buf, ack_handler->payload, ack_handler->payload_len); /* copy data to write buf form ack handler */
mqtt_send_packet(c, ack_handler->payload_len, &timer); /* resend data */
MQTT_LOG_W("%s:%d %s()... resend %d package, packet_id is %d ", __FILE__, __LINE__, __FUNCTION__, ack_handler->type, ack_handler->packet_id);
platform_mutex_unlock(&c->mqtt_write_lock);
MQTT_LOG_W("%s:%d %s()... resend %d package, packet_id is %d ", __FILE__, __LINE__, __FUNCTION__, ack_handler->type, ack_handler->packet_id);
}
static int mqtt_ack_list_node_is_exist(mqtt_client_t* c, int type, uint16_t packet_id)
@@ -495,15 +494,24 @@ static void mqtt_clean_session(mqtt_client_t* c)
if (!(mqtt_list_is_empty(&c->mqtt_ack_handler_list))) {
LIST_FOR_EACH_SAFE(curr, next, &c->mqtt_ack_handler_list) {
ack_handler = LIST_ENTRY(curr, ack_handlers_t, list);
mqtt_list_del(&ack_handler->list);
//@lchnu, 2020-10-08, avoid socket disconnet when waiting for suback/unsuback....
if(NULL != ack_handler->handler) {
mqtt_msg_handler_destory(ack_handler->handler);
ack_handler->handler = NULL;
}
platform_memory_free(ack_handler);
}
mqtt_list_del_init(&c->mqtt_ack_handler_list);
}
/* need clean mqtt_ack_handler_number value, find the bug by @lchnu */
c->mqtt_ack_handler_number = 0;
/* release all msg_handler_list memory */
if (!(mqtt_list_is_empty(&c->mqtt_msg_handler_list))) {
LIST_FOR_EACH_SAFE(curr, next, &c->mqtt_msg_handler_list) {
msg_handler = LIST_ENTRY(curr, message_handlers_t, list);
mqtt_list_del(&msg_handler->list);
msg_handler->topic_filter = NULL;
platform_memory_free(msg_handler);
}
@@ -538,9 +546,17 @@ static void mqtt_ack_list_scan(mqtt_client_t* c, uint8_t flag)
/* timeout has occurred. for qos1 and qos2 packets, you need to resend them. */
mqtt_ack_handler_resend(c, ack_handler);
continue;
} else if ((ack_handler->type == SUBACK) || (ack_handler->type == UNSUBACK)) {
/*@lchnu, 2020-10-08, destory handler memory, if suback/unsuback is overdue!*/
if (NULL != ack_handler->handler) {
mqtt_msg_handler_destory(ack_handler->handler);
ack_handler->handler = NULL;
}
}
/* if it is not a qos1 or qos2 message, it will be destroyed in every processing */
mqtt_ack_handler_destroy(ack_handler);
mqtt_subtract_ack_handler_num(c); /*@lchnu, 2020-10-08 */
}
}
@@ -589,12 +605,16 @@ static int mqtt_try_reconnect(mqtt_client_t* c)
{
int rc = MQTT_SUCCESS_ERROR;
/*before connect, call reconnect handler, it can used to update the mqtt password, eg: onenet platform need*/
if (NULL != c->mqtt_reconnect_handler) {
c->mqtt_reconnect_handler(c, c->mqtt_reconnect_data);
}
rc = mqtt_try_do_reconnect(c);
if ((MQTT_SUCCESS_ERROR != rc) && (platform_timer_is_expired(&c->mqtt_reconnect_timer))) {
platform_timer_cutdown(&c->mqtt_reconnect_timer, c->mqtt_reconnect_try_duration);
if (NULL != c->mqtt_reconnect_handler)
c->mqtt_reconnect_handler(c, c->mqtt_reconnect_data);
if(MQTT_SUCCESS_ERROR != rc) {
/*connect fail must delay reconnect try duration time and let cpu time go out, the lowest priority task can run */
mqtt_sleep_ms(c->mqtt_reconnect_try_duration);
RETURN_ERROR(MQTT_RECONNECT_TIMEOUT_ERROR);
}
@@ -606,8 +626,6 @@ static int mqtt_publish_ack_packet(mqtt_client_t *c, uint16_t packet_id, int pac
int len = 0;
int rc = MQTT_SUCCESS_ERROR;
platform_timer_t timer;
platform_timer_init(&timer);
platform_timer_cutdown(&timer, c->mqtt_cmd_timeout);
platform_mutex_lock(&c->mqtt_write_lock);
@@ -796,7 +814,11 @@ static int mqtt_packet_handle(mqtt_client_t* c, platform_timer_t* timer)
rc = mqtt_read_packet(c, &packet_type, timer);
switch (packet_type) {
case 0: /* timed out reading packet */
case 0: /* timed out reading packet or an error occurred while reading data*/
if (MQTT_BUFFER_TOO_SHORT_ERROR == rc) {
MQTT_LOG_E("the client read buffer is too short, please call mqtt_set_read_buf_size() to reset the buffer size");
/* don't return directly, you need to stay active, because there is data readable now, but the buffer is too small */
}
break;
case CONNACK: /* has been processed */
@@ -829,7 +851,7 @@ static int mqtt_packet_handle(mqtt_client_t* c, platform_timer_t* timer)
break;
default:
goto exit;
break;
}
rc = mqtt_keep_alive(c);
@@ -866,7 +888,7 @@ static int mqtt_yield(mqtt_client_t* c, int timeout_ms)
if (0 == timeout_ms)
timeout_ms = c->mqtt_cmd_timeout;
platform_timer_init(&timer);
platform_timer_cutdown(&timer, timeout_ms);
while (!platform_timer_is_expired(&timer)) {
@@ -891,9 +913,6 @@ static int mqtt_yield(mqtt_client_t* c, int timeout_ms)
} else if (MQTT_NOT_CONNECT_ERROR == rc) {
MQTT_LOG_E("%s:%d %s()... mqtt not connect", __FILE__, __LINE__, __FUNCTION__);
/* reconnect timer cutdown */
platform_timer_cutdown(&c->mqtt_reconnect_timer, c->mqtt_reconnect_try_duration);
} else {
break;
}
@@ -907,6 +926,7 @@ static void mqtt_yield_thread(void *arg)
int rc;
client_state_t state;
mqtt_client_t *c = (mqtt_client_t *)arg;
platform_thread_t *thread_to_be_destoried = NULL;
state = mqtt_get_client_state(c);
if (CLIENT_STATE_CONNECTED != state) {
@@ -917,17 +937,19 @@ static void mqtt_yield_thread(void *arg)
while (1) {
rc = mqtt_yield(c, c->mqtt_cmd_timeout);
if (MQTT_CLEAN_SESSION_ERROR == rc) {
MQTT_LOG_E("%s:%d %s()..., mqtt clean session....", __FILE__, __LINE__, __FUNCTION__);
MQTT_LOG_W("%s:%d %s()..., mqtt clean session....", __FILE__, __LINE__, __FUNCTION__);
network_disconnect(c->mqtt_network);
mqtt_clean_session(c);
goto exit;
} else if (MQTT_RECONNECT_TIMEOUT_ERROR == rc) {
MQTT_LOG_E("%s:%d %s()..., mqtt reconnect timeout....", __FILE__, __LINE__, __FUNCTION__);
MQTT_LOG_W("%s:%d %s()..., mqtt reconnect timeout....", __FILE__, __LINE__, __FUNCTION__);
}
}
exit:
platform_thread_destroy(c->mqtt_thread);
thread_to_be_destoried = c->mqtt_thread;
c->mqtt_thread = (platform_thread_t *)0;
platform_thread_destroy(thread_to_be_destoried);
}
static int mqtt_connect_with_results(mqtt_client_t* c)
@@ -944,18 +966,7 @@ static int mqtt_connect_with_results(mqtt_client_t* c)
if (CLIENT_STATE_CONNECTED == mqtt_get_client_state(c))
RETURN_ERROR(MQTT_SUCCESS_ERROR);
if ((MQTT_MIN_PAYLOAD_SIZE >= c->mqtt_read_buf_size) || (MQTT_MAX_PAYLOAD_SIZE <= c->mqtt_read_buf_size))
c->mqtt_read_buf_size = MQTT_DEFAULT_BUF_SIZE;
if ((MQTT_MIN_PAYLOAD_SIZE >= c->mqtt_write_buf_size) || (MQTT_MAX_PAYLOAD_SIZE <= c->mqtt_write_buf_size))
c->mqtt_write_buf_size = MQTT_DEFAULT_BUF_SIZE;
c->mqtt_read_buf = (uint8_t*) platform_memory_alloc(c->mqtt_write_buf_size);
c->mqtt_write_buf = (uint8_t*) platform_memory_alloc(c->mqtt_write_buf_size);
if ((NULL == c->mqtt_read_buf) || (NULL == c->mqtt_write_buf)) {
MQTT_LOG_E("%s:%d %s()... malloc buf failed...", __FILE__, __LINE__, __FUNCTION__);
RETURN_ERROR(MQTT_MEM_NOT_ENOUGH_ERROR);
}
#ifndef MQTT_NETWORK_TYPE_NO_TLS
rc = network_init(c->mqtt_network, c->mqtt_host, c->mqtt_port, c->mqtt_ca);
@@ -967,8 +978,6 @@ static int mqtt_connect_with_results(mqtt_client_t* c)
if (MQTT_SUCCESS_ERROR != rc) {
if (NULL != c->mqtt_network) {
network_release(c->mqtt_network);
platform_memory_free(c->mqtt_network);
c->mqtt_network = NULL;
RETURN_ERROR(rc);
}
}
@@ -998,7 +1007,6 @@ static int mqtt_connect_with_results(mqtt_client_t* c)
if ((len = MQTTSerialize_connect(c->mqtt_write_buf, c->mqtt_write_buf_size, &connect_data)) <= 0)
goto exit;
platform_timer_init(&connect_timer);
platform_timer_cutdown(&connect_timer, c->mqtt_cmd_timeout);
/* send connect packet */
@@ -1024,6 +1032,11 @@ exit:
mqtt_set_client_state(c, CLIENT_STATE_CONNECTED);
platform_thread_startup(c->mqtt_thread);
platform_thread_start(c->mqtt_thread); /* start run mqtt thread */
} else {
/*creat the thread fail and disconnect the mqtt socket connect*/
network_release(c->mqtt_network);
rc = MQTT_CONNECT_FAILED_ERROR;
MQTT_LOG_W("%s:%d %s()... mqtt yield thread creat faile...", __FILE__, __LINE__, __FUNCTION__);
}
} else {
mqtt_set_client_state(c, CLIENT_STATE_CONNECTED); /* reconnect, mqtt thread is already exists */
@@ -1032,6 +1045,7 @@ exit:
c->mqtt_ping_outstanding = 0; /* reset ping outstanding */
} else {
network_release(c->mqtt_network);
mqtt_set_client_state(c, CLIENT_STATE_INITIALIZED); /* connect failed */
}
@@ -1040,6 +1054,50 @@ exit:
RETURN_ERROR(rc);
}
static uint32_t mqtt_read_buf_malloc(mqtt_client_t* c, uint32_t size)
{
MQTT_ROBUSTNESS_CHECK(c, 0);
if (NULL != c->mqtt_read_buf)
platform_memory_free(c->mqtt_read_buf);
c->mqtt_read_buf_size = size;
/* limit the size of the read buffer */
if ((MQTT_MIN_PAYLOAD_SIZE >= c->mqtt_read_buf_size) || (MQTT_MAX_PAYLOAD_SIZE <= c->mqtt_read_buf_size))
c->mqtt_read_buf_size = MQTT_DEFAULT_BUF_SIZE;
c->mqtt_read_buf = (uint8_t*) platform_memory_alloc(c->mqtt_read_buf_size);
if (NULL == c->mqtt_read_buf) {
MQTT_LOG_E("%s:%d %s()... malloc read buf failed...", __FILE__, __LINE__, __FUNCTION__);
RETURN_ERROR(MQTT_MEM_NOT_ENOUGH_ERROR);
}
return c->mqtt_read_buf_size;
}
static uint32_t mqtt_write_buf_malloc(mqtt_client_t* c, uint32_t size)
{
MQTT_ROBUSTNESS_CHECK(c, 0);
if (NULL != c->mqtt_write_buf)
platform_memory_free(c->mqtt_write_buf);
c->mqtt_write_buf_size = size;
/* limit the size of the read buffer */
if ((MQTT_MIN_PAYLOAD_SIZE >= c->mqtt_write_buf_size) || (MQTT_MAX_PAYLOAD_SIZE <= c->mqtt_write_buf_size))
c->mqtt_write_buf_size = MQTT_DEFAULT_BUF_SIZE;
c->mqtt_write_buf = (uint8_t*) platform_memory_alloc(c->mqtt_write_buf_size);
if (NULL == c->mqtt_write_buf) {
MQTT_LOG_E("%s:%d %s()... malloc write buf failed...", __FILE__, __LINE__, __FUNCTION__);
RETURN_ERROR(MQTT_MEM_NOT_ENOUGH_ERROR);
}
return c->mqtt_write_buf_size;
}
static int mqtt_init(mqtt_client_t* c)
{
/* network init */
@@ -1071,13 +1129,15 @@ static int mqtt_init(mqtt_client_t* c)
c->mqtt_reconnect_handler = NULL;
c->mqtt_interceptor_handler = NULL;
mqtt_read_buf_malloc(c, MQTT_DEFAULT_BUF_SIZE);
mqtt_write_buf_malloc(c, MQTT_DEFAULT_BUF_SIZE);
mqtt_list_init(&c->mqtt_msg_handler_list);
mqtt_list_init(&c->mqtt_ack_handler_list);
platform_mutex_init(&c->mqtt_write_lock);
platform_mutex_init(&c->mqtt_global_lock);
platform_timer_init(&c->mqtt_reconnect_timer);
platform_timer_init(&c->mqtt_last_sent);
platform_timer_init(&c->mqtt_last_received);
@@ -1098,12 +1158,20 @@ 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)
uint32_t mqtt_set_read_buf_size(mqtt_client_t *c, uint32_t size)
{
return mqtt_read_buf_malloc(c, size);
}
uint32_t mqtt_set_write_buf_size(mqtt_client_t *c, uint32_t size)
{
return mqtt_write_buf_malloc(c, size);
}
void mqtt_sleep_ms(int ms)
{
platform_timer_usleep(ms * 1000);
@@ -1120,6 +1188,9 @@ int mqtt_keep_alive(mqtt_client_t* c)
if (platform_timer_is_expired(&c->mqtt_last_sent) || platform_timer_is_expired(&c->mqtt_last_received)) {
if (c->mqtt_ping_outstanding) {
MQTT_LOG_W("%s:%d %s()... ping outstanding", __FILE__, __LINE__, __FUNCTION__);
/*must realse the socket file descriptor zhaoshimin 20200629*/
network_release(c->mqtt_network);
mqtt_set_client_state(c, CLIENT_STATE_DISCONNECTED);
rc = MQTT_NOT_CONNECT_ERROR; /* PINGRESP not received in keepalive interval */
} else {
@@ -1158,7 +1229,7 @@ int mqtt_release(mqtt_client_t* c)
if (NULL == c)
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
platform_timer_init(&timer);
platform_timer_cutdown(&timer, c->mqtt_cmd_timeout);
/* wait for the clean session to complete */
@@ -1185,6 +1256,9 @@ int mqtt_release(mqtt_client_t* c)
c->mqtt_write_buf = NULL;
}
platform_mutex_destroy(&c->mqtt_write_lock);
platform_mutex_destroy(&c->mqtt_global_lock);
memset(c, 0, sizeof(mqtt_client_t));
RETURN_ERROR(MQTT_SUCCESS_ERROR);
@@ -1202,7 +1276,7 @@ int mqtt_disconnect(mqtt_client_t* c)
platform_timer_t timer;
int len = 0;
platform_timer_init(&timer);
platform_timer_cutdown(&timer, c->mqtt_cmd_timeout);
platform_mutex_lock(&c->mqtt_write_lock);
@@ -1232,10 +1306,10 @@ int mqtt_subscribe(mqtt_client_t* c, const char* topic_filter, mqtt_qos_t qos, m
if (CLIENT_STATE_CONNECTED != mqtt_get_client_state(c))
RETURN_ERROR(MQTT_NOT_CONNECT_ERROR);
platform_mutex_lock(&c->mqtt_write_lock);
packet_id = mqtt_get_next_packet_id(c);
platform_mutex_lock(&c->mqtt_write_lock);
/* serialize subscribe packet and send it */
len = MQTTSerialize_subscribe(c->mqtt_write_buf, c->mqtt_write_buf_size, 0, packet_id, 1, &topic, (int*)&qos);
if (len <= 0)
@@ -1249,8 +1323,10 @@ int mqtt_subscribe(mqtt_client_t* c, const char* topic_filter, mqtt_qos_t qos, m
/* create a message and record it */
msg_handler = mqtt_msg_handler_create(topic_filter, qos, handler);
if (NULL == msg_handler)
RETURN_ERROR(MQTT_MEM_NOT_ENOUGH_ERROR);
if (NULL == msg_handler) {
rc = MQTT_MEM_NOT_ENOUGH_ERROR;
goto exit;
}
rc = mqtt_ack_list_record(c, SUBACK, packet_id, len, msg_handler);
@@ -1274,20 +1350,22 @@ int mqtt_unsubscribe(mqtt_client_t* c, const char* topic_filter)
if (CLIENT_STATE_CONNECTED != mqtt_get_client_state(c))
RETURN_ERROR(MQTT_NOT_CONNECT_ERROR);
platform_mutex_lock(&c->mqtt_write_lock);
packet_id = mqtt_get_next_packet_id(c);
platform_mutex_lock(&c->mqtt_write_lock);
/* serialize unsubscribe packet and send it */
if ((len = MQTTSerialize_unsubscribe(c->mqtt_write_buf, c->mqtt_write_buf_size, 0, packet_id, 1, &topic)) <= 0)
goto exit;
if ((rc = mqtt_send_packet(c, len, &timer)) != MQTT_SUCCESS_ERROR)
goto exit;
/* create a message and record it */
msg_handler = mqtt_msg_handler_create((const char*)topic_filter, QOS0, NULL);
if (NULL == msg_handler)
RETURN_ERROR(MQTT_MEM_NOT_ENOUGH_ERROR);
/* get a already subscribed message handler */
msg_handler = mqtt_get_msg_handler(c, &topic);
if (NULL == msg_handler) {
rc = MQTT_MEM_NOT_ENOUGH_ERROR;
goto exit;
}
rc = mqtt_ack_list_record(c, UNSUBACK, packet_id, len, msg_handler);
@@ -1314,6 +1392,11 @@ int mqtt_publish(mqtt_client_t* c, const char* topic_filter, mqtt_message_t* msg
if ((NULL != msg->payload) && (0 == msg->payloadlen))
msg->payloadlen = strlen((char*)msg->payload);
if (msg->payloadlen > c->mqtt_write_buf_size) {
MQTT_LOG_E("publish payload len is is greater than client write buffer...");
RETURN_ERROR(MQTT_BUFFER_TOO_SHORT_ERROR);
}
platform_mutex_lock(&c->mqtt_write_lock);
if (QOS0 != msg->qos) {
@@ -1334,7 +1417,7 @@ int mqtt_publish(mqtt_client_t* c, const char* topic_filter, mqtt_message_t* msg
goto exit;
if (QOS0 != msg->qos) {
mqtt_set_publish_dup(c,1); /* may resend this data, set the udp flag in advance */
mqtt_set_publish_dup(c,1); /* may resend this data, set the dup flag in advance */
if (QOS1 == msg->qos) {
/* expect to receive PUBACK, otherwise data will be resent */
@@ -1354,6 +1437,9 @@ exit:
if ((MQTT_ACK_HANDLER_NUM_TOO_MUCH_ERROR == rc) || (MQTT_MEM_NOT_ENOUGH_ERROR == rc)) {
MQTT_LOG_W("%s:%d %s()... there is not enough memory space to record...", __FILE__, __LINE__, __FUNCTION__);
/*must realse the socket file descriptor zhaoshimin 20200629*/
network_release(c->mqtt_network);
/* record too much retransmitted data, may be disconnected, need to reconnect */
mqtt_set_client_state(c, CLIENT_STATE_DISCONNECTED);
}
@@ -1391,7 +1477,7 @@ int mqtt_set_will_options(mqtt_client_t* c, char *topic, mqtt_qos_t qos, uint8_t
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
if (NULL == c->mqtt_will_options) {
c->mqtt_will_options = platform_memory_alloc(sizeof(mqtt_will_options_t));
c->mqtt_will_options = (mqtt_will_options_t *)platform_memory_alloc(sizeof(mqtt_will_options_t));
MQTT_ROBUSTNESS_CHECK(c->mqtt_will_options, MQTT_MEM_NOT_ENOUGH_ERROR);
}

View File

@@ -2,7 +2,7 @@
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-09 21:31:25
* @LastEditTime: 2020-06-16 16:57:40
* @LastEditTime: 2020-10-17 14:16:58
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#ifndef _MQTTCLIENT_H_
@@ -24,6 +24,10 @@
#include "mqtt_error.h"
#include "mqtt_log.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum mqtt_qos {
QOS0 = 0,
QOS1 = 1,
@@ -118,7 +122,6 @@ typedef struct mqtt_client {
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;
@@ -170,4 +173,8 @@ 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_set_will_options(mqtt_client_t* c, char *topic, mqtt_qos_t qos, uint8_t retained, char *message);
#ifdef __cplusplus
}
#endif
#endif /* _MQTTCLIENT_H_ */

View File

@@ -2,7 +2,7 @@
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-15 13:39:00
* @LastEditTime: 2020-05-24 15:49:46
* @LastEditTime: 2020-10-17 14:17:10
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#ifndef _NETTYPE_TCP_H_
@@ -12,9 +12,17 @@
#include "network.h"
#include "mqtt_error.h"
#ifdef __cplusplus
extern "C" {
#endif
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);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -2,7 +2,7 @@
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2020-01-11 19:45:35
* @LastEditTime: 2020-05-24 17:03:47
* @LastEditTime: 2020-09-20 14:29:06
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#include "nettype_tls.h"
@@ -207,7 +207,6 @@ int nettype_tls_write(network_t *n, unsigned char *buf, int len, int timeout)
nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->nettype_tls_params;
platform_timer_init(&timer);
platform_timer_cutdown(&timer, timeout);
do {
@@ -235,7 +234,6 @@ int nettype_tls_read(network_t *n, unsigned char *buf, int len, int timeout)
nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->nettype_tls_params;
platform_timer_init(&timer);
platform_timer_cutdown(&timer, timeout);
do {

View File

@@ -2,7 +2,7 @@
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2020-01-11 19:45:44
* @LastEditTime: 2020-05-24 17:03:13
* @LastEditTime: 2020-10-17 14:14:11
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
@@ -16,6 +16,10 @@
#ifndef MQTT_NETWORK_TYPE_NO_TLS
#ifdef __cplusplus
extern "C" {
#endif
typedef struct nettype_tls_params {
mbedtls_net_context socket_fd; /**< mbed TLS network context. */
mbedtls_entropy_context entropy; /**< mbed TLS entropy. */
@@ -36,4 +40,8 @@ void nettype_tls_disconnect(network_t* n);
#endif /* MQTT_NETWORK_TYPE_NO_TLS */
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -2,7 +2,7 @@
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-09 21:31:02
* @LastEditTime: 2020-05-21 01:09:29
* @LastEditTime: 2020-10-17 14:14:41
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#ifndef _NETWORK_H_
@@ -10,6 +10,10 @@
#include "mqtt_defconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
#define NETWORK_CHANNEL_TCP 0
#define NETWORK_CHANNEL_TLS 1
@@ -36,4 +40,8 @@ int network_connect(network_t* n);
void network_disconnect(network_t *n);
void network_release(network_t* n);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -2,7 +2,7 @@
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2020-01-10 23:45:59
* @LastEditTime: 2020-04-25 17:54:44
* @LastEditTime: 2020-06-18 20:13:02
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#include "platform_net_socket.h"

View File

@@ -2,7 +2,7 @@
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-15 13:39:00
* @LastEditTime: 2020-04-27 23:46:35
* @LastEditTime: 2020-06-18 20:12:15
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
*/
#ifndef _PLATFORM_NET_SOCKET_H_

View File

@@ -1,100 +0,0 @@
/*
* @Author: jiejie
* @Github: https://github.com/jiejieTop
* @Date: 2019-12-11 21:53:07
* @LastEditTime: 2020-04-23 15:03:32
* @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();
mqtt_client_t client;
client_init_params_t init_params;
static void topic1_handler(void* client, message_data_t* msg)
{
(void) client;
LOG_I("-----------------------------------------------------------------------------------");
LOG_I("%s:%d %s()...\ntopic: %s\nmessage:%s", __FILE__, __LINE__, __FUNCTION__, msg->topic_name, (char*)msg->message->payload);
LOG_I("-----------------------------------------------------------------------------------");
}
void *mqtt_publish_thread(void *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;
pthread_t thread2;
printf("\nwelcome to mqttclient test...\n");
log_init();
init_params.read_buf_size = 1024;
init_params.write_buf_size = 1024;
#ifdef MQTT_NETWORK_TYPE_TLS
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";
init_params.connect_params.password = random_string(10); //random_string(10); // "123456";
init_params.connect_params.client_id = random_string(10); //random_string(10); // "clientid-acer1";
init_params.connect_params.clean_session = 1;
mqtt_init(&client, &init_params);
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(&thread2, NULL, mqtt_publish_thread, NULL);
if(res != 0) {
LOG_E("create mqtt publish thread fail");
exit(res);
}
while (1) {
sleep(100);
}
}

View File

@@ -1,75 +0,0 @@
/*
* @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;
}