zcbzjx 发表于 2012-9-6 14:51:12

ENC28J60利用ethercard库httpPost函数发送数据到yeelink或者乐联网

本帖最后由 zcbzjx 于 2013-5-29 00:39 编辑

2013年5月29日更新:由于库文件更新比较多,以前的帖子有些不适用了,重新开贴又没有必要,所以就直接修改这个帖子,并争取把这个帖子修改成精华帖。


最近研究ethercard库,发觉有个httpPost函数,用这个库函数发送post数据比较省事,而且可以方便获得服务器返回数据。

实验硬件器材和这个帖子的实验器材一样,不再赘述。
ArduinoIDE版本:1.0.4
库文件为最新的ethercard库文件

Yeelink代码

#include <OneWire.h>
#include <EtherCard.h>
#include <DallasTemperature.h>
#define OUT
// Data wire is plugged into port A5 on the Arduino
#define ONE_WIRE_BUS A5
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

#define REQUEST_RATE 15000 // milliseconds
// ethernet interface mac address
static byte mymac[] = {
0x74,0x69,0x69,0x2D,0x30,0x31 };
// ethernet interface ip address
static byte myip[] = {
10,21,0,193 };
// gateway ip address
static byte gwip[] = {
10,21,0,1 };
// remote dns ip address
static byte dnsip[] = {
10,11,5,25 };

// remote website name
char website[] PROGMEM = "api.yeelink.net";
char urlBuf[] PROGMEM = "/v1.0/device/xxx/sensor/xxx/datapoints";
char apiKey[] PROGMEM = "U-ApiKey: xxxxxxxxxxxxxx";
byte Ethernet::buffer;   // a very small tcp/ip buffer is enough here
static long timer;

// called when the client request is complete
static void my_result_cb (byte status, word off, word len) {
Serial.print("<<< reply ");
Serial.print(millis() - timer);
Serial.println(" ms");
Serial.println((const char*) Ethernet::buffer + off);
}

void setup () {
sensors.begin();
Serial.begin(57600);
Serial.println("\n");

if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
    Serial.println( "Failed to access Ethernet controller");

ether.staticSetup(myip, gwip, dnsip);

while (ether.clientWaitingGw())
    ether.packetLoop(ether.packetReceive());
Serial.println("Gateway found");

timer = - REQUEST_RATE; // start timing out right away
}

void loop () {
ether.packetLoop(ether.packetReceive());

if (millis() > timer + REQUEST_RATE) {
    timer = millis();
    Serial.println("\n>>> REQ");
    static char buf;
    get_send_string(buf);
    if (!ether.dnsLookup(website))
      Serial.println("DNS failed");
    ether.printIp("Server: ", ether.hisip);
    ether.httpPost (urlBuf, website, apiKey, buf, my_result_cb);
}
}

void get_send_string(OUT char *p){
sensors.requestTemperatures();
uint16_t Tc_100 = sensors.getTempCByIndex(0)*10;
uint8_t whole, fract;
whole = Tc_100/10 ;// separate off the whole and fractional portions
fract = Tc_100 % 10;
sprintf(p,"{\"value\":%d.%d}",whole,fract);
}


串口图如下:




乐联网代码如下:

#include <OneWire.h>
#include <EtherCard.h>
#include <DallasTemperature.h>
#define OUT
// Data wire is plugged into port A5 on the Arduino
#define ONE_WIRE_BUS 7
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

#define REQUEST_RATE 15000 // milliseconds
// ethernet interface mac address 需要根据你的实际网络环境进行更改,我这儿用的是固定ip
static byte mymac[] = {
0x74,0x69,0x69,0x2D,0x30,0x31 };
// ethernet interface ip address
static byte myip[] = {
10,21,0,193 };
// gateway ip address
static byte gwip[] = {
10,21,0,1 };
// remote dns ip address
static byte dnsip[] = {
10,21,0,1 };

// remote website name
char website[] PROGMEM = "www.lewei50.com";
char urlBuf[] PROGMEM = "/api/V1/gateway/UpdateSensors/01"; // 01应该更改为你对应的网关标识
char apiKey[] PROGMEM = "userkey:xxxxxxxxxxxxxxxxxxxxxxxxx"; //需要更改为你的userkey
byte Ethernet::buffer;   // a very small tcp/ip buffer is enough here
static long timer;

