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(); #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) { if (!clientMsg.IsOnline) continue; SendHostHeart_01(clientMsg); } } private void Server_ClientConnected(object? sender, TcpClientConnectedEventArgs e) { string clientAddr = e.TcpClient.ClientAddr(); if (clientAddr == ":") return; string clientIp = clientAddr.Split(':')[0]; string clientPort = clientAddr.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 clientAddr = e.TcpClient.ClientAddr(); if (clientAddr == ":") return; string clientIp = clientAddr.Split(':')[0]; string clientPort = clientAddr.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 clientAddr = e.ClientState.Client.ClientAddr(); if (clientAddr == ":") return; string clientIp = clientAddr.Split(':')[0]; string clientPort = clientAddr.Split(':')[1]; if (TryGetDevice(clientIp, out ClientMessage clientMsg)) { if (clientMsg.Client == null || !clientMsg.Client.Connected) clientMsg.Client = e.ClientState.Client; clientMsg.Host ??= new() { Id = -1, Ip = clientIp, Port = clientPort }; clientMsg.AddData(e.Datagram); ProcessDeviceStateEvent(ref clientMsg, 1); AnalysisClientMessage(ref clientMsg); } } #endregion Events #region Analysis private int SendCmdInterval { get; } = 6000; private void AnalysisClientMessage(ref ClientMessage clientMsg) { List msgList = clientMsg.GetMessageList(); ClientMessage taskClientMsg = clientMsg; foreach (byte[] msg in msgList) { bool vaild = msg.Length >= 19 && msg[0] == 0xAA && msg[1] == 0xAA; Console.WriteLine("Recv from {0}:{1} => {2}, vaild:{3}", clientMsg.ClientIp, clientMsg.ClientPort, DataMessage.ToHexString(msg), vaild); if (!vaild) continue; DataMessage mm = new(); mm.Decode(msg); if (clientMsg.Host.Id != mm.DeviceId) clientMsg.Host.Id = mm.DeviceId; switch (mm.FunctionNum) { case 0x00: Console.WriteLine("主机登录:{0}", clientMsg.ClientAddr); ResponseHostLogin_10(clientMsg, mm); if (clientMsg.Init_0_21) break; if (!Monitor.TryEnter(clientMsg.Init_0_21, 500)) break; Task.Run(() => { while (!taskClientMsg.Init_0_21) { Thread.Sleep(SendCmdInterval); RequestSensorsTurnOn_21(taskClientMsg); } Monitor.Exit(taskClientMsg.Init_0_21); }); break; case 0x01: Console.WriteLine("主机心跳:{0}", clientMsg.ClientAddr); break; case 0x12: Console.WriteLine("传感器地址设置响应:{0}", clientMsg.ClientAddr); SetDataResponse(mm, 0x02); break; case 0x13: Console.WriteLine("传感器模式设置响应:{0}", clientMsg.ClientAddr); SetDataResponse(mm, 0x03); break; case 0x14: Console.WriteLine("传感器轮询状态响应:{0}", clientMsg.ClientAddr); int sensorAddr = mm.Data[0] + mm.Data[1] * 256; int state = mm.Data[2] + mm.Data[3] * 256; ProcessSensorStateEvent(ref clientMsg, mm, sensorAddr, state); SetDataResponse(mm, 0x04); break; case 0x15: Console.WriteLine("传感器复位响应:{0}", clientMsg.ClientAddr); SetDataResponse(mm, 0x05); break; case 0x17: Console.WriteLine("主机返回传感器列表:{0}", clientMsg.ClientAddr); clientMsg.Init_2_17 = true; for (int j = 0; j < mm.Data.Length; j++) { sensorAddr = Convert.ToByte((mm.Data[j] + mm.Data[++j] * 256)); if (clientMsg.SensorDict.ContainsKey(sensorAddr)) continue; SensorState sensor = new(mm.DeviceId, sensorAddr, 0, 0); clientMsg.SensorDict[sensorAddr] = sensor; } RequestSensorsState_04(clientMsg); SetDataResponse(mm, 0x07); break; case 0x18: Console.WriteLine("传感器主动状态响应:{0}", clientMsg.ClientAddr); sensorAddr = mm.Data[0] + mm.Data[1] * 256; state = mm.Data[2] + mm.Data[3] * 256; ProcessSensorStateEvent(ref clientMsg, mm, sensorAddr, state); ResponseHostUploadState_08(clientMsg, mm); break; case 0x19: Console.WriteLine("传感器关闭响应:{0}", clientMsg.ClientAddr); SetDataResponse(mm, 0x09); break; case 0x30: Console.WriteLine("传感器启动响应:{0}", clientMsg.ClientAddr); SetDataResponse(mm, 0x20); break; case 0x31: Console.WriteLine("传感器全部启动响应:{0}", clientMsg.ClientAddr); clientMsg.Init_0_21 = true; if (clientMsg.Init_1_24) break; if (!Monitor.TryEnter(clientMsg.Init_1_24, 500)) break; Task.Run(() => { while (!taskClientMsg.Init_1_24) { Thread.Sleep(SendCmdInterval); RequestHostAutoUploadState_24(taskClientMsg); } Monitor.Exit(taskClientMsg.Init_1_24); }); SetDataResponse(mm, 0x21); break; case 0x34: Console.WriteLine("主机启动自动上传响应:{0}", clientMsg.ClientAddr); clientMsg.Init_1_24 = true; if (clientMsg.Init_2_17) break; if (!Monitor.TryEnter(clientMsg.Init_2_17, 500)) break; Task.Run(() => { while (!taskClientMsg.Init_2_17) { Thread.Sleep(SendCmdInterval); RequestSensorList_07(taskClientMsg); } Monitor.Exit(taskClientMsg.Init_2_17); }); SetDataResponse(mm, 0x24); break; case 0x35: Console.WriteLine("主机关闭自动上传响应:{0}", clientMsg.ClientAddr); SetDataResponse(mm, 0x25); 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 state) { int offline = state % 2; int alarm = state / 2 % 2; 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(client, 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 Analysis #region Send /// /// 0x10:主机响应0x00登录 /// /// /// /// public bool ResponseHostLogin_10(ClientMessage client, DataMessage mm) { if (!client.IsOnline) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x10, 0); return SendResponse(msg, mm.FrameNum); } /// /// 0x01:心跳 /// /// /// public bool SendHostHeart_01(ClientMessage client) { if (!client.IsOnline) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x01, 1); msg.Data = new byte[] { 0xFF }; return SendNoRequest(msg); } /// /// 0x02:设置传感器地址 /// /// /// /// public bool RequestSensorChange_02(ClientMessage client, int newSensorAddr) { if (!client.IsOnline) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x02, 4); msg.Data = new byte[] { (byte)(newSensorAddr % 256), (byte)(newSensorAddr / 256), (100 % 256), (100 / 256) }; DataRequest request = new() { Request = msg }; return SendRequestTry(ref request); } /// /// 0x04:请求传感器状态 /// /// /// /// public bool RequestSensorState_04(ClientMessage client, int sensorAddr) { if (!client.IsOnline) return false; if (!client.SensorDict.TryGetValue(sensorAddr, out _)) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x04, 2); msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) }; DataRequest request = new() { Request = msg }; return SendRequestTry(ref request); } /// /// 0x04:请求传感器状态 /// /// /// public bool RequestSensorsState_04(ClientMessage client) { if (!client.IsOnline) 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 }; SendRequestTry(ref request); Thread.Sleep(500); } return true; } /// /// 0x05:复位传感器 /// /// /// /// public bool RequestSensorReset_05(ClientMessage client, int sensorAddr) { if (!client.IsOnline) return false; if (!client.SensorDict.TryGetValue(sensorAddr, out _)) 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 }; return SendRequestTry(ref request); } /// /// 0x07:请求传感器列表 /// /// /// public bool RequestSensorList_07(ClientMessage client) { if (!client.IsOnline) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x07, 0); DataRequest request = new() { Request = msg }; return SendRequestTry(ref request); } /// /// 0x08:主机响应0x18主动上传状态 /// /// /// /// public bool ResponseHostUploadState_08(ClientMessage client, DataMessage mm) { if (!client.IsOnline) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x08, 2); msg.Data = new byte[] { mm.Data[0], mm.Data[1] }; return SendResponse(msg, mm.FrameNum); } /// /// 0x09:关闭传感器 /// /// /// /// public bool RequestSensorTurnOff_09(ClientMessage client, int sensorAddr) { if (!client.IsOnline) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x09, 2); msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) }; DataRequest request = new() { Request = msg }; return SendRequestTry(ref request); } /// /// 0x09:关闭传感器 /// /// /// public bool RequestSensorsTurnOff_09(ClientMessage client) { if (!client.IsOnline) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x09, 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 }; SendRequestTry(ref request); Thread.Sleep(500); } return true; } /// /// 0x20:启动传感器 /// /// /// /// public bool RequestSensorTurnOn_20(ClientMessage client, int sensorAddr) { if (!client.IsOnline) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x20, 2); msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) }; DataRequest request = new() { Request = msg }; return SendRequestTry(ref request); } /// /// 0x20:启动传感器 /// /// /// public bool RequestSensorsTurnOn_20(ClientMessage client) { if (!client.IsOnline) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x20, 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 }; SendRequestTry(ref request); Thread.Sleep(500); } return true; } /// /// 0x21:启动全部传感器 /// /// /// public bool RequestSensorsTurnOn_21(ClientMessage client) { if (!client.IsOnline) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x21, 0); DataRequest request = new() { Request = msg }; return SendRequestTry(ref request); } /// /// 0x24:启动自动上传 /// /// /// public bool RequestHostAutoUploadState_24(ClientMessage client) { if (!client.IsOnline) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x24, 0); DataRequest request = new() { Request = msg }; return SendRequestTry(ref request); } /// /// 0x25:关闭自动上传 /// /// /// public bool RequestSensorsTurnOn_25(ClientMessage client) { if (!client.IsOnline) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x25, 0); DataRequest request = new() { Request = msg }; return SendRequestTry(ref request); } #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 _); } public List GetDeviceList() { return DeviceDict.Values.ToList(); } #endregion ClientMessage #region Set private byte Frame { get; set; } = 0; private byte FrameInc { get { return (byte)(++Frame % byte.MaxValue); } } private int SendTryTime { get; set; } = 3; private int SendTryInterval { get; set; } = 500; private int ReqWaitTime { get; set; } = 3; private int ReqWaitInterval { get; set; } = 2000; private DataMessage GetSendMessageHead(int deviceId, ClientMessage client, byte funNum, byte dataLen) { DataMessage msg = new() { DeviceId = deviceId, SendIp = client.LocalIp, SendPort = client.LocalPort.ToInt(), ReceiveIp = client.ClientIp, ReceivePort = client.ClientPort.ToInt(), FunctionNum = funNum, DataLen = dataLen }; return msg; } private 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); bool send = false; for (int i = 0; i < SendTryTime; i++) { send = Server.SendAsync(clientMsg.Client, bytes); if (send) break; Thread.Sleep(SendTryInterval); } Console.WriteLine("Send to {0}:{1} => {2}, send:{3}", clientMsg.ClientIp, clientMsg.ClientPort, cmd, send); return send; } private bool SendRequestTry(ref DataRequest request) { if (request.Request == null) return false; request.Request.FrameNum = FrameInc; SetDataRequest(request); bool send = SendMessage(request.Request.ReceiveIp, request.Request.Encode()); RemoveDataRequest(request); return send; } private bool SendRequestMust(ref DataRequest request) { if (request.Request == null) return false; request.Request.FrameNum = FrameInc; SetDataRequest(request); bool send, respond = false; do { send = SendMessage(request.Request.ReceiveIp, request.Request.Encode()); if (!send) { Thread.Sleep(SendTryInterval); continue; } for (int i = 0; i < ReqWaitTime; i++) { respond = IsResponse(request); if (respond) break; Thread.Sleep(ReqWaitInterval); } } while (!send || !respond); RemoveDataRequest(request); return true; } private bool SendNoRequest(DataMessage request) { request.FrameNum = FrameInc; bool send = SendMessage(request.ReceiveIp, request.Encode()); return send; } private bool SendResponse(DataMessage request, byte frameNum) { request.FrameNum = frameNum; bool send = SendMessage(request.ReceiveIp, request.Encode()); return send; } private ConcurrentDictionary DataRequestDict { get; } = new(); private void SetDataRequest(DataRequest request) { string key = $"{request.Request.FunctionNum:X}-{request.Request.FrameNum}"; DataRequestDict[key] = request; } private void SetDataResponse(DataMessage msg, byte funcNum) { string key = $"{funcNum:X}-{msg.FrameNum}"; if (DataRequestDict.TryGetValue(key, out DataRequest? item)) item.Responce = msg; } private void RemoveDataRequest(DataRequest request) { string key = $"{request.Request.FunctionNum:X}-{request.Request.FrameNum}"; DataRequestDict.Remove(key); } private bool IsResponse(DataRequest request) { string key = $"{request.Request.FunctionNum:X}-{request.Request.FrameNum}"; DataRequestDict.TryGetValue(key, out DataRequest? item); return item != null && item.Responce != null; } #endregion Set }