stm32zet6将温度数据上传至yeelnk服务器,电脑上位机查看

对于yeelink服务器的请求的最快的频率是11秒一次,请求时间间隔小于10秒的时候会丢包,不知道机智云的效果怎么样,有尝试过的朋友可以留言。

stm32将18b20的温度信息上传到yeelink服务器。上位机读取yeelink服务器的数据。同时可用stm32串口查看服务器的回传信息(usart1 波特率115200 无校验位 一个停止位)。


stm32zet6将温度数据上传至yeelnk服务器,电脑上位机查看_第1张图片

上位机显示界面,代码和上一篇的代码基本相同。不同的地方是定时器的时间间隔加长了,因为时间间隔过短会导致丢包。


下位机是stm32zet6+18b20.18b20的DQ引脚接PG11,至于w5500按照用户手册插线即可。用网线将路由器和w5500模块连接(因为路由器可以自动分配ip地址,使用起来很方便)。


下位机的难点是dns解析。


/**
  ******************************************************************************
  * @file    main.c
  * $Author: 飞鸿踏雪 $
  * $Revision: 17 $
  * $Date:: 2014-10-25 11:16:48 +0800 #$
  * @brief   主函数.
  ******************************************************************************
  * @attention
  *
  *

© Copyright 2009-2012, EmbedNet
*
http://www.embed-net.com
*
All Rights Reserved

* ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "usart.h" #include "delay.h" #include "spi.h" #include "socket.h" // Just include one header for WIZCHIP #include "Internet/DNS/dns.h" #include "timer.h" #include #include /* Private typedef -----------------------------------------------------------*/ #include "ds18b20.h" /* Private define ------------------------------------------------------------*/ #define SOCK_TCPS 0 #define SOCK_DNS 1 #define DATA_BUF_SIZE 2048 /* Private macro -------------------------------------------------------------*/ uint8_t gDATABUF[DATA_BUF_SIZE]; uint8_t domain_ip[4]={0}; uint8_t domain_name[]="yeelink.net"; // Default Network Configuration wiz_NetInfo gWIZNETINFO = { .mac = {0x00, 0x08, 0xdc,0x00, 0xab, 0xcd}, .ip = {192, 168, 0, 123},//貌似瞎写就行 .sn = {255,255,255,0}, .gw = {192, 168, 0, 1},//这个也需要用ipconfig /all查看 .dns = {192, 168, 0, 1},//修改成自己网络的DNS,windows下需要用ipconfig /all查看dns服务器地址 .dhcp = NETINFO_STATIC }; /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ void platform_init(void); // initialize the dependent host peripheral void network_init(void); // Initialize Network information and display it uint8_t yeelink_get(const char *device_id,const char *sensors_id,char *value); /** * @brief 串口打印输出 * @param None * @retval None */ int main(void) { uint8_t tmp; int32_t ret = 0,t=0; uint8_t memsize[2][8] = {{2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2}}; char value[16]={0}; delay_init(); // DS18B20_Init(); while(DS18B20_Init()) //DS18B20初始化 { } //Host dependent peripheral initialized platform_init(); // First of all, Should register SPI callback functions implemented by user for accessing WIZCHIP /* Critical section callback */ reg_wizchip_cris_cbfunc(SPI_CrisEnter, SPI_CrisExit); //注册临界区函数 /* Chip selection call back */ #if _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_ reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect);//注册SPI片选信号函数 #elif _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_FDM_ reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect); // CS must be tried with LOW. #else #if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SIP_) != _WIZCHIP_IO_MODE_SIP_ #error "Unknown _WIZCHIP_IO_MODE_" #else reg_wizchip_cs_cbfunc(wizchip_select, wizchip_deselect); #endif #endif /* SPI Read & Write callback function */ reg_wizchip_spi_cbfunc(SPI_ReadByte, SPI_WriteByte); //注册读写函数 /* WIZCHIP SOCKET Buffer initialize */ if(ctlwizchip(CW_INIT_WIZCHIP,(void*)memsize) == -1){ printf("WIZCHIP Initialized fail.\r\n"); while(1); } /* PHY link status check */ do{ if(ctlwizchip(CW_GET_PHYLINK, (void*)&tmp) == -1){ printf("Unknown PHY Link stauts.\r\n"); } }while(tmp == PHY_LINK_OFF); /* Network initialization */ network_init(); /* DNS client initialization */ DNS_init(SOCK_DNS, gDATABUF); Timer_Start(); /* DNS procssing */ if ((ret = DNS_run(gWIZNETINFO.dns, domain_name, domain_ip)) > 0){ // try to 1st DNS printf("> 1st DNS Reponsed\r\n"); }else if(ret == -1){ printf("> MAX_DOMAIN_NAME is too small. Should be redefined it.\r\n"); Timer_Stop(); while(1); }else{ printf("> DNS Failed\r\n"); Timer_Stop(); while(1); } //DNS解析成功 if(ret > 0){ printf("> Translated %s to %d.%d.%d.%d\r\n",domain_name,domain_ip[0],domain_ip[1],domain_ip[2],domain_ip[3]); } Timer_Stop(); while(1) { yeelink_get("358143","406963",value);//获取开关变量 // printf("%s\n\r",value); // delay_ms(1000); for(t=0;t<11;t++){ delay_ms(1000); } } } /** * @brief Intialize the network information to be used in WIZCHIP * @retval None */ void network_init(void) { uint8_t tmpstr[6]; ctlnetwork(CN_SET_NETINFO, (void*)&gWIZNETINFO); ctlnetwork(CN_GET_NETINFO, (void*)&gWIZNETINFO); // Display Network Information ctlwizchip(CW_GET_ID,(void*)tmpstr); printf("\r\n=== %s NET CONF ===\r\n",(char*)tmpstr); printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n",gWIZNETINFO.mac[0],gWIZNETINFO.mac[1],gWIZNETINFO.mac[2], gWIZNETINFO.mac[3],gWIZNETINFO.mac[4],gWIZNETINFO.mac[5]); printf("SIP: %d.%d.%d.%d\r\n", gWIZNETINFO.ip[0],gWIZNETINFO.ip[1],gWIZNETINFO.ip[2],gWIZNETINFO.ip[3]); printf("GAR: %d.%d.%d.%d\r\n", gWIZNETINFO.gw[0],gWIZNETINFO.gw[1],gWIZNETINFO.gw[2],gWIZNETINFO.gw[3]); printf("SUB: %d.%d.%d.%d\r\n", gWIZNETINFO.sn[0],gWIZNETINFO.sn[1],gWIZNETINFO.sn[2],gWIZNETINFO.sn[3]); printf("DNS: %d.%d.%d.%d\r\n", gWIZNETINFO.dns[0],gWIZNETINFO.dns[1],gWIZNETINFO.dns[2],gWIZNETINFO.dns[3]); printf("======================\r\n"); } /** * @brief Loopback Test Example Code using ioLibrary_BSD * @retval None */ void platform_init(void) { SystemInit();//系统时钟初始化 USART_Configuration();//串口1初始化 printf("\x0c");printf("\x0c");//超级终端清屏 printf("\033[1;40;32m");//设置超级终端背景为黑色,字符为绿色 printf("\r\n*******************************************************************************"); printf("\r\n************************ Copyright 2009-2014, EmbedNet ************************"); printf("\r\n*************************** http://www.embed-net.com **************************"); printf("\r\n***************************** All Rights Reserved *****************************"); printf("\r\n*******************************************************************************"); printf("\r\n"); //Config SPI SPI_Configuration(); //延时初始化 delay_init(); //初始化DNS所需要的定时器 Timer_Config(); } uint8_t yeelink_get(const char *device_id,const char *sensors_id,char *value) { int ret; int temperature=256; char* presult; char remote_server[] = "api.yeelink.net"; char str_tmp[128] = {0}; // 请求缓冲区和响应缓冲区 static char http_request[DATA_BUF_SIZE] = {0}; //声明为静态变量,防止堆栈溢出 static char http_response[DATA_BUF_SIZE] = {0}; //声明为静态变量,防止堆栈溢出 static char test_request[DATA_BUF_SIZE] = {0}; //声明为静态变量,防止堆栈溢出 static char http_content[64] = { 0, }; temperature=DS18B20_Get_Temp(); sprintf(http_content, "{\"value\":%d}", temperature); sprintf(test_request,"POST /v1.0/device/写自己的/sensor/写自己的/datapoints HTTP/1.1\r\nHost:api.yeelink.net\r\nU-ApiKey:写自己的\r\nContent-Length:%d\r\nContent-Type:application/x-www-form-urlencoded\r\n\r\n{\"value\":%d}",strlen(http_content),temperature); sprintf(str_tmp,"/v1.0/device/%s/sensor/%s/datapoints",device_id,sensors_id); // 确定 HTTP请求首部 // 例如POST /v1.0/device/98d19569e0474e9abf6f075b8b5876b9/1/1/datapoints/add HTTP/1.1\r\n sprintf( http_request , "GET %s HTTP/1.1\r\n",str_tmp); // 增加属性 例如 Host: api.machtalk.net\r\n sprintf( str_tmp , "Host:%s\r\n" , remote_server); strcat( http_request , str_tmp); // 增加密码 例如 APIKey: d8a605daa5f4c8a3ad086151686dce64 sprintf( str_tmp , "U-ApiKey:%s\r\n" , "写自己的");//需要替换为自己的APIKey strcat( http_request , str_tmp); // strcat( http_request , "Accept: */*\r\n"); // 增加表单编码格式 Content-Type:application/x-www-form-urlencoded\r\n strcat( http_request , "Content-Type: application/x-www-form-urlencoded\r\n"); strcat( http_request , "Connection: close\r\n"); // HTTP首部和HTTP内容 分隔部分 strcat( http_request , "\r\n"); //将数据通过TCP发送出去 //新建一个Socket并绑定本地端口5000 ret = socket(SOCK_TCPS,Sn_MR_TCP,5000,0x00); if(ret != SOCK_TCPS){ printf("%d:Socket Error\r\n",SOCK_TCPS); while(1); } //连接TCP服务器 ret = connect(SOCK_TCPS,domain_ip,80); if(ret != SOCK_OK){ printf("%d:Socket Connect Error\r\n",SOCK_TCPS); while(1); } //发送请求 // ret = send(SOCK_TCPS,(unsigned char *)http_request,strlen(http_request)); ret = send(SOCK_TCPS,(unsigned char *)test_request,strlen(test_request)); if(ret != strlen(test_request)){ printf("%d:Socket Send Error\r\n",SOCK_TCPS); while(1); } // 获得响应 ret = recv(SOCK_TCPS,(unsigned char *)http_response,DATA_BUF_SIZE); if(ret <= 0){ printf("%d:Socket Get Error\r\n",SOCK_TCPS); while(1); } http_response[ret] = '\0'; //判断是否收到HTTP OK printf("%s",http_response); // presult = strstr( (const char *)http_response , (const char *)"200 OK\r\n"); // if( presult != NULL ){ // static char strTmp[DATA_BUF_SIZE]={0};//声明为静态变量,防止堆栈溢出 // sscanf(http_response,"%*[^{]{%[^}]",strTmp); // //提取返回信息 // char timestamp[64]={0}; // char timestampTmp[64]={0}; // char valueTmp[64]={0}; // sscanf(strTmp,"%[^,],%[^,]",timestampTmp,valueTmp); // strncpy(timestamp,strstr(timestampTmp,":")+2,strlen(strstr(timestampTmp,":"))-3); // strncpy(value,strstr(valueTmp,":")+1,strlen(strstr(valueTmp,":"))-1); // }else{ // printf("Http Response Error\r\n"); // printf("%s",http_response); // } close(SOCK_TCPS); return 0; } /*********************************END OF FILE**********************************/

