楼主太高深了,看我的arduino客户端吧:
简单来讲,只需要UDP通讯,就可以达到穿透外网的功能,并且速度飞快。
1:打开UDP通讯口,并且一直保持
2:定时(下面程序我用了30秒)向服务器发udp心跳包(格式见程序)
3:当收到服务器发来的包时,分析包属性(全在loop程序中)
要注意的:
1:先到fuhome.net注册帐号,增加设备
2:修改下面的设备ID与设备密码
3:修改arduino IP地址设定
/*
fuhome.ino:
by:wxws qq:1103012
协议:
http://www.fuhome.net/api/must/
服务器IP:115.28.93.201
udp端口:7001
30s
心跳发送: f=1 设备id 密码
心跳:f=1&d=设备id&m=密码&from=sb->server
心跳收到返回:f=1&d=设备id&from=server->sb1
远程收到命令:f=a&d=设备id&n=jyzhkj&com=open&from=server->sb
命令返回:f=b 设备id 密码 用户名 响应消息(可自定义)
返回:f=b&d=设备id&m=密码&n=jyzhkj&com=open&from=sb->server
*/
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
//#include "system.h"
EthernetUDP Udp;
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192, 168, 0, 46);
IPAddress ddns(192, 168, 0, 254);
IPAddress getway(192, 168, 0, 254);
IPAddress subnet(255, 255, 255, 0);
unsigned int localPort = 8888; // 本地端口
IPAddress rip(115, 28, 93, 201); //远程ip
unsigned int rPort = 7001; // 远程端口
String deviceid = "1234567890"; //设备ID
String deviceps = "1234567890"; //设备密码
String Heart = "f=1&d=%s1&m=%s2&from=sb->server"; //心跳包模板
String ReplyTemp = "f=b&d=%s1&m=%s2&n=%s3&com=%s4&from=sb->server"; //命令包模板
String udpget = "";
String usename = "";
String command = "";
char ttc[100];
#define LED 27
int ledstate = 1;
void setup()
{
// start the Ethernet and UDP:
pinMode(LED, OUTPUT);
digitalWrite(LED, 1);
Ethernet.begin(mac, ip, ddns, getway, subnet); //当然也可以用 DPCH 具体请看 arduino例子
Udp.begin(localPort);
Serial.begin(115200);
Heart.replace("%s1", deviceid);
Heart.replace("%s2", deviceps);
ReplyTemp.replace("%s1", deviceid);
ReplyTemp.replace("%s2", deviceps);
}
void loop()
{
// if there's data available, read a packet
int packetSize = Udp.parsePacket();
if (packetSize)
{
udpget = "";
for (int i = 0; i < packetSize; i++)
{
udpget += (char)Udp.read();
}
Serial.print(getuptime());
Serial.print(" R:");
Serial.println(udpget);
if (udpget.indexOf("f=a") >= 0)//心跳包不响应
{
usename = Findany("&n=");
command = Findany("&com=");
if (command == "open")
{
ledstate = 1;
command="已"+command;
}
if (command == "close")
{
ledstate = 0;
command="已"+command;
}
if (command == "flash")
{
ledstate = 2;
command="已"+command;
}
udpget = ReplyTemp;
udpget.replace("%s3", usename);
udpget.replace("%s4", command);
udpget.toCharArray(ttc, 100);
Serial.print(" Send reply:");
Serial.println(udpget);
Udp.beginPacket(rip, rPort);
Udp.write(ttc); //状态响应回复包 f=b&d=设备ID&m=设备密码&n=jyzhkj&com=命令&from=sb->server
Udp.endPacket();
}
else
{
// if (udpget.indexOf("f=1") >= 0) //心跳包
// Serial.println("Recive f=1.");
// if (udpget.indexOf("f=b") >= 0) //回复包
// Serial.println("Recive f=b.");
}
}
LedControl();
UdpHeart();
}
//灯状态切换
void LedControl()
{
static long previousMillis = 0;
static int currstate = 0;
switch (ledstate)
{
case 0:
currstate = 0;
break;
case 1:
currstate = 1;
break;
case 2:
if (millis() - previousMillis > 200) //200ms
{
previousMillis = millis();
currstate = 1 - currstate;
}
break;
}
digitalWrite(LED, currstate);
}
//查找参数,下一个“&”为界
String Findany(String findstr)
{
String ttv = "";
int t1, t2;
t1 = udpget.indexOf(findstr);
if (t1 >= 0)
{
t2 = udpget.indexOf("&", t1 + 1);
ttv = udpget.substring(t1 + findstr.length(), t2);
}
return ttv;
}
//UDP心跳包
void UdpHeart()
{
static long previousMillis = 0;
if (millis() - previousMillis > 30000) //30秒
{
previousMillis = millis();
Serial.print(getuptime());
Serial.print(" S:");
Serial.println(Heart);
Heart.toCharArray(ttc, 100);
Udp.beginPacket(rip, rPort);
Udp.write(ttc); //心跳包 f=1&d=设备ID&m=设备密码&from=sb->server
Udp.endPacket();
}
}
String getuptime() //从millis转换成 天数:小时:分:秒
{
String tts = "";
long days = 0;
long hours = 0;
long mins = 0;
long secs = 0;
char ccc[20];
secs = millis() / 1000; //convect milliseconds to seconds
mins = secs / 60; //convert seconds to minutes
hours = mins / 60; //convert minutes to hours
days = hours / 24; //convert hours to days
secs = secs - (mins * 60); //subtract the coverted seconds to minutes in order to display 59 secs max
mins = mins - (hours * 60); //subtract the coverted minutes to hours in order to display 59 minutes max
hours = hours - (days * 24); //subtract the coverted hours to days in order to display 23 hours max
sprintf(ccc, "%02d:%02d:%02d:%02d", int(days), int(hours), int(mins), int(secs));
tts = String(ccc);
return tts;
} |