using System; using System.Xml; using Aitex.Core.RT.Device; using MECF.Framework.Common.Communications; using MECF.Framework.Common.Event; namespace MECF.Framework.Common.PLC { public class WcfPlc : BaseDevice, IConnection, IConnectable, IAdsPlc, IDevice { private WcfPlcServiceClient _plcClient; private FsmConnection _connection; private int _heartbeat = 1; public AlarmEventItem AlarmConnectFailed { get; set; } public AlarmEventItem AlarmCommunicationError { get; set; } public string Address { get; } public bool IsConnected { get; set; } public event Action OnConnected; public event Action OnDisconnected; public event Action OnCommunicationError; public event Action OnAsciiDataReceived; public event Action OnBinaryDataReceived; public WcfPlc(string module, XmlElement node, string ioModule = "") { string attribute = node.GetAttribute("module"); base.Module = (string.IsNullOrEmpty(attribute) ? module : attribute); base.Name = node.GetAttribute("id"); } public bool Initialize() { _plcClient = new WcfPlcServiceClient(); AlarmConnectFailed = SubscribeAlarm(base.Module + "." + base.Name + ".ConnectionError", "Can not connect with " + Address, null); AlarmCommunicationError = SubscribeAlarm(base.Module + "." + base.Name + ".CommunicationError", "Can not Communication " + Address, null); _connection = new FsmConnection(Name); IConnectionContext config = new StaticConnectionContext { IsEnabled = true, Address = "WCF PLC", EnableCheckConnection = false, EnableLog = false, MaxRetryConnectCount = 3, IsAscii = false, NewLine = string.Empty, RetryConnectIntervalMs = 1000 }; _connection.OnConnected += _connection_OnConnected; _connection.OnDisconnected += _connection_OnDisconnected; _connection.OnError += _connection_OnError; _connection.Initialize(50, this, config); return true; } private void _connection_OnError(string error) { AlarmConnectFailed.Set(error); } private void _connection_OnDisconnected() { if (this.OnDisconnected != null) { this.OnDisconnected(); } } private void _connection_OnConnected() { if (this.OnConnected != null) { this.OnConnected(); } } public void Monitor() { } public void Terminate() { } public void Reset() { ResetAlarm(); _connection.InvokeReset(); } public bool Connect() { _connection.InvokeConnect(); return true; } public bool Disconnect() { _connection.InvokeDisconnect(); return true; } public bool Connect(out string reason) { reason = string.Empty; return true; } public bool Disconnect(out string reason) { reason = string.Empty; return true; } public bool CheckIsConnected() { if (_plcClient == null) { return false; } _heartbeat++; if (_plcClient.Heartbeat(_heartbeat) > 0 && !_plcClient.ActionFailed) { return true; } return false; } public bool SendBinaryData(byte[] data) { return true; } public bool SendAsciiData(string data) { return true; } public bool Read(string variable, out object data, string type, int length, out string reason) { if (!_connection.IsConnected) { reason = "Not connected with PLC"; data = null; return false; } if (base.HasAlarm) { reason = "Has alarm"; data = null; return false; } bool result = _plcClient.Read(variable, out data, type, length, out reason); if (data == null || _plcClient.ActionFailed) { AlarmCommunicationError.Description = "Failed read PLC data"; AlarmCommunicationError.Set(); return false; } return result; } public bool WriteArrayElement(string variable, int index, object value, out string reason) { if (!_connection.IsConnected) { reason = "Not connected with PLC"; return false; } if (base.HasAlarm) { reason = "Has alarm"; return false; } bool result = _plcClient.WriteArrayElement(variable, index, value, out reason); if (_plcClient.ActionFailed) { AlarmCommunicationError.Description = "Failed read PLC data"; AlarmCommunicationError.Set(); return false; } return result; } public bool BulkReadRenderResult(string Adrress, ushort length, out byte[] data) { throw new NotImplementedException(); } public bool BulkWriteFloatRenderResult(string Adrress, float data) { throw new NotImplementedException(); } public bool BulkWriteByteRenderResult(string Adrress, byte[] data) { throw new NotImplementedException(); } } }