【智能家居入门2】(MQTT协议、微信小程序、STM32、ONENET云平台)

news2024/12/26 22:22:16

此篇智能家居入门与前两篇类似,但是是使用MQTT协议接入ONENET云平台,实现微信小程序与下位机的通信,这里相较于使用http协议的那两篇博客,在主程序中添加了独立看门狗防止程序卡死和服务器掉线问题。后续还有使用MQTT协议连接MQTT服务器的智能家居项目。

    • 前言
    • 一、硬件模块
    • 二、连接服务器测试
    • 三、两个协议的对比分析
      • 1、代码结构上:
      • 2、获取服务器数据上:
      • 3、架构上:
    • 四、下位机主要代码
      • 1、接收并解析云平台下发数据:
      • 2、传感器数据上云:
    • 五、微信小程序主要代码
      • 1、index.js
      • 2、index.wxml
    • 六、源码获取

前言

这里给出前两篇使用http协议博客的网址:
①实现数据上云:https://blog.csdn.net/m0_71523511/article/details/135892908
②实现小程序控制下位机:https://blog.csdn.net/m0_71523511/article/details/135907645
在第二篇的博客结尾提出了服务器经常掉线的问题,使用别人编写好的心跳包也没用,因为程序一直卡死在重连中,所以也可以参照本篇的解决办法:加上独立看门狗,隔一段时间喂狗,如果超过时间没喂狗,说明程序多半卡死,此时看门狗处理逻辑中执行初始化esp8266和连接服务器的操作。
③独立看门狗:https://www.bilibili.com/video/BV1th411z7sn/?p=46&spm_id_from=pageDriver&vd_source=2a10d30b8351190ea06d85c5d0bfcb2a
④由于使用到了MQTT协议,想深入了解源码的话可以看看之前的的博客,对MQTT协议进行详解:https://blog.csdn.net/m0_71523511/article/details/135905690

一、硬件模块

1、0.96寸OLED液晶显示屏
2、DHT11温湿度传感器
3、继电器
4、小风扇、小水泵
5、MQ-4、MQ-9
6、esp8266-01s或者esp-12f
7、JLink下载器
8、STM32F103C8T6
大部分在上面说的第一篇博客中有介绍,这里介绍一下继电器、小风扇、小水泵:
①继电器:
由于单片机的io口无法直接驱动小风扇和水泵,这里用继电器充当开关,使用继电器驱动小风扇和小水泵运动。
在这里插入图片描述输入端口:外接5V电源,黑色跳帽可以控制继电器是高电平触发还是低电平触发。
输出端口:从左往右看,分别是NO1/NO2,COM1/COM2,NC1/NC2,代表常开,公共端,常闭三种状态。
继电器的两种状态,开和关,当继电器触发时,为打开状态,NOn口就会被使能,当继电器为关闭状态时,NCn口就会被使能,中间作为公共端连接输出。

硬件连线:
继电器输出端:小风扇红黑两根线子,红线接入继电器的NO1/NO2口,继电器的COM1/COM2拿一根公母杜邦线引出来接入5V电源,小风扇的黑线接STM32的GND口。
在这里插入图片描述
继电器输入端:
在这里插入图片描述
原文链接:https://blog.csdn.net/qq_51868810/article/details/127792611

②小风扇、小水泵:
这两个小东西就只有电源线和底线,给5v输入即可转动起来:
在这里插入图片描述
在这里插入图片描述

二、连接服务器测试

如果想单独先使用esp8266测试是否能正常与服务器通信的话可以参考这篇博客,不会创建产品也可以看:
https://blog.csdn.net/m0_71523511/article/details/135887108
需要注意的点:
①创建产品时要选择MQTT协议那个目录下进行创建
②AT指令中的IP地址和端口号要换成:183.230.40.39 6002
③需要记住的有:产品ID、鉴权信息(创建产品时自己填写的)、Master-APIkey、设备ID

三、两个协议的对比分析

1、代码结构上:

相较于使用http协议连接onenet,使用mqtt协议需要多几个源文件:onenet.c、cJSON.c、MqttKit.c。
①onenet.c是与onenet平台的数据交互接口层,通过调用MqttKit.c和esp8266.c中的库函数实现与云平台的通信,
②MqttKit.c是MQTT协议库,是MQTT协议最底层,由onenet.c进行调用。前面两个都是大神张继瑞开源。
③cJSON.c是一个用于处理JSON数据格式的轻量级C语言库,JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,常用于在不同系统之间传输和存储数据。在对云平台下发数据进行解析时会用到(onenet.c)。
在这里插入图片描述

2、获取服务器数据上:

******使用http协议和MQTT协议连接onenet,最大的不同就是获取onenet云平台数据的方式:
http协议:直接构建HTTP请求报文并调用esp8266_send_data函数发送HTTP请求,并获取返回的字符串。
mqtt协议:不主动发送请求,使用ESP8266_WaitRecive函数等待,如果云平台有数据下发,那就存起来当作变量传入OneNet_RevPro函数,进行消息解析。

3、架构上:

在这里插入图片描述
"请求/响应"和"发布/订阅"是两种不同的通信模式,它们在系统架构和通信方式上有所不同。
①请求/响应:
特点: 在请求/响应模式中,通信的一方发送请求,而另一方回复响应。通信是单向的,有一个明确的请求者和一个响应者。
用途: 这种模式常见于客户端和服务器之间的通信。客户端发送请求,服务器处理请求并返回相应的响应。
②发布/订阅:
特点: 在发布/订阅模式中,消息的发布者将消息发送到一个主题(topic),而订阅者可以选择订阅特定主题以接收相关消息。通信是多对多的,发布者和订阅者之间是松耦合的。
用途: 这种模式常见于事件驱动系统、消息中间件和实时数据更新场景。发布者发布消息到主题,所有订阅该主题的订阅者都会收到消息。
由以上分析很容易得出一个结论:在做环境信息检测这种实时数据更新的项目上,使用MQTT协议更具优势。

四、下位机主要代码

1、接收并解析云平台下发数据:

主循环中使用以下代码接收并跳转:

		dataPtr = ESP8266_GetIPD(10);
		if(dataPtr != NULL)
		{
			timeCount = 0;
			OneNet_RevPro(dataPtr);
		
		}

接收到数据后跳转至onenet.c的OneNet_RevPro函数中进行mqtt数据包(报文)解包和数据解析:

void OneNet_RevPro(unsigned char *cmd)
{
	
	MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0};								//协议包
	
	char *req_payload = NULL;
	char *cmdid_topic = NULL;
	
	unsigned short req_len = 0;
  unsigned char type = 0;

	short result = 0;

	char *dataPtr = NULL;
	char numBuf[10];
	int num = 0;

	
	cJSON *json , *json_value;
  cJSON *json1, *json_value1;
  cJSON *json2, *json_value2;

	type = MQTT_UnPacketRecv(cmd);

	switch(type)
	{
		case MQTT_PKT_CMD:															//命令下发
			OLED_Refresh_Line("jinru111");
			result = MQTT_UnPacketCmd(cmd, &cmdid_topic, &req_payload, &req_len);	//解出topic和消息体
			if(result == 0)
			{
				//打印收到的信息
				printf(  "cmdid: %s, req: %s, req_len: %d\r\n", cmdid_topic, req_payload, req_len);
				
				// 对数据包req_payload进行JSON格式解析
				json = cJSON_Parse(req_payload);
				
				if (!json)//如果json内容为空,则打印错误信息
					printf("Error before: [%s]\n",cJSON_GetErrorPtr());
				else
				{
					json_value = cJSON_GetObjectItem(json , "LED0");//提取对应属性的数值
					
					if((json_value->valueint)==1)
					{
						GPIO_SetBits(GPIOB,GPIO_Pin_12);	
					}
					else if((json_value->valueint)==0)			
						GPIO_ResetBits(GPIOB,GPIO_Pin_12);	
				}
				//开关风扇
				json1 = cJSON_Parse(req_payload);
				if (!json1)
					printf("Error before: [%s]\n",cJSON_GetErrorPtr());
				else
				{
					json_value1 = cJSON_GetObjectItem(json1 , "feng");

					if((json_value1->valueint)==1)
					
						GPIO_SetBits(GPIOB,GPIO_Pin_5);	
					
					else if((json_value1->valueint)==0)
						
						GPIO_ResetBits(GPIOB,GPIO_Pin_5);	
				
				}
				//开关水泵
				json2 = cJSON_Parse(req_payload);
				if (!json2)
					printf("Error before: [%s]\n",cJSON_GetErrorPtr());
				else
				{
					json_value2 = cJSON_GetObjectItem(json2 , "shui");

					if((json_value2->valueint)==1)
					{
						GPIO_SetBits(GPIOB,GPIO_Pin_6);	
					}
					else if((json_value2->valueint)==0)
						GPIO_ResetBits(GPIOB,GPIO_Pin_6);	
				
				}

				if(MQTT_PacketCmdResp(cmdid_topic, req_payload, &mqttPacket) == 0)	//命令回复组包
				{
					printf( "Tips:	Send CmdResp\r\n");
					
					ESP8266_SendData(mqttPacket._data, mqttPacket._len);			//回复命令
					MQTT_DeleteBuffer(&mqttPacket);									//删包
				}
				cJSON_Delete(json);//释放位于堆中cJSON结构体内存
				cJSON_Delete(json1);
			}
		
		break;
			
		case MQTT_PKT_PUBACK:														//发送Publish消息,平台回复的Ack
		
			if(MQTT_UnPacketPublishAck(cmd) == 0)
				//printf(  "Tips:	MQTT Publish Send OK\r\n");
			
		break;
		
		default:
			result = -1;
		break;
	}
	
	ESP8266_Clear();									//清空缓存
	
	if(result == -1)
		return;
	
	dataPtr = strchr(req_payload, ':');					//搜索'}'

	if(dataPtr != NULL && result != -1)					//如果找到了
	{
		dataPtr++;
		
		while(*dataPtr >= '0' && *dataPtr <= '9')		//判断是否是下发的命令控制数据
		{
			numBuf[num++] = *dataPtr++;
		}
		numBuf[num] = 0;
		
		num = atoi((const char *)numBuf);				//转为数值形式
	}

	
	
	if(type == MQTT_PKT_CMD || type == MQTT_PKT_PUBLISH)
	{
		MQTT_FreeBuffer(cmdid_topic);
		MQTT_FreeBuffer(req_payload);
	}
}

2、传感器数据上云:

主函数中读取传感器数值,每隔一段时间上传:

		else if(timeCount >= 100)	//发送间隔
		{
			DHT11_Read_Data(&tempValue,&humidity);
			gas = AD_GetValue(ADC_Channel_2);
			ranqi = AD_GetValue(ADC_Channel_3);

			delay_ms(10);
					
			OneNet_SendData();//发送数据给onenet
			ESP8266_Clear();	
			timeCount = 0;
		}

调用OneNet_SendData发送数据,在OneNet_SendData函数中又调用OneNet_FillBuf函数将要发送的数据拼接起来。

unsigned char OneNet_FillBuf(char *buf)
{
	
	char text[32];
	
	//LED0_FLAG=GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12);//读取LED的开关状态(即对应引脚的)
	//LED1_FLAG=GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);

	memset(text, 0, sizeof(text));
	
	strcpy(buf, ",;");
	
	memset(text, 0, sizeof(text));
	sprintf(text, "Tempreture,%d;",tempValue);
	strcat(buf, text);
	
	memset(text, 0, sizeof(text));
	sprintf(text, "Humidity,%d;", humidity);
	strcat(buf, text);
	
	memset(text, 0, sizeof(text));
	sprintf(text, "tianranqi,%d;", gas);
	strcat(buf, text);
	
	memset(text, 0, sizeof(text));
	sprintf(text, "keranqiti,%d;", ranqi);
	strcat(buf, text);
	
	printf("buf_mqtt=%s\r\n",buf);
	return strlen(buf);

}

