饮水机加入Onenet联网代码实操

饮水机加入Onenet联网代码实操

引言

饮水机联网调试变量解析

在上一讲, 我们已经分析了 饮水机各个功能的调试方法, 并且确定了需要调试的变量, 这次我们就进行Onenet的代码实操, 加入联网工程代码, 主要是走个流程.

我们加入联网, 主要是把这些变量,上传到服务器, 让我们可视化的实时的观察单片机的内部变量状态。

把变量上传到服务器实时观察, 就取代了oled在屏幕上, 观察变量

同时我们要修改其中的变量, 所以我们就要在服务器下发修改变量的值, 然后单片机拆包解析后, 赋予本地变量。

服务器下发指令, 就代替了, 调试时候的赋予变量和按键赋值, 更具有灵活性

加入工程, 参考示例步骤:

手把手stm32与Onenet联网配置步骤

上面的示例步骤是物联网预警系统的, 我们只是变量不同罢了, 所以只需要更改相关的标识符就可以了.

所以我们比葫芦画瓢就可以了.在掌握了上面的联网工程后, 后面就会很简单, 我们直接忽略详细步骤, 只讲 饮水机和预警系统, 赋值的不同的变量的部分, 站在已经能够掌握整个流程的角度来, 如何快速复制黏贴.

本项目调试好的工程代码(后面是从头开始操作,这是成品):

跳转下载

https://wwyz.lanzoul.com/i3Wn728iriji

本地工程加入联网

无联网本地饮水机工程

点击跳转下载

https://wwyz.lanzoul.com/i6fZu28he71a

饮水机联网工程文件

点击跳转下载

回去(ctrl 加鼠标左键,快速跳转)

https://wwyz.lanzoul.com/ix8Ys28heg4h

需要上传的变量整理

加热系统

回去(ctrl 加鼠标左键,快速跳转)

需要上传

//水温
water_temp
//加热阈值
heat_temp_th
//保温阈值
KeepWarm_th
//加热模式
heat_mode

image-20240826163334910

饮水系统

我们根据饮水机的童锁和红外的交互功能, 来判断, 是否可以控制底层开启水龙头

image-20240826175716062

image-20240826215853205

上图, 描述了他们之间的关系, 代码中也体现了出来, 所以我们上传的变量分别是

//童锁状态
child_lock_info.Status
//杯子是否放置
cup_place_info.Status
//水龙头出水状态    
out_water_info.Status   

Onenet服务器产品创建

1.官网

OneNET - 中国移动物联网开放平台 (10086.cn)

2.登录注册

注意, 密码的特殊符号是 @ 其他标点不行

3.进入Onenet产品开发

如果找不到, 就直接把这个链接放在导航栏直接回车

产品开发 - OneNET物联网平台 (10086.cn)

https://open.iot.10086.cn/console/product/own

image-20240827094719136

4.点击创建产品

image-20240827094814899

5.产品分类->其他行业->其他行业->其他类别

image-20240827101405078

6.产品名称:饮水机示例

所属城市:随便填

节点类型: 直连设备

接入协议: MQTT

数据协议: OneJson

联网方式: wifi

开发方案: 自定义方案

image-20240827101625703

7.根据所需变量设置对应的物模型

image-20240827101836831

image-20240827102510213

8.变量对应的物模型

本地变量(ctrl 加鼠标左键,快速跳转)

一般情况下, 服务器物模型标识符可以设置成和本地一样, 这样方便, 但是如果我们使用结构体的话, 直接使用会造成变量太长, 所以我们可以换其他简短的意思一样的变量就行, 相当于取了一个代号, 到时候服务器下发控制变量也会按照这个标识符进行下发, 我们单片机解析的时候,记得按照Onenet设置的这个简短标识符进行拆包解析就行了.

<1>水温

物模型标识符 water_temp

对应本地变量 water_temp

数据类型: int32(整数型)(onenet整数类型都是这个)

取值范围: 0-100

步长: 1

单位:摄氏度