上述代码是网站上的大神编写的。不过已经被我按照自己的需求更改过了。下面的链接是这个大神的博客,里面有他的源码。

http://www.embed-net.com/forum.php?mod=viewthread&tid=69

这是文章链接。他写了很多关于yeelink的博客,都很有用。

http://www.embed-net.com/thread-57-1-1.html

这是用stm32实现域名解析的链接。




stm32zet6将温度数据上传至yeelnk服务器,电脑上位机查看_第2张图片

上图显示了工程所引用的文件。个人感觉dns.c dhcp.c的文件嘴刁。他们可以将域名解析成ip地址。前提是要在程序里面书写正确的dns服务器地址。


stm32zet6将温度数据上传至yeelnk服务器,电脑上位机查看_第3张图片


stm32zet6将温度数据上传至yeelnk服务器,电脑上位机查看_第4张图片


stm32zet6将温度数据上传至yeelnk服务器,电脑上位机查看_第5张图片


因为我的电脑里面安装了虚拟机,所以可能和大多数人不一样。上面三张命令行的图片中的第一张图片显示了dns服务器的ip地址,网关地址等重要信息。在stm32的程序中把自己的dns服务器的地址写上,网关也写上。就可以解析域名了。





uint8_t yeelink_get(const char *device_id,const char *sensors_id,char *value)
{
	int ret;
	int temperature=256;
	char* presult;
	char remote_server[] = "api.yeelink.net";
	char str_tmp[128] = {0};
	// 请求缓冲区和响应缓冲区
	static char http_request[DATA_BUF_SIZE] = {0};	//声明为静态变量,防止堆栈溢出
	static char http_response[DATA_BUF_SIZE] = {0};	//声明为静态变量,防止堆栈溢出
	static char test_request[DATA_BUF_SIZE] = {0};	//声明为静态变量,防止堆栈溢出
	static char http_content[64] = { 0, };
	
	temperature=DS18B20_Get_Temp();	
	sprintf(http_content, "{\"value\":%d}", temperature);
	sprintf(test_request,"POST /v1.0/device/写自己的/sensor/写自己的/datapoints HTTP/1.1\r\nHost:api.yeelink.net\r\nU-ApiKey:写自己的\r\nContent-Length:%d\r\nContent-Type:application/x-www-form-urlencoded\r\n\r\n{\"value\":%d}",strlen(http_content),temperature);
	sprintf(str_tmp,"/v1.0/device/%s/sensor/%s/datapoints",device_id,sensors_id);
	// 确定 HTTP请求首部
	// 例如POST /v1.0/device/98d19569e0474e9abf6f075b8b5876b9/1/1/datapoints/add HTTP/1.1\r\n
	sprintf( http_request , "GET %s HTTP/1.1\r\n",str_tmp);
	// 增加属性 例如 Host: api.machtalk.net\r\n
	sprintf( str_tmp , "Host:%s\r\n" , remote_server);
	strcat( http_request , str_tmp);

	// 增加密码 例如 APIKey: d8a605daa5f4c8a3ad086151686dce64
	sprintf( str_tmp , "U-ApiKey:%s\r\n" , "写自己的");//需要替换为自己的APIKey
	strcat( http_request , str_tmp);
	//
	strcat( http_request , "Accept: */*\r\n");
	// 增加表单编码格式 Content-Type:application/x-www-form-urlencoded\r\n
	strcat( http_request , "Content-Type: application/x-www-form-urlencoded\r\n");
	strcat( http_request , "Connection: close\r\n");
	// HTTP首部和HTTP内容 分隔部分
	strcat( http_request , "\r\n");
	
	//将数据通过TCP发送出去
	//新建一个Socket并绑定本地端口5000
	ret = socket(SOCK_TCPS,Sn_MR_TCP,5000,0x00);
	if(ret != SOCK_TCPS){
		printf("%d:Socket Error\r\n",SOCK_TCPS);
		while(1);
	}
	//连接TCP服务器
	ret = connect(SOCK_TCPS,domain_ip,80);
	if(ret != SOCK_OK){
		printf("%d:Socket Connect Error\r\n",SOCK_TCPS);
		while(1);
	}	
	//发送请求
//	ret = send(SOCK_TCPS,(unsigned char *)http_request,strlen(http_request));
	ret = send(SOCK_TCPS,(unsigned char *)test_request,strlen(test_request));
	if(ret != strlen(test_request)){
		printf("%d:Socket Send Error\r\n",SOCK_TCPS);
		while(1);
	}

	// 获得响应
	ret = recv(SOCK_TCPS,(unsigned char *)http_response,DATA_BUF_SIZE);
	if(ret <= 0){
		printf("%d:Socket Get Error\r\n",SOCK_TCPS);
		while(1);
	}
	http_response[ret] = '\0';
	//判断是否收到HTTP OK
	printf("%s",http_response);
//	presult = strstr( (const char *)http_response , (const char *)"200 OK\r\n");
//	if( presult != NULL ){
//		static char strTmp[DATA_BUF_SIZE]={0};//声明为静态变量,防止堆栈溢出
//		sscanf(http_response,"%*[^{]{%[^}]",strTmp);
//		//提取返回信息
//		char timestamp[64]={0};
//		char timestampTmp[64]={0};
//		char valueTmp[64]={0};
//		sscanf(strTmp,"%[^,],%[^,]",timestampTmp,valueTmp);
//		strncpy(timestamp,strstr(timestampTmp,":")+2,strlen(strstr(timestampTmp,":"))-3);
//		strncpy(value,strstr(valueTmp,":")+1,strlen(strstr(valueTmp,":"))-1);
//	}else{
//		printf("Http Response Error\r\n");
//		printf("%s",http_response);
//	}
	close(SOCK_TCPS);
	return 0;
}
用上面这段程序向服务器发送指令。但是一定要记住,不管是上位机发送指令还是下位机发送指令,指令之间的时间间隔必须大于10秒。否则会出错。


