(转)linux下和云端通讯的例程, ubuntu和openwrt实验成功(一)

一.  HTTP请求的数据流总结
#上传数据, yeelink的数据流如下
POST /v1.0/device/4420/sensor/9089/datapoints HTTP/1.1
Host: api.yeelink.net
U-ApiKey: 729d1ba15b26b6a48f4807ef3f2f4df4
Content-Length: 49
Content-Type: application/x-www-form-urlencoded
Connection: Close

{"timestamp":"2013-07-23T06:04:15","value":21.9}

#上传数据, lewer50的数据流如下
POST /api/V1/gateway/UpdateSensors/01 HTTP/1.1
Host: www.lewei50.com
userkey: 36be8ff22f794f1e8a0bee3336eef237
Content-Length: 31
Content-Type: application/x-www-form-urlencoded
Connection: Close

[{"Name":"T1","Value":"24.02"}]

三. 代码如下, 公用的 http_clound.h

点击(此处)折叠或打开

  1. /*----------------------------------------------------------------------------------------------------
  2. 云端查询: http://www.yeelink.net/devices/4420, http://www.lewei50.com/u/g/2375
  3. #调用例程
  4. float current_temp = 24.02;
  5. yeelink_create_data(YEELINK_DEVICE_ID, YEELINK_SENSOR_ID, current_temp);
  6. lewei50_create_data(LEWEI50_DEVICE_ID, current_temp);
  7. linux下三种方法和云端通讯:
  8. 1. 纯利用linux的网络函数
  9. 2. 利用libcurl的发送和接收函数
  10. 3. 利用libcurl的回调机制
  11. #上传数据, yeelink的字符流如下
  12. POST /v1.0/device/4420/sensor/9089/datapoints HTTP/1.1
  13. Host: api.yeelink.net
  14. U-ApiKey: 729d1ba15b26b6a48f4807ef3f2f4df4
  15. Content-Length: 49
  16. Content-Type: application/x-www-form-urlencoded
  17. Connection: Close
  18. {"timestamp":"2013-07-23T06:04:15","value":21.9}
  19. #上传数据, lewer50的字符流如下
  20. POST /api/V1/gateway/UpdateSensors/01 HTTP/1.1
  21. Host: www.lewei50.com
  22. userkey: 36be8ff22f794f1e8a0bee3336eef237
  23. Content-Length: 31
  24. Content-Type: application/x-www-form-urlencoded
  25. Connection: Close
  26. [{"Name":"T1","Value":"24.02"}]
  27. lewei50 ret = {"Successful":true,"Message":"Warning: T1\u0027s frequency limit is 10s; "}
  28. V1.0 2013-11-5 初步实现了上面三种方法的Demo.
  29. 错误: bfe06000-bfe1b000 rw-p 00000000 00:00 0 [stack], 修改: char pc_ret[200] -> char pc_ret[500]
  30. -----------------------------------------------------------------------------------------------------*/
  31. #ifndef HTTP_CLOUD_H
  32. #define HTTP_CLOUD_H
  33. //有replace的地方换成自己的参数
  34. #define YEELINK (1)    //www.yeelink.net
  35. #define LEWEI50 (1)    //www.lewei50.com
  36. #if (YEELINK == 1)
  37. #define YEELINK_URL            "http://api.yeelink.net"
  38. #define YEELINK_HOST        "api.yeelink.net"        //网址, 由此获得公网IP
  39. #define YEELINK_PORT        80
  40. #define YEELINK_API_KEY "729d1ba15b26b6a48f4807ef3f2f4df4" //replace your yeelink api key here.
  41. #define YEELINK_DEVICE_ID                4420 //replace your device ID
  42. #define YEELINK_SENSOR_ID                9089 //replace your sensor ID
  43. #endif
  44. #if (LEWEI50 == 1)
  45. #define LEWEI50_GATEWAY     01        //网关号
  46. #define LEWEI50_URL             "http://www.lewei50.com/api/V1/gateway/UpdateSensors/01"
  47. #define LEWEI50_HOST            "www.lewei50.com"        //网址, 由此获得公网IP
  48. #define LEWEI50_PORT            80
  49. #define LEWEI50_HOST_FILE    "api/V1/gateway/UpdateSensors/01"
  50. #define LEWEI50_USER_KEY     "36be8ff22f794f1e8a0bee3336eef237"    //replace your lewei50 key here.
  51. #define LEWEI50_DEVICE_ID "T1"                                                                //replace your device ID
  52. #endif
  53. #define DATA_CREATE     (0)    //创建数据点
  54. #define DATA_MODIFY     (1)    //修改数据点
  55. #define DATA_QUERY         (2)    //查询数据点
  56. #define HTTP_GET "GET"
  57. #define HTTP_PUT "PUT"
  58. #define HTTP_HEAD "HEAD"
  59. #define HTTP_POST "POST"
  60. #define HTTP_DELETE "DELETE"
  61. #define MAX_SEND_BUFFER_SIZE            (2 * 1024 * 1024)
  62. #define MAX_RECV_BUFFER_SIZE            (2 * 1024 * 1024)
  63. #define MAX_HEADER_BUFFER_SIZE        (128 * 1024)
  64. //http请求与接受的buffer总体结构
  65. //param_buffer_t中buffer的内容
  66. typedef struct {
  67. char *ptr; /**< 缓冲区首指针 */
  68. FILE *fp; /**< 文件指针 */
  69. unsigned int left; /** 缓冲区剩余大小 */
  70. unsigned int allocated; /** 缓冲区总大小 */
  71. unsigned short code; /**返回码 */
  72. } param_buffer_t;
  73. typedef struct {
  74. param_buffer_t *send_buffer; /**< send buffer */
  75. param_buffer_t *recv_buffer; /**< receive buffer */
  76. param_buffer_t *header_buffer; /**< header buffer */
  77. } curl_request_param_t;
  78. extern int yeelink_create_data(const int device_id, const int sensor_id, const float device_value);
  79. extern int lewei50_create_data(const char *device_id, const float device_value);
  80. #endif

