335 lines
11 KiB
C#
335 lines
11 KiB
C#
|
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 IoCylinder : BaseDevice, IDevice
|
|||
|
{
|
|||
|
private DIAccessor _diOpened;
|
|||
|
private DIAccessor _diClosed;
|
|||
|
|
|||
|
private DOAccessor _doOpen;
|
|||
|
private DOAccessor _doClose;
|
|||
|
|
|||
|
private CylinderState _operation;
|
|||
|
private DeviceTimer _timer = new DeviceTimer();
|
|||
|
private R_TRIG _trigReset = new R_TRIG();
|
|||
|
private R_TRIG _trigError = new R_TRIG();
|
|||
|
|
|||
|
public bool EnableOpen { get; set; }
|
|||
|
public bool EnableClose { get; set; }
|
|||
|
|
|||
|
public int SetPoint
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (_doOpen.Value && _doClose.Value) return (int) CylinderState.Error;
|
|||
|
if (_doOpen.Value && !_doClose.Value) return (int) CylinderState.Open;
|
|||
|
if (!_doOpen.Value && _doClose.Value) return (int) CylinderState.Close;
|
|||
|
if (!_doOpen.Value && !_doClose.Value) return (int) CylinderState.Unknown;
|
|||
|
|
|||
|
return (int) CylinderState.Unknown;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public CylinderState State
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (_diOpened != null && _diClosed != null)
|
|||
|
{
|
|||
|
if (OpenFeedback && _diClosed.Value)
|
|||
|
return CylinderState.Error;
|
|||
|
|
|||
|
if (OpenFeedback && !_diClosed.Value)
|
|||
|
return CylinderState.Open;
|
|||
|
if (!OpenFeedback && _diClosed.Value)
|
|||
|
return CylinderState.Close;
|
|||
|
if (!OpenFeedback && !_diClosed.Value)
|
|||
|
return CylinderState.Unknown;
|
|||
|
}
|
|||
|
return CylinderState.Unknown;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public bool OpenFeedback
|
|||
|
{
|
|||
|
get { return _diOpened != null && _diOpened.Value; }
|
|||
|
}
|
|||
|
public bool CloseFeedback
|
|||
|
{
|
|||
|
get { return _diClosed != null && _diClosed.Value; }
|
|||
|
}
|
|||
|
public bool OpenSetPoint
|
|||
|
{
|
|||
|
get { return _doOpen != null && _doOpen.Value; }
|
|||
|
set
|
|||
|
{
|
|||
|
if (_doOpen != null && _doOpen.Check(value, out _))
|
|||
|
_doOpen.Value = value;
|
|||
|
}
|
|||
|
}
|
|||
|
public bool CloseSetPoint
|
|||
|
{
|
|||
|
get { return _doClose != null && _doClose.Value; }
|
|||
|
set
|
|||
|
{
|
|||
|
if (_doClose != null && _doClose.Check(value, out _))
|
|||
|
_doClose.Value = value;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private AITCylinderData DeviceData
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
AITCylinderData deviceData = new AITCylinderData
|
|||
|
{
|
|||
|
Module = Module,
|
|||
|
DeviceName = Name,
|
|||
|
DeviceSchematicId = DeviceID,
|
|||
|
DisplayName = Display,
|
|||
|
|
|||
|
OpenFeedback = OpenFeedback,
|
|||
|
CloseFeedback = CloseFeedback,
|
|||
|
OpenSetPoint = OpenSetPoint,
|
|||
|
CloseSetPoint = CloseSetPoint
|
|||
|
};
|
|||
|
|
|||
|
return deviceData;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//public int Status
|
|||
|
//{
|
|||
|
// get
|
|||
|
// {
|
|||
|
// if (OpenFeedback && _diClosed.Value)
|
|||
|
// return (int)CylinderState.Error;
|
|||
|
// if (OpenFeedback && !_diClosed.Value)
|
|||
|
// return (int)CylinderState.Open;
|
|||
|
// if (!OpenFeedback && _diClosed.Value)
|
|||
|
// return (int)CylinderState.Close;
|
|||
|
// if (!OpenFeedback && !_diClosed.Value)
|
|||
|
// return (int)CylinderState.Unknown;
|
|||
|
|
|||
|
// return (int)CylinderState.Unknown;
|
|||
|
// }
|
|||
|
//}
|
|||
|
|
|||
|
public IoCylinder(string module, XmlElement node, string ioModule = "")
|
|||
|
{
|
|||
|
base.Module = node.GetAttribute("module");
|
|||
|
base.Name = node.GetAttribute("id");
|
|||
|
base.Display = node.GetAttribute("display");
|
|||
|
base.DeviceID = node.GetAttribute("schematicId");
|
|||
|
|
|||
|
_diOpened = ParseDiNode("diOpen", node, ioModule);
|
|||
|
_diClosed = ParseDiNode("diClose", node, ioModule);
|
|||
|
_doOpen = ParseDoNode("doOpen", node, ioModule);
|
|||
|
_doClose = ParseDoNode("doClose", node, ioModule);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
public bool Initialize()
|
|||
|
{
|
|||
|
DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData);
|
|||
|
|
|||
|
OP.Subscribe($"{Module}.{Name}.{AITCylinderOperation.Open}", InvokeOpenCylinder);
|
|||
|
OP.Subscribe($"{Module}.{Name}.{AITCylinderOperation.Close}", InvokeCloseCylinder);
|
|||
|
|
|||
|
|
|||
|
DEVICE.Register($"{Name}.{AITCylinderOperation.Open}", (out string reason, int time, object[] param) =>
|
|||
|
{
|
|||
|
bool ret = SetCylinder(true, out reason);
|
|||
|
if (ret)
|
|||
|
{
|
|||
|
reason = string.Format("Open Cylinder {0}", Name);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
});
|
|||
|
|
|||
|
DEVICE.Register($"{Name}.{AITCylinderOperation.Close}", (out string reason, int time, object[] param) =>
|
|||
|
{
|
|||
|
bool ret = SetCylinder(false, out reason);
|
|||
|
if (ret)
|
|||
|
{
|
|||
|
reason = string.Format("Close Cylinder {0}", Name);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
});
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
private bool InvokeOpenCylinder(string arg1, object[] arg2)
|
|||
|
{
|
|||
|
string reason;
|
|||
|
|
|||
|
if (!SetCylinder(true, out reason))
|
|||
|
{
|
|||
|
EV.PostWarningLog(Module, $"Can not open cylinder {Module}.{Name}, {reason}");
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
EV.PostInfoLog(Module, $"Open cylinder {Module}.{Name}");
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
private bool InvokeCloseCylinder(string arg1, object[] arg2)
|
|||
|
{
|
|||
|
string reason;
|
|||
|
|
|||
|
if (!SetCylinder(false, out reason))
|
|||
|
{
|
|||
|
EV.PostWarningLog(Module, $"Can not close cylinder {Module}.{Name}, {reason}");
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
EV.PostInfoLog(Module, $"Close cylinder {Module}.{Name}");
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
public void Terminate()
|
|||
|
{
|
|||
|
CloseSetPoint = false;
|
|||
|
OpenSetPoint = false;
|
|||
|
}
|
|||
|
|
|||
|
public bool SetCylinder(bool isOpen, out string reason)
|
|||
|
{
|
|||
|
if (_doOpen != null)
|
|||
|
{
|
|||
|
if (!_doOpen.Check(isOpen, out reason))
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
if (_doClose != null)
|
|||
|
{
|
|||
|
if (!_doClose.Check(!isOpen, out reason))
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
reason = "";
|
|||
|
|
|||
|
OpenSetPoint = isOpen;
|
|||
|
CloseSetPoint = !isOpen;
|
|||
|
|
|||
|
_operation = isOpen ? CylinderState.Open : CylinderState.Close;
|
|||
|
_timer.Start(1000 * 60 * 3);
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
public void Monitor()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (_diOpened != null && _diClosed != null)
|
|||
|
{
|
|||
|
MonitorSetAndResetValue();
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
LOG.Write(ex);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
private void MonitorSetAndResetValue()
|
|||
|
{
|
|||
|
if (_timer.IsTimeout())
|
|||
|
{
|
|||
|
_timer.Stop();
|
|||
|
|
|||
|
if (State != _operation)
|
|||
|
{
|
|||
|
if (_operation == CylinderState.Open)
|
|||
|
{
|
|||
|
string reason;
|
|||
|
if (!_doOpen.Check(true, out reason))
|
|||
|
EV.PostMessage(Module, EventEnum.DefaultAlarm, "Open Cylinder Failed for interlock, " + reason);
|
|||
|
else
|
|||
|
EV.PostMessage(Module, EventEnum.DefaultAlarm, "Cylinder hold close status");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
string reason;
|
|||
|
if (!_doOpen.Check(false, out reason))
|
|||
|
EV.PostMessage(Module, EventEnum.DefaultAlarm, "Close Cylinder Failed for interlock, " + reason);
|
|||
|
else
|
|||
|
EV.PostMessage(Module, EventEnum.DefaultAlarm, "Cylinder hold open status");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
_operation = (CylinderState) SetPoint;
|
|||
|
}
|
|||
|
else if (_timer.IsIdle())
|
|||
|
{
|
|||
|
_trigReset.CLK = SetPoint != (int) _operation; // fire event only check at first, SetPoint set by interlock
|
|||
|
if (_trigReset.Q)
|
|||
|
{
|
|||
|
if (_operation == CylinderState.Open)
|
|||
|
{
|
|||
|
string reason;
|
|||
|
if (!_doOpen.Check(true, out reason))
|
|||
|
EV.PostMessage(Module, EventEnum.SwInterlock, Module,
|
|||
|
string.Format("Cylinder {0} was {1},Reason:{2}", Display, "Close", reason));
|
|||
|
else
|
|||
|
EV.PostMessage(Module, EventEnum.SwInterlock, Module,
|
|||
|
string.Format("Cylinder {0} was {1},Reason {2}", Display, "Close", "PLC kept"));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
string reason;
|
|||
|
if (!_doOpen.Check(false, out reason))
|
|||
|
EV.PostMessage(Module, EventEnum.SwInterlock, Module,
|
|||
|
string.Format("Cylinder {0} was {1},Reason:{2}", Display, "Open", reason));
|
|||
|
else
|
|||
|
EV.PostMessage(Module, EventEnum.SwInterlock, Module,
|
|||
|
string.Format("Cylinder {0} was {1},Reason {2}", Display, "Open", "PLC Kept"));
|
|||
|
}
|
|||
|
|
|||
|
_operation = (CylinderState) SetPoint;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
_trigError.CLK = State == CylinderState.Error;
|
|||
|
if (_trigError.Q)
|
|||
|
{
|
|||
|
EV.PostMessage(Module, EventEnum.DefaultAlarm, "Cylinder in error status");
|
|||
|
}
|
|||
|
|
|||
|
if ((SetPoint == (int) State) && (SetPoint == (int) CylinderState.Open || SetPoint == (int) CylinderState.Close))
|
|||
|
{
|
|||
|
CloseSetPoint = false;
|
|||
|
OpenSetPoint = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void Reset()
|
|||
|
{
|
|||
|
_trigReset.RST = true;
|
|||
|
_trigError.RST = true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|