物联协议在0905上测试通过

This commit is contained in:
大石头 2017-08-29 23:29:55 +08:00
parent 466cdae9ad
commit a1c72b8774
6 changed files with 329 additions and 0 deletions

154
Board/LinkBoard.cpp Normal file
View File

@ -0,0 +1,154 @@
#include "LinkBoard.h"
#include "Drivers\W5500.h"
#include "Drivers\Esp8266\Esp8266.h"
LinkBoard::LinkBoard()
{
Client = nullptr;
Data = nullptr;
Size = 0;
}
void* LinkBoard::InitData(void* data, int size)
{
// 启动信息
auto hot = &HotConfig::Current();
hot->Times++;
data = hot->Next();
if (hot->Times == 1)
{
Buffer ds(data, size);
ds.Clear();
ds[0] = size;
}
Data = data;
Size = size;
#if DEBUG
debug_printf("数据区[%d]", hot->Times);
Buffer(Data, Size).Show(true);
#endif
return data;
}
// 写入数据区并上报
void LinkBoard::Write(uint offset, byte data)
{
auto client = Client;
if (!client) return;
client->Store.Write(offset, data);
client->ReportAsync(offset, 1);
}
/******************************** Link ********************************/
void LinkBoard::InitClient()
{
if (Client) return;
// 初始化配置区
InitConfig();
// 初始化令牌网
auto tk = LinkConfig::Create("tcp://192.168.0.3:2233");
// 创建客户端
auto tc = LinkClient::CreateFast(Buffer(Data, Size));
tc->Cfg = tk;
tc->MaxNotActive = 8 * 60 * 1000;
Client = tc;
}
void LinkBoard::Register(uint offset, IDataPort& dp)
{
if (!Client) return;
auto& ds = Client->Store;
ds.Register(offset, dp);
}
void LinkBoard::Register(uint offset, uint size, Handler hook)
{
if (!Client) return;
auto& ds = Client->Store;
ds.Register(offset, size, hook);
}
void LinkBoard::OnLongPress(InputPort* port, bool down)
{
if (down) return;
debug_printf("Press P%c%d Time=%d ms\r\n", _PIN_NAME(port->_Pin), port->PressTime);
auto client = Client;
if (!client) return;
ushort time = port->PressTime;
if (time >= 5000 && time < 10000)
{
client->Reset("按键重置");
}
else if (time >= 3000)
{
client->Reboot("按键重启");
Sys.Reboot(1000);
}
}
NetworkInterface* LinkBoard::Create5500()
{
debug_printf("\r\nW5500::Create \r\n");
auto net = new W5500(Net.Spi, Net.Irq, Net.Reset);
if (!net->Open())
{
delete net;
return nullptr;
}
net->SetLed(*Leds[0]);
net->EnableDNS();
net->EnableDHCP();
return net;
}
NetworkInterface* LinkBoard::Create8266()
{
debug_printf("\r\nEsp8266::Create \r\n");
auto esp = new Esp8266();
esp->Init(Esp.Com, Esp.Baudrate);
esp->Set(Esp.Power, Esp.Reset, Esp.LowPower);
// 初次需要指定模式 否则为 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;
}
esp->SetLed(*Leds[1]);
//Client->Register("SetWiFi", &Esp8266::SetWiFi, esp);
//Client->Register("GetWiFi", &Esp8266::GetWiFi, esp);
return esp;
}

48
Board/LinkBoard.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef _LinkBoard_H_
#define _LinkBoard_H_
#include "Net\Socket.h"
#include "Device\Spi.h"
#include "Device\SerialPort.h"
#include "BaseBoard.h"
#include "Link\LinkClient.h"
// 物联协议板级包基类
class LinkBoard : public BaseBoard
{
public:
LinkClient* Client; // 物联客户端
LinkBoard();
// 设置数据区
void* InitData(void* data, int size);
// 写入数据区并上报
void Write(uint offset, byte data);
typedef bool(*Handler)(uint offset, uint size, bool write);
void Register(uint offset, uint size, Handler hook);
void Register(uint offset, IDataPort& dp);
void OnLongPress(InputPort* port, bool down);
void Restore();
void InitClient();
SpiConfig Net;
SerialConfig Esp;
// 打开以太网W5500
NetworkInterface* Create5500();
// 打开Esp8266作为主控或者纯AP
NetworkInterface* Create8266();
private:
void* Data;
int Size;
};
#endif

View File

