diff --git a/JiLinApp.Docking/Alarm/AlarmCodeHelper.cs b/JiLinApp.Docking/Alarm/AlarmCodeHelper.cs index 18b3273..6f460c1 100644 --- a/JiLinApp.Docking/Alarm/AlarmCodeHelper.cs +++ b/JiLinApp.Docking/Alarm/AlarmCodeHelper.cs @@ -14,7 +14,9 @@ public class AlarmCodeHelper static AlarmCodeHelper() { - using StreamReader r = new(Path.Combine("config", "alarmcode.json")); + string filePath = Path.Combine("config", "alarmcodes.json"); + if (!File.Exists(filePath)) throw new FileNotFoundException(filePath); + using StreamReader r = new(filePath); string jsonStr = r.ReadToEnd(); List list = JsonConvert.DeserializeObject>(jsonStr) ?? new(); AlarmCodeDict = list.ToDictionary(item => item.Id, item => item); @@ -28,7 +30,7 @@ public class AlarmCodeHelper public static AlarmCode Get(string id) { - return AlarmCodeDict[id]; + return AlarmCodeDict[id] ?? AlarmCodeDict["1000"]; } public static bool TryGet(string id, out AlarmCode alarmCode) diff --git a/JiLinApp.Docking/JiLinApp.Docking.csproj b/JiLinApp.Docking/JiLinApp.Docking.csproj index e750c76..0fdd1f5 100644 --- a/JiLinApp.Docking/JiLinApp.Docking.csproj +++ b/JiLinApp.Docking/JiLinApp.Docking.csproj @@ -17,7 +17,7 @@ - + PreserveNewest diff --git a/JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs b/JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs index 67dd1d9..2371a79 100644 --- a/JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs +++ b/JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs @@ -22,6 +22,12 @@ public class ClientMessage } } + public bool Init_0_21 { get; set; } + + public bool Init_1_24 { get; set; } + + public bool Init_2_17 { get; set; } + public ConcurrentDictionary SensorDict { get; } = new(); public int SensorTotal diff --git a/JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs b/JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs index 540808a..c157360 100644 --- a/JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs +++ b/JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Net; using System.Net.Sockets; +using System.Runtime.InteropServices; using System.Text; namespace JiLinApp.Docking.VibrateAlarm; @@ -67,7 +68,7 @@ public class AsyncTcpServer : IDisposable Encoding = Encoding.Default; Listener = new(address, port); Clients = new(); - Listener.AllowNatTraversal(true); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) Listener.AllowNatTraversal(true); } ~AsyncTcpServer() @@ -111,6 +112,9 @@ public class AsyncTcpServer : IDisposable { Listener.Stop(); } + catch + { + } finally { foreach (var client in Clients.Values) @@ -178,40 +182,36 @@ public class AsyncTcpServer : IDisposable private void AcceptTcpClient(TcpListener listener) { - listener.BeginAcceptTcpClient(HandleTcpClientAccepted, listener); + TaskUtil.RunCatch(() => listener.BeginAcceptTcpClient(HandleTcpClientAccepted, listener)); } private void HandleTcpClientAccepted(IAsyncResult ar) { - if (!IsRunning()) return; - if (ar.AsyncState is not TcpListener listener) return; - - TcpClient? client; try { - client = listener.EndAcceptTcpClient(ar); + if (ar.AsyncState is not TcpListener listener) return; + TcpClient? client = listener.EndAcceptTcpClient(ar); if (client == null || !client.Connected) { client?.Client.Disconnect(false); return; } + + // add client connection to cache + string clientAddr = client.ClientAddr(); + byte[] buffer = new byte[client.ReceiveBufferSize]; + TcpClientState clientState = new(client, buffer); + RaiseClientConnected(clientAddr, clientState); + + // begin to read data + ReadBuffer(clientState); + + // keep listening to accept next connection + AcceptTcpClient(listener); } catch (Exception) { - return; } - - // add client connection to cache - string clientAddr = client.ClientAddr(); - byte[] buffer = new byte[client.ReceiveBufferSize]; - TcpClientState clientState = new(client, buffer); - RaiseClientConnected(clientAddr, clientState); - - // begin to read data - ReadBuffer(clientState); - - // keep listening to accept next connection - AcceptTcpClient(listener); } private void ReadBuffer(TcpClientState clientState) @@ -219,12 +219,19 @@ public class AsyncTcpServer : IDisposable try { NetworkStream stream = clientState.GetStream; - if (clientState.IsRead) return; - lock (clientState.IsReadLock) + int tryTime = 3, tryInterval = 200; + bool sleepFlag = false; + for (int i = 0; i < tryTime; i++) { - if (clientState.IsRead) return; - clientState.IsRead = true; - stream.BeginRead(clientState.Buffer, 0, clientState.Buffer.Length, HandleDatagramReceived, clientState); + if (sleepFlag) Thread.Sleep(tryInterval); + lock (clientState.IsReadLock) + { + sleepFlag = clientState.IsRead; + if (sleepFlag) continue; + clientState.IsRead = true; + stream.BeginRead(clientState.Buffer, 0, clientState.Buffer.Length, HandleDatagramReceived, clientState); + break; + } } } catch (IOException e) @@ -242,9 +249,7 @@ public class AsyncTcpServer : IDisposable private void HandleDatagramReceived(IAsyncResult ar) { - if (!IsRunning()) return; if (ar.AsyncState is not TcpClientState clientState) return; - int readNum; string clientAddr = clientState.Client.ClientAddr(); try @@ -269,11 +274,8 @@ public class AsyncTcpServer : IDisposable Buffer.BlockCopy(clientState.Buffer, 0, receivedBytes, 0, readNum); RaiseDatagramReceived(clientState, receivedBytes); - lock (clientState.IsReadLock) - { - clientState.IsRead = false; - } // continue listening for tcp datagram packets + lock (clientState.IsReadLock) clientState.IsRead = false; ReadBuffer(clientState); } @@ -319,10 +321,7 @@ public class AsyncTcpServer : IDisposable public void SendToAll(byte[] datagram) { if (!IsRunning()) return; - foreach (var client in Clients.Values) - { - Send(client.Client, datagram); - } + foreach (var client in Clients.Values) Send(client.Client, datagram); } /// @@ -331,7 +330,6 @@ public class AsyncTcpServer : IDisposable /// 报文 public void SendToAll(string datagram) { - if (!IsRunning()) return; SendToAll(Encoding.GetBytes(datagram)); } @@ -375,10 +373,7 @@ public class AsyncTcpServer : IDisposable public void SendToAllAsync(byte[] datagram) { if (!IsRunning()) return; - foreach (var client in Clients.Values) - { - SendAsync(client.Client, datagram); - } + foreach (var client in Clients.Values) SendAsync(client.Client, datagram); } /// @@ -387,7 +382,6 @@ public class AsyncTcpServer : IDisposable /// 报文 public void SendToAllAsync(string datagram) { - if (!IsRunning()) return; SendToAllAsync(Encoding.GetBytes(datagram)); } @@ -402,6 +396,7 @@ public class AsyncTcpServer : IDisposable { string clientAddr = client.ClientAddr(); RaiseClientDisconnected(clientAddr, client); + return; } } diff --git a/JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs b/JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs index e839d12..314953d 100644 --- a/JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs +++ b/JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs @@ -151,9 +151,12 @@ public class TcpManager #region Analysis + private int SendCmdInterval { get; } = 3000; + 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; @@ -167,10 +170,18 @@ public class TcpManager case 0x00: Console.WriteLine("主机登录:{0}", clientMsg.ClientAddr); ResponseHostLogin_10(clientMsg, mm); - Thread.Sleep(200); - RequestHostAutoUploadState_24(clientMsg); - Thread.Sleep(200); - RequestSensorList_07(clientMsg); + + 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: @@ -206,6 +217,7 @@ public class TcpManager 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)); @@ -240,12 +252,36 @@ public class TcpManager 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; @@ -434,7 +470,7 @@ public class TcpManager { Request = msg }; - return SendRequestMust(ref request); + return SendRequestTry(ref request); } /// @@ -560,7 +596,7 @@ public class TcpManager { Request = msg }; - return SendRequestMust(ref request); + return SendRequestTry(ref request); } /// @@ -643,13 +679,13 @@ public class TcpManager private byte FrameInc { get { return (byte)(++Frame % byte.MaxValue); } } - private int SendTryTime { get; set; } = 5; + private int SendTryTime { get; set; } = 3; - private int SendTryInterval { get; set; } = 200; + private int SendTryInterval { get; set; } = 300; - private int ReqWaitTime { get; set; } = 3 * 10; + private int ReqWaitTime { get; set; } = 3; - private int ReqWaitInterval { get; set; } = 100; + private int ReqWaitInterval { get; set; } = 2000; private DataMessage GetSendMessageHead(int deviceId, ClientMessage client, byte funNum, byte dataLen) { @@ -686,37 +722,29 @@ public class TcpManager { if (request.Request == null) return false; request.Request.FrameNum = FrameInc; - bool send = SendMessage(request.Request.ReceiveIp, request.Request.Encode()); - if (!send) return false; - bool respond = false; SetDataRequest(request); - for (int i = 0; i < ReqWaitTime; i++) - { - respond = IsResponse(request); - if (respond) break; - Thread.Sleep(ReqWaitInterval); - } + bool send = SendMessage(request.Request.ReceiveIp, request.Request.Encode()); RemoveDataRequest(request); - return respond; + 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) continue; - SetDataRequest(request); + 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); + } while (!send || !respond); RemoveDataRequest(request); return true; } @@ -739,27 +767,26 @@ public class TcpManager private void SetDataRequest(DataRequest request) { - string key = $"{request.Request.FunctionNum}-{request.Request.FrameNum}"; + string key = $"{request.Request.FunctionNum:X}-{request.Request.FrameNum}"; DataRequestDict[key] = request; } private void SetDataResponse(DataMessage msg, byte funcNum) { - string key = $"{funcNum}-{msg.FrameNum}"; - DataRequest? item = DataRequestDict[key]; - if (item != null) item.Responce = msg; + 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}-{request.Request.FrameNum}"; + string key = $"{request.Request.FunctionNum:X}-{request.Request.FrameNum}"; DataRequestDict.Remove(key); } private bool IsResponse(DataRequest request) { - string key = $"{request.Request.FunctionNum}-{request.Request.FrameNum}"; - DataRequest? item = DataRequestDict[key]; + string key = $"{request.Request.FunctionNum:X}-{request.Request.FrameNum}"; + DataRequestDict.TryGetValue(key, out DataRequest? item); return item != null && item.Responce != null; } diff --git a/JiLinApp.Docking/config/alarmcode.json b/JiLinApp.Docking/config/alarmcodes.json similarity index 100% rename from JiLinApp.Docking/config/alarmcode.json rename to JiLinApp.Docking/config/alarmcodes.json diff --git a/JiLinApp/Core/Global.cs b/JiLinApp/Core/Global.cs index 233e709..927a8fe 100644 --- a/JiLinApp/Core/Global.cs +++ b/JiLinApp/Core/Global.cs @@ -29,7 +29,9 @@ public static class Global try { // Config - ConfigProvider = new() { FileName = Path.Combine("config", "config.json") }; + string filePath = Path.Combine("config", "appconfig.json"); + if (!File.Exists(filePath)) throw new FileNotFoundException(filePath); + ConfigProvider = new() { FileName = filePath }; AppConfig = new AppConfig(); ConfigProvider.Bind(AppConfig); diff --git a/JiLinApp/JiLinApp.csproj b/JiLinApp/JiLinApp.csproj index cc52e02..2a322a8 100644 --- a/JiLinApp/JiLinApp.csproj +++ b/JiLinApp/JiLinApp.csproj @@ -33,7 +33,7 @@ - + PreserveNewest diff --git a/JiLinApp/Pages/PtzManage/Main.xaml.cs b/JiLinApp/Pages/PtzManage/Main.xaml.cs index e89261a..36bbc3e 100644 --- a/JiLinApp/Pages/PtzManage/Main.xaml.cs +++ b/JiLinApp/Pages/PtzManage/Main.xaml.cs @@ -337,6 +337,7 @@ public partial class Main : UserControl string cameraId = item.CameraId; ICameraSDK cameraSdk = GetCameraSdk(cameraId); if (cameraSdk == null) { LogUnit.Error(this, $"CameraSdk(cameraId:{cameraId}) not found."); return; } + if (cameraSdk.ConnectSuccess()) { MessageBox.Show($"Camera:{cameraSdk.CameraInfo.Ip}, connect failed."); return; } if (realPlay) Dispatcher.Invoke(() => ShowLiveVideo(cameraSdk)); // TODO: 设计 PriorityQueue @@ -435,7 +436,11 @@ public partial class Main : UserControl foreach (var item in CameraSdkDict.Values) { if (item == null) continue; - if (cameraId.Equals(item.CameraInfo.Id)) return item; + if (cameraId.Equals(item.CameraInfo.Id)) + { + if (!item.ConnectSuccess()) item.Init(); + return item; + } } return null; } diff --git a/JiLinApp/config/config.json b/JiLinApp/config/appconfig.json similarity index 100% rename from JiLinApp/config/config.json rename to JiLinApp/config/appconfig.json