WIFI模块不支持MQTT协议,可通过MCU实现

文章介绍了如何在不支持MQTT协议的WIFI模块上通过MCU代码实现MQTT协议,利用TCP连接和已有的底层函数。MQTT是一种轻量级的消息传输协议,常用于物联网和M2M通信。示例代码包括连接、发布/订阅等功能。
摘要由CSDN通过智能技术生成

1.话题原因

我们使用某款WIFI模块,在物联网开发时,平台端的开发者想要使用MQTT协议,但是我们当前使用的模块不支持MQTT协议(好像ESP8266可以通过重新烧录固件的方式支持),使用新的模块成本会增加。
经过初步研究,发现MQTT协议就是基于TCP/IP的协议,WIFI模块只要能提供TCP连接,可以通过MCU的代码实现MQTT协议,而且已经有封装好的底层函数提供调用。

2.MQTT协议

MQTT (Message Queuing Telemetry Transport,消息队列传输探测)是一种基于客户端服务端架构的发布/订阅模式的消息传输协议。它的设计思想是轻巧、开放、 简单、规范,易于实现。这些特点使得它对很多场景来说都是很好的选择,特别是对于受限的环境如机器与机器的通信(M2M)以及物联网环境(IoT)。与 HTTP 协议一样,MQTT 协议也是应用层协议,工作在 TCP/IP 四层模型中的最上层(应用层),构建于 TCP/IP协议上。
现在主要使用MQTT 3.1.1 协议(网上很多介绍,这个协议需要重点看一下)。

3.实现方法

使用WIFI模块连接网络,与服务器建立TCP连接后,WIFI模块开启透传模式,之后就可以按照MQTT协议的格式和步骤进行通信。

4.底层代码

代码建议结合MQTT 3.1.1 协议阅读,函数的主要功能包括连接、发布/订阅等

/********************************************************************************************
[函数名称]GetDataFixedHead
[函数功能]获取MQTT数据包头
[参    数]MesType,DupFlag,QosLevel,Retain
[全局变量]无
[返 回 值]包头数据
[备    注]
*********************************************************************************************/
u8 GetDataFixedHead(u8 MesType,u8 DupFlag,u8 QosLevel,u8 Retain)
{
	u8 dat = 0;
	dat  = (MesType & 0x0f) << 4;
	dat |= (DupFlag & 0x01) << 3;
	dat |= (QosLevel & 0x03) << 1;
	dat |= (Retain & 0x01);
	return dat;
}

/********************************************************************************************
[函数名称]GetDataConnet
[函数功能]获取连接的数据包正确连接返回
[参 数]buff,ClientIdentifier,UserName,Password
[全局变量]无
[返 回 值]数据长度
[备 注]
****************************************************************************************/
u16 GetDataConnet(u8
buff, char
ClientIdentifier,char
UserName,char
Password)
{
u16 i,len,lennum = 0;
char
msg;

buff[0] = GetDataFixedHead(MQTT_TypeCONNECT,0,0,0); 
buff[2] = 0x00;
buff[3] = 0x04;
buff[4] = 'M';
buff[5] = 'Q';
buff[6] = 'T';
buff[7] = 'T';
buff[8] = 0x04;	//协议级别Protocol Level
buff[9] = 0 | (MQTT_StaCleanSession << 1) | (MQTT_StaWillFlag << 1)
			| (MQTT_StaWillQoS << 3) | (MQTT_StaWillRetain << 5) 
			| (MQTT_StaPasswordFlag << 6) |(MQTT_StaUserNameFlag << 7);
i = MQTT_KeepAlive;
buff[10] = i >> 8;
buff[11] = i;
len = strlen(ClientIdentifier);
buff[12] = len >> 8;
buff[13] = len;
msg = ClientIdentifier;
for(i = 0;i<len;i++)
{
	buff[14+i] =  msg[i];
}
lennum = len;
if(MQTT_StaWillFlag) //遗嘱标志
{
	len = strlen(MQTT_WillTopic);     //遗嘱topic
	buff[13 + lennum + 1] = len >> 8;
	buff[13 + lennum + 2] = len;
	lennum += 2;
	msg = MQTT_WillTopic;
	for(i = 0;i<len;i++)
	{
		buff[14+lennum+i] =  msg[i];
	}
	lennum += len;
	len = strlen(MQTT_WillMessage); //遗嘱message
	buff[12] = len >> 8;
	buff[13] = len;
	lennum += 2;
	msg = MQTT_WillMessage;
	for(i = 0;i<len;i++)
	{
		buff[14+lennum+i] =  msg[i];
	}
	lennum += len;
}
if(MQTT_StaUserNameFlag) 		//用户名标志
{
	len = strlen(UserName);
	buff[13 + lennum + 1] = len >> 8;
	buff[13 + lennum + 2] = len;
	lennum += 2;
	msg = UserName;
	for(i = 0;i<len;i++)
	{
		buff[14+lennum+i] = msg[i];
	}
	lennum += len;
	
}
if(MQTT_StaPasswordFlag)		//密码标志
{
	len = strlen(Password);
	buff[13 + lennum + 1] = len >> 8;
	buff[13 + lennum + 2] = len;
	lennum += 2;
	msg = Password;
	for(i = 0;i<len;i++)
	{
		buff[14+lennum+i] =  msg[i];
	}
	lennum += len;
}
buff[1] = 13 + lennum - 1;

return (buff[1]+2);

}