读写类型: 读写 (可读可写方便一会儿我们进行模拟上帝调试, 实际使用切勿可写, 需要真正从器件读取水温)

image-20240827102543956

<2>加热阈值

物模型标识符 heat_temp_th

对应本地变量 heat_temp_th

数据类型: int32(整数型)(onenet整数类型都是这个)

取值范围: 0-100

步长: 1

单位:摄氏度

读写类型: 读写 (可读可写方便一会儿我们进行模拟上帝调试, 同时后续方便用户设置阈值)

image-20240827102844737

<3>保温阈值

物模型标识符 Keepwarm_th

对应本地变量 Keepwarm_th

数据类型: int32(整数型)(onenet整数类型都是这个)

取值范围: 0-100

步长: 1

单位:摄氏度

读写类型: 读写 (可读可写方便一会儿我们进行模拟上帝调试, 同时后续方便用户设置阈值)

<4>加热模式

物模型标识符 heat_mode

对应本地变量 heat_mode

数据类型: int32(整数型)(onenet整数类型都是这个)

取值范围: 0-2

步长: 1

单位:个

读写类型: 读写 (可读可写方便一会儿我们进行模拟上帝调试, 同时后续方便用户设置模式)

image-20240827103314850

<5> 童锁状态

物模型标识符 children_lock

对应本地变量 child_lock_info.Status

数据类型: bool(布尔)

布尔值 true - 1 (童锁锁住)

​ false - 0 (童锁解开)

读写类型: 读写 (可读可写方便一会儿我们进行模拟上帝调试, 同时后续方便用户设置童锁)

image-20240827103639267

<6>杯子是否放置 (红外检测)

物模型标识符 cup_place

对应本地变量 cup_place_info.Status

数据类型: bool(布尔)

布尔值 true - 1 (放置了杯子)

​ false - 0 (未检测到杯子)

读写类型: 读写 (可读可写方便一会儿我们进行模拟上帝调试, 同时后续方便模拟杯子放上,优化本地逻辑)

image-20240827104034851

<7> 水龙头出水状态

物模型标识符 out_water

对应本地变量 out_water_info.Status

数据类型: bool(布尔)

布尔值 true - 1 (正在放水)

​ false - 0 (水龙头关闭)

读写类型: 读写 (可读可写方便一会儿我们进行模拟上帝调试, 同时后续方便测试安全措施,优化本地逻辑)

image-20240827104230293

9.创建产品

image-20240511104656266

image-20240827174511716

回去(ctrl 加鼠标左键,快速跳转)

image-20240827174553636

(1)产品id:A9g7LOO1B3

(2)设备名称:d1

(3)设备秘钥:(设备管理->设备->详情->设备秘钥)

UGNZQmt2SFFpbFV0NkczMGNTMzh0QW9IUTVpbGp1Skg=

单片机本地联网代码加入

1.代码下载

联网代码下载(ctrl 加鼠标左键,快速跳转)

下载完联网功能代码, 解压

image-20240827105317506

2.把Net文件夹复制加入Source_code源代码文件夹内

image-20240827105558072

3.把此文件夹内的所有类别文件夹, 加入工程

image-20240511094249365

我们首先打开工程

image-20240827115551215

4.点击品字, 然后添加联网文件夹内的工程名字

cjson
mqtt
onenet
uart
wifi

image-20240827115640650

image-20240827120118400

5.逐个把对应文件夹的文件加入

点击对应的Group,再点击Add Files,然后选中本地对应的文件夹, 把文件类型选为all , 然后鼠标选中所有文件点击add

image-20240827120406090

6.接着把这些文件夹路径加入

image-20240827120912820

image-20240827121046029

7.这样就可以看到工程左侧已经添加了文件

image-20240827121153234

联网代码初始化

wifi:ESP32-01S初始化

1.main.c引入 wifi头文件

image-20240827121525098

#include "esp8266.h"

定义

#define ESP8266_ONENET_INFO		"AT+CIPSTART=\"TCP\",\"mqtts.heclouds.com\",1883\r\n"