纯利用linux的网络函数实现的代码如下

点击(此处)折叠或打开

  1. /*----------------------------------------------------------------------------------------------------
  2. 直接利用linux的内部函数实现云端通讯, 另外可以利用libcurl的API.
  3. -----------------------------------------------------------------------------------------------------*/
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <errno.h>
  10. #include <unistd.h>
  11. #include <netinet/in.h>
  12. #include <limits.h>
  13. #include <netdb.h>
  14. #include <arpa/inet.h>
  15. #include <ctype.h>
  16. #include <time.h>
  17. #include <assert.h>
  18. #include "../http_cloud.h"
  19. #define DBG printf
  20. //-----------------------------------------------------------------------------------------
  21. static void get_local_time(char *pc_str)
  22. {
  23. time_t now;
  24. struct tm *timenow;
  25. assert(pc_str != NULL);
  26. time(&now);
  27. timenow = localtime(&now);
  28. sprintf(pc_str, "%04d-%02d-%02dT%02d:%02d:%02d", timenow->tm_year+1900, timenow->tm_mon+1, timenow->tm_mday,
  29. timenow->tm_hour, timenow->tm_min, timenow->tm_sec);
  30. }
  31. //连接云端: host_addr:网址(如api.yeelink.net), portno:端口号(一般为80), request: 完整的请求
  32. //返回参数: \r\n\r\n之后的数据, 一般为有效数据, 如{"Successful":true,"Message":"Successful. "}
  33. static char connect_cloud(char *pc_ret, const char *host_addr, const int portno, const char *request)
  34. {
  35. int sockfd = 0;
  36. char buffer[1024] = "";
  37. struct sockaddr_in server_addr;
  38. struct hostent *host;
  39. //int portno = 80;    //默认端口
  40. int nbytes = 0;
  41. //char host_addr[256] = "";
  42. //char host_file[1024] = "";
  43. char pc_tmp[1024] = "";
  44. int send = 0, totalsend = 0;
  45. int i = 0, iLen = 0, iRet = 0, iPos = 0, mark_num;
  46. assert((pc_ret != NULL) && (host_addr != NULL) && (request != NULL));
  47. //由host_addr取得主机IP地址
  48. if((host = gethostbyname(host_addr)) == NULL) {
  49. fprintf(stderr, "Gethostname error, %s\n ", strerror(errno));
  50. exit(1);
  51. }
  52. //客户程序开始建立sockfd描述符,建立SOCKET连接
  53. if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  54. fprintf(stderr, "Socket Error:%s\a\n ",strerror(errno));
  55. exit(1);
  56. }
  57. //客户程序填充服务端的资料
  58. bzero(&server_addr, sizeof(server_addr));
  59. server_addr.sin_family = AF_INET;
  60. server_addr.sin_port = htons(portno);
  61. server_addr.sin_addr = *((struct in_addr*)host->h_addr);
  62. //DBG("server_addr.sin_addr = %08X\n", server_addr.sin_addr);    //server_addr.sin_addr = CB3888CA
  63. //客户程序发起连接请求, 连接网站
  64. if(connect(sockfd, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr)) == -1) {
  65. fprintf(stderr, "Connect Error:%s\a\n ",strerror(errno));
  66. exit(1);
  67. }
  68. //发送http请求request
  69. send = 0;
  70. totalsend = 0;
  71. nbytes = strlen(request);
  72. while(totalsend < nbytes)
  73. {
  74. send = write(sockfd, request+totalsend, nbytes-totalsend);
  75. if(send == -1) {
  76. DBG( "send error!%s\n ", strerror(errno));
  77. exit(0);
  78. }
  79. totalsend += send;
  80. //DBG("%d bytes send OK!\n ", totalsend);
  81. }
  82. //DBG( "\nThe following is the response header:\n");
  83. i = 0;
  84. mark_num = 4;        //正常=4,
  85. //连接成功了,接收http响应
  86. while((nbytes = read(sockfd, buffer, 1)) == 1)
  87. {
  88. //DBG("%c", buffer[0]);
  89. if(i < mark_num) {
  90. if(buffer[0] == ‘\r‘ || buffer[0] == ‘\n‘) {
  91. i++;
  92. //DBG("i = %d, ", i);
  93. if (iRet == 0) {
  94. pc_tmp[iPos] = ‘\0‘;
  95. if (!strcmp(pc_tmp, "HTTP/1.1 200 OK")) {
  96. iRet = 1;
  97. }
  98. }
  99. }
  100. else {
  101. i = 0;    //新行重新计数
  102. pc_tmp[iPos++] = buffer[0];
  103. }
  104. }
  105. else {
  106. pc_ret[iLen++] = buffer[0];    //获取有效数据
  107. }
  108. }
  109. close(sockfd);
  110. pc_ret[iLen] = ‘\0‘;
  111. DBG("\nret(%d): %s\n", iLen, pc_ret);
  112. return(iRet);
  113. }
  114. #if (YEELINK == 1)
  115. int yeelink_create_data(const int device_id, const int sensor_id, const float device_value)
  116. {
  117. char pc_ret[200], request[1024], pc_json[100], pc_time[30], pc_host_file[100], pc_header[100], ret;
  118. int len;
  119. sprintf(pc_host_file, "v1.0/device/%d/sensor/%d/datapoints", device_id, sensor_id);
  120. sprintf(pc_header, "U-ApiKey: %s", YEELINK_API_KEY);
  121. get_local_time(pc_time);
  122. sprintf(pc_json, "{\"timestamp\":\"%s\",\"value\":%.2f}", pc_time, device_value);
  123. len = strlen(pc_json);
  124. sprintf(request, "POST /%s HTTP/1.1\r\nHost: %s\r\nAccept: */*\r\n%s\r\nContent-Length: %d\r\nContent-Type: application/x-www-form-urlencoded\r\nConnection: Close\r\n\r\n%s\r\n",
  125. pc_host_file, YEELINK_HOST, pc_header, len, pc_json);
  126. DBG("request = %s\n", request);
  127. ret = connect_cloud(pc_ret, YEELINK_HOST, YEELINK_PORT, request);
  128. return(ret);
  129. }
  130. #endif
  131. #if (LEWEI50 == 1)
  132. //curl --request POST http://www.lewei50.com/api/V1/Gateway/UpdateSensors/01 --data "[{\"Name\":\"T1\",\"Value\":\"23.08\"}]" --header "userkey:36be8ff22f794f1e8a0bee3336eef237"
  133. int lewei50_create_data(const char *device_id, const float device_value)
  134. {
  135. char pc_ret[200], request[1024], pc_json[100], pc_header[100], ret;
  136. int len;
  137. assert(device_id != NULL);
  138. sprintf(pc_header, "userkey: %s", LEWEI50_USER_KEY);
  139. sprintf(pc_json, "[{\"Name\":\"%s\",\"Value\":\"%.2f\"}]", device_id, device_value);
  140. len = strlen(pc_json);
  141. sprintf(request, "POST /%s HTTP/1.1\r\nHost: %s\r\nAccept: */*\r\n%s\r\nContent-Length: %d\r\nContent-Type: application/x-www-form-urlencoded\r\nConnection: Close\r\n\r\n%s\r\n",
  142. LEWEI50_HOST_FILE, LEWEI50_HOST, pc_header, len, pc_json);
  143. DBG("request = %s\n", request);
  144. ret = connect_cloud(pc_ret, LEWEI50_HOST, LEWEI50_PORT, request);
  145. return(ret);
  146. }
  147. #endif
  148. //-------------------------------------------------------------------
  149. int main(void)
  150. {
  151. float f_value = 15.02;
  152. int i_tmp;
  153. time_t t;
  154. srand((unsigned)time(&t));    //初始化随机种子, 否则随机数不随机
  155. i_tmp = rand();
  156. i_tmp -= (i_tmp >> 4 << 4);
  157. f_value += i_tmp;
  158. #if (YEELINK == 1)
  159. yeelink_create_data(YEELINK_DEVICE_ID, YEELINK_SENSOR_ID, f_value);
  160. #endif
  161. #if (LEWEI50 == 1)
  162. lewei50_create_data(LEWEI50_DEVICE_ID, f_value);
  163. #endif
  164. return 1;
  165. }

