社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
上篇文章主要讲解了W5100S特色功能——SOCKET - less PING功能。
文章链接 - W5100S——SOCKET - less PING功能解析(可以了解下W5100S硬件PING功能如何使用)
本篇文章则是讲解,如何让W5100S 通过MQTT连接百度天工云平台。
软件环境:Windows
硬件环境:STM32F103+W5100S
开发工具:Keil uVision5
调试工具:串口调试助手
连接平台:百度云天工(https://cloud.baidu.com/)
MQTT官网地址:(http://mqtt.org/)
MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。
MQTT协议当前版本为,2014年发布的MQTT v3.1.1。除标准版外,还有一个简化版MQTT-SN,该协议主要针对嵌入式设备。
MQTT协议运行在TCP/IP或其他网络协议,提供有序、可靠、双向连接。其特点包括:
数据传输和协议交换的最小化(协议头部只有2字节),以减少网络流量
通知机制,异常中断时通知传输双方
实现MQTT协议需要:客户端和服务器端
MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。
MQTT传输的消息分为:主题(Topic)和消息的内容(payload)两部分
Topic,可以理解为消息的类型,订阅者订阅(Subscribe)后,就会收到该主题的消息内容(payload)
payload,可以理解为消息的内容,是指订阅者具体要使用的内容
2.3.1.进入管理控制台(请提前登录);
2.3.2. 选择“物接入IoT Hub”板块
2.3.3. 创建项目
(例程搭配数据型设备使用,详细数据型与设备型差异,请前往百度云天工查询)
2.3.4. 项目提交后,进入项目创建子用户
名称:MQTT连接报文中的用户名
身份:确定访问形式,可以使用密钥连接。
策略:绑定对应权限与主题。
密钥:请妥善保管,此为连接的密码。(遗忘可在身份列表重置)
项目创建成功后,记录下:名称、身份、密钥。即可通过例程修改对应字符串连接自己所创建的设备。
首选我们查看烧录程序后,应有的实验现象。
3.1.串口打印信息显示“连接成功”或者“连接失败的具体原因”。
3.2.订阅主题
3.3.接收主题消息
3.4.发布主题消息
由于代码内涉及MQTT的拆包组包部分,详细讲解太过冗杂。
故此次解析,仅从函数功能及代码框架解析,不对函数实现做过多拆解。
4.1.主函数整体框架流程
#include <stdio.h>
#include <string.h>
#include "stm32f10x.h"
#include "bsp_usart1.h"
#include "bsp_fsmc.h"
#include "bsp_spi.h"
#include "w5100s.h"
#include "W5100s_conf.h"
#include "wizchip_conf.h"
#include "w5100s_conf.h"
#include "utility.h"
#include "tcp_demo.h"
#include "MqttKit.h"
int main(void)
{
systick_init(72); // 初始化滴答定时器
USART1_Config(); // 初始化USART1:115200@8-N-1
reset_break_gpio_init(); // 复位与中断管脚初始化
#if (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_)
spi_gpio_init(); // SPI管脚初始化
spiinitailize(); // SPI配置初始化
reg_wizchip_spi_cbfunc(spi_read_byte,spi_send_byte); // SPI读写数据函数映射
reg_wizchip_cs_cbfunc(cs_low,cs_high); // SPI片选控制函数映射
#elif (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_)
FSMC_gpio_init(); // FSMC管脚初始化c
FSMCInitialize(); // FSMC配置初始化
#endif
printf("rn 炜世科技--WIZnet W5100S官方代理商。全程技术支持,价格优势大!rnrn");
reset_w5100s(); // W5100S硬件复位
PHY_check(); // 网线检测程序
set_w5100s_mac(); // 设置W5100SMAC地址
set_w5100s_netinfo(); // 设置W5100S网络参数
wizchip_init(txsize,rxsize); // 初始化4个Socket的发送接收缓存大小
printf("rn W5100S网络参数配置完成,请使用电脑 'PING' W5100SIP地址,检查网络是否畅通。");
while(1) /*循环执行的函数*/
{
do_tcp_client(); // TCP 客户端数据回环测试
delay_ms(100);
if(User1 == 0) //订阅
{
while(User1 == 0);
MQTT_STATE = MQTT_PKT_SUBSCRIBE;
}
// if(KEY_5 == 0) //取消订阅
// {
// MQTT_STATE = MQTT_PKT_UNSUBSCRIBE;
// }
else if(User0 == 0) //发布
{
while(User0 == 0);
MQTT_STATE =MQTT_PKT_PUBLISH;
}
}
}
主函数部分,代码整体框架还是十分明了的。
main函数之前是单片机和W5100S使用前的初始化部分。
main内则是基本的TCP客户端程序和按键检测,不同按键改变MQTT_STATE的不同状态。
接下来详细进一步探究do_tcp_client()函数。
4.2.do_tcp_client()函数
uint8 buff[2048]; /*定义一个2KB的缓存*/
uint8 BD_TG_server_ip[4] = {163,177,150,12}; //BD_TG服务器IP地址
uint16 BD_TG_server_port = 1883; //BD_TG服务器端口号
int MQTT_STATE = MQTT_PKT_CONNECT; //连接
const char *topics[] = {"test"}; //主题
uint8 BD_TG_ping_pak[2] = {0xC0,0x00}; //心跳报文
unsigned char *data_ptr = NULL; //指针指空
/**
*@brief TCP Client回环演示函数。
*@param 无
*@return 无
*/
void do_tcp_client(void)
{
uint16 len=0;
switch(getSn_SR(SOCK_TCPC)) /*获取socket的状态*/
{
case SOCK_CLOSED: /*socket处于关闭状态*/
socket(SOCK_TCPC,Sn_MR_TCP,local_port++,Sn_MR_ND);
break;
case SOCK_INIT: /*socket处于初始化状态*/
connect(SOCK_TCPC,BD_TG_server_ip,BD_TG_server_port); /*socket连接服务器*/
break;
case SOCK_ESTABLISHED: /*socket处于连接建立状态*/
if(getSn_IR(SOCK_TCPC) & Sn_IR_CON)
{
setSn_IR(SOCK_TCPC, Sn_IR_CON); /*清除接收中断标志位*/
}
len=getSn_RX_RSR(SOCK_TCPC); /*定义len为已接收数据长度*/
if(len>0)
{
recv(SOCK_TCPC,buff,len); /*接收来自Server的数据*/
data_ptr = buff;
if(data_ptr != NULL)
BD_TG_RevPro(data_ptr);
if(publish_buf[0] == 0x31)
{
LED_ALL_ON;
}
else if(publish_buf[0] == 0x32)
{
LED_ALL_OFF;
}
}
switch(MQTT_STATE)
{
/*MQTT协议连接BD_TG代理平台*/
case MQTT_PKT_CONNECT:
BD_TG_DevLink();
MQTT_STATE = MQTT_PKT_PINGREQ;
break;
/*订阅主题*/
case MQTT_PKT_SUBSCRIBE:
BD_TG_Subscribe(topics,1);
MQTT_STATE = MQTT_PKT_PINGREQ;
break;
/*Qos2级别发布消息*/
case MQTT_PKT_PUBLISH:
BD_TG_Publish(*topics, "MQTT Publish Test"); //发布消息
delay_ms(300); //等待平台响应
/*接收平台发送的PubRec并回复PubRel响应*/
len=getSn_RX_RSR(SOCK_TCPC);
recv(SOCK_TCPC,buff,len);
data_ptr = buff;
if(data_ptr != NULL)
BD_TG_RevPro(data_ptr);
delay_ms(100); //PubRel响应等待平台响应
len=getSn_RX_RSR(SOCK_TCPC);
recv(SOCK_TCPC,buff,len);
data_ptr = buff;
if(data_ptr != NULL)
BD_TG_RevPro(data_ptr);
MQTT_STATE = MQTT_PKT_PINGREQ;
/*120秒发送一次Ping响应保持长连接*/
break;
case MQTT_PKT_UNSUBSCRIBE:
MQTT_UnSubscribe(topics,1);
MQTT_STATE = MQTT_PKT_PINGREQ;
break;
case MQTT_PKT_PINGREQ:
if(BD_TG_ping_time > 120)
{
send(SOCK_TCPC,BD_TG_ping_pak,2);
BD_TG_ping_time = 0;
}
break;
}
break;
case SOCK_CLOSE_WAIT: /*socket处于等待关闭状态*/
close(SOCK_TCPC);
break;
}
}
主要是个状态机的编写格式,基本的TCP建立连接(SOCK_ESTABLISHED状态)后,通过MQTT_STATE变量的状态,判断是发送MQTT连接报文、MQTT订阅报文、MQTT消息发布、MQTT取消订阅、MQTT心跳报文等不同的case。
最开始会先默认进入MQTT_PKT_CONNECT,发送连接报文,我们连接百度云,主要有以下参数需要更改。
#define PROID "7321ph4/w5500" // 设备全称
#define AUTH_INFO "23h0wtzkmmti982q" // API密钥
#define DEVID "qwe" // 身份
以上信息,在百度云建立设备时,会让客户设置。我们只需要把设置的复制,替换上述字符串即可。
而我们MQTT的功能实现,则替换以下函数相应的传参字符即可。
const char *topics[] = {"test"}; //主题
BD_TG_Subscribe(topics,1); //订阅主题,数量 1
BD_TG_Publish(*topics, "MQTT Publish Test"); //发布的主题,发布的消息
MQTT_UnSubscribe(topics,1); //取消订阅的主题,数量 1
上述的代码,均是www.w5100s.com内17.MQTT_BDTG例程内的,该例程已经过实测,可正常连接百度天工云平台,实现MQTT订阅、发布等相关功能。
W5100S目前已经到货,炜世已经正式调通并将配套的资料例程补充完毕。
相关资料炜世已经整理上传至www.w5100s.com网址内,欢迎各位前往浏览。
WIZnet W5100S技术交流群:579842114,群内有“大神”为大家答疑解惑。
后续我将会陆续发布关于W5100S各类功能测试博文,有兴趣的朋友欢迎关注。
炜世是WIZnet的的的官方代理商,W5100S可提供模块/评估板供客户测试。
如需详细资料/样品申请/技术支持等,欢迎与我们联系。
炜世为客户提供全程的技术支持与优异的价格优势。
网址:深圳炜世科技 - 物联网系统解决方案提供商&WIZnet授权代理商
电话:13798261264
QQ:2571856470
邮箱:jason@wisioe.com
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!