parent
017035f573
commit
217618d848
|
@ -0,0 +1,397 @@
|
||||||
|
#include "Kernel\Sys.h"
|
||||||
|
#include "Kernel\Task.h"
|
||||||
|
#include "Kernel\TTime.h"
|
||||||
|
#include "Kernel\WaitHandle.h"
|
||||||
|
|
||||||
|
#include "Device\SerialPort.h"
|
||||||
|
|
||||||
|
#include "AT.h"
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
#include "App\FlushPort.h"
|
||||||
|
|
||||||
|
#define NET_DEBUG DEBUG
|
||||||
|
//#define NET_DEBUG 0
|
||||||
|
#if NET_DEBUG
|
||||||
|
#define net_printf debug_printf
|
||||||
|
#else
|
||||||
|
#define net_printf(format, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct CmdState
|
||||||
|
{
|
||||||
|
const String* Command = nullptr;
|
||||||
|
String* Result = nullptr;
|
||||||
|
cstring Key1 = nullptr;
|
||||||
|
cstring Key2 = nullptr;
|
||||||
|
cstring Key3 = nullptr;
|
||||||
|
|
||||||
|
bool Capture = true; // 是否捕获所有
|
||||||
|
|
||||||
|
uint Parse(const Buffer& bs, WaitHandle& handle);
|
||||||
|
uint FindKey(const String& str);
|
||||||
|
};
|
||||||
|
|
||||||
|
void LoadStationTask(void* param);
|
||||||
|
|
||||||
|
/*
|
||||||
|
注意事项
|
||||||
|
1、设置模式AT+CWMODE需要重启后生效AT+RST
|
||||||
|
2、AP模式下查询本机IP无效,可能会造成死机
|
||||||
|
3、开启server需要多连接作为基础AT+CIPMUX=1
|
||||||
|
4、单连接模式,多连接模式 收发数据有参数个数区别
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******************************** AT ********************************/
|
||||||
|
|
||||||
|
AT::AT()
|
||||||
|
{
|
||||||
|
Port = nullptr;
|
||||||
|
DataKey = nullptr;
|
||||||
|
_Expect = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
AT::~AT()
|
||||||
|
{
|
||||||
|
delete Port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AT::Init(COM idx, int baudrate)
|
||||||
|
{
|
||||||
|
auto srp = new SerialPort(idx, baudrate);
|
||||||
|
srp->Tx.SetCapacity(0x200);
|
||||||
|
srp->Rx.SetCapacity(0x200);
|
||||||
|
srp->MaxSize = 512;
|
||||||
|
|
||||||
|
Init(srp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AT::Init(ITransport* port)
|
||||||
|
{
|
||||||
|
Port = port;
|
||||||
|
if (Port) Port->Register(OnPortReceive, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AT::Open()
|
||||||
|
{
|
||||||
|
if (!Port->Open()) return false;
|
||||||
|
|
||||||
|
/*if (!CheckReady())
|
||||||
|
{
|
||||||
|
net_printf("AT::Open 打开失败!");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AT::Close()
|
||||||
|
{
|
||||||
|
Port->Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送指令,在超时时间内等待返回期望字符串,然后返回内容
|
||||||
|
String AT::Send(const String& cmd, cstring expect, cstring expect2, uint msTimeout)
|
||||||
|
{
|
||||||
|
TS("AT::Send");
|
||||||
|
|
||||||
|
String rs;
|
||||||
|
|
||||||
|
auto& task = Task::Current();
|
||||||
|
// 判断是否正在发送其它指令
|
||||||
|
if (_Expect)
|
||||||
|
{
|
||||||
|
#if NET_DEBUG
|
||||||
|
auto h = (WaitHandle*)_Expect;
|
||||||
|
auto w = (CmdState*)h->State;
|
||||||
|
net_printf("AT::Send %d 正在发送 ", h->TaskID);
|
||||||
|
if (w->Command)
|
||||||
|
w->Command->Trim().Show(false);
|
||||||
|
else
|
||||||
|
net_printf("数据");
|
||||||
|
net_printf(" ,%d 无法发送 ", task.ID);
|
||||||
|
cmd.Trim().Show(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在接收事件中拦截
|
||||||
|
CmdState we;
|
||||||
|
// 数据不显示Command,没有打开NET_DEBUG时也不显示
|
||||||
|
//we.Command = &cmd;
|
||||||
|
we.Result = &rs;
|
||||||
|
we.Key1 = expect;
|
||||||
|
we.Key2 = expect2;
|
||||||
|
we.Key3 = "busy ";
|
||||||
|
|
||||||
|
WaitHandle handle;
|
||||||
|
handle.State = &we;
|
||||||
|
|
||||||
|
_Expect = &handle;
|
||||||
|
|
||||||
|
#if NET_DEBUG
|
||||||
|
bool EnableLog = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (cmd)
|
||||||
|
{
|
||||||
|
Port->Write(cmd);
|
||||||
|
|
||||||
|
#if NET_DEBUG
|
||||||
|
// 只有AT指令显示日志
|
||||||
|
if (!cmd.StartsWith("AT") || (expect && expect[0] == '>')) EnableLog = false;
|
||||||
|
if (EnableLog)
|
||||||
|
{
|
||||||
|
we.Command = &cmd;
|
||||||
|
//net_printf("%d=> ", task.ID);
|
||||||
|
cmd.Trim().Show(true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
handle.WaitOne(msTimeout);
|
||||||
|
if (_Expect == &handle) _Expect = nullptr;
|
||||||
|
|
||||||
|
//if(rs.Length() > 4) rs.Trim();
|
||||||
|
|
||||||
|
#if NET_DEBUG
|
||||||
|
if (EnableLog && rs)
|
||||||
|
{
|
||||||
|
net_printf("%d<= ", task.ID);
|
||||||
|
// 太长时不要去尾,避免产生重新分配
|
||||||
|
if (rs.Length() < 0x40)
|
||||||
|
rs.Trim().Show(true);
|
||||||
|
else
|
||||||
|
rs.Show(true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送命令,自动检测并加上\r\n,等待响应OK
|
||||||
|
bool AT::SendCmd(const String& cmd, uint msTimeout)
|
||||||
|
{
|
||||||
|
TS("AT::SendCmd");
|
||||||
|
|
||||||
|
static const cstring ok = "OK";
|
||||||
|
static const cstring err = "ERROR";
|
||||||
|
|
||||||
|
String cmd2;
|
||||||
|
|
||||||
|
// 只有AT指令需要检查结尾,其它指令不检查,避免产生拷贝
|
||||||
|
auto p = &cmd;
|
||||||
|
if (cmd.StartsWith("AT") && !cmd.EndsWith("\r\n"))
|
||||||
|
{
|
||||||
|
cmd2 = cmd;
|
||||||
|
cmd2 += "\r\n";
|
||||||
|
p = &cmd2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 二级拦截。遇到错误也马上结束
|
||||||
|
auto rt = Send(*p, ok, err, msTimeout);
|
||||||
|
|
||||||
|
return rt.Contains(ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AT::WaitForCmd(cstring expect, uint msTimeout)
|
||||||
|
{
|
||||||
|
String rs;
|
||||||
|
|
||||||
|
// 在接收事件中拦截
|
||||||
|
CmdState we;
|
||||||
|
we.Result = &rs;
|
||||||
|
we.Key1 = expect;
|
||||||
|
we.Capture = false;
|
||||||
|
|
||||||
|
WaitHandle handle;
|
||||||
|
handle.State = &we;
|
||||||
|
|
||||||
|
_Expect = &handle;
|
||||||
|
|
||||||
|
// 等待收到数据
|
||||||
|
bool rt = handle.WaitOne(msTimeout);
|
||||||
|
|
||||||
|
_Expect = nullptr;
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParseFail(cstring name, const Buffer& bs)
|
||||||
|
{
|
||||||
|
#if NET_DEBUG
|
||||||
|
if (bs.Length() == 0) return;
|
||||||
|
|
||||||
|
int p = 0;
|
||||||
|
if (p < bs.Length() && bs[p] == ' ') p++;
|
||||||
|
if (p < bs.Length() && bs[p] == '\r') p++;
|
||||||
|
if (p < bs.Length() && bs[p] == '\n') p++;
|
||||||
|
|
||||||
|
// 无法识别的数据可能是空格前缀,需要特殊处理
|
||||||
|
auto str = bs.Sub(p, -1).AsString();
|
||||||
|
if (str)
|
||||||
|
{
|
||||||
|
net_printf("AT:%s 无法识别[%d]:", name, bs.Length());
|
||||||
|
//if(bs.Length() == 2) net_printf("%02X %02X ", bs[0], bs[1]);
|
||||||
|
str.Show(true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint AT::OnPortReceive(ITransport* sender, Buffer& bs, void* param, void* param2)
|
||||||
|
{
|
||||||
|
auto esp = (AT*)param;
|
||||||
|
return esp->OnReceive(bs, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 引发数据到达事件
|
||||||
|
uint AT::OnReceive(Buffer& bs, void* param)
|
||||||
|
{
|
||||||
|
if (bs.Length() == 0) return 0;
|
||||||
|
|
||||||
|
//!!! 分析数据和命令返回,特别要注意粘包
|
||||||
|
int s = 0;
|
||||||
|
int p = 0;
|
||||||
|
auto str = bs.AsString();
|
||||||
|
while (p >= 0 && p < bs.Length())
|
||||||
|
{
|
||||||
|
s = p;
|
||||||
|
p = str.IndexOf(DataKey, s);
|
||||||
|
|
||||||
|
// +IPD之前之后的数据,留给命令分析
|
||||||
|
int size = p >= 0 ? p - s : bs.Length() - s;
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
if (_Expect)
|
||||||
|
{
|
||||||
|
ParseReply(bs.Sub(s, size));
|
||||||
|
#if NET_DEBUG
|
||||||
|
// 如果没有吃完,剩下部分报未识别
|
||||||
|
//if(rs < size) ParseFail("ParseReply", bs.Sub(s + rs, size - rs));
|
||||||
|
// 不要报未识别了,反正内部会全部吃掉
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if NET_DEBUG
|
||||||
|
ParseFail("NoExpect", bs.Sub(s, size));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// +IPD开头的数据,作为收到数据
|
||||||
|
if (p >= 0)
|
||||||
|
{
|
||||||
|
if (p + 5 >= bs.Length())
|
||||||
|
{
|
||||||
|
#if NET_DEBUG
|
||||||
|
ParseFail("+IPD<=5", bs.Sub(p, -1));
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto bs2 = bs.Sub(p, -1);
|
||||||
|
Received(bs2);
|
||||||
|
int rs = bs2.Length();
|
||||||
|
if (rs <= 0)
|
||||||
|
{
|
||||||
|
#if NET_DEBUG
|
||||||
|
ParseFail("ParseReceive", bs.Sub(p + rs, -1));
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 游标移到下一组数据
|
||||||
|
p += rs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分析关键字。返回被用掉的字节数
|
||||||
|
uint AT::ParseReply(const Buffer& bs)
|
||||||
|
{
|
||||||
|
if (!_Expect) return 0;
|
||||||
|
|
||||||
|
// 拦截给同步方法
|
||||||
|
auto handle = (WaitHandle*)_Expect;
|
||||||
|
auto we = (CmdState*)handle->State;
|
||||||
|
bool rs = we->Parse(bs, *handle);
|
||||||
|
|
||||||
|
// 如果内部已经适配,则清空
|
||||||
|
if (!we->Result) _Expect = nullptr;
|
||||||
|
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint CmdState::Parse(const Buffer& bs, WaitHandle& handle)
|
||||||
|
{
|
||||||
|
if (bs.Length() == 0 || !Result) return 0;
|
||||||
|
|
||||||
|
TS("WaitExpect::Parse");
|
||||||
|
|
||||||
|
// 适配任意关键字后,也就是收到了成功或失败,通知业务层已结束
|
||||||
|
auto s_ = bs.AsString();
|
||||||
|
auto& s = (const String&)s_;
|
||||||
|
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;
|
||||||
|
|
||||||
|
// 设置事件,通知等待任务退出循环
|
||||||
|
handle.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果后面是换行,则跳过
|
||||||
|
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 CmdState::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(Key3);
|
||||||
|
if (p >= 0)
|
||||||
|
{
|
||||||
|
net_printf("适配第三关键字 %s \r\n", Key3);
|
||||||
|
return p + String(Key3).Length();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef __AT_H__
|
||||||
|
#define __AT_H__
|
||||||
|
|
||||||
|
// GPRS的AT指令集 GSM 07.07
|
||||||
|
class AT
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ITransport* Port; // 传输口
|
||||||
|
|
||||||
|
cstring DataKey; // 数据关键字
|
||||||
|
|
||||||
|
Delegate<Buffer&> Received;
|
||||||
|
|
||||||
|
AT();
|
||||||
|
~AT();
|
||||||
|
|
||||||
|
void Init(COM idx, int baudrate = 115200);
|
||||||
|
void Init(ITransport* port);
|
||||||
|
|
||||||
|
// 打开与关闭
|
||||||
|
bool Open();
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
/******************************** 发送指令 ********************************/
|
||||||
|
// 发送指令,在超时时间内等待返回期望字符串,然后返回内容
|
||||||
|
String Send(const String& cmd, cstring expect, cstring expect2 = nullptr, uint msTimeout = 1000);
|
||||||
|
// 发送命令,自动检测并加上\r\n,等待响应OK
|
||||||
|
bool SendCmd(const String& cmd, uint msTimeout = 1000);
|
||||||
|
// 等待命令返回
|
||||||
|
bool WaitForCmd(cstring expect, uint msTimeout);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* _Expect; // 等待内容
|
||||||
|
|
||||||
|
// 分析关键字。返回被用掉的字节数
|
||||||
|
uint ParseReply(const Buffer& bs);
|
||||||
|
|
||||||
|
// 引发数据到达事件
|
||||||
|
uint OnReceive(Buffer& bs, void* param);
|
||||||
|
static uint OnPortReceive(ITransport* sender, Buffer& bs, void* param, void* param2);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -5,9 +5,7 @@
|
||||||
#include "Device\WatchDog.h"
|
#include "Device\WatchDog.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#include "Drivers\NRF24L01.h"
|
#include "Drivers\GSM07.h"
|
||||||
#include "Drivers\W5500.h"
|
|
||||||
#include "Drivers\Esp8266\Esp8266.h"
|
|
||||||
|
|
||||||
#include "TokenNet\TokenController.h"
|
#include "TokenNet\TokenController.h"
|
||||||
#include "TokenNet\TokenConfig.h"
|
#include "TokenNet\TokenConfig.h"
|
||||||
|
@ -124,52 +122,22 @@ void AP0803::InitButtons(const Delegate2<InputPort&, bool>& press)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkInterface* AP0803::Create5500()
|
NetworkInterface* AP0803::CreateGPRS()
|
||||||
{
|
{
|
||||||
debug_printf("\r\nW5500::Create \r\n");
|
debug_printf("\r\nCreateGPRS::Create \r\n");
|
||||||
|
|
||||||
auto net = new W5500(Spi2, PE1, PD13);
|
auto net = new GSM07();
|
||||||
|
net->Init(COM4);
|
||||||
|
net->Set(P0, P0);
|
||||||
if(!net->Open())
|
if(!net->Open())
|
||||||
{
|
{
|
||||||
delete net;
|
delete net;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
net->EnableDNS();
|
|
||||||
net->EnableDHCP();
|
|
||||||
|
|
||||||
return net;
|
return net;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkInterface* AP0803::Create8266(bool apOnly)
|
|
||||||
{
|
|
||||||
debug_printf("\r\nEsp8266::Create \r\n");
|
|
||||||
|
|
||||||
auto esp = new Esp8266(COM4, PE2, PD3);
|
|
||||||
|
|
||||||
// 初次需要指定模式 否则为 Wire
|
|
||||||
bool join = esp->SSID && *esp->SSID;
|
|
||||||
if (!join)
|
|
||||||
{
|
|
||||||
*esp->SSID = "WSWL";
|
|
||||||
*esp->Pass = "12345678";
|
|
||||||
|
|
||||||
esp->Mode = NetworkType::STA_AP;
|
|
||||||
esp->WorkMode = NetworkType::STA_AP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!esp->Open())
|
|
||||||
{
|
|
||||||
delete esp;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Client->Register("SetWiFi", &Esp8266::SetWiFi, esp);
|
|
||||||
Client->Register("GetWiFi", &Esp8266::GetWiFi, esp);
|
|
||||||
|
|
||||||
return esp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************** Token ********************************/
|
/******************************** Token ********************************/
|
||||||
|
|
||||||
void AP0803::InitClient()
|
void AP0803::InitClient()
|
||||||
|
@ -209,8 +177,7 @@ static void OnInitNet(void* param)
|
||||||
{
|
{
|
||||||
auto& bsp = *(AP0803*)param;
|
auto& bsp = *(AP0803*)param;
|
||||||
|
|
||||||
bsp.Create5500();
|
bsp.CreateGPRS();
|
||||||
bsp.Create8266(false);
|
|
||||||
|
|
||||||
Client->Open();
|
Client->Open();
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,12 +40,8 @@ public:
|
||||||
void InitLeds();
|
void InitLeds();
|
||||||
void InitButtons(const Delegate2<InputPort&, bool>& press);
|
void InitButtons(const Delegate2<InputPort&, bool>& press);
|
||||||
|
|
||||||
// 打开以太网W5500
|
// 打开GPRS
|
||||||
NetworkInterface* Create5500();
|
NetworkInterface* CreateGPRS();
|
||||||
// 打开Esp8266,作为主控或者纯AP
|
|
||||||
NetworkInterface* Create8266(bool apOnly);
|
|
||||||
|
|
||||||
// ITransport* Create2401();
|
|
||||||
|
|
||||||
void InitClient();
|
void InitClient();
|
||||||
void InitNet();
|
void InitNet();
|
||||||
|
|
|
@ -18,21 +18,6 @@ bool WaitExpect::Wait(int msTimeout)
|
||||||
Sys.Sleep(40);
|
Sys.Sleep(40);
|
||||||
if(!Result) return true;
|
if(!Result) return true;
|
||||||
|
|
||||||
/*// 等待收到数据
|
|
||||||
TimeWheel tw(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;*/
|
|
||||||
|
|
||||||
return Handle.WaitOne(msTimeout);
|
return Handle.WaitOne(msTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,324 @@
|
||||||
|
#include "Kernel\Sys.h"
|
||||||
|
#include "Kernel\Task.h"
|
||||||
|
#include "Kernel\TTime.h"
|
||||||
|
#include "Kernel\WaitHandle.h"
|
||||||
|
|
||||||
|
#include "Device\SerialPort.h"
|
||||||
|
|
||||||
|
#include "GSM07.h"
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
#include "App\FlushPort.h"
|
||||||
|
|
||||||
|
#define NET_DEBUG DEBUG
|
||||||
|
//#define NET_DEBUG 0
|
||||||
|
#if NET_DEBUG
|
||||||
|
#define net_printf debug_printf
|
||||||
|
#else
|
||||||
|
#define net_printf(format, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct CmdState
|
||||||
|
{
|
||||||
|
String* Command = nullptr;
|
||||||
|
String* Result = nullptr;
|
||||||
|
cstring Key1 = nullptr;
|
||||||
|
cstring Key2 = nullptr;
|
||||||
|
|
||||||
|
bool Capture = true; // 是否捕获所有
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
注意事项
|
||||||
|
1、设置模式AT+CWMODE需要重启后生效AT+RST
|
||||||
|
2、AP模式下查询本机IP无效,可能会造成死机
|
||||||
|
3、开启server需要多连接作为基础AT+CIPMUX=1
|
||||||
|
4、单连接模式,多连接模式 收发数据有参数个数区别
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******************************** GSM07 ********************************/
|
||||||
|
|
||||||
|
GSM07::GSM07()
|
||||||
|
{
|
||||||
|
Name = "GSM07";
|
||||||
|
Speed = 10;
|
||||||
|
|
||||||
|
APN = "CMNET";
|
||||||
|
|
||||||
|
Led = nullptr;
|
||||||
|
|
||||||
|
Buffer(_sockets, 5 * 4).Clear();
|
||||||
|
|
||||||
|
Mode = NetworkType::STA_AP;
|
||||||
|
|
||||||
|
InitConfig();
|
||||||
|
LoadConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
GSM07::~GSM07()
|
||||||
|
{
|
||||||
|
RemoveLed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GSM07::Init(COM idx, int baudrate)
|
||||||
|
{
|
||||||
|
At.Init(idx, baudrate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GSM07::Init(ITransport* port)
|
||||||
|
{
|
||||||
|
At.Init(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GSM07::Set(Pin power, Pin rst)
|
||||||
|
{
|
||||||
|
if (power != P0) _Power.Init(power, false);
|
||||||
|
if (rst != P0) _Reset.Init(rst, true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GSM07::SetLed(Pin led)
|
||||||
|
{
|
||||||
|
if (led != P0)
|
||||||
|
{
|
||||||
|
auto port = new OutputPort(led);
|
||||||
|
SetLed(*port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GSM07::SetLed(OutputPort& led)
|
||||||
|
{
|
||||||
|
auto fp = new FlushPort();
|
||||||
|
fp->Port = &led;
|
||||||
|
fp->Start();
|
||||||
|
Led = fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GSM07::RemoveLed()
|
||||||
|
{
|
||||||
|
if (Led)delete (FlushPort*)Led;
|
||||||
|
Led = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GSM07::OnOpen()
|
||||||
|
{
|
||||||
|
if (!At.Open()) return false;
|
||||||
|
|
||||||
|
if (!CheckReady())
|
||||||
|
{
|
||||||
|
net_printf("GSM07::Open 打开失败!");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
At.Received.Bind(&GSM07::OnReceive, this);
|
||||||
|
|
||||||
|
// 开回显
|
||||||
|
Echo(true);
|
||||||
|
|
||||||
|
#if NET_DEBUG
|
||||||
|
// 获取版本
|
||||||
|
GetVersion();
|
||||||
|
//auto ver = GetVersion();
|
||||||
|
//net_printf("版本:");
|
||||||
|
//ver.Show(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Config();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GSM07::CheckReady()
|
||||||
|
{
|
||||||
|
// 先关一会电,然后再上电,让它来一个完整的冷启动
|
||||||
|
if (!_Power.Empty())
|
||||||
|
{
|
||||||
|
_Power.Open(); // 使用前必须Open;
|
||||||
|
_Power.Down(20);
|
||||||
|
}
|
||||||
|
if (!_Reset.Empty()) _Reset.Open(); // 使用前必须Open;
|
||||||
|
|
||||||
|
// 每两次启动会有一次打开失败,交替
|
||||||
|
if (!_Reset.Empty())
|
||||||
|
Reset(false); // 硬重启
|
||||||
|
else
|
||||||
|
Reset(true); // 软件重启命令
|
||||||
|
|
||||||
|
// 等待模块启动进入就绪状态
|
||||||
|
if (!Test())
|
||||||
|
{
|
||||||
|
net_printf("GSM07::Open 打开失败!");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GSM07::OnClose()
|
||||||
|
{
|
||||||
|
// 先断开已有连接
|
||||||
|
At.SendCmd("AT+CIPSHUT\r");
|
||||||
|
|
||||||
|
At.Close();
|
||||||
|
|
||||||
|
_Power.Close();
|
||||||
|
_Reset.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GSM07::OnLink(uint retry)
|
||||||
|
{
|
||||||
|
//if(Linked) return true;
|
||||||
|
|
||||||
|
debug_printf("GSM07::OnLink\r\n");
|
||||||
|
|
||||||
|
/*bool join = SSID && *SSID;
|
||||||
|
// 等待WiFi自动连接
|
||||||
|
if (!WaitForCmd("WIFI CONNECTED", 3000))
|
||||||
|
{
|
||||||
|
auto mode = WorkMode;
|
||||||
|
// 默认Both
|
||||||
|
if (mode == NetworkType::Wire) mode = NetworkType::STA_AP;
|
||||||
|
if (!join || mode == NetworkType::STA_AP) OpenAP();
|
||||||
|
if (join)
|
||||||
|
{
|
||||||
|
if (!JoinAP(*SSID, *Pass)) return false;
|
||||||
|
|
||||||
|
ShowConfig();
|
||||||
|
SaveConfig();
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 配置网络参数
|
||||||
|
void GSM07::Config()
|
||||||
|
{
|
||||||
|
// ATE0 关闭回显
|
||||||
|
// ATE1 开启回显
|
||||||
|
At.SendCmd("ATE0\r");
|
||||||
|
At.SendCmd("AT+CIPSHUT\r");
|
||||||
|
At.SendCmd("AT+CGCLASS=\"B\"\r");
|
||||||
|
SetAPN(APN, false);
|
||||||
|
At.SendCmd("AT+CGATT=1\r");
|
||||||
|
// 先断开已有连接
|
||||||
|
//At.SendCmd("AT+CIPSHUT\r");
|
||||||
|
//设置APN
|
||||||
|
SetAPN(APN, true);
|
||||||
|
At.SendCmd("AT+CLPORT=\"UDP\",\"3399\"\r");
|
||||||
|
// IP设置方式
|
||||||
|
//At.SendCmd("AT+CIPSTART=\"UDP\",\"183.63.213.113\",\"3388\"\r");
|
||||||
|
// 域名设置方式
|
||||||
|
At.SendCmd("AT+CIPMUX=0\r");
|
||||||
|
At.SendCmd("AT+CIPRXGET=1\r");
|
||||||
|
At.SendCmd("AT+CIPQRCLOSE=1\r");
|
||||||
|
At.SendCmd("AT+CIPMODE=0\r");
|
||||||
|
}
|
||||||
|
|
||||||
|
Socket* GSM07::CreateSocket(NetType type)
|
||||||
|
{
|
||||||
|
/*auto es = (EspSocket**)_sockets;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
if (es[i] == nullptr) break;
|
||||||
|
}
|
||||||
|
if (i >= 5)
|
||||||
|
{
|
||||||
|
net_printf("没有空余的Socket可用了 !\r\n");
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
/*case NetType::Tcp:
|
||||||
|
return es[i] = new EspTcp(*this, i);
|
||||||
|
|
||||||
|
case NetType::Udp:
|
||||||
|
return es[i] = new EspUdp(*this, i);*/
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据到达
|
||||||
|
void GSM07::OnReceive(Buffer& bs)
|
||||||
|
{
|
||||||
|
Received(bs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************** 基础AT指令 ********************************/
|
||||||
|
|
||||||
|
// 基础AT指令
|
||||||
|
bool GSM07::Test()
|
||||||
|
{
|
||||||
|
// 避免在循环内部频繁构造和析构
|
||||||
|
String cmd = "AT";
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
if (At.SendCmd(cmd, 500)) return true;
|
||||||
|
|
||||||
|
Reset(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GSM07::Reset(bool soft)
|
||||||
|
{
|
||||||
|
if (soft) return At.SendCmd("AT+RST");
|
||||||
|
|
||||||
|
_Reset.Up(100);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
AT 版本信息
|
||||||
|
基于的SDK版本信息
|
||||||
|
编译生成时间
|
||||||
|
*/
|
||||||
|
String GSM07::GetVersion()
|
||||||
|
{
|
||||||
|
return At.Send("AT+GMR\r\n", "OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GSM07::Sleep(uint ms)
|
||||||
|
{
|
||||||
|
String cmd = "AT+GSLP=";
|
||||||
|
cmd += ms;
|
||||||
|
return At.SendCmd(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GSM07::Echo(bool open)
|
||||||
|
{
|
||||||
|
String cmd = "ATE";
|
||||||
|
cmd = cmd + (open ? '1' : '0');
|
||||||
|
return At.SendCmd(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复出厂设置,将擦写所有保存到Flash的参数,恢复为默认参数。会导致模块重启
|
||||||
|
bool GSM07::Restore()
|
||||||
|
{
|
||||||
|
return At.SendCmd("AT+RESTORE");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 00:CMNET 10:CMHK 01:CHKT 11:HKCSL
|
||||||
|
void GSM07::SetAPN(cstring apn, bool issgp)
|
||||||
|
{
|
||||||
|
String str;
|
||||||
|
if(issgp)
|
||||||
|
str = "AT+CIPCSGP=1";
|
||||||
|
else
|
||||||
|
str = "AT+CGDCONT=1,\"IP\"";
|
||||||
|
str = str + ",\"" + apn + "\"\r";
|
||||||
|
|
||||||
|
At.SendCmd(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************** TCP/IP ********************************/
|
|
@ -0,0 +1,84 @@
|
||||||
|
#ifndef __GSM07_H__
|
||||||
|
#define __GSM07_H__
|
||||||
|
|
||||||
|
#include "Device\Port.h"
|
||||||
|
|
||||||
|
#include "App\AT.h"
|
||||||
|
|
||||||
|
#include "Net\Socket.h"
|
||||||
|
#include "Net\NetworkInterface.h"
|
||||||
|
#include "Net\ITransport.h"
|
||||||
|
|
||||||
|
#include "Message\DataStore.h"
|
||||||
|
#include "Message\Pair.h"
|
||||||
|
|
||||||
|
// GPRS的AT指令集 GSM 07.07
|
||||||
|
class GSM07 : public NetworkInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AT At; // AT操作对象
|
||||||
|
cstring APN;
|
||||||
|
|
||||||
|
IDataPort* Led; // 指示灯
|
||||||
|
|
||||||
|
OutputPort _Power;
|
||||||
|
OutputPort _Reset;
|
||||||
|
OutputPort _LowPower;
|
||||||
|
|
||||||
|
Delegate<Buffer&> Received;
|
||||||
|
|
||||||
|
GSM07();
|
||||||
|
virtual ~GSM07();
|
||||||
|
|
||||||
|
void Init(ITransport* port);
|
||||||
|
void Init(COM idx, int baudrate = 115200);
|
||||||
|
void Set(Pin power = P0, Pin rst = P0);
|
||||||
|
|
||||||
|
virtual void Config();
|
||||||
|
void SetLed(Pin led);
|
||||||
|
void SetLed(OutputPort& led);
|
||||||
|
void RemoveLed();
|
||||||
|
|
||||||
|
virtual Socket* CreateSocket(NetType type);
|
||||||
|
|
||||||
|
/******************************** 基础AT指令 ********************************/
|
||||||
|
bool Test();
|
||||||
|
bool Reset(bool soft);
|
||||||
|
String GetVersion();
|
||||||
|
bool Sleep(uint ms);
|
||||||
|
bool Echo(bool open);
|
||||||
|
// 恢复出厂设置,将擦写所有保存到Flash的参数,恢复为默认参数。会导致模块重启
|
||||||
|
bool Restore();
|
||||||
|
void SetAPN(cstring apn, bool issgp);
|
||||||
|
|
||||||
|
/******************************** 功能指令 ********************************/
|
||||||
|
IPAddress GetIP(bool sta);
|
||||||
|
|
||||||
|
/******************************** TCP/IP ********************************/
|
||||||
|
|
||||||
|
/******************************** 发送指令 ********************************/
|
||||||
|
|
||||||
|
private:
|
||||||
|
IPEndPoint _Remote; // 当前数据包远程地址
|
||||||
|
|
||||||
|
// 打开与关闭
|
||||||
|
virtual bool OnOpen();
|
||||||
|
virtual void OnClose();
|
||||||
|
// 检测连接
|
||||||
|
virtual bool OnLink(uint retry);
|
||||||
|
|
||||||
|
bool CheckReady();
|
||||||
|
|
||||||
|
// 多个硬件socket
|
||||||
|
int* _sockets[5];
|
||||||
|
|
||||||
|
// 分析+IPD接收数据。返回被用掉的字节数
|
||||||
|
uint ParseReceive(const Buffer& bs);
|
||||||
|
// 分析关键字。返回被用掉的字节数
|
||||||
|
uint ParseReply(const Buffer& bs);
|
||||||
|
|
||||||
|
// 数据到达
|
||||||
|
void OnReceive(Buffer& bs);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -13,6 +13,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\App\ACZero.cpp" />
|
<ClCompile Include="..\App\ACZero.cpp" />
|
||||||
<ClCompile Include="..\App\Alarm.cpp" />
|
<ClCompile Include="..\App\Alarm.cpp" />
|
||||||
|
<ClCompile Include="..\App\AT.cpp" />
|
||||||
<ClCompile Include="..\App\BlinkPort.cpp" />
|
<ClCompile Include="..\App\BlinkPort.cpp" />
|
||||||
<ClCompile Include="..\App\Button.cpp" />
|
<ClCompile Include="..\App\Button.cpp" />
|
||||||
<ClCompile Include="..\App\Button_GrayLevel.cpp" />
|
<ClCompile Include="..\App\Button_GrayLevel.cpp" />
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
<ClCompile Include="..\Board\AP0104.cpp" />
|
<ClCompile Include="..\Board\AP0104.cpp" />
|
||||||
<ClCompile Include="..\Board\AP0801.cpp" />
|
<ClCompile Include="..\Board\AP0801.cpp" />
|
||||||
<ClCompile Include="..\Board\AP0802.cpp" />
|
<ClCompile Include="..\Board\AP0802.cpp" />
|
||||||
|
<ClCompile Include="..\Board\AP0803.cpp" />
|
||||||
<ClCompile Include="..\Board\BaseBoard.cpp" />
|
<ClCompile Include="..\Board\BaseBoard.cpp" />
|
||||||
<ClCompile Include="..\Board\IOK026X.cpp" />
|
<ClCompile Include="..\Board\IOK026X.cpp" />
|
||||||
<ClCompile Include="..\Board\IOK027X.cpp" />
|
<ClCompile Include="..\Board\IOK027X.cpp" />
|
||||||
|
@ -84,6 +86,7 @@
|
||||||
<ClCompile Include="..\Drivers\Esp8266\EspTcp.cpp" />
|
<ClCompile Include="..\Drivers\Esp8266\EspTcp.cpp" />
|
||||||
<ClCompile Include="..\Drivers\Esp8266\EspUdp.cpp" />
|
<ClCompile Include="..\Drivers\Esp8266\EspUdp.cpp" />
|
||||||
<ClCompile Include="..\Drivers\Esp8266\WaitExpect.cpp" />
|
<ClCompile Include="..\Drivers\Esp8266\WaitExpect.cpp" />
|
||||||
|
<ClCompile Include="..\Drivers\GSM07.cpp" />
|
||||||
<ClCompile Include="..\Drivers\HX711.cpp" />
|
<ClCompile Include="..\Drivers\HX711.cpp" />
|
||||||
<ClCompile Include="..\Drivers\JTW8953.cpp" />
|
<ClCompile Include="..\Drivers\JTW8953.cpp" />
|
||||||
<ClCompile Include="..\Drivers\NRF24L01.cpp" />
|
<ClCompile Include="..\Drivers\NRF24L01.cpp" />
|
||||||
|
|
|
@ -560,5 +560,14 @@
|
||||||
<ClCompile Include="..\Drivers\Esp8266\WaitExpect.cpp">
|
<ClCompile Include="..\Drivers\Esp8266\WaitExpect.cpp">
|
||||||
<Filter>Drivers\Esp8266</Filter>
|
<Filter>Drivers\Esp8266</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\Board\AP0803.cpp">
|
||||||
|
<Filter>Board</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\Drivers\GSM07.cpp">
|
||||||
|
<Filter>Drivers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\App\AT.cpp">
|
||||||
|
<Filter>App</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in New Issue