using Serilog; using Ayay.SerilogLogs; namespace SHH.CameraSdk.HikFeatures; /// /// [海康功能组件] 预置点管理实现 /// 适配说明:使用 NET_DVR_PTZPreset_Other 接口 /// public class HikPresetProvider : IPresetFeature { private readonly IHikContext _context; #region --- 海康 PTZ 预置点命令常量 --- private const uint SET_PRESET = 8; // 设置预置点 private const uint CLE_PRESET = 9; // 清除预置点 private const uint GOTO_PRESET = 39; // 转到预置点 #endregion public HikPresetProvider(IHikContext context) { _context = context; } /// 跳转到指定预置点 public async Task GotoPresetAsync(int presetIndex) { await ExecutePresetAction(presetIndex, GOTO_PRESET, "调用"); } /// 将当前位置保存为预置点 public async Task SetPresetAsync(int presetIndex) { await ExecutePresetAction(presetIndex, SET_PRESET, "保存"); } /// 删除指定的预置点 public async Task RemovePresetAsync(int presetIndex) { await ExecutePresetAction(presetIndex, CLE_PRESET, "删除"); } /// 统一执行海康预置点 SDK 调用 private async Task ExecutePresetAction(int index, uint command, string actionName) { int userId = _context.GetUserId(); if (userId < 0) return; // 位置是从 1 开始, 调用 0 会导致设备重启 if (index == 0) return; // 海康工业相机通道号通常为 1 int channel = 1; await Task.Run(() => { // Optimized: [原因] 使用 _Other 接口确保在单机多路并发下通道句柄准确 bool result = HikNativeMethods.NET_DVR_PTZPreset_Other( userId, channel, command, (uint)index ); if (!result) { uint err = HikNativeMethods.NET_DVR_GetLastError(); Log.ForContext("SourceContext", LogModules.HikVisionSdk) .Warning("[SDK] Hik 预置点{Action}失败. Index: {Index}, Error: {Error}", actionName, index, err); } else { Log.ForContext("SourceContext", LogModules.HikVisionSdk) .Debug("[SDK] Hik 预置点{Action}成功. Index: {Index}", actionName, index); } }); } }