image-20240827121602253

2.wifi串口初始化

image-20240827121700158

	Delay_Init();//滴答定时器初始化
	uart1_init(115200);//串口1,调试用
	uart2_Init(115200);	//串口2,驱动ESP8266用
	ESP8266_Init();//wifi初始化

3.wifi配置

回去(ctrl 加鼠标左键,快速跳转)

image-20240511130504013

4.发现文件里都有delay.c

user里面添加delay.c delay.h

image-20240511110008065

delay.h

#ifndef _DELAY_H_
#define _DELAY_H_



#include "stm32f10x.h"



void Delay_Init(void);

void DelayUs(unsigned short us);

void DelayXms(unsigned short ms);

void DelayMs(unsigned short ms);
void delay(uint32_t t);

void delay_us(u32 us);
void delay_ms(u32 ms);
#endif


delay.c

/**
	************************************************************
	************************************************************
	************************************************************
	*	文件名: 	delay.c
	*
	*	作者: 		张继瑞
	*
	*	日期: 		2016-11-23
	*
	*	版本: 		V1.0
	*
	*	说明: 		利用systick做阻塞式延时
	*
	*	修改记录:	
	************************************************************
	************************************************************
	************************************************************
**/

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

//delay头文件
#include "delay.h"


//延时系数
unsigned char UsCount = 0;
unsigned short MsCount = 0;


/*
************************************************************
*	函数名称:	Delay_Init
*
*	函数功能:	systick初始化
*
*	入口参数:	无
*
*	返回参数:	无
*
*	说明:		
************************************************************
*/
void Delay_Init(void)
{

	SysTick->CTRL &= ~(1 << 2);		//选择时钟为HCLK(72MHz)/8		103--9MHz
	
	UsCount = 9;					//微秒级延时系数
	
	MsCount = UsCount * 1000;		//毫秒级延时系数

}

/*
************************************************************
*	函数名称:	DelayUs
*
*	函数功能:	微秒级延时
*
*	入口参数:	us:延时的时长
*
*	返回参数:	无
*
*	说明:		此时钟(21MHz)最大延时798915us
************************************************************
*/
void DelayUs(unsigned short us)
{

	unsigned int ctrlResult = 0;
	
	us &= 0x00FFFFFF;											//取低24位
	
	SysTick->LOAD = us * UsCount;								//装载数据
	SysTick->VAL = 0;
	SysTick->CTRL = 1;											//使能倒计数器
	
	do
	{
		ctrlResult = SysTick->CTRL;
	}
	while((ctrlResult & 0x01) && !(ctrlResult & (1 << 16)));	//保证在运行、检查是否倒计数到0
	
	SysTick->CTRL = 0;											//关闭倒计数器
	SysTick->VAL = 0;

}

/*
************************************************************
*	函数名称:	DelayXms
*
*	函数功能:	毫秒级延时
*
*	入口参数:	ms:延时的时长
*
*	返回参数:	无
*
*	说明:		
************************************************************
*/
void DelayXms(unsigned short ms)
{

	unsigned int ctrlResult = 0;
	
	if(ms == 0)
		return;
	
	ms &= 0x00FFFFFF;											//取低24位
	
	SysTick->LOAD = ms * MsCount;								//装载数据
	SysTick->VAL = 0;
	SysTick->CTRL = 1;											//使能倒计数器
	
	do
	{
		ctrlResult = SysTick->CTRL;
	}
	while((ctrlResult & 0x01) && !(ctrlResult & (1 << 16)));	//保证在运行、检查是否倒计数到0
	
	SysTick->CTRL = 0;											//关闭倒计数器
	SysTick->VAL = 0;

}

/*
************************************************************
*	函数名称:	DelayMs
*
*	函数功能:	微秒级长延时
*
*	入口参数:	ms:延时的时长
*
*	返回参数:	无
*
*	说明:		多次调用DelayXms,做到长延时
************************************************************
*/
void DelayMs(unsigned short ms)
{

	unsigned char repeat = 0;
	unsigned short remain = 0;
	
	repeat = ms / 500;
	remain = ms % 500;
	
	while(repeat)
	{
		DelayXms(500);
		repeat--;
	}
	
	if(remain)
		DelayXms(remain);

}