四. 编译, Makefile如下,
OPENWRT = 0 时目标文件运行下ubuntu下了.

点击(此处)折叠或打开

  1. OPENWRT = 1
  2. ifeq ($(OPENWRT), 1)
  3. CC = ~/OpenWrt-SDK-ar71xx-for-linux-i486-gcc-4.6-linaro_uClibc-0.9.33.2/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-gcc
  4. CFLAGS += -I ~/openwrt-lib/include -L ~/openwrt-lib/lib
  5. else
  6. CC = gcc
  7. endif
  8. CFLAGS += -Wall -O2
  9. #CFLAGS += -g
  10. #可执行文件名和相关的obj文件
  11. APP_BINARY = http_cloud
  12. SRCS += http_cloud.c
  13. OBJS = $(SRCS:.c=.o)
  14. all: APP_FILE
  15. APP_FILE: $(OBJS)
  16. $(CC) $(CFLAGS) $(OBJS) -o $(APP_BINARY) $(LFLAGS)
  17. .PHONY: clean
  18. clean:
  19. @echo "cleanning project"
  20. $(RM) *.a $(OBJS) *~ *.so *.lo $(APP_BINARY)
  21. @echo "clean completed"

编译过程:
[email protected]:~/1-wire/http_cloud/linux_only$ make
gcc -Wall -O2   -c -o http_cloud.o http_cloud.c
gcc -Wall -O2 http_cloud.o -o http_cloud