//==========================================================
//	函数名称:	OneNet_SendData
//
//	函数功能:	上传数据到平台
//
//	入口参数:	type:发送数据的格式
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void OneNet_SendData(void)
{
	
	MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0};												//协议包
	
	char buf[128];
	
	short body_len = 0, i = 0;
	
	//printf( "Tips:	OneNet_SendData-MQTT\r\n");
	
	memset(buf, 0, sizeof(buf));//清空数组内容
	
	body_len = OneNet_FillBuf(buf);																	//获取当前需要发送的数据流的总长度
	
	if(body_len)
	{
		if(MQTT_PacketSaveData(DEVID, body_len, NULL, 5, &mqttPacket) == 0)							数据点上传组包,将数据封装成mqtt协议所要求的数据包格式
		{
		{
			for(; i < body_len; i++)
				mqttPacket._data[mqttPacket._len++] = buf[i];
			
			ESP8266_SendData(mqttPacket._data, mqttPacket._len);									//上传数据到平台
			printf( "Send %d Bytes\r\n", mqttPacket._len);
			
			MQTT_DeleteBuffer(&mqttPacket);															//删包
		}
		else{
			printf(  "WARN:	EDP_NewBuffer Failed\r\n");
		}
	}
	
}

五、微信小程序主要代码

在这里插入图片描述
图中圈起来的地方需要根据自己的数据进行填写,在下面的调试信息栏可以看到有数据上传,查看数据流即可:
在这里插入图片描述

1、index.js

主要是增加了控制风扇和水泵的代码:

feng_kai:function(){
  //按钮发送命令控制硬件
   wx.request({
     url:'https://api.heclouds.com/cmds?device_id=1108129261',
     header: {
       'content-type': 'application/json',
       'api-key':'nV4Cso3uQMZR2EGQQiY49MRCfx8='
     },
     method: 'POST',
     data:{"feng":1},
     success(res){
       console.log("成功",res.data)
     },
     fail(res){
       console.log("失败",res)
     }
   })
},

feng_guan:function(){
  //按钮发送命令控制硬件
   wx.request({
     url:'https://api.heclouds.com/cmds?device_id=1108129261',
     header: {
       'content-type': 'application/json',
       'api-key':'nV4Cso3uQMZR2EGQQiY49MRCfx8='
     },
     method: 'POST',
     data:{"feng":0},
     success(res){
       console.log("成功",res.data)
     },
     fail(res){
       console.log("失败",res)
     }
   })
},

shui_kai:function(){
  //按钮发送命令控制硬件
   wx.request({
     url:'https://api.heclouds.com/cmds?device_id=1108129261',
     header: {
       'content-type': 'application/json',
       'api-key':'nV4Cso3uQMZR2EGQQiY49MRCfx8='
     },
     method: 'POST',
     data:{"shui":1},
     success(res){
       console.log("成功",res.data)
     },
     fail(res){
       console.log("失败",res)
     }
   })
},

shui_guan:function(){
  //按钮发送命令控制硬件
   wx.request({
     url:'https://api.heclouds.com/cmds?device_id=1108129261',
     header: {
       'content-type': 'application/json',
       'api-key':'nV4Cso3uQMZR2EGQQiY49MRCfx8='
     },
     method: 'POST',
     data:{"shui":0},
     success(res){
       console.log("成功",res.data)
     },
     fail(res){
       console.log("失败",res)
     }
   })
},

需要注意的是这里的url需要更换成:‘https://api.heclouds.com/cmds?device_id=11081xxxxxx’,并且文件开头的apikey和设备号也要换成自己的。

2、index.wxml

最后加上:

<button type="primary" style="margin-top: 20px;" bindtap="feng_kai">开风扇</button>
<button type="warn" bindtap="feng_guan">关风扇</button>

<button type="primary" style="margin-top: 20px;" bindtap="shui_kai">开水泵</button>
<button type="warn" bindtap="shui_guan">关水泵</button>

六、源码获取

我用夸克网盘分享了「智能家居(MQTT+ONENET).rar」,点击链接即可保存。打开「夸克APP」,无需下载在线播放视频,畅享原画5倍速,支持电视投屏。
链接:https://pan.quark.cn/s/db251fd599bd
提取码:9sR9

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1422075.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android悬浮窗实现步骤