/********************************************************************************************
[函数名称]GetDataSUBSCRIBE
[函数功能]订阅主题的数据包
[参 数]buff,TopicName, Num:主题序号 RequestedQoS:服务质量要求0,1或2 nIndex:0订阅 1取消订阅
[全局变量]无
[返 回 值]数据长度
[备 注]
*********************************************************************************************/
u16 GetDataSUBSCRIBE(u8 buff,char TopicName,u16 Num,u8 RequestedQoS, u8 nIndex)
{
u16 i,len = 0,lennum = 0;

if(nIndex==0)	//订阅
{
	buff[0] = GetDataFixedHead(MQTT_TypeSUBSCRIBE,0,1,0); 
}
else        	//取消订阅
{
	buff[0] = GetDataFixedHead(MQTT_TypeUNSUBSCRIBE,0,1,0);
}
buff[2] = Num>>8;
buff[3] = Num;
len = strlen(TopicName);
buff[4] = len>>8;
buff[5] = len;
for(i = 0;i<len;i++)
{
	buff[6+i] = TopicName[i];
}
lennum = len;
if(nIndex==0) 	//订阅需要增加 RequestedQoS
{
	buff[6 + lennum] = RequestedQoS; 
	buff[1] = lennum + 5;
}
else 			//取消订阅
{
	buff[1] = lennum + 4;
}

return (buff[1]+2);

}

/********************************************************************************************
[函数名称]GetDataPUBLISH
[函数功能]获取发布消息的数据包
[参 数]buff,topic, Num,msg
[全局变量]无
[返 回 值]数据长度
[备 注]MQTT中的Remaining Length,最大长度为4个字节(低字节在前,高字节再后)。
其中每个字节的第一位为 “是否有后续字节” 的状态位。如果有设置该状态位为1,没有则设置为0
*********************************************************************************************/
u16 GetDataPUBLISH(u8 *buff,char *topic,u16 Num,char *msg)
{
u32 i,j=0,Length=0,topic_len=0,msg_len=0;

buff[0]   = GetDataFixedHead(MQTT_TypePUBLISH,0,1,0);
topic_len = strlen(topic);
msg_len   = strlen(msg);
Length    = topic_len+msg_len +4;
if(Length>127)
{
	buff[1] = (Length&0x7F) | 0x80;
	buff[2] = Length>>7;
	j = 1;
}
else
{
	buff[1] = Length;
	j = 0;
}
buff[2+j] = topic_len>>8;
buff[3+j] = topic_len;
for(i = 0;i<topic_len;i++)
{
	buff[4+j+i] = topic[i];
}
buff[4+j+topic_len] = Num/256;
buff[5+j+topic_len] = Num%256;
for(i = 0;i<msg_len;i++)
{
	buff[6+j+topic_len+i] = msg[i];
}	
Length += (Length>127) ? 3 : 2;
return  Length;

}

/********************************************************************************************
[函数名称]GetPCDataPUBLISH
[函数功能]获取发布消息的数据包
[参 数]buff,topic, Num,msg
[全局变量]无
[返 回 值]数据长度
[备 注]MQTT中的Remaining Length,最大长度为4个字节(低字节在前,高字节再后)。
其中每个字节的第一位为 “是否有后续字节” 的状态位。如果有设置该状态位为1,没有则设置为0
*********************************************************************************************/
u16 GetPCDataPUBLISH(u8 *buff,char *topic,u16 Num,char *msg,u16 msg_len)
{
u32 i,j=0,Length=0,topic_len=0,DevIdLen=0;

buff[0]   = GetDataFixedHead(MQTT_TypePUBLISH,0,0,0);
topic_len = strlen(topic);
DevIdLen  = strlen((char *)DevicePara.m_DeviceID);
Length    = topic_len+msg_len+DevIdLen+4;

if(Length>127)
{
	buff[1] = (Length&0x7F) | 0x80;
	buff[2] = Length>>7;
	j = 1;
}
else
{
	buff[1] = Length;
	j = 0;
}

buff[2+j] = topic_len>>8;
buff[3+j] = topic_len;
for(i = 0;i<topic_len;i++)
{
	buff[4+j+i] = topic[i];
}

for(i = 0;i<DevIdLen;i++)
{
	buff[4+j+topic_len+i] = DevicePara.m_DeviceID[i];
}

for(i = 0;i<msg_len;i++)
{
	buff[4+j+topic_len+DevIdLen+i] = msg[i];
}

Length += (Length>127) ? 3 : 2;
return  Length;

}

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值