lwIP TCP/IP 协议栈笔记之二十: MQTT 移植

目录

1. MQTT 协议简介

2. 移植MQTT 协议

3. cJSON 移植

4. 例程


1. MQTT 协议简介

MQTT 协议全称是Message Queuing Telemetry Transport,翻译过来就是消息队列遥测传输协议,它是物联网常用的应用层协议,运行在TCP/IP 中的应用层中,依赖TCP 协议,因此它具有非常高的可靠性,同时它是基于TCP 协议的<客户端-服务器>模型发布/订阅主题消息的轻量级协议。

MQTT 3.1 协议:

官方: http://mqtt.org/documentation

个人整理:https://blog.csdn.net/XieWinter/article/details/101198750

2. 移植MQTT 协议

因为MQTT 是应用层协议,基于TCP 协议至少,首先我们就需要把LwIP 协议跑通,我们就使用Socket API 来进行移植。

首先下载MQTT 的源码库:

GitHub 相关链接:

https://github.com/mqtt/mqtt.github.io/wiki

lwIP TCP/IP 协议栈笔记之二十: MQTT 移植_第1张图片

进入libraries 页面会发现,有多种语言的支持,选择所需要的C库,下载

lwIP TCP/IP 协议栈笔记之二十: MQTT 移植_第2张图片

源码下载链接:https://github.com/eclipse/paho.mqtt.embedded-c

下载的压缩包,并解压。

lwIP TCP/IP 协议栈笔记之二十: MQTT 移植_第3张图片

lwIP TCP/IP 协议栈笔记之二十: MQTT 移植_第4张图片

创建 一个MQTT的文件夹,将MQTTPacket\src 目录下的文件添加到工程目录MQTT 文件夹,再将MQTTPacket\samples 目录下的transport.c、transport.h 添加到这个文件夹下,添加完成后文件夹内容如下:

lwIP TCP/IP 协议栈笔记之二十: MQTT 移植_第5张图片

把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

3. cJSON 移植

见:https://blog.csdn.net/XieWinter/article/details/101049395

4. 例程

实现定时推送信息,手上没有DHT11 , 直接模拟一个动态数据。通过MQTT FX 发布消息,接收订阅解析。

 

 

你可能感兴趣的:(嵌入式开发,TCP/IP,LWIP)