智能家居的OneNet云平台

发布于:2025-05-09 ⋅ 阅读:(18) ⋅ 点赞:(0)

一、声明

        该项目只需要创建一个产品,然后这个产品里面包含几个设备,而不是直接创建几个产品

        注意:传输数据使用到了不同的power,还有一定要手机先联网才能使用云平台

二、OneNet云平台创建

(1)创建一个产品

第一步:OneNet网站登录,然后进入开发者中心

第二步:在产品开发里面选择创建产品,注意联网方式是wifi,开发方案是自定义方案

        这个里面的设备名称不一定要是英文,可以是中文,也就是这个项目的大标题

第三步:添加设备

          在产品开发的设备管理里面添加设备      

          记得!!!这个里面的设备名称就是需要用英文的!!!也就是MQTT协议里面用到的设备ID!!!

第四步:在产品开发的产品开发里面设置物模型,也就是我们要传输的四个数据

        到这里我们产品创建得差不多了,接下来就是需要获取信息,为后面写代码做准备

(2)获取信息

设备名称:zhinengjiaju

设备密钥:Q1g0ZU1ETnpsd21TR0IwaGVHbnlXMzF2RUwwVmRtSEo=

产品ID:zv9My9QY4s

(下面这两个是通用的,然后有一个工具需要在官网去下载,这个可以看之前的CSDN)

url:mqtts.heclouds.com

端口号:1883

时间戳:2052911776

res:products/zv9My9QY4s/devices/zhinengjiaju

et:2052911776

key:Q1g0ZU1ETnpsd21TR0IwaGVHbnlXMzF2RUwwVmRtSEo=

password:version=2018-10-31&res=products%2Fzv9My9QY4s%2Fdevices%2Fzhinengjiaju&et=2052911776&method=md5&sign=0%2Fh%2F1yGDE3aGxdo%2FcVZTyA%3D%3D

订阅:$sys/zv9My9QY4s/zhinengjiaju/thing/property/post/reply

发布:$sys/zv9My9QY4s/zhinengjiaju/thing/property/post

(3)串口调试(这一步可以判断设备有没有调试好)

        首先如果发送出来的东西不正常看看是不是波特率有问题,波特率是115200

        要是还有问题,就换几个端口重新试几次

        如果还是有问题就重新刷一下固件库,刷固件库的之后记得用辰哥单片机的烧入软件,再用专门的烧录器,这样能够省很多没必要的麻烦。选好下载速度115200,选好串口的端口,其他的都不改变,直接烧录就行

        如果固件库刷完了,还是在连上热点之后出问题的话,那么可能出现的问题就是串口发送的代码有问题,自己再好好检查一下ID,设备名称之类的信息有没有改正确

        最后一行的power就是标识符,设置物模型时候写的什么标识符,在这里写什么标识符就可以了,后面的那个25就是发送的数据

AT
 
AT+RST
 
AT+CWMODE=1
 
AT+CWDHCP=1,1
 
AT+CWJAP="iPhone","123456789"
 
AT+MQTTUSERCFG=0,1,"zhinengjiaju","zv9My9QY4s","version=2018-10-31&res=products%2Fzv9My9QY4s%2Fdevices%2Fzhinengjiaju&et=2052911776&method=md5&sign=0%2Fh%2F1yGDE3aGxdo%2FcVZTyA%3D%3D",0,0,""
 
AT+MQTTCONN=0,"mqtts.heclouds.com",1883,1
 
AT+MQTTSUB=0,"$sys/zv9My9QY4s/zhinengjiaju/thing/property/post/reply",1
 
AT+MQTTPUB=0,"$sys/zv9My9QY4s/zhinengjiaju/thing/property/post","{\"id\":\"123\"\,\"params\":{\"power1\":{\"value\":25\}}}",0,0

        如果以上的步骤都没有问题,说明云平台创建正确,esp01s工作正常。那么就可以在接下来进行单片机发数据了

(三)单片机发数据

esp01s.c

        这个头文件有点问题,后续改改就行了

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

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

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

//C库
#include <string.h>
#include <stdio.h>
#include <string.h>
 

