using System; using System.Xml; using Aitex.Core.Common.DeviceData; using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Event; using Aitex.Core.RT.IOCore; using Aitex.Core.RT.Log; using Aitex.Core.RT.OperationCenter; using Aitex.Core.Util; namespace Aitex.Core.RT.Device.Unit { public class IoValve : BaseDevice, IDevice { public string GVName { get { return Name; } } public string GVDeviceID { get { return DeviceID; } } public bool GVIsDefaultOpen { get { return _isDefaultOpen; } } [Subscription(AITValveDataPropertyName.SetPoint)] public bool SetPoint //True:open| False:close { get { return _isNc ? _doOpen.Value : !_doOpen.Value; } set { if (_doOpen != null) { _doOpen.Value = _isNc ? value : !value; } if (_doClose != null) { _doClose.Value = _isNc ? !value : value; } } } [Subscription(AITValveDataPropertyName.Status)] public bool Status //True:open | False:close { get { if (_diOpen != null) return _isNc ? _diOpen.Value : !_diOpen.Value; if (_doOpen != null) return _isNc ? _doOpen.Value : !_doOpen.Value; if (_doClose != null) return _isNc ? !_doClose.Value : _doClose.Value; return false; } } private AITValveData DeviceData { get { AITValveData data = new AITValveData() { UniqueName = _uniqueName, DeviceName = GVName, DefaultValue = GVIsDefaultOpen, DeviceSchematicId = DeviceID, DisplayName = Display, Feedback = Status, SetPoint = SetPoint, }; return data; } } /// /// normal closed, 0 关闭,1打开 /// public bool _isNc; /// /// default open /// public bool _isDefaultOpen; private DIAccessor _diOpenSensor; private DIAccessor _diCloseSensor; private DIAccessor _diOpen; private DOAccessor _doOpen; private DOAccessor _doClose; private bool _operation; private R_TRIG eventTrigger = new R_TRIG(); private DeviceTimer _timer = new DeviceTimer(); private string _uniqueName; private object _lockerOperation = new object(); public IoValve(string module, XmlElement node, string ioModule = "") { var attrModule = node.GetAttribute("module"); base.Module = string.IsNullOrEmpty(attrModule) ? module : attrModule; base.Name = node.GetAttribute("id"); base.Display = node.GetAttribute("display"); base.DeviceID = node.GetAttribute("schematicId"); _isNc = Convert.ToBoolean(node.GetAttribute("isNc")); _isDefaultOpen = Convert.ToBoolean(node.GetAttribute("isDefaultOpen")); _diOpenSensor = ParseDiNode("diOpenSensor", node, ioModule); _diCloseSensor = ParseDiNode("diCloseSensor", node, ioModule); _doOpen = ParseDoNode("doOpen", node, ioModule); _diOpen = ParseDiNode("diOpen", node, ioModule); _doClose = ParseDoNode("doClose", node, ioModule); _uniqueName = $"{Module}.{Name}"; } public bool Initialize() { DATA.Subscribe($"{Module}.{GVName}", () => DeviceData); //DATA.Subscribe($"{_uniqueName}.DeviceData", () => DeviceData); OP.Subscribe($"{_uniqueName}.{AITValveOperation.GVTurnValve}", InvokeOpenCloseValve); DEVICE.Register($"{Module}.{Name}.{AITValveOperation.GVTurnValve}", (out string reason, int time, object[] param) => { bool bOn = Convert.ToBoolean((string)param[0]); bool ret = TurnValve(bOn, out reason); if (ret) { reason = string.Format("Valve {0}{1}", Name, bOn ? "Open" : "Close"); return true; } return false; }); //for recipe DEVICE.Register($"{Module}.{Name}", (out string reason, int time, object[] param) => { bool bOn = Convert.ToBoolean((string)param[0]); bool ret = TurnValve(bOn, out reason); if (ret) { reason = string.Format("Valve {0}{1}", Name, bOn ? "Open" : "Close"); return true; } return false; }); return true; } public void Terminate() { TurnValve(_isDefaultOpen, out string reason); } private bool InvokeOpenCloseValve(string method, object[] args) { bool op = (bool)args[0]; string name = op ? "Open" : "Close"; if (!TurnValve(op, out string reason)) { EV.PostWarningLog(Module, $"Can not {name} valve {Module}.{Name}, {reason}"); return false; } EV.PostInfoLog(Module, $"{name} valve {Module}.{Name}"); return true; } public void Monitor() { try { lock (_lockerOperation) { if (_timer.IsTimeout()) { _timer.Stop(); if (Status != _operation) { if (_operation) { EV.PostAlarmLog(Module, _doOpen.Check(_isNc ? true : false, out string reason) ? $"{Display} open: valve keep closed" : $"{Display} Fail to open due to interlock {reason}"); } else { EV.PostAlarmLog(Module, _doOpen.Check(_isNc ? true : false, out string reason) ? $"{Display} Close : Valve keep open" : $"{Display} Close : Failed for interlock {reason}"); } } _operation = SetPoint; } else if (_timer.IsIdle()) { eventTrigger.CLK = SetPoint != _operation; // fire event only check at first, SetPoint set by interlock if (eventTrigger.Q) { if (_operation) { EV.PostAlarmLog(Module, _doOpen.Check(_isNc ? true : false, out string reason) ? $"Valve {Display} was Close,Reason PLC kept" : $"Valve {Display} was Close,Reason {reason}"); } else { EV.PostAlarmLog(Module, _doOpen.Check(_isNc ? true : false, out string reason) ? $"Valve {Display} was Open,Reason PLC Kept" : $"Valve {Display} was Open,Reason:{reason}"); } _operation = SetPoint; } } } } catch (Exception ex) { LOG.Write(ex); } } public bool TurnValve(bool bOperation, out string reason) { lock (_lockerOperation) { bool bValue = _isNc ? bOperation : !bOperation; reason = ""; SetPoint = bValue; _operation = bOperation; _timer.Start(2000); //2 seconds to monitor } return true; } public void Reset() { eventTrigger.RST = true; } } }