void delay(uint32_t t)
{
	while(t--);
}	

void delay_us(u32 us)//微秒
{
	SysTick_Config(72);
	while(us-->0)
	{
		while(!((SysTick->CTRL)&(1<<16)));
	}
	SysTick ->CTRL&=~SysTick_CTRL_ENABLE_Msk;
}

void delay_ms(u32 ms)//毫秒
{
	SysTick_Config(72000);
  while(ms-->0)
	{
		while(!((SysTick->CTRL)&(1<<16)));
	}
	SysTick ->CTRL&=~SysTick_CTRL_ENABLE_Msk;
}


5.发现delay.c里面有中断, 加入中断的库函数

image-20240511110257371

配置Onenet联网文件

wifi已经配置成功,下面配置链接onenet服务器

1.刚才导入的onenet配置文件

image-20240511130932868 image-20240511131040411 image-20240511131145551

2.在main.c里面引入 onenet头文件

#include "onenet.h"
image-20240827174206962

3.main.c主函数里面, 链接onetnet

	while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "CONNECT"))
		DelayXms(500);
	
	while(OneNet_DevLink())			//接入OneNET
		DelayXms(500);	
	
	OneNET_Subscribe();				//解析onenet下发指令	

image-20240827174246310

4.要想链接成功, onenet里面的服务器配置也要对应

5.进入onenet.c, 定义的属性, 进行替换

服务器信息(ctrl 加鼠标左键,快速跳转)

image-20240827174922503

6.回到主函数, 进行上传变量

定义发送间隔

unsigned short timeCount = 0;	//发送间隔变量
image-20240827175008391

main.c主函数, 定时上传, 延时10ms, 100次就是1s

72Mhz = 7200,0000次,(1s)

10ms,就是 7200,00次, 换算十六进制为 0xAFC80

		//打包上传
		if(++timeCount >= 100)
		{
			
			OneNet_SendData();	
			timeCount = 0;
			ESP8266_Clear();
		}
		delay(0xAFC80);//延时10ms
image-20240827175131860

7.先编译运行,鼠标按下f12, 跳转OneNet_SendData();

image-20240511150432185 image-20240827175237374

8.就会来到上传变量的位置

image-20240827175327293

9.引入上传变量

image-20240827175401028
extern int water_temp;		//水温
extern int heat_temp_th;	//加热阈值
extern int KeepWarm_th;		//保温阈值
extern int heat_mode;		//加热模式

因为童锁和红外线是定义在其他文件内, 所以我们包含其头文件即可

#include "infrared_cup.h"
#include "out_water.h"
image-20240827175519473

10.严格按照下面格式进行填写:

image-20240827175807978

11…强调:

最后一项,后面没逗号, 之前都有逗号

image-20240827175857322

代码摘录:

extern int water_temp;		//水温
extern int heat_temp_th;	//加热阈值
extern int KeepWarm_th;		//保温阈值
extern int heat_mode;		//加热模式


uint16_t OneNet_FillBuf(char *buf)
{
	
	char text[48];
	
	memset(text, 0, sizeof(text));
	
	strcpy(buf, "{\"id\":\"123\",\"params\":{");
	
	memset(text, 0, sizeof(text));
	sprintf(text, "\"water_temp\":{\"value\":%d},", water_temp);
	strcat(buf, text);

	memset(text, 0, sizeof(text));
	sprintf(text, "\"heat_temp_th\":{\"value\":%d},", heat_temp_th);
	strcat(buf, text);	
	
	memset(text, 0, sizeof(text));
	sprintf(text, "\"KeepWarm_th\":{\"value\":%d},", KeepWarm_th);
	strcat(buf, text);

	memset(text, 0, sizeof(text));
	sprintf(text, "\"heat_mode\":{\"value\":%d},", heat_mode);
	strcat(buf, text);


	memset(text, 0, sizeof(text));
	sprintf(text, "\"cup_place\":{\"value\":%s},", cup_place_info.Status ? "true" : "false");
	strcat(buf, text);

	memset(text, 0, sizeof(text));
	sprintf(text, "\"out_water\":{\"value\":%s},", out_water_info.Status ? "true" : "false");
	strcat(buf, text);

	memset(text, 0, sizeof(text));
	sprintf(text, "\"children_lock\":{\"value\":%s}", child_lock_info.Status ? "true" : "false");
	strcat(buf, text);
	
	strcat(buf, "}}");
	
	return strlen(buf);

}

