随着物联网逐渐进入我们的生活,我们需要随时随地查看远端的设备运行状态及对设备进行控制,Yeelink为我们提供了一个很好的云端服务器平台,设备通过网络连接到Yeelink服务器,上传本地检测数据,电脑或手机通过手机访问即可看到设备数据,网上也有很多朋友使用Yeelink来做远程监控的示例,下面我们来介绍如何使用Yeelink做远程检测与控制,如有错误还请大家指正。



   下面是Yeelink远程监控的一个大致框图




监控云服务器配置方案 家用监控云端服务器_监控云服务器配置方案



Yeelink 主页“ http://www.yeelink.net/ ”注册一个自己的帐号,下面是主页为我们开发者提供的一个简单的开发流程


监控云服务器配置方案 家用监控云端服务器_监控云服务器配置方案_02



2、按照上面的流程点击添加设备,输入设备信息,在下面的地图中选择设备所在地


监控云服务器配置方案 家用监控云端服务器_数据_03



3、进入到设备管理界面,设置设备图片,添加传感器


监控云服务器配置方案 家用监控云端服务器_字符串_04



4、添加传感器,这里我们添加一个数值型传感器和一个开关型传感器,通过下面选择设置传感器信息


监控云服务器配置方案 家用监控云端服务器_字符串_05




传感器添加完成之后宝马 1768 设备下面出现两个传感器: AD 转换值和 LED1 , AD 转换值属于数值型传感器,显示 AD 转换电压, LED1 属于开关型传感器,用于控制宝马开发板 LED 灯亮灭,注意下面标记出来的地方蓝色框框第一个是设备 ID 即宝马 1768 的 ID ,第二个为传感器 ID 即对应 AD 转换值和 LED1 各自的 ID ,由于两个传感器同属于宝马 1768 设备下面的两个传感器所以设备 ID 相同,而传感器 ID 不同,这几个 ID 会在后面编程中使用到


监控云服务器配置方案 家用监控云端服务器_监控云服务器配置方案_06




API KEY ,当要进行传输数据时需要使用到该密码



监控云服务器配置方案 家用监控云端服务器_监控云服务器配置方案_07




7、上面Yeelink的设置基本完成了,就要开始进行程序编写了,这里我们直接使用宝马开发板搭建好的TCP客户端例程进行添加修改,在系统配置完成之后初始化ADC和LED


