Browse Source

[feat] 添加linux上大华宇视播放实时视频功能

todolist:
1.CameraFactory.cs 下库文件,解压后需要赋予 777 权限.目前是手动赋予 777 权限
2.CameraFactory.cs 下库文件,LD_LIBRARY_PATH,海康不需要设置,大华将相关库文件放在软件根目录下解决,宇视需要设置LD_LIBRARAY_PATH.
master
fajiao 2 years ago
parent
commit
0e9ca4e69e
  1. 1
      EC.Util/CameraSDK/Common/CameraFactory.cs
  2. 7
      EC.Util/CameraSDK/Common/CameraStruct.cs
  3. 71
      EC.Util/CameraSDK/DaHua/DaHuaOriSdk.cs
  4. 75
      EC.Util/CameraSDK/DaHua/DaHuaSdk.cs
  5. 97
      EC.Util/CameraSDK/DaHua/DhPlaySdk.cs
  6. 15
      EC.Util/CameraSDK/HiK/HiKOriSdk.cs
  7. 16
      EC.Util/CameraSDK/HiK/HiKSdk.cs
  8. 6
      EC.Util/CameraSDK/HiK/PlayCtrlSdk.cs
  9. 8
      EC.Util/CameraSDK/YuShi/YuShiOriSdk.cs
  10. 53
      EC.Util/CameraSDK/YuShi/YuShiSdk.cs
  11. 94
      EC.Util/Common/ReflectUtil.cs
  12. 12
      EC.Util/Common/SystemUtil.cs
  13. 1
      EC.Util/EC.Util.csproj
  14. 155
      EC.Util/Platform/LinuxUtil.cs
  15. 5
      EC.Util/Platform/SystemUtil.cs
  16. 96
      EC.Util/Platform/WinUtil.cs
  17. BIN
      EC.Util/libs/cameraSdks.zip
  18. 2
      JiLinApp.Docking/Alarm/AlarmCodeHelper.cs
  19. 17
      JiLinApp.Docking/FenceAlarm/Service/UdpServer.cs
  20. 6
      JiLinApp.Docking/Ptz/PtzCmd.cs
  21. 6
      JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs
  22. 74
      JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs
  23. 92
      JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs
  24. 18
      JiLinApp.Docking/config/alarmcodes.json
  25. 111
      JiLinApp/Components/CameraRealPlay.axaml.cs
  26. 103
      JiLinApp/Core/Avalonia/ControlsUtil.cs
  27. 2
      JiLinApp/Pages/FenceServer/Fence.axaml.cs
  28. 4
      JiLinApp/Pages/Main/MainWindow.axaml.cs
  29. 10
      JiLinApp/Pages/PtzServer/Ptz.axaml.cs

1
EC.Util/CameraSDK/Common/CameraFactory.cs

@ -15,6 +15,7 @@ public class CameraFactory
string hkOrDir = $"cameraSdks/hik/{sysEnv}/";
string dhOrDir = $"cameraSdks/dahua/{sysEnv}/";
string ysOrDir = $"cameraSdks/yushi/{sysEnv}/";
// TODO: linux chmod 777, LD_LIBRARY_PATH
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.Length == 0) continue;

7
EC.Util/CameraSDK/Common/CameraStruct.cs

@ -104,7 +104,12 @@ public enum CameraManufactor : int
public enum CameraPort : int
{
HiK = 8000,
DaHua = 37777,
DaHua =
37777,
YuShi = 80,
}

71
EC.Util/CameraSDK/DaHua/DaHuaOriSdk.cs

@ -14,7 +14,7 @@ public static class DaHuaOriSdk
public const string LibSdkPath = @"./libs/dahua/libdhnetsdk.so";
#endif
private const bool Debug = true;
private const bool Debug = false;
#endregion Fields
@ -40,7 +40,7 @@ public static class DaHuaOriSdk
{
dwSize = (uint)Marshal.SizeOf(typeof(NET_LOG_SET_PRINT_INFO)),
bSetFilePath = 1,
szLogFilePath = Path.Combine("./log", "dahuaSdkLog", "sdk_log.log")
szLogFilePath = Path.Combine("./logs", "dahuaSdkLog", "sdk_log.log")
};
CLIENT_LogOpen(ref logInfo);
}
@ -1265,6 +1265,34 @@ public static class DaHuaOriSdk
Realplay_Test = 255,
}
[Flags]
public enum EM_REALDATA_FLAG
{
/// <summary>
/// raw data flag, corresponding param dwDataType in fRealDataCallBackEx / fRealDataCallBackEx2 is 0, 0x01 = 0x01 << 0
/// 原始数据标志, 对应fRealDataCallBack(Ex/Ex2)回调函数中 dwDataType 为0, 0x01 = 0x01 << 0
/// </summary>
RAW_DATA = 0x01,
/// <summary>
/// data with frame info flag, corresponding param dwDataType in fRealDataCallBackEx / fRealDataCallBackEx2 is 1, 0x02 = 0x01 << 1
/// 带有帧信息的数据标志, 对应fRealDataCallBack(Ex/Ex2)回调函数中 dwDataType 为1, 0x02 = 0x01 << 1
/// </summary>
DATA_WITH_FRAME_INFO = 0x02,
/// <summary>
/// YUV data flag, corresponding param dwDataType in fRealDataCallBackEx / fRealDataCallBackEx2 is 2, 0x04 = 0x01 << 2
/// YUV 数据标志, 对应fRealDataCallBack(Ex/Ex2)回调函数中 dwDataType 为2, 0x04 = 0x01 << 2
/// </summary>
YUV_DATA = 0x04,
/// <summary>
/// PCM audio data flag, corresponding param dwDataType in fRealDataCallBackEx / fRealDataCallBackEx2 is 3, 0x08 = 0x01 << 3
/// PCM 音频数据标志, 对应fRealDataCallBack(Ex/Ex2)回调函数中 dwDataType 为3, 0x08 = 0x01 << 3
/// </summary>
PCM_AUDIO_DATA = 0x08,
}
#endregion Sdk Enum
#region Sdk Struct
@ -1601,6 +1629,44 @@ public static class DaHuaOriSdk
[DllImport(LibSdkPath)]
public static extern IntPtr CLIENT_RealPlayEx(IntPtr lLoginID, int nChannelID, IntPtr hWnd, EM_RealPlayType rType);
/// <summary>
/// real-time monitor data callback function original shape---extensive. support 32bit and 64bit
/// 实时预览数据回调函数.支持32位和64位.
/// </summary>
/// <param name="lRealHandle">monitor handle 预览句柄</param>
/// <param name="dwDataType">callback data type ,only data set in dwFlag will be callback:回调数据类型
/// <para>0 original data (identicla SaveRealData saveddata)</para>
/// <para>1 frame data</para>
/// <para>2 yuv data</para>
/// <para>3 pcm audio data</para></param>
/// <param name="pBuffer">byte array, length is dwBufSize 回调数据缓存
/// <para>callback data, except type 0, other type is base on frame, one frame data per callback</para></param>
/// <param name="dwBufSize">pBuffer's size 回调数据的缓存大小</param>
/// <param name="param">pointer to parameter structure,based on different type 参数结构体的指针
/// <para>if type is 0(original) or 2(yuv), param is 0</para>
/// <para>if callback data is frame data, pointer to NET_VideoFrameParam</para>
/// <para>if callback data is PCM data, pointer to NET_CBPCMDataParam</para></param>
/// <param name="dwUser">user data,which input above</param>
public delegate void RealDataCallBack(IntPtr lRealHandle, uint dwDataType, IntPtr pBuffer, uint dwBufSize, IntPtr param, IntPtr dwUser);
/// <summary>
/// set real-time monitor data callback
/// 设置实时预览数据回调
/// </summary>
/// <param name="lRealHandle">monitor handle 预览句柄</param>
/// <param name="realDataCallBack">callback function 回调函数</param>
/// <param name="dwUser">user data, there is no data, please use IntPtr.Zero 用户数据</param>
/// <param name="dwFlag">by bit, can combine, when it is 0x1f, callback the five types, 回调数据类型as:
/// <para>0x00000001 is equivalent with original data</para>
/// <para>0x00000002 is MPEG4/H264 standard data</para>
/// <para>0x00000004 YUV data</para>
/// <para>0x00000008 PCM data</para>
/// <para>0x00000010 original audio data</para>
/// <para>0x0000001f above five data type</para></param>
/// <returns>failed return false, successful return true 失败返回false 成功返回true</returns>
[DllImport(LibSdkPath)]
public static extern bool CLIENT_SetRealDataCallBackEx2(IntPtr lRealHandle, RealDataCallBack realDataCallBack, IntPtr dwUser, uint dwFlag);
/// <summary>
/// stop real time monitoring
/// 关闭实时监视
@ -1611,4 +1677,5 @@ public static class DaHuaOriSdk
public static extern bool CLIENT_StopRealPlayEx(IntPtr lRealHandle);
#endregion Common Method
}