单片机拆包(解析下发变量):

(1)检测是否有下发信息

定义接受判断变量

image-20240827180007725

unsigned char *dataPtr = NULL;	//标志位, 是否接受到onenet发送的数据

image-20240827180038923

代码摘录:

//检测是否有下发信息
dataPtr = ESP8266_GetIPD(0);
if(dataPtr != NULL)
{
    OneNet_RevPro(dataPtr);
  //UsartPrintf(USART_DEBUG, "6666666666\r\n");
}
(2)配置CJSON拆包

1.编译,运行 ,然后f12跳转OneNet_RevPro(dataPtr);

2.这里就是接受数据包的函数

我们在这里利用cjson拆包

image-20240827180140911

3.在此函数内,定义拆包所需要的cjson变量

image-20240827180254005

4.①接下来解析原始字符串数据到raw_jason

raw_jason = cJSON_Parse(req_payload);//解析原始字符串数据到raw_jason

② 从处理的cjson数据中,从raw_jason中提取params字符段到params_jason

params_jason=cJSON_GetObjectItem(raw_jason,"params");

image-20240827180449472

5.然后再从params_jason中提取要操作的饮水机变量

image-20240827180601077

				water_temp_jason = cJSON_GetObjectItem(params_jason,"water_temp");
				heat_temp_th_jason = cJSON_GetObjectItem(params_jason,"heat_temp_th");
				KeepWarm_th_jason = cJSON_GetObjectItem(params_jason,"KeepWarm_th");
				heat_mode_jason = cJSON_GetObjectItem(params_jason,"heat_mode");
				children_lock_jason = cJSON_GetObjectItem(params_jason,"children_lock");				
				
				out_water_jason = cJSON_GetObjectItem(params_jason,"out_water");
				
				cup_place_jason = cJSON_GetObjectItem(params_jason,"cup_place");

6.判断对应cjson 标识符变量 是否为空, 不空,则代表有对应的下发信息

image-20240827180849614

布尔类型, 需要对照其变量

image-20240827180941577
if(out_water_jason != NULL)
{
    if(out_water_jason->type == cJSON_True ) 
    {
        OUT_water_Set(out_water_ON);
    }
    else
    {
        OUT_water_Set(out_water_OFF);
    }
}				


if(cup_place_jason != NULL)
{
    if(cup_place_jason->type == cJSON_True ) 
    {
        cup_place_info.Status = Cup_placement;
    }
    else
    {
        cup_place_info.Status = Cup_disappears;
    }
}								


if(children_lock_jason != NULL)
{
    if(children_lock_jason->type == cJSON_True ) 
    {
        if(child_lock_info.Status != lock_child)
        {
            child_lock_info.Status = lock_child;
        }
    }
    else
    {
        if(child_lock_info.Status != Unlock_child)
        {
            child_lock_info.Status = Unlock_child;
        }
    }
}

7.末尾释放解析字符串空间

cJSON_Delete(raw_jason);
image-20240827181112467

此函数代码备份:

//==========================================================
//	函数名称:	OneNet_RevPro
//
//	函数功能:	平台返回数据检测
//
//	入口参数:	dataPtr:平台返回的数据
//
//	返回参数:	无
//
//	说明:		
//==========================================================