最近想做一个悬浮窗秒表的功能&#xff0c;所以看下悬浮窗具体的实现步骤 1、初识WindowManager 实现悬浮窗主要用到的是WindowManager SystemService(Context.WINDOW_SERVICE) public interface WindowManager extends ViewManager {... }WindowManager是接口类&#xff0c…

Observability:在 Elastic Stack 8.12 中使用 Elastic Agent 性能预设

作者&#xff1a;来自 Elastic Nima Rezainia, Bill Easton 8.12 中 Elastic Agent 性能有了重大改进 最新版本 8.12 标志着 Elastic Agent 和 Beats 调整方面的重大转变。 在此更新中&#xff0c;Elastic 引入了 Performance Presets&#xff0c;旨在简化用户的调整过程并增强…

计算机网络_1.3电路交换、分组交换和报文交换

1.3电路交换、分组交换和报文交换 一、电路交换1、“电路交换”例子引入2、电路交换的三个阶段3、计算机之间的数据传送不适合采用电路交换 二、分组交换1、发送方&#xff08;1&#xff09;报文&#xff08;2&#xff09;分组&#xff08;3&#xff09;首部 2、交换节点3、接收…

机器学习模型预测贷款审批

机器学习模型预测贷款审批 作者&#xff1a;i阿极 作者简介&#xff1a;数据分析领域优质创作者、多项比赛获奖者&#xff1a;博主个人首页 &#x1f60a;&#x1f60a;&#x1f60a;如果觉得文章不错或能帮助到你学习&#xff0c;可以点赞&#x1f44d;收藏&#x1f4c1;评论&…

CHS_05.2.3.4_1+信号量机制

CHS_05.2.3.4_1信号量机制 知识总览信号量机制信号量机制——整型信号量信号量机制——记录型信号量知识回顾 在这个小节中 我们会学习信号量 机制这个极其重要的知识点 知识总览 在考研当中 我们需要掌握两种类型的信号量 一种是整形信号量 另一种是记录型信号量 我们会在后面…

AsyncLocal是如何实现在Thread直接传值的?

一&#xff1a;背景 1. 讲故事 这个问题的由来是在.NET高级调试训练营第十期分享ThreadStatic底层玩法的时候&#xff0c;有朋友提出了AsyncLocal是如何实现的&#xff0c;虽然做了口头上的表述&#xff0c;但总还是会不具体&#xff0c;所以觉得有必要用文字图表的方式来系统…

Camunda简介

&#x1f496;专栏简介 ✔️本专栏将从Camunda(卡蒙达) 7中的关键概念到实现中国式工作流相关功能。 ✔️文章中只包含演示核心代码及测试数据&#xff0c;完整代码可查看作者的开源项目snail-camunda ✔️请给snail-camunda 点颗星吧&#x1f618; &#x1f496;系列文章 …

【PyTorch实战演练】Fast R-CNN中的RoI(Region of Interest)池化详解

文章目录 0. 前言1. ROI池化的提出背景2. RoI池化的结构与工作原理3. RoI池化的作用及意义4. RoI使用示例 0. 前言 按照国际惯例&#xff0c;首先声明&#xff1a;本文只是我自己学习的理解&#xff0c;虽然参考了他人的宝贵见解及成果&#xff0c;但是内容可能存在不准确的地方…

Linux第40步_移植ST公司uboot的第1步_创建配置文件_设备树_修改电源管理和sdmmc节点

ST公司uboot移植分两步走&#xff1a; 第1步&#xff1a;完成“创建配置文件&#xff0c;设备树&#xff0c;修改电源管理和sdmmc节点&#xff0c;以及shell脚本和编译”。 第2步“完成”修改网络驱动、USB OTG设备树和LCD驱动&#xff0c;以及编译和烧写测试“。 移植太复杂…

Spring 中获取 Bean 对象的三种方式

目录 1、根据名称获取Bean 2、根据Bean类型获取Bean 3、根据 Bean 名称 Bean 类型来获取 Bean&#xff08;好的解决方法&#xff09; 假设 Bean 对象是 User&#xff0c;并存储到 Spring 中&#xff0c;注册到 xml 文件中 public class User {public String sayHi(){retur…

