首页 > 编程语言 >【嵌入式裸机开发】智能家居入门7:最新ONENET,MQTT协议接入,最全最新(微信小程序、MQTT协议、ONENET云平台、STM32)

【嵌入式裸机开发】智能家居入门7:最新ONENET,MQTT协议接入,最全最新(微信小程序、MQTT协议、ONENET云平台、STM32)

时间:2024-08-21 20:53:49浏览次数:14  
标签:ONENET ESP8266 res 智能家居 json char MQTT data esp8266

智能家居入门7

前言

本篇文章介绍最新ONENET云平台的MQTT协议接入方法,在STM32上实现数据上云与服务器下发数据解析,以及微信小程序接入服务器。对于智能家居而言,最重要的就是通信,通信是否稳定是否响应快,这是最重要的,外设的连接与控制这些都是很简单的,网上的一搜直接就有现成的代码,所以本篇博客不会介绍关于外设的使用与控制,主要介绍最新ONENET的接入与消息解析,这个框架搭好以后,其它外设连接那都不是事儿。

硬件准备:
STM32F103C8T6
ESP8266-01S
OLED液晶显示屏或串口调试模块(USB转TTL)
DHT11(可有可无,自己虚构上传数据也可以)
烧录器


一、ONENET云平台创建产品与设备

这部分直接以视频的形式给出:

<iframe allowfullscreen="true" data-mediaembed="youku" frameborder="0" id="ECb9P52C-1723861765198" src="https://player.youku.com/embed/XNjQxNTE0OTAyNA=="></iframe>

需要注意的点:
①数据协议:
这里选择的是OneJson,当然也可以选择数据流,但是它们对应的发送数据和接收数据的topic是不一样的,所以如果想省事直接使用本文代码,那就选择OneJson。
在这里插入图片描述

②新版三元组:
按照视频创建完毕后,进入设备管理的设备详情中,可以看到后续会用到的三个参数:
在这里插入图片描述


二、STM32端连接服务器前的准备

①token:
首先计算token,在连接时会用到:
在这里插入图片描述
上图中的clienid和username就是新版三元组中包含的其中两个参数:设备名称、产品ID,password就是使用官方软件计算生成的token。
接下来视频演示如何计算token:

<iframe allowfullscreen="true" data-mediaembed="youku" frameborder="0" id="s9KCn6XZ-1723865797422" src="https://player.youku.com/embed/XNjQyMjAzNDkxMg=="></iframe>

重点提取如下:
在这里插入图片描述
纠错:上图中的时间过小,在后面多加随便一个数字既可:2810295937232。

②STM32端OneJson数据协议对应的发布、订阅topic:
在创建产品时我们选择的数据协议是OneJson,文档中有明确给出OneJson数据协议(物模型)的发布和订阅topic,如果数据协议选择数据流的小伙伴,在文档的这个界面往后翻翻就可以看到对应的。
在这里插入图片描述
在代码中,首先连接服务器,成功之后就可以订阅主题或者发布数据到主题中。
我们不止要知道发布订阅主题,对于上传数据而言还要知道上传的数据格式;对于订阅服务器下发的数据而言,还需要知道数据格式,以便于解析,下面第三点来介绍这些。

③STM32端OneJson数据协议对应的数据格式::
1、设备属性上报OneJSON数据格式:
在这里插入图片描述
图中很容易看出来数据格式中有些可以不用填,本文最终上传的数据格式如下:

{
  "id": "123",
  "params": {
    "temp": {
      "value": 25.00,
    },
    "humi": {
      "value": 70.00,
    }
  }
}

2、设备属性设置OneJSON数据格式(服务器下发数据):
在这里插入图片描述
本文代码中订阅话题之后,若是服务器下发数据,STM32端就会收到,打印出接收到的数据如下:

 +MQTTSUBRECV:0,"$sys/bs2u21MIHC/dht11/thing/property/set",54,{"id":"208","version":"1.0","params":{"fan_ctl":true}}

代码中会对此消息进行解析,就可以将控制命令给解出来进行动作了。

④esp8266-01s烧录新的mqtt固件:
下载固件与烧录软件:通过百度网盘分享的文件:new_onenet_mqtt固件烧录.rar
链接:https://pan.baidu.com/s/1aAEqlCVyUB-9ZoaFU0qf2w?pwd=1yjb 提取码:1yjb

