yeelink探究

对yeelink服务器上的相应数据进行改写,并用上位机查看。




#include 
#include 
#include 
#include 
#pragma comment(lib, "ws2_32.lib")
// 请求缓冲区和响应缓冲区
char http_request[1024] = { 0, };
char http_response[1024] = { 0, };
// 主机IP地址,也可以是主机域名
char remote_server[] = "api.yeelink.net";
// 文件地址 RESTFUL形式
char remote_path[] = "/v1.0/device/写自己的/sensor/写自己的/datapoints";//需要相应更改
// 用户密码
char apikey[] = "写自己的";//需要相应更改
int main(int argc, char **argv)
{WSADATA wsaData;int result;int socket_id;// 传感器检测结果double value = 5.9;// Http属性char http_attribute[64] = { 0, };// Http内容,表单内容char http_content[64] = { 0, };// 确定HTTP表单提交内容 {"value":20}sprintf_s(http_content, "{\"value\":%.2f}", value);// 确定 HTTP请求首部// 例如POST /v1.0/device/1949/sensor/2510/datapoints HTTP/1.1\r\nchar http_header[64] = { 0, };sprintf_s(http_header, "POST %s HTTP/1.1\r\n", remote_path);strcpy_s(http_request, http_header); // 复制到请求缓冲区中// 增加属性 例如 Host: api.yeelink.net\r\nsprintf_s(http_attribute, "Host:%s\r\n", remote_server);strcat_s(http_request, http_attribute);memset(http_attribute, 0, sizeof(http_attribute));// 增加密码 例如 U-ApiKey: ffa3826972d6cc7ba5b17e104ec59fa3sprintf_s(http_attribute, "U-ApiKey:%s\r\n", apikey);strcat_s(http_request, http_attribute);memset(http_attribute, 0, sizeof(http_attribute));// 增加提交表单内容的长度 例如 Content-Length:12\r\nsprintf_s(http_attribute, "Content-Length:%d\r\n", strlen(http_content));strcat_s(http_request, http_attribute);memset(http_attribute, 0, sizeof(http_attribute));// 增加表单编码格式 Content-Type:application/x-www-form-urlencoded\r\n// 该步骤可省略strcat_s(http_request, "Content-Type:application/x-www-form-urlencoded\r\n");memset(http_attribute, 0, sizeof(http_attribute));// HTTP首部和HTTP内容 分隔部分strcat_s(http_request, "\r\n");// HTTP负载内容strcat_s(http_request, http_content);// Winsows下启用socketresult = WSAStartup(MAKEWORD(2, 2), &wsaData);if (result != 0) {printf("WSAStartup failed: %d\n", result);return 1;}// DNS解析 获得远程IP地址struct hostent *remote_host;remote_host = gethostbyname(remote_server);if (remote_host == NULL){printf("DNS failed\r\n");return 1;}// 创建套接字socket_id = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in remote_sockaddr;remote_sockaddr.sin_family = AF_INET;remote_sockaddr.sin_port = htons(80);remote_sockaddr.sin_addr.s_addr = *(u_long *)remote_host->h_addr_list[0];memset(&(remote_sockaddr.sin_zero), 0, sizeof(remote_sockaddr.sin_zero));// 连接远程主机result = connect(socket_id, (struct sockaddr *)&remote_sockaddr, sizeof(struct sockaddr));if (result == SOCKET_ERROR){printf("connect ok\r\n");}// 发送请求printf("Http request:\r\n%s\r\n", http_request);printf("--------------------\r\n");send(socket_id, http_request, strlen(http_request), 0);// 获得响应int bytes_received = 0;bytes_received = recv(socket_id, http_response, 1024, 0);http_response[bytes_received] = '\0';printf("Receive Message:\r\n%s\r\n", http_response);printf("--------------------\r\n");// 判断是否收到HTTP OKchar* presult = strstr(http_response, "200 OK\r\n");if (presult != NULL) printf("Http response OK\r\n");// 关闭套接字closesocket(socket_id);WSACleanup();// 输入任何字符则关闭程序printf("Finish\r\n"); getchar();return 0;
}

上述代码为数据改写代码,在vs2013c/c++上运行可更改yeelink服务器其上相应数据。