// called when the client request is complete
static void my_result_cb (byte status, word off, word len) {
Serial.print("<<< reply ");
Serial.print(millis() - timer);
Serial.println(" ms");
Serial.println((const char*) Ethernet::buffer + off);
}

void setup () {
sensors.begin();
Serial.begin(57600);
Serial.println("\n");

if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
    Serial.println( "Failed to access Ethernet controller");

ether.staticSetup(myip, gwip, dnsip);

while (ether.clientWaitingGw())
    ether.packetLoop(ether.packetReceive());
Serial.println("Gateway found");

timer = - REQUEST_RATE; // start timing out right away
}

void loop () {
ether.packetLoop(ether.packetReceive());

if (millis() > timer + REQUEST_RATE) {
    timer = millis();
    Serial.println("\n>>> REQ");
    static char buf;
    get_send_string(buf);
    if (!ether.dnsLookup(website))
      Serial.println("DNS failed");
    ether.printIp("Server: ", ether.hisip);
    ether.httpPost (urlBuf, website, apiKey, buf, my_result_cb);
}
}

void get_send_string(OUT char *p){
sensors.requestTemperatures();
uint16_t Tc_100 = sensors.getTempCByIndex(0)*10;
uint8_t whole, fract;
whole = Tc_100/10 ;// separate off the whole and fractional portions
fract = Tc_100 % 10;
sprintf(p,"[{\"Name\":\"T2\",\"Value\":\"%d.%d\"}]",whole,fract);//T2应该更改为你对应的设备标识
}


以下为串口切图:



相信大家已经看出来来了,代码没什么大的变化。

水乐天 发表于 2012-9-6 16:49:45

好快。。。。

zcbzjx 发表于 2012-9-6 20:15:12

嘛意思。。。。

erjiang 发表于 2012-9-6 20:43:14

张老师给力

自己 发表于 2012-9-12 14:15:46

请问这个函数可不可以放到wifi模块上去用?
求指点

holyglenn 发表于 2012-9-12 20:03:07

感谢分享!

zhangdeyue1 发表于 2012-9-23 17:05:30

请问MAC地址是如何获取的呢

zcbzjx 发表于 2012-9-24 01:52:53

mac地址可以自己随便编,只要本地没重复的就行。

all_heart 发表于 2012-10-28 23:55:16

可以向自己的服务器发送数据吗?比如向192.168.1.222发送数据。

zcbzjx 发表于 2012-10-29 07:49:49

all_heart 发表于 2012-10-28 23:55 static/image/common/back.gif
可以向自己的服务器发送数据吗?比如向192.168.1.222发送数据。

可以,192.168.1.222作为服务器,应该有相应的脚本将数据存储到数据库或者文本文件。

erjiang 发表于 2012-10-29 09:56:09

张老师能不能将这个ecard库直接改动一下,封装成直连yeelink的库?提供几个简单的参数就能完成上传?

all_heart 发表于 2012-10-29 22:48:24

zcbzjx 发表于 2012-10-29 07:49 static/image/common/back.gif
可以,192.168.1.222作为服务器,应该有相应的脚本将数据存储到数据库或者文本文件。

能具体点吗,asp.net我知道该如何做,但arduino我还是比较茫然。望指点。

zcbzjx 发表于 2012-10-30 07:52:43

本帖最后由 zcbzjx 于 2012-10-30 07:55 编辑

all_heart 发表于 2012-10-29 22:48 static/image/common/back.gif
能具体点吗,asp.net我知道该如何做,但arduino我还是比较茫然。望指点。

ardino端用httppost函数,把数据发送到服务器相应页面,asp.net服务器端脚本处理这个post请求就行了。再详细我就要架服务器编服务器代码调试了。。太麻烦,建议你试试yeelink。然后再自己编写服务器端代码。

从开始到现在 发表于 2013-5-15 17:08:10

对照这个研究了数天后终于成功了,感谢楼主的教程

从开始到现在 发表于 2013-5-16 16:10:09

好帖子,再次谢过楼主
页: [1] 2 3
查看完整版本: ENC28J60利用ethercard库httpPost函数发送数据到yeelink或者乐联网