using EC.Util.Common; using System.Collections.Concurrent; using System.Net; using System.Timers; using Timer = System.Timers.Timer; namespace JiLinApp.Docking.VibrateAlarm; public class TcpManager { #region Fields private AsyncTcpServer Server { get; set; } private TcpManagerConfig Config { get; set; } private ConcurrentDictionary DeviceDict { get; } = new(); private Timer HeartTimer { get; } = new(); private Timer StateSpanTimer { get; } = new(); #region Event public delegate void VibrateTcpDeviceStateEvent(ClientMessage device); public delegate void VibrateTcpSensorStateEvent(SensorState sensor); public delegate void VibrateTcpAlarmEvent(TcpAlarmHostMessage msg); public event VibrateTcpDeviceStateEvent? OnVibrateTcpDeviceState; public event VibrateTcpSensorStateEvent? OnVibrateTcpSensorState; public event VibrateTcpAlarmEvent? OnVibrateTcpAlarm; #endregion Event #endregion Fields public TcpManager() { } #region Server public void Start(TcpManagerConfig config) { if (IsRunning()) return; Server = new(IPAddress.Any, 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.Start(); Config = config; } public void Stop() { if (!IsRunning()) return; try { Server.Stop(); } finally { Server.ClientConnected -= Server_ClientConnected; Server.ClientDisconnected -= Server_ClientDisconnected; Server.DatagramReceived -= Server_DatagramReceived; Server = null; DeviceDict.Clear(); HeartTimer.Stop(); HeartTimer.Elapsed -= HeartTimer_Elapsed; } } public bool IsRunning() { return Server != null && Server.IsRunning(); } #endregion Server #region Events private void HeartTimer_Elapsed(object? sender, ElapsedEventArgs e) { foreach (var clientMsg in DeviceDict.Values) { SendHostHeart_01(clientMsg); } } private void Server_ClientConnected(object? sender, TcpClientConnectedEventArgs e) { string clientKey = e.TcpClient.Client.RemoteEndPoint?.ToString() ?? ""; if (clientKey == "") return; string clientIp = clientKey.Split(':')[0]; string clientPort = clientKey.Split(':')[1]; Console.WriteLine("上线:{0}", clientIp); if (!TryGetDevice(clientIp, out ClientMessage clientMsg)) { clientMsg = new() { Client = e.TcpClient, Host = new() { Id = -1, Ip = clientIp, Port = clientPort } }; AddDeivce(clientIp, clientMsg); } else { ProcessDeviceStateEvent(ref clientMsg, 1); } } private void Server_ClientDisconnected(object? sender, TcpClientDisconnectedEventArgs e) { string clientKey = e.TcpClient.Client.RemoteEndPoint?.ToString() ?? ""; if (clientKey == "") return; string clientIp = clientKey.Split(':')[0]; string clientPort = clientKey.Split(':')[1]; Console.WriteLine("下线:{0}", clientIp); if (TryGetDevice(clientIp, out ClientMessage clientMsg)) { ProcessDeviceStateEvent(ref clientMsg, 0); } } private void Server_DatagramReceived(object? sender, TcpDatagramReceivedEventArgs e) { string clientKey = e.TcpClient.TcpClient.Client.RemoteEndPoint?.ToString() ?? ""; if (clientKey == "") return; string clientIp = clientKey.Split(':')[0]; if (TryGetDevice(clientIp, out ClientMessage clientMsg)) { clientMsg.AddData(e.Datagram); AnalysisClientMessage(ref clientMsg); } } #endregion Events #region Analysisbo private void AnalysisClientMessage(ref ClientMessage clientMsg) { //AA AA 01 C0 A8 01 05 28 23 C0 A8 01 64 88 13 7C 04 02 04 00 2B //AA AA 01 C0 A8 01 64 88 13 C0 A8 01 05 28 23 24 14 04 0A 00 02 00 03 List msglist = clientMsg.GetMessageList(); if (msglist == null || msglist.Count == 0) return; for (int i = 0; i < msglist.Count; i++) { byte[] msg = msglist[i]; bool vaild = msg.Length >= 19 && msg[0] == 0xAA && msg[1] == 0xAA; if (!vaild) continue; DataMessage mm = new(); mm.Decode(msglist[i]); Console.WriteLine("Receive from {0}:{1} => {2}, {3}", clientMsg.Ip, clientMsg.Port, DataMessage.ToHexString(msglist[i]), JsonUtil.ToJson(mm)); switch (mm.FunctionNum) { case 0x00: Console.WriteLine("主机登录:{0}", clientMsg.Ip); if (clientMsg.Host == null || clientMsg.Host.Id != mm.DeviceId) { clientMsg.Host = new() { Id = mm.DeviceId, Ip = mm.SendIp, Port = mm.SendPort.ToString() }; UpdateDevice(clientMsg.Ip, clientMsg.Host); ProcessDeviceStateEvent(ref clientMsg, 1); } ResponseHostLogin_10(clientMsg, mm); ClientMessage clientMsg2 = clientMsg; if (clientMsg2.SensorsEmpty && clientMsg2.SensorsLock.TryEnterWriteLock(1000)) { Task.Run(() => { while (clientMsg2.SensorsEmpty) { RequestSensorList_07(clientMsg2); Thread.Sleep(1000); } clientMsg2.SensorsLock.ExitWriteLock(); }); } break; case 0x01: Console.WriteLine("心跳:{0}", clientMsg.Ip); ProcessDeviceStateEvent(ref clientMsg, 1); break; case 0x12: Console.WriteLine("传感器地址设置响应:{0}", clientMsg.Ip); SetDataRequest(mm, 0x02); break; case 0x13: Console.WriteLine("传感器模式设置响应:{0}", clientMsg.Ip); SetDataRequest(mm, 0x03); break; case 0x14: Console.WriteLine("传感器状态响应:{0}", clientMsg.Ip); int sensorAddr = 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; if (clientMsg.Host == null || clientMsg.Host.Id != mm.DeviceId) { clientMsg.Host = new() { Id = mm.DeviceId, Ip = mm.SendIp, Port = mm.SendPort.ToString() }; UpdateDevice(clientMsg.Ip, clientMsg.Host); } ProcessSensorStateEvent(ref clientMsg, mm, sensorAddr, online, alarm); SetDataRequest(mm, 0x04); break; case 0x15: Console.WriteLine("传感器复位响应:{0}", clientMsg.Ip); SetDataRequest(mm, 0x05); break; case 0x17: Console.WriteLine("返回传感器列表:{0}", clientMsg.Ip); if (clientMsg.Host == null || clientMsg.Host.Id != mm.DeviceId) { clientMsg.Host = new() { Id = mm.DeviceId, Ip = mm.SendIp, Port = mm.SendPort.ToString() }; UpdateDevice(clientMsg.Ip, clientMsg.Host); } if (clientMsg.SensorsEmpty) { for (int j = 2; j < mm.Data.Length; j++) { sensorAddr = Convert.ToByte((mm.Data[j] + mm.Data[++j] * 256)); SensorState sensor = new(mm.DeviceId, sensorAddr, 0, 0); clientMsg.SensorDict[sensorAddr] = sensor; } RequestSensorState_04(clientMsg); } SetDataRequest(mm, 0x07); break; } } } private void ProcessDeviceStateEvent(ref ClientMessage device, int online) { if (device.OnlineState != online) { device.OnlineState = online; ReportDeviceState(device); } } private void ProcessSensorStateEvent(ref ClientMessage client, DataMessage mm, int sensorAddr, int offline, int alarm) { if (!client.SensorDict.TryGetValue(sensorAddr, out SensorState? sensor)) { sensor = new(mm.DeviceId, sensorAddr, offline, alarm); client.SensorDict[sensorAddr] = sensor; ReportSensorState(sensor); } else if (sensor.OfflineState != offline || sensor.AlarmState != alarm) { sensor.OfflineState = offline; sensor.AlarmState = alarm; ReportSensorState(sensor); } if (alarm == 1) { ReportAlarm(sensor.DeviceId, sensorAddr); //RequestSensorReset_05(clientMsg, sensorAddr); } } private void ReportDeviceState(ClientMessage device) { OnVibrateTcpDeviceState?.Invoke(device); } private void ReportSensorState(SensorState sensor) { OnVibrateTcpSensorState?.Invoke(sensor); } private void ReportAlarm(int deviceId, int sensorAddr) { TcpAlarmHostMessage alarmMsg = new() { AlarmTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), CID = "1151", DeviceID = deviceId, SensorAddr = sensorAddr.ToString() }; OnVibrateTcpAlarm?.Invoke(alarmMsg); } #endregion Analysisbo #region Send public bool SendMessage(string ip, byte[] bytes) { if (Server == null || !Server.IsRunning()) return false; if (!TryGetDevice(ip, out ClientMessage clientMsg)) return false; string cmd = DataMessage.ToHexString(bytes); DataMessage mm = new(); mm.Decode(bytes); Console.WriteLine("Send to {0}:{1} => {2}, {3}", ip, clientMsg.Port, cmd, JsonUtil.ToJson(mm)); Server.SendAsync(clientMsg.Client, bytes); return true; } public bool SendRequest(ref DataRequest request) { if (request.Request == null) return false; request.Request.FrameNum = FrameNumber; FrameNumber++; bool send = SendMessage(request.Request.ReceiveIp, request.Request.Encode()); return send; } public bool SendNoRequest(DataMessage msg) { msg.FrameNum = FrameNumber; FrameNumber++; bool send = SendMessage(msg.ReceiveIp, msg.Encode()); return send; } public bool SendResponse(DataMessage msg) { bool send = SendMessage(msg.ReceiveIp, msg.Encode()); return send; } public bool SendHostHeart_01(ClientMessage client) { if (client.Host == null) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x01, 1); msg.Data = new byte[] { 0xFF }; return SendNoRequest(msg); } public bool RequestSensorChange_02(ClientMessage client) { if (client.Host == null || client.Host.Id < 0) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x02, 4); int channel = 10; msg.Data = new byte[] { (byte)(channel % 256), (byte)(channel / 256), (100 % 256), (100 / 256) }; DataRequest request = new() { Request = msg }; SendRequest(ref request); return true; } public bool RequestSensorState_04(ClientMessage client) { if (client.Host == null || client.Host.Id < 0) return false; if (client.SensorsEmpty) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x04, 2); foreach (var item in client.SensorDict.Values) { int sensorAddr = item.Addr; msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) }; DataRequest request = new() { Request = msg }; SendRequest(ref request); } return true; } public bool RequestSensorReset_05(ClientMessage client, int sensorAddr) { if (client.Host == null || client.Host.Id < 0) return false; if (client.SensorsEmpty) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x05, 2); msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) }; DataRequest request = new() { Request = msg }; SendRequest(ref request); return true; } public bool RequestSensorList_07(ClientMessage client) { if (client.Host == null || client.Host.Id < 0) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x07, 0); DataRequest request = new() { Request = msg }; return SendRequest(ref request); } public bool ResponseHostLogin_10(ClientMessage client, DataMessage mm) { if (client.Host == null) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x10, 0); msg.FrameNum = mm.FrameNum; return SendResponse(msg); } #endregion Send #region ClientMessage public bool ContainsDevice(string clientIp) { return DeviceDict.ContainsKey(clientIp); } public ClientMessage GetDevice(string clientIp) { return DeviceDict[clientIp]; } public bool TryGetDevice(string clientIp, out ClientMessage clientMsg) { return DeviceDict.TryGetValue(clientIp, out clientMsg); } public bool TryGetDevice(int deviceId, out ClientMessage clientMsg) { foreach (var item in DeviceDict.Values) { if (item.Host.Id == deviceId) { clientMsg = item; return true; } } clientMsg = null; return false; } private bool AddDeivce(string clientIp, ClientMessage clientMsg) { if (ContainsDevice(clientIp)) return false; DeviceDict[clientIp] = clientMsg; return true; } private void SetDevice(string clientIp, ClientMessage clientMsg) { DeviceDict[clientIp] = clientMsg; } private bool RemoveDevice(string clientIp) { return DeviceDict.Remove(clientIp, out _); } private bool UpdateDevice(string clientIp, TcpAlarmHost host) { if (!DeviceDict.ContainsKey(clientIp)) return false; DeviceDict[clientIp].Host = host; return true; } public List GetDeviceList() { return DeviceDict.Values.ToList(); } #endregion ClientMessage #region Set private List Reqlist { get; } = new(); private byte FrameNumber { get; set; } = 0; private DataMessage GetSendMessageHead(int deviceId, ClientMessage client, byte fun_num, byte datalen) { DataMessage msg = new() { DeviceId = deviceId, SendIp = client.Client.Client.LocalEndPoint.ToString().Split(':')[0], SendPort = Server.Port, ReceiveIp = client.Ip, ReceivePort = int.Parse(client.Port), FunctionNum = fun_num, DataLen = datalen }; return 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; // } //} } } #endregion Set }