一、MQTT协议
MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。
实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。
在这里我们选择使用STM32F103+W5500作为客户端,来实现发布和订阅消息。
二、开发环境
硬件设备:stm32f103c8t6+w5500
开发软件:Keil MDK 525
云平台:阿里云
三、云端准备
-
以aliyun账号直接进入IoT控制台,如果还没有开通阿里云物联网套件服务,则申请开通
-
开通完后,创建一个自定义产品类

-
之后再添加一个测试设备 名称默认为空就好

-
添加好之后点进去查看设备,获取该设备的设备证书(ProductKey、DeviceName、DeviceSecret),后面会用到

-
之后再去产品那边查看自定义Topic列表,默认有一个发布和一个订阅的Topic,将${deviceName}替换成上一个步骤获取的DeviceName然后保存,后面会用到,到这里开发所需的云端就准备好了

四、移植和开发
先去W5500官网下载对应的例程下来,我们只需要提取其MQTT的库文件,至于它那个MQTT_CON_ALI函数实现就不要了,封装可读性太差了,感觉这例程就是赶出来了的( ̄o ̄)

将以上库文件添加到工程之后,就可以开始进行封装了
创建一个新的文件 mqtt_api.c 将MQTT库文件和W5500库文件声明导入
#include "mqtt_api.h"
#include "MQTTPacket.h"
#include "w5500api.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
新建一个函数 来判断过来的数据包类型,传入接收到的数据 返回数据包类型
/******解析收到的ACK报文*********/
int mqtt_decode_msg(unsigned char*buf)
{
int rc = -1;
MQTTHeader header = {
0};
header.byte = buf[0];
rc = header.bits.type;
return rc;
}
MQTT包类型声明在MQTTPacket.h 文件里
enum msgTypes
{
CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL,
PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK,
PINGREQ, PINGRESP, DISCONNECT
};
然后实现Connect函数,W5500有8个SOCKET,函数可以根据需求传入不同的SOCKET建立多个连接(该SOCKET必须处于SOCK_ESTABLISHED状态)
该函数主要是拼接连接报文,MQTTPacket_connectData参数设置好之后通过MQTTSerialize_connect函数拼接
然后通过socket发送给服务器,这边要注意的是 不同云平台验证的字段和方法不同,需根据具体情况更改,这边只介绍阿里云平台的方法:
> data.clientID.cstring="$clientId|securemode=3,signmethod=hmacsha1,timestamp=789|";//$clientId为是客户端自表示id,建议mac或sn,64字符内 其它三个参数分别是安全模式【可选值有2(TLS直连模式)、3(TCP直连模式)】、签名算法类型、时间截
> data.keepAliveInterval =180;//保活时间 阿里云规定必须大于60 单位:秒
> data.cleansession=1;//该标志置1服务器必须丢弃之前保持的客户端的信息
> data.username.cstring="$deviceName&$productKey";//$deviceName和$productKey为设备证书里的
> data.password.cstring=hmacsha1($deviceSecret,$content);//$deviceSecret为为设备证书里的 $content为productKey,deviceName,timestamp,clientId按照手母顺序排序,然后将参数值依次拼接例如:
> clientId192.168.207.115deviceNameMQTT1productKeyTKKMt4nMF8Utimestamp789
//连接MQTT服务器函数
uint8 connectMqtt(SOCKET Socket){
int len,rc,wait_ack_time=0;
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;//配置部分可变头部的值
data.clientID.cstring = mqttClientId; //客户端标识,用于区分每个客户端
data.keepAliveInterval = keepalive; //保活计时器,定义了服务器收到客户端消息的最大时间间隔
data.cleansession = cleansession; //该标志置1服务器必须丢弃之前保持的客户端的信息,将该连接视为“不存在”
data.username.cstring = mqttUsername;
data.password.cstring = password;
memset(buf,0,buflen);
len = MQTTSerialize_connect(buf, buflen, &data); /*1 构造连接报文*/
rc

本文详细介绍如何使用STM32F103和W5500芯片通过MQTT协议与阿里云平台进行数据交互,包括开发环境搭建、云端准备、代码封装及测试过程。

1618

被折叠的 条评论
为什么被折叠?