#define ESP01S_WIFI_INFO		"AT+CWJAP=\"iPhone\",\"123456789\"\r\n"
const char* ClintID="zhinengjiaju";
const char* username="zv9My9QY4s";
const char* passwd="version=2018-10-31&res=products%2Fzv9My9QY4s%2Fdevices%2Fzhinengjiaju&et=2052911776&method=md5&sign=0%2Fh%2F1yGDE3aGxdo%2FcVZTyA%3D%3D";
const char* Url="mqtts.heclouds.com";
const char* pubtopic="$sys/zv9My9QY4s/zhinengjiaju/thing/property/post";
const char* subtopic="$sys/zv9My9QY4s/zhinengjiaju/thing/property/post/reply";
const char* func1="temperature";
const char* func2="humidity";
const char* func3="light";
const char* func4="MQ135";

unsigned char ESP01S_buf[256];
unsigned short ESP01S_cnt = 0, ESP01S_cntPre = 0;



uint8_t aRxBuffer;			//接收中断缓冲
//==========================================================
//	函数名称:	ESP01S_Clear
//
//	函数功能:	清空缓存
//
//	入口参数:	无
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void ESP01S_Clear(void)
{

	memset(ESP01S_buf, 0, sizeof(ESP01S_buf));
	ESP01S_cnt = 0;

}

//==========================================================
//	函数名称:	ESP01S_WaitRecive
//
//	函数功能:	等待接收完成
//
//	入口参数:	无
//
//	返回参数:	REV_OK-接收完成		REV_WAIT-接收超时未完成
//
//	说明:		循环调用检测是否接收完成
//==========================================================
_Bool ESP01S_WaitRecive(void)
{

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

}

//==========================================================
//	函数名称:	ESP01S_SendCmd
//
//	函数功能:	发送命令
//
//	入口参数:	cmd:命令
//				res:需要检查的返回指令
//
//	返回参数:	0-成功	1-失败
//
//	说明:		
//==========================================================
_Bool ESP01S_SendCmd(char *cmd, char *res)
{
	
	unsigned char timeOut = 200;

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

}



//==========================================================
//	函数名称:	ESP01S_Init
//
//	函数功能:	初始化ESP01S
//
//	入口参数:	无
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void ESP01S_Init(void)
{
	char cmdBuf[512];
	
	ESP01S_Clear();
	
	UsartPrintf(USART_DEBUG, "0. AT\r\n");
	while(ESP01S_SendCmd("AT\r\n", "OK"))
		HAL_Delay(500);
	
	UsartPrintf(USART_DEBUG, "1. RST\r\n");
	ESP01S_SendCmd("AT+RST\r\n", "");
        HAL_Delay(500);	
	
	
	UsartPrintf(USART_DEBUG, "2. CWMODE\r\n");
	while(ESP01S_SendCmd("AT+CWMODE=1\r\n", "OK"))     //模式1(Station),默认保存Flash
		HAL_Delay(500);
	
	UsartPrintf(USART_DEBUG, "3. AT+CWDHCP\r\n");       //开启DHCP(获取分配IP),默认保存Flash
	while(ESP01S_SendCmd("AT+CWDHCP=1,1\r\n", "OK"))  
		HAL_Delay(500);
	
	UsartPrintf(USART_DEBUG, "4. CWJAP\r\n");           //链接WIFI
	while(ESP01S_SendCmd(ESP01S_WIFI_INFO, "OK"))
		HAL_Delay(500);

	
	UsartPrintf(USART_DEBUG, "5.MQTTUSERCFG\r\n");           //用户信息配置
	sprintf(cmdBuf,"AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"\r\n", ClintID,username,passwd);
	while(ESP01S_SendCmd(cmdBuf, "OK"))
	HAL_Delay(500);
	memset(cmdBuf,0,sizeof(cmdBuf));
	
	UsartPrintf(USART_DEBUG, "6.MQTTCONN\r\n");           //连接服务器
	sprintf(cmdBuf,"AT+MQTTCONN=0,\"%s\",1883,1\r\n",Url);
	while(ESP01S_SendCmd(cmdBuf, "OK"))
	HAL_Delay(500);
	memset(cmdBuf,0,sizeof(cmdBuf));
	
	
	UsartPrintf(USART_DEBUG, "7.MQTTSUB\r\n");           //订阅消息
	sprintf(cmdBuf,"AT+MQTTSUB=0,\"%s\",1\r\n",subtopic);
	while(ESP01S_SendCmd(cmdBuf, "OK"))
	HAL_Delay(500);
	memset(cmdBuf,0,sizeof(cmdBuf));
}


//功能:esp发送消息
//参数:无
//返回值:0:发送成功;1:发送失败
void Esp_PUB(int value1,int value2,int value3,int value4)
{
	
	char cmdBuf[256];
	UsartPrintf(USART_DEBUG, "Publish\r\n");           //订阅消息
//  sprintf(cmdBuf,"AT+MQTTPUB=0,\"%s\",\"{\\\"id\\\":\\\"123\\\"\\,\\\"params\\\":{\\\"%s\\\":{\\\"value\\\":%d\\}}}\",0,0\r\n",pubtopic,func1,value1);
  sprintf(cmdBuf,"AT+MQTTPUB=0,\"%s\",\"{\\\"id\\\":\\\"123\\\"\\,\\\"params\\\":{\\\"%s\\\":{\\\"value\\\":%d\\}\\,\\\"%s\\\":{\\\"value\\\":%d\\}\\,\\\"%s\\\":{\\\"value\\\":%d\\}\\,\\\"%s\\\":{\\\"value\\\":%d\\}}}\",0,0\r\n",pubtopic,func1,value1,func2,value2,func3,value3,func4,value4);
	while(ESP01S_SendCmd(cmdBuf, "OK"))
	HAL_Delay(500);
	memset(cmdBuf,0,sizeof(cmdBuf));
	HAL_Delay(100);
	
}





/* USER CODE BEGIN 4 */
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  
    UNUSED(huart);
 
	if(ESP01S_cnt >= sizeof(ESP01S_buf))  //溢出判断
	{
		ESP01S_cnt = 0;
		memset(ESP01S_buf,0x00,sizeof(ESP01S_buf));
		HAL_UART_Transmit(&huart1, (uint8_t *)"接收缓存溢出", 10,0xFFFF); 	      
	}
	else
	{
		ESP01S_buf[ESP01S_cnt++] = aRxBuffer;   //接收数据转存	
//		  if(aRxBuffer=='1')  HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET);
//        if(aRxBuffer=='0')  HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);
 	}
	
	HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);   //再开启接收中断
}