@ -28,6 +28,10 @@ LinkClient::LinkClient()
Delay = 0;
MaxNotActive = 0;
_task = 0;
ReportStart = 0;
ReportLength = 0;
assert(!Current, "只能有一个物联客户端实例");
Current = this;
}
@ -123,6 +127,8 @@ void LinkClient::LoopTask()
Ping();
break;
}
CheckReport();
}
uint LinkClient::Dispatch(ITransport* port, Buffer& bs, void* param, void* param2)
@ -397,6 +403,31 @@ void LinkClient::OnPing(LinkMessage& msg)
if (serverTime > 1000) ((TTime&)Time).SetTime(serverTime);
}
void LinkClient::Reset(const String& reason)
{
Json js;
js.Add("time", DateTime::Now().TotalSeconds());
js.Add("reason", reason);
Invoke("Reset", js);
debug_printf("设备500ms后重置\r\n");
Sys.Sleep(500);
Config::Current->RemoveAll();
Sys.Reboot();
}
void LinkClient::Reboot(const String& reason)
{
Json js;
js.Add("time", DateTime::Now().TotalSeconds());
js.Add("reason", reason);
Invoke("Reboot", js);
}
void LinkClient::OnRead(LinkMessage& msg)
{
TS("LinkClient::OnRead");
@ -441,3 +472,72 @@ void LinkClient::OnWrite(LinkMessage& msg)
Reply(js["action"].AsString(), msg.Seq, 0, rs);
}
void LinkClient::Write(int start, const Buffer& bs)
{
Json js;
js.Add("start", start);
js.Add("data", bs.ToHex());
Invoke("Write", js);
}
void LinkClient::Write(int start, byte dat)
{
Write(start, Buffer(&dat, 1));
}
void LinkClient::ReportAsync(int start, uint length)
{
if (start<0 || start + (int)length > Store.Data.Length())
{
debug_printf("布置异步上报数据失败\r\n");
debug_printf("start=%d len:%d data.len:%d\r\n", start, length, Store.Data.Length());
return;
}
ReportStart = start;
ReportLength = length;
// 延迟上报,期间有其它上报任务到来将会覆盖
Sys.SetTask(_task, true, 20);
}
bool LinkClient::CheckReport()
{
TS("LinkClient::CheckReport");
auto offset = ReportStart;
int len = ReportLength;
if (offset < 0) return false;
// 检查索引,否则数组越界
auto& bs = Store.Data;
if (bs.Length() >= offset + len) Write(offset, Buffer(&bs[offset], len));
ReportStart = -1;
return true;
}
// 快速建立客户端注册默认Api
LinkClient* LinkClient::CreateFast(const Buffer& store)
{
auto tc = new LinkClient();
/*// 重启
tc->Register("Gateway/Restart", &LinkClient::InvokeRestart, tc);
// 重置
tc->Register("Gateway/Reset", &LinkClient::InvokeReset, tc);
// 设置远程地址
tc->Register("Gateway/SetRemote", &LinkClient::InvokeSetRemote, tc);
// 获取远程配置信息
tc->Register("Gateway/GetRemote", &LinkClient::InvokeGetRemote, tc);
// 获取所有Invoke命令
tc->Register("Api/All", &LinkClient::InvokeGetAllApi, tc);*/
if (store.Length()) tc->Store.Data.Set(store.GetBuffer(), store.Length());
return tc;
}

View File

@ -3,6 +3,9 @@
#include "Kernel\Sys.h"
#include "Net\ITransport.h"
#include "Net\Socket.h"
#include "Message\DataStore.h"
#include "Message\Json.h"
@ -38,6 +41,16 @@ public:
bool Invoke(const String& action, const Json& args);
bool Reply(const String& action, int seq, int code, const Json& result);
void Read(int start, int size);
void Write(int start, const Buffer& bs);
void Write(int start, byte dat);
// 异步上传并等待响应,返回实际上传字节数
int WriteAsync(int start, const Buffer& bs, int msTimeout);
// 必须满足 start > 0 才可以。
void ReportAsync(int start, uint length = 1);
// 收到功能消息时触发
//MessageHandler Received;
void* Param;
@ -48,6 +61,13 @@ public:
// 心跳,用于保持与对方的活动状态
void Ping();
// 重置并上报
void Reset(const String& reason);
void Reboot(const String& reason);
// 快速建立客户端注册默认Api
static LinkClient* CreateFast(const Buffer& store);
static LinkClient* Current;
private:
@ -62,9 +82,12 @@ private:
private:
uint _task;
int ReportStart; // 下次上报偏移,-1不动
byte ReportLength; // 下次上报数据长度
void LoopTask();
void CheckNet();
bool CheckReport();
static uint Dispatch(ITransport* port, Buffer& bs, void* param, void* param2);
};

View File

@ -38,6 +38,7 @@
<ClCompile Include="..\Board\IOK026X.cpp" />
<ClCompile Include="..\Board\IOK027X.cpp" />
<ClCompile Include="..\Board\IOK0612.cpp" />
<ClCompile Include="..\Board\LinkBoard.cpp" />
<ClCompile Include="..\Board\NH3_0317.cpp" />
<ClCompile Include="..\Board\Pandora.cpp" />
<ClCompile Include="..\Board\TokenBoard.cpp" />

View File

@ -593,5 +593,8 @@
<ClCompile Include="..\Link\LinkConfig.cpp">
<Filter>Link</Filter>
</ClCompile>
<ClCompile Include="..\Board\LinkBoard.cpp">
<Filter>Board</Filter>
</ClCompile>
</ItemGroup>
</Project>