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.

407 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 == null) { LogUnit.Error(this, $"CameraSdk({sdk?.CameraInfo.Id}-{sdk?.CameraInfo.Ip}) not found."); return; }
if (!sdk.ConnectSuccess()) { LogUnit.Error(this, $"CameraSdk({sdk.CameraInfo.Id}-{sdk.CameraInfo.Ip}) connect failed."); 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})",
ShowInTaskbar = false
};
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);
string cameraIp = cameraSdk?.CameraInfo.Ip ?? string.Empty;
if (cameraSdk == null) { LogUnit.Error(this, $"CameraSdk({cameraId}-{cameraIp}) not found."); return; }
if (!cameraSdk.ConnectSuccess()) { LogUnit.Error(this, $"CameraSdk({cameraId}-{cameraIp}), connect failed."); 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
}