/* USER CODE END 4 */

        这个里面最难写的就是发送数据,如果要分开写发送数据的话,那么要连四次热点才能把四个数据全都给发出去,所以只写一个发送数据,但是一次最多只能发五个数据。稍微根据这个代码改改就行了

        参考发数据的模式可以参考姜帆的代码,我自己的代码,还有B站上给这个代码的博主

sprintf(cmdBuf,"AT+MQTTPUB=0,\"%s\",\"{\\\"id\\\":\\\"123\\\"\\,\\\"params\\\":{\\\"%s\\\":{\\\"value\\\":%d\\}}}\",0,0\r\n",pubtopic,func1,power);
sprintf(cmdBuf,"AT+MQTTPUB=0,\"%s\",\"{\\\"id\\\":\\\"123\\\"\\,\\\"params\\\":{\\\"%s\\\":{\\\"value\\\":%d\\}\\,\\\"%s\\\":{\\\"value\\\":%d\\}\\,\\\"%s\\\":{\\\"value\\\":%d\\}\\,\\\"%s\\\":{\\\"value\\\":%d\\}}}\",0,0\r\n",pubtopic,func1,value1,func2,value2,func3,value3,func4,value4);
sprintf(cmdBuf,"AT+MQTTPUB=0,\"%s\",\"{\\\"id\\\":\\\"123\\\"\\,\\\"params\\\":{\\\"%s\\\":{\\\"value\\\":%d\\}\\,\\\"%s\\\":{\\\"value\\\":%d\\}\\,\\\"%s\\\":{\\\"value\\\":%d\\}\\,\\\"%s\\\":{\\\"value\\\":%d\\}\\,\\\"%s\\\":{\\\"value\\\":%d\\}}}\",0,0\r\n",pubtopic,func1,value1,func2,value2,func3,value3,func4,value4,func5,value5);

esp01s.h

#ifndef _ESP8266_H_
#define _ESP8266_H_
#include <string.h>
#include <stdio.h>
#include <stdint.h>

#define REV_OK		0	//接收完成标志
#define REV_WAIT	1	//接收未完成标志