具体烧录过程参考:https://blog.csdn.net/jackcsdnfghdtrjy/article/details/104770612

三、STM32端实现

上传数据至服务器这部分,是参考的b站视频(彼岸有光我们有船),数据接收与解析为原创,干货来咯。
相较于之前的智能家居stm32端代码,本文的NET相关代码只剩下面两个即可:
在这里插入图片描述

esp8266.cpp:

//单片机头文件
#include "stm32f10x.h"

//网络设备驱动
#include "esp8266.h"

//硬件驱动
#include "delay.h"
#include "usart.h"

//C库
#include <string.h>
#include <stdio.h>
#include "cJSON.h"
#include <stdlib.h>

#define WIFI_SSID 						"wzqzq"								//	WIFI名
#define WIFI_PSWD 						"12345678"				//	WIFI密码

#define ESP8266_WIFI_INFO			"AT+CWJAP=\"" WIFI_SSID "\",\"" WIFI_PSWD "\"\r\n"

#define ESP8266_ONENET_INFO		"AT+MQTTCONN=0,\"mqtts.heclouds.com\",1883,1\r\n"

#define ESP8266_USERCFG_INFO  "AT+MQTTUSERCFG=0,1,\"dht11\",\"bs2u21MIHC\",\"version=2018-10-31&res=produmd5&sign=dkKx5uuWp0sMqet7BJGa2w%3D%3D\",0,0,\"\"\r\n"

const char* pubtopic="$sys/bs2u21MIHC/dht11/thing/property/post";
const char* subtopic="$sys/bs2u21MIHC/dht11/thing/property/set";

unsigned char esp8266_buf[ESP_RX_MAX];
unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;

extern u8 ESP8266_INIT_OK;

char bool_value[12];
char *new_json;

//	函数功能:	清空缓存
void ESP8266_Clear(void)
{
	memset(esp8266_buf, 0, sizeof(esp8266_buf));
	esp8266_cnt = 0;
}

//	函数功能:	等待接收完成
_Bool ESP8266_WaitRecive(void)
{
	if(esp8266_cnt == 0) 							//如果接收计数为0 则说明没有处于接收数据中,所以直接跳出,结束函数
		return REV_WAIT;
		
	if(esp8266_cnt == esp8266_cntPre)				//如果上一次的值和这次相同,则说明接收完毕
	{
		esp8266_cnt = 0;							//清0接收计数
			
		return REV_OK;								//返回接收完成标志
	}
		
	esp8266_cntPre = esp8266_cnt;					//置为相同
	
	return REV_WAIT;								//返回接收未完成标志

}

//	函数功能:	发送命令
_Bool ESP8266_SendCmd(char *cmd, char *res)
{
	
	unsigned char timeOut = 200;

	Usart_SendString(USART2, (unsigned char *)cmd, strlen((const char *)cmd));
	
	while(timeOut--)
	{
		if(ESP8266_WaitRecive() == REV_OK)							//如果收到数据
		{
			if(strstr((const char *)esp8266_buf, res) != NULL)		//如果检索到关键词
			{
				ESP8266_Clear();									//清空缓存
				
				return 0;
			}
		}
		
		delay_ms(10);
	}
	
	return 1;

}

//	函数功能:	发送数据
void ESP8266_SendData(double temp,double humi,double adcx)
{
	char cmdBuf[512];
	
	ESP8266_Clear();								//清空接收缓存
	
	//先发送要发送数据的指令做准备
	
	sprintf(cmdBuf, "AT+MQTTPUB=0,\"%s\",\"{\\\"id\\\":\\\"123\\\"\\,\\\"params\\\":{\\\"temp\\\":{\\\"value\\\":%.2f\\}\\,\\\"humi\\\":{\\\"value\\\":%.2f\\}\\,\\\"ch4\\\":{\\\"value\\\":%.2f\\}}}\",0,0\r\n",pubtopic,temp,humi,adcx);		//发送命令
	while(ESP8266_SendCmd(cmdBuf, "OK"))
		delay_ms(500);
	memset(cmdBuf,0,sizeof(cmdBuf));
	delay_ms(100);
}

