using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using MECF.Framework.Common.Algorithm;
using MECF.Framework.Common.Beckhoff.ModuleIO;
using MECF.Framework.Common.CommonData.Prewet;
using MECF.Framework.Common.Persistent.Prewet;
using MECF.Framework.Common.TwinCat;
using CyberX8_Core;
using System;
using System.Collections.Generic;
using System.Reflection;
using CyberX8_RT.Modules;
using CyberX8_RT.Modules.Prewet;
using CyberX8_RT.Modules.Metal;
using MECF.Framework.Common.Persistent.Temperature;
using MECF.Framework.Common.IOCore;
namespace CyberX8_RT.Devices.Prewet
{
public class PrewetDevice : BaseDevice, IDevice
{
private enum PrewetOperation
{
None,
PumpEnable,
PumpDisable
}
#region 常量
private const string PUMP_VALVE = "PumpValve";
private const string PUMP_ENABLE = "PumpEnable";
private const string PUMP_SPEED = "PumpSpeed";
private const string PUMP_STAUS = "PumpStatus";
private const string PUMP_CURRENT = "PumpCurrent";
private const string PUMP_FLOW = "PumpFlow";
private const string PUMP_PRESSURE = "PumpPressure";
private const string PUMP_DATA = "PumpData";
private const string PERSISTENT_VALUE = "PersistentValue";
#endregion
#region 内部变量
///
/// 数据
///
private PrewetPumpData _prewetPumpData=new PrewetPumpData();
///
/// pdi控制中的p
///
private double _pumpKp;
///
/// pdi控制中的i
///
private double _pumpKi;
///
/// pdi控制中的d
///
private double _pumpKd;
///
/// 操作当前状态
///
private RState _status;
///
/// 当前操作
///
private PrewetOperation _currentOperation;
///
/// Prewet 持久性数值对象
///
private PrewetPersistentValue _prewetPersistentValue;
///
/// Pump Enable routine
///
private PrewetPumpEnableRoutine _prewetPumpEnableRoutine;
///
/// Pump Disable routine
///
private PrewetPumpDisableRoutine _prewetPumpDisableRoutine;
///
/// 上一次Pump速度
///
private short _lastPumpSpeed;
///
/// 变量是否初始化字典
///
private Dictionary _variableInitializeDic = new Dictionary();
///
/// 定时器Job
///
PeriodicJob _periodicJob = null;
///
/// Run recipe total time
///
public int _runRecipeTotalTime;
#endregion
#region 属性
///
/// Pump 数据
///
public PrewetPumpData PrewetPumpData { get { return _prewetPumpData; } }
///
/// 操作当前状态
///
public RState Status { get { return _status; } }
///
/// 所有io变量是否初始化
///
public bool IOInitialized { get { return AllIoVariableInitialized(); } }
///
/// Last Pump Speed
///
public short LastPumpSpeed { get { return _lastPumpSpeed; } }
/// 是否启动调速
///
public bool IsStartAutoSpeed { get; set; }
#endregion
///
/// 构造函数
///
///
///
public PrewetDevice(string moduleName) : base(moduleName, moduleName,moduleName,moduleName)
{
_prewetPumpData = new PrewetPumpData();
_prewetPumpData.PumpPressureData = new MECF.Framework.Common.CommonData.CommonLimitData();
_prewetPumpData.PumpFlowData = new MECF.Framework.Common.CommonData.CommonLimitData();
_periodicJob = new PeriodicJob(100, OnTimer, $"{Module}.OnTimer", true);
}
///
/// 初始化
///
///
public bool Initialize()
{
InitializeParameter();
InitializeRoutine();
SubscribeData();
SubscribeValueAction();
InitializeOperation();
return true;
}
///
/// 初始化参数
///
private void InitializeParameter()
{
_prewetPersistentValue = PrewetPersistentManager.Instance.GetPrewetPersistentValue(Module);
if (_prewetPersistentValue != null)
{
_lastPumpSpeed = _prewetPersistentValue.Speed;
}
else
{
LOG.WriteLog(eEvent.ERR_PREWET, Module, "Persistent Value Object is not exist");
}
}
///
/// 初始化Routine
///
private void InitializeRoutine()
{
_prewetPumpEnableRoutine = new PrewetPumpEnableRoutine(Module, this, _prewetPersistentValue);
_prewetPumpDisableRoutine = new PrewetPumpDisableRoutine(Module, this, _prewetPersistentValue);
}
///
/// 订阅数据
///
private void SubscribeData()
{
DATA.Subscribe($"{Module}.{PERSISTENT_VALUE}", () => _prewetPersistentValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.{PUMP_DATA}", () => PrewetPumpData, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.OfTotalTime", () => _runRecipeTotalTime ,SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.PumpStatus", () => PrewetPumpData.PumpStatus, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.PumpCurrent",()=>PrewetPumpData.PumpCurrent,SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.PumpSpeed", () => _lastPumpSpeed, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.PumpEnable", () => PrewetPumpData.PumpEnable, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.PumpValve", () => PrewetPumpData.PumpValve, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.PumpFlow", () => PrewetPumpData.PumpFlowData.Value, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.PumpFlow.MinWarning", () => PrewetPumpData.PumpFlowData.MinWarning, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.PumpFlow.MaxWarning", () => PrewetPumpData.PumpFlowData.MaxWarning, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.PumpFlow.MinError", () => PrewetPumpData.PumpFlowData.MinError, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.PumpFlow.MaxError", () => PrewetPumpData.PumpFlowData.MaxError, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.PumpPressure", () => PrewetPumpData.PumpPressureData.Value, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.PumpPressure.MinWarning", () => PrewetPumpData.PumpPressureData.MinWarning, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.PumpPressure.MaxWarning", () => PrewetPumpData.PumpPressureData.MaxWarning, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.PumpPressure.MinError", () => PrewetPumpData.PumpPressureData.MinError, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.PumpPressure.MaxError", () => PrewetPumpData.PumpPressureData.MaxError, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{Module}.TargetPressure", () => PrewetPumpData.PressureTarget, SubscriptionAttribute.FLAG.IgnoreSaveDB);
}
///
/// 订阅变量数值发生变化
///
private void SubscribeValueAction()
{
BeckhoffIoSubscribeUpdateVariable( PUMP_VALVE);
BeckhoffIoSubscribeUpdateVariable( PUMP_ENABLE);
BeckhoffIoSubscribeUpdateVariable( PUMP_STAUS);
BeckhoffIoSubscribeUpdateVariable( PUMP_CURRENT);
BeckhoffIoSubscribeUpdateVariable( PUMP_PRESSURE);
BeckhoffIoSubscribeUpdateVariable( PUMP_FLOW);
}
///
/// 订阅IO变量
///
///
private void BeckhoffIoSubscribeUpdateVariable(string variable)
{
_variableInitializeDic[variable] = false;
IOModuleManager.Instance.SubscribeModuleVariable(Module, variable, UpdateVariableValue);
}
///
/// 更新变量数值
///
///
///
private void UpdateVariableValue(string variable, object value)
{
if (!PrewetPumpData.IsDataInitialized)
{
PrewetPumpData.IsDataInitialized = true;
PrewetPumpData.PumpModel = "Manual";
}
PropertyInfo property = PrewetPumpData.GetType().GetProperty(variable);
if (property != null)
{
property.SetValue(PrewetPumpData, value);
}
if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
{
_variableInitializeDic[variable] = true;
}
switch (variable)
{
case PUMP_STAUS:
string statusContent = PrewetPumpData.PumpStatus ? "On" : "Off";
PrewetPumpData.PumpStatusContent = $"{PrewetPumpData.PumpModel}: {statusContent}";
break;
case PUMP_FLOW:
if (double.TryParse(value.ToString(), out var flow))
{
PrewetPumpData.PumpFlowData.Value = flow;
}
break;
case PUMP_PRESSURE:
if(double.TryParse(value.ToString(),out var pressure))
{
PrewetPumpData.PumpPressureData.Value = pressure;
}
break;
}
}
///
/// 是否所有IO变量初始化完成
///
///
private bool AllIoVariableInitialized()
{
foreach (string item in _variableInitializeDic.Keys)
{
if (!_variableInitializeDic[item])
{
LOG.WriteLog(eEvent.ERR_PREWET, Module, $"{item} is not initialized");
return false;
}
}
return true;
}
///
/// 初始化操作
///
private void InitializeOperation()
{
OP.Subscribe($"{Module}.PumpValveOn", PumpValveOnOperation);
OP.Subscribe($"{Module}.PumpValveOff", PumpValveOffOperation);
OP.Subscribe($"{Module}.PumpEnable", PumpEnableOperation);
OP.Subscribe($"{Module}.PumpDisable", PumpDisableOperation);
OP.Subscribe($"{Module}.PumpSpeedManual", PumpSpeedManualOperation);
OP.Subscribe($"{Module}.PumpSpeedAuto", PumpSpeedAutoOperation);
OP.Subscribe($"{Module}.PumpSpeedKeyDown", PumpSpeedKeyDownOperation);
OP.Subscribe($"{Module}.DisabledAction", DisabledOperation);
OP.Subscribe($"{Module}.ManualAction", ManualOperation);
OP.Subscribe($"{Module}.AutoAction", AutoOperation);
OP.Subscribe($"{Module}.EngineeringModeAction", EngineeringModeOperation);
OP.Subscribe($"{Module}.ProductionModeAction", ProductionModeOperation);
}
///
/// 定时器
///
///
private bool OnTimer()
{
PrewetPumpData.PumpFlowData.MinError = SC.GetValue($"Prewet.PumpFlow.Error_Min");
PrewetPumpData.PumpFlowData.MinWarning = SC.GetValue($"Prewet.PumpFlow.Warning_Min");
PrewetPumpData.PumpFlowData.MaxError = SC.GetValue($"Prewet.PumpFlow.Error_Max");
PrewetPumpData.PumpFlowData.MaxWarning = SC.GetValue($"Prewet.PumpFlow.Warning_Max");
PrewetPumpData.PumpPressureData.MinError = SC.GetValue($"Prewet.PumpPressure.Error_Min");
PrewetPumpData.PumpPressureData.MinWarning = SC.GetValue($"Prewet.PumpPressure.Warning_Min");
PrewetPumpData.PumpPressureData.MaxError = SC.GetValue($"Prewet.PumpPressure.Error_Max");
PrewetPumpData.PumpPressureData.MaxWarning = SC.GetValue($"Prewet.PumpPressure.Warning_Max");
PrewetPumpData.PressureTarget = SC.GetValue($"Prewet.PressureTarget");
if (_status == RState.Running)
{
IRoutine routine = GetCurrentRoutine();
if (routine != null)
{
RState rsState = routine.Monitor();
if (rsState == RState.Failed || rsState == RState.Timeout)
{
_status = RState.Failed;
_currentOperation = PrewetOperation.None;
LOG.WriteLog(eEvent.ERR_LINMOT, Module.ToString(), $"{_currentOperation} error");
IsStartAutoSpeed = false;
}
else if (rsState == RState.End)
{
if (_currentOperation == PrewetOperation.PumpEnable)
{
IsStartAutoSpeed = true;
}
else
{
IsStartAutoSpeed = false;
}
_status = RState.End;
_currentOperation = PrewetOperation.None;
}
}
}
if (IsStartAutoSpeed)
{
AdjustPumpSpeed();
}
return true;
}
///
/// 调速
///
public void AdjustPumpSpeed()
{
//Speed Auto模式同时pump enbled,根据kdi调整泵速
if (PrewetPumpData.PumpSpeedAuto && PrewetPumpData.PumpEnable)
{
_pumpKp = SC.GetValue($"Prewet.PumpKp");
_pumpKd = SC.GetValue($"Prewet.PumpKd");
_pumpKi = SC.GetValue($"Prewet.PumpKi");
double limit = SC.GetValue("Prewet.PrewetTargetLimit");
short speed = PdiAlgorithm.Instance.CalculateSpeed(_pumpKp, _pumpKi, _pumpKd, PrewetPumpData.PressureTarget,
PrewetPumpData.PumpPressureData.Value, _lastPumpSpeed,limit);
if (Math.Abs(speed - _lastPumpSpeed) >= 1)
{
_lastPumpSpeed = speed;
PumpSpeed(speed);
}
}
else
{
IsStartAutoSpeed = false;
}
}
///
/// 当前Routine;
///
///
private IRoutine GetCurrentRoutine()
{
switch (_currentOperation)
{
case PrewetOperation.PumpEnable:
return _prewetPumpEnableRoutine;
case PrewetOperation.PumpDisable:
return _prewetPumpDisableRoutine;
default:
return null;
}
}
#region Operation
///
/// DisabledAction
///
///
///
///
private bool DisabledOperation(string cmd, object[] args)
{
string currentOperation = "Disabled";
PrewetEntity prewetEntity = Singleton.Instance.GetModule(Module);
if (prewetEntity == null || _prewetPersistentValue == null) return false;
if (_prewetPersistentValue.OperatingMode != "Disabled") prewetEntity.EnterInit();
_prewetPersistentValue.OperatingMode = currentOperation;
PrewetPersistentManager.Instance.UpdatePersistentValue(Module);
return true;
}
///
/// ManualAction
///
///
///
///
private bool ManualOperation(string cmd, object[] args)
{
string currentOperation = "Manual";
PrewetEntity prewetEntity = Singleton.Instance.GetModule(Module);
if (prewetEntity == null || _prewetPersistentValue == null) return false;
if (_prewetPersistentValue.OperatingMode == "Auto" && prewetEntity.IsBusy)
{
LOG.WriteLog(eEvent.ERR_PREWET, Module, $"{Module} is Busy, can't change to manual mode");
return false;
}
if (_prewetPersistentValue.OperatingMode != "Manual") prewetEntity.EnterInit();
_prewetPersistentValue.OperatingMode = currentOperation;
PrewetPersistentManager.Instance.UpdatePersistentValue(Module);
return true;
}
///
/// AutoAction
///
///
///
///
private bool AutoOperation(string cmd, object[] args)
{
string currentOperation = "Auto";
PrewetEntity prewetEntity = Singleton.Instance.GetModule(Module);
if (prewetEntity == null || _prewetPersistentValue == null) return false;
if (_prewetPersistentValue.OperatingMode != "Auto") prewetEntity.EnterInit();
_prewetPersistentValue.OperatingMode = currentOperation;
PrewetPersistentManager.Instance.UpdatePersistentValue(Module);
return true;
}
///
/// EngineeringModeAction
///
///
///
///
private bool EngineeringModeOperation(string cmd, object[] args)
{
string currentRecipeOperation = "Engineering";
_prewetPersistentValue.RecipeOperatingMode=currentRecipeOperation;
PrewetPersistentManager.Instance.UpdatePersistentValue(Module);
return true;
}
///
/// ProductionAction
///
///
///
///
private bool ProductionModeOperation(string cmd, object[] args)
{
string currentRecipeOperation = "Production";
_prewetPersistentValue.RecipeOperatingMode = currentRecipeOperation;
PrewetPersistentManager.Instance.UpdatePersistentValue(Module);
return true;
}
///
/// Pump Valve On
///
///
///
///
public bool PumpValveOnOperation(string cmd, object[] param)
{
return PumpValveOpen();
}
///
/// Pump Valve Off
///
///
///
///
public bool PumpValveOffOperation(string cmd, object[] param)
{
return PumpValveClose();
}
///
/// Pump Valve Open
///
///
public bool PumpValveOpen()
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{PUMP_VALVE}");
return IOModuleManager.Instance.WriteIoValue(ioName, true);
}
///
/// Pump Valve Close
///
///
public bool PumpValveClose()
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{PUMP_VALVE}");
bool result= IOModuleManager.Instance.WriteIoValue(ioName, false);
if(result && PrewetPumpData.PumpEnable)
{
PumpDisable();
}
return result;
}
///
/// Pump Enable操作
///
///
///
///
public bool PumpEnableOperation(string cmd, object[] param)
{
if (_status == RState.Running)
{
LOG.WriteLog(eEvent.ERR_PREWET, Module.ToString(), $"{Module} current execute {_currentOperation},cannot Pump enable");
return false;
}
_status = _prewetPumpEnableRoutine.Start();
_currentOperation = PrewetOperation.PumpEnable;
return _status==RState.Running;
}
///
/// pump disable 操作
///
///
///
///
public bool PumpDisableOperation(string cmd, object[] param)
{
if (_status == RState.Running)
{
LOG.WriteLog(eEvent.ERR_PREWET, Module.ToString(), $"{Module} current execute {_currentOperation},cannot Pump disable");
return false;
}
_status = _prewetPumpDisableRoutine.Start();
_currentOperation = PrewetOperation.PumpDisable;
return _status == RState.Running;
//return PumpDisable();
}
///
/// Pump enable
///
///
public bool PumpEnable()
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{PUMP_ENABLE}");
return IOModuleManager.Instance.WriteIoValue(ioName, true);
}
///
/// Pump disable
///
///
public bool PumpDisable()
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{PUMP_ENABLE}");
return IOModuleManager.Instance.WriteIoValue(ioName, false);
}
///
/// 写入Pump速度
///
///
///
public bool PumpSpeed(short speed=0)
{
string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{PUMP_SPEED}");
return IOModuleManager.Instance.WriteIoValue(ioName, speed==0?_lastPumpSpeed:speed);
}
///
/// Pump Speed手动模式
///
///
///
///
public bool PumpSpeedManualOperation(string cmd, object[] param)
{
PrewetPumpData.PumpSpeedAuto = false;
PrewetPumpData.PumpModel = "Manual";
string statusContent = PrewetPumpData.PumpStatus ? "On" : "Off";
PrewetPumpData.PumpStatusContent = $"{PrewetPumpData.PumpModel}: {statusContent}";
return true;
}
///
/// Pump Speed自动模式
///
///
///
///
public bool PumpSpeedAutoOperation(string cmd, object[] param)
{
PrewetPumpData.PumpSpeedAuto = true;
PrewetPumpData.PumpModel = "Auto";
string statusContent = PrewetPumpData.PumpStatus ? "On" : "Off";
PrewetPumpData.PumpStatusContent = $"{PrewetPumpData.PumpModel}: {statusContent}";
return true;
}
///
/// Pump Speed回车操作
///
///
///
///
public bool PumpSpeedKeyDownOperation(string cmd, object[] param)
{
if (PrewetPumpData.PumpSpeedAuto)
{
LOG.WriteLog(eEvent.ERR_PREWET, Module, "Pump speed is auto,cannot change speed");
return false;
}
short speed=(short)param[0];
bool result = PumpSpeed(speed);
if(result)
{
_prewetPersistentValue.Speed = speed;
_lastPumpSpeed = speed;
PrewetPersistentManager.Instance.UpdatePersistentValue(Module);
}
return true;
}
///
/// 中止当前Routine
///
public void AbortCurrentRoutine()
{
if (_status == RState.Running)
{
IRoutine routine = GetCurrentRoutine();
if (routine != null)
{
routine.Abort();
_currentOperation = PrewetOperation.None;
}
}
}
#endregion
#region 设备接口
///
/// 监控
///
public void Monitor()
{
}
public void Reset()
{
}
public void Terminate()
{
_prewetPersistentValue.Speed = _lastPumpSpeed;
PrewetPersistentManager.Instance.UpdatePersistentValue(Module);
_periodicJob.Stop(false);
}
#endregion
}
}