void ESP01S_Init(void);
void ESP01S_Clear(void);
//void ESP01S_SendData(unsigned char *data, unsigned short len);
//unsigned char *ESP01S_GetIPD(unsigned short timeOut);
void Esp_PUB(int value1,int value2,int value3,int value4);
#endif

(1)CubeMx的配置

        串口1用来和电脑通信

        最开始是用来判断串口是否正常工作,后面可以用来判断单片机和esp01s有没有正常通信成功

        这个可以不用开串口接收中断

        这就是串口助手发回来的数据,通过串口1发回来的,由此可以看到esp01s有没有成功连上手机,只有成功连上之后才能发数据给云平台

        串口2是用来给onenet发数据

        这个我具体不知道是怎样的一个工作原理,但是串口2就是单片机和esp01s进行通信,串口1 就是单片机和电脑进行通信

        这个就要注意开一下中断了

(2)keil.5的配置

        首先我前面已经把esp01s.c和esp01s.h的代码已经写上去了。但是这个代码直接写上去是会报错的,所以需要在usart.c和usart.h里面添加代码

void Usart_SendString(UART_HandleTypeDef USARTx, unsigned char *str, unsigned short len)
{

	unsigned short count = 0;
	
	for(; count < len; count++)
	{
		HAL_UART_Transmit (&USARTx ,(uint8_t *)str++,1,HAL_MAX_DELAY );									
	}

}

void UsartPrintf(UART_HandleTypeDef USARTx, char *fmt,...)
{
 
	unsigned char UsartPrintfBuf[296];
	va_list ap;
	unsigned char *pStr = UsartPrintfBuf;
	
	va_start(ap, fmt);
	vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);							
	va_end(ap);
	
	while(*pStr != NULL)
	{
        HAL_UART_Transmit (&USARTx ,(uint8_t *)pStr++,1,HAL_MAX_DELAY );		
	}
 
}

#include <stdarg.h>
#include "stdio.h"
#define USART_DEBUG		huart1	
void Usart_SendString(UART_HandleTypeDef USARTx, unsigned char *str, unsigned short len);
void UsartPrintf(UART_HandleTypeDef USARTx, char *fmt,...);

        上述代码添加完之后调用esp01s的文件就不会出错了

main.c文件

	UsartPrintf(USART_DEBUG, "The USART1 is OK!\r\n");
	HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1); 
	ESP01S_Init();  
	ESP01S_Clear(); 
	UsartPrintf(USART_DEBUG, "Init is OK!\r\n");
Esp_PUB(temp,humi,Light_val,MQ135_val);

        这一行代码里面的temp,humi这些数据要在main.c里面定义。因为onenet里面传输的数据是int32类型,所以这里定义的类型也是int32的数据

/* USER CODE BEGIN Includes */

#include "dht11.h"
#include "oled.h"
#include "mq135.h"
#include "gy302.h"
#include "esp8266.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

extern uint8_t aRxBuffer;			
int32_t temp;
int32_t humi;
int32_t Light_val;
int32_t MQ135_val;

/* USER CODE END PTD */

        在dht11等温湿度、光照、大气压的代码里面传输的数据就声明使用就可以

        main.c的代码

        这个里面是整个智能家居的所以外设的运行代码

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "i2c.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

#include "dht11.h"
#include "oled.h"
#include "mq135.h"
#include "gy302.h"
#include "esp8266.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

extern uint8_t aRxBuffer;			
int32_t temp;
int32_t humi;
int32_t Light_val;
int32_t MQ135_val;

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_I2C1_Init();
  MX_TIM4_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */

	OLED_Init();
	
  HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_3);
	
	
	UsartPrintf(USART_DEBUG, "The USART1 is OK!\r\n");
	HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1); 
	ESP01S_Init();  
	ESP01S_Clear(); 
	UsartPrintf(USART_DEBUG, "Init is OK!\r\n");
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		
		
		DHT11();
		
		MQ135_Init();
		MQ135_ReadData();
	
		Value_GY30();	
	 
		Esp_PUB(temp,humi,Light_val,MQ135_val);
		
  }
  /* USER CODE END 3 */
}

        最后一个问题就是我没有学会如何加上freertos来让执行起来更快,我也不知道为什么加上esp01s发数据之后,oled就不显示了,要等到连上手机热点之后才会显示,而且比以前要卡一些 

        


网站公告

今日签到

点亮在社区的每一天
去签到