using Bro.Common.Helper; using Bro.Common.Interface; using Newtonsoft.Json; using System; using System.ComponentModel; using System.Threading; using static Bro.Common.Helper.EnumHelper; namespace Bro.Common.Base { public abstract class DeviceBase : IDevice { #region Event [JsonIgnore] [Browsable(false)] public Action OnExceptionOccured { get; set; } public event Action OnLog; public event Action OnDeviceStateChanged; public event PropertyChangedEventHandler PropertyChanged; #endregion #region field int RetryTime = 3; /// /// 和设备暂停状态关联的信号量 /// private ManualResetEvent pauseHandle = new ManualResetEvent(true); Timer stateChangedTimer; #endregion #region Property #region State private EnumHelper.DeviceState _currentStateToBe = EnumHelper.DeviceState.DSUninit; /// /// 当前设备状态 /// [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 /// /// 设备标识符 从数据库获取 /// public string Id { get; set; } /// /// 设备名称 从数据库获取 /// public string Name { get; set; } private IInitialConfig initialConfig = null; /// /// 设备初始化配置 从数据库获取 /// public virtual IInitialConfig InitialConfig { get => initialConfig; set { initialConfig = value; this.Id = initialConfig.Id; this.Name = initialConfig.Name; LoggerHelper.LogPath = initialConfig.LogPath; LoggerHelper.LogPrefix = initialConfig.Name; } } #endregion public DeviceBase() { stateChangedTimer = new Timer(new TimerCallback(CheckDeviceOpTimeOut), null, Timeout.Infinite, Timeout.Infinite); } #region 设备抽象方法 protected abstract void Init(); protected abstract void Pause(); protected abstract void Resume(); protected abstract void Start(); protected abstract void Stop(); public abstract void AttachToProcess(IProcess process); #endregion #region IDispose public virtual void Dispose() { } #endregion [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 (this.CurrentState != EnumHelper.DeviceState.DSExcept) { 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); } } #region 日志处理 public LoggerHelper LoggerHelper { get; set; } = new LoggerHelper(); public virtual void LogAsync(DateTime dt, string prefix, string msg) { OnLog?.BeginInvoke(dt, this, prefix + "\t" + msg, null, null); if (InitialConfig.IsEnableLog) { LoggerHelper.LogAsync(dt, prefix, msg); } } #endregion } }