您的位置:控制工程论坛网论坛 » 嵌入式系统 » 一步步教你使用云端服务器yeelink远程监控

wdf375791964

wdf375791964   |   当前状态:在线

总积分:80  2024年可用积分:0

注册时间: 2016-12-02

最后登录时间: 2017-01-12

空间 发短消息加为好友

一步步教你使用云端服务器yeelink远程监控

wdf375791964  发表于 2016/12/29 14:54:07      1424 查看 3 回复  [上一主题]  [下一主题]

手机阅读

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

下面是Yeelink远程监控的一个大致框图
 
1、首先进入Yeelink主页“http://www.yeelink.net/”注册一个自己的帐号,下面是主页为我们开发者提供的一个简单的开发流程
 

2、按照上面的流程点击添加设备,输入设备信息,在下面的地图中选择设备所在地
 
3、进入到设备管理界面,设置设备图片,添加传感器
 

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

6、进入我的账户找到API KEY,当要进行传输数据时需要使用到该密码
 

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

  1. ADC_Init();                                                        //        ADC初始化

  2.                 

  3. LPC_GPIO2->FIODIR  = 0x000000ff;    //        LED配置

  4. LPC_GPIO0->FIODIR  = 0x00200000;                                                         

  5. LPC_GPIO0->FIOPIN |= 0x00200000;                                                                     

  6. while(1)

  7. {

  8.         tcpclient("42.96.164.52",80 ,1);                //AD转换值上传                                                                

  9.         tcpclient("42.96.164.52",80 ,2);                //获取LED状态并改变开发板LED状态                        

  10.         rt_thread_delay(RT_TICK_PER_SECOND * 4);        //延时4s

  11. }                

  12. //TCP客户端实验

  13. int tcpclient(const char* url, int port,int num)

  14. {

  15.     char *recv_data;

  16.     struct hostent *host;

  17.     int sock, bytes_received;

  18.     struct sockaddr_in server_addr;

  19.         int        Buf = 0;


  20.     /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */

  21.     host = gethostbyname(url);


  22.     /* 分配用于存放接收数据的缓冲 */

  23.     recv_data = rt_malloc(BUFSZ);

  24.     if (recv_data == RT_NULL)

  25.     {

  26.         rt_kprintf("No memory\n");

  27.         return;

  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.         rt_free(recv_data);

  36.         return 1;

  37.     }

  38.         if(num == 1)                /

  39.         {

  40.                 Buf   = ADC_Get();                                                                    

  41.                 Buf = (Buf * 3300)/4096;

  42.                 INT_CHAR(Buf);                

  43.                 send_data1[234] = dis[0];                //更改上传数据内容即AD值

  44.                 send_data1[234+1] = '.';

  45.                 send_data1[234+2] = dis[0+1];

  46.                 send_data1[234+3] = dis[0+2];

  47.         }

  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.     while (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)

  56.     {

  57.         /* 连接失败 */

  58.         rt_kprintf("Connect fail!\n");

  59.         lwip_close(sock);


  60.          /*释放接收缓冲 */

  61.         rt_free(recv_data);

  62.                return 1;

  63.     }

  64.         rt_kprintf("Connect OK!\n");


  65.         if(num == 1)

  66.         {

  67.                 /* 发送数据到sock连接 */

  68.                 if(send(sock,send_data1,strlen(send_data1), 0) < 0)

  69.                 {

  70.                         /* 发送失败,关闭这个连接 */

  71.                         rt_kprintf("\nSend error ");

  72.                         lwip_close(sock);


  73.                         /* 释放接收缓冲 */

  74.                         rt_free(recv_data);

  75.                 }

  76.                 else

  77.                 {

  78.                         rt_kprintf("\nSend OK ");

  79.                         bytes_received = recv(sock, recv_data, BUFSZ - 1, 0);

  80.                         lwip_close(sock);


  81.                         /* 释放接收缓冲 */

  82.                         rt_free(recv_data);

  83.                 }

  84.         }

  85.         else if(num == 2)

  86.         {

  87.                 /* 发送数据到sock连接 */

  88.                 if(send(sock,send_data2,strlen(send_data2), 0) < 0)

  89.                 {

  90.                         /* 发送失败,关闭这个连接 */

  91.                         rt_kprintf("\nSend error ");

  92.                         lwip_close(sock);


  93.                         /* 释放接收缓冲 */

  94.                         rt_free(recv_data);

  95.                 }

  96.                 else

  97.                 {

  98.                         rt_kprintf("\nSend OK ");

  99.                         /* 从sock连接中接收最大BUFSZ - 1字节数据 */

  100.                 bytes_received = recv(sock, recv_data, BUFSZ - 1, 0);

  101.                         Buf = Search_str(recv_data,"\"value\":");

  102.                         if(recv_data[Buf] == '0')

  103.                                 LPC_GPIO2->FIOPIN &= ~0xff;                        //关闭LED

  104.                         else

  105.                                 LPC_GPIO2->FIOPIN |= 0xff;                        //打开LED

  106.                         rt_kprintf("\n%s ",recv_data+Buf);

  107.                         lwip_close(sock);


  108.                         /* 释放接收缓冲 */

  109.                         rt_free(recv_data);

  110.                 }

  111.         }                        

  112.     return 1;

  113. }

复制代码



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

  1. char send_data1[300] = "POST /v1.0/device/12402/sensor/20165/datapoints HTTP/1.1\r\n\

  2. Host: api.yeelink.net\r\n\

  3. Accept: */*\r\n\

  4. U-ApiKey: 615e52feacb3a8b18ab424703c00bfbf\r\n\

  5. Content-Length: 14\r\n\

  6. Content-Type: application/json;charset=utf-8\r\n\

  7. Connection: close\r\n\

  8. \r\n\

  9. {\"value\":96  }\r\n"; /* 发送用到的数据 */

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

  11. 这里初始化是”96  “

  12. char send_data2[300] = "GET /v1.0/device/12402/sensor/20166/datapoints HTTP/1.1\r\n\

  13. Host: api.yeelink.net\r\n\

  14. Accept: */*\r\n\

  15. U-ApiKey: 615e52feacb3a8b18ab424703c00bfbf\r\n\

  16. Content-Length: 0\r\n\

  17. Connection: close\r\n\

  18. \r\n\

  19. print get done.\r\n"; /* 发送用到的数据 */

复制代码



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


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

手机可以查看设备地址
 
 


下面在看一下LED控制
 


1楼 0 0 回复
总共 , 当前 /