//订阅话题
void ESP8266_sub()
{
	char cmdBuf[512];
	
	ESP8266_Clear();								                          //清空接收缓存
	sprintf(cmdBuf, "AT+MQTTSUB=0,\"%s\",0\r\n", subtopic);		//发送命令
	
	while(ESP8266_SendCmd(cmdBuf, "OK"))
		delay_ms(500);
	memset(cmdBuf,0,sizeof(cmdBuf));
	delay_ms(100);
}
//键值对提取
char * extract_json(const char *src) {
    // 找到 "params" 字段的开始位置
    const char *start = strstr(src, "params");
	  DEBUG_LOG("JSON: %s\n",src);
    if (start) {
        // 跳过 "params" 字符串的长度
        start += strlen("params");
        
        // 找到 '{' 字符的位置,表示 params 对象的开始
        while (*start && *start != '{') {
            start++;
        }
        if (*start == '{') {
            // 从 '{' 开始复制,直到 '}' 或字符串结束
            const char *end = strchr((char *)start, '}');
            if (end) {
                // 计算需要复制的长度
                size_t len = (size_t)(end - start);
                // 创建一个新的缓冲区并复制目标字符串
                char *new_json = (char *)malloc(len + 2); // +1 为了空字符,+1 为了避免潜在的 '{'
                if (new_json) {
                    strncpy(new_json, start, len);
                    new_json[len] = '}'; // 添加 '}' 以确保 JSON 结束
                    new_json[len + 1] = '\0'; // 确保以空字符结尾
										DEBUG_LOG("Extracted JSON: %s\n",new_json);
										return new_json;
                }
            }
        }
    }
}

//解析
void parse_onenet_command(const char *json_str) {
    cJSON *json, *led_ctl_item, *fan_ctl_item;
	
	  char* temp = extract_json(json_str);

    json = cJSON_Parse(temp);
    if (json == NULL) {
        // 处理 JSON 解析错误
        const char *error_ptr = cJSON_GetErrorPtr();
        printf("Error parsing JSON: %s\n", error_ptr);
        return;
    }

    // 直接获取 "led_ctl" 的值
    led_ctl_item = cJSON_GetObjectItem(json, "led_ctl");
    if (led_ctl_item != NULL)
		{
			  if(led_ctl_item -> valueint)
				{
						DEBUG_LOG("led open\n");
				}
				else
				{
						DEBUG_LOG("led close\n");
				}
    } 
	fan_ctl_item = cJSON_GetObjectItem(json, "fan_ctl");
	if (fan_ctl_item != NULL)
	{
			if(fan_ctl_item -> valueint)
			{
					DEBUG_LOG("fan open\n");
			}
			else
			{
					DEBUG_LOG("fan close\n");
			}
	}

    // 清理并释放内存
	free(new_json);
	free(temp);
    cJSON_Delete(json);
}


//主函数或者定时器中循环调用,如果esp8266接收到数据,就解析
unsigned char *ESP8266_GetIPD(unsigned short timeOut)
{
	char *ptrIPD = NULL;
	
	do
	{
		if(ESP8266_WaitRecive() == REV_OK)								//如果接收完成
		{
			parse_onenet_command((const char *)esp8266_buf);
		}
		delay_ms(5);
		timeOut--;	//延时等待
	} while(timeOut > 0);
	
	return NULL;														//超时还未找到,返回空指针

}

//	函数功能:	初始化ESP8266
void ESP8266_Init(void)
{
	ESP8266_Clear();
	
	DEBUG_LOG("0. AT - 测试MCU-8266通讯");
	while(ESP8266_SendCmd("AT\r\n", "OK"))
		delay_ms(500);
	
	DEBUG_LOG("1. AT+RST - 软复位8266");
	ESP8266_SendCmd("AT+RST\r\n", "");
		delay_ms(500);
	ESP8266_SendCmd("AT+CIPCLOSE\r\n", "");
		delay_ms(500);
	DEBUG_LOG("2. AT+CWMODE=1,1 - 设置8266工作模式为STA");
	while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"))
		delay_ms(500);
	
	DEBUG_LOG("3. AT+CWDHCP=1,1 - 使能STA模式下DHCP");
	while(ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK"))
		delay_ms(500);
	
	DEBUG_LOG("4. AT+CWJAP - 连接WIFI -> [ SSID: %s ]  -> [ Password: %s ] ",WIFI_SSID, WIFI_PSWD);
	while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "GOT IP"))
		delay_ms(500);
	
	DEBUG_LOG("6. AT+MQTTUSERCFG=0,1 - 设置user信息:ID,devicename,token");
	while(ESP8266_SendCmd(ESP8266_USERCFG_INFO, "OK"))
		delay_ms(500);

	
	DEBUG_LOG("7. AT+MQTTCONN=0 - 连接服务器:ip,端口号");
	while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "OK"))
		delay_ms(500);
	
	DEBUG_LOG("服务器已连接");
}


