MQTT|MQTT初体验-百度智能云

说明:
该文章记录了基于百度智能云MQTT服务器的测试使用过程,方便以后查阅。
MQTT协议中文版下载 https://legacy.gitbook.com/book/mcxiaoke/mqtt-cn/details

1、创建百度智能云 登陆入口地址:https://login.bce.baidu.com/?account=
找到如下入口并进入。
MQTT|MQTT初体验-百度智能云
文章图片

MQTT|MQTT初体验-百度智能云
文章图片

创建新项目:
MQTT|MQTT初体验-百度智能云
文章图片

设备型:百度云已提供JSON解析过滤功能,提供主题变动及发布等事件的处理。适用于一般控制类设备,不适合数据流设备。使用简单快速。
数据型:该类型设备只提供MQTT的服务器功能,不提供payload数据解析功能。使用灵活。

创建项目成功后会出现三个连接地址:

  1. tcp://au****.mqtt.iot.gz.baidubce.com:1883用于TCP通讯使用
  2. ssl://au*****.mqtt.iot.gz.baidubce.com:1884客户端MQTT.fx 使用该端口1884支持 SSL/TLS安全认证
  3. wss://au*****.mqtt.iot.gz.baidubce.com:443
在用户列表下可进行测试,输入身份密钥执行连接,
测试主题发布与订阅时,必须保证该主题在策略列表中已添加过。只有策略列表里添加的主题才允许被使用
MQTT|MQTT初体验-百度智能云
文章图片

如上发布订阅测试通过。即可用于实际应用场合

2、通过 MQTT.fx 客户端测试连接 参考百度智能云提供的教程 https://cloud.baidu.com/doc/IOT/Quickstart-new.html#.E6.93.8D.E4.BD.9C.E6.AD.A5.E9.AA.A4

MQTT|MQTT初体验-百度智能云
文章图片

MQTT|MQTT初体验-百度智能云
文章图片

3、Socket 通讯测试 原理:MQTT C语言库提供MQTT协议序列化和反序列功能。
接收过程是将Socket接收到的数据流传递给MQTT库解算。发送工程是将要登陆信息、发布的主题、订阅主题操作序列化成数据流传递给Socket发送数据流中。完成一个数据传输的功能。MQTT是一套协议,Socket是一个数据传输工具。
3.1、C语言Socket 测试使用在VS2013平台,MQTT服务器连接在Socket连接阶段完成。
#include #include #include #pragma comment (lib, "ws2_32.lib")//socket库文件typedef struct sockaddr_in sockaddr_in; SOCKET s_socket; int SocketClass::Connect(char*hostname, int port) { sockaddr_in sockaddr; char buffer[MAXBYTE] = { 0 }; WSADATA wsaData; //加载库 WSAStartup(MAKEWORD(2, 2), &wsaData); //创建套接字 s_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); //域名解析出IP struct hostent *host = gethostbyname(hostname); char *ip; if (host == NULL) return -1; else ip = inet_ntoa(*(struct in_addr*)host->h_addr_list[0]); //连接服务器 sockaddr.sin_family = PF_INET; sockaddr.sin_addr.S_un.S_addr = inet_addr(ip); sockaddr.sin_port = htons(port); return connect(s_socket, (SOCKADDR*)&sockaddr, sizeof(SOCKADDR)); }int SocketClass::Close() { closesocket(s_socket); WSACleanup(); return 0; }int SocketClass::Write(char* buff, int len) { return send(s_socket, buff, len, 0); }int SocketClass::Read(char* buff, int len) { //等待接收到数据才会退出 return recv(s_socket, buff, len, 0); }

3.2、MQTT登陆
int mqtt_connect(void) { u8 connectBuf[CONNECTBUFMAX]; int len; MQTTPacket_connectData data = https://www.it610.com/article/MQTTPacket_connectData_initializer; data.clientID.cstring = (char*)coco_mqttConnectName; // 客户端标识符(自定义字符串) data.keepAliveInterval = 50; // keep Alive 单位s data.cleansession = 0; // 清理会话标志置位 data.username.cstring ="aut6m7h/device"; // 用户名 data.password.cstring = "yhnG3PJm6666666"; // 用户密码 len = MQTTSerialize_connect(connectBuf, sizeof(connectBuf), &data); //发送登陆信息 _socket.Write((char*)connectBuf, len); //等待登陆结果应答 len = _socket.Read(readBuff, 512); if (len >= 4 && (memcmp("\x20\x02", readBuff, 2) == 0))//参考MQTT文档CONNACK报文说明 { printf_s("MQTT登陆成功\r\n"); return 0; } else { printf_s("MQTT登陆失败\r\n"); return -1; } }

3.3、MQTT主题订阅
bool MQTT_Subscribe(char *subscribe) { int len; int req_qos = 0; u8 buf[512]; MQTTString topicString = MQTTString_initializer; topicString.cstring = subscribe; len = MQTTSerialize_subscribe(buf, sizeof(buf), 0, MQTT_packid++, 1, &topicString, &req_qos); _socket.Write((char*)buf, len); len = _socket.Read((char*)buf, 512); if (len >= 5 && (memcmp("\x90\x03", buf, 2) == 0)) { if ((buf[4] & 0x80) != 0x80) { return true; } } return false; }

3.4、MQTT主题发布
bool MQTT_Publish(char *topic, char *str) { u8 fifo[512]; int outLen = 0; MQTTString topicString = MQTTString_initializer; topicString.cstring = topic; int len = MQTTSerialize_publish(fifo, 512, 0, 0, 0, MQTT_packid++, topicString, (u8*)str, strlen(str)); _socket.Write((char*)fifo, len); return false; }

3.5、MQTT接收订阅消息
int len = _socket.Read(rxfifo, 512); if (len >= 2) { if ((rxfifo[0] & 0xF0) == 0x30)//收到发布的消息 { u8 dup; int qos; u8 retanined; u16 msgid; MQTTString receiveTopic; u8 *payload; int payloadLen; int ret = MQTTDeserialize_publish(&dup, &qos, &retanined, &msgid, &receiveTopic, &payload, &payloadLen, (u8*)rxfifo, len); if (ret) { char topic[100]; char data[512]; memcpy(topic, receiveTopic.lenstring.data, receiveTopic.lenstring.len); topic[receiveTopic.lenstring.len] = 0; memcpy(data, payload, payloadLen); data[payloadLen] = 0; printf_s("发序列化成功 topic[%s] payload[%s]\r\n", topic, data); } } }

【MQTT|MQTT初体验-百度智能云】注意:反序列化函数输出值主题名(receiveTopic.lenstring.data)和主题的数据部分(payload)地址指向原始数据空间(rxfifo数组)中的某一个位置,结算后拷贝出来,不要对上述两个值执行写操作,以免数据破坏。

    推荐阅读