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.Util; using MECF.Framework.Common.CommonData.PowerSupplier; using MECF.Framework.Common.Device.PowerSupplier; using MECF.Framework.Common.Equipment; using CyberX8_Core; using CyberX8_RT.Modules.Transporter; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Channels; using System.Threading.Tasks; using System.Windows; namespace CyberX8_RT.Devices.PowerSupplier { public class CellPowerSupplier : BaseDevice, IDevice { private enum PowerSupplierOperation { None=0, StepOperation=1, SetCurrent=2, SetStartOperation=3 } #region 常量 private const string POWERSUPPLIER_DATA = "PowerSupplierData"; private const string SET_POINT = "SetPoint"; private const string CURRENT = "Current"; private const string VOLTAGE = "Voltage"; private const string ENABLED = "Enabled"; private const string CONNECTED = "Connected"; private const string POWER_STATUS = "PowerStatus"; private const string POWER_CONTROL = "PowerControl"; private const string POWER_RUN_MODEL = "PowerRunModel"; private const int CURRENT_UNIT_SCALE = 10000; private const int CURRENT_DEVICE_UNIT_SCALE = 1000; private const int VOLTAGE_DEVICE_SCALE = 10000; #endregion #region 内部变量 /// /// 数据 /// private PowerSupplierData _powerSupplierData; /// /// 通道 /// private byte _channel=0; /// /// 设备参数 /// private PowerSupplierDevice _deviceParameter; /// /// 定时器 /// private PeriodicJob _periodicJob; /// /// 指定读取指令集合 /// private ConcurrentQueue _readCommandList = new ConcurrentQueue(); /// /// 步阶Routine /// private PowerSupplierStepRoutine _powerSupplierStepRoutine; /// /// 设置电流Routine /// private PowerSupplierSetCurrentRoutine _powerSupplierSetCurrentRoutine; /// /// 设置步阶Routine /// private PowerSupplierStartStepRoutine _powerSupplierStartStepRoutine; /// /// 状态 /// private RState _status; /// /// 当前操作 /// private PowerSupplierOperation _currentOperation; /// /// /// 读取电流时间 /// private DateTime _sendDateTime = DateTime.Now; /// /// 连接上升沿 /// private R_TRIG _connectedTrig = new R_TRIG(); /// /// 发送Remote上升沿 /// private R_TRIG _sendRemoteTrig = new R_TRIG(); /// /// 连接成功时间 /// private DateTime _connectTime = DateTime.Now; #endregion #region 属性 /// /// 数据 /// public PowerSupplierData PowerSupplierData { get { return _powerSupplierData; } } /// /// 状态 /// public RState Status { get { return _status; } } /// /// 连接状态 /// public bool IsConnected { get { return PowerSupplierDeviceConfigManager.Instance.GetModuleConnected(Module); } } #endregion /// /// 构造函数 /// /// public CellPowerSupplier(string moduleName) : base(moduleName, moduleName, moduleName, moduleName) { _powerSupplierData = new PowerSupplierData(); _periodicJob = new PeriodicJob(100, OnTimer, $"{Module}.OnTimer", true); } /// /// 初始化 /// /// public bool Initialize() { InitializeOperation(); InitializeData(); InitializeRoutine(); return true; } /// /// 初始化操作 /// private void InitializeOperation() { OP.Subscribe($"{Module}.Enable", EnableOperation); OP.Subscribe($"{Module}.Disable", DisableOperation); OP.Subscribe($"{Module}.SetPoint", SetPointOperation); OP.Subscribe($"{Module}.StartStepPeriod", StartStepPeriod); OP.Subscribe($"{Module}.SetLocalControl", SetLocalOperation); OP.Subscribe($"{Module}.SetRemoteControl", SetRemoteOperation); OP.Subscribe($"{Module}.Abort", AbortOperation); } /// /// 初始化数据 /// private void InitializeData() { _deviceParameter = PowerSupplierDeviceConfigManager.Instance.GetPowerSupplierDeviceByName(Module); if(_deviceParameter!=null) { if(!byte.TryParse(_deviceParameter.Address,out _channel)) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, $"{Module} channel is invalid"); } } else { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, $"{Module} is not in config xml"); } DATA.Subscribe($"{Module}.{POWERSUPPLIER_DATA}", () => _powerSupplierData, Aitex.Core.Util.SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.{CONNECTED}", () => PowerSupplierDeviceConfigManager.Instance.GetModuleConnected(Module), SubscriptionAttribute.FLAG.IgnoreSaveDB); PowerSupplierDeviceConfigManager.Instance.SubscribeModuleVariable(Module, ENABLED, UpdateVariableValue); PowerSupplierDeviceConfigManager.Instance.SubscribeModuleVariable(Module, SET_POINT, UpdateVariableValue); PowerSupplierDeviceConfigManager.Instance.SubscribeModuleVariable(Module, VOLTAGE, UpdateVariableValue); PowerSupplierDeviceConfigManager.Instance.SubscribeModuleVariable(Module, CURRENT, UpdateVariableValue); PowerSupplierDeviceConfigManager.Instance.SubscribeModuleVariable(Module, POWER_STATUS, UpdateVariableValue); PowerSupplierDeviceConfigManager.Instance.SubscribeModuleVariable(Module,POWER_CONTROL, UpdateVariableValue); PowerSupplierDeviceConfigManager.Instance.SubscribeModuleVariable(Module, POWER_RUN_MODEL, UpdateVariableValue); } /// /// 初始化Routine /// private void InitializeRoutine() { _powerSupplierStepRoutine = new PowerSupplierStepRoutine(Module); _powerSupplierSetCurrentRoutine = new PowerSupplierSetCurrentRoutine(Module); _powerSupplierStartStepRoutine= new PowerSupplierStartStepRoutine(Module); } /// /// 更新变量数值 /// /// /// private void UpdateVariableValue(string variable, object value) { PropertyInfo property = PowerSupplierData.GetType().GetProperty(variable); if (property != null) { if (!PowerSupplierData.IsDataInitialized) { PowerSupplierData.IsDataInitialized = true; SetPowerCCStatus(); } if(variable==SET_POINT) { if (double.TryParse(value.ToString(), out double doubleValue)) { property.SetValue(PowerSupplierData, doubleValue / CURRENT_DEVICE_UNIT_SCALE); } else { property.SetValue(PowerSupplierData, value); } } else if(variable==CURRENT) { if (double.TryParse(value.ToString(), out double doubleValue)) { property.SetValue(PowerSupplierData, doubleValue / CURRENT_UNIT_SCALE); } else { property.SetValue(PowerSupplierData, value); } } else if (variable == VOLTAGE) { if (double.TryParse(value.ToString(), out double doubleValue)) { property.SetValue(PowerSupplierData, doubleValue / VOLTAGE_DEVICE_SCALE); } else { property.SetValue(PowerSupplierData, value); } } else { property.SetValue(PowerSupplierData, value); } } } /// /// 定时器 /// /// private bool OnTimer() { bool connected = PowerSupplierDeviceConfigManager.Instance.GetModuleConnected(Module); _connectedTrig.CLK = connected; if (_connectedTrig.Q) { _connectTime = DateTime.Now; return true; } if(!connected) { _connectedTrig.RST = true; PowerSupplierDeviceConfigManager.Instance.StartConnectDevice(Module); return true; } if (!_sendRemoteTrig.Q) { if (DateTime.Now.Subtract(_connectTime).TotalSeconds >= 1) { _sendRemoteTrig.CLK = SetRemoteOperation("", null); SetRemoteOperation("", null); } return true; } if (_readCommandList.Count != 0) { if (_readCommandList.TryDequeue(out string command)) { switch (command) { case ENABLED: PowerSupplierDeviceConfigManager.Instance.GetChannelOutputSwitch(Module, _channel); break; case SET_POINT: PowerSupplierDeviceConfigManager.Instance.GetChannelCurrentSetting(Module, _channel); break; case POWER_STATUS: PowerSupplierDeviceConfigManager.Instance.GetChannelPowerStatus(Module, _channel); break; case POWER_CONTROL: PowerSupplierDeviceConfigManager.Instance.GetChannelPowerControl(Module, _channel); break; case POWER_RUN_MODEL: PowerSupplierDeviceConfigManager.Instance.GetPowerRunmodelControl(Module, _channel); break; } _sendDateTime = DateTime.Now; } } else { //控制模式为local if (PowerSupplierData.PowerControlContent != null && PowerSupplierData.PowerControlContent.ToLower() == "local") { return true; } if (DateTime.Now.Subtract(_sendDateTime).TotalMilliseconds >= 300) { ReadCurrentAndVoltage(); } } if(_status==RState.Running) { IRoutine routine = GetCurrentRoutine(); if (routine != null) { _status = routine.Monitor(); if (_status == RState.Failed || _status == RState.Timeout) { _status = RState.Failed; if(_currentOperation==PowerSupplierOperation.SetCurrent) { DisableOperation("", null); } _currentOperation = PowerSupplierOperation.None; } else if (_status == RState.End) { _currentOperation = PowerSupplierOperation.None; } } } return true; } /// /// 读取电流和电压 /// private void ReadCurrentAndVoltage() { _sendDateTime = DateTime.Now; PowerSupplierDeviceConfigManager.Instance.GetChannelCurrentAndVoltage(Module, _channel); } /// /// 获取比例后的数值 /// /// /// private double GetAfterScaledValue(int value) { return (double)value / (CURRENT_UNIT_SCALE); } #region Operation /// /// Enable Operation /// /// /// /// public bool EnableOperation(string cmd, object[] args) { if (PowerSupplierData == null) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Data is null"); return false; } if (PowerSupplierData.PowerControl == (short)PowerControlEnum.Local) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is local control"); return false; } if (PowerSupplierData.SetPoint==0) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Setpoint is 0,cannot enable output"); return false; } EnableOutput(); LOG.WriteLog(eEvent.INFO_POWERSUPPLIER, Module, $"Power Control enable output Success"); return true; } /// /// Disable Operation /// /// /// /// public bool DisableOperation(string cmd, object[] args) { if(_status==RState.Running) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is Busy"); return false; } DisableOutput(); LOG.WriteLog(eEvent.INFO_POWERSUPPLIER, Module, $"Power Control disable output Success"); return true; } /// /// 中止 /// /// /// /// private bool AbortOperation(string cmd, object[] args) { if(_status==RState.Running) { IRoutine routine = GetCurrentRoutine(); if(routine!=null) { routine.Abort(); } DisableOutput(); PowerSupplierDeviceConfigManager.Instance.SetPowerRunmodelControl(Module, _channel, (byte)PowerRunModelEnum.Normal); LOG.WriteLog(eEvent.INFO_POWERSUPPLIER, Module, $"abort {_currentOperation} operation"); _status = RState.End; _currentOperation = PowerSupplierOperation.None; _readCommandList.Enqueue(POWER_RUN_MODEL); } return true; } /// /// 关闭输出 /// /// public bool DisableOutput() { if(PowerSupplierData==null) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Data is null"); return false; } if(PowerSupplierData.PowerControl==(short)PowerControlEnum.Local) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is local control"); return false; } bool result= PowerSupplierDeviceConfigManager.Instance.SetChannelOutputSwitchControl(Module, _channel, false); _sendDateTime = DateTime.Now; _readCommandList.Enqueue(ENABLED); _readCommandList.Enqueue(POWER_STATUS); return result; } /// /// 启动输出 /// /// public bool EnableOutput() { if (PowerSupplierData == null) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Data is null"); return false; } if (PowerSupplierData.PowerControl == (short)PowerControlEnum.Local) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is local control"); return false; } bool result= PowerSupplierDeviceConfigManager.Instance.SetChannelOutputSwitchControl(Module, _channel, true); _sendDateTime = DateTime.Now; _readCommandList.Enqueue(ENABLED); _readCommandList.Enqueue(POWER_STATUS); return result; } /// /// SetPoint /// /// /// /// public bool SetPointOperation(string cmd, object[] args) { if (_status == RState.Running) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is Busy"); return false; } if (PowerSupplierData == null) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Data is null"); return false; } if (PowerSupplierData.PowerControl == (short)PowerControlEnum.Local) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is local control"); return false; } if (args.Length<2) { return false; } if (double.TryParse(args[1].ToString(), out double value)) { SetCurrent(value); } return true; } /// /// 设置电流 /// /// /// public bool SetCurrent(double current) { PowerSupplierDeviceConfigManager.Instance.SetPowerRunmodelControl(Module, _channel, (byte)PowerRunModelEnum.Normal); ushort setPoint = (ushort)Math.Round(CURRENT_DEVICE_UNIT_SCALE * current, 0); bool result= PowerSupplierDeviceConfigManager.Instance.SetChannelCurrent(Module, _channel, setPoint); _sendDateTime = DateTime.Now; if (result) { LOG.WriteLog(eEvent.INFO_POWERSUPPLIER, Module, $"Current {current} Setting success"); _readCommandList.Enqueue(SET_POINT); _readCommandList.Enqueue(POWER_RUN_MODEL); return true; } else { return false; } } /// /// 启动 /// /// /// /// private bool StartStepPeriod(string cmd, object[] args) { if (_status == RState.Running) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is Busy"); return false; } if (PowerSupplierData == null) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Data is null"); return false; } if (PowerSupplierData.PowerControl == (short)PowerControlEnum.Local) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is local control"); return false; } bool result= _powerSupplierStepRoutine.Start(args)==RState.Running; if(result) { _status = RState.Running; _currentOperation = PowerSupplierOperation.StepOperation; } return result; } /// /// 启动设置步阶, /// /// /// /// public bool StartSetStepPeriodNoWaitEnd(List datas) { if (_status == RState.Running) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is Busy"); return false; } if (PowerSupplierData == null) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Data is null"); return false; } if (PowerSupplierData.PowerControl == (short)PowerControlEnum.Local) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is local control"); return false; } bool result = _powerSupplierStartStepRoutine.Start(datas) == RState.Running; if (result) { _status = RState.Running; _currentOperation = PowerSupplierOperation.SetStartOperation; } return result; } /// /// 设置步阶 /// /// /// /// public bool SetStepPeriod(string cmd, object[] args) { List powerSupplierStepPeriodDatas = (List)args[1]; bool result=PowerSupplierDeviceConfigManager.Instance.SetStepPeriod(Module, _channel, powerSupplierStepPeriodDatas,CURRENT_DEVICE_UNIT_SCALE); _sendDateTime = DateTime.Now; if (result) { LOG.WriteLog(eEvent.INFO_POWERSUPPLIER, Module, $"Step Period Set Success"); return true; } else { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, $"Step Period Set Fail"); return false; } } /// /// 启动步阶 /// /// /// /// public bool StartStepPeriod(ushort endStep,ushort cycle) { bool result = PowerSupplierDeviceConfigManager.Instance.StartStepPeriod(Module, _channel, 1, endStep, cycle); _sendDateTime= DateTime.Now; return result; } /// /// 设置电源运行模式 /// /// /// public bool SwitchPowerRunModel(byte runModel) { bool result= PowerSupplierDeviceConfigManager.Instance.SetPowerRunmodelControl(Module,_channel, runModel); _sendDateTime = DateTime.Now; _readCommandList.Enqueue(POWER_RUN_MODEL); return result; } /// /// 设置本地模式 /// /// /// /// private bool SetLocalOperation(string cmd, object[] args) { if (_status == RState.Running) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is Busy"); return false; } bool result= PowerSupplierDeviceConfigManager.Instance.SetChannelPowerControl(Module, _channel, 1); _sendDateTime = DateTime.Now; if (result) { LOG.WriteLog(eEvent.INFO_POWERSUPPLIER, Module, $"Power Control Switch Local Control Success"); _readCommandList.Enqueue(POWER_CONTROL); return true; } else { return false; } } /// /// 设置远程模式 /// /// /// /// private bool SetRemoteOperation(string cmd, object[] args) { if (_status == RState.Running) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is Busy"); return false; } bool result= PowerSupplierDeviceConfigManager.Instance.SetChannelPowerControl(Module, _channel, 2); _sendDateTime = DateTime.Now; if (result) { LOG.WriteLog(eEvent.INFO_POWERSUPPLIER, Module, $"Power Control Switch Remote Control Success"); _readCommandList.Enqueue(POWER_CONTROL); return true; } else { return false; } } /// /// 设置电流并设置输出 /// /// /// /// public bool SetCurrentAndOutput(double current) { if (_status == RState.Running) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is Busy"); return false; } if (PowerSupplierData == null) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Data is null"); return false; } if (PowerSupplierData.PowerControl == (short)PowerControlEnum.Local) { LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, Module, "Power Supplier is local control"); return false; } bool result = _powerSupplierSetCurrentRoutine.Start(current) == RState.Running; if (result) { _status = RState.Running; _currentOperation = PowerSupplierOperation.SetCurrent; } return result; } /// /// 获取当前的routine /// /// private IRoutine GetCurrentRoutine() { switch(_currentOperation) { case PowerSupplierOperation.StepOperation: return _powerSupplierStepRoutine; case PowerSupplierOperation.SetCurrent: return _powerSupplierSetCurrentRoutine; case PowerSupplierOperation.SetStartOperation: return _powerSupplierStartStepRoutine; default: return null; } } /// /// 设置CC电源状态 /// private void SetPowerCCStatus() { _readCommandList.Enqueue(POWER_STATUS); _readCommandList.Enqueue(SET_POINT); _readCommandList.Enqueue(ENABLED); _readCommandList.Enqueue(POWER_CONTROL); _readCommandList.Enqueue(POWER_RUN_MODEL); } #endregion public void Monitor() { } public void Reset() { } public void Terminate() { DisableOutput(); } } }