目录
1. MQTT 协议简介
2. 移植MQTT 协议
3. cJSON 移植
4. 例程
MQTT 协议全称是Message Queuing Telemetry Transport,翻译过来就是消息队列遥测传输协议,它是物联网常用的应用层协议,运行在TCP/IP 中的应用层中,依赖TCP 协议,因此它具有非常高的可靠性,同时它是基于TCP 协议的<客户端-服务器>模型发布/订阅主题消息的轻量级协议。
MQTT 3.1 协议:
官方: http://mqtt.org/documentation
个人整理:https://blog.csdn.net/XieWinter/article/details/101198750
因为MQTT 是应用层协议,基于TCP 协议至少,首先我们就需要把LwIP 协议跑通,我们就使用Socket API 来进行移植。
首先下载MQTT 的源码库:
GitHub 相关链接:
https://github.com/mqtt/mqtt.github.io/wiki
进入libraries 页面会发现,有多种语言的支持,选择所需要的C库,下载
源码下载链接:https://github.com/eclipse/paho.mqtt.embedded-c
下载的压缩包,并解压。
创建 一个MQTT的文件夹,将MQTTPacket\src 目录下的文件添加到工程目录MQTT 文件夹,再将MQTTPacket\samples 目录下的transport.c、transport.h 添加到这个文件夹下,添加完成后文件夹内容如下:
把MQTT 添加到工程,然后实现transport.c 文件的移植层接口。
#include "transport.h"
#include "lwip/opt.h"
#include "lwip/arch.h"
#include "lwip/api.h"
#include "lwip/inet.h"
#include "lwip/sockets.h"
#include "string.h"
static int mysock;
/************************************************************************
** 函数名称: transport_sendPacketBuffer
** 函数功能: 以TCP方式发送数据
** 入口参数: unsigned char* buf:数据缓冲区
** int buflen:数据长度
** 出口参数: <0发送数据失败
************************************************************************/
int32_t transport_sendPacketBuffer( uint8_t* buf, int32_t buflen)
{
int32_t rc;
rc = write(mysock, buf, buflen);
return rc;
}
/************************************************************************
** 函数名称: transport_getdata
** 函数功能: 以阻塞的方式接收TCP数据
** 入口参数: unsigned char* buf:数据缓冲区
** int count:数据长度
** 出口参数: <=0接收数据失败
************************************************************************/
int32_t transport_getdata(uint8_t* buf, int32_t count)
{
int32_t rc;
//这个函数在这里不阻塞
rc = recv(mysock, buf, count, 0);
return rc;
}
/************************************************************************
** 函数名称: transport_open
** 函数功能: 打开一个接口,并且和服务器 建立连接
** 入口参数: char* servip:服务器域名
** int port:端口号
** 出口参数: <0打开连接失败
************************************************************************/
int32_t transport_open(int8_t* servip, int32_t port)
{
int32_t *sock = &mysock;
int32_t ret;
// int32_t opt;
struct sockaddr_in addr;
//初始换服务器信息
memset(&addr,0,sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
//填写服务器端口号
addr.sin_port = PP_HTONS(port);
//填写服务器IP地址
addr.sin_addr.s_addr = inet_addr((const char*)servip);
//创建SOCK
*sock = socket(AF_INET,SOCK_STREAM,0);
//连接服务器
ret = connect(*sock,(struct sockaddr*)&addr,sizeof(addr));
if(ret != 0)
{
//关闭链接
close(*sock);
//连接失败
return -1;
}
//连接成功,设置超时时间1000ms
// opt = 1000;
// setsockopt(*sock,SOL_SOCKET,SO_RCVTIMEO,&opt,sizeof(int));
//返回套接字
return *sock;
}
/************************************************************************
** 函数名称: transport_close
** 函数功能: 关闭套接字
** 入口参数: unsigned char* buf:数据缓冲区
** int buflen:数据长度
** 出口参数: <0发送数据失败
************************************************************************/
int transport_close(void)
{
int rc;
// rc = close(mysock);
rc = shutdown(mysock, SHUT_WR);
rc = recv(mysock, NULL, (size_t)0, 0);
rc = close(mysock);
return rc;
}
#ifndef __TRANSPORT_H
#define __TRANSPORT_H
#include "stm32f4xx.h"
#include "main.h"
/************************************************************************
** 函数名称: transport_sendPacketBuffer
** 函数功能: 以TCP方式发送数据
** 入口参数: unsigned char* buf:数据缓冲区
** int buflen:数据长度
** 出口参数: <0发送数据失败
************************************************************************/
int32_t transport_sendPacketBuffer( uint8_t* buf, int32_t buflen);
/************************************************************************
** 函数名称: transport_getdata
** 函数功能: 以阻塞的方式接收TCP数据
** 入口参数: unsigned char* buf:数据缓冲区
** int count:数据长度
** 出口参数: <=0接收数据失败
************************************************************************/
int32_t transport_getdata(uint8_t* buf, int32_t count);
/************************************************************************
** 函数名称: transport_open
** 函数功能: 打开一个接口,并且和服务器 建立连接
** 入口参数: char* servip:服务器域名
** int port:端口号
** 出口参数: <0打开连接失败
************************************************************************/
int32_t transport_open(int8_t* servip, int32_t port);
/************************************************************************
** 函数名称: transport_close
** 函数功能: 关闭套接字
** 入口参数: unsigned char* buf:数据缓冲区
** int buflen:数据长度
** 出口参数: <0发送数据失败
************************************************************************/
int32_t transport_close(void);
#endif
见:https://blog.csdn.net/XieWinter/article/details/101049395
实现定时推送信息,手上没有DHT11 , 直接模拟一个动态数据。通过MQTT FX 发布消息,接收订阅解析。