极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 10745|回复: 4

两句UDP语句,实现跨内网外网实时控制设备(手机APP,网页)

[复制链接]
发表于 2014-9-23 09:24:41 | 显示全部楼层 |阅读模式
两句UDP语句,实现跨内网外网实时控制设备(手机APP,网页),视频中用的是单片机+ENC28J60,其他什么硬件都无所谓。

响应速度极快:手机APP是1s以内响应,网页1-2s响应,大大提高了速度,而且带信息反馈哦。

演示视频:


具体详情:fuhome/bbs/

视频:讲解如何接入平台,很简单,讲的废话有点啰嗦,不过适合不用阶层的伙计,大家要有一颗包容的心,哈哈

回复

使用道具 举报

发表于 2014-9-24 16:34:35 | 显示全部楼层
楼主太高深了,看我的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;
}
回复 支持 反对

使用道具 举报

发表于 2014-9-24 16:37:51 | 显示全部楼层
我的程序已经可以直接调用了,只要修改本地网络参数与设备ID、密码。

注意LED脚 ,我用的是27脚 ,请自定义,注意不要用13脚 ,与SPI通讯冲突。

实现了3个状态:
close  :关
open:开
flash:闪烁

附件是手机app,

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

发表于 2014-9-24 16:43:59 | 显示全部楼层
忘了说硬件:  我用的是w5500,w5100也肯定没问题
enj修改修改也没问题的。

与yeelink比较:
非http协议,yeelink使用http,注定了会有延时。
udp联接属于实时联接,手机,web控制全实时。

我将arduino挂在网上,大家可以控制:
http://www.fuhome.net/home/?id=40



图中的“消息”,是由arduino反馈给服务器的。见loop函数。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

发表于 2014-9-24 16:54:55 | 显示全部楼层
程序可能看着长,我已经全做完善了,232有调试信息。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-5-8 08:57 , Processed in 0.039893 second(s), 19 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表