合并修改
This commit is contained in:
399
DH.Commons/Base/CameraBase.cs
Normal file
399
DH.Commons/Base/CameraBase.cs
Normal file
@ -0,0 +1,399 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing.Imaging;
|
||||
using AntdUI;
|
||||
using DH.Commons.Enums;
|
||||
using DVPCameraType;
|
||||
using HalconDotNet;
|
||||
using OpenCvSharp;
|
||||
|
||||
namespace DH.Commons.Base
|
||||
{
|
||||
public class MatSet
|
||||
{
|
||||
public DateTime ImageTime { get; set; } = DateTime.Now;
|
||||
|
||||
private string id = "";
|
||||
public string Id
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
{
|
||||
id = ImageTime.ToString("HHmmssfff");
|
||||
}
|
||||
return id;
|
||||
}
|
||||
set
|
||||
{
|
||||
id = value;
|
||||
}
|
||||
}
|
||||
public string CameraId { get; set; }
|
||||
public Mat _mat { get; set; } = null;
|
||||
|
||||
public ImageFormat _imageFormat { get; set; } = ImageFormat.Jpeg;
|
||||
public virtual void Dispose()
|
||||
{
|
||||
_mat?.Dispose();
|
||||
_mat = null;
|
||||
|
||||
}
|
||||
}
|
||||
public class CameraBase : NotifyProperty
|
||||
{
|
||||
|
||||
// public LoggerHelper LoggerHelper { get; set; } = new LoggerHelper();
|
||||
|
||||
// 私有字段 + 带通知的属性(与DetectionLabel风格一致)
|
||||
private bool _isEnabled = false;
|
||||
private bool _isallPicEnabled = true;//默认全画幅
|
||||
private bool _isRGBEnabled = true;//默认彩色
|
||||
private bool _isContinueMode = false;
|
||||
private bool _isSavePicEnabled = false;
|
||||
private bool _isZoomCamera = false;
|
||||
private string _imageSaveDirectory;
|
||||
private EnumCamType _CamType;
|
||||
private dvpStreamFormat _dvpstreamFormat = dvpStreamFormat.S_RGB24;
|
||||
private ImageFormat _imageFormat = ImageFormat.Jpeg;
|
||||
private bool _isHardwareTrigger = true;
|
||||
private string _serialNumber = string.Empty;
|
||||
private string _cameraName = string.Empty;
|
||||
private string _cameraIP = string.Empty;
|
||||
private string _computerIP = string.Empty;
|
||||
private bool _isDirectHardwareTrigger = false;
|
||||
private float _gain =6;
|
||||
private int _rotateImage = 0;
|
||||
private float _exposure = 200;
|
||||
private float _triggerDelay = 0;
|
||||
private decimal _roiX = 0;
|
||||
private decimal _roiY = 0;
|
||||
private decimal _roiW = 2448;
|
||||
private decimal _roiH = 2048;
|
||||
private int _lineDebouncerTime = 0;
|
||||
|
||||
public volatile int SnapshotCount = 0;
|
||||
|
||||
[Category("相机设置")]
|
||||
[DisplayName("图像格式")]
|
||||
[Description("相机采集图像格式")]
|
||||
public dvpStreamFormat DvpImageFormat
|
||||
{
|
||||
get => _dvpstreamFormat;
|
||||
set
|
||||
{
|
||||
if (_dvpstreamFormat == value) return;
|
||||
_dvpstreamFormat = value;
|
||||
OnPropertyChanged(nameof(DvpImageFormat));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("采图模式")]
|
||||
[DisplayName("连续模式")]
|
||||
[Description("是否连续模式。true:连续模式采图;false:触发模式采图")]
|
||||
public bool IsContinueMode
|
||||
{
|
||||
get => _isContinueMode;
|
||||
set
|
||||
{
|
||||
if (_isContinueMode == value) return;
|
||||
_isContinueMode = value;
|
||||
OnPropertyChanged(nameof(IsContinueMode));
|
||||
}
|
||||
}
|
||||
public bool IsZoomCamera
|
||||
{
|
||||
get => _isZoomCamera;
|
||||
set
|
||||
{
|
||||
if (_isZoomCamera == value) return;
|
||||
_isZoomCamera = value;
|
||||
OnPropertyChanged(nameof(IsZoomCamera));
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsEnabled
|
||||
{
|
||||
get => _isEnabled;
|
||||
set
|
||||
{
|
||||
if (_isEnabled == value) return;
|
||||
_isEnabled = value;
|
||||
OnPropertyChanged(nameof(IsEnabled));
|
||||
}
|
||||
}
|
||||
public virtual bool IsAllPicEnabled
|
||||
{
|
||||
get => _isallPicEnabled;
|
||||
set
|
||||
{
|
||||
if (_isallPicEnabled == value) return;
|
||||
_isallPicEnabled = value;
|
||||
OnPropertyChanged(nameof(IsAllPicEnabled));
|
||||
}
|
||||
}
|
||||
public virtual bool IsSavePicEnabled
|
||||
{
|
||||
get => _isSavePicEnabled;
|
||||
set
|
||||
{
|
||||
if (_isSavePicEnabled == value) return;
|
||||
_isSavePicEnabled = value;
|
||||
OnPropertyChanged(nameof(IsSavePicEnabled));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("图片保存")]
|
||||
[DisplayName("图片保存文件夹")]
|
||||
[Description("图片保存文件夹")]
|
||||
public virtual string ImageSaveDirectory
|
||||
{
|
||||
get => _imageSaveDirectory;
|
||||
set
|
||||
{
|
||||
if (_imageSaveDirectory == value) return;
|
||||
_imageSaveDirectory = value;
|
||||
OnPropertyChanged(nameof(ImageSaveDirectory));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("图片保存")]
|
||||
[DisplayName("图片保存格式")]
|
||||
[Description("图片保存格式")]
|
||||
public ImageFormat ImageFormat
|
||||
{
|
||||
get => _imageFormat;
|
||||
set
|
||||
{
|
||||
if (_imageFormat == value) return;
|
||||
_imageFormat = value;
|
||||
OnPropertyChanged(nameof(ImageFormat));
|
||||
}
|
||||
}
|
||||
[Category("设备配置")]
|
||||
[DisplayName("相机类型")]
|
||||
[Description("相机类型")]
|
||||
public EnumCamType CamType
|
||||
{
|
||||
get => _CamType;
|
||||
set
|
||||
{
|
||||
if (_CamType == value) return;
|
||||
_CamType = value;
|
||||
OnPropertyChanged(nameof(CamType));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("采图模式")]
|
||||
[DisplayName("硬触发")]
|
||||
[Description("是否硬触发模式。true:硬触发;false:软触发")]
|
||||
public bool IsHardwareTrigger
|
||||
{
|
||||
get => _isHardwareTrigger;
|
||||
set
|
||||
{
|
||||
if (_isHardwareTrigger == value) return;
|
||||
_isHardwareTrigger = value;
|
||||
OnPropertyChanged(nameof(IsHardwareTrigger));
|
||||
}
|
||||
}
|
||||
|
||||
public string SerialNumber
|
||||
{
|
||||
get => _serialNumber;
|
||||
set
|
||||
{
|
||||
if (_serialNumber == value) return;
|
||||
_serialNumber = value;
|
||||
OnPropertyChanged(nameof(SerialNumber));
|
||||
}
|
||||
}
|
||||
|
||||
public string CameraName
|
||||
{
|
||||
get => _cameraName;
|
||||
set
|
||||
{
|
||||
if (_cameraName == value) return;
|
||||
_cameraName = value;
|
||||
OnPropertyChanged(nameof(CameraName));
|
||||
}
|
||||
}
|
||||
|
||||
public string CameraIP
|
||||
{
|
||||
get => _cameraIP;
|
||||
set
|
||||
{
|
||||
if (_cameraIP == value) return;
|
||||
_cameraIP = value;
|
||||
OnPropertyChanged(nameof(CameraIP));
|
||||
}
|
||||
}
|
||||
|
||||
public string ComputerIP
|
||||
{
|
||||
get => _computerIP;
|
||||
set
|
||||
{
|
||||
if (_computerIP == value) return;
|
||||
_computerIP = value;
|
||||
OnPropertyChanged(nameof(ComputerIP));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("采图模式")]
|
||||
[DisplayName("是否传感器直接硬触发")]
|
||||
[Description("是否传感器直接硬触发。true:传感器硬触发,不通过软件触发;false:通过软件触发IO 的硬触发模式")]
|
||||
public bool IsDirectHardwareTrigger
|
||||
{
|
||||
get => _isDirectHardwareTrigger;
|
||||
set
|
||||
{
|
||||
if (_isDirectHardwareTrigger == value) return;
|
||||
_isDirectHardwareTrigger = value;
|
||||
OnPropertyChanged(nameof(IsDirectHardwareTrigger));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("相机设置")]
|
||||
[DisplayName("增益")]
|
||||
[Description("Gain:增益,-1:不设置,不同型号相机的增益,请参考mvs")]
|
||||
public float Gain
|
||||
{
|
||||
get => _gain;
|
||||
set
|
||||
{
|
||||
if (_gain.Equals(value)) return;
|
||||
_gain = value;
|
||||
OnPropertyChanged(nameof(Gain));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("图像旋转")]
|
||||
[DisplayName("默认旋转")]
|
||||
[Description("默认旋转,相机开启后默认不旋转")]
|
||||
public virtual int RotateImage
|
||||
{
|
||||
get => _rotateImage;
|
||||
set
|
||||
{
|
||||
if (_rotateImage.Equals(value)) return;
|
||||
_rotateImage = value;
|
||||
OnPropertyChanged(nameof(RotateImage));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("取像配置")]
|
||||
[DisplayName("曝光")]
|
||||
[Description("曝光")]
|
||||
public virtual float Exposure
|
||||
{
|
||||
get => _exposure;
|
||||
set
|
||||
{
|
||||
if (_exposure.Equals(value)) return;
|
||||
_exposure = value;
|
||||
OnPropertyChanged(nameof(Exposure));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("相机设置")]
|
||||
[DisplayName("硬触发后的延迟")]
|
||||
[Description("TriggerDelay:硬触发后的延迟,单位:us 微秒")]
|
||||
public float TriggerDelay
|
||||
{
|
||||
get => _triggerDelay;
|
||||
set
|
||||
{
|
||||
if (_triggerDelay.Equals(value)) return;
|
||||
_triggerDelay = value;
|
||||
OnPropertyChanged(nameof(TriggerDelay));
|
||||
}
|
||||
}
|
||||
|
||||
public decimal ROIX
|
||||
{
|
||||
get => _roiX;
|
||||
set
|
||||
{
|
||||
if (_roiX == value) return;
|
||||
_roiX = value;
|
||||
OnPropertyChanged(nameof(ROIX));
|
||||
}
|
||||
}
|
||||
|
||||
public decimal ROIY
|
||||
{
|
||||
get => _roiY;
|
||||
set
|
||||
{
|
||||
if (_roiY == value) return;
|
||||
_roiY = value;
|
||||
OnPropertyChanged(nameof(ROIY));
|
||||
}
|
||||
}
|
||||
|
||||
public decimal ROIW
|
||||
{
|
||||
get => _roiW;
|
||||
set
|
||||
{
|
||||
if (_roiW == value) return;
|
||||
_roiW = value;
|
||||
OnPropertyChanged(nameof(ROIW));
|
||||
}
|
||||
}
|
||||
|
||||
public decimal ROIH
|
||||
{
|
||||
get => _roiH;
|
||||
set
|
||||
{
|
||||
if (_roiH == value) return;
|
||||
_roiH = value;
|
||||
OnPropertyChanged(nameof(ROIH));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("相机设置")]
|
||||
[DisplayName("滤波时间")]
|
||||
[Description("LineDebouncerTime:I/O去抖时间 单位:us")]
|
||||
public int LineDebouncerTime
|
||||
{
|
||||
get => _lineDebouncerTime;
|
||||
set
|
||||
{
|
||||
if (_lineDebouncerTime == value) return;
|
||||
_lineDebouncerTime = value;
|
||||
OnPropertyChanged(nameof(LineDebouncerTime));
|
||||
}
|
||||
}
|
||||
|
||||
// 其他方法保持原有逻辑
|
||||
public MatSet CopyImageSet(MatSet srcSet)
|
||||
{
|
||||
MatSet imageSet = new MatSet
|
||||
{
|
||||
Id = srcSet.Id,
|
||||
_mat = srcSet._mat.Clone(),
|
||||
// ImageSaveOption = srcSet.ImageSaveOption.Copy(),
|
||||
ImageTime = srcSet.ImageTime
|
||||
};
|
||||
return imageSet;
|
||||
}
|
||||
public Action<DateTime, CameraBase, MatSet> OnHImageOutput { get; set; }
|
||||
|
||||
public virtual bool CameraConnect() { return false; }
|
||||
|
||||
public virtual bool CameraDisConnect() { return false; }
|
||||
|
||||
public virtual void SetExposure(int exposureTime, string cameraName) { }
|
||||
|
||||
public virtual void SetGain(int gain, string cameraName) { }
|
||||
|
||||
internal virtual void SetAcquisitionMode(int mode) { }
|
||||
|
||||
internal virtual void SetAcqRegion(int offsetV, int offsetH, int imageH, int imageW, string cameraName) { }
|
||||
}
|
||||
}
|
1558
DH.Commons/Base/DetectionConfig.cs
Normal file
1558
DH.Commons/Base/DetectionConfig.cs
Normal file
File diff suppressed because it is too large
Load Diff
389
DH.Commons/Base/DeviceBase.cs
Normal file
389
DH.Commons/Base/DeviceBase.cs
Normal file
@ -0,0 +1,389 @@
|
||||
|
||||
using DH.Commons.Enums;
|
||||
using OpenCvSharp.Internal;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static DH.Commons.Enums.EnumHelper;
|
||||
using Timer = System.Threading.Timer;
|
||||
|
||||
namespace DH.Commons.Base
|
||||
{
|
||||
public abstract class DeviceBase : IDisposable
|
||||
{
|
||||
#region Event
|
||||
[JsonIgnore]
|
||||
[Browsable(false)]
|
||||
public Action<DateTime, Exception> OnExceptionOccured { get; set; }
|
||||
//public event Action<DateTime, LogLevel, string> OnLog;
|
||||
public event Action<LogMsg> OnLog;
|
||||
// public event Action<IDevice, DeviceState> OnDeviceStateChanged;
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
#endregion
|
||||
|
||||
#region field
|
||||
int RetryTime = 3;
|
||||
/// <summary>
|
||||
/// 和设备暂停状态关联的信号量
|
||||
/// </summary>
|
||||
private readonly ManualResetEvent pauseHandle = new ManualResetEvent(true);
|
||||
readonly Timer stateChangedTimer;
|
||||
#endregion
|
||||
|
||||
#region Property
|
||||
#region State
|
||||
private EnumHelper.DeviceState _currentStateToBe = EnumHelper.DeviceState.DSUninit;
|
||||
/// <summary>
|
||||
/// 当前设备状态
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
internal EnumHelper.DeviceState CurrentStateToBe
|
||||
{
|
||||
get
|
||||
{
|
||||
return _currentStateToBe;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value != _currentStateToBe)
|
||||
{
|
||||
var initialState = _currentStateToBe;
|
||||
_currentStateToBe = value;
|
||||
|
||||
if (_currentStateToBe != EnumHelper.DeviceState.DSExcept)
|
||||
{
|
||||
// OnStateChanged(initialState);
|
||||
}
|
||||
else
|
||||
{
|
||||
stateChangedTimer.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//private EnumHelper.DeviceState initialState = EnumHelper.DeviceState.DSUninit;
|
||||
private EnumHelper.DeviceState _currentState = EnumHelper.DeviceState.DSUninit;
|
||||
public EnumHelper.DeviceState CurrentState
|
||||
{
|
||||
get
|
||||
{
|
||||
return _currentState;
|
||||
}
|
||||
set
|
||||
{
|
||||
_currentState = value;
|
||||
|
||||
if (value != EnumHelper.DeviceState.TBD)
|
||||
{
|
||||
// OnDeviceStateChanged?.Invoke(this, _currentState);
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentState"));
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// initialState = _currentState;
|
||||
//}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 设备标识符 从数据库获取
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备名称 从数据库获取
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
//private IInitialConfig initialConfig = null;
|
||||
///// <summary>
|
||||
///// 设备初始化配置 从数据库获取
|
||||
///// </summary>
|
||||
//public virtual IInitialConfig InitialConfig
|
||||
//{
|
||||
// get => initialConfig;
|
||||
// set
|
||||
// {
|
||||
// initialConfig = value;
|
||||
// Id = initialConfig.Id;
|
||||
// Name = initialConfig.Name;
|
||||
|
||||
// LoggerHelper.LogPath = initialConfig.LogPath;
|
||||
// LoggerHelper.LogPrefix = initialConfig.Name;
|
||||
// }
|
||||
//}
|
||||
#endregion
|
||||
|
||||
#region 构造函数
|
||||
public DeviceBase()
|
||||
{
|
||||
RegisterFileWriterException();
|
||||
// stateChangedTimer = new Timer(new TimerCallback(CheckDeviceOpTimeOut), null, Timeout.Infinite, Timeout.Infinite);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 设备抽象方法
|
||||
protected virtual void Init()
|
||||
{
|
||||
LogAsync(DateTime.Now, LogLevel.Information, $"{Name}初始化完成");
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
LogAsync(DateTime.Now, LogLevel.Information, $"{Name}启动");
|
||||
}
|
||||
|
||||
protected virtual void Stop()
|
||||
{
|
||||
LogAsync(DateTime.Now, LogLevel.Information, $"{Name}停止");
|
||||
}
|
||||
|
||||
//public abstract void AttachToProcess(IProcess process);
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 常用操作封装方法
|
||||
/// </summary>
|
||||
/// <param name="opConfig"></param>
|
||||
/// <returns></returns>
|
||||
//public virtual ResponseMessage RunWrap(IOperationConfig opConfig)
|
||||
//{
|
||||
// ResponseMessage msg = new ResponseMessage();
|
||||
// msg.Message = "设备基类默认操作";
|
||||
// return msg;
|
||||
//}
|
||||
|
||||
#region 状态切换
|
||||
//[DeviceExceptionAspect]
|
||||
//public void StateChange(EnumHelper.DeviceState stateToBe)
|
||||
//{
|
||||
// if (CurrentState == stateToBe)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (!stateToBe.CheckPreStateValid((int)CurrentStateToBe))
|
||||
// {
|
||||
// string currentStateStr = CurrentStateToBe.GetEnumDescription();
|
||||
// string stateToBeStr = stateToBe.GetEnumDescription();
|
||||
// throw new ProcessException($"{InitialConfig.Name}设备的当前状态为{currentStateStr},无法切换至{stateToBeStr}");
|
||||
// }
|
||||
|
||||
// CurrentState = EnumHelper.DeviceState.TBD;
|
||||
// CurrentStateToBe = stateToBe;
|
||||
//}
|
||||
|
||||
//[DeviceExceptionAspect]
|
||||
//private void OnStateChanged(EnumHelper.DeviceState initialState)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// if (CurrentStateToBe != EnumHelper.DeviceState.DSExcept)
|
||||
// {
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (CurrentState == EnumHelper.DeviceState.DSExcept)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// throw new ProcessException($"{InitialConfig.Name}设备操作超时");
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (RetryTime >= 0)
|
||||
// {
|
||||
// if (initialState == CurrentStateToBe)
|
||||
// {
|
||||
// CurrentState = CurrentStateToBe;
|
||||
// return;
|
||||
// }
|
||||
|
||||
// #region 状态切换操作
|
||||
// switch (CurrentStateToBe)
|
||||
// {
|
||||
// case EnumHelper.DeviceState.DSInit:
|
||||
// if (initialState == EnumHelper.DeviceState.DSOpen)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Init();
|
||||
// }
|
||||
// break;
|
||||
// case EnumHelper.DeviceState.DSOpen:
|
||||
// if (initialState == EnumHelper.DeviceState.DSInit)
|
||||
// {
|
||||
// Start();
|
||||
// }
|
||||
// else if (initialState == EnumHelper.DeviceState.DSPause)
|
||||
// {
|
||||
// Resume();
|
||||
// pauseHandle.Set();
|
||||
// }
|
||||
// break;
|
||||
// case EnumHelper.DeviceState.DSPause:
|
||||
// pauseHandle.Reset();
|
||||
// Pause();
|
||||
// break;
|
||||
// case EnumHelper.DeviceState.DSClose:
|
||||
// if (initialState != DeviceState.DSUninit)
|
||||
// {
|
||||
// Stop();
|
||||
// }
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
|
||||
// RetryTime = 3;
|
||||
// CurrentState = CurrentStateToBe;
|
||||
// #endregion
|
||||
// }
|
||||
|
||||
// stateChangedTimer.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// RetryTime--;
|
||||
// if (RetryTime > 0)
|
||||
// {
|
||||
// OnStateChanged(initialState);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (CurrentState != EnumHelper.DeviceState.DSExcept)
|
||||
// {
|
||||
// RetryTime = 3;
|
||||
// throw new ProcessException($"设备{InitialConfig.Name}的{CurrentStateToBe.GetEnumDescription()}操作重复3次失败", ex, ExceptionLevel.Warning);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//private void CheckDeviceOpTimeOut(object state)
|
||||
//{
|
||||
// stateChangedTimer?.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
|
||||
// if (CurrentState != EnumHelper.DeviceState.DSExcept)
|
||||
// {
|
||||
// StateChange(EnumHelper.DeviceState.DSExcept);
|
||||
// }
|
||||
//}
|
||||
#endregion
|
||||
|
||||
#region 日志处理
|
||||
private void RegisterFileWriterException()
|
||||
{
|
||||
LoggerHelper.OnLogExceptionRaised -= LoggerHelper_OnLogExceptionRaised;
|
||||
// CSVHelper.OnCSVExceptionRaised -= LoggerHelper_OnLogExceptionRaised;
|
||||
|
||||
LoggerHelper.OnLogExceptionRaised += LoggerHelper_OnLogExceptionRaised;
|
||||
// CSVHelper.OnCSVExceptionRaised += LoggerHelper_OnLogExceptionRaised;
|
||||
}
|
||||
// public CSVHelper CSVHelper { get; set; } = new CSVHelper();
|
||||
|
||||
public LoggerHelper LoggerHelper { get; set; } = new LoggerHelper();
|
||||
|
||||
public virtual void LogAsync(LogMsg msg)
|
||||
{
|
||||
msg.MsgSource = Name;
|
||||
msg.ThreadId = Thread.CurrentThread.ManagedThreadId;
|
||||
|
||||
//OnLog?.BeginInvoke(msg, null, null);
|
||||
OnLog?.Invoke(msg);
|
||||
|
||||
//if (InitialConfig.IsEnableLog)
|
||||
//{
|
||||
LoggerHelper.LogAsync(msg);
|
||||
//}
|
||||
}
|
||||
|
||||
public virtual void LogAsync(DateTime dt, LogLevel logLevel, string msg)
|
||||
{
|
||||
LogAsync(new LogMsg(dt, logLevel, msg));
|
||||
}
|
||||
private void LoggerHelper_OnLogExceptionRaised(DateTime dt, string msg)
|
||||
{
|
||||
OnLog?.Invoke(new LogMsg(dt, LogLevel.Error, msg));
|
||||
}
|
||||
/// <summary>
|
||||
/// CSV异步数据输出
|
||||
/// </summary>
|
||||
/// <param name="csvFile">CSV输出文件的文件全路径</param>
|
||||
/// <param name="csvData">CSV输出数据</param>
|
||||
/// <param name="csvHead">CSV文件表头</param>
|
||||
public virtual void CSVRecordAsync(string csvFile, string csvData, string csvHead = "")
|
||||
{
|
||||
// CSVHelper.CSVOutputAsync(csvFile, csvData, csvHead);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 报警记录
|
||||
//object _alarmLock = new object();
|
||||
//protected virtual async void SaveAlarmCSVAsync(DateTime now, string deviceName, IWarningSet ws)
|
||||
//{
|
||||
// await Task.Run(() =>
|
||||
// {
|
||||
// LogAsync(now, LogLevel.Warning, $"{ws.WarningCode}-{ws.WarningDescription} {(ws.CurrentStatus ? "发生" : "取消")}");
|
||||
|
||||
// if (string.IsNullOrWhiteSpace(this.InitialConfig.LogPath) || !InitialConfig.IsEnableCSV)
|
||||
// return;
|
||||
|
||||
// string path = Path.Combine(InitialConfig.LogPath, $"Alarm_{Name}_{now.ToString("yyyyMMdd")}.csv");
|
||||
// string head = "Time,Source,AlarmCode,AlarmDescription,AlarmStatus";
|
||||
// string data = $"{now.ToString("HH:mm:ss.fff")},{deviceName},{ws.WarningCode},{ws.WarningDescription},{(ws.CurrentStatus ? "报警发生" : "报警取消")}";
|
||||
// CSVRecordAsync(path, data, head);
|
||||
// });
|
||||
//}
|
||||
#endregion
|
||||
|
||||
#region IDisposable Support
|
||||
private bool disposedValue = false; // 要检测冗余调用
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
//释放托管状态(托管对象)。
|
||||
stateChangedTimer?.Dispose();
|
||||
pauseHandle?.Dispose();
|
||||
}
|
||||
|
||||
// TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
|
||||
// TODO: 将大型字段设置为 null。
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
|
||||
// ~DeviceBase()
|
||||
// {
|
||||
// // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
|
||||
// Dispose(false);
|
||||
// }
|
||||
|
||||
// 添加此代码以正确实现可处置模式。
|
||||
public void Dispose()
|
||||
{
|
||||
// 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
|
||||
Dispose(true);
|
||||
// TODO: 如果在以上内容中替代了终结器,则取消注释以下行。
|
||||
// GC.SuppressFinalize(this);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
169
DH.Commons/Base/GlobalConfig.cs
Normal file
169
DH.Commons/Base/GlobalConfig.cs
Normal file
@ -0,0 +1,169 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using AntdUI;
|
||||
|
||||
namespace DH.Commons.Base
|
||||
{
|
||||
public class GlobalConfig : NotifyProperty
|
||||
{
|
||||
bool _EnableVibrator=false;
|
||||
bool _EnableBelt = false;
|
||||
int _ClearTime=0;
|
||||
string _name;
|
||||
private BindingList<PLCItem> _InitProcessList = new BindingList<PLCItem>();
|
||||
private BindingList<PLCItem> _StartProcessList = new BindingList<PLCItem>();
|
||||
private BindingList<PLCItem> _StopProcessList = new BindingList<PLCItem>();
|
||||
private BindingList<PLCItem> _StartResetList = new BindingList<PLCItem>();
|
||||
private BindingList<PLCItem> _StopResetList = new BindingList<PLCItem>();
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
if (_name != value)
|
||||
{
|
||||
_name = value;
|
||||
OnPropertyChanged(nameof(Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool EnableBelt
|
||||
{
|
||||
get => _EnableBelt;
|
||||
set
|
||||
{
|
||||
if (_EnableBelt != value)
|
||||
{
|
||||
_EnableBelt = value;
|
||||
OnPropertyChanged(nameof(EnableBelt));
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool EnableVibrator
|
||||
{
|
||||
get => _EnableVibrator;
|
||||
set
|
||||
{
|
||||
if (_EnableVibrator != value)
|
||||
{
|
||||
_EnableVibrator = value;
|
||||
OnPropertyChanged(nameof(EnableVibrator));
|
||||
}
|
||||
}
|
||||
}
|
||||
public int ClearTime
|
||||
{
|
||||
get => _ClearTime;
|
||||
set
|
||||
{
|
||||
if (_ClearTime != value)
|
||||
{
|
||||
_ClearTime = value;
|
||||
OnPropertyChanged(nameof(ClearTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
public BindingList<PLCItem> InitProcessList
|
||||
{
|
||||
get => _InitProcessList;
|
||||
set
|
||||
{
|
||||
if (_InitProcessList == value) return;
|
||||
_InitProcessList = value;
|
||||
OnPropertyChanged(nameof(InitProcessList));
|
||||
}
|
||||
}
|
||||
public BindingList<PLCItem> StartProcessList
|
||||
{
|
||||
get => _StartProcessList;
|
||||
set
|
||||
{
|
||||
if (_StartProcessList == value) return;
|
||||
_StartProcessList = value;
|
||||
OnPropertyChanged(nameof(StartProcessList));
|
||||
}
|
||||
}
|
||||
public BindingList<PLCItem> StopProcessList
|
||||
{
|
||||
get => _StopProcessList;
|
||||
set
|
||||
{
|
||||
if (_StopProcessList == value) return;
|
||||
_StopProcessList = value;
|
||||
OnPropertyChanged(nameof(StopProcessList));
|
||||
}
|
||||
}
|
||||
public BindingList<PLCItem> StartResetList
|
||||
{
|
||||
get => _StartResetList;
|
||||
set
|
||||
{
|
||||
if (_StartResetList == value) return;
|
||||
_StartResetList = value;
|
||||
OnPropertyChanged(nameof(StartResetList));
|
||||
}
|
||||
}
|
||||
public BindingList<PLCItem> StopResetList
|
||||
{
|
||||
get => _StopResetList;
|
||||
set
|
||||
{
|
||||
if (_StopResetList == value) return;
|
||||
_StopResetList = value;
|
||||
OnPropertyChanged(nameof(StopResetList));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
string _imgSavePath;
|
||||
string _dbSavePath;
|
||||
string _configSavePath;
|
||||
|
||||
public string ImgSavePath
|
||||
{
|
||||
get => _imgSavePath;
|
||||
set
|
||||
{
|
||||
if (_imgSavePath != value)
|
||||
{
|
||||
_imgSavePath = value;
|
||||
OnPropertyChanged(nameof(ImgSavePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string DbSavePath
|
||||
{
|
||||
get => _dbSavePath;
|
||||
set
|
||||
{
|
||||
if (_dbSavePath != value)
|
||||
{
|
||||
_dbSavePath = value;
|
||||
OnPropertyChanged(nameof(DbSavePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string ConfigSavePath
|
||||
{
|
||||
get => _configSavePath;
|
||||
set
|
||||
{
|
||||
if (_configSavePath != value)
|
||||
{
|
||||
_configSavePath = value;
|
||||
OnPropertyChanged(nameof(ConfigSavePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
378
DH.Commons/Base/PLCBase.cs
Normal file
378
DH.Commons/Base/PLCBase.cs
Normal file
@ -0,0 +1,378 @@
|
||||
using System.ComponentModel;
|
||||
using System.IO.Ports;
|
||||
using System.Text.Json.Serialization;
|
||||
using AntdUI;
|
||||
using DH.Commons.Enums; // 请确保此命名空间包含EnumPLCType
|
||||
|
||||
namespace DH.Commons.Base
|
||||
{
|
||||
public class PLCBase : NotifyProperty
|
||||
{
|
||||
|
||||
// 私有字段
|
||||
private bool _enable;
|
||||
private bool _connected;
|
||||
private string _plcName;
|
||||
private EnumPLCType _plcType;
|
||||
private string _com = "COM1";
|
||||
private int _baudRate = 9600;
|
||||
private int _dataBit = 8;
|
||||
private StopBits _stopBit = StopBits.One;
|
||||
private Parity _parity = Parity.None;
|
||||
private string _ip = "192.168.6.61";
|
||||
private int _port = 502;
|
||||
private BindingList<PLCItem> _PLCItemList = new BindingList<PLCItem>();
|
||||
|
||||
[Category("设备配置")]
|
||||
[DisplayName("是否启用")]
|
||||
[Description("是否启用")]
|
||||
public bool Enable
|
||||
{
|
||||
get => _enable;
|
||||
set
|
||||
{
|
||||
if (_enable == value) return;
|
||||
_enable = value;
|
||||
OnPropertyChanged(nameof(Enable));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Category("状态监控")]
|
||||
[DisplayName("连接状态")]
|
||||
[Description("PLC连接状态")]
|
||||
public bool Connected
|
||||
{
|
||||
get => _connected;
|
||||
set
|
||||
{
|
||||
if (_connected == value) return;
|
||||
_connected = value;
|
||||
OnPropertyChanged(nameof(Connected));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("设备配置")]
|
||||
[DisplayName("PLC名称")]
|
||||
[Description("PLC设备名称")]
|
||||
public string PLCName
|
||||
{
|
||||
get => _plcName;
|
||||
set
|
||||
{
|
||||
if (_plcName == value) return;
|
||||
_plcName = value;
|
||||
OnPropertyChanged(nameof(PLCName));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("设备配置")]
|
||||
[DisplayName("PLC类型")]
|
||||
[Description("PLC通信协议类型")]
|
||||
public EnumPLCType PLCType
|
||||
{
|
||||
get => _plcType;
|
||||
set
|
||||
{
|
||||
if (_plcType == value) return;
|
||||
_plcType = value;
|
||||
OnPropertyChanged(nameof(PLCType));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("串口配置")]
|
||||
[DisplayName("COM端口")]
|
||||
[Description("串口号,如COM1")]
|
||||
public string COM
|
||||
{
|
||||
get => _com;
|
||||
set
|
||||
{
|
||||
if (_com == value) return;
|
||||
_com = value;
|
||||
OnPropertyChanged(nameof(COM));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("串口配置")]
|
||||
[DisplayName("波特率")]
|
||||
[Description("串口通信波特率")]
|
||||
public int BaudRate
|
||||
{
|
||||
get => _baudRate;
|
||||
set
|
||||
{
|
||||
if (_baudRate == value) return;
|
||||
_baudRate = value;
|
||||
OnPropertyChanged(nameof(BaudRate));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("串口配置")]
|
||||
[DisplayName("数据位")]
|
||||
[Description("数据位长度(5/6/7/8)")]
|
||||
public int DataBit
|
||||
{
|
||||
get => _dataBit;
|
||||
set
|
||||
{
|
||||
if (_dataBit == value) return;
|
||||
_dataBit = value;
|
||||
OnPropertyChanged(nameof(DataBit));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("串口配置")]
|
||||
[DisplayName("停止位")]
|
||||
[Description("停止位设置")]
|
||||
public StopBits StopBit
|
||||
{
|
||||
get => _stopBit;
|
||||
set
|
||||
{
|
||||
if (_stopBit == value) return;
|
||||
_stopBit = value;
|
||||
OnPropertyChanged(nameof(StopBit));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("串口配置")]
|
||||
[DisplayName("校验位")]
|
||||
[Description("奇偶校验方式")]
|
||||
public Parity Parity
|
||||
{
|
||||
get => _parity;
|
||||
set
|
||||
{
|
||||
if (_parity == value) return;
|
||||
_parity = value;
|
||||
OnPropertyChanged(nameof(Parity));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("网络配置")]
|
||||
[DisplayName("IP地址")]
|
||||
[Description("PLC网络地址")]
|
||||
public string IP
|
||||
{
|
||||
get => _ip;
|
||||
set
|
||||
{
|
||||
if (_ip == value) return;
|
||||
_ip = value;
|
||||
OnPropertyChanged(nameof(IP));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("网络配置")]
|
||||
[DisplayName("端口号")]
|
||||
[Description("网络通信端口")]
|
||||
public int Port
|
||||
{
|
||||
get => _port;
|
||||
set
|
||||
{
|
||||
if (_port == value) return;
|
||||
_port = value;
|
||||
OnPropertyChanged(nameof(Port));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("点位配置")]
|
||||
[DisplayName("点位配置")]
|
||||
[Description("点位配置")]
|
||||
public BindingList<PLCItem> PLCItemList
|
||||
{
|
||||
get => _PLCItemList;
|
||||
set
|
||||
{
|
||||
if (_PLCItemList == value) return;
|
||||
_PLCItemList = value;
|
||||
OnPropertyChanged(nameof(PLCItemList));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public virtual bool PLCConnect()
|
||||
{
|
||||
Connected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual bool PLCDisConnect()
|
||||
{
|
||||
Connected = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual Int16 ReadInt16(string address) { return 0; }
|
||||
|
||||
public virtual Int32 ReadInt32(string address) { return 0; }
|
||||
|
||||
public virtual UInt16 ReadUInt16(string address) { return 0; }
|
||||
|
||||
public virtual UInt32 ReadUInt32(string address) { return 0; }
|
||||
public virtual float ReadFloat(string address) { return 0; }
|
||||
public virtual bool ReadBool(string address) { return false; }
|
||||
|
||||
public virtual bool WriteInt16(string address, Int16 value, bool waitForReply = true) { return false; }
|
||||
public virtual bool WriteInt32(string address, Int32 value, bool waitForReply = true) { return false; }
|
||||
|
||||
|
||||
public virtual bool WriteUInt16(string address, UInt16 value, bool waitForReply = true) { return false; }
|
||||
public virtual bool WriteUInt32(string address, UInt32 value, bool waitForReply = true) { return false; }
|
||||
|
||||
public virtual bool WriteFloat(string address, float value, bool waitForReply = true) { return false; }
|
||||
public virtual bool WriteBool(string address, bool value, bool waitForReply = true) { return false; }
|
||||
}
|
||||
|
||||
|
||||
public class PLCItem : NotifyProperty
|
||||
{
|
||||
private bool _selected;
|
||||
private string _name = string.Empty;
|
||||
private EnumPLCDataType _type;
|
||||
private string _value = string.Empty;
|
||||
private bool _startexecute;
|
||||
private int _startindex;
|
||||
private string _address;
|
||||
/// <summary>
|
||||
/// 是否选中
|
||||
/// </summary>
|
||||
public bool Selected
|
||||
{
|
||||
get => _selected;
|
||||
set
|
||||
{
|
||||
if (_selected != value)
|
||||
{
|
||||
_selected = value;
|
||||
OnPropertyChanged(nameof(Selected));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 参数名称
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
if (_name != value)
|
||||
{
|
||||
_name = value;
|
||||
OnPropertyChanged(nameof(Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
public EnumPLCDataType Type
|
||||
{
|
||||
get => _type;
|
||||
set
|
||||
{
|
||||
if (_type != value)
|
||||
{
|
||||
_type = value;
|
||||
OnPropertyChanged(nameof(Type));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 参数类型
|
||||
/// </summary>
|
||||
public string Address
|
||||
{
|
||||
get => _address;
|
||||
set
|
||||
{
|
||||
if (_address != value)
|
||||
{
|
||||
_address = value;
|
||||
OnPropertyChanged(nameof(Address));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 参数值
|
||||
/// </summary>
|
||||
public string Value
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
if (_value != value)
|
||||
{
|
||||
_value = value;
|
||||
OnPropertyChanged(nameof(Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启用状态
|
||||
/// </summary>
|
||||
public bool StartExecute
|
||||
{
|
||||
get => _startexecute;
|
||||
set
|
||||
{
|
||||
if (_startexecute != value)
|
||||
{
|
||||
_startexecute = value;
|
||||
OnPropertyChanged(nameof(StartExecute));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 顺序
|
||||
/// </summary>
|
||||
public int StartIndex
|
||||
{
|
||||
get => _startindex;
|
||||
set
|
||||
{
|
||||
if (_startindex != value)
|
||||
{
|
||||
_startindex = value;
|
||||
OnPropertyChanged(nameof(StartIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CellLink[] cellLinks;
|
||||
[JsonIgnore]
|
||||
public CellLink[] CellLinks
|
||||
{
|
||||
get { return cellLinks; }
|
||||
set
|
||||
{
|
||||
if (cellLinks == value) return;
|
||||
cellLinks = value;
|
||||
OnPropertyChanged(nameof(CellLinks));
|
||||
}
|
||||
}
|
||||
|
||||
//private CellTag[] cellTags;
|
||||
//[JsonIgnore]
|
||||
//public CellTag[] CellTags
|
||||
//{
|
||||
// get { return cellTags; }
|
||||
// set
|
||||
// {
|
||||
// if (cellTags == value) return;
|
||||
// cellTags = value;
|
||||
// OnPropertyChanged(nameof(CellTags));
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
}
|
78
DH.Commons/Base/VisionEngineBase.cs
Normal file
78
DH.Commons/Base/VisionEngineBase.cs
Normal file
@ -0,0 +1,78 @@
|
||||
using System.Collections;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using DH.Commons.Enums;
|
||||
using DH.Commons.Helper;
|
||||
using HalconDotNet;
|
||||
using OpenCvSharp;
|
||||
|
||||
|
||||
|
||||
namespace DH.Commons.Base
|
||||
{
|
||||
/// <summary>
|
||||
/// 视觉处理引擎:1.传统视觉 2.深度学习
|
||||
/// CV深度学习 四大领域
|
||||
/// Image Classification 图像分类:判别图中物体是什么,比如是猫还是狗;
|
||||
/// Semantic Segmentation 语义分割:对图像进行像素级分类,预测每个像素属于的类别,不区分个体;
|
||||
/// Object Detection 目标检测:寻找图像中的物体并进行定位;
|
||||
/// Instance Segmentation 实例分割:定位图中每个物体,并进行像素级标注,区分不同个体;
|
||||
/// </summary>
|
||||
public abstract class VisionEngineBase : DeviceBase
|
||||
{
|
||||
public List<DetectionConfig> DetectionConfigs = new List<DetectionConfig>();
|
||||
#region event
|
||||
public event Action<string, List<double>> OnCropParamsOutput;
|
||||
public event Action<string, Bitmap, List<IShapeElement>> OnDetectionDone;
|
||||
public event Action<string> OnDetectionWarningStop;//有无检测 需要报警停机
|
||||
#endregion
|
||||
//public VisionEngineInitialConfigBase IConfig
|
||||
//{
|
||||
// get => InitialConfig as VisionEngineInitialConfigBase;
|
||||
//}
|
||||
// public ImageSaveHelper ImageSaveHelper { get; set; } = new ImageSaveHelper();
|
||||
public string BatchNO { get; set; }
|
||||
|
||||
public HTuple hv_ModelID;
|
||||
|
||||
public abstract DetectStationResult RunInference(MatSet originImgSet, string detectionId = null);
|
||||
|
||||
//public abstract void SaveDetectResultAsync(DetectStationResult detectResult);
|
||||
|
||||
|
||||
|
||||
public virtual void DetectionDone(string detectionId, Bitmap image, List<IShapeElement> detectionResults)
|
||||
{
|
||||
OnDetectionDone?.Invoke(detectionId, image, detectionResults);
|
||||
}
|
||||
|
||||
public virtual void DetectionWarningStop(string detectionDes)
|
||||
{
|
||||
OnDetectionWarningStop?.Invoke(detectionDes);
|
||||
}
|
||||
public ImageSaveHelper ImageSaveHelper { get; set; } = new ImageSaveHelper();
|
||||
public virtual void SaveImageAsync(string fullname, Bitmap saveMap, ImageFormat imageFormat)
|
||||
{
|
||||
if (saveMap != null)
|
||||
{
|
||||
ImageSaveSet imageSaveSet = new ImageSaveSet()
|
||||
{
|
||||
FullName = fullname,
|
||||
SaveImage = saveMap.CopyBitmap(),
|
||||
ImageFormat = imageFormat.DeepSerializeClone()
|
||||
|
||||
};
|
||||
|
||||
ImageSaveHelper.ImageSaveAsync(imageSaveSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
80
DH.Commons/Base/VisualLocalization.cs
Normal file
80
DH.Commons/Base/VisualLocalization.cs
Normal file
@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace DH.Commons.Base
|
||||
{
|
||||
public class VisualLocalization
|
||||
{
|
||||
// 配置属性
|
||||
public string CameraName { get; set; }
|
||||
public string ModelPath { get; set; }
|
||||
public string ImgPath { get; set; }
|
||||
public string Threshold { get; set; }
|
||||
public string Direction { get; set; }
|
||||
public string Speed { get; set; }
|
||||
|
||||
public string MSpeed { get; set; }
|
||||
|
||||
// 配置文件路径
|
||||
private const string ConfigFile = "VisualConfigs.json";
|
||||
private static readonly object _fileLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// 保存当前配置(存在则更新,不存在则新增)
|
||||
/// </summary>
|
||||
public void Save()
|
||||
{
|
||||
lock (_fileLock)
|
||||
{
|
||||
var list = LoadAll();
|
||||
var existing = list.FirstOrDefault(c => c.CameraName == CameraName);
|
||||
|
||||
if (existing != null)
|
||||
{
|
||||
// 更新现有配置
|
||||
existing.ModelPath = ModelPath;
|
||||
existing.ImgPath = ImgPath;
|
||||
existing.Threshold = Threshold;
|
||||
existing.Direction = Direction;
|
||||
existing.Speed = Speed;
|
||||
existing.MSpeed = MSpeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(this);
|
||||
}
|
||||
|
||||
SaveAll(list);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取全部配置列表
|
||||
/// </summary>
|
||||
public static List<VisualLocalization> LoadAll()
|
||||
{
|
||||
lock (_fileLock)
|
||||
{
|
||||
if (!File.Exists(ConfigFile)) return new List<VisualLocalization>();
|
||||
|
||||
var json = File.ReadAllText(ConfigFile);
|
||||
return JsonSerializer.Deserialize<List<VisualLocalization>>(json)
|
||||
?? new List<VisualLocalization>();
|
||||
}
|
||||
}
|
||||
|
||||
private static void SaveAll(List<VisualLocalization> list)
|
||||
{
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true,
|
||||
IgnoreNullValues = true
|
||||
};
|
||||
|
||||
File.WriteAllText(ConfigFile, JsonSerializer.Serialize(list, options));
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user