void OneNet_RevPro(unsigned char *cmd)
{
	
	char *req_payload = NULL;
	char *cmdid_topic = NULL;
	
	unsigned short topic_len = 0;
	unsigned short req_len = 0;
	
	unsigned char qos = 0;
	static unsigned short pkt_id = 0;
	
	unsigned char type = 0;
	
	short result = 0;
	
	//原始数据 -> cjson数据
	cJSON *raw_jason;
	// cjson中摘出标识符变量
	cJSON *params_jason;

	//这里定义 cjson格式的变量名,例如 *led_jason
	cJSON *water_temp_jason;
	cJSON *heat_temp_th_jason;
	cJSON *KeepWarm_th_jason;
	cJSON *heat_mode_jason;
	cJSON *children_lock_jason;
	
	cJSON *cup_place_jason;
	
	cJSON *out_water_jason;
	
	
	type = MQTT_UnPacketRecv(cmd);
	//UsartPrintf(USART_DEBUG, "688\r\n");
	switch(type)
	{
		case MQTT_PKT_PUBLISH:																//接收的Publish消息
//			UsartPrintf(USART_DEBUG, "689\r\n");
			result = MQTT_UnPacketPublish(cmd, &cmdid_topic, &topic_len, &req_payload, &req_len, &qos, &pkt_id);
			
			if(result == 0)
			{

				
				UsartPrintf(USART_DEBUG, "topic: %s, topic_len: %d, payload: %s, payload_len: %d\r\n",
																	cmdid_topic, topic_len, req_payload, req_len);
				
				//将原始字符串信息,转化成cjson格式
				raw_jason = cJSON_Parse(req_payload);//解析原始字符串数据到raw_jason
				//从raw_jason中提取params字符段到params_jason
				params_jason = cJSON_GetObjectItem(raw_jason,"params");
				//然后再从params_jason中提取要操作的器件,

				water_temp_jason = cJSON_GetObjectItem(params_jason,"water_temp");
				heat_temp_th_jason = cJSON_GetObjectItem(params_jason,"heat_temp_th");
				KeepWarm_th_jason = cJSON_GetObjectItem(params_jason,"KeepWarm_th");
				heat_mode_jason = cJSON_GetObjectItem(params_jason,"heat_mode");
				children_lock_jason = cJSON_GetObjectItem(params_jason,"children_lock");				
				
				out_water_jason = cJSON_GetObjectItem(params_jason,"out_water");
				
				cup_place_jason = cJSON_GetObjectItem(params_jason,"cup_place");
				
				//判断对应cjson 标识符变量 是否为空, 不空,则代表有对应的下发信息

				if(water_temp_jason != NULL)
				{
					water_temp = water_temp_jason->valueint;
				}
				if(heat_temp_th_jason != NULL)
				{
					heat_temp_th = heat_temp_th_jason->valueint;
				}
				if(KeepWarm_th_jason != NULL)
				{
					KeepWarm_th = KeepWarm_th_jason->valueint;
				}
				if(heat_mode_jason != NULL)
				{
					heat_mode = heat_mode_jason->valueint;
				}				

				if(out_water_jason != NULL)
				{
					if(out_water_jason->type == cJSON_True ) 
					{
						OUT_water_Set(out_water_ON);
					}
					else
					{
						OUT_water_Set(out_water_OFF);
					}
				}				
				
				
				if(cup_place_jason != NULL)
				{
					if(cup_place_jason->type == cJSON_True ) 
					{
						cup_place_info.Status = Cup_placement;
					}
					else
					{
						cup_place_info.Status = Cup_disappears;
					}
				}								
				
				
				if(children_lock_jason != NULL)
				{
					if(children_lock_jason->type == cJSON_True ) 
					{
						if(child_lock_info.Status != lock_child)
						{
							child_lock_info.Status = lock_child;
						}
					}
					else
					{
						if(child_lock_info.Status != Unlock_child)
						{
							child_lock_info.Status = Unlock_child;
						}
					}
				}
				

				cJSON_Delete(raw_jason);
				
			}
			
		case MQTT_PKT_PUBACK:														//发送Publish消息,平台回复的Ack
//			UsartPrintf(USART_DEBUG, "111\r\n");
			if(MQTT_UnPacketPublishAck(cmd) == 0)
//				UsartPrintf(USART_DEBUG, "Tips:	MQTT Publish Send OK\r\n");
			
		break;
		
		case MQTT_PKT_SUBACK:																//发送Subscribe消息的Ack
//			UsartPrintf(USART_DEBUG, "222\r\n");
			if(MQTT_UnPacketSubscribe(cmd) == 0)
				UsartPrintf(USART_DEBUG, "Tips:	MQTT Subscribe OK\r\n");
			else
				UsartPrintf(USART_DEBUG, "Tips:	MQTT Subscribe Err\r\n");
		
		break;
		
		default:
//			UsartPrintf(USART_DEBUG, "333\r\n");
			result = -1;
		break;
	}
	
	ESP8266_Clear();									//清空缓存
	
	if(result == -1)
		return;
	

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

}

