You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

685 lines
23 KiB

1 year ago
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Timer = System.Timers.Timer;
namespace JiLinApp.Docking.VibrateAlarm;
public class TcpManager
{
#region Fields
private JsonSerializerSettings jSetting { get; } = new();
private AsyncTcpServer server { get; set; } = null;
private Timer stateSpanTimer { get; } = new();
private Timer heartTimer { get; } = new();
private List<ClientMessage> list { get; } = new();
#endregion Fields
1 year ago
public TcpManager()
{
jSetting.NullValueHandling = NullValueHandling.Ignore;
jSetting.DefaultValueHandling = DefaultValueHandling.Ignore;
}
#region BaseMethod
public void StartServer(TcpManagerConfig config)
{
if (IsRunning()) return;
IPAddress address = IPAddress.Any;
_ = IPAddress.TryParse(config.ServerIp, out address);
server = new AsyncTcpServer(address, config.ServerPort);
server.ClientConnected += server_ClientConnected;
server.ClientDisconnected += server_ClientDisconnected;
server.DatagramReceived += server_DatagramReceived;
server.Start();
heartTimer.Close();
heartTimer.Interval = 1000 * config.DeviceHeartKeep;
heartTimer.Elapsed += HeartTimer_Elapsed;
heartTimer.Enabled = true;
heartTimer.Start();
}
public void StopServer()
{
heartTimer.Enabled = false;
if (IsRunning())
{
server.Stop();
server = null;
}
}
public bool IsRunning()
{
return server != null && server.IsRunning;
}
public bool StartScan(ref string error)
{
if (server == null)
{
error = "服务未创建";
return false;
}
if (!server.IsRunning)
{
error = "服务未运行";
return false;
}
stateSpanTimer.Enabled = true;
return true;
}
public void StopScan()
{
stateSpanTimer.Enabled = false;
}
#endregion BaseMethod
private void StateSpanTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
string error = "";
for (int i = 0; i < list.Count; i++)
{
sendState(list[i], ref error);
}
}
private void HeartTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
string error = "";
for (int i = 0; i < list.Count; i++)
{
sendHeart(list[i], ref error);
}
}
private ClientMessage GetClientMessage(TcpClient client)
{
string clientIP = client.Client.RemoteEndPoint.ToString().Split(':')[0];
for (int i = 0; i < list.Count; i++)
{
if (list[i].IP == clientIP)
{
return list[i];
}
}
return null;
}
private ClientMessage GetClientMessageIP(string clientIP)
{
for (int i = 0; i < list.Count; i++)
{
if (list[i].IP == clientIP)
{
return list[i];
}
}
return null;
}
private ClientMessage GetClientMessageDeviceID(int deviceId)
{
for (int i = 0; i < list.Count; i++)
{
if (list[i].host != null && list[i].host.id == deviceId)
{
return list[i];
}
}
return null;
}
public delegate void TCPSectionAlarmOnEvent(TcpAlarmHostMessage msg);
public event TCPSectionAlarmOnEvent OnTcpSectionAlarmOn;
public delegate void TCPSectionStateChangeEvent(SectionState state);
public event TCPSectionStateChangeEvent OnTcpSectionStateChange;
public delegate void TCPDeviceMessageEvent(TcpAlarmHostTable host, string msg);
public event TCPDeviceMessageEvent OnTcpDeviceMessage;
public delegate void TCPSectionMessageEvent(TcpAlarmHostTable host, TcpSectionTable section, string msg);
public event TCPSectionMessageEvent OnTcpSectionMessage;
private void server_DatagramReceived(object sender, TcpDatagramReceivedEventArgs<byte[]> e)
{
string clientIP = e.TcpClient.TcpClient.Client.RemoteEndPoint.ToString().Split(':')[0];
ClientMessage client = GetClientMessage(e.TcpClient.TcpClient);
if (client != null)
{
AnalysisClientMessage(client, e.Datagram);
}
}
public void TestAlarm(string devideId, string channel)
{
ClientMessage message = new ClientMessage();
message.client = new TcpClient("127.0.0.1", 5080);
list.Add(message);
byte[] bytes1 = BitConverter.GetBytes(int.Parse(devideId));
byte[] bytes2 = BitConverter.GetBytes(int.Parse(channel));
byte[] bytes = new byte[24]{
0xAA,0xAA,bytes1[0],bytes1[1],
127,0,0,1,
0x00,0x00,127,0,
0,1,0x00,0x00,
1,0x14,0x04,bytes2[0],
bytes2[1],0x02,0x00,0x00
};
AnalysisClientMessage(message, bytes);
}
private string ToHexString(byte[] bytes)
{
string hexString = string.Empty;
if (bytes != null)
{
StringBuilder strB = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
strB.Append(bytes[i].ToString("X2") + " ");
}
hexString = strB.ToString();
}
return hexString;
}
private void AnalysisClientMessage(ClientMessage client, byte[] bytes)
{
client.list.AddRange(bytes);
List<byte[]> msglist = client.getMessageList();
if (msglist != null && msglist.Count > 0)
{
for (int i = 0; i < msglist.Count; i++)
{
Console.WriteLine(client.IP + " 收到数据:" + ToHexString(msglist[i]));
DataMessage mm = new DataMessage();
mm.decode(msglist[i]);
switch (mm.functionNum)
{
case 0x00:
Console.WriteLine(client.IP + " 登录");
if (client.host == null || client.host.id != mm.deviceID)
{
//string error = "";
//JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPAlarmHost", "id=" + mm.deviceID, ref error);
JArray arr = new();
if (arr != null && arr.Count > 0)
{
client.host = JsonConvert.DeserializeObject<TcpAlarmHostTable>(arr[0].ToString(), jSetting);
client.host.ip = mm.sendIP;
client.host.port = mm.sendPort.ToString();
}
}
if (OnTcpDeviceMessage != null)
{
if (client.host != null)
{
OnTcpDeviceMessage(client.host, "报警主机登录");
}
else
{
OnTcpDeviceMessage(new TcpAlarmHostTable() { id = mm.deviceID, ip = mm.sendIP, port = mm.sendPort.ToString(), name = "未知设备" }, "报警主机登录");
}
}
break;
case 0x01:
Console.WriteLine(client.IP + " 心跳");
break;
case 0x12:
Console.WriteLine(client.IP + "传感器地址设置响应");
SetDataRequest(mm, 0x02);
break;
case 0x13:
Console.WriteLine(client.IP + "传感器模式设置响应");
SetDataRequest(mm, 0x03);
break;
case 0x14:
Console.WriteLine(client.IP + "传感器状态响应");
int channel = mm.data[0] + mm.data[1] * 256;
int state = mm.data[2] + mm.data[3] * 256;
int online = state % 2;
int alarm = state / 2 % 2;
TcpAlarmHostTable host = new() { id = mm.deviceID, ip = mm.sendIP, port = mm.sendPort.ToString(), name = "未知设备" };
ProcessOnlineEvent(client, host, mm, channel, online);
ProcessAlarmEvent(client, host, mm, channel, alarm);
UpdateOnLineAlarm(client, host, channel, online, alarm);
SetDataRequest(mm, 0x04);
break;
case 0x15:
Console.WriteLine(client.IP + "传感器复位响应");
SetDataRequest(mm, 0x05);
break;
}
}
}
}
private void ProcessOnlineEvent(ClientMessage client, TcpAlarmHostTable host, DataMessage mm, int channel, int online)
{
if (client.sectioTable.ContainsKey(channel))
{
SectionState oldState = client.sectioTable[channel] as SectionState;
if (oldState.online == online) return;
}
TcpAlarmHostTable host1 = client.host == null ? host : client.host;
string error = "";
TcpSectionTable section = new TcpSectionTable() { deviceID = host.id, name = "未知传感器", channel = channel.ToString() };
//JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPSection", "deviceID=" + mm.deviceID + "/channel='" + channel + "'", ref error);
JArray arr = new();
if (arr != null && arr.Count > 0) section = JsonConvert.DeserializeObject<TcpSectionTable>(arr[0].ToString(), jSetting);
if (OnTcpSectionMessage != null)
{
OnTcpSectionMessage(host1, section, online == 0 ? "传感器上线" : "传感器离线");
}
}
private void ProcessAlarmEvent(ClientMessage client, TcpAlarmHostTable host, DataMessage mm, int channel, int alarm)
{
if (client.sectioTable.ContainsKey(channel))
{
SectionState oldState = client.sectioTable[channel] as SectionState;
if (oldState.alarm == alarm) return;
}
TcpAlarmHostTable host1 = client.host == null ? host : client.host;
if (alarm == 1)
{
ProcessAlarm(host1.id, channel, alarm);
}
}
private void UpdateOnLineAlarm(ClientMessage client, TcpAlarmHostTable host, int channel, int online, int alarm)
{
if (client.sectioTable.ContainsKey(channel))
{
SectionState oldState = client.sectioTable[channel] as SectionState;
oldState.online = online;
oldState.alarm = alarm;
if (OnTcpSectionStateChange != null)
{
OnTcpSectionStateChange(oldState);
}
}
else
{
TcpAlarmHostTable host1 = client.host == null ? host : client.host;
SectionState state = new SectionState(host1.id, channel, online, alarm);
client.sectioTable[channel] = state;
if (OnTcpSectionStateChange != null)
{
OnTcpSectionStateChange(state);
}
}
}
private void ProcessAlarm(int deviceId, int channel, int alarmId)
{
TcpAlarmHostMessage alarm = new()
{
AlarmId = Convert.ToString(alarmId),
AlarmTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
DeviceID = deviceId,
ChannelNum = channel.ToString()
};
ProcessAlarmDB(alarm);
}
//处理报警事件
private void ProcessAlarmDB(TcpAlarmHostMessage msg)
{
if (OnTcpSectionAlarmOn != null) OnTcpSectionAlarmOn(msg);
}
public void SetDataRequest(DataMessage msg, byte functionNum)
{
lock (this)
{
for (int i = 0; i < reqlist.Count; i++)
{
if (reqlist[i].request.functionNum == functionNum && reqlist[i].request.frameNum == msg.frameNum)
{
reqlist[i].responce = msg;
}
}
}
}
public bool SendMessage(string IP, byte[] bytes, ref string error)
{
if (server == null)
{
error = "服务未创建";
return false;
}
if (!server.IsRunning)
{
error = "服务未运行";
return false;
}
ClientMessage client = GetClientMessageIP(IP);
if (client != null)
{
server.Send(client.client, bytes);
return true;
}
else
{
error = "主机未连接";
return false;
}
}
private List<DataRequest> reqlist = new List<DataRequest>();
private byte frameNumber = 0;
public bool sendRequest(ref DataRequest request, ref string error)
{
if (request.request == null)
{
error = "请求信息未填写";
return false;
}
//int waitTime = int.Parse(DBCenter.center.GetConfig("WW_TCP_DeviceTimeOut")) * 10;
int waitTime = 100;
request.request.frameNum = frameNumber;
frameNumber++;
bool send = SendMessage(request.request.receiveIP, request.request.encode(), ref error);
if (!send) return false;
reqlist.Add(request);
for (int i = 0; i < waitTime; i++)
{
if (request.responce != null)
{
reqlist.Remove(request);
return true;
}
System.Threading.Thread.Sleep(100);
}
return false;
}
public bool sendNoRequest(DataMessage msg, ref string error)
{
msg.frameNum = frameNumber;
frameNumber++;
return SendMessage(msg.receiveIP, msg.encode(), ref error);
}
public bool sendHeart(ClientMessage client, ref string error)
{
if (client.host == null)
{
error = "报警主机信息缺失";
return false;
}
DataMessage msg = getSendMessageHead(client.host.id, client, 0x01, 1);
msg.data = new byte[] { 0xFF };
return sendNoRequest(msg, ref error);
}
public bool SetSectionAddress(int deviceId, string channel_str, int address, ref string error)
{
ClientMessage client = GetClientMessageDeviceID(deviceId);
if (client == null)
{
error = "此主机号不在线";
return false;
}
DataMessage msg = getSendMessageHead(deviceId, client, 0x02, 4);
int channel = int.Parse(channel_str);
msg.data = new byte[] { (byte)(channel % 256), (byte)(channel / 256), (byte)(address % 256), (byte)(address / 256) };
DataRequest request = new DataRequest();
request.request = msg;
bool result = sendRequest(ref request, ref error);
if (result)
{
JObject conlist = new JObject();
conlist.Add("deviceID", deviceId);
conlist.Add("channel", channel_str);
JObject valuelist = new JObject();
valuelist.Add("channel", address.ToString());
//DBCenter.center.UpdateResult("table_TCPSection", valuelist, conlist, ref error);
}
return result;
}
public bool SetSectionMode(int deviceId, string channel_str, byte mode, byte sensitivity, ref string error)
{
ClientMessage client = GetClientMessageDeviceID(deviceId);
if (client == null)
{
error = "此主机号不在线";
return false;
}
DataMessage msg = getSendMessageHead(deviceId, client, 0x03, 3);
int channel = int.Parse(channel_str);
msg.data = new byte[] { (byte)(channel % 256), (byte)(channel / 256), (byte)(mode + sensitivity * 8) };
DataRequest request = new DataRequest();
request.request = msg;
bool result = sendRequest(ref request, ref error);
if (result)
{
JObject conlist = new JObject();
conlist.Add("deviceID", deviceId);
conlist.Add("channel", channel_str);
JObject valuelist = new JObject();
valuelist.Add("mode", mode.ToString());
valuelist.Add("sensitivity", sensitivity.ToString());
//DBCenter.center.UpdateResult("table_TCPSection", valuelist, conlist, ref error);
}
return result;
}
public bool SetSectionReset(int deviceId, string channel_str, ref string error)
{
ClientMessage client = GetClientMessageDeviceID(deviceId);
if (client == null)
{
error = "此主机号不在线";
return false;
}
DataMessage msg = getSendMessageHead(deviceId, client, 0x05, 2);
int channel = int.Parse(channel_str);
msg.data = new byte[] { (byte)(channel % 256), (byte)(channel / 256) };
DataRequest request = new DataRequest();
request.request = msg;
return sendRequest(ref request, ref error);
}
public SectionState SetSectionCheck(int deviceId, string channel_str, ref string error)
{
ClientMessage client = GetClientMessageDeviceID(deviceId);
if (client == null)
{
error = "此主机号不在线";
return null;
}
DataMessage msg = getSendMessageHead(deviceId, client, 0x04, 2);
int channel = int.Parse(channel_str);
msg.data = new byte[] { (byte)(channel % 256), (byte)(channel / 256) };
DataRequest request = new DataRequest();
request.request = msg;
bool result = sendRequest(ref request, ref error);
if (result)
{
int channel2 = request.responce.data[0] + request.responce.data[1] * 256;
int state2 = request.responce.data[2] + request.responce.data[3] * 256;
return new SectionState(deviceId, channel2, state2);
}
else
{
return null;
}
}
public List<SectionState> SetDeviceCheck(int deviceId, ref string error)
{
List<SectionState> list = new List<SectionState>();
//JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPSection", "deviceID=" + deviceId, ref error);
JArray arr = new();
if (arr != null && arr.Count > 0)
{
for (int i = 0; i < arr.Count; i++)
{
string channel = arr[i]["channel"].ToString();
SectionState state = SetSectionCheck(deviceId, channel, ref error);
if (state == null)
{
state = new SectionState(deviceId, int.Parse(channel), -1, -1);
}
list.Add(state);
}
}
else
{
error = "数据库中没有防区信息";
}
return list;
}
public List<SectionState> SetAllCheck(ref string error)
{
List<SectionState> list = new List<SectionState>();
//JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPAlarmHost", "", ref error);
JArray arr = new();
if (arr != null && arr.Count > 0)
{
for (int i = 0; i < arr.Count; i++)
{
int deviceId = int.Parse(arr[i]["id"].ToString());
list.AddRange(SetDeviceCheck(deviceId, ref error));
}
}
return list;
}
private DataMessage getSendMessageHead(int deviceId, ClientMessage client, byte fun_num, byte datalen)
{
//DataMessage msg = new DataMessage();
//msg.deviceID = deviceId;
//msg.sendIP = DBCenter.center.GetConfig("WW_TCP_ServeIP");
//msg.sendPort = int.Parse(DBCenter.center.GetConfig("WW_TCP_ServePort"));
//msg.receiveIP = client.IP;
//msg.receivePort = int.Parse(client.Port);
//msg.functionNum = fun_num;
//msg.dataLen = datalen;
//return msg;
return null;
}
public void sendState(ClientMessage client, ref string error)
{
//if (client.host == null)
//{
// error = "报警主机信息缺失";
// return;
//}
//JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPSection", "deviceID='" + client.host.id + "'", ref error);
//if (arr != null && arr.Count > 0)
//{
// for (int i = 0; i < arr.Count; i++)
// {
// DataMessage msg = getSendMessageHead(client.host.id, client, 0x04, 2);
// int channel = int.Parse(arr[i]["channel"].ToString());
// msg.data = new byte[] { (byte)(channel % 256), (byte)(channel / 256) };
// sendNoRequest(msg, ref error);
// }
//}
}
private void server_ClientDisconnected(object sender, TcpClientDisconnectedEventArgs e)
{
string clientIP = e.TcpClient.Client.RemoteEndPoint.ToString().Split(':')[0];
Console.WriteLine(clientIP + "下线");
ClientMessage client = GetClientMessage(e.TcpClient);
if (client != null)
{
list.Remove(client);
if (OnTcpDeviceMessage != null)
{
if (client.host != null)
{
OnTcpDeviceMessage(client.host, "报警主机掉线");
}
else
{
OnTcpDeviceMessage(new TcpAlarmHostTable() { id = -1, ip = clientIP, port = client.Port, name = "未知设备" }, "报警主机掉线");
}
}
}
}
private void server_ClientConnected(object sender, TcpClientConnectedEventArgs e)
{
string error = "";
string clientIP = e.TcpClient.Client.RemoteEndPoint.ToString().Split(':')[0];
string port = e.TcpClient.Client.RemoteEndPoint.ToString().Split(':')[1];
Console.WriteLine(clientIP + "上线");
ClientMessage client = GetClientMessage(e.TcpClient);
if (client == null)
{
ClientMessage msg = new ClientMessage();
msg.client = e.TcpClient;
//JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPAlarmHost", "IP='" + clientIP + "'", ref error);
JArray arr = new();
if (arr != null && arr.Count > 0)
{
msg.host = JsonConvert.DeserializeObject<TcpAlarmHostTable>(arr[0].ToString(), jSetting);
}
list.Add(msg);
if (OnTcpDeviceMessage != null)
{
if (msg.host != null)
{
OnTcpDeviceMessage(msg.host, "报警主机上线");
}
else
{
OnTcpDeviceMessage(new TcpAlarmHostTable() { id = -1, ip = clientIP, port = client.Port, name = "未知设备" }, "报警主机上线");
}
}
}
}
public List<SectionState> getOnlineState(int deviceId)
{
ClientMessage msg = GetClientMessageDeviceID(deviceId);
if (msg != null)
{
return msg.sectioTable.Values as List<SectionState>;
}
else
{
return new List<SectionState>();
}
}
}