//	函数功能:	串口2收发中断
void USART2_IRQHandler(void)
{

	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断
	{
		if(esp8266_cnt >= sizeof(esp8266_buf))	esp8266_cnt = 0; //防止串口被刷爆
		esp8266_buf[esp8266_cnt++] = USART2->DR;
		
		
		USART_ClearFlag(USART2, USART_FLAG_RXNE);
	}

}

集成到自己的代码时需要修改wifi、产品ID、设备名称、token、发布订阅话题、发送数据中的标识符要与自己在云平台创建的一致。重要代码的注释也写的很清楚了,结合上面讲的那些话题与数据格式,很容易就可以看懂。
这部分代码解决之后就可以使用云平台进行测试了,测试过程如下视频:

<iframe allowfullscreen="true" data-mediaembed="youku" frameborder="0" id="6DF7e5sC-1724060742972" src="https://player.youku.com/embed/XNjQxNTc2ODc2NA=="></iframe>

四、微信小程序端连接服务器前的准备

跟第二节一样,也需要准备token,前面已经弄好了,直接复制即可。

①onenet 云端API介绍:
通过阅读onenet物联网开放平台的文档,发现OneNET API提供产品、设备、服务等云端API,使用标准HTTP方法实现资源CURD操作,其中URL中的中文参数使用UTF-8编码。具体的大家可以去看文档,写的很清楚,所以微信小程序使用这种方式接入服务器。
在这里插入图片描述
从文档中的接口列表可以看到物模型使用的接口:
在这里插入图片描述

②具体的使用方式如下:
1、设备属性最新数据查询(微信小程序从服务器获取数据):
在这里插入图片描述
文档往下翻可以看到使用示例,微信小程序中参考这种格式即可:
在这里插入图片描述
2、设备属性期望设置(微信小程序发布数据到图中所示的接口地址,此时服务器对应的就会将此数据发布到:$sys/{pid}/{device-name}/thing/property/set这个话题中,这个话题也就是stm32端订阅的话题,这样32端就会接收到微信小程序下发的指令):
在这里插入图片描述
文档往下翻可以看到使用示例,微信小程序中参考这种格式即可:
在这里插入图片描述
有了上面这两个示例,就可以在微信小程序中进行代码的编写了!

五、微信小程序端实现

index.js