运行结果:
[email protected]:~/1-wire/http_cloud/linux_only$ ./http_cloud
request = POST /v1.0/device/4420/sensor/9089/datapoints HTTP/1.1
Host: api.yeelink.net
Accept: */*
U-ApiKey: 729d1ba15b26b6a48f4807ef3f2f4df4
Content-Length: 49
Content-Type: application/x-www-form-urlencoded
Connection: Close

{"timestamp":"2013-11-05T14:32:48","value":16.02}

ret(5): 0

request = POST /api/V1/gateway/UpdateSensors/01 HTTP/1.1
Host: www.lewei50.com
Accept: */*
userkey: 36be8ff22f794f1e8a0bee3336eef237
Content-Length: 31
Content-Type: application/x-www-form-urlencoded
Connection: Close

[{"Name":"T1","Value":"16.02"}]

ret(44): {"Successful":true,"Message":"Successful. "}
[email protected]:~/1-wire/http_cloud/linux_only$



这个只是第一部分的实验, 后续的还有利用libcurl库的实现代码.

时间: 2024-11-09 00:30:53

(转)linux下和云端通讯的例程, ubuntu和openwrt实验成功(一)的相关文章

(转)linux下和云端通讯的例程, ubuntu和openwrt下实验成功(二)

前言: 上节用纯linux的函数实现了和云端通讯, 本节开始利用传说中的神器libcurl 话说一个网络程序员对书法十分感兴趣,退休后决定在这方面有所建树. 于是花重金购买了上等的文房四宝.    一日,饭后突生雅兴,一番磨墨拟纸,  并点上了上好的檀香,颇有王羲之风范,  又具颜真卿气势,定神片刻,泼墨挥毫,    郑重地写下一行字:libcurl. 由此可知libcurl的刻骨铭心! 官方文档请参考这里 http://curl.haxx.se/libcurl/c/curl_easy_seto