小型洗衣机什么牌子好又便宜?家用内衣洗衣机推荐

近几年家用洗衣机标准容积的大大增加&#xff0c;从5Kg、6Kg升级到9Kg、10Kg。大容量洗衣机满足了家庭中清洗大件衣物、床上用品的需求。但由于普通大型洗衣机所洗衣物混杂&#xff0c;很多时候内衣袜子、宝宝衣物数量不多&#xff0c;却也并不适合放在一起扔进大型洗衣机中清洗…

关于maven项目构建的解释

在Idea中使用模块化构建项目 项目介绍&#xff1a; sky-take-out sky-common pom.xml sky-pojo pom.xml sky-server pom.xml pom.xml 说明 sky-server依赖sky-pojo和sky-common&#xff0c;继承sky-take-outsky-pojo继承sky-take-outsky-common继承sky-take-out 由于Idea编…

“二奢”已成为年轻人新年货

配图来自Canva可画 正应了那句流行语&#xff1a;“不是全新买不起&#xff0c;而是二奢更有性价比。” 现今&#xff0c;“买二手、用二手”不再是什么让人难以启齿的事情&#xff0c;反而被越来越多年轻人推崇&#xff0c;二奢消费已然成为一种流行的生活方式。人们积极通过…

向上调整向下调整算法

目录 AdjustUp向上调整 AdjustDown向下调整 AdjustUp向上调整 前提是&#xff1a;插入数据之后&#xff0c;除去插入的数据其他的数据还是为堆 应用&#xff1a;插入数据。 先插入一个10到数组的尾上&#xff0c;再进行向上调整算法&#xff0c;直到满足堆。 性质&#xff1…

2024年网络安全趋势简析

国际研究机构Gartner会在每年10月份左右发布下一年度的战略发展趋势预测&#xff0c;并在次年3月左右发布和网络安全相关的趋势预测。绿盟科技通过将近3年的趋势预测进行分组对比分析后发现&#xff0c;除了众人皆知的AI技术应用外&#xff0c;数据模块化、身份优先安全、行业云…

力扣 122.买卖股票的最佳时机 II

代码&#xff1a; class Solution { public:int maxProfit(vector<int>& prices) {if(prices.size()1) return 0;int res 0;int i0;while(i<prices.size()-1){int ji1;if(prices[j]>prices[i]){//在找到对应元素的下一个元素比他大的时候买入while(j1 < p…

python222网站实战(SpringBoot+SpringSecurity+MybatisPlus+thymeleaf+layui)-菜单管理实现

锋哥原创的SpringbootLayui python222网站实战&#xff1a; python222网站实战课程视频教程&#xff08;SpringBootPython爬虫实战&#xff09; ( 火爆连载更新中... )_哔哩哔哩_bilibilipython222网站实战课程视频教程&#xff08;SpringBootPython爬虫实战&#xff09; ( 火…

uniapp状态管理Vuex介绍及vuex核心概念

状态管理Vuex Vuex 是什么&#xff1f; Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。 uni-app 内置了 Vuex 什么是“状态管理模式”&#xff1f; <!…

集成学习之Boosting方法系列_XGboost

文章目录 【文章系列】【前言】【算法简介】【正文】&#xff08;一&#xff09;XGBoost前身&#xff1a;梯度提升树&#xff08;二&#xff09;XGBoost的特点&#xff08;三&#xff09;XGBoost实际操作1. 前期准备&#xff08;1&#xff09;数据格式&#xff08;2&#xff09…

使用Banana Pi BPI-R4开发板实现5G上网、Wi-Fi AP、文件共享和Docker服务

转载&#xff1a;本文出处https://think8848.cnblogs.com和作者: think8848 本文目的&#xff1a;记录近一个月以来折腾BPI-R4的过程&#xff0c;为后面可能的学习提供参考资料&#xff0c;此外也把折腾中踩过的坑发出来&#xff0c;让更多研究BPI-R4的筒子们少踩坑。 一、需求…