SmartOS/TinyNet/TinyServer.cpp

373 lines
7.1 KiB
C++

#include "Time.h"
#include "TinyServer.h"
#include "JoinMessage.h"
#include "Config.h"
#include "Security\MD5.h"
/******************************** TinyServer ********************************/
static bool OnServerReceived(Message& msg, void* param);
TinyServer::TinyServer(TinyController* control)
{
Control = control;
Config = NULL;
DeviceType = Sys.Code;
Control->Received = OnServerReceived;
Control->Param = this;
Received = NULL;
Param = NULL;
Current = NULL;
}
bool TinyServer::Send(Message& msg)
{
return Control->Send(msg);
}
bool TinyServer::Reply(Message& msg)
{
return Control->Reply(msg);
}
bool OnServerReceived(Message& msg, void* param)
{
TinyServer* server = (TinyServer*)param;
assert_ptr(server);
// 消息转发
return server->OnReceive((TinyMessage&)msg);
}
// 常用系统级消息
void TinyServer::Start()
{
assert_param2(Config, "未指定微网服务器的配置");
Control->Open();
}
// 收到本地无线网消息
bool TinyServer::OnReceive(TinyMessage& msg)
{
// 如果设备列表没有这个设备,那么加进去
byte id = msg.Src;
Device* dv = Current;
if(!dv) dv = FindDevice(id);
switch(msg.Code)
{
case 1:
OnJoin(msg);
dv = Current;
break;
case 2:
OnDisjoin(msg);
break;
case 3:
OnPing(msg);
break;
case 5:
// 系统指令不会被转发,这里修改为用户指令
msg.Code = 0x15;
case 0x15:
OnReadReply(msg, *dv);
break;
case 6:
case 0x16:
//OnWriteReply(msg, *dv);
break;
}
// 更新设备信息
if(dv) dv->LastTime = Time.Current();
// 设置当前设备
Current = dv;
// 消息转发
if(Received) return Received(msg, Param);
Current = NULL;
return true;
}
// 分发外网过来的消息。返回值表示是否有响应
bool TinyServer::Dispatch(TinyMessage& msg)
{
// 先找到设备
Device* dv = FindDevice(msg.Dest);
if(!dv) return false;
bool rs = false;
// 缓存内存操作指令
switch(msg.Code)
{
case 5:
case 0x15:
rs = OnRead(msg, *dv);
break;
case 6:
case 0x16:
rs = OnWrite(msg, *dv);
break;
}
// 非休眠设备直接发送
//if(!dv->CanSleep())
//{
Send(msg);
//}
// 休眠设备进入发送队列
//else
//{
//}
return rs;
}
// 组网
bool TinyServer::OnJoin(const TinyMessage& msg)
{
if(msg.Reply) return false;
// 如果设备列表没有这个设备,那么加进去
byte id = msg.Src;
if(!id) return false;
ulong now = Time.Current();
JoinMessage dm;
dm.ReadMessage(msg);
// 根据硬件编码找设备
Device* dv = FindDevice(dm.HardID);
if(!dv)
{
// 以网关地址为基准,进行递增分配
byte addr = Config->Address;
{
id = addr;
while(FindDevice(++id) != NULL && id < 0xFF);
debug_printf("发现节点设备 0x%02X ,为其分配 0x%02X\r\n", dm.Kind, id);
if(id == 0xFF) return false;
}
dv = new Device();
dv->Address = id;
Devices.Add(dv);
// 节点注册
dv->RegTime = now;
}
// 更新设备信息
Current = dv;
dv->Kind = dm.Kind;
dv->HardID = dm.HardID;
dv->Version = dm.Version;
if(dv->Logins++ == 0) dv->LoginTime = now;
dv->LastTime = now;
debug_printf("\r\nTinyServer::新设备第 %d 次组网 TranID=0x%08X \r\n", dv->Logins, dm.TranID);
dv->Show(true);
// 生成随机密码。当前时间的MD5
ByteArray bs((byte*)&now, 8);
dv->Pass = MD5::Hash(bs);
dv->Pass.SetLength(8); // 小心不要超长
// 响应
TinyMessage rs;
rs.Code = msg.Code;
rs.Dest = msg.Src;
rs.Sequence = msg.Sequence;
// 发现响应
dm.Reply = true;
dm.Server = Config->Address;
dm.Channel = Config->Channel;
dm.Speed = Config->Speed / 10;
dm.Address = dv->Address;
dm.Password = dv->Pass;
dm.HardID.SetLength(6); // 小心不要超长
dm.HardID = Sys.ID;
dm.WriteMessage(rs);
Reply(rs);
return true;
}
// 读取
bool TinyServer::OnDisjoin(const TinyMessage& msg)
{
return true;
}
// 心跳保持与对方的活动状态
bool TinyServer::OnPing(const TinyMessage& msg)
{
// 网关内没有相关节点信息时不鸟他
if(FindDevice(msg.Src) == NULL)return false;
//if(!msg.Reply) Reply(msg);
return true;
}
// 读取
bool TinyServer::OnRead(TinyMessage& msg, Device& dv)
{
if(msg.Reply) return false;
if(msg.Length < 2) return false;
// 起始地址为7位压缩编码整数
Stream ms(msg.Data, msg.Length);
uint offset = ms.ReadEncodeInt();
uint len = ms.ReadEncodeInt();
ByteArray& bs = dv.Store;
// 重新一个数据流,避免前面的不够
Stream ms2(4 + len);
ms2.WriteEncodeInt(offset);
int remain = bs.Length() - offset;
if(remain < 0)
{
// 出错,使用原来的数据区即可,只需要返回一个起始位置
msg.Error = true;
}
else
{
if(len > remain) len = remain;
if(len > 0) ms2.Write(bs.GetBuffer(), offset, len);
}
msg.SetData(ms2.GetBuffer(), ms2.Position());
msg.Reply = true;
return true;
}
// 读取响应,服务端趁机缓存一份。定时上报也是采用该指令。
bool TinyServer::OnReadReply(const TinyMessage& msg, Device& dv)
{
if(!msg.Reply || msg.Error) return false;
if(msg.Length < 2) return false;
// 起始地址为7位压缩编码整数
Stream ms(msg.Data, msg.Length);
uint offset = ms.ReadEncodeInt();
ByteArray& bs = dv.Store;
int remain = bs.Length() - offset;
if(remain < 0) return false;
uint len = ms.Remain();
if(len > remain) len = remain;
// 保存一份到缓冲区
if(len > 0)
{
bs.Copy(ms.Current(), len, offset);
}
return true;
}
// 写入
bool TinyServer::OnWrite(TinyMessage& msg, Device& dv)
{
if(msg.Reply) return false;
if(msg.Length < 2) return false;
// 起始地址为7位压缩编码整数
Stream ms(msg.Data, msg.Length);
uint offset = ms.ReadEncodeInt();
ByteArray& bs = dv.Store;
int remain = bs.Length() - offset;
if(remain < 0)
{
// 出错,使用原来的数据区即可,只需要返回一个起始位置
msg.Error = true;
debug_printf("读写指令错误");
ms.Write(1);
ms.Write(0);
}
else
{
uint len = ms.Remain();
if(len > remain) len = remain;
// 保存一份到缓冲区
if(len > 0)
{
bs.Copy(ms.Current(), len, offset);
// 实际写入的长度
ms.WriteEncodeInt(len);
debug_printf("读写指令转换");
}
}
msg.Length = ms.Position();
msg.Reply = true;
msg.Show();
return true;
}
Device* TinyServer::FindDevice(byte id)
{
if(id == 0) return NULL;
for(int i=0; i<Devices.Count(); i++)
{
if(id == Devices[i]->Address) return Devices[i];
}
return NULL;
}
Device* TinyServer::FindDevice(const ByteArray& hardid)
{
if(hardid.Length() == 0) return NULL;
for(int i=0; i<Devices.Count(); i++)
{
if(hardid == Devices[i]->HardID) return Devices[i];
}
return NULL;
}
bool TinyServer::DeleteDevice(byte id)
{
Device* dv = FindDevice(id);
if(dv && dv->Address == id)
{
Devices.Remove(dv);
delete dv;
return true;
}
return false;
}