(转)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
点击(此处)折叠或打开
- /*----------------------------------------------------------------------------------------------------
- 云端查询: http://www.yeelink.net/devices/4420, http://www.lewei50.com/u/g/2375
- #调用例程
- float current_temp = 24.02;
- yeelink_create_data(YEELINK_DEVICE_ID, YEELINK_SENSOR_ID, current_temp);
- lewei50_create_data(LEWEI50_DEVICE_ID, current_temp);
- linux下三种方法和云端通讯:
- 1. 纯利用linux的网络函数
- 2. 利用libcurl的发送和接收函数
- 3. 利用libcurl的回调机制
- #上传数据, 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"}]
- lewei50 ret = {"Successful":true,"Message":"Warning: T1\u0027s frequency limit is 10s; "}
- V1.0 2013-11-5 初步实现了上面三种方法的Demo.
- 错误: bfe06000-bfe1b000 rw-p 00000000 00:00 0 [stack], 修改: char pc_ret[200] -> char pc_ret[500]
- -----------------------------------------------------------------------------------------------------*/
- #ifndef HTTP_CLOUD_H
- #define HTTP_CLOUD_H
- //有replace的地方换成自己的参数
- #define YEELINK (1) //www.yeelink.net
- #define LEWEI50 (1) //www.lewei50.com
- #if (YEELINK == 1)
- #define YEELINK_URL "http://api.yeelink.net"
- #define YEELINK_HOST "api.yeelink.net" //网址, 由此获得公网IP
- #define YEELINK_PORT 80
- #define YEELINK_API_KEY "729d1ba15b26b6a48f4807ef3f2f4df4" //replace your yeelink api key here.
- #define YEELINK_DEVICE_ID 4420 //replace your device ID
- #define YEELINK_SENSOR_ID 9089 //replace your sensor ID
- #endif
- #if (LEWEI50 == 1)
- #define LEWEI50_GATEWAY 01 //网关号
- #define LEWEI50_URL "http://www.lewei50.com/api/V1/gateway/UpdateSensors/01"
- #define LEWEI50_HOST "www.lewei50.com" //网址, 由此获得公网IP
- #define LEWEI50_PORT 80
- #define LEWEI50_HOST_FILE "api/V1/gateway/UpdateSensors/01"
- #define LEWEI50_USER_KEY "36be8ff22f794f1e8a0bee3336eef237" //replace your lewei50 key here.
- #define LEWEI50_DEVICE_ID "T1" //replace your device ID
- #endif
- #define DATA_CREATE (0) //创建数据点
- #define DATA_MODIFY (1) //修改数据点
- #define DATA_QUERY (2) //查询数据点
- #define HTTP_GET "GET"
- #define HTTP_PUT "PUT"
- #define HTTP_HEAD "HEAD"
- #define HTTP_POST "POST"
- #define HTTP_DELETE "DELETE"
- #define MAX_SEND_BUFFER_SIZE (2 * 1024 * 1024)
- #define MAX_RECV_BUFFER_SIZE (2 * 1024 * 1024)
- #define MAX_HEADER_BUFFER_SIZE (128 * 1024)
- //http请求与接受的buffer总体结构
- //param_buffer_t中buffer的内容
- typedef struct {
- char *ptr; /**< 缓冲区首指针 */
- FILE *fp; /**< 文件指针 */
- unsigned int left; /** 缓冲区剩余大小 */
- unsigned int allocated; /** 缓冲区总大小 */
- unsigned short code; /**返回码 */
- } param_buffer_t;
- typedef struct {
- param_buffer_t *send_buffer; /**< send buffer */
- param_buffer_t *recv_buffer; /**< receive buffer */
- param_buffer_t *header_buffer; /**< header buffer */
- } curl_request_param_t;
- extern int yeelink_create_data(const int device_id, const int sensor_id, const float device_value);
- extern int lewei50_create_data(const char *device_id, const float device_value);
- #endif
纯利用linux的网络函数实现的代码如下
点击(此处)折叠或打开
- /*----------------------------------------------------------------------------------------------------
- 直接利用linux的内部函数实现云端通讯, 另外可以利用libcurl的API.
- -----------------------------------------------------------------------------------------------------*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <errno.h>
- #include <unistd.h>
- #include <netinet/in.h>
- #include <limits.h>
- #include <netdb.h>
- #include <arpa/inet.h>
- #include <ctype.h>
- #include <time.h>
- #include <assert.h>
- #include "../http_cloud.h"
- #define DBG printf
- //-----------------------------------------------------------------------------------------
- static void get_local_time(char *pc_str)
- {
- time_t now;
- struct tm *timenow;
- assert(pc_str != NULL);
- time(&now);
- timenow = localtime(&now);
- sprintf(pc_str, "%04d-%02d-%02dT%02d:%02d:%02d", timenow->tm_year+1900, timenow->tm_mon+1, timenow->tm_mday,
- timenow->tm_hour, timenow->tm_min, timenow->tm_sec);
- }
- //连接云端: host_addr:网址(如api.yeelink.net), portno:端口号(一般为80), request: 完整的请求
- //返回参数: \r\n\r\n之后的数据, 一般为有效数据, 如{"Successful":true,"Message":"Successful. "}
- static char connect_cloud(char *pc_ret, const char *host_addr, const int portno, const char *request)
- {
- int sockfd = 0;
- char buffer[1024] = "";
- struct sockaddr_in server_addr;
- struct hostent *host;
- //int portno = 80; //默认端口
- int nbytes = 0;
- //char host_addr[256] = "";
- //char host_file[1024] = "";
- char pc_tmp[1024] = "";
- int send = 0, totalsend = 0;
- int i = 0, iLen = 0, iRet = 0, iPos = 0, mark_num;
- assert((pc_ret != NULL) && (host_addr != NULL) && (request != NULL));
- //由host_addr取得主机IP地址
- if((host = gethostbyname(host_addr)) == NULL) {
- fprintf(stderr, "Gethostname error, %s\n ", strerror(errno));
- exit(1);
- }
- //客户程序开始建立sockfd描述符,建立SOCKET连接
- if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
- fprintf(stderr, "Socket Error:%s\a\n ",strerror(errno));
- exit(1);
- }
- //客户程序填充服务端的资料
- bzero(&server_addr, sizeof(server_addr));
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = htons(portno);
- server_addr.sin_addr = *((struct in_addr*)host->h_addr);
- //DBG("server_addr.sin_addr = %08X\n", server_addr.sin_addr); //server_addr.sin_addr = CB3888CA
- //客户程序发起连接请求, 连接网站
- if(connect(sockfd, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr)) == -1) {
- fprintf(stderr, "Connect Error:%s\a\n ",strerror(errno));
- exit(1);
- }
- //发送http请求request
- send = 0;
- totalsend = 0;
- nbytes = strlen(request);
- while(totalsend < nbytes)
- {
- send = write(sockfd, request+totalsend, nbytes-totalsend);
- if(send == -1) {
- DBG( "send error!%s\n ", strerror(errno));
- exit(0);
- }
- totalsend += send;
- //DBG("%d bytes send OK!\n ", totalsend);
- }
- //DBG( "\nThe following is the response header:\n");
- i = 0;
- mark_num = 4; //正常=4,
- //连接成功了,接收http响应
- while((nbytes = read(sockfd, buffer, 1)) == 1)
- {
- //DBG("%c", buffer[0]);
- if(i < mark_num) {
- if(buffer[0] == '\r' || buffer[0] == '\n') {
- i++;
- //DBG("i = %d, ", i);
- if (iRet == 0) {
- pc_tmp[iPos] = '\0';
- if (!strcmp(pc_tmp, "HTTP/1.1 200 OK")) {
- iRet = 1;
- }
- }
- }
- else {
- i = 0; //新行重新计数
- pc_tmp[iPos++] = buffer[0];
- }
- }
- else {
- pc_ret[iLen++] = buffer[0]; //获取有效数据
- }
- }
- close(sockfd);
- pc_ret[iLen] = '\0';
- DBG("\nret(%d): %s\n", iLen, pc_ret);
- return(iRet);
- }
- #if (YEELINK == 1)
- int yeelink_create_data(const int device_id, const int sensor_id, const float device_value)
- {
- char pc_ret[200], request[1024], pc_json[100], pc_time[30], pc_host_file[100], pc_header[100], ret;
- int len;
- sprintf(pc_host_file, "v1.0/device/%d/sensor/%d/datapoints", device_id, sensor_id);
- sprintf(pc_header, "U-ApiKey: %s", YEELINK_API_KEY);
- get_local_time(pc_time);
- sprintf(pc_json, "{\"timestamp\":\"%s\",\"value\":%.2f}", pc_time, device_value);
- len = strlen(pc_json);
- 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",
- pc_host_file, YEELINK_HOST, pc_header, len, pc_json);
- DBG("request = %s\n", request);
- ret = connect_cloud(pc_ret, YEELINK_HOST, YEELINK_PORT, request);
- return(ret);
- }
- #endif
- #if (LEWEI50 == 1)
- //curl --request POST http://www.lewei50.com/api/V1/Gateway/UpdateSensors/01 --data "[{\"Name\":\"T1\",\"Value\":\"23.08\"}]" --header "userkey:36be8ff22f794f1e8a0bee3336eef237"
- int lewei50_create_data(const char *device_id, const float device_value)
- {
- char pc_ret[200], request[1024], pc_json[100], pc_header[100], ret;
- int len;
- assert(device_id != NULL);
- sprintf(pc_header, "userkey: %s", LEWEI50_USER_KEY);
- sprintf(pc_json, "[{\"Name\":\"%s\",\"Value\":\"%.2f\"}]", device_id, device_value);
- len = strlen(pc_json);
- 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",
- LEWEI50_HOST_FILE, LEWEI50_HOST, pc_header, len, pc_json);
- DBG("request = %s\n", request);
- ret = connect_cloud(pc_ret, LEWEI50_HOST, LEWEI50_PORT, request);
- return(ret);
- }
- #endif
- //-------------------------------------------------------------------
- int main(void)
- {
- float f_value = 15.02;
- int i_tmp;
- time_t t;
- srand((unsigned)time(&t)); //初始化随机种子, 否则随机数不随机
- i_tmp = rand();
- i_tmp -= (i_tmp >> 4 << 4);
- f_value += i_tmp;
- #if (YEELINK == 1)
- yeelink_create_data(YEELINK_DEVICE_ID, YEELINK_SENSOR_ID, f_value);
- #endif
- #if (LEWEI50 == 1)
- lewei50_create_data(LEWEI50_DEVICE_ID, f_value);
- #endif
- return 1;
- }
四. 编译, Makefile如下,
OPENWRT = 0 时目标文件运行下ubuntu下了.
点击(此处)折叠或打开
- OPENWRT = 1
- ifeq ($(OPENWRT), 1)
- 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
- CFLAGS += -I ~/openwrt-lib/include -L ~/openwrt-lib/lib
- else
- CC = gcc
- endif
- CFLAGS += -Wall -O2
- #CFLAGS += -g
- #可执行文件名和相关的obj文件
- APP_BINARY = http_cloud
- SRCS += http_cloud.c
- OBJS = $(SRCS:.c=.o)
- all: APP_FILE
- APP_FILE: $(OBJS)
- $(CC) $(CFLAGS) $(OBJS) -o $(APP_BINARY) $(LFLAGS)
- .PHONY: clean
- clean:
- @echo "cleanning project"
- $(RM) *.a $(OBJS) *~ *.so *.lo $(APP_BINARY)
- @echo "clean completed"
编译过程:
xxg@xxg-desktop:~/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
运行结果:
xxg@xxg-desktop:~/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. "}
xxg@xxg-desktop:~/1-wire/http_cloud/linux_only$
这个只是第一部分的实验, 后续的还有利用libcurl库的实现代码.
(转)linux下和云端通讯的例程, ubuntu和openwrt实验成功(一)的更多相关文章
- (转)linux下和云端通讯的例程, ubuntu和openwrt下实验成功(二)
前言: 上节用纯linux的函数实现了和云端通讯, 本节开始利用传说中的神器libcurl 话说一个网络程序员对书法十分感兴趣,退休后决定在这方面有所建树. 于是花重金购买了上等的文房四宝. 一 ...
- (转)利用libcurl和国内著名的两个物联网云端通讯的例程, ubuntu和openwrt下调试成功(四)
1. libcurl 的参考文档如下 CURLOPT_HEADERFUNCTION Pass a pointer to a function that matches the following pr ...
- openwrt下和云端通讯的例程,
openwrt下和云端通讯的例程 ibcurl 官方文档请参考这里 http://curl.haxx.se/libcurl/c/curl_easy_setopt.html 刚接触 libcurl的时候 ...
- (转)利用libcurl获取新浪股票接口, ubuntu和openwrt实验成功(三)
1. 利用 CURLOPT_WRITEFUNCTION 设置回调函数, 利用 CURLOPT_WRITEDATA 获取数据指针 官网文档如下 CALLBACK OPTIONS CURLOPT_WRI ...
- [笔记]linux下和windows下的 创建线程函数
linux下和windows下的 创建线程函数 #ifdef __GNUC__ //Linux #include <pthread.h> #define CreateThreadEx(ti ...
- linux 下进程通讯详解
linux 下进程通讯方法主要有以下六种: 1.管道 2.信号 3.共享内存 4.消息队列 5.信号量 6.socket
- 【转帖】Linux发行版:CentOS、Ubuntu、RedHat、Android、Tizen、MeeGo
Linux发行版:CentOS.Ubuntu.RedHat.Android.Tizen.MeeGo作者:阳光岛主 原文在这儿 Linux,最早由Linus Benedict Torvalds在199 ...
- Linux 进程间通讯方式 pipe()函数 (转载)
转自:http://blog.csdn.net/ta893115871/article/details/7478779 Linux 进程间通讯方式有以下几种: 1->管道(pipe)和有名管道( ...
- 【原创】xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(三)--实时与非实时数据交互
版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 目录 1.概述 1.概述 [原创]实时IPC概述 [ ...
随机推荐
- Angular2入门系列教程4-服务
上一篇文章 Angular2入门系列教程-多个组件,主从关系 在编程中,我们通常会将数据提供单独分离出来,以免在编写程序的过程中反复复制粘贴数据请求的代码 Angular2中提供了依赖注入的概念,使得 ...
- jquery.uploadify文件上传组件
1.jquery.uploadify简介 在ASP.NET中上传的控件有很多,比如.NET自带的FileUpload,以及SWFUpload,Uploadify等等,尤其后面两个控件的用户体验比较好, ...
- Linq之旅:Linq入门详解(Linq to Objects)
示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...
- 解决 Springboot Unable to build Hibernate SessionFactory @Column命名不起作用
问题: Springboot启动报错: Caused by: org.springframework.beans.factory.BeanCreationException: Error creati ...
- Angular企业级开发-AngularJS1.x学习路径
博客目录 有链接的表明已经完成了,其他的正在建设中. 1.AngularJS简介 2.搭建Angular开发环境 3.Angular MVC实现 4.[Angular项目目录结构] 5.[SPA介绍] ...
- nginx源码分析之模块初始化
在nginx启动过程中,模块的初始化是整个启动过程中的重要部分,而且了解了模块初始化的过程对应后面具体分析各个模块会有事半功倍的效果.在我看来,分析源码来了解模块的初始化是最直接不过的了,所以下面主要 ...
- Swift enum(枚举)使用范例
//: Playground - noun: a place where people can play import UIKit var str = "Hello, playground& ...
- C++随笔:.NET CoreCLR之GC探索(1)
一直是.NET程序员,但是.NET的核心其实还是C++,所以我准备花 一点时间来研究CoreCLR和CoreFX.希望这个系列的文章能给大家带来 帮助. GC的代码有很多很多,而且结构层次对于一个初学 ...
- docker4dotnet #1 – 前世今生 & 世界你好
作为一名.NET Developer,这几年看着docker的流行实在是有些眼馋.可惜的是,Docker是基于Linux环境的,眼瞧着那些 java, python, node.js, go 甚至连p ...
- zookeeper集群的搭建以及hadoop ha的相关配置
1.环境 centos7 hadoop2.6.5 zookeeper3.4.9 jdk1.8 master作为active主机,data1作为standby备用机,三台机器均作为数据节点,yarn资源 ...