新增微联模块,专用于串口通信的精简版Json协议

This commit is contained in:
大石头 2017-09-13 01:04:06 +08:00
parent 4b7bae26a5
commit a5a3847322
4 changed files with 285 additions and 2 deletions

View File

@ -12,7 +12,7 @@
#include "LinkMessage.h"
#include "LinkConfig.h"
// 物联客户端
// 物联客户端。以太网通信
class LinkClient
{
public:

View File

@ -29,7 +29,7 @@ Json LinkMessage::Create(int len) {
}
void LinkMessage::Show(bool newline) const {
debug_printf("Seq=%d [%d] ", Seq, Length);
debug_printf("%d [%d] ", Seq, Length);
String str((cstring)&this[1], Length);
str.Show(newline);

228
Link/TinyLink.cpp Normal file
View File

@ -0,0 +1,228 @@
#include "Kernel\TTime.h"
#include "Kernel\WaitHandle.h"
#include "Net\ITransport.h"
#include "Message\Json.h"
#include "Message\Api.h"
#include "TinyLink.h"
TinyLink::TinyLink()
{
Opened = false;
PingTime = 10;
_task = 0;
}
void TinyLink::Open()
{
if (Opened) return;
TS("TinyLink::Open");
assert(Port, "未指定Port");
Port->Open();
_task = Sys.AddTask(&TinyLink::LoopTask, this, 0, 1000, "微联定时");
Opened = true;
}
void TinyLink::Close()
{
if (!Opened) return;
Port->Close();
Sys.RemoveTask(_task);
Opened = false;
}
// 定时任务
void TinyLink::LoopTask()
{
TS("TinyLink::LoopTask");
if (!Logined)
Login();
else
Ping();
}
uint TinyLink::Dispatch(ITransport* port, Buffer& bs, void* param, void* param2)
{
TS("TinyLink::Dispatch");
byte* buf = bs.GetBuffer();
uint len = bs.Length();
auto& client = *(TinyLink*)param;
auto& msg = *(LinkMessage*)buf;
if (len - sizeof(msg) < msg.Length) {
debug_printf("TinyLink::Receive %d < %d 数据包长度不足\r\n", len - sizeof(msg), msg.Length);
return 0;
}
client.OnReceive(msg);
return 0;
}
// 接收处理
void TinyLink::OnReceive(LinkMessage& msg)
{
TS("TinyLink::OnReceive");
#if DEBUG
debug_printf("Link <= ");
msg.Show(true);
#endif // DEBUG
auto js = msg.Create();
if (!msg.Reply) {
// 调用全局动作
auto act = js["action"].AsString();
auto act2 = act;
String rs;
int code = Api.Invoke(act2.GetBuffer(), js["args"].AsString(), rs);
Reply(act, msg.Seq, code, rs);
}
}
bool TinyLink::Send(LinkMessage& msg, const String& data) {
auto& str = data;
// 长度
msg.Length = str.Length();
msg.Code = 1;
#if DEBUG
debug_printf("Link => ");
str.Show(true);
#endif
// 发送
Port->Write(Buffer(&msg, sizeof(msg)));
return Port->Write(str);
}
bool TinyLink::Invoke(const String& action, const Json& args) {
LinkMessage msg;
msg.Init();
Json js;
js.Add("action", action);
js.Add("args", args);
// 序列号
static byte _g_seq = 1;
msg.Seq = _g_seq++;
if (_g_seq == 0)_g_seq++;
return Send(msg, js.ToString());
}
bool TinyLink::Reply(const String& action, int seq, int code, const String& result) {
LinkMessage msg;
msg.Init();
msg.Reply = true;
msg.Error = code != 0;
msg.Seq = seq;
Json js;
js.Add("action", action);
js.Add("code", code);
js.Add("result", result);
return Send(msg, js.ToString());
}
// 登录
void TinyLink::Login()
{
TS("TinyLink::Login");
Json json;
json.Add("user", Buffer(Sys.ID, 16).ToHex());
ushort code = _REV16(Sys.Code);
json.Add("type", Buffer(&code, 2).ToHex());
json.Add("agent", Sys.Name);
json.Add("version", Version(Sys.Ver).ToString());
Invoke("Login", json);
}
void TinyLink::OnLogin(LinkMessage& msg)
{
TS("TinyLink::OnLogin");
if (!msg.Reply) return;
auto js = msg.Create();
auto rs = js["result"];
if (msg.Error)
{
Logined = false;
#if DEBUG
debug_printf("登录失败!");
rs.AsString().Show(true);
#endif
}
else
{
Logined = true;
debug_printf("登录成功!\r\n");
// 登录成功后加大心跳间隔
Sys.SetTaskPeriod(_task, PingTime * 1000);
}
}
// 心跳,用于保持与对方的活动状态
void TinyLink::Ping()
{
TS("TinyLink::Ping");
Json json;
auto ms = (int)Sys.Ms();
json.Add("Time", ms);
json.Add("Data", Store.Data.ToHex());
Invoke("Device/Ping", json);
}
void TinyLink::OnPing(LinkMessage& msg)
{
TS("TinyLink::OnPing");
if (!msg.Reply || msg.Error) return;
auto js = msg.Create();
int ms = js["Time"].AsInt();
int cost = (int)(Sys.Ms() - ms);
debug_printf("心跳延迟 %dms \r\n", cost);
// 同步本地时间
int serverTime = js["ServerSeconds"].AsInt();
if (serverTime > 1000) ((TTime&)Time).SetTime(serverTime);
}
// 快速建立客户端注册默认Api
TinyLink* TinyLink::Create(ITransport& port, const Buffer& store)
{
auto tk = new TinyLink();
tk->Port = &port;
if (store.Length()) tk->Store.Data.Set(store.GetBuffer(), store.Length());
return tk;
}

55
Link/TinyLink.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef __TinyLink_H__
#define __TinyLink_H__
#include "Kernel\Sys.h"
#include "Net\ITransport.h"
#include "Message\DataStore.h"
#include "Message\Json.h"
#include "LinkMessage.h"
// 微联客户端。串口、无线通信
class TinyLink
{
public:
bool Opened;
bool Logined;
ushort PingTime; // 心跳时间。秒
ITransport* Port; // 传输口
DataStore Store; // 数据存储区
TinyLink();
void Open();
void Close();
// 发送消息
bool Send(LinkMessage& msg, const String& data);
bool Invoke(const String& action, const Json& args);
bool Reply(const String& action, int seq, int code, const String& result);
// 登录
void Login();
void OnLogin(LinkMessage& msg);
// 心跳,用于保持与对方的活动状态
void Ping();
void OnPing(LinkMessage& msg);
// 快速建立客户端注册默认Api
static TinyLink* Create(ITransport& port, const Buffer& store);
private:
uint _task;
void LoopTask();
void OnReceive(LinkMessage& msg);
static uint Dispatch(ITransport* port, Buffer& bs, void* param, void* param2);
};
#endif