注:本文章纯属个人一些小经验,大神请勿喷
另:第一次写博客,语言可能不连贯,望见谅!
最近在研究Arduino上网的问题,逛论坛时发现了ENC28J60网盾,相比5100这个相对便宜,通过SPI与Arduino连接。
我学习的教程是极客工坊张老师的教程,连线教程中都有了,不懂的同学可以看看。张老师的教程使用的enc28j60库是JeeLabs Café编写的EtherCard库。
个人在学习时由于要post数据给自己写的接口,寻找之下库文件中有个httpPost的方法,在极客工坊中发现张老师有httpPost方法的教程
httpPost方法的参数如下:
urlbuf 是post地址路径地址,如/v1.0/device/xxx/sensor/xxx/datapoints
hoststr 是post地址主机名,如api.yeelink.net
additionalheaderline 是添加在http请求报文中的apikey,一般调用api都有用到的,如自己写本地测试没有apikey,此处可以写NULL
postval 是post的数据
void (*callback)(uint8_t,uint16_t,uint16_t) 是回调函数,根据我使用的过程,其实这个函数就是接收调用api后返回来的数据
httpPost函数的调用挺简单的,在loop()中调用便行
我自己实验的是用php写一个接口上传传感器的数据,部分的代码如下:
<pre name="code" class="php">function upwendu(){
$re = array('success' => 'true',
'message' => 'null');
if($get = $this->input->post('data')){
$get_value = json_decode($get,true);
if($get_value['seneor'] == "Temp")
{
self::savecache("wendu",$get_value['value']);
}elseif ($get_value['seneor'] == "guanxian") {
self::savecache("guanxian",$get_value['value']);
}else{
$re['success'] = 'falus';
$re['message'] = "seneor faild";
echo json_encode($re);
return 0;
}
echo json_encode($re);
}else{
$re['success'] = 'falus';
$re['message'] = "no values";
echo json_encode($re);
}
}
Arduino这边写使用httpPost方法上传数据,代码如下:
<pre name="code" class="c++">
#include <EtherCard.h>
#define REQUEST_RATE 5000
static byte hisip[] = { 192,168,88,111 };
static byte mymac[] = {0x74,0x69,0x23,0x2D,0x30,0x31};
char website[] PROGMEM = "192.168.88.111";
//char website1[] PROGMEM = "api.yeelink.net";
char urlBuf[] PROGMEM = "/IntelligentDesktop/updata/upwendu";
//char apiKey[] PROGMEM = "U-ApiKey: xxxxxxxxxxxxxx";
byte Ethernet::buffer[700];
static long timer;
//String switchStatus;
static void my_result_cb (byte status, word off, word len) {
// String reply=(const char*)Ethernet::buffer + off;
// switchStatus = reply.substring(reply.length()-35,reply.length()+5);
Serial.print("<<< reply ");
Serial.print(millis() - timer);
Serial.println(" ms");
Serial.print("Return Message:");
Serial.println((const char*) Ethernet::buffer + off + 200);
// Serial.println(switchStatus);
// Serial.println();
}
static void response_callback (byte status, word off, word len) {
Serial.println(">>>");
Ethernet::buffer[off+300] = 0;
Serial.print((const char*) Ethernet::buffer + off);
Serial.println("...");
}
void setup(){
Serial.begin(57600);
Serial.println("<<< GetWay Init");
Serial.println("\t- - - - - - - - - - - - - - - - - -");
Serial.println("\t| Welcome to use |");
Serial.println("\t| intelligent dormitory platform |");
Serial.println("\t- - - - - - - - - - - - - - - - - -");
if(!ether.begin(sizeof Ethernet::buffer,mymac,10))
Serial.println(">>> Failed to access Ethernet controller");
else
Serial.println("<<< Ethernet controller initialized");
if (!ether.dhcpSetup()){
Serial.println(">>> Failed to get configuration from DHCP");
while(1);
}
else
Serial.println("<<< DHCP configuration done");
Serial.println("- - - - - - - - - - - - - - - - - - - - - - - ");
ether.printIp("IP Address:\t", ether.myip);
ether.printIp("Gateway:\t", ether.gwip);
ether.printIp("DnsIp: \t",ether.dnsip);
// if(!ether.dnsLookup(website1))
// Serial.println("DNS Faild");
ether.copyIp(ether.hisip,hisip);
ether.printIp("Server: \t", ether.hisip);
Serial.println("- - - - - - - - - - - - - - - - - - - - - - - ");
timer = - REQUEST_RATE; // start timing out right away
delay(100);
}
void loop(){
ether.packetLoop(ether.packetReceive());
// if (millis() > timer) {
// timer = millis() + 5000;
// Serial.println();
// Serial.print("<<< REQ ");
// ether.browseUrl("/IntelligentDesktop/login/ii","bar",website,response_callback);
// }
if(millis() > timer + REQUEST_RATE){
timer = millis();
Serial.println("\n>>>REQ");
char data[] = {"data={\"seneor\":\"Temp\",\"value\":\"307\"}"};
ether.httpPost(urlBuf , website , NULL ,data , my_result_cb);
}
}
注意:在使用httpPost时,有一步骤很重要,就是调用dnsLookup方法,其作用是解析出post的IP地址,如果没有进行这一步,则httpPost不会成功,由于我是在本地实验的,dnsLookup的方法就不适应了,但我在阅读库文件的时候,发现dnsLookup方法调用时是将解析出来的IP地址赋值到EtherCard类的公有成员static uint8_t hisip[4]中,而EtherCard类中有copyIp的方法
<pre class="cpp" name="code"><pre class="php" name="code"><pre name="code" class="c++">
static void copyIp (uint8_t *dst, const uint8_t *src);
其作用是讲src源Ip地址赋值给dst EtherCard类中的公有成员定义的IP地址,如
hisip目标地址或
myip网盾的IP地址