#include 
#include 
#include 
#include 
#pragma comment(lib, "ws2_32.lib")
// 请求缓冲区和响应缓冲区
char http_request[1024] = { 0, };
char http_response[1024] = { 0, };
// 主机IP地址,也可以是主机域名
char remote_server[] = "api.yeelink.net";
// 文件地址 RESTFUL形式
char remote_path[] = "/v1.0/device/写自己的/sensor/写自己的/datapoints";
// 用户密码
char apikey[] = "写自己的";char test_http[1024] = { 0, };
char test_str[32];
int main(int argc, char **argv)
{WSADATA wsaData;int result;int socket_id;result = WSAStartup(MAKEWORD(2, 2), &wsaData);if (result != 0) {printf("WSAStartup failed: %d\n", result);return 1;}// DNS解析 获得远程IP地址struct hostent *remote_host;remote_host = gethostbyname(remote_server);if (remote_host == NULL){printf("DNS failed\r\n");return 1;}//printf("yeelink address: %s\n", inet_ntop(remote_host->h_addrtype, remote_host->h_addr_list, test_str, sizeof(test_str)));//test_http = "POST / v1.0 / device / 写自己的/ sensor / 写自己的 / datapoints HTTP / 1.1\r\nHost:api.yeelink.net\r\nU - ApiKey:写自己的\r\nContent - Length:14\r\nContent - Type:application / x - www - form - urlencoded\r\n\r\n{ \"value\":5.90}"sprintf_s(test_http, "POST /v1.0/device/写自己的/sensor/写自己的/datapoints HTTP/1.1\r\nHost:api.yeelink.net\r\nU-ApiKey:写自己的\r\nContent-Length:14\r\nContent-Type:application/x-www-form-urlencoded\r\n\r\n{\"value\":3.90}");// 创建套接字socket_id = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in remote_sockaddr;remote_sockaddr.sin_family = AF_INET;remote_sockaddr.sin_port = htons(80);remote_sockaddr.sin_addr.s_addr = *(u_long *)remote_host->h_addr_list[0];memset(&(remote_sockaddr.sin_zero), 0, sizeof(remote_sockaddr.sin_zero));// 连接远程主机result = connect(socket_id, (struct sockaddr *)&remote_sockaddr, sizeof(struct sockaddr));if (result == SOCKET_ERROR){printf("connect ok\r\n");}// 发送请求//printf("Http request:\r\n%s\r\n", http_request);//printf("--------------------\r\n");printf("test_http:\r\n%s\r\n", test_http);//自定义,需要修改printf("--------------------\r\n");send(socket_id, test_http, strlen(test_http), 0);// 获得响应int bytes_received = 0;bytes_received = recv(socket_id, http_response, 1024, 0);http_response[bytes_received] = '\0';printf("Receive Message:\r\n%s\r\n", http_response);printf("--------------------\r\n");// 判断是否收到HTTP OKchar* presult = strstr(http_response, "200 OK\r\n");if (presult != NULL) printf("Http response OK\r\n");// 关闭套接字closesocket(socket_id);WSACleanup();// 输入任何字符则关闭程序printf("Finish\r\n"); getchar();return 0;
}

第二段代码是对于第一段代码的改写。对比可以发现,整个程序的主要分以下几步



result = WSAStartup(MAKEWORD(2, 2), &wsaData);

1 开启windows自带的功能,固定格式。



remote_host = gethostbyname(remote_server);

2 将域名解析成ip,其中解析的ip地址可以用以下的方式打印出来

printf("yeelink address: %s\n", inet_ntop(remote_host->h_addrtype, remote_host->h_addr_list, test_str, sizeof(test_str)));




3 创建套接字,通过这步,我们得到了两个比较重要的东西:socket_id(不知道干啥) remote_sockaddr(remote_sockaddr.sin_addr.s_addr = *(u_long *)remote_host->h_addr_list[0]; 含有刚才解析的域名的ip)

// 创建套接字socket_id = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in remote_sockaddr;remote_sockaddr.sin_family = AF_INET;remote_sockaddr.sin_port = htons(80);remote_sockaddr.sin_addr.s_addr = *(u_long *)remote_host->h_addr_list[0];memset(&(remote_sockaddr.sin_zero), 0, sizeof(remote_sockaddr.sin_zero));



4 连接远程主机。利用上面已经得到的socket_id 和 remote_sockaddr连接主机

result = connect(socket_id, (struct sockaddr *)&remote_sockaddr, sizeof(struct sockaddr));


5 发送请求。

send(socket_id, test_http, strlen(test_http), 0);

这个请求是有一定格式的,控制相应变量的格式如下

POST /v1.0/device/写自己的/sensor/写自己的/datapoints HTTP/1.1
Host:api.yeelink.net
U-ApiKey:写自己的
Content-Length:14//根据设定的数据长度进行改变
Content-Type:application/x-www-form-urlencoded{"value":5.90}

获取相应变量的格式为

GET /v1.0/device/写自己的/sensor/写自己的/datapoints HTTP/1.1
Host:api.yeelink.net
U-ApiKey:写自己的
Accept: */*
Content-Type:application/x-www-form-urlencoded
Connection: close

只要在连接后,通过send函数将相应格式发送到yeelink服务器上,就能得到相应。


6 获得响应

	bytes_received = recv(socket_id, http_response, 1024, 0);http_response[bytes_received] = '\0';

运行之后http_reponse这个变量里面就包含了相应结果。对于获取数据,返回字符串里面就包含数据;对于设定数据,返回字符串里面包含数据设定的成功与否。




7 关闭套接字

closesocket(socket_id);


8 关闭第一步是运行的那个玩意儿

WSACleanup();





运行成功后显示如下

改写后yeelink平台也会有相应变化,这里就不展示了。


以上工程详见:控制yeelink服务器变量;控制yeelink服务器变量(原版)


下面是上位机的制作。上位机的主要功能是没一秒刷新一次结果(yeelink平台上的显示需要手动刷新,恨不爽)。下面是一个网上大神发布的上位机(无刷新)的截图,亲测好使。




以上工程详见:查看yeelink服务器变量


下图是我的上位机


我的上位机是自动刷新,每秒刷新一次。


以上工程详见:查看yeelink服务器变量(刷新)








本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部