SmartOS/Drivers/Esp8266/EspSocket.cpp

164 lines
3.6 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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, NetType protocol, byte idx)
: _Host(host)
{
_Index = idx;
_Error = 0;
Host = &host;
Protocol = protocol;
}
EspSocket::~EspSocket()
{
if (_Host.Sockets[_Index] == this) _Host.Sockets[_Index] = nullptr;
Close();
}
bool EspSocket::OnOpen()
{
// 确保宿主打开
if (!_Host.Open()) return false;
// 如果没有指定本地端口,则使用累加端口
if (!Local.Port)
{
// 累加端口
static ushort g_port = 1024;
// 随机拿到1024 至 1024+255 的端口号
if (g_port <= 1024)g_port += Sys.Ms() & 0xff;
Local.Port = g_port++;
}
Local.Address = _Host.IP;
//_Host.SetMux(true);
#if NET_DEBUG
net_printf("%s::Open ", Protocol == NetType::Tcp ? "Tcp" : "Udp");
Local.Show(false);
net_printf(" => ");
if (Server)
{
Server.Show(false);
net_printf(":%d\r\n", Remote.Port);
}
else
Remote.Show(true);
#endif
String cmd = "AT+CIPSTART=";
cmd = cmd + _Index + ",";
if (Protocol == NetType::Udp)
cmd += "\"UDP\"";
else if (Protocol == NetType::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*/
if (Protocol == NetType::Udp) cmd += ",0";
// 打开Socket。有OK/ERROR/ALREADY CONNECTED三种
auto rt = _Host.At.Send(cmd + "\r\n", "OK", "ERROR", 10000, false);
if (!rt.Contains("OK") && !rt.Contains("ALREADY CONNECTED"))
{
net_printf("协议 %d, %d 打开失败 \r\n", (byte)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;
_Host.At.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.At.Send(cmd, ">", "ERROR", 1600, false);
if (rt.Contains(">")) break;
Sys.Sleep(500);
}
if (i < 3 && _Host.At.Send(bs.AsString(), "SEND OK", "ERROR", 1600, false).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);
}