1. ADC_Init();         //        ADC初始化
2. LPC_GPIO2->FIODIR  = 0x000000ff;    //        LED配置
3. LPC_GPIO0->FIODIR  = 0x00200000; 
4. LPC_GPIO0->FIOPIN |= 0x00200000;              
5. while(1)
6. {
7. tcpclient("42.96.164.52",80 ,1);         //AD转换值上传         tcpclient("42.96.164.52",80 ,2);         //获取LED状态并改变开发板LED状态 rt_thread_delay(RT_TICK_PER_SECOND * 4);        //延时4s
8. }
9. //TCP客户端实验
10. int tcpclient(const char* url, int port,int num)
11. {
12.     char *recv_data;
13.     struct hostent *host;
14.     int sock, bytes_received;
15.     struct sockaddr_in server_addr;
16. int        Buf = 0;
17. 
18.     /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */
19.     host = gethostbyname(url);
20. 
21.     /* 分配用于存放接收数据的缓冲 */
22.     recv_data = rt_malloc(BUFSZ);
23.     if (recv_data == RT_NULL)
24.     {
25.         rt_kprintf("No memory\n");
26.         return;
27.     }
28. 
29.     /* 创建一个socket,类型是SOCKET_STREAM,TCP类型 */
30.     if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
31.     {
32.         /* 创建socket失败 */
33.         rt_kprintf("Socket error\n");
34. 
35.         /* 释放接收缓冲 */
36.         rt_free(recv_data);
37.         return 1;
38.     }
39. if(num == 1)         /
40. {
41. Buf   = ADC_Get();                     
42. Buf = (Buf * 3300)/4096;
43. INT_CHAR(Buf);
44. send_data1[234] = dis[0];         //更改上传数据内容即AD值
45. send_data1[234+1] = '.';
46. send_data1[234+2] = dis[0+1];
47. send_data1[234+3] = dis[0+2];
48. }
49.     /* 初始化预连接的服务端地址 */
50.     server_addr.sin_family = AF_INET;
51.     server_addr.sin_port = htons(port);
52.     server_addr.sin_addr = *((struct in_addr *)host->h_addr);
53.     rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
54. 
55.     /* 连接到服务端 */
56.     while (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
57.     {
58.         /* 连接失败 */
59.         rt_kprintf("Connect fail!\n");
60.         lwip_close(sock);
61. 
62.          /*释放接收缓冲 */
63.         rt_free(recv_data);
64.                return 1;
65.     }
66. rt_kprintf("Connect OK!\n");
67. 
68. if(num == 1)
69. {
70. /* 发送数据到sock连接 */
71. if(send(sock,send_data1,strlen(send_data1), 0) < 0)
72. {
73. /* 发送失败,关闭这个连接 */
74. rt_kprintf("\nSend error ");
75. lwip_close(sock);
76. 
77. /* 释放接收缓冲 */
78. rt_free(recv_data);
79. }
80. else
81. {
82. rt_kprintf("\nSend OK ");
83. bytes_received = recv(sock, recv_data, BUFSZ - 1, 0);
84. lwip_close(sock);
85. 
86. /* 释放接收缓冲 */
87. rt_free(recv_data);
88. }
89. }
90. else if(num == 2)
91. {
92. /* 发送数据到sock连接 */
93. if(send(sock,send_data2,strlen(send_data2), 0) < 0)
94. {
95. /* 发送失败,关闭这个连接 */
96. rt_kprintf("\nSend error ");
97. lwip_close(sock);
98. 
99. /* 释放接收缓冲 */
100. rt_free(recv_data);
101. }
102. else
103. {
104. rt_kprintf("\nSend OK ");
105. /* 从sock连接中接收最大BUFSZ - 1字节数据 */
106.                 bytes_received = recv(sock, recv_data, BUFSZ - 1, 0);
107. Buf = Search_str(recv_data,"\"value\":");
108. if(recv_data[Buf] == '0')
109. LPC_GPIO2->FIOPIN &= ~0xff;         //关闭LED
110. else
111. LPC_GPIO2->FIOPIN |= 0xff;         //打开LED
112. rt_kprintf("\n%s ",recv_data+Buf);
113. lwip_close(sock);
114. 
115. /* 释放接收缓冲 */
116. rt_free(recv_data);
117. }
118. }
119.     return 1;
120. }

复制代码



8、我们可以看到程序中通过判断num值来发送两个不同的字符串,这里num就是用来区别是用来上传AD转换值还是LED状态获取的下面看看两个字符串数据,我们可以看到下面两个字符串中第一行都出现了我们设备的ID和传感器ID,send_data1对应是AD转换值上传,所以ID为20165,而send_data2为LED控制,ID对应为20166,U-ApiKey后面紧跟着就是我们上面在账户设置里面的密码,Yeelink的API格式比较固定,至于其他一些参数可以参考Yeelink API文档


char send_data1[300] = "POST /v1.0/device/12402/sensor/20165/datapoints HTTP/1.1\r\n\
  
Host: api.yeelink.net\r\n\
  
Accept: */*\r\n\
  
U-ApiKey: 615e52feacb3a8b18ab424703c00bfbf\r\n\
  
Content-Length: 14\r\n\
  
Content-Type: application/json;charset=utf-8\r\n\
  
Connection: close\r\n\
  
\r\n\
  
{\"value\":96  }\r\n"; /* 发送用到的数据 */


这里有一点需要注意的是Content-Length的长度必须为”value”后面跟着字符串的长度值加10,上面设置为14即”value”后面的值为4位,这里初始化是”96  “


char send_data2[300] = "GET /v1.0/device/12402/sensor/20166/datapoints HTTP/1.1\r\n\
  
Host: api.yeelink.net\r\n\
  
Accept: */*\r\n\
  
U-ApiKey: 615e52feacb3a8b18ab424703c00bfbf\r\n\
  
Content-Length: 0\r\n\
  
Connection: close\r\n\
  
\r\n\
  
print get done.\r\n"; /* 发送用到的数据 */


另外还有一点需要注意的是,当我们查询LED状态时需要接收Yeelink服务器数据,那么数据的哪部分才是对我们有用的呢,我们可以使用网络调试助手,将调试助手连接到Yeelink服务器,发送字符串send_data2的内容,即可获取服务器返回消息,其中”value”后面的0是我们需要的数据,表明现在开关是关着的,若开关打开则返回为1




监控云服务器配置方案 家用监控云端服务器_数据_08



Yeelink 设置和程序都介绍完了,下面就开始测试了下面是电脑显示波形


监控云服务器配置方案 家用监控云端服务器_LPC_09


手机可以查看设备地址


监控云服务器配置方案 家用监控云端服务器_字符串_10


监控云服务器配置方案 家用监控云端服务器_LPC_11



LED 控制,手机拍照效果不好


监控云服务器配置方案 家用监控云端服务器_监控云服务器配置方案_12


监控云服务器配置方案 家用监控云端服务器_LPC_13