Page({
    data: {
     temp:0.0,
     humi:0.0,
     gas_ch4:0.0,
     fumes:0.0,
     leds:false,
     fen:false,
     water:false
    },
   /* 获取OneNET云平台设备数据 */
     getinfo() {
    /* 发起 HTTPS 网络请求 获取设备参数 */
    wx.request({
        /* 网址、产品ID、设备名 */
        url: "https://iot-api.heclouds.com/thingmodel/query-device-property?product_id=bs2u21MIHC&device_name=dht11",

        header: {
            /* 用户鉴权信息 */
            "authorization": "version=2018-10-31&res=products%2Fbs2u21MIHC%2Fdevices%2Fdht11&et=2810295937232&method=md5&sign"
        },
       
        method: "GET",   /* HTTP 请求方法:获取 */
        success: res => {
            console.log("获取成功", res)
            this.setData({
               humi: res.data.data[3].value,
               temp: res.data.data[5].value,
               gas_ch4: res.data.data[0].value,
            })
        }
    });
  },

   //下发指令:led
   onledsChange(event){
    const that = this
    console.log(event.detail.value);
    const sw = event.detail.value
    that.setData({leds:sw})

    if(sw){
      wx.request({
        url: 'https://iot-api.heclouds.com/thingmodel/set-device-property',
        method: 'POST',
        header: {
            /* 用户鉴权信息 */
            "authorization": "version=2018-10-31&res=products%2Fbs2u21MIHC%2Fdevices%2Fdht11&et=2810295937232&method=md5&sign"
        },
        data: {
            "product_id": "bs2u21MIHC",
            "device_name": "dht11",
            "params": {
                "led_ctl": true   /* 控制板端LED */
            }
        },
         success(res){
           console.log("成功",res.data)
         },
         fail(res){
           console.log("失败",res)
         }
       })
    }else{
      wx.request({
        url: 'https://iot-api.heclouds.com/thingmodel/set-device-desired-property',
        method: 'POST',
        header: {
            /* 用户鉴权信息 */
            "authorization": "version=2018-10-31&res=products%2Fbs2u21MIHC%2Fdevices%2Fdht11&et=2810295937232&method=md5&sign"
        },
        data: {
            "product_id": "bs2u21MIHC",
            "device_name": "dht11",
            "params": {
                "led_ctl": false   /* 控制板端LED */
            }
        },
         success(res){
           console.log("成功",res.data)
         },
         fail(res){
           console.log("失败",res)
         }
       })
    }
  },

 //下发指令:风扇
 onfenChange(event){
  const that = this
  console.log(event.detail.value);
  const sw = event.detail.value
  that.setData({fen:sw})

  if(sw){
    wx.request({
      url: 'https://iot-api.heclouds.com/thingmodel/set-device-desired-property',
      method: 'POST',
      header: {
          /* 用户鉴权信息 */
          "authorization": "version=2018-10-31&res=products%2Fbs2u21MIHC%2Fdevices%2Fdht11&et=2810295937232&method=md5&sign"
      },
      data: {
          "product_id": "bs2u21MIHC",
          "device_name": "dht11",
          "params": {
              "fan_ctl": true   /* 控制板端空调 */
          }
      },
       success(res){
         console.log("成功",res.data)
       },
       fail(res){
         console.log("失败",res)
       }
     })
  }else{
    wx.request({
      url: 'https://iot-api.heclouds.com/thingmodel/set-device-desired-property',
      method: 'POST',
      header: {
          /* 用户鉴权信息 */
          "authorization": "version=2018-10-31&res=products%2Fbs2u21MIHC%2Fdevices%2Fdht11&et=2810295937232&method=md5&sign"
      },
      data: {
          "product_id": "bs2u21MIHC",
          "device_name": "dht11",
          "params": {
              "fan_ctl": false   /* 控制板端空调 */
          }
      },
       success(res){
         console.log("成功",res.data)
       },
       fail(res){
         console.log("失败",res)
       }
     })
  }
},

  sliderChanging:function(e){
    console.log(e.detail.value)
    wx.request({
      url: 'https://iot-api.heclouds.com/thingmodel/set-device-desired-property',
      method: 'POST',
      header: {
          /* 用户鉴权信息 */
          "authorization": "version=2018-10-31&res=products%2Fbs2u21MIHC%2Fdevices%2Fdht11&et=2810295937232&method=md5&sign"
      },
      data: {
          "product_id": "bs2u21MIHC",
          "device_name": "dht11",
          "params": {
              "curtain": e.detail.value   /* 控制板端窗帘,这个例子中stm32端没写 */
          }
      },
       success(res){
         console.log("成功",res.data)
       },
       fail(res){
         console.log("失败",res)
       }
     })
  },

    onl oad() {
      var that = this
      setInterval(function(){
        that.getinfo()
      },5000)
    }
  })
  
  

上面的代码也不是完整的,有了思路和格式就是非常大的帮助,大家可以参照这样的发布与请求数据的格式将代码集成到自己的项目中,进行自己的界面设计,注意替换产品ID、设备名称、鉴权信息(token)等。

六、最终测试

微信小程序代码也调试好之后,就可以进行联调了,开发板上电连接上服务器中,微信小程序观察能否接收到数据,并测试能否下发指令控制开发板,具体如下视频:

<iframe allowfullscreen="true" data-mediaembed="youku" frameborder="0" id="maIePRnj-1724065694682" src="https://player.youku.com/embed/XNjQxNTc3NzkzNg=="></iframe>

