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 list { get; } = new(); #endregion Fields 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 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 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(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(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 reqlist = new List(); 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 SetDeviceCheck(int deviceId, ref string error) { List list = new List(); //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 SetAllCheck(ref string error) { List list = new List(); //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(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 getOnlineState(int deviceId) { ClientMessage msg = GetClientMessageDeviceID(deviceId); if (msg != null) { return msg.sectioTable.Values as List; } else { return new List(); } } }