Sic.Framework-Nanjing-Baishi/MECF.Framework.RT.Equipment.../Devices/TcAds.cs

422 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using MECF.Framework.Common.Communications;
using MECF.Framework.Common.Event;
using MECF.Framework.Common.PLC;
using MECF.Framework.RT.Core.IoProviders.Siemens;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.OffsetManage;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml;
namespace Aitex.Core.RT.Device.Devices
{
public class TcAds : BaseDevice, IConnectable, IConnectionContext, IDevice, IConnection, IAdsPlc
{
#region IConnectionContext
public int RetryConnectIntervalMs => 1000;
//这个属性是底层库重连次数,超过重连次数,以后不在重新连接
public int MaxRetryConnectCount => 5;
public bool EnableCheckConnection => true;
public virtual string Address { get; }
public bool IsAscii { get; }
public string NewLine { get; }
public bool EnableLog { get; }
private int MaxFailCount = 3;
private int readPLCFailCount;
private R_TRIG trig_readPLCFailCount = new R_TRIG();
private int writePLCFailCount;
private R_TRIG trig_writePLCFailCount = new R_TRIG();
private R_TRIG trig_Reconnection = new R_TRIG();
private PeriodicJob _thread;
#endregion IConnectionContext
#region IConnectable
public event Action<string> OnCommunicationError;
public event Action<string> OnAsciiDataReceived;
public event Action<byte[]> OnBinaryDataReceived;
#endregion IConnectable
public event Action OnDisconnected;
bool IAdsPlc.CheckIsConnected()
{
return Connection.IsConnected;
}
bool IConnection.IsConnected
{
get
{
return Connection.IsConnected;
}
}
bool IConnection.Connect()
{
Connect(out _);
return true;
}
bool IConnection.Disconnect()
{
Disconnect(out _);
return true;
}
public FsmConnection Connection { get; set; } = new FsmConnection();
//public bool IsCommunicationError
//{
// get
// {
// return _isCommunicationError;
// }
//}
//private bool _isCommunicationError;
private OffsetManager offset;
private OperateResult connect;
public SiemensS7Net siemensTcpNet = null;
private SiemensPLCS siemensPLCSelected = SiemensPLCS.S1500;
private string _plcType;
private Dictionary<string, int> _nameHandleMap = new Dictionary<string, int>();
private bool _isTargetConnected;
public AlarmEventItem AlarmConnectFailed { get; set; }
public AlarmEventItem AlarmCommunicationError { get; set; }
public event Action OnConnected;
public TcAds(string module, XmlElement node, string ioModule = "")
{
var attrModule = node.GetAttribute("module");
Module = string.IsNullOrEmpty(attrModule) ? module : attrModule;
Name = node.GetAttribute("id");
Address = SC.GetStringValue($"PM.{Module}.SiemensIP");
_plcType = SC.GetStringValue($"PM.{Module}.SiemensType");
}
public bool Initialize()
{
if (!SC.GetValue<bool>($"System.SetUp.Is{Module}Installed"))
return true;
offset = new OffsetManager(Module);
AlarmConnectFailed = SubscribeAlarm($"{Module}.{Name}.ConnectionError", $"Can not connect with {Address}", null);
AlarmCommunicationError = SubscribeAlarm($"{Module}.{Name}.CommunicationError", $"Can not Communication {Address}", null);
Connection = new FsmConnection();
Connection.Initialize(100, this, this);
Connection.OnConnected += Connection_OnConnected;
Connection.OnDisconnected += Connection_OnDisconnected;
Connection.OnError += Connection_OnError;
ConnectionManager.Instance.Subscribe($"{Module}.{Name}", this);
_thread = new PeriodicJob(2000, OnTimer, "PLC Reconnection Thread", false);
return true;
}
bool IConnectable.CheckIsConnected()
{
return siemensTcpNet != null && siemensTcpNet.IsConnected;
}
public bool Connect(out string reason)
{
var ipAddr = ParseAdsIPAddr(Address);
siemensPLCSelected = (SiemensPLCS)Enum.Parse(typeof(SiemensPLCS), _plcType);
siemensTcpNet = new SiemensS7Net(siemensPLCSelected);
siemensTcpNet.IpAddress = ipAddr.Item1;// _ipAddress;
siemensTcpNet.Port = ipAddr.Item2; // int.Parse(_port);
siemensTcpNet.ConnectTimeOut = 1;
siemensTcpNet.ReceiveTimeOut = 1000;
try
{
if (siemensPLCSelected != SiemensPLCS.S200Smart &&
siemensPLCSelected != SiemensPLCS.S200)
{
siemensTcpNet.Rack = 0;
siemensTcpNet.Slot = 0;
siemensTcpNet.ConnectionType = 1;
siemensTcpNet.LocalTSAP = 258;
}
connect = siemensTcpNet.ConnectServer();
if (!siemensTcpNet.IsConnected)
{
//_isCommunicationError = true;
//IsConnect = true;
//EV.PostInfoLog(Module, "PLC Connection Successful");
}
else
{
//_isCommunicationError = false;
}
//return connect.IsSuccess;
}
catch (Exception ex)
{
_isTargetConnected = false;
//_isCommunicationError = true;
reason = ex.Message;
return false;
}
_isTargetConnected = true;
reason = string.Empty;
return true;
}
public bool Disconnect(out string reason)
{
reason = string.Empty;
siemensTcpNet.ConnectClose();
siemensTcpNet = null;
connect = null;
return false;
}
private void Connection_OnError(string obj)
{
AlarmConnectFailed.Set();
_thread.Start();
}
private void Connection_OnDisconnected()
{
EV.PostInfoLog(Module, $"Disconnect from PLC {Address}");
_thread.Start();
ResetAlarm();
}
private void Connection_OnConnected()
{
EV.PostInfoLog(Module, $"Connected with PLC {Address}");
EV.PostInfoLog(Module, $"Delay 5s can do offset");
Task.Delay(5000).ContinueWith(x => offset.Set());
ResetAlarm();
}
protected override void HandleMonitor()
{
//Reconnection();
}
public bool OnTimer()
{
Reconnection();
return true;
}
/// <summary>
/// 事件触发线程启动PLC断线延时2秒重连连接后才会退出线程
/// </summary>
protected void Reconnection()
{
try
{
if (siemensTcpNet == null || siemensTcpNet.IsConnected)//连接被主动切断,或者已连接直接退出
return;
trig_Reconnection.CLK = true;
if (trig_Reconnection.Q)//首次进去提示用户
EV.PostWarningLog(Module, "Disconnect from PLC,Stat reconnection");
connect = siemensTcpNet.ConnectServer();
if (siemensTcpNet.IsConnected)
{
trig_Reconnection.RST = true;
Connection.InvokeReset();
EV.PostInfoLog(Module, "PLC reconnection successful");
_thread.Stop();
}
}
catch
{ }
}
public void Terminate()
{
Connection.Terminate();
}
private Tuple<string, int> ParseAdsIPAddr(string addr)
{
if (addr == null)
throw (new Exception("PM.SiemensIP is not exist in sc.data!"));
Regex reg = new Regex(@"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?):(\d{1,5})$");
if (!reg.IsMatch(addr))
throw (new Exception($@"{Module}.SiemensIP '{addr}' is invalid!"));
var item = addr.Split(':');
return Tuple.Create(item[0], int.Parse(item[1]));
}
public void Reset()
{
ResetAlarm();
trig_Reconnection.RST = true;//复位重连trig信号
//复位读写异常trig信号
trig_readPLCFailCount.RST = true;
trig_writePLCFailCount.CLK = true;
Connection.InvokeReset();
}
public bool Read(string variableName, out object data, string type, int length, out string reason)
{
data = null;
reason = string.Empty;
return true;
}
public bool WriteArrayElement(string variableName, int index, object data, out string reason)
{
reason = "";
return true;
}
public bool SendBinaryData(byte[] data)
{
return true;
}
public bool SendAsciiData(string data)
{
return true;
}
public bool BulkReadRenderResult(string Adrress, ushort length, out byte[] data)
{
try
{
if (siemensTcpNet == null || !siemensTcpNet.IsConnected)
{
data = null;
return false;
}
OperateResult<byte[]> read = siemensTcpNet.Read(Adrress, length);// ushort.Parse(lengthTextBox.Text));
if (read.IsSuccess)
{
data = read.Content;
//复位读错误次数
trig_readPLCFailCount.RST = true;
readPLCFailCount = 0;
return true;
}
else
{
//if (!_isCommunicationError)
LOG.Write($"PLC BulkReadRenderResult Communication error with Siemens PLC , {read.Message}");
//_isCommunicationError = true;
data = null;
//新增读错误次数判断
if (readPLCFailCount < MaxFailCount)
{
readPLCFailCount++;
}
else
{
trig_readPLCFailCount.CLK = true;
if (trig_readPLCFailCount.Q)
{
EV.PostWarningLog(Module, $"PLC BulkReadRenderResult error with Siemens PLC , {read.Message}");
}
}
return false;
}
}
catch (Exception ex)
{
// EV.PostAlarmLog("", "Read Failed" + ex.Message);
}
data = null;
return false;
}
public bool BulkWriteByteRenderResult(string Adrress, byte[] data)
{
try
{
if (siemensTcpNet == null || !siemensTcpNet.IsConnected)
{
data = null;
return false;
}
OperateResult write = siemensTcpNet.Write(Adrress, data);
if (!write.IsSuccess)
{
//if (!_isCommunicationError)
//EV.PostInfoLog("PLC", $"Communication error with Siemens PLC , {write.Message}");
LOG.Write($"PLC BulkWriteByteRenderResult Communication error with Siemens PLC , {write.Message}");
//_isCommunicationError = true;
//新增写错误次数判断
if (writePLCFailCount < MaxFailCount)
{
writePLCFailCount++;
}
else
{
trig_writePLCFailCount.CLK = true;
if (trig_writePLCFailCount.Q)
{
EV.PostWarningLog(Module, $"PLC BulkWriteByteRenderResult error with Siemens PLC , {write.Message}");
}
}
return false;
}
//复位写错误次数
trig_writePLCFailCount.RST = true;
writePLCFailCount = 0;
return write.IsSuccess;
}
catch (Exception ex)
{
// EV.PostAlarmLog("", "Read Failed" + ex.Message);
}
return false;
}
}
}