if ((ret = DNS_run(gWIZNETINFO.dns, domain_name, domain_ip)) > 0){ // try to 1st DNS
		printf("> 1st DNS Reponsed\r\n");
	}else if(ret == -1){
		printf("> MAX_DOMAIN_NAME is too small. Should be redefined it.\r\n");
		Timer_Stop();
		while(1);
	}else{
		printf("> DNS Failed\r\n");
		Timer_Stop();
		while(1);
	}
初始化中(while死循环外部)有域名解析



一下代码是yeelink_get函数里面的


//新建一个Socket并绑定本地端口5000
	ret = socket(SOCK_TCPS,Sn_MR_TCP,5000,0x00);
	if(ret != SOCK_TCPS){
		printf("%d:Socket Error\r\n",SOCK_TCPS);
		while(1);
	}

创建端口


//连接TCP服务器
	ret = connect(SOCK_TCPS,domain_ip,80);
	if(ret != SOCK_OK){
		printf("%d:Socket Connect Error\r\n",SOCK_TCPS);
		while(1);
	}

与服务器连接



	//发送请求
//	ret = send(SOCK_TCPS,(unsigned char *)http_request,strlen(http_request));
	ret = send(SOCK_TCPS,(unsigned char *)test_request,strlen(test_request));
	if(ret != strlen(test_request)){
		printf("%d:Socket Send Error\r\n",SOCK_TCPS);
		while(1);
	}

向服务器发送请求,再次强调,任何想yeelink服务器发送请求的时间间隔必须大于10秒


	// 获得响应
	ret = recv(SOCK_TCPS,(unsigned char *)http_response,DATA_BUF_SIZE);
	if(ret <= 0){
		printf("%d:Socket Get Error\r\n",SOCK_TCPS);
		while(1);
	}
	http_response[ret] = '\0';
	//判断是否收到HTTP OK
	printf("%s",http_response);

获得服务器的回传数据,并将其数据通过串口打印到串口调试住手。


	close(SOCK_TCPS);

关闭套接字


主要步骤为:域名解析 建立套接字 连接服务器 向服务器发送请求 服务器回传信息 关闭套接字(第一次)


                                     建立套接字 连接服务器 向服务器发送请求 服务器回传信息 关闭套接字 (域名解析一次就行了)


http://download.csdn.net/detail/m1f2c3/9849558

YIXIN_W5500模块用户手册

http://download.csdn.net/detail/m1f2c3/9849573

JXW_W5500+模块配套资料

http://download.csdn.net/detail/m1f2c3/9849630

yeelink+stm32+18b20下位机





















你可能感兴趣的:(stm32zet6将温度数据上传至yeelnk服务器,电脑上位机查看)