using System.Runtime.InteropServices; namespace EC.Util.CameraSDK; public class HiKSDK : ICameraSDK { #region Fields private int LoginId { get; set; } = -1; private int RealplayHandle { get; set; } = -1; #endregion Fields public HiKSDK(CameraInfo cameraInfo) : base(cameraInfo) { } #region Base Method public override bool Init() { bool ret = ConnectSuccess(); if (ret) return true; HiKOriSDK.NET_DVR_DEVICEINFO_V30 deviceInfo = new(); LoginId = HiKOriSDK.NET_DVR_Login_V30(CameraInfo.Ip, CameraInfo.Port, CameraInfo.UserName, CameraInfo.Password, ref deviceInfo); ret = ConnectSuccess(); return ret; } public override bool Destory() { bool ret = ConnectSuccess(); if (!ret) return true; ret = HiKOriSDK.NET_DVR_Logout(LoginId); if (ret) LoginId = -1; return ret; } public override bool ConnectSuccess() { return LoginId >= 0; } internal override void BuildException() { uint errCode = HiKOriSDK.NET_DVR_GetLastError(); if (errCode == 0) return; throw CameraException.New(CameraInfo, (int)errCode); } #endregion Base Method #region Ptz Method private static class GPIParams { public static int Size { get; private set; } public static Type Type { get; private set; } static GPIParams() { HiKOriSDK.NET_DVR_PTZPOS ptzPos = new(); Size = Marshal.SizeOf(ptzPos); Type = ptzPos.GetType(); } } public override PtzInfo GetPtzInfo() { bool ret = ConnectSuccess(); if (!ret) return PtzInfo.Default; HiKOriSDK.NET_DVR_PTZPOS entity = new(); int dwSize = GPIParams.Size; uint dwReturned = 0; IntPtr ptrBuf = Marshal.AllocHGlobal(dwSize); Marshal.StructureToPtr(entity, ptrBuf, true); try { ret = HiKOriSDK.NET_DVR_GetDVRConfig(LoginId, HiKOriSDK.NET_DVR_GET_PTZPOS, 0, ptrBuf, (uint)dwSize, ref dwReturned); if (!ret) { BuildException(); return PtzInfo.Default; } object? objBuf = Marshal.PtrToStructure(ptrBuf, GPIParams.Type); if (objBuf == null) return PtzInfo.Default; entity = (HiKOriSDK.NET_DVR_PTZPOS)objBuf; return PtzInfo.New(entity.wPanPos, entity.wTiltPos, entity.wZoomPos); } finally { Marshal.FreeHGlobal(ptrBuf); } } public override bool TryGetPtzInfo(out PtzInfo ptzInfo) { bool ret = ConnectSuccess(); if (!ret) { ptzInfo = PtzInfo.Default; return false; } HiKOriSDK.NET_DVR_PTZPOS entity = new(); int dwSize = GPIParams.Size; uint dwReturned = 0; IntPtr ptrBuf = Marshal.AllocHGlobal(dwSize); Marshal.StructureToPtr(entity, ptrBuf, true); try { ret = HiKOriSDK.NET_DVR_GetDVRConfig(LoginId, HiKOriSDK.NET_DVR_GET_PTZPOS, 0, ptrBuf, (uint)dwSize, ref dwReturned); if (!ret) { BuildException(); ptzInfo = PtzInfo.Default; return false; } object? objBuf = Marshal.PtrToStructure(ptrBuf, GPIParams.Type); if (objBuf == null) { ptzInfo = PtzInfo.Default; return false; } entity = (HiKOriSDK.NET_DVR_PTZPOS)objBuf; ptzInfo = PtzInfo.New(entity.wPanPos, entity.wTiltPos, entity.wZoomPos); return true; } finally { Marshal.FreeHGlobal(ptrBuf); } } public override bool PtzMove(int cmd, int stop, int speed) { if (!ConnectSuccess()) return false; int lChannel = 1; bool flag = HiKOriSDK.NET_DVR_PTZControlWithSpeed_Other(LoginId, lChannel, (uint)cmd, (uint)stop, (uint)speed); if (flag) BuildException(); return flag; } public override bool PtzPreset(int cmd, int presetId) { if (!ConnectSuccess()) return false; int lChannel = 1; bool flag = HiKOriSDK.NET_DVR_PTZPreset_Other(LoginId, lChannel, (uint)cmd, (uint)presetId); if (flag) BuildException(); return flag; } #endregion Ptz Method #region Video Method public override void StartPlay(IntPtr hwnd) { if (!ConnectSuccess() || IsPlaying()) return; HiKOriSDK.NET_DVR_PREVIEWINFO previewInfo = new() { hPlayWnd = hwnd, //预览窗口 lChannel = 1, //预览的设备通道 dwStreamType = 0, //码流类型:0-主码流,1-子码流,2-码流3,3-码流4,以此类推 dwLinkMode = 0, //连接方式:0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP bBlocked = true, //0- 非阻塞取流,1- 阻塞取流 dwDisplayBufNum = 1, //播放库播放缓冲区最大缓冲帧数 byProtoType = 0, byPreviewMode = 0 }; IntPtr pUser = new(); //用户数据 RealplayHandle = HiKOriSDK.NET_DVR_RealPlay_V40(LoginId, ref previewInfo, null, pUser); if (RealplayHandle < 0) BuildException(); } public override void StopPlay() { if (!IsPlaying()) return; bool flag = HiKOriSDK.NET_DVR_StopRealPlay(RealplayHandle); RealplayHandle = -1; if (!flag) BuildException(); } public override bool IsPlaying() { return RealplayHandle >= 0; } #endregion Video Method }