75
EC.Util/CameraSDK/DaHua/DaHuaSdk.cs

@ -8,7 +8,7 @@ public class DaHuaSdk : ICameraSdk
private IntPtr LoginId { get; set; } = IntPtr.Zero;
private int Channel { get; } = 1;
private int Channel { get; } = 0;
#endregion Fields
@ -34,10 +34,7 @@ public class DaHuaSdk : ICameraSdk
stuOutParam.dwSize = (uint)Marshal.SizeOf(stuOutParam);
LoginId = DaHuaOriSdk.CLIENT_LoginWithHighLevelSecurity(ref stuInParam, ref stuOutParam);
ret = ConnectSuccess();
if (ret) DaHuaOriSdk.CLIENT_SetAutoReconnect(delegate (IntPtr lLoginID, IntPtr pchDVRIP, int nDVRPort, IntPtr dwUser)
{
LoginId = lLoginID;
}, IntPtr.Zero);
if (ret) DaHuaOriSdk.CLIENT_SetAutoReconnect(null, IntPtr.Zero);
else BuildException();
return ret;
}
@ -154,23 +151,89 @@ public class DaHuaSdk : ICameraSdk
#region Video Method
private IntPtr Hwnd { get; set; }
private IntPtr RealplayHandle { get; set; } = IntPtr.Zero;
private int RealplayPort { get; set; } = -1;
public override void StartPlay(IntPtr hwnd)
{
if (!ConnectSuccess() || IsPlaying()) return;
RealplayHandle = DaHuaOriSdk.CLIENT_RealPlayEx(LoginId, Channel, hwnd, DaHuaOriSdk.EM_RealPlayType.Realplay);
Hwnd = hwnd;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) StartPlayLinux();
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) StartPlayLinux();
else Hwnd = IntPtr.Zero;
}
private void StartPlayWindows()
{
RealplayHandle = DaHuaOriSdk.CLIENT_RealPlayEx(LoginId, Channel, Hwnd, DaHuaOriSdk.EM_RealPlayType.Realplay);
if (RealplayHandle == IntPtr.Zero) BuildException();
}
private void StartPlayLinux()
{
bool ret;
if (RealDataCallBack == null && RealplayPort < 0)
{
int nPort = -1;
if (!DhPlaySdk.PLAY_GetFreePort(ref nPort)) DhPlaySdk.BuildException(this, nPort);
if (!DhPlaySdk.PLAY_OpenStream(nPort, 0, 0, 3 * 1024 * 1024)) DhPlaySdk.BuildException(this, nPort);
if (!DhPlaySdk.PLAY_Play(nPort, Hwnd)) DhPlaySdk.BuildException(this, nPort);
RealplayPort = nPort;
}
RealplayHandle = DaHuaOriSdk.CLIENT_RealPlayEx(LoginId, Channel, IntPtr.Zero, DaHuaOriSdk.EM_RealPlayType.Realplay);
if (RealplayHandle < 0) BuildException();
RealDataCallBack ??= DefaultRealDataCallBack;
ret = DaHuaOriSdk.CLIENT_SetRealDataCallBackEx2(RealplayHandle, RealDataCallBack, IntPtr.Zero, (uint)(DaHuaOriSdk.EM_REALDATA_FLAG.RAW_DATA));
if (!ret) BuildException();
}
public override void StopPlay()
{
if (!IsPlaying()) return;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) StopPlayLinux();
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) StopPlayLinux();
Hwnd = IntPtr.Zero;
}
private void StopPlayWindows()
{
bool ret = DaHuaOriSdk.CLIENT_StopRealPlayEx(RealplayHandle);
RealplayHandle = IntPtr.Zero;
if (!ret) BuildException();
}
private void StopPlayLinux()
{
bool ret = DaHuaOriSdk.CLIENT_StopRealPlayEx(RealplayHandle);
RealplayHandle = IntPtr.Zero;
RealDataCallBack = null;
if (RealplayPort >= 0)
{
DhPlaySdk.PLAY_Stop(RealplayPort);
DhPlaySdk.PLAY_CloseStream(RealplayPort);
DhPlaySdk.PLAY_ReleasePort(RealplayPort);
RealplayPort = -1;
}
if (!ret) BuildException();
}
public DaHuaOriSdk.RealDataCallBack? RealDataCallBack { get; set; }
private void DefaultRealDataCallBack(IntPtr lRealHandle, uint dwDataType, IntPtr pBuffer, uint dwBufSize, IntPtr param, IntPtr dwUser)
{
if (RealplayPort < 0 || dwBufSize <= 0) return;
switch (dwDataType)
{
case 0:
//original unencrypted stream
DhPlaySdk.PLAY_InputData(RealplayPort, pBuffer, dwBufSize);
break;
}
}
public override bool IsPlaying()
{
return RealplayHandle != IntPtr.Zero;

97
EC.Util/CameraSDK/DaHua/DhPlaySdk.cs

@ -0,0 +1,97 @@
//#define Win
using System.Runtime.InteropServices;
namespace EC.Util.CameraSDK;
/// <summary>
/// linux下 需要安装 opengl
/// </summary>
public class DhPlaySdk
{
#region Fields
#if Win
public const string LibSdkPath = @"./libs/dahua/dhplay.dll";
#else
public const string LibSdkPath = @"./libs/dahua/libdhplay.so";
#endif
#endregion Fields
static DhPlaySdk()
{
}
#region struct enum
public enum LogLevel
{
LOG_LevelUnknown = 0, // 未知等级
LOG_LevelFatal, // fatal等级,当设置为此等级时,有一种打印输出(fatal)都有输出
LOG_LevelError, // error等级,当设置为此等级时,有两种打印输出(fatal,error)都有输出
LOG_LevelWarn, // warn等级,当设置为此等级时,有三种打印输出(fatal,error,warn)都有输出
LOG_LevelInfo, // info等级,当设置为此等级时,有四种打印输出(fatal,error,warn,info)都有输出
LOG_LevelTrace, // Trace等级,当设置为此等级时,有五种打印输出(fatal,error,warn,info,trace)都有输出
LOG_LevelDebug // Debug等级,当设置为此等级时,以上六种打印(fatal,error,warn,info,trace,debug)都有输出
}
/* 渲染模式 */
public enum RenderType
{
RENDER_NOTSET = 0, // 未设置
RENDER_GDI, // GDI渲染
RENDER_X11 = RENDER_GDI, // 非windows平台X11渲染
RENDER_DDRAW, // ddraw渲染
RENDER_OPENGL = RENDER_DDRAW, // 非windows平台opengl渲染
RENDER_D3D, // D3D渲染,默认等同于D3D9渲染
RENDER_D3D9 = RENDER_D3D, // D3D9渲染
RENDER_WGL, // windows平台opengl渲染
RENDER_D3D11 // D3D11渲染
}
#endregion struct enum
#region PlaySdk
public static void BuildException(ICameraSdk cameraSdk, int nPort)
{
string err = $"DhPlaySdk failed, error code={PLAY_GetLastErrorEx()}";
throw CameraException.New(cameraSdk.CameraInfo, -1, err);
}
[DllImport(LibSdkPath)]
public static extern bool PLAY_GetFreePort(ref int nPort);
[DllImport(LibSdkPath)]
public static extern bool PLAY_ReleasePort(int nPort);
[DllImport(LibSdkPath)]
public static extern bool PLAY_SetRenderMode(int nPort, RenderType nMode);
[DllImport(LibSdkPath)]
public static extern uint PLAY_GetLastErrorEx();
[DllImport(LibSdkPath)]
public static extern uint PLAY_SetPrintLogLevel(LogLevel logLevel);
[DllImport(LibSdkPath)]
public static extern bool PLAY_SetStreamOpenMode(int nPort, uint nMode);
[DllImport(LibSdkPath)]
public static extern bool PLAY_OpenStream(int nPort, IntPtr pFileHeadBuf, uint nSize, uint nBufPoolSize);
[DllImport(LibSdkPath)]
public static extern bool PLAY_Play(int nPort, IntPtr hWnd);
[DllImport(LibSdkPath)]
public static extern bool PLAY_InputData(int nPort, IntPtr pBuf, uint nSize);
[DllImport(LibSdkPath)]
public static extern bool PLAY_Stop(int nPort);
[DllImport(LibSdkPath)]
public static extern bool PLAY_CloseStream(int nPort);
#endregion PlaySdk
}

15
EC.Util/CameraSDK/HiK/HiKOriSdk.cs

@ -34,7 +34,7 @@ public class HiKOriSdk
bool ret = NET_DVR_Init();
InitSuccess = ret;
if (!ret) throw new Exception("HiKOriSdk global init failure.");
if (Debug) NET_DVR_SetLogToFile(3, Path.Combine("./log", "hikSdkLog"), true);
if (Debug) NET_DVR_SetLogToFile(3, Path.Combine("./logs", "hikSdkLog"), true);
return ret;
}
@ -387,19 +387,10 @@ public class HiKOriSdk
**********************************************************/
[DllImport(LibSdkPath, CallingConvention = CallingConvention.StdCall)]
public static extern int NET_DVR_RealPlay_V40(int iUserID, ref NET_DVR_PREVIEWINFO lpPreviewInfo, RealDataCallBack fRealDataCallBack_V30, IntPtr pUser);
/*********************************************************
Function: REALDATACALLBACK
Desc: (ص)
Input:
Output:
Return:
**********************************************************/
//public delegate void SETREALDATACALLBACK(int lRealHandle, uint dwDataType, IntPtr pBuffer, uint dwBufSize, uint dwUser);
public static extern int NET_DVR_RealPlay_V40(int iUserID, ref NET_DVR_PREVIEWINFO lpPreviewInfo, RealDataCallBack realDataCallBack, IntPtr pUser);
[DllImport(LibSdkPath, CallingConvention = CallingConvention.StdCall)]
public static extern bool NET_DVR_SetRealDataCallBack(int lRealHandle, RealDataCallBack fRealDataCallBack, IntPtr pUser);
public static extern bool NET_DVR_SetRealDataCallBack(int lRealHandle, RealDataCallBack realDataCallBack, IntPtr pUser);
/*********************************************************
Function: NET_DVR_StopRealPlay

16
EC.Util/CameraSDK/HiK/HiKSdk.cs

@ -66,12 +66,6 @@ public class HiKSdk : ICameraSdk
throw CameraException.New(CameraInfo, (int)errCode);
}
public void BuildPlayCtrlException(int nPort)
{
string err = $"PlayCtrlSdk failed, error code={PlayCtrlSdk.PlayM4_GetLastError(nPort)}";
throw CameraException.New(CameraInfo, -1, err);
}
#endregion Base Method
#region Ptz Method
@ -160,12 +154,12 @@ public class HiKSdk : ICameraSdk
#region Video Method
private IntPtr Hwnd { get; set; }
private int RealplayHandle { get; set; } = -1;
private int RealplayPort { get; set; } = -1;
private IntPtr Hwnd { get; set; }
public override void StartPlay(IntPtr hwnd)
{
if (!ConnectSuccess() || IsPlaying()) return;
@ -192,11 +186,11 @@ public class HiKSdk : ICameraSdk
private void StartPlayLinux()
{
if (RealplayPort < 0 && RealDataCallBack == null)
if (RealDataCallBack == null && RealplayPort < 0)
{
int nPort = -1;
bool ret = PlayCtrlSdk.PlayM4_GetPort(ref nPort);
if (!ret) BuildPlayCtrlException(nPort);
if (!ret) PlayCtrlSdk.BuildException(this, nPort);
RealplayPort = nPort;
}
HiKOriSdk.NET_DVR_PREVIEWINFO previewInfo = new()
@ -253,7 +247,7 @@ public class HiKSdk : ICameraSdk
PlayCtrlSdk.PlayM4_SetStreamOpenMode(RealplayPort, 0);
PlayCtrlSdk.PlayM4_OpenStream(RealplayPort, pBuffer, dwBufSize, 2 * 1024 * 1024);
PlayCtrlSdk.PlayM4_SetDisplayBuf(RealplayPort, 5);
if (!PlayCtrlSdk.PlayM4_Play(RealplayPort, Hwnd)) BuildPlayCtrlException(RealplayPort);
if (!PlayCtrlSdk.PlayM4_Play(RealplayPort, Hwnd)) PlayCtrlSdk.BuildException(this, RealplayPort);
break;
case HiKOriSdk.NET_DVR_STREAMDATA:

6
EC.Util/CameraSDK/HiK/PlayCtrlSdk.cs

@ -36,6 +36,12 @@ public class PlayCtrlSdk
#region Sdk Method
public static void BuildException(ICameraSdk cameraSdk, int nPort)
{
string err = $"PlayCtrlSdk failed, error code={PlayM4_GetLastError(nPort)}";
throw CameraException.New(cameraSdk.CameraInfo, -1, err);
}
[DllImport(LibSdkPath)]
public static extern bool PlayM4_GetPort(ref int nPort);

8
EC.Util/CameraSDK/YuShi/YuShiOriSdk.cs

@ -14,7 +14,7 @@ public class YuShiOriSdk
public const string LibSdkPath = @"./libs/yushi/libNetDEVSDK.so";
#endif
private const bool Debug = true;
private const bool Debug = false;
#endregion Fields
@ -35,7 +35,7 @@ public class YuShiOriSdk
if (!ret) throw new Exception("YuShiOriSdk global init failure.");
if (Debug)
{
string logPath = Path.Combine("./log", "yushiSdkLog");
string logPath = Path.Combine("./logs", "yushiSdkLog");
Directory.CreateDirectory(logPath);
NETDEV_SetLogPath(logPath);
}
@ -236,8 +236,10 @@ public class YuShiOriSdk
[DllImport(LibSdkPath, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern int NETDEV_PTZPreset_Other(IntPtr lpUserID, int dwChannelID, int dwPTZPresetCmd, byte[] szPresetName, int dwPresetID);
public delegate void RealDataCallBack(IntPtr lpPlayHandle, IntPtr pucBuffer, uint dwBufSize, uint dwMediaDataType, IntPtr lpUserParam);
[DllImport(LibSdkPath, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr NETDEV_RealPlay(IntPtr lpUserID, ref NETDEV_PREVIEWINFO_S pstPreviewInfo, IntPtr cbPlayDataCallBack, IntPtr lpUserData);
public static extern IntPtr NETDEV_RealPlay(IntPtr lpUserID, ref NETDEV_PREVIEWINFO_S pstPreviewInfo, RealDataCallBack cbPlayDataCallBack, IntPtr lpUserData);
[DllImport(LibSdkPath, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern int NETDEV_StopRealPlay(IntPtr lpRealHandle);

53
EC.Util/CameraSDK/YuShi/YuShiSdk.cs

@ -111,31 +111,80 @@ public class YuShiSdk : ICameraSdk
#region Video Method
private IntPtr Hwnd { get; set; }
private IntPtr RealplayHandle { get; set; } = IntPtr.Zero;
private int RealplayPort { get; set; } = -1;
public override void StartPlay(IntPtr hwnd)
{
if (!ConnectSuccess() || IsPlaying()) return;
Hwnd = hwnd;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) StartPlayWindows();
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) StartPlayLinux();
else Hwnd = IntPtr.Zero;
}
private void StartPlayWindows()
{
YuShiOriSdk.NETDEV_PREVIEWINFO_S stPreviewInfo = new()
{
hPlayWnd = hwnd,
hPlayWnd = Hwnd,
dwChannelID = Channel,
dwStreamType = 0, // YuShiOriSdk.NETDEV_LIVE_STREAM_INDEX_E
dwLinkMode = 1, // YuShiOriSdk.NETDEV_PROTOCAL_E
dwFluency = 0, // YuShiOriSdk.NETDEV_PICTURE_FLUENCY_E
};
RealplayHandle = YuShiOriSdk.NETDEV_RealPlay(LoginId, ref stPreviewInfo, IntPtr.Zero, IntPtr.Zero);
RealplayHandle = YuShiOriSdk.NETDEV_RealPlay(LoginId, ref stPreviewInfo, null, IntPtr.Zero);
if (RealplayHandle == IntPtr.Zero) BuildException();
}
private void StartPlayLinux()
{
YuShiOriSdk.NETDEV_PREVIEWINFO_S stPreviewInfo = new()
{
hPlayWnd = Hwnd,
dwChannelID = Channel,
dwStreamType = 0, // YuShiOriSdk.NETDEV_LIVE_STREAM_INDEX_E
dwLinkMode = 1, // YuShiOriSdk.NETDEV_PROTOCAL_E
dwFluency = 0, // YuShiOriSdk.NETDEV_PICTURE_FLUENCY_E
};
RealplayHandle = YuShiOriSdk.NETDEV_RealPlay(LoginId, ref stPreviewInfo, null, IntPtr.Zero);
if (RealplayHandle == IntPtr.Zero) BuildException();
}
public override void StopPlay()
{
if (!IsPlaying()) return;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) StopPlayWindows();
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) StopPlayLinux();
Hwnd = IntPtr.Zero;
}
private void StopPlayWindows()
{
int ret = YuShiOriSdk.NETDEV_StopRealPlay(RealplayHandle);
RealplayHandle = IntPtr.Zero;
if (ret == YuShiOriSdk.FALSE) BuildException();
}
private void StopPlayLinux()
{
int ret = YuShiOriSdk.NETDEV_StopRealPlay(RealplayHandle);
RealplayHandle = IntPtr.Zero;
RealDataCallBack = null;
if (ret == YuShiOriSdk.FALSE) BuildException();
}
public YuShiOriSdk.RealDataCallBack? RealDataCallBack { get; set; }
private void DefaultRealDataCallBack(IntPtr lpPlayHandle, IntPtr pucBuffer, uint dwBufSize, uint dwMediaDataType, IntPtr lpUserParam)
{
if (RealplayPort < 0 || dwBufSize <= 0) return;
Console.WriteLine($"{lpPlayHandle},{pucBuffer},{dwBufSize},{dwMediaDataType},{lpUserParam}");
}
public override bool IsPlaying()
{
return RealplayHandle != IntPtr.Zero;

94
EC.Util/Common/ReflectUtil.cs

@ -0,0 +1,94 @@
using System.Reflection;
namespace EC.Util.Common;
public class ReflectUtil
{
private static readonly BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
public static bool ContainProperty(object instance, string propertyName)
{
if (instance == null || string.IsNullOrEmpty(propertyName)) return false;
PropertyInfo? property = instance.GetType()?.GetProperty(propertyName, bindingAttr);
return property != null;
}
public static T? GetProperty<T>(object instance, string propertyName)
{
if (instance == null || string.IsNullOrEmpty(propertyName)) return default;
PropertyInfo? property = instance.GetType()?.GetProperty(propertyName, bindingAttr);
try
{
return (T?)property?.GetValue(instance, null);
}
catch (Exception)
{
return default;
}
}
public static bool GetProperty<T>(object instance, string propertyName, out T? val)
{
val = GetProperty<T>(instance, propertyName);
return val != null;
}
public static bool ContainField(object instance, string propertyName)
{
if (instance == null || string.IsNullOrEmpty(propertyName)) return false;
FieldInfo? field = instance.GetType()?.GetField(propertyName, bindingAttr);
return field != null;
}
public static T? GetField<T>(object instance, string propertyName)
{
if (instance == null || string.IsNullOrEmpty(propertyName)) return default;
FieldInfo? field = instance.GetType()?.GetField(propertyName, bindingAttr);
try
{
return (T?)field?.GetValue(instance);
}
catch (Exception)
{
return default;
}
}
public static bool GetField<T>(object instance, string propertyName, out T? val)
{
val = GetField<T>(instance, propertyName);
return val != null;
}
public static void SetField<T>(object instance, string propertyName, T? val)
{
if (instance == null || string.IsNullOrEmpty(propertyName)) return;
FieldInfo? field = instance.GetType()?.GetField(propertyName, bindingAttr);
try
{
field?.SetValue(instance, val);
}
catch (Exception)
{
}
}
public static MethodInfo? GetMethod(object instance, string name)
{
MethodInfo? method = instance.GetType().GetMethod(name);
return method;
}
public static T? RunMethod<T>(object instance, string name, object?[]? parameters)
{
try
{
MethodInfo? method = instance.GetType().GetMethod(name);
return (T?)method?.Invoke(instance, parameters);
}
catch (Exception)
{
return default;
}
}
}

12
EC.Util/Common/SystemUtil.cs

@ -1,12 +0,0 @@
using System.Runtime.InteropServices;
namespace EC.Util.Common;
public static class SystemUtil
{
[DllImport("Kernel32")]
public static extern void AllocConsole();
[DllImport("Kernel32")]
public static extern void FreeConsole();
}

1
EC.Util/EC.Util.csproj

@ -4,6 +4,7 @@
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>

155
EC.Util/Platform/LinuxUtil.cs

@ -0,0 +1,155 @@
using System.Runtime.InteropServices;
namespace EC.Util.Platform;
public static class LinuxUtil
{
#region const
private const string libX11 = "libX11.so.6";
private const string libX11Randr = "libXrandr.so.2";
private const string libX11Ext = "libXext.so.6";
private const string libXInput = "libXi.so.6";
private const string libXCursor = "libXcursor.so.1";
private enum PropertyMode
{
Replace = 0,
Prepend = 1,
Append = 2
}
[Flags]
private enum MotifFlags
{
Functions = 1,
Decorations = 2,
InputMode = 4,
Status = 8
}
[Flags]
private enum MotifFunctions
{
All = 0x01,
Resize = 0x02,
Move = 0x04,
Minimize = 0x08,
Maximize = 0x10,
Close = 0x20
}
[Flags]
private enum MotifDecorations
{
All = 0x01,
Border = 0x02,
ResizeH = 0x04,
Title = 0x08,
Menu = 0x10,
Minimize = 0x20,
Maximize = 0x40,
}
[Flags]
private enum MotifInputMode
{
Modeless = 0,
ApplicationModal = 1,
SystemModal = 2,
FullApplicationModal = 3
}
#endregion const
#region struct
[StructLayout(LayoutKind.Sequential)]
private struct MotifWmHints
{
public IntPtr flags;
public IntPtr functions;
public IntPtr decorations;
public IntPtr input_mode;
public IntPtr status;
public override string ToString()
{
return string.Format("MotifWmHints <flags={0}, functions={1}, decorations={2}, input_mode={3}, status={4}", (MotifFlags)flags.ToInt32(), (MotifFunctions)functions.ToInt32(), (MotifDecorations)decorations.ToInt32(), (MotifInputMode)input_mode.ToInt32(), status.ToInt32());
}
}
[StructLayout(LayoutKind.Sequential)]
private struct XSizeHints
{
private IntPtr flags;
private int x;
private int y;
private int width;
private int height;
private int min_width;
private int min_height;
private int max_width;
private int max_height;
private int width_inc;
private int height_inc;
private int min_aspect_x;
private int min_aspect_y;
private int max_aspect_x;
private int max_aspect_y;
private int base_width;
private int base_height;
private int win_gravity;
}
[Flags]
private enum XSizeHintsFlags
{
USPosition = (1 << 0),
USSize = (1 << 1),
PPosition = (1 << 2),
PSize = (1 << 3),
PMinSize = (1 << 4),
PMaxSize = (1 << 5),
PResizeInc = (1 << 6),
PAspect = (1 << 7),
PAllHints = (PPosition | PSize | PMinSize | PMaxSize | PResizeInc | PAspect),
PBaseSize = (1 << 8),
PWinGravity = (1 << 9),
}
#endregion struct
#region lib
[DllImport(libX11, CharSet = CharSet.Unicode)]
private static extern IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
[DllImport(libX11)]
private static extern int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type,
int format, PropertyMode mode, ref MotifWmHints data, int nelements);
[DllImport(libX11)]
private static extern void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
#endregion lib
#region cmd
public static void DisableMinMaximizeButton(IntPtr display, IntPtr handle, IntPtr atom)
{
MotifDecorations decorations = MotifDecorations.Title | MotifDecorations.Border;
MotifFunctions functions = MotifFunctions.Move | MotifFunctions.Close;
MotifWmHints hints = new()
{
flags = (nint)(MotifFlags.Decorations | MotifFlags.Functions),
decorations = (nint)decorations,
functions = (nint)functions,
input_mode = 0,
status = 0,
};
int result = XChangeProperty(display, handle, atom, atom, 32, PropertyMode.Replace, ref hints, 5);
}
#endregion cmd
}

5
EC.Util/Platform/SystemUtil.cs

@ -0,0 +1,5 @@
namespace EC.Util.Platform;
public class SystemUtil
{
}

96
EC.Util/Platform/WinUtil.cs

@ -0,0 +1,96 @@
using System.Runtime.InteropServices;
namespace EC.Util.Platform;
public class WinUtil
{
#region const
private const int GWL_STYLE = -16;
private const int WS_MAXIMIZEBOX = 0x10000;
private const int WS_MINIMIZEBOX = 0x20000;
private const int WS_SYSMENU = 0x80000;
private const int SWP_NOSIZE = 0x0001;
private const int SWP_NOMOVE = 0x0002;
private const int SWP_NOZORDER = 0x0004;
private const int SWP_FRAMECHANGED = 0x0020;
#endregion const
#region lib
[DllImport("Kernel32")]
public static extern void AllocConsole();
[DllImport("Kernel32")]
public static extern void FreeConsole();
[DllImport("user32", EntryPoint = "GetWindowLong", CharSet = CharSet.Auto)]
private static extern int GetWindowLong32(IntPtr hWnd, int nIndex);
[DllImport("user32", EntryPoint = "SetWindowLong", CharSet = CharSet.Auto)]
private static extern int SetWindowLong32(IntPtr hwnd, int index, int value);
[DllImport("user32")]
private static extern int GetWindowLongPtr(IntPtr hwnd, int index);
[DllImport("user32")]
private static extern int SetWindowLongPtr(IntPtr hwnd, int index, int value);
[DllImport("user32")]
private static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
#endregion lib
#region cmd
public static void DisableMinimizeButton(IntPtr handle)
{
if (IntPtr.Size == 4)
{
int currentStyle = GetWindowLong32(handle, GWL_STYLE);
_ = SetWindowLong32(handle, GWL_STYLE, (currentStyle & ~WS_MINIMIZEBOX));
}
else
{
int currentStyle = GetWindowLongPtr(handle, GWL_STYLE);
_ = SetWindowLongPtr(handle, GWL_STYLE, (currentStyle & ~WS_MINIMIZEBOX));
}
//call SetWindowPos to make sure the SetWindowLongPtr take effect according to MSDN
SetWindowPos(handle, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
}
public static void DisableMaximizeButton(IntPtr handle)
{
if (IntPtr.Size == 4)
{
int currentStyle = GetWindowLong32(handle, GWL_STYLE);
_ = SetWindowLong32(handle, GWL_STYLE, (currentStyle & ~WS_MAXIMIZEBOX));
}
else
{
int currentStyle = GetWindowLongPtr(handle, GWL_STYLE);
_ = SetWindowLongPtr(handle, GWL_STYLE, (currentStyle & ~WS_MAXIMIZEBOX));
}
//call SetWindowPos to make sure the SetWindowLongPtr take effect according to MSDN
SetWindowPos(handle, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
}
public static void DisableMinMaximizeButton(IntPtr handle)
{
if (IntPtr.Size == 4)
{
int currentStyle = GetWindowLong32(handle, GWL_STYLE);
_ = SetWindowLong32(handle, GWL_STYLE, (currentStyle & ~WS_MINIMIZEBOX & ~WS_MAXIMIZEBOX));
}
else
{
int currentStyle = GetWindowLongPtr(handle, GWL_STYLE);
_ = SetWindowLongPtr(handle, GWL_STYLE, (currentStyle & ~WS_MINIMIZEBOX & ~WS_MAXIMIZEBOX));
}
//call SetWindowPos to make sure the SetWindowLongPtr take effect according to MSDN
SetWindowPos(handle, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
}
#endregion cmd
}

BIN
EC.Util/libs/cameraSdks.zip

Binary file not shown.

2
JiLinApp.Docking/Alarm/AlarmCodeHelper.cs

@ -29,7 +29,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)

17
JiLinApp.Docking/FenceAlarm/Service/UdpServer.cs

@ -98,14 +98,15 @@ public class UdpServer
IPEndPoint remoteIpep = new(IPAddress.Any, 0);
while (Worker != null && !Worker.CancellationPending)
{
try
{
byte[] bytRecv = RecvUdp.Receive(ref remoteIpep);
RaiseDatagramReceived(remoteIpep, bytRecv);
}
catch
{
}
byte[] bytRecv = RecvUdp.Receive(ref remoteIpep);
RaiseDatagramReceived(remoteIpep, bytRecv);
//try
//{
//}
//catch
//{
// throw;
//}
}
}

6
JiLinApp.Docking/Ptz/PtzCmd.cs

@ -274,9 +274,9 @@ public class PtzCameraCmd
sdk.PtzMove((int)DaHuaOriSdk.EM_EXTPTZ_ControlType.RIGHTDOWN, stop, speed);
break;
case PtzCmdType.AutoMove:
sdk.PtzMove((int)DaHuaOriSdk.EM_EXTPTZ_ControlType.STARTPANCRUISE, stop, speed);
break;
//case PtzCmdType.AutoMove:
// sdk.PtzMove((int)DaHuaOriSdk.EM_EXTPTZ_ControlType.STARTPANCRUISE, stop, speed);
// break;
case PtzCmdType.ZoomIn:
sdk.PtzMove((int)DaHuaOriSdk.EM_EXTPTZ_ControlType.ZOOM_ADD, stop, speed);

6
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<int, SensorState> SensorDict { get; } = new();
public int SensorTotal

74
JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs

@ -112,6 +112,9 @@ public class AsyncTcpServer : IDisposable
{
Listener.Stop();
}
catch
{
}
finally
{
foreach (var client in Clients.Values)
@ -179,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)
@ -220,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)
@ -243,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
@ -270,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);
}
@ -320,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);
}
/// <summary>
@ -332,7 +330,6 @@ public class AsyncTcpServer : IDisposable
/// <param name="datagram">报文</param>
public void SendToAll(string datagram)
{
if (!IsRunning()) return;
SendToAll(Encoding.GetBytes(datagram));
}
@ -376,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);
}
/// <summary>
@ -388,7 +382,6 @@ public class AsyncTcpServer : IDisposable
/// <param name="datagram">报文</param>
public void SendToAllAsync(string datagram)
{
if (!IsRunning()) return;
SendToAllAsync(Encoding.GetBytes(datagram));
}
@ -403,6 +396,7 @@ public class AsyncTcpServer : IDisposable
{
string clientAddr = client.ClientAddr();
RaiseClientDisconnected(clientAddr, client);
return;
}
}

92
JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs

@ -151,9 +151,12 @@ public class TcpManager
#region Analysis
private int SendCmdInterval { get; } = 6000;
private void AnalysisClientMessage(ref ClientMessage clientMsg)
{
List<byte[]> msgList = clientMsg.GetMessageList();
ClientMessage taskClientMsg = clientMsg;
foreach (byte[] msg in msgList)
{
bool vaild = msg.Length >= 19 && msg[0] == 0xAA && msg[1] == 0xAA;
@ -167,8 +170,18 @@ public class TcpManager
case 0x00:
Console.WriteLine("主机登录:{0}", clientMsg.ClientAddr);
ResponseHostLogin_10(clientMsg, mm);
RequestHostAutoUploadState_24(clientMsg);
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:
@ -204,7 +217,8 @@ public class TcpManager
case 0x17:
Console.WriteLine("主机返回传感器列表:{0}", clientMsg.ClientAddr);
for (int j = 2; j < mm.Data.Length; j++)
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;
@ -238,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;
@ -396,6 +434,7 @@ public class TcpManager
Request = msg
};
SendRequestTry(ref request);
Thread.Sleep(500);
}
return true;
}
@ -432,7 +471,7 @@ public class TcpManager
{
Request = msg
};
return SendRequestMust(ref request);
return SendRequestTry(ref request);
}
/// <summary>
@ -485,6 +524,7 @@ public class TcpManager
Request = msg
};
SendRequestTry(ref request);
Thread.Sleep(500);
}
return true;
}
@ -525,6 +565,7 @@ public class TcpManager
Request = msg
};
SendRequestTry(ref request);
Thread.Sleep(500);
}
return true;
}
@ -558,7 +599,7 @@ public class TcpManager
{
Request = msg
};
return SendRequestMust(ref request);
return SendRequestTry(ref request);
}
/// <summary>
@ -641,13 +682,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; } = 500;
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)
{
@ -676,7 +717,7 @@ public class TcpManager
if (send) break;
Thread.Sleep(SendTryInterval);
}
Console.WriteLine("Send to {0}:{1} => {2}, {3}", clientMsg.ClientIp, clientMsg.ClientPort, cmd, send);
Console.WriteLine("Send to {0}:{1} => {2}, send:{3}", clientMsg.ClientIp, clientMsg.ClientPort, cmd, send);
return send;
}
@ -684,37 +725,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;
}
@ -737,27 +770,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;
}

18
JiLinApp.Docking/config/alarmcodes.json

@ -5,6 +5,24 @@
"Type": "错误",
"Content": "接收到未定义的代码"
},
{
"Id": "1001",
"Level": "1",
"Type": "紧急",
"Content": "经线掉断报警"
},
{
"Id": "1002",
"Level": "1",
"Type": "紧急",
"Content": "纬线掉断报警"
},
{
"Id": "1003",
"Level": "1",
"Type": "紧急",
"Content": "经纬线掉断报警"
},
{
"Id": "1100",
"Level": "1",

111
JiLinApp/Components/CameraRealPlay.axaml.cs

@ -1,8 +1,10 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Platform;
using Avalonia.Threading;
using EC.Util.CameraSDK;
using EC.Util.Platform;
using JiLinApp.Core.Avalonia;
using JiLinApp.Docking.Ptz;
using System;
@ -23,6 +25,19 @@ public partial class CameraRealPlay : Window
{
InitializeComponent();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
IPlatformHandle? pfHandle = TryGetPlatformHandle();
if (pfHandle != null) WinUtil.DisableMinMaximizeButton(pfHandle.Handle);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && PlatformImpl != null)
{
IntPtr _display = ControlsUtil.GetDisplay(PlatformImpl);
IntPtr _handle = ControlsUtil.GetHandle(PlatformImpl);
IntPtr _atom = ControlsUtil.GetAtom(PlatformImpl, "_MOTIF_WM_HINTS");
LinuxUtil.DisableMinMaximizeButton(_display, _handle, _atom);
}
//°ó¶¨ÔÆ̨ÏìӦʼþ
List<Button> btnList = new();
ControlsUtil.FindChild(PtzCtrlPanel, ref btnList);
@ -52,7 +67,7 @@ public partial class CameraRealPlay : Window
CameraSdk = cameraSdk;
}
public IntPtr GetHwnd()
public IntPtr GetPlayerHwnd()
{
return player.Handle;
}
@ -74,25 +89,35 @@ public partial class CameraRealPlay : Window
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
}
if (CameraSdk is HiKSdk hikSdk)
{
if (RealplayPort < 0)
if (CameraSdk is HiKSdk hikSdk)
{
if (RealplayPort < 0)
{
int nPort = -1;
bool ret = PlayCtrlSdk.PlayM4_GetPort(ref nPort);
if (!ret) PlayCtrlSdk.BuildException(hikSdk, nPort);
RealplayPort = nPort;
}
hikSdk.RealDataCallBack = HikRealDataCallBack;
}
else if (CameraSdk is DaHuaSdk dhSdk)
{
if (RealplayPort < 0)
{
int nPort = -1;
DhPlaySdk.PLAY_GetFreePort(ref nPort);
DhPlaySdk.PLAY_SetStreamOpenMode(nPort, 0);
DhPlaySdk.PLAY_OpenStream(nPort, 0, 0, 3 * 1024 * 1024);
if (!DhPlaySdk.PLAY_Play(nPort, GetPlayerHwnd())) DhPlaySdk.BuildException(dhSdk, nPort);
RealplayPort = nPort;
}
dhSdk.RealDataCallBack = DaHuaRealDataCallBack;
}
else if (CameraSdk is YuShiSdk ysSdk)
{
int nPort = -1;
bool ret = PlayCtrlSdk.PlayM4_GetPort(ref nPort);
if (!ret) hikSdk.BuildPlayCtrlException(nPort);
RealplayPort = nPort;
}
hikSdk.RealDataCallBack = HikRealDataCallBack;
}
else if (CameraSdk is DaHuaSdk dhSdk)
{
}
else if (CameraSdk is YuShiSdk ysSdk)
{
}
CameraSdk?.StartPlay(player.Handle);
CameraSdk?.StartPlay(GetPlayerHwnd());
}
public void StopPlay()
@ -100,23 +125,29 @@ public partial class CameraRealPlay : Window
Dispatcher.UIThread.InvokeAsync(() => CameraSdk?.StopPlay());
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
}
if (CameraSdk is HiKSdk hikSdk)
{
if (RealplayPort >= 0)
if (CameraSdk is HiKSdk hikSdk)
{
if (RealplayPort >= 0)
{
PlayCtrlSdk.PlayM4_Stop(RealplayPort);
PlayCtrlSdk.PlayM4_CloseStream(RealplayPort);
PlayCtrlSdk.PlayM4_FreePort(RealplayPort);
RealplayPort = -1;
}
}
else if (CameraSdk is DaHuaSdk dhSdk)
{
if (RealplayPort >= 0)
{
DhPlaySdk.PLAY_Stop(RealplayPort);
DhPlaySdk.PLAY_CloseStream(RealplayPort);
DhPlaySdk.PLAY_ReleasePort(RealplayPort);
RealplayPort = -1;
}
}
else if (CameraSdk is YuShiSdk ysSdk)
{
PlayCtrlSdk.PlayM4_Stop(RealplayPort);
PlayCtrlSdk.PlayM4_CloseStream(RealplayPort);
PlayCtrlSdk.PlayM4_FreePort(RealplayPort);
RealplayPort = -1;
}
hikSdk.RealDataCallBack = null;
}
else if (CameraSdk is DaHuaSdk dhSdk)
{
}
else if (CameraSdk is YuShiSdk ysSdk)
{
}
}
@ -138,7 +169,7 @@ public partial class CameraRealPlay : Window
PlayCtrlSdk.PlayM4_SetStreamOpenMode(RealplayPort, 0);
PlayCtrlSdk.PlayM4_OpenStream(RealplayPort, pBuffer, dwBufSize, 2 * 1024 * 1024);
PlayCtrlSdk.PlayM4_SetDisplayBuf(RealplayPort, 5);
PlayCtrlSdk.PlayM4_Play(RealplayPort, GetHwnd());
PlayCtrlSdk.PlayM4_Play(RealplayPort, GetPlayerHwnd());
break;
case HiKOriSdk.NET_DVR_STREAMDATA:
@ -148,6 +179,20 @@ public partial class CameraRealPlay : Window
});
}
private void DaHuaRealDataCallBack(IntPtr lRealHandle, uint dwDataType, IntPtr pBuffer, uint dwBufSize, IntPtr param, IntPtr dwUser)
{
if (RealplayPort < 0 || dwBufSize <= 0) return;
Dispatcher.UIThread.Invoke(() =>
{
switch (dwDataType)
{
case 0:
DhPlaySdk.PLAY_InputData(RealplayPort, pBuffer, dwBufSize);
break;
}
});
}
#endregion Play
#region ElementEvent

103
JiLinApp/Core/Avalonia/ControlsUtil.cs

@ -1,6 +1,10 @@
using Avalonia.Controls;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Platform;
using EC.Util.Common;
using Material.Dialog;
using Material.Dialog.Icons;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
@ -9,6 +13,8 @@ namespace JiLinApp.Core.Avalonia;
public static class ControlsUtil
{
#region Controls
/// <summary>
/// 查找子控件
/// </summary>
@ -73,8 +79,8 @@ public static class ControlsUtil
if (item == null) return val;
if (item is Control)
{
if (TryGetValue(item, "Content", out object? content)) val = content?.ToString();
else if (TryGetValue(item, "Text", out string? text)) val = text;
if (ReflectUtil.GetProperty(item, "Content", out object? content)) val = content?.ToString();
else if (ReflectUtil.GetProperty(item, "Text", out string? text)) val = text;
}
else val = item.ToString();
return val ?? string.Empty;
@ -85,38 +91,17 @@ public static class ControlsUtil
var item = cbx.SelectedItem;
if (item is Control)
{
if (TryGetValue(item, "Content", out object? content)) val = content?.ToString();
else if (TryGetValue(item, "Text", out string? text)) val = text;
if (ReflectUtil.GetProperty(item, "Content", out object? content)) val = content?.ToString();
else if (ReflectUtil.GetProperty(item, "Text", out string? text)) val = text;
else val = null;
}
else val = item?.ToString();
return val != null;
}
/// <summary>
/// 利用反射来判断对象是否包含某个属性
/// </summary>
/// <param name="instance">object</param>
/// <param name="propertyName">需要判断的属性</param>
/// <returns>是否包含</returns>
private static bool ContainProperty(object instance, string propertyName)
{
if (instance == null || string.IsNullOrEmpty(propertyName)) return false;
PropertyInfo? property = instance.GetType()?.GetProperty(propertyName);
return property != null;
}
#endregion Controls
private static bool TryGetValue<T>(object instance, string propertyName, out T? val)
{
if (instance == null || string.IsNullOrEmpty(propertyName))
{
val = default;
return false;
}
PropertyInfo? property = instance.GetType()?.GetProperty(propertyName);
val = (T?)property?.GetValue(instance, null);
return val != null;
}
#region Dialog
public static async Task<DialogResult> ShowDialog(Window? window, string title = "Info", string message = "")
{
@ -147,4 +132,66 @@ public static class ControlsUtil
});
return await dialog.ShowDialog(window);
}
#endregion Dialog
#region AvaloniaLocator.Current.GetService
private static AvaloniaLocator? _locator;
private static MethodInfo? _getService;
public static T? GetService<T>()
{
if (_locator == null)
{
FieldInfo[] fieldInfos = typeof(AvaloniaLocator).GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo item in fieldInfos)
if (item.FieldType.IsAssignableFrom(typeof(AvaloniaLocator))) { _locator = (AvaloniaLocator?)item.GetValue(null); break; }
}
if (_getService == null)
{
MethodInfo[] methodInfos = typeof(AvaloniaLocator).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MethodInfo item in methodInfos) if (item.Name.Equals("GetService")) { _getService = item; break; }
}
return (T?)_getService?.Invoke(_locator, new object[] { typeof(T) });
}
#endregion AvaloniaLocator.Current.GetService
#region Avalonia.X11
private static IWindowingPlatform? Platform { get; set; }
private static object? X11 { get; set; }
private static object? Atoms { get; set; }
public static IntPtr GetHandle(IWindowImpl? platformImpl)
{
IntPtr handle = platformImpl != null ? ReflectUtil.GetField<IntPtr>(platformImpl, "_handle") : IntPtr.Zero;
return handle;
}
public static IntPtr GetDisplay(IWindowImpl platformImpl)
{
IWindowingPlatform? _platform = Platform ??= ReflectUtil.GetField<IWindowingPlatform>(platformImpl, "_platform");
if (_platform == null) return IntPtr.Zero;
IntPtr display = ReflectUtil.GetProperty<IntPtr>(_platform, "Display");
return display;
}
public static IntPtr GetAtom(IWindowImpl platformImpl, string name)
{
IWindowingPlatform? _platform = Platform ??= ReflectUtil.GetField<IWindowingPlatform>(platformImpl, "_platform");
if (_platform == null) return IntPtr.Zero;
object? _x11 = X11 ??= ReflectUtil.GetProperty<object>(_platform, "Info");
if (_x11 == null) return IntPtr.Zero;
object? _atoms = Atoms ??= ReflectUtil.GetProperty<object>(_x11, "Atoms");
if (_atoms == null) return IntPtr.Zero;
IntPtr _atom = ReflectUtil.RunMethod<IntPtr>(_atoms, "GetAtom", new object[] { name });
return _atom;
}
#endregion Avalonia.X11
}

2
JiLinApp/Pages/FenceServer/Fence.axaml.cs

@ -1,13 +1,11 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Media;
using EC.Util.Common;
using JiLinApp.Biz.TransmitAlarm;
using JiLinApp.Core;
using JiLinApp.Core.App;
using JiLinApp.Core.Avalonia;
using JiLinApp.Docking.FenceAlarm;
using Material.Dialog;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;

4
JiLinApp/Pages/Main/MainWindow.axaml.cs

@ -1,7 +1,4 @@
using Avalonia.Controls;
using JiLinApp.Pages.FenceServer;
using JiLinApp.Pages.PtzServer;
using JiLinApp.Pages.VibrateServer;
namespace JiLinApp.Pages.Main;
@ -10,5 +7,6 @@ public partial class MainWindow : Window
public MainWindow()
{
InitializeComponent();
WindowStartupLocation = WindowStartupLocation.CenterScreen;
}
}

10
JiLinApp/Pages/PtzServer/Ptz.axaml.cs

@ -288,7 +288,8 @@ public partial class Ptz : UserControl
private void ShowLiveVideo(ICameraSdk sdk)
{
if (!sdk.ConnectSuccess()) { LogUnit.Error(this, $"CameraSdk(cameraIp:{sdk.CameraInfo.Ip}) connect failure."); return; }
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);
@ -297,8 +298,7 @@ public partial class Ptz : UserControl
realPlay = new(sdk)
{
Title = $"RealPlay({sdk.CameraInfo.Name})",
CanResize = false,
ShowInTaskbar = true
ShowInTaskbar = false
};
RealPlayDict[cameraIp] = realPlay;
}
@ -331,7 +331,9 @@ public partial class Ptz : UserControl
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; }
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;

Loading…
Cancel
Save