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

進入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

3. cJSON 移植

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

4. 例程

實現定時推送信息,手上沒有DHT11 , 直接模擬一個動態數據。通過MQTT FX 發佈消息,接收訂閱解析。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章