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.
		
		
		
		
		
			
		
			
				
					
					
						
							405 lines
						
					
					
						
							14 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							405 lines
						
					
					
						
							14 KiB
						
					
					
				| using Avalonia.Controls; | |
| using Avalonia.Input; | |
| using Avalonia.Interactivity; | |
| using Avalonia.Threading; | |
| using EC.Util.CameraSDK; | |
| using EC.Util.Common; | |
| using EC.Util.Port; | |
| using JiLinApp.Biz.TransmitAlarm; | |
| using JiLinApp.Components; | |
| using JiLinApp.Core; | |
| using JiLinApp.Core.App; | |
| using JiLinApp.Core.Avalonia; | |
| using JiLinApp.Docking.FenceAlarm; | |
| using JiLinApp.Docking.Military; | |
| using JiLinApp.Docking.Ptz; | |
| using JiLinApp.Docking.VibrateAlarm; | |
| using System; | |
| using System.Collections.Concurrent; | |
| using System.Collections.Generic; | |
| using System.IO.Ports; | |
| using System.Linq; | |
| using System.Text.RegularExpressions; | |
| using System.Threading; | |
| 
 | |
| namespace JiLinApp.Pages.PtzServer; | |
| 
 | |
| public partial class Ptz : UserControl | |
| { | |
|     #region Fields | |
|  | |
|     private AppConfig AppConfig { get; } = Global.AppConfig; | |
| 
 | |
|     private MilitaryService MilitaryService { get; } = Global.MilitaryService; | |
| 
 | |
|     private List<CameraLinkageInfo> CameraLinkageList { get; set; } = new(); | |
| 
 | |
|     private ConcurrentDictionary<string, ICameraSdk> CameraSdkDict { get; } = new(); | |
| 
 | |
|     private ConcurrentDictionary<string, CameraRealPlay> RealPlayDict { get; } = new(); | |
| 
 | |
|     private Window? _win; | |
| 
 | |
|     private Window? Wdw | |
|     { | |
|         get | |
|         { | |
|             _win ??= ControlsUtil.GetWindow(this); | |
|             return _win; | |
|         } | |
|     } | |
| 
 | |
|     #endregion Fields | |
|  | |
|     public Ptz() | |
|     { | |
|         InitializeComponent(); | |
| 
 | |
|         //绑定串口服务开关响应事件 | |
|         OpenComBtn.Click += OpenComBtn_Click; | |
|         CloseComBtn.Click += CloseComBtn_Click; | |
|         //绑定实时视频响应事件 | |
|         ShowLiveVideoBtn.Click += ShowLiveVideoBtn_Click; | |
|         //绑定云台响应事件 | |
|         List<Button> btnList = new(); | |
|         ControlsUtil.FindChild(PtzCtrlPanel, ref btnList); | |
|         foreach (var btn in btnList) | |
|         { | |
|             btn.AddHandler(PointerPressedEvent, PtzBtn_MouseDown, RoutingStrategies.Tunnel); | |
|             btn.AddHandler(PointerReleasedEvent, PtzBtn_MouseUp, RoutingStrategies.Tunnel); | |
|         } | |
|         GotoBtn.Click += GotoBtn_Click; | |
|         //绑定云台控制类型更改事件 | |
|         ControlTypeNameCbx.SelectionChanged += ControlTypeName_SelectionChanged; | |
| 
 | |
|         MessageEvent.VibrateAlarm.Subscribe(HandleVibrateAlarm); | |
|         MessageEvent.FenceAlarm.Subscribe(HandleFenceAlarm); | |
| 
 | |
|         // 初始化串口下拉框 | |
|         string[] ports = SerialPort.GetPortNames().OrderBy(s => int.Parse(Regex.Match(s, @"\d+").Value)).ToArray(); | |
|         foreach (string port in ports) ComNameCbx.Items.Add(new ComboBoxItem { Content = port }); | |
|         ComNameCbx.SelectedIndex = 0; | |
|         // 初始化相机 sdk 和相机 ip 下拉框 | |
|         CameraLinkageList = MilitaryService.GetCameraLinkageList(); | |
|         TaskUtil.RunCatch(() => Dispatcher.UIThread.Invoke(() => LoadCameraSdkDict(MilitaryService.GetCameraList()))); | |
|         // 初始化云台控制类型下拉框 | |
|         foreach (var cfg in AppConfig.Base.PtzCtrlTypes) ControlTypeNameCbx.Items.Add(new ComboBoxItem { Content = cfg.Name }); | |
|         ControlTypeNameCbx.SelectedIndex = 0; | |
|         // 初始化相机 id 下拉框 | |
|         for (int i = 1; i <= 5; i++) CameraIdCbx.Items.Add(new ComboBoxItem { Content = i }); | |
|         CameraIdCbx.SelectedIndex = 0; | |
|         // 初始化预置点 id 下拉框 | |
|         for (int i = 1; i <= 10; i++) PresetIdCbx.Items.Add(new ComboBoxItem { Content = i }); | |
|         PresetIdCbx.SelectedIndex = 0; | |
|     } | |
| 
 | |
|     #region Com | |
|  | |
|     private YcSerialPort? Port { get; set; } | |
| 
 | |
|     private bool IsComConnect() | |
|     { | |
|         return Port != null && Port.IsOpen(); | |
|     } | |
| 
 | |
|     private void ChangeState(bool openState) | |
|     { | |
|         OpenComBtn.IsEnabled = !openState; | |
|         CloseComBtn.IsEnabled = openState; | |
|     } | |
| 
 | |
|     #endregion Com | |
|  | |
|     #region Element Event | |
|  | |
|     private void OpenComBtn_Click(object? sender, RoutedEventArgs e) | |
|     { | |
|         if (IsComConnect()) return; | |
|         try | |
|         { | |
|             SerialPortParam param = new() | |
|             { | |
|                 ComName = ComNameCbx.GetText(), | |
|                 BaudRate = int.Parse(BaudRateCbx.GetText()), | |
|                 Parity = 0, | |
|                 DataBits = int.Parse(DataBitsCbx.GetText()), | |
|                 StopBits = int.Parse(StopBitsCbx.GetText()), | |
|             }; | |
|             Port = new YcSerialPort(param); | |
|             Port.OpenCom(); | |
|             ChangeState(true); | |
|         } | |
|         catch (Exception ex) | |
|         { | |
|             Port = null; | |
|             _ = ControlsUtil.ShowWarnDialog(Wdw, message: ex.ToString()); | |
|             LogUnit.Error(ex); | |
|         } | |
|     } | |
| 
 | |
|     private void CloseComBtn_Click(object? sender, RoutedEventArgs e) | |
|     { | |
|         if (!IsComConnect()) return; | |
|         try | |
|         { | |
|             Port?.CloseCom(); | |
|             Port = null; | |
|             ChangeState(false); | |
|         } | |
|         catch (Exception ex) | |
|         { | |
|             _ = ControlsUtil.ShowWarnDialog(Wdw, message: ex.ToString()); | |
|             LogUnit.Error(ex); | |
|         } | |
|     } | |
| 
 | |
|     private void PtzBtn_MouseDown(object? sender, PointerPressedEventArgs e) | |
|     { | |
|         if (sender is not Button btn) return; | |
|         PtzControlType ctrlType = PtzControlTypeConfigHelper.GetControlType(ControlTypeNameCbx.GetText()); | |
|         PtzCmdType cmdType = PtzCmd.GetCmdType((btn.Name ?? string.Empty).Replace("Btn", "")); | |
|         switch (ctrlType) | |
|         { | |
|             case PtzControlType.PelcoD: | |
|             case PtzControlType.PelcoP: | |
|                 if (!IsComConnect()) break; | |
|                 byte cameraId = byte.Parse(CameraIdCbx.GetText()); | |
|                 byte[] cmd = PtzComCmd.GetCmd(ctrlType, cmdType, new object[] { cameraId }); | |
|                 if (cmd != null && cmd.Length > 0) Port?.SendHex(cmd); | |
|                 break; | |
| 
 | |
|             case PtzControlType.DCamera: | |
|                 if (!IsComConnect()) break; | |
|                 cmd = PtzComCmd.GetCmd(ctrlType, cmdType); | |
|                 if (cmd != null && cmd.Length > 0) Port?.SendHex(cmd); | |
|                 break; | |
| 
 | |
|             case PtzControlType.CameraSdk: | |
|                 string cameraIp = CameraIpCbx.GetText(); | |
|                 CameraSdkDict.TryGetValue(cameraIp, out ICameraSdk? cameraSdk); | |
|                 if (cameraSdk == null) break; | |
|                 int stop = 0; | |
|                 PtzCameraCmd.PtzMove(cameraSdk, cmdType, new int[] { stop }); | |
|                 break; | |
| 
 | |
|             default: break; | |
|         } | |
|     } | |
| 
 | |
|     private void PtzBtn_MouseUp(object? sender, PointerReleasedEventArgs e) | |
|     { | |
|         if (sender is not Button btn) return; | |
|         PtzControlType ctrlType = PtzControlTypeConfigHelper.GetControlType(ControlTypeNameCbx.GetText()); | |
|         PtzCmdType cmdType = PtzCmdType.Stop; | |
|         switch (ctrlType) | |
|         { | |
|             case PtzControlType.PelcoD: | |
|             case PtzControlType.PelcoP: | |
|                 if (!IsComConnect()) break; | |
|                 byte cameraId = byte.Parse(CameraIdCbx.GetText()); | |
|                 byte[] cmd = PtzComCmd.GetCmd(ctrlType, cmdType, new object[] { cameraId }); | |
|                 if (cmd != null && cmd.Length > 0) Port?.SendHex(cmd); | |
|                 break; | |
| 
 | |
|             case PtzControlType.DCamera: | |
|                 if (!IsComConnect()) break; | |
|                 cmd = PtzComCmd.GetCmd(ctrlType, cmdType); | |
|                 if (cmd != null && cmd.Length > 0) Port?.SendHex(cmd); | |
|                 break; | |
| 
 | |
|             case PtzControlType.CameraSdk: | |
|                 string cameraIp = CameraIpCbx.GetText(); | |
|                 CameraSdkDict.TryGetValue(cameraIp, out ICameraSdk? cameraSdk); | |
|                 if (cameraSdk == null) break; | |
|                 cmdType = PtzCmd.GetCmdType((btn.Name ?? string.Empty).Replace("Btn", "")); | |
|                 int stop = 1; | |
|                 PtzCameraCmd.PtzMove(cameraSdk, cmdType, new int[] { stop }); | |
|                 break; | |
| 
 | |
|             default: break; | |
|         } | |
|     } | |
| 
 | |
|     private void GotoBtn_Click(object? sender, RoutedEventArgs e) | |
|     { | |
|         PtzControlType ctrlType = PtzControlTypeConfigHelper.GetControlType(ControlTypeNameCbx.GetText()); | |
|         PtzCmdType cmdType = PtzCmdType.PresetGoto; | |
|         byte presetId = byte.Parse(PresetIdCbx.GetText()); | |
|         switch (ctrlType) | |
|         { | |
|             case PtzControlType.PelcoD: | |
|             case PtzControlType.PelcoP: | |
|                 if (!IsComConnect()) break; | |
|                 byte cameraId = byte.Parse(CameraIdCbx.GetText()); | |
|                 byte[] cmd = PtzComCmd.GetCmd(ctrlType, cmdType, new object[] { cameraId, presetId }); | |
|                 if (cmd != null && cmd.Length > 0) Port?.SendHex(cmd); | |
|                 break; | |
| 
 | |
|             case PtzControlType.CameraSdk: | |
|                 string cameraIp = CameraIpCbx.GetText(); | |
|                 CameraSdkDict.TryGetValue(cameraIp, out ICameraSdk? cameraSdk); | |
|                 if (cameraSdk == null) break; | |
|                 PtzCameraCmd.PtzMove(cameraSdk, cmdType, new int[] { presetId }); | |
|                 break; | |
| 
 | |
|             default: break; | |
|         } | |
|     } | |
| 
 | |
|     private void ShowLiveVideoBtn_Click(object? sender, RoutedEventArgs e) | |
|     { | |
|         string cameraIp = CameraIpCbx.GetText(); | |
|         if (!CameraSdkDict.TryGetValue(cameraIp, out ICameraSdk? sdk)) return; | |
|         Dispatcher.UIThread.Invoke(() => ShowLiveVideo(sdk)); | |
|     } | |
| 
 | |
|     private void ControlTypeName_SelectionChanged(object? sender, SelectionChangedEventArgs e) | |
|     { | |
|         if (e.AddedItems[0] is not ComboBoxItem cbxItem) return; | |
|         string ctrlTypeName = cbxItem?.Content?.ToString() ?? string.Empty; | |
|         PtzControlType ctrlType = PtzControlTypeConfigHelper.GetControlType(ctrlTypeName); | |
|         switch (ctrlType) | |
|         { | |
|             case PtzControlType.PelcoD: | |
|             case PtzControlType.PelcoP: | |
|             case PtzControlType.DCamera: | |
|                 CameraIdCbx.IsEnabled = true; | |
|                 CameraIpCbx.IsEnabled = false; | |
|                 ShowLiveVideoBtn.IsEnabled = false; | |
|                 break; | |
| 
 | |
|             case PtzControlType.CameraSdk: | |
|                 CameraIdCbx.IsEnabled = false; | |
|                 CameraIpCbx.IsEnabled = true; | |
|                 ShowLiveVideoBtn.IsEnabled = true; | |
|                 break; | |
| 
 | |
|             default: | |
|                 CameraIdCbx.IsEnabled = false; | |
|                 CameraIpCbx.IsEnabled = false; | |
|                 ShowLiveVideoBtn.IsEnabled = false; | |
|                 break; | |
|         } | |
|     } | |
| 
 | |
|     #endregion Element Event | |
|  | |
|     #region Invoke Event | |
|  | |
|     private void ShowLiveVideo(ICameraSdk sdk) | |
|     { | |
|         if (!sdk.ConnectSuccess()) { LogUnit.Error(this, $"CameraSdk(cameraIp:{sdk.CameraInfo.Ip}) connect failure."); return; } | |
|         if (!ControlsUtil.TryGetWindow(this, out Window? w)) return; | |
|         string cameraIp = sdk.CameraInfo.Ip; | |
|         RealPlayDict.TryGetValue(cameraIp, out CameraRealPlay? realPlay); | |
|         if (realPlay == null || realPlay.IsClosed) | |
|         { | |
|             realPlay = new(sdk) | |
|             { | |
|                 Title = $"RealPlay({sdk.CameraInfo.Name})", | |
|                 CanResize = false, | |
|                 ShowInTaskbar = true | |
|             }; | |
|             RealPlayDict[cameraIp] = realPlay; | |
|         } | |
|         realPlay.Show(w); | |
|         realPlay.WindowState = WindowState.Normal; | |
|         realPlay.StartPlay(); | |
|     } | |
| 
 | |
|     private void HandleVibrateAlarm(TcpAlarmHostMessage msg) | |
|     { | |
|         AlarmMessage alarm = msg.ToAlarmMessage(); | |
|         TaskUtil.RunCatch(() => HandleAlarmInvoke(alarm)); | |
|     } | |
| 
 | |
|     private void HandleFenceAlarm(UdpAlarmHostMessage msg) | |
|     { | |
|         AlarmMessage alarm = msg.ToAlarmMessage(); | |
|         TaskUtil.RunCatch(() => HandleAlarmInvoke(alarm)); | |
|     } | |
| 
 | |
|     private void HandleAlarmInvoke(AlarmMessage alarm) | |
|     { | |
|         if (alarm == null) return; | |
|         bool realPlay = AppConfig.AlarmPlatform.RealPlay; | |
|         string deviceId = alarm.LabelCode; | |
|         string sensorId = alarm.ChannelId; | |
|         List<CameraLinkageInfo> cameraLinkages = GetCameraLinkageList(sensorId); | |
|         foreach (var item in cameraLinkages) | |
|         { | |
|             if (item == null) { LogUnit.Error(this, $"CameraLinkageInfo(sensorId:{sensorId}) not found."); return; } | |
|             string cameraId = item.CameraId; | |
|             ICameraSdk? cameraSdk = GetCameraSdk(cameraId); | |
|             if (cameraSdk == null) { LogUnit.Error(this, $"CameraSdk(cameraId:{cameraId}) not found."); return; } | |
|             if (realPlay) Dispatcher.UIThread.Invoke(() => ShowLiveVideo(cameraSdk)); | |
|             // TODO: 设计 PriorityQueue | |
|             int len = item.PresetIds.Length; | |
|             for (int i = 0; i < len; i++) | |
|             { | |
|                 int presetId = item.PresetIds[i]; | |
|                 PtzCameraCmd.PtzMove(cameraSdk, PtzCmdType.PresetGoto, new int[] { presetId }); | |
|                 if (i != len) Thread.Sleep(5000); | |
|             } | |
|         } | |
|     } | |
| 
 | |
|     #endregion Invoke Event | |
|  | |
|     #region Military | |
|  | |
|     private void LoadCameraSdkDict(List<CameraInfo> cameraList) | |
|     { | |
|         int tryTime = 5, tryInterval = 500; | |
|         for (int i = 0; i < cameraList.Count; i++) | |
|         { | |
|             CameraInfo info = cameraList[i]; | |
|             string ip = info.Ip; | |
|             if (CameraSdkDict.ContainsKey(ip)) continue; | |
|             ICameraSdk sdk = CameraFactory.BuildCameraSdk(info); | |
|             CameraSdkDict[ip] = sdk; | |
|             CameraIpCbx.Items.Add(new ComboBoxItem { Content = ip }); | |
|             TaskUtil.RunCatch(() => | |
|             { | |
|                 bool flag = false; | |
|                 for (int i = 0; i < tryTime; i++) | |
|                 { | |
|                     flag = sdk.Init(); | |
|                     if (flag) break; | |
|                     Thread.Sleep(tryInterval); | |
|                 } | |
|             }); | |
|         } | |
|     } | |
| 
 | |
|     private CameraLinkageInfo? GetCameraLinkage(string sensorId) | |
|     { | |
|         foreach (var item in CameraLinkageList) | |
|         { | |
|             if (sensorId.Equals(item.SensorId)) return item; | |
|         } | |
|         return null; | |
|     } | |
| 
 | |
|     private List<CameraLinkageInfo> GetCameraLinkageList(string sensorId) | |
|     { | |
|         List<CameraLinkageInfo> list = new(); | |
|         foreach (var item in CameraLinkageList) | |
|         { | |
|             if (sensorId.Equals(item.SensorId)) list.Add(item); | |
|         } | |
|         return list; | |
|     } | |
| 
 | |
|     private ICameraSdk? GetCameraSdk(string cameraId) | |
|     { | |
|         foreach (var item in CameraSdkDict.Values) | |
|         { | |
|             if (item == null) continue; | |
|             if (cameraId.Equals(item.CameraInfo.Id)) return item; | |
|         } | |
|         return null; | |
|     } | |
| 
 | |
|     #endregion Military | |
| } |