标签:ONENET,ESP8266,res,智能家居,json,char,MQTT,data,esp8266
From: https://blog.csdn.net/m0_71523511/article/details/141316931

相关文章

  • MQTT
    目录mosquitto搭建本地服务器下载配置启动订阅主题发布消息mosquitto搭建本地服务器下载配置启动mosquitto.exe-cmosquitto.conf-v订阅主题发布消息mosquito_pub-hlocalhost-t"topic"-i"client"-m"message"......
  • Linux安装MQTT 服务器(图文教程)
    MQTT(MessageQueuingTelemetryTransport)是一种轻量级的消息传输协议,专为低带宽和不稳定的网络环境设计,非常适合物联网(IoT)应用。官网地址:https://www.emqx.com/一、版本选择根据自己的操作系统进行下载即可,推荐使用rpm安装方式。下载地址:https://www.emqx.com/zh/do......
  • 浅谈MQTT协议
    一、基本介绍MQTT(MessageQueuingTelemetryTransport,消息队列遥测传输)是一种轻量级的消息传输协议,设计用于连接一些使用TCP/IP协议的设备。它被广泛用于物联网(IoT)中,因为其低带宽、低延迟、高可靠性的特点,非常适合于远程设备和移动设备之间的通信。二、关键特性轻量级:M......
  • 【嵌入式linux开发】智能家居入门6:最新ONENET,物联网开放平台(QT、微信小程序、MQTT协议
    智能家居入门6:最新ONENET物联网开放平台前言最终现象一、ONENET云平台创建产品与设备二、使用MQTT客户端软件测试2.1测试前的准备2.2测试三、LInuxQT代码四、onenet云端API介绍及微信小程序代码4.1onenetAPI介绍4.2微信小程序代码五、板端运行前言ONENET云......
  • 基于stm32智能家居
    智能家居,基于stm32f103c8t6+温湿度传感器+超声波传感器+光敏智能家居物联网的一个课题项目,然后接下来我就介绍一下我在做课设的时候,一些步骤,最后将完整代码放入最后,方便各类爱好者提出问题以及修改。主要功能通过阿里云控制继电器,在阿里云云端上面显示当前传感器数据通过连......
  • 合宙Air780EP模组LuatOS脚本开发MQTT应用示例
    本文详细讲解了基于合宙Air780EP模组LuatOS开发的多个MQTT应用示例。本文同样适用于合宙的以下型号:Air780EPA/Air780EPT/Air780EPSAir780E/Air780EX/Air201…一、相关准备工作1.1硬件准备合宙EVB_Air780EP开发板一套,包括天线、SIM卡;USB线PC电脑1.2软件准备登录合宙......
  • MFC制作MQTT(EMQX)客户端,报错:MQTTClient_message::MQTTClient_message”: 没有重载函
    前言全局说明MQTTClient_message::MQTTClient_message”:没有重载函数接受9个参数一、说明环境:Windows7旗舰版VisualStudio2013CMakeversion3.19.8paho.mqtt.cV1.3.13二、报错MQTTClient_message::MQTTClient_message”:没有重载函数接受9个参数......
  • Qt5编译qmqtt库使用MQTT协议连接华为云IOT完成数据上传与交互
    一、前言随着物联网技术的发展,越来越多的设备通过网络互相连接,形成了庞大的智能系统。这些系统能够收集、分析并响应各种数据,从而实现自动化控制和智能化管理。在这个背景下,MQTT成为了一个广泛使用的轻量级消息传输协议,特别适用于资源受限的环境,如移动应用或远程传感器网......
  • Mqttnet实现的mqtt客户端
    usingSystem.Collections.Concurrent;usingSystem.Text;usingMQTTnet;usingMQTTnet.Client;usingMicrosoft.Extensions.Options;usingMicrosoft.Extensions.Logging;usingMQTTnet.Server;usingMicrosoft.Extensions.Hosting;usingSystem.Net.NetworkInformat......
  • 在Unity中开发MQTT客户端
    概述:        在Unity环境中使用MQTTnet库(一个流行的.NET库,用于实现MQTT客户端和服务器。它支持.NETCore和.NETFramework,并提供了灵活的API以及高性能的实现)搭建自己的MQTT客户端.我使用的版本:Version=4.3.6.1152        但是在开发客户端之前,你需要......