烧录调试现象

1.烧录方法

2.esp32连线方法 , esp32上 RX 链接 PA2 ,TX链接PA3

GND–单片机gnd, vcc–单片机3.3v

3.手机wifi热点设置为 配置的

跳转单片机wifi设置(ctrl+鼠标左键跳转)

4.观察服务器设备在线情况

image-20240827184552881

5.模拟下发设备信息,再次观察属性是否被修改,并上传

image-20240827184621266

6.然后就按照我们之前的调试方法, 进行调试

饮水机复杂交互功能联网调试

https://blog.csdn.net/qq_57484399/article/details/141574662

以下是ESP8266 NodeMCU连接OneNET的基本代码框架: ```c++ #include <ESP8266WiFi.h> #include <PubClient.h> // Replace with your network credentials const* ssid = "your_SSID"; const char password = "your_PASSWORD"; // Replace with your One MQTT server and port const char* server = ".heclouds.com"; const int port = 6002; // Replace with your OneNET device ID and API key const char* deviceId = "your_DEVICE_ID"; const char* apiKey "your_API_KEY"; // Create an instance of the WiFiClient object WiFiClient wifiClient; // Create an instance of the PubSubClient object PubSubClient mqttClient(wifiClient); // Function to connect to OneNET MQTT server void connectToMqttServer() { while (!mqttClient.connected()) { Serial.println("Connecting to OneNET MQTT server..."); // Create a unique client ID using the ESP8266 MAC address String clientId = "ESP8266Client-"; clientId += String(WiFi.macAddress()); // Connect to OneNET MQTT server if (mqttClient.connect(clientId.c_str(), deviceId, apiKey)) { Serial.println("Connected to OneNET MQTT server!"); } else { Serial.print("Failed to connect to OneNET MQTT server with error code "); Serial.println(mqttClient.state()); delay(2000); } } } void setup() { Serial.begin(9600); // Connect to Wi-Fi network WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi network..."); } Serial.println("Connected to WiFi network!"); // Set OneNET MQTT server and port mqttClient.setServer(server, port); // Connect to OneNET MQTT server connectToMqttServer(); } void loop() { // Add your code here to publish or subscribe to MQTT topics } ``` 在上面的代码中,你需要将以下变量替换为你自己的值: - `ssid` 和 `password`:你的 Wi-Fi 网络 SSID 和密码 - `server` 和 `port`:OneNET MQTT 服务器地址和端口 - `deviceId` 和 `apiKey`:你的 OneNET 设备 ID 和 API 密钥 接下来,你可以在 `loop()` 函数中添加你的代码来发布或订阅 MQTT 主题。例如,下面是一个发布消息到 OneNET 的例子: ```c++ void loop() { // Check if connected to OneNET MQTT server if (!mqttClient.connected()) { connectToMqttServer(); } // Publish a message to OneNET mqttClient.publish("topic", "message"); // Wait for a few seconds delay(5000); } ``` 这将发布一个名为 "topic" 的主题,并将消息 "message" 发送到 OneNET。你可以通过 OneNET 控制台查看接收到的消息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值