(转)利用libcurl和国内著名的两个物联网云端通讯的例程, ubuntu和openwrt下调试成功(四)

1. libcurl 的参考文档如下 CURLOPT_HEADERFUNCTION Pass a pointer to a function that matches the following prototype: size_t function( void *ptr, size_t size, size_t nmemb, void *userdata);. This function gets called by libcurl as soon as it has received head

openwrt下和云端通讯的例程,

openwrt下和云端通讯的例程 ibcurl 官方文档请参考这里 http://curl.haxx.se/libcurl/c/curl_easy_setopt.html 刚接触 libcurl的时候, 自然的想到按照常规的思路来连接云端: 先连接Web, 再发送请求, 然后等待接受返回数据.  这样思路的代码如下 点击(此处)折叠或打开 /*-----------------------------------------------------------------------------

(转)利用libcurl获取新浪股票接口, ubuntu和openwrt实验成功(三)

1.  利用 CURLOPT_WRITEFUNCTION 设置回调函数, 利用 CURLOPT_WRITEDATA 获取数据指针 官网文档如下 CALLBACK OPTIONS CURLOPT_WRITEFUNCTION Pass a pointer to a function that matches the following prototype: size_t function( char *ptr, size_t size, size_t nmemb, void *userdata); 

ahjesus SSHkey登陆linux服务器,无需密码,ubuntu

cd ~/.ssh/如果目录不存在就新建一个 mkdir ~/.ssh制作公匙 ssh-keygen -t rsa默认会生成id_rsa.pub的公匙将公匙推送到指定的服务器 scp id_rsa.pub [email protected]:~/.ssh/id_rsa.pub登录到服务器 ssh [email protected]执行如下命令cd ~/.sshcat id_rsa.pub >> authorized_keys销毁目录下公匙 rm id_rsa.pub退出服务器 exit 下次登

linux进程间通讯-System V IPC 信号量

进程间通信的机制--信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信--使用信号.下面就进入信号量的讲解. 一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临界区域是指执行数据更新的代码需要独占式地执行.而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在

关于在Linux mint(应该所有基于ubuntu的发行版都是这样子)jade安装使用问题

本文出自blog.csdn.net/svitter jade是什么? 模板引擎 如何在Ubuntu下使用? github上给的答案是 使用 npm install jade 来安装使用. 但是在ubuntu下没有办法直接在命令行使用jade. 你需要找到~/node_modules/jade/bin下的jade.js 如果使用deb安装的node,那么node在命令行下为js 希望不正确之处大家给予指正_(:3」∠)_ 关于在Linux mint(应该所有基于ubuntu的发行版都是这样子)ja

[笔记]linux下和windows下的 创建线程函数

linux下和windows下的 创建线程函数 1 #ifdef __GNUC__ 2 //Linux 3 #include <pthread.h> 4 #define CreateThreadEx(tid,threadFun,args) pthread_create(tid, 0, threadFun, args) 5 #define CloseHandle(ph) 6 7 int pthread_create( 8 //指向线程标识符的指针. 9 pthread_t *restrict t

[转载]Ubuntu Linux 入门(四):Ubuntu 初始设置

转载自http://terrychen.info/ubuntu-linux-beginners-guide-finetuning-ubuntu/ 在Ubuntu Linux 入门(三):熟悉 Ubuntu Linux 桌面环境一文中,我们已经基本了解 Ubuntu 的桌面环境,但是要开始使用 Ubuntu Linux 之前,我们还需要对 Ubuntu 进行一定的设置. 虽然 Ubuntu 有两种不同的桌面,但是对 Ubuntu 进行设置的方法在两种不同的桌面环境之下是完全一致的.完成以下设置只要