Esp8266驱动独立目录,每个类一对源码文件
This commit is contained in:
parent
a745365404
commit
323c04a457
|
@ -4,6 +4,10 @@
|
|||
#include "Message\DataStore.h"
|
||||
|
||||
#include "Esp8266.h"
|
||||
#include "EspTcp.h"
|
||||
#include "EspUdp.h"
|
||||
#include "WaitExpect.h"
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#define NET_DEBUG DEBUG
|
||||
|
@ -14,23 +18,6 @@
|
|||
#define net_printf(format, ...)
|
||||
#endif
|
||||
|
||||
// 等待
|
||||
class WaitExpect
|
||||
{
|
||||
public:
|
||||
const String* Command = nullptr;
|
||||
String* Result = nullptr;
|
||||
cstring Key1 = nullptr;
|
||||
cstring Key2 = nullptr;
|
||||
|
||||
bool Capture = true; // 是否捕获所有
|
||||
//bool OK = false;
|
||||
|
||||
bool Wait(int msTimeout);
|
||||
uint Parse(const Buffer& bs);
|
||||
uint FindKey(const String& str);
|
||||
};
|
||||
|
||||
/*
|
||||
注意事项
|
||||
1、设置模式AT+CWMODE需要重启后生效AT+RST
|
||||
|
@ -39,61 +26,6 @@ public:
|
|||
4、单连接模式,多连接模式 收发数据有参数个数区别
|
||||
*/
|
||||
|
||||
/******************************** 内部Tcp/Udp ********************************/
|
||||
class EspSocket : public Object, public ITransport, public ISocket
|
||||
{
|
||||
protected:
|
||||
Esp8266& _Host;
|
||||
byte _Index;
|
||||
int _Error;
|
||||
|
||||
public:
|
||||
EspSocket(Esp8266& host, ProtocolType protocol, byte idx);
|
||||
virtual ~EspSocket();
|
||||
|
||||
// 打开Socket
|
||||
virtual bool OnOpen();
|
||||
virtual void OnClose();
|
||||
|
||||
//// 应用配置,修改远程地址和端口
|
||||
//virtual bool Change(const String& remote, ushort port);
|
||||
|
||||
virtual bool OnWrite(const Buffer& bs);
|
||||
virtual uint OnRead(Buffer& bs);
|
||||
|
||||
// 发送数据
|
||||
virtual bool Send(const Buffer& bs);
|
||||
// 接收数据
|
||||
virtual uint Receive(Buffer& bs);
|
||||
|
||||
// 收到数据
|
||||
virtual void OnProcess(const Buffer& bs, const IPEndPoint& remote);
|
||||
|
||||
protected:
|
||||
bool SendData(const String& cmd, const Buffer& bs);
|
||||
};
|
||||
|
||||
class EspTcp : public EspSocket
|
||||
{
|
||||
public:
|
||||
EspTcp(Esp8266& host, byte idx);
|
||||
|
||||
virtual String& ToStr(String& str) const { return str + "Tcp_" + Local.Port; }
|
||||
};
|
||||
|
||||
class EspUdp : public EspSocket
|
||||
{
|
||||
public:
|
||||
EspUdp(Esp8266& host, byte idx);
|
||||
|
||||
virtual bool SendTo(const Buffer& bs, const IPEndPoint& remote);
|
||||
|
||||
virtual String& ToStr(String& str) const { return str + "Udp_" + Local.Port; }
|
||||
|
||||
private:
|
||||
virtual bool OnWriteEx(const Buffer& bs, const void* opt);
|
||||
};
|
||||
|
||||
/******************************** Esp8266 ********************************/
|
||||
|
||||
Esp8266::Esp8266(ITransport* port, Pin power, Pin rst)
|
||||
|
@ -294,10 +226,6 @@ bool Esp8266::EnableDNS() { return true; }
|
|||
// 启用DHCP
|
||||
bool Esp8266::EnableDHCP() { Mode = SocketMode::STA_AP; return true;/* return SetDHCP(SocketMode::Both, true); */}
|
||||
|
||||
#if NET_DEBUG
|
||||
static bool EnableLog = true;
|
||||
#endif
|
||||
|
||||
// 发送指令,在超时时间内等待返回期望字符串,然后返回内容
|
||||
String Esp8266::Send(const String& cmd, cstring expect, cstring expect2, uint msTimeout)
|
||||
{
|
||||
|
@ -337,6 +265,10 @@ String Esp8266::Send(const String& cmd, cstring expect, cstring expect2, uint ms
|
|||
|
||||
_Expect = &we;
|
||||
|
||||
#if NET_DEBUG
|
||||
bool EnableLog = true;
|
||||
#endif
|
||||
|
||||
if(cmd)
|
||||
{
|
||||
// 设定小灯快闪时间,单位毫秒
|
||||
|
@ -346,7 +278,8 @@ String Esp8266::Send(const String& cmd, cstring expect, cstring expect2, uint ms
|
|||
|
||||
#if NET_DEBUG
|
||||
// 只有AT指令显示日志
|
||||
if(EnableLog && cmd.StartsWith("AT"))
|
||||
if(!cmd.StartsWith("AT") || expect && expect[0] == '<') EnableLog = false;
|
||||
if(EnableLog)
|
||||
{
|
||||
we.Command = &cmd;
|
||||
net_printf("%d=> ", tid);
|
||||
|
@ -946,283 +879,3 @@ bool Esp8266::SetIPD(bool enable)
|
|||
String cmd = "AT+CIPDINFO=";
|
||||
return SendCmd(cmd + (enable ? '1' : '0'));
|
||||
}
|
||||
|
||||
/******************************** Socket ********************************/
|
||||
|
||||
EspSocket::EspSocket(Esp8266& host, ProtocolType protocol, byte idx)
|
||||
: _Host(host)
|
||||
{
|
||||
_Index = idx;
|
||||
_Error = 0;
|
||||
|
||||
Host = &host;
|
||||
Protocol = protocol;
|
||||
}
|
||||
|
||||
EspSocket::~EspSocket()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
bool EspSocket::OnOpen()
|
||||
{
|
||||
// 确保宿主打开
|
||||
if(!_Host.Open()) return false;
|
||||
|
||||
// 如果没有指定本地端口,则使用累加端口
|
||||
if(!Local.Port)
|
||||
{
|
||||
// 累加端口
|
||||
static ushort g_port = 1024;
|
||||
if(g_port < 1024) g_port = 1024;
|
||||
Local.Port = g_port++;
|
||||
}
|
||||
Local.Address = _Host.IP;
|
||||
|
||||
_Host.SetMux(true);
|
||||
|
||||
#if DEBUG
|
||||
debug_printf("%s::Open ", Protocol == ProtocolType::Tcp ? "Tcp" : "Udp");
|
||||
Local.Show(false);
|
||||
debug_printf(" => ");
|
||||
Server.Show(false);
|
||||
debug_printf(" ");
|
||||
Remote.Show(true);
|
||||
#endif
|
||||
|
||||
String cmd = "AT+CIPSTART=";
|
||||
cmd = cmd + _Index + ",";
|
||||
|
||||
if(Protocol == ProtocolType::Udp)
|
||||
cmd += "\"UDP\"";
|
||||
else if(Protocol == ProtocolType::Tcp)
|
||||
cmd += "\"TCP\"";
|
||||
|
||||
auto rm = Server;
|
||||
if(!rm) rm = Remote.Address.ToString();
|
||||
|
||||
// 设置端口目的(远程)IP地址和端口号
|
||||
cmd = cmd + ",\"" + rm + "\"," + Remote.Port;
|
||||
// 设置自己的端口号
|
||||
if(Local.Port) cmd = cmd + ',' + Local.Port;
|
||||
// UDP传输属性。0,收到数据不改变远端目标;1,收到数据改变一次远端目标;2,收到数据改变远端目标
|
||||
|
||||
/*if(Remote.Address == IPAddress::Broadcast())
|
||||
cmd += ",2";
|
||||
else*/
|
||||
cmd += ",0";
|
||||
|
||||
// 打开Socket。有OK/ERROR/ALREADY CONNECTED三种
|
||||
auto rt = _Host.Send(cmd + "\r\n", "OK", "ERROR", 1600);
|
||||
if(!rt.Contains("OK") && ! rt.Contains("ALREADY CONNECTED"))
|
||||
{
|
||||
debug_printf("协议 %d, %d 打开失败 \r\n", Protocol, Remote.Port);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 清空一次缓冲区
|
||||
/*cmd = "AT+CIPBUFRESET=";
|
||||
_Host.SendCmd(cmd + _Index);*/
|
||||
_Error = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EspSocket::OnClose()
|
||||
{
|
||||
String cmd = "AT+CIPCLOSE=";
|
||||
cmd += _Index;
|
||||
cmd += "\r\n";
|
||||
|
||||
_Host.SendCmd(cmd, 1600);
|
||||
}
|
||||
|
||||
// 接收数据
|
||||
uint EspSocket::Receive(Buffer& bs)
|
||||
{
|
||||
if(!Open()) return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 发送数据
|
||||
bool EspSocket::Send(const Buffer& bs)
|
||||
{
|
||||
if(!Open()) return false;
|
||||
|
||||
String cmd = "AT+CIPSEND=";
|
||||
cmd = cmd + _Index + ',' + bs.Length() + "\r\n";
|
||||
|
||||
return SendData(cmd, bs);
|
||||
}
|
||||
|
||||
bool EspSocket::SendData(const String& cmd, const Buffer& bs)
|
||||
{
|
||||
#if NET_DEBUG
|
||||
EnableLog = false;
|
||||
#endif
|
||||
|
||||
// 重发3次AT指令,避免busy
|
||||
int i = 0;
|
||||
for(i=0; i<3; i++)
|
||||
{
|
||||
//auto rt = _Host.Send(cmd, ">", "OK", 1600);
|
||||
// 不能等待OK,而应该等待>,因为发送期间可能给别的指令碰撞
|
||||
auto rt = _Host.Send(cmd, ">", "ERROR", 1600);
|
||||
if(rt.Contains(">")) break;
|
||||
}
|
||||
if(i<3 && _Host.Send(bs.AsString(), "SEND OK", "ERROR", 1600).Contains("SEND OK"))
|
||||
{
|
||||
#if NET_DEBUG
|
||||
EnableLog = true;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
#if NET_DEBUG
|
||||
EnableLog = true;
|
||||
#endif
|
||||
|
||||
// 发送失败,关闭链接,下一次重新打开
|
||||
if(++_Error >= 10)
|
||||
{
|
||||
_Error = 0;
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EspSocket::OnWrite(const Buffer& bs) { return Send(bs); }
|
||||
uint EspSocket::OnRead(Buffer& bs) { return Receive(bs); }
|
||||
|
||||
// 收到数据
|
||||
void EspSocket::OnProcess(const Buffer& bs, const IPEndPoint& remote)
|
||||
{
|
||||
OnReceive((Buffer&)bs, (void*)&remote);
|
||||
}
|
||||
|
||||
/******************************** Tcp ********************************/
|
||||
|
||||
EspTcp::EspTcp(Esp8266& host, byte idx)
|
||||
: EspSocket(host, ProtocolType::Tcp, idx)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/******************************** Udp ********************************/
|
||||
|
||||
EspUdp::EspUdp(Esp8266& host, byte idx)
|
||||
: EspSocket(host, ProtocolType::Udp, idx)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool EspUdp::SendTo(const Buffer& bs, const IPEndPoint& remote)
|
||||
{
|
||||
//!!! ESP8266有BUG,收到数据后,远程地址还是乱了,所以这里的远程地址跟实际可能不一致
|
||||
if(remote == Remote) return Send(bs);
|
||||
|
||||
if(!Open()) return false;
|
||||
|
||||
String cmd = "AT+CIPSEND=";
|
||||
cmd = cmd + _Index + ',' + bs.Length();
|
||||
|
||||
// 加上远程IP和端口
|
||||
cmd = cmd + ",\"" + remote.Address + "\"";
|
||||
cmd = cmd + ',' + remote.Port;
|
||||
cmd += "\r\n";
|
||||
|
||||
return SendData(cmd, bs);
|
||||
}
|
||||
|
||||
bool EspUdp::OnWriteEx(const Buffer& bs, const void* opt)
|
||||
{
|
||||
auto ep = (IPEndPoint*)opt;
|
||||
if(!ep) return OnWrite(bs);
|
||||
|
||||
return SendTo(bs, *ep);
|
||||
}
|
||||
|
||||
/******************************** WaitExpect ********************************/
|
||||
|
||||
bool WaitExpect::Wait(int msTimeout)
|
||||
{
|
||||
// 提前等待一会,再开始轮询,专门为了加快命中快速响应的指令
|
||||
Sys.Sleep(40);
|
||||
if(!Result) return true;
|
||||
|
||||
// 等待收到数据
|
||||
TimeWheel tw(0, msTimeout - 40);
|
||||
// 默认检查间隔200ms,如果超时时间大于1000ms,则以四分之一为检查间隔
|
||||
// ESP8266串口任务平均时间为150ms左右,为了避免接收指令任务里面发送指令时等不到OK,需要加大检查间隔
|
||||
tw.Sleep = 200;
|
||||
if(msTimeout > 1000) tw.Sleep = msTimeout >> 2;
|
||||
if(tw.Sleep > 1000) tw.Sleep = 1000;
|
||||
|
||||
while(Result)
|
||||
{
|
||||
if(tw.Expired()) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint WaitExpect::Parse(const Buffer& bs)
|
||||
{
|
||||
if(bs.Length() == 0 || !Result) return 0;
|
||||
|
||||
TS("WaitExpect::Parse");
|
||||
|
||||
// 适配任意关键字后,也就是收到了成功或失败,通知业务层已结束
|
||||
auto s = (const String)bs.AsString();
|
||||
int p = FindKey(s);
|
||||
auto& rs= *Result;
|
||||
|
||||
// 捕获所有
|
||||
if(Capture)
|
||||
{
|
||||
if(p > 0)
|
||||
rs += bs.Sub(0, p).AsString();
|
||||
else
|
||||
rs += s;
|
||||
}
|
||||
else if(p > 0)
|
||||
rs = bs.Sub(0, p).AsString();
|
||||
|
||||
// 匹配关键字,任务完成
|
||||
if(p > 0) Result = nullptr;
|
||||
|
||||
// 如果后面是换行,则跳过
|
||||
if(p < s.Length() && s[p] == ' ') p++;
|
||||
if(p < s.Length() && s[p] == '\r') p++;
|
||||
if(p < s.Length() && s[p] == '\n') p++;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
uint WaitExpect::FindKey(const String& str)
|
||||
{
|
||||
// 适配第一关键字
|
||||
int p = Key1 ? str.IndexOf(Key1) : -1;
|
||||
if(p >= 0)
|
||||
{
|
||||
//net_printf("适配第一关键字 %s \r\n", Key1);
|
||||
return p + String(Key1).Length();
|
||||
}
|
||||
// 适配第二关键字
|
||||
p = Key2 ? str.IndexOf(Key2) : -1;
|
||||
if(p >= 0)
|
||||
{
|
||||
net_printf("适配第二关键字 %s \r\n", Key2);
|
||||
return p + String(Key2).Length();
|
||||
}
|
||||
// 适配busy
|
||||
p = str.IndexOf("busy ");
|
||||
if(p >= 0)
|
||||
{
|
||||
net_printf("适配 busy \r\n");
|
||||
return p + 4 + 1 + 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef __Esp8266_H__
|
||||
#define __Esp8266_H__
|
||||
|
||||
#include "Sys.h"
|
||||
#include "Port.h"
|
||||
#include "Net\ITransport.h"
|
||||
#include "Net\Socket.h"
|
||||
|
@ -13,11 +12,8 @@ class Esp8266 : public PackPort, public ISocketHost
|
|||
{
|
||||
public:
|
||||
bool AutoConn; // 是否自动连接WiFi,默认false
|
||||
//String SSID;
|
||||
//String Pass;
|
||||
|
||||
IDataPort* Led; // 指示灯
|
||||
//Action NetReady; // 网络准备就绪
|
||||
|
||||
Esp8266(ITransport* port, Pin power = P0, Pin rst = P0);
|
||||
virtual ~Esp8266();
|
|
@ -0,0 +1,154 @@
|
|||
#include "EspSocket.h"
|
||||
|
||||
#define NET_DEBUG DEBUG
|
||||
//#define NET_DEBUG 0
|
||||
#if NET_DEBUG
|
||||
#define net_printf debug_printf
|
||||
#else
|
||||
#define net_printf(format, ...)
|
||||
#endif
|
||||
|
||||
/******************************** Socket ********************************/
|
||||
|
||||
EspSocket::EspSocket(Esp8266& host, ProtocolType protocol, byte idx)
|
||||
: _Host(host)
|
||||
{
|
||||
_Index = idx;
|
||||
_Error = 0;
|
||||
|
||||
Host = &host;
|
||||
Protocol = protocol;
|
||||
}
|
||||
|
||||
EspSocket::~EspSocket()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
bool EspSocket::OnOpen()
|
||||
{
|
||||
// 确保宿主打开
|
||||
if(!_Host.Open()) return false;
|
||||
|
||||
// 如果没有指定本地端口,则使用累加端口
|
||||
if(!Local.Port)
|
||||
{
|
||||
// 累加端口
|
||||
static ushort g_port = 1024;
|
||||
if(g_port < 1024) g_port = 1024;
|
||||
Local.Port = g_port++;
|
||||
}
|
||||
Local.Address = _Host.IP;
|
||||
|
||||
_Host.SetMux(true);
|
||||
|
||||
#if DEBUG
|
||||
debug_printf("%s::Open ", Protocol == ProtocolType::Tcp ? "Tcp" : "Udp");
|
||||
Local.Show(false);
|
||||
debug_printf(" => ");
|
||||
Server.Show(false);
|
||||
debug_printf(" ");
|
||||
Remote.Show(true);
|
||||
#endif
|
||||
|
||||
String cmd = "AT+CIPSTART=";
|
||||
cmd = cmd + _Index + ",";
|
||||
|
||||
if(Protocol == ProtocolType::Udp)
|
||||
cmd += "\"UDP\"";
|
||||
else if(Protocol == ProtocolType::Tcp)
|
||||
cmd += "\"TCP\"";
|
||||
|
||||
auto rm = Server;
|
||||
if(!rm) rm = Remote.Address.ToString();
|
||||
|
||||
// 设置端口目的(远程)IP地址和端口号
|
||||
cmd = cmd + ",\"" + rm + "\"," + Remote.Port;
|
||||
// 设置自己的端口号
|
||||
if(Local.Port) cmd = cmd + ',' + Local.Port;
|
||||
// UDP传输属性。0,收到数据不改变远端目标;1,收到数据改变一次远端目标;2,收到数据改变远端目标
|
||||
|
||||
/*if(Remote.Address == IPAddress::Broadcast())
|
||||
cmd += ",2";
|
||||
else*/
|
||||
cmd += ",0";
|
||||
|
||||
// 打开Socket。有OK/ERROR/ALREADY CONNECTED三种
|
||||
auto rt = _Host.Send(cmd + "\r\n", "OK", "ERROR", 1600);
|
||||
if(!rt.Contains("OK") && ! rt.Contains("ALREADY CONNECTED"))
|
||||
{
|
||||
debug_printf("协议 %d, %d 打开失败 \r\n", Protocol, Remote.Port);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 清空一次缓冲区
|
||||
/*cmd = "AT+CIPBUFRESET=";
|
||||
_Host.SendCmd(cmd + _Index);*/
|
||||
_Error = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EspSocket::OnClose()
|
||||
{
|
||||
String cmd = "AT+CIPCLOSE=";
|
||||
cmd += _Index;
|
||||
cmd += "\r\n";
|
||||
|
||||
_Host.SendCmd(cmd, 1600);
|
||||
}
|
||||
|
||||
// 接收数据
|
||||
uint EspSocket::Receive(Buffer& bs)
|
||||
{
|
||||
if(!Open()) return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 发送数据
|
||||
bool EspSocket::Send(const Buffer& bs)
|
||||
{
|
||||
if(!Open()) return false;
|
||||
|
||||
String cmd = "AT+CIPSEND=";
|
||||
cmd = cmd + _Index + ',' + bs.Length() + "\r\n";
|
||||
|
||||
return SendData(cmd, bs);
|
||||
}
|
||||
|
||||
bool EspSocket::SendData(const String& cmd, const Buffer& bs)
|
||||
{
|
||||
// 重发3次AT指令,避免busy
|
||||
int i = 0;
|
||||
for(i=0; i<3; i++)
|
||||
{
|
||||
//auto rt = _Host.Send(cmd, ">", "OK", 1600);
|
||||
// 不能等待OK,而应该等待>,因为发送期间可能给别的指令碰撞
|
||||
auto rt = _Host.Send(cmd, ">", "ERROR", 1600);
|
||||
if(rt.Contains(">")) break;
|
||||
}
|
||||
if(i<3 && _Host.Send(bs.AsString(), "SEND OK", "ERROR", 1600).Contains("SEND OK"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// 发送失败,关闭链接,下一次重新打开
|
||||
if(++_Error >= 10)
|
||||
{
|
||||
_Error = 0;
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EspSocket::OnWrite(const Buffer& bs) { return Send(bs); }
|
||||
uint EspSocket::OnRead(Buffer& bs) { return Receive(bs); }
|
||||
|
||||
// 收到数据
|
||||
void EspSocket::OnProcess(const Buffer& bs, const IPEndPoint& remote)
|
||||
{
|
||||
OnReceive((Buffer&)bs, (void*)&remote);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef __EspSocket_H__
|
||||
#define __EspSocket_H__
|
||||
|
||||
#include "Esp8266.h"
|
||||
|
||||
class EspSocket : public Object, public ITransport, public ISocket
|
||||
{
|
||||
protected:
|
||||
Esp8266& _Host;
|
||||
byte _Index;
|
||||
int _Error;
|
||||
|
||||
public:
|
||||
EspSocket(Esp8266& host, ProtocolType protocol, byte idx);
|
||||
virtual ~EspSocket();
|
||||
|
||||
// 打开Socket
|
||||
virtual bool OnOpen();
|
||||
virtual void OnClose();
|
||||
|
||||
//// 应用配置,修改远程地址和端口
|
||||
//virtual bool Change(const String& remote, ushort port);
|
||||
|
||||
virtual bool OnWrite(const Buffer& bs);
|
||||
virtual uint OnRead(Buffer& bs);
|
||||
|
||||
// 发送数据
|
||||
virtual bool Send(const Buffer& bs);
|
||||
// 接收数据
|
||||
virtual uint Receive(Buffer& bs);
|
||||
|
||||
// 收到数据
|
||||
virtual void OnProcess(const Buffer& bs, const IPEndPoint& remote);
|
||||
|
||||
protected:
|
||||
bool SendData(const String& cmd, const Buffer& bs);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,9 @@
|
|||
#include "EspTcp.h"
|
||||
|
||||
/******************************** Tcp ********************************/
|
||||
|
||||
EspTcp::EspTcp(Esp8266& host, byte idx)
|
||||
: EspSocket(host, ProtocolType::Tcp, idx)
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef __EspTcp_H__
|
||||
#define __EspTcp_H__
|
||||
|
||||
#include "EspSocket.h"
|
||||
|
||||
class EspTcp : public EspSocket
|
||||
{
|
||||
public:
|
||||
EspTcp(Esp8266& host, byte idx);
|
||||
|
||||
virtual String& ToStr(String& str) const { return str + "Tcp_" + Local.Port; }
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,35 @@
|
|||
#include "EspUdp.h"
|
||||
|
||||
/******************************** Udp ********************************/
|
||||
|
||||
EspUdp::EspUdp(Esp8266& host, byte idx)
|
||||
: EspSocket(host, ProtocolType::Udp, idx)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool EspUdp::SendTo(const Buffer& bs, const IPEndPoint& remote)
|
||||
{
|
||||
//!!! ESP8266有BUG,收到数据后,远程地址还是乱了,所以这里的远程地址跟实际可能不一致
|
||||
if(remote == Remote) return Send(bs);
|
||||
|
||||
if(!Open()) return false;
|
||||
|
||||
String cmd = "AT+CIPSEND=";
|
||||
cmd = cmd + _Index + ',' + bs.Length();
|
||||
|
||||
// 加上远程IP和端口
|
||||
cmd = cmd + ",\"" + remote.Address + "\"";
|
||||
cmd = cmd + ',' + remote.Port;
|
||||
cmd += "\r\n";
|
||||
|
||||
return SendData(cmd, bs);
|
||||
}
|
||||
|
||||
bool EspUdp::OnWriteEx(const Buffer& bs, const void* opt)
|
||||
{
|
||||
auto ep = (IPEndPoint*)opt;
|
||||
if(!ep) return OnWrite(bs);
|
||||
|
||||
return SendTo(bs, *ep);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef __EspUdp_H__
|
||||
#define __EspUdp_H__
|
||||
|
||||
#include "EspSocket.h"
|
||||
|
||||
class EspUdp : public EspSocket
|
||||
{
|
||||
public:
|
||||
EspUdp(Esp8266& host, byte idx);
|
||||
|
||||
virtual bool SendTo(const Buffer& bs, const IPEndPoint& remote);
|
||||
|
||||
virtual String& ToStr(String& str) const { return str + "Udp_" + Local.Port; }
|
||||
|
||||
private:
|
||||
virtual bool OnWriteEx(const Buffer& bs, const void* opt);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,95 @@
|
|||
#include "Time.h"
|
||||
#include "Sys.h"
|
||||
|
||||
#include "WaitExpect.h"
|
||||
|
||||
#define NET_DEBUG DEBUG
|
||||
//#define NET_DEBUG 0
|
||||
#if NET_DEBUG
|
||||
#define net_printf debug_printf
|
||||
#else
|
||||
#define net_printf(format, ...)
|
||||
#endif
|
||||
|
||||
/******************************** WaitExpect ********************************/
|
||||
|
||||
bool WaitExpect::Wait(int msTimeout)
|
||||
{
|
||||
// 提前等待一会,再开始轮询,专门为了加快命中快速响应的指令
|
||||
Sys.Sleep(40);
|
||||
if(!Result) return true;
|
||||
|
||||
// 等待收到数据
|
||||
TimeWheel tw(0, msTimeout - 40);
|
||||
// 默认检查间隔200ms,如果超时时间大于1000ms,则以四分之一为检查间隔
|
||||
// ESP8266串口任务平均时间为150ms左右,为了避免接收指令任务里面发送指令时等不到OK,需要加大检查间隔
|
||||
tw.Sleep = 200;
|
||||
if(msTimeout > 1000) tw.Sleep = msTimeout >> 2;
|
||||
if(tw.Sleep > 1000) tw.Sleep = 1000;
|
||||
|
||||
while(Result)
|
||||
{
|
||||
if(tw.Expired()) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint WaitExpect::Parse(const Buffer& bs)
|
||||
{
|
||||
if(bs.Length() == 0 || !Result) return 0;
|
||||
|
||||
TS("WaitExpect::Parse");
|
||||
|
||||
// 适配任意关键字后,也就是收到了成功或失败,通知业务层已结束
|
||||
auto s = (const String)bs.AsString();
|
||||
int p = FindKey(s);
|
||||
auto& rs= *Result;
|
||||
|
||||
// 捕获所有
|
||||
if(Capture)
|
||||
{
|
||||
if(p > 0)
|
||||
rs += bs.Sub(0, p).AsString();
|
||||
else
|
||||
rs += s;
|
||||
}
|
||||
else if(p > 0)
|
||||
rs = bs.Sub(0, p).AsString();
|
||||
|
||||
// 匹配关键字,任务完成
|
||||
if(p > 0) Result = nullptr;
|
||||
|
||||
// 如果后面是换行,则跳过
|
||||
if(p < s.Length() && s[p] == ' ') p++;
|
||||
if(p < s.Length() && s[p] == '\r') p++;
|
||||
if(p < s.Length() && s[p] == '\n') p++;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
uint WaitExpect::FindKey(const String& str)
|
||||
{
|
||||
// 适配第一关键字
|
||||
int p = Key1 ? str.IndexOf(Key1) : -1;
|
||||
if(p >= 0)
|
||||
{
|
||||
//net_printf("适配第一关键字 %s \r\n", Key1);
|
||||
return p + String(Key1).Length();
|
||||
}
|
||||
// 适配第二关键字
|
||||
p = Key2 ? str.IndexOf(Key2) : -1;
|
||||
if(p >= 0)
|
||||
{
|
||||
net_printf("适配第二关键字 %s \r\n", Key2);
|
||||
return p + String(Key2).Length();
|
||||
}
|
||||
// 适配busy
|
||||
p = str.IndexOf("busy ");
|
||||
if(p >= 0)
|
||||
{
|
||||
net_printf("适配 busy \r\n");
|
||||
return p + 4 + 1 + 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef __WaitExpect_H__
|
||||
#define __WaitExpect_H__
|
||||
|
||||
// 等待
|
||||
class WaitExpect
|
||||
{
|
||||
public:
|
||||
const String* Command = nullptr;
|
||||
String* Result = nullptr;
|
||||
cstring Key1 = nullptr;
|
||||
cstring Key2 = nullptr;
|
||||
|
||||
bool Capture = true; // 是否捕获所有
|
||||
|
||||
bool Wait(int msTimeout);
|
||||
uint Parse(const Buffer& bs);
|
||||
uint FindKey(const String& str);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue