前言: 为了防止再次被管理员误当成广告而被删除, 特以2个目前比较著名的网站举例
以下代码都已实验成功, 具体结果可在相关网站查看
http://www.yeelink.net/devices/4420
一. 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:
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 ""
-
#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:///api/V1/gateway/UpdateSensors/01"
-
#define LEWEI50_HOST "" //网址, 由此获得公网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:
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库的实现代码.
阅读(1775) | 评论(0) | 转发(0) |