using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OrpaonVision.Core.Results;
using OrpaonVision.SiteApp.Runtime.Contracts;
using OrpaonVision.SiteApp.Runtime.Services;
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using MvCamCtrl.NET;
namespace OrpaonVision.SiteApp.Runtime.Services;
///
/// 海康相机服务实现(支持真实和模拟模式)。
///
public sealed class RealHikCameraService : IHikCameraService, IDisposable
{
private readonly ILogger _logger;
private readonly HikCameraOptions _options;
private readonly object _lockObject = new();
private HikCameraDevice? _currentDevice;
private bool _isConnected;
private bool _isGrabbing;
private Timer? _frameTimer;
private readonly ConcurrentQueue _frameQueue = new();
private MyCamera? _camera;
private bool _sdkInitialized;
private IntPtr _deviceHandle = IntPtr.Zero;
private MyCamera.MV_CC_DEVICE_INFO? _deviceInfo;
private int _reconnectAttempts = 0;
///
/// 构造函数。
///
public RealHikCameraService(ILogger logger, IOptions options)
{
_logger = logger;
_options = options.Value;
_logger.LogInformation("海康相机服务已初始化(模式: {RunMode})", _options.RunMode);
if (_options.RunMode == "Real")
{
InitializeSdk();
}
}
///
public bool IsConnected => _isConnected;
///
public HikCameraDevice? CurrentDevice => _currentDevice;
///
public event Action? OnImageReceived;
///
public event Action? OnConnectionStateChanged;
///
/// 初始化海康SDK。
///
private void InitializeSdk()
{
try
{
if (_sdkInitialized)
{
return;
}
_logger.LogInformation("正在初始化海康SDK...");
// 初始化海康SDK
var result = MyCamera.MV_CC_Initialize_NET();
if (result != MyCamera.MV_OK)
{
_logger.LogError("海康SDK初始化失败,错误代码: {ErrorCode}", result);
return;
}
_camera = new MyCamera();
_sdkInitialized = true;
_logger.LogInformation("海康SDK初始化成功");
}
catch (Exception ex)
{
_logger.LogError(ex, "初始化海康SDK失败,将回退到模拟模式");
}
}
///
public Result> EnumerateDevices()
{
try
{
_logger.LogInformation("正在枚举海康相机设备...");
if (_options.RunMode != "Real" || !_sdkInitialized || _camera == null)
{
_logger.LogWarning("真实模式未启用或SDK未初始化,返回模拟设备");
return GetMockDevices();
}
// 使用海康SDK枚举设备
var deviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
var result = _camera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref deviceList);
if (result != MyCamera.MV_OK)
{
_logger.LogError("枚举海康设备失败,错误代码: {ErrorCode}", result);
return GetMockDevices();
}
var devices = new List();
for (uint i = 0; i < deviceList.nDeviceNum; i++)
{
var deviceInfo = deviceList.MvDeviceInfo[i];
var device = new HikCameraDevice
{
SerialNumber = Marshal.PtrToStringAnsi(deviceInfo.SpecialInfo.stGigEInfo.chSerialNumber) ?? $"HK_DEVICE_{i}",
DeviceName = Marshal.PtrToStringAnsi(deviceInfo.SpecialInfo.stGigEInfo.chUserDefinedName) ?? $"海康相机_{i}",
IpAddress = Marshal.PtrToStringAnsi(deviceInfo.SpecialInfo.stGigEInfo.nCurrentIp) ?? "Unknown",
MacAddress = Marshal.PtrToStringAnsi(deviceInfo.SpecialInfo.stGigEInfo.nCurrentMac) ?? "Unknown",
IsConnected = true
};
devices.Add(device);
_logger.LogInformation("发现海康设备: {DeviceName} ({SerialNumber})", device.DeviceName, device.SerialNumber);
}
if (devices.Count == 0)
{
_logger.LogInformation("未发现海康设备,返回模拟设备");
return GetMockDevices();
}
_logger.LogInformation("成功枚举到 {Count} 个海康设备", devices.Count);
return Result.Success>(devices);
}
catch (Exception ex)
{
_logger.LogError(ex, "枚举海康设备失败");
return Result.Fail>("HIK_ENUM_FAILED", "枚举海康设备失败");
}
}
///
public Result ConnectToDevice(HikCameraDevice device)
{
if (device == null)
{
return Result.Fail("HIK_CAMERA_DEVICE_NULL", "相机设备不能为空。");
}
lock (_lockObject)
{
try
{
if (_isConnected)
{
return Result.Fail("HIK_CAMERA_ALREADY_CONNECTED", "相机已连接,请先断开。");
}
_logger.LogInformation("正在连接相机设备: {SerialNumber}", device.SerialNumber);
if (_options.RunMode != "Real" || !_sdkInitialized)
{
_logger.LogWarning("真实模式未启用或SDK未初始化,使用模拟连接");
return MockConnect(device);
}
// 查找目标设备信息
MyCamera.MV_CC_DEVICE_INFO targetDeviceInfo = default;
bool foundDevice = false;
var deviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
var enumResult = _camera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref deviceList);
if (enumResult == MyCamera.MV_OK)
{
for (uint i = 0; i < deviceList.nDeviceNum; i++)
{
var deviceInfo = deviceList.MvDeviceInfo[i];
var serialNumber = Marshal.PtrToStringAnsi(deviceInfo.SpecialInfo.stGigEInfo.chSerialNumber) ?? "";
var ipAddress = Marshal.PtrToStringAnsi(deviceInfo.SpecialInfo.stGigEInfo.nCurrentIp) ?? "";
if (serialNumber.Equals(device.SerialNumber, StringComparison.OrdinalIgnoreCase) ||
ipAddress.Equals(device.IpAddress, StringComparison.OrdinalIgnoreCase))
{
targetDeviceInfo = deviceInfo;
foundDevice = true;
break;
}
}
}
if (!foundDevice)
{
_logger.LogError("未找到指定的相机设备: {SerialNumber}", device.SerialNumber);
return Result.Fail("HIK_DEVICE_NOT_FOUND", $"未找到指定的相机设备: {device.SerialNumber}");
}
// 创建设备句柄
var createResult = _camera.MV_CC_CreateHandle_NET(ref targetDeviceInfo, out _deviceHandle);
if (createResult != MyCamera.MV_OK)
{
_logger.LogError("创建相机句柄失败,错误代码: {ErrorCode}", createResult);
return Result.Fail("HIK_CREATE_HANDLE_FAILED", $"创建相机句柄失败,错误代码: {createResult}");
}
// 打开设备
var openResult = _camera.MV_CC_OpenDevice_NET(_deviceHandle, MyCamera.MV_ACCESS_Exclusive, 0);
if (openResult != MyCamera.MV_OK)
{
_logger.LogError("打开相机设备失败,错误代码: {ErrorCode}", openResult);
_camera.MV_CC_DestroyHandle_NET(_deviceHandle);
_deviceHandle = IntPtr.Zero;
return Result.Fail("HIK_OPEN_DEVICE_FAILED", $"打开相机设备失败,错误代码: {openResult}");
}
// 获取设备信息
_deviceInfo = targetDeviceInfo;
var deviceInfoResult = GetDeviceInfo();
if (!deviceInfoResult.Succeeded)
{
_camera.MV_CC_CloseDevice_NET(_deviceHandle);
_camera.MV_CC_DestroyHandle_NET(_deviceHandle);
_deviceHandle = IntPtr.Zero;
_deviceInfo = null;
return Result.Fail(deviceInfoResult.Code, deviceInfoResult.Message, deviceInfoResult.Errors.ToArray());
}
_currentDevice = new HikCameraDevice
{
SerialNumber = device.SerialNumber,
DeviceName = device.DeviceName,
IpAddress = device.IpAddress,
SubnetMask = device.SubnetMask,
DefaultGateway = device.DefaultGateway,
MacAddress = device.MacAddress,
FirmwareVersion = device.FirmwareVersion,
IsConnected = true,
ConnectedAt = DateTime.UtcNow
};
_isConnected = true;
_reconnectAttempts = 0;
_logger.LogInformation("相机连接成功: {SerialNumber}", device.SerialNumber);
OnConnectionStateChanged?.Invoke(true, $"已连接到 {device.DeviceName}");
return Result.Success(message: $"相机 {device.DeviceName} 连接成功。");
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "连接相机失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "HIK_CAMERA_CONNECT_FAILED", "连接相机失败。", traceId);
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
}
///
public Result ConnectToDevice(string serialNumberOrIp)
{
var devicesResult = EnumerateDevices();
if (!devicesResult.Succeeded)
{
return Result.Fail(devicesResult.Code, devicesResult.Message, devicesResult.Errors.ToArray());
}
var targetDevice = devicesResult.Data.FirstOrDefault(d =>
d.SerialNumber.Equals(serialNumberOrIp, StringComparison.OrdinalIgnoreCase) ||
d.IpAddress.Equals(serialNumberOrIp, StringComparison.OrdinalIgnoreCase));
if (targetDevice == null)
{
return Result.Fail("HIK_CAMERA_NOT_FOUND", $"未找到序列号或IP为 {serialNumberOrIp} 的相机设备。");
}
return ConnectToDevice(targetDevice);
}
///
public Result Disconnect()
{
lock (_lockObject)
{
try
{
if (!_isConnected)
{
return Result.Success(message: "相机未连接。");
}
_logger.LogInformation("正在断开相机连接...");
// 停止采集
if (_isGrabbing)
{
StopGrabbing();
}
// 实际实现需要调用海康SDK的MV_CC_CloseDevice、MV_CC_DestroyHandle等函数
if (_options.RunMode == "Real" && _deviceHandle != IntPtr.Zero && _camera != null)
{
// 关闭设备
var closeResult = _camera.MV_CC_CloseDevice_NET(_deviceHandle);
if (closeResult != MyCamera.MV_OK)
{
_logger.LogWarning("关闭相机设备失败,错误代码: {ErrorCode}", closeResult);
}
// 销毁句柄
var destroyResult = _camera.MV_CC_DestroyHandle_NET(_deviceHandle);
if (destroyResult != MyCamera.MV_OK)
{
_logger.LogWarning("销毁相机句柄失败,错误代码: {ErrorCode}", destroyResult);
}
_deviceHandle = IntPtr.Zero;
_deviceInfo = null;
}
Thread.Sleep(100);
var deviceName = _currentDevice?.DeviceName ?? "未知设备";
_currentDevice = null;
_isConnected = false;
_logger.LogInformation("相机断开连接成功");
OnConnectionStateChanged?.Invoke(false, $"已断开与 {deviceName} 的连接");
return Result.Success(message: "相机断开连接成功。");
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "断开相机连接失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "HIK_CAMERA_DISCONNECT_FAILED", "断开相机连接失败。", traceId);
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
}
///
public Result SetCameraParameters(int width, int height, string pixelFormat, int triggerMode = 0)
{
lock (_lockObject)
{
try
{
if (!_isConnected)
{
return Result.Fail("HIK_CAMERA_NOT_CONNECTED", "相机未连接。");
}
_logger.LogInformation("正在设置相机参数: {Width}x{Height}, {PixelFormat}, TriggerMode: {TriggerMode}",
width, height, pixelFormat, triggerMode);
if (_options.RunMode != "Real" || _deviceHandle == IntPtr.Zero || _camera == null)
{
_logger.LogDebug("模拟模式:设置相机参数");
return Result.Success(message: "相机参数设置成功(模拟模式)。");
}
// 设置图像宽度
var widthResult = _camera.MV_CC_SetIntValue_NET(_deviceHandle, "Width", width);
if (widthResult != MyCamera.MV_OK)
{
_logger.LogWarning("设置图像宽度失败,错误代码: {ErrorCode}", widthResult);
}
// 设置图像高度
var heightResult = _camera.MV_CC_SetIntValue_NET(_deviceHandle, "Height", height);
if (heightResult != MyCamera.MV_OK)
{
_logger.LogWarning("设置图像高度失败,错误代码: {ErrorCode}", heightResult);
}
// 设置像素格式
var pixelFormatResult = _camera.MV_CC_SetEnumValue_NET(_deviceHandle, "PixelFormat", GetPixelFormatValue(pixelFormat));
if (pixelFormatResult != MyCamera.MV_OK)
{
_logger.LogWarning("设置像素格式失败,错误代码: {ErrorCode}", pixelFormatResult);
}
// 设置触发模式
var triggerModeResult = _camera.MV_CC_SetEnumValue_NET(_deviceHandle, "TriggerMode", triggerMode);
if (triggerModeResult != MyCamera.MV_OK)
{
_logger.LogWarning("设置触发模式失败,错误代码: {ErrorCode}", triggerModeResult);
}
Thread.Sleep(100); // 等待参数生效
_logger.LogInformation("相机参数设置成功");
return Result.Success(message: "相机参数设置成功。");
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "设置相机参数失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "HIK_CAMERA_SET_PARAMS_FAILED", "设置相机参数失败。", traceId);
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
}
///
public Result StartGrabbing()
{
lock (_lockObject)
{
try
{
if (!_isConnected)
{
return Result.Fail("HIK_CAMERA_NOT_CONNECTED", "相机未连接。");
}
if (_isGrabbing)
{
return Result.Success(message: "相机已在采集中。");
}
_logger.LogInformation("正在开始图像采集...");
if (_options.RunMode != "Real" || _deviceHandle == IntPtr.Zero || _camera == null)
{
_logger.LogDebug("模拟模式:开始图像采集");
_isGrabbing = true;
_frameQueue.Clear();
// 启动定时器生成模拟帧
_frameTimer = new Timer(GenerateMockFrame, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(33)); // 约30fps
return Result.Success(message: "图像采集启动成功(模拟模式)。");
}
// 开始采集
var startResult = _camera.MV_CC_StartGrabbing_NET(_deviceHandle);
if (startResult != MyCamera.MV_OK)
{
_logger.LogError("启动图像采集失败,错误代码: {ErrorCode}", startResult);
return Result.Fail("HIK_START_GRABBING_FAILED", $"启动图像采集失败,错误代码: {startResult}");
}
Thread.Sleep(100); // 等待采集启动
_isGrabbing = true;
_frameQueue.Clear();
// 启动定时器获取图像帧
_frameTimer = new Timer(GetFrameFromCamera, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(33)); // 约30fps
_logger.LogInformation("图像采集已启动");
return Result.Success(message: "图像采集启动成功。");
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "启动图像采集失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "HIK_CAMERA_START_GRAB_FAILED", "启动图像采集失败。", traceId);
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
}
///
public Result StopGrabbing()
{
lock (_lockObject)
{
try
{
if (!_isGrabbing)
{
return Result.Success(message: "相机未在采集状态。");
}
_logger.LogInformation("正在停止图像采集...");
// 停止定时器
_frameTimer?.Dispose();
_frameTimer = null;
if (_options.RunMode == "Real" && _deviceHandle != IntPtr.Zero && _camera != null)
{
var stopResult = _camera.MV_CC_StopGrabbing_NET(_deviceHandle);
if (stopResult != MyCamera.MV_OK)
{
_logger.LogWarning("停止图像采集失败,错误代码: {ErrorCode}", stopResult);
}
}
Thread.Sleep(50); // 等待采集停止
_isGrabbing = false;
_frameQueue.Clear();
_logger.LogInformation("图像采集已停止");
return Result.Success(message: "图像采集停止成功。");
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "停止图像采集失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "HIK_CAMERA_STOP_GRAB_FAILED", "停止图像采集失败。", traceId);
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
}
///
public Result TriggerSoftware()
{
lock (_lockObject)
{
try
{
if (!_isConnected)
{
return Result.Fail("HIK_CAMERA_NOT_CONNECTED", "相机未连接。");
}
if (!_isGrabbing)
{
return Result.Fail("HIK_CAMERA_NOT_GRABBING", "相机未在采集状态。");
}
if (_options.RunMode == "Real" && _camera != null)
{
_logger.LogDebug("执行软件触发");
var triggerResult = _camera.MV_CC_SetCommandValue_NET(_deviceHandle, "TriggerSoftware");
if (triggerResult != MyCamera.MV_OK)
{
_logger.LogWarning("软件触发失败,错误代码: {ErrorCode}", triggerResult);
return Result.Fail("HIK_CAMERA_TRIGGER_FAILED", $"软件触发失败,错误代码: {triggerResult}");
}
}
return Result.Success(message: "软件触发执行成功。");
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "软件触发失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "HIK_CAMERA_TRIGGER_FAILED", "软件触发失败。", traceId);
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
}
///
public Result GetLatestFrame()
{
try
{
if (!_isGrabbing)
{
return Result.Fail("HIK_CAMERA_NOT_GRABBING", "相机未在采集状态。");
}
if (_frameQueue.TryDequeue(out var frame))
{
return Result.Success(frame, message: "获取图像帧成功。");
}
return Result.Fail("HIK_CAMERA_NO_FRAME", "暂无可用图像帧。");
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "获取图像帧失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "HIK_CAMERA_GET_FRAME_FAILED", "获取图像帧失败。", traceId);
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
///
public Result GetLatestFrameWithTimestamp()
{
var frameResult = GetLatestFrame();
if (!frameResult.Succeeded)
{
return Result.Fail(frameResult.Code, frameResult.Message, frameResult.Errors.ToArray());
}
var now = DateTime.UtcNow;
return Result.Success(new CameraFrameDto
{
FrameId = Guid.NewGuid(),
CapturedAtUtc = now,
CameraId = _currentDevice?.SerialNumber ?? string.Empty,
ImageData = frameResult.Data,
Timestamp = now,
Width = _options.ImageWidth,
Height = _options.ImageHeight,
PixelFormat = _options.PixelFormat
}, message: "获取图像帧成功。");
}
///
/// 从相机获取图像帧。
///
private void GetFrameFromCamera(object? state)
{
try
{
if (!_isGrabbing || _options.RunMode != "Real" || !_sdkInitialized)
{
return;
}
if (_deviceHandle == IntPtr.Zero || _camera == null)
{
return;
}
// 获取一帧图像数据
var frame = new MyCamera.MV_FRAME_OUT_INFO_EX();
var imageBuffer = IntPtr.Zero;
var getFrameResult = _camera.MV_CC_GetOneFrameTimeout_NET(_deviceHandle, ref frame, 1000);
if (getFrameResult == MyCamera.MV_OK)
{
try
{
// 转换图像数据为BGR格式
var convertResult = _camera.MV_CC_ConvertPixelType_NET(_deviceHandle, frame, MyCamera.MV_Gvsp_RGB8_Packed, ref imageBuffer);
if (convertResult == MyCamera.MV_OK && imageBuffer != IntPtr.Zero)
{
var frameSize = frame.nWidth * frame.nHeight * 3; // BGR8Packed
var frameData = new byte[frameSize];
Marshal.Copy(imageBuffer, frameData, 0, frameSize);
var timestamp = DateTime.UtcNow;
// 添加到队列
if (_frameQueue.Count < 10) // 限制队列大小防止内存溢出
{
_frameQueue.Enqueue(frameData);
}
// 触发事件
OnImageReceived?.Invoke(frameData, timestamp);
// 释放图像缓冲区
_camera.MV_CC_FreeImageBuffer_NET(_deviceHandle, ref frame);
}
else
{
// 转换失败,使用模拟数据
GenerateMockFrame(null);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "处理图像帧数据时发生异常");
}
finally
{
// 确保释放缓冲区
if (imageBuffer != IntPtr.Zero)
{
_camera.MV_CC_FreeImageBuffer_NET(_deviceHandle, ref frame);
}
}
}
else
{
// 获取图像失败,使用模拟数据
GenerateMockFrame(null);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "从相机获取图像帧失败");
}
}
///
/// 生成模拟图像帧。
///
private void GenerateMockFrame(object? state)
{
try
{
var width = _options.ImageWidth;
var height = _options.ImageHeight;
var frameSize = width * height * 3; // BGR8Packed
var frameData = new byte[frameSize];
// 填充模拟图像数据(简单的渐变图案)
var random = new Random();
for (int i = 0; i < frameSize; i += 3)
{
frameData[i] = (byte)(i % 256); // B
frameData[i + 1] = (byte)((i / 3) % 256); // G
frameData[i + 2] = (byte)random.Next(256); // R
}
var timestamp = DateTime.UtcNow;
// 添加到队列
if (_frameQueue.Count < 10)
{
_frameQueue.Enqueue(frameData);
}
// 触发事件
OnImageReceived?.Invoke(frameData, timestamp);
}
catch (Exception ex)
{
_logger.LogError(ex, "生成模拟图像帧失败");
}
}
///
/// 获取设备详细信息。
///
private Result GetDeviceInfo()
{
try
{
if (_deviceHandle == IntPtr.Zero || !_deviceInfo.HasValue)
{
return Result.Fail("HIK_DEVICE_NOT_CONNECTED", "设备未连接");
}
var info = _deviceInfo.Value;
// 获取设备型号名称
var modelName = Marshal.PtrToStringAnsi(info.SpecialInfo.stGigEInfo.chModelName) ?? "Unknown";
// 获取设备序列号
var serialNumber = Marshal.PtrToStringAnsi(info.SpecialInfo.stGigEInfo.chSerialNumber) ?? "Unknown";
// 获取设备用户定义名称
var userDefinedName = Marshal.PtrToStringAnsi(info.SpecialInfo.stGigEInfo.chUserDefinedName) ?? "Unknown";
// 获取固件版本
var firmwareVersion = Marshal.PtrToStringAnsi(info.SpecialInfo.stGigEInfo.chFirmwareVersion) ?? "Unknown";
// 获取IP地址
var ipAddress = Marshal.PtrToStringAnsi(info.SpecialInfo.stGigEInfo.nCurrentIp) ?? "Unknown";
// 获取子网掩码
var subnetMask = Marshal.PtrToStringAnsi(info.SpecialInfo.stGigEInfo.nCurrentSubNet) ?? "Unknown";
// 获取默认网关
var defaultGateway = Marshal.PtrToStringAnsi(info.SpecialInfo.stGigEInfo.nDefaultGate) ?? "Unknown";
// 获取MAC地址
var macAddress = Marshal.PtrToStringAnsi(info.SpecialInfo.stGigEInfo.nCurrentMac) ?? "Unknown";
// 更新当前设备信息
if (_currentDevice != null)
{
_currentDevice.DeviceName = userDefinedName;
_currentDevice.FirmwareVersion = firmwareVersion;
_currentDevice.SubnetMask = subnetMask;
_currentDevice.DefaultGateway = defaultGateway;
_currentDevice.MacAddress = macAddress;
}
_logger.LogDebug("设备信息: {ModelName}, {SerialNumber}, {IpAddress}", modelName, serialNumber, ipAddress);
return Result.Success(message: "获取设备信息成功。");
}
catch (Exception ex)
{
var traceId = Guid.NewGuid().ToString("N");
_logger.LogError(ex, "获取设备信息失败。TraceId: {TraceId}", traceId);
var result = Result.FromException(ex, "HIK_GET_DEVICE_INFO_FAILED", "获取设备信息失败。", traceId);
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
///
/// 模拟连接。
///
private Result MockConnect(HikCameraDevice device)
{
_currentDevice = new HikCameraDevice
{
SerialNumber = device.SerialNumber,
DeviceName = device.DeviceName,
IpAddress = device.IpAddress,
MacAddress = device.MacAddress,
IsConnected = true,
ConnectedAt = DateTime.UtcNow
};
_isConnected = true;
_logger.LogInformation("模拟连接成功: {SerialNumber}", device.SerialNumber);
OnConnectionStateChanged?.Invoke(true, $"模拟连接到 {device.DeviceName}");
return Result.Success(message: $"相机 {device.DeviceName} 模拟连接成功。");
}
///
/// 获取模拟设备。
///
private Result> GetMockDevices()
{
var mockDevices = new List
{
new()
{
SerialNumber = "MOCK_HIK_001",
DeviceName = "模拟海康相机_001",
IpAddress = "192.168.1.100",
MacAddress = "00:11:22:33:44:55",
IsConnected = true
},
new()
{
SerialNumber = "MOCK_HIK_002",
DeviceName = "模拟海康相机_002",
IpAddress = "192.168.1.101",
MacAddress = "00:11:22:33:44:56",
IsConnected = true
}
};
_logger.LogInformation("返回 {Count} 个模拟设备", mockDevices.Count);
return Result.Success>(mockDevices);
}
///
/// 获取像素格式值。
///
private uint GetPixelFormatValue(string pixelFormat)
{
return pixelFormat.ToUpperInvariant() switch
{
"BGR8PACKED" => MyCamera.MV_Gvsp_RGB8_Packed,
"RGB8PACKED" => MyCamera.MV_Gvsp_RGB8_Packed,
"MONO8" => MyCamera.MV_Gvsp_Mono8,
"MONO16" => MyCamera.MV_Gvsp_Mono16,
_ => MyCamera.MV_Gvsp_RGB8_Packed
};
}
///
/// 自动重连。
///
private async Task AutoReconnectAsync()
{
if (_reconnectAttempts >= _options.AutoReconnectCount)
{
_logger.LogWarning("已达到最大重连次数,停止重连");
return;
}
_reconnectAttempts++;
_logger.LogInformation("执行第 {Attempt} 次自动重连", _reconnectAttempts);
await Task.Delay(_options.AutoReconnectIntervalMs);
if (_currentDevice != null)
{
var connectResult = ConnectToDevice(_currentDevice.SerialNumber);
if (connectResult.Succeeded)
{
_logger.LogInformation("自动重连成功");
_reconnectAttempts = 0;
}
else
{
_logger.LogWarning("自动重连失败: {Error}", connectResult.Message);
await AutoReconnectAsync();
}
}
}
///
/// 释放资源。
///
public void Dispose()
{
try
{
// 停止定时器
_frameTimer?.Dispose();
_frameTimer = null;
// 断开连接
Disconnect();
// 释放SDK
if (_sdkInitialized && _options.RunMode == "Real")
{
_camera?.MV_CC_Finalize_NET();
_camera?.Dispose();
_camera = null;
_sdkInitialized = false;
}
_logger.LogInformation("海康相机服务已释放");
}
catch (Exception ex)
{
_logger.LogError(ex, "释放海康相机服务资源时发生错误");
}
}
}