using System.Runtime.InteropServices; using Serilog; using Ayay.SerilogLogs; namespace SHH.CameraSdk.DahuaFeatures; /// /// [大华功能组件] 时间同步实现 /// 参照原代码逻辑重构,实现 EM_DEV_CFG_TYPE.TIMECFG 配置下发 /// public class DahuaTimeSyncProvider : ITimeSyncFeature { private readonly IDahuaContext _context; public DahuaTimeSyncProvider(IDahuaContext context) { _context = context; } /// /// 获取设备当前时间 /// public async Task GetTimeAsync() { IntPtr loginId = _context.GetUserId(); if (loginId == IntPtr.Zero) throw new InvalidOperationException("大华设备未登录"); return await Task.Run(() => { NET_TIME time = new NET_TIME(); uint retLen = 0; int nSize = Marshal.SizeOf(typeof(NET_TIME)); IntPtr inPtr = Marshal.AllocHGlobal(nSize); try { // Optimized: [原因] 沿用原代码的 GetDevConfig 逻辑与 TIMECFG 指令 Marshal.StructureToPtr(time, inPtr, true); bool result = NETClient.GetDevConfig(loginId, EM_DEV_CFG_TYPE.TIMECFG, -1, inPtr, (uint)nSize, ref retLen, 5000); if (result && retLen == (uint)nSize) { time = (NET_TIME)Marshal.PtrToStructure(inPtr, typeof(NET_TIME)); // 使用你现有的 ToDateTime() 扩展方法 return time.ToDateTime(); } else { string err = NETClient.GetLastError(); throw new Exception($"[SDK] Dahua 获取时间失败: {err}"); } } finally { Marshal.FreeHGlobal(inPtr); } }); } /// /// 设置设备时间 (校时) /// public async Task SetTimeAsync(DateTime targetTime) { IntPtr loginId = _context.GetUserId(); if (loginId == IntPtr.Zero) throw new InvalidOperationException("大华设备未登录"); await Task.Run(() => { // Modified: [原因] 使用你原有的 FromDateTime 静态方法进行结构体转换 NET_TIME time = NET_TIME.FromDateTime(targetTime); int nSize = Marshal.SizeOf(typeof(NET_TIME)); IntPtr inPtr = Marshal.AllocHGlobal(nSize); try { Marshal.StructureToPtr(time, inPtr, true); // Optimized: [原因] 沿用原代码的 SetDevConfig 逻辑 bool result = NETClient.SetDevConfig(loginId, EM_DEV_CFG_TYPE.TIMECFG, -1, inPtr, (uint)nSize, 5000); if (result) { Log.ForContext("SourceContext", LogModules.DaHuaSdk) .Information("[SDK] Dahua 校时成功 => {Time}", targetTime.ToString("yyyy-MM-dd HH:mm:ss")); } else { string err = NETClient.GetLastError(); Log.ForContext("SourceContext", LogModules.DaHuaSdk) .Error("[SDK] Dahua 校时指令失败. Error: {Error}", err); throw new Exception($"大华校时失败: {err}"); } } finally { Marshal.FreeHGlobal(inPtr); } }); } }