using ProjectBase.Data.Redis;
using SIASUN.Autopilot.Device.EventMessage;
using SIASUN.Autopilot.Model;
using System;
using TwinCAT.Ads;
namespace SIASUN.Autopilot.Device.BeckHoff
{
///
/// 类型限定为 string、boolen、int、double、结构体
///
///
public class TwinCatAds : AbsTwinCatOpc
{
#region 变量
private int iHandle;
private int notificationHandle;
private TcAdsClient adsClient =null;
private T strValue;
private MoBeckhoffNode moBFNodeInfo = null;
private object objUserData { get; set; }
#endregion
private RedisHelper redis =null;
public TwinCatAds(MoBeckhoffNode mNodeInfo):base()
{
try
{
moBFNodeInfo = mNodeInfo;
objUserData = mNodeInfo.NodeName;
this.adsClient = base.GetAds();
ConnectOpc();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
#region 方法
public bool ConnectOpc()
{
if (redis == null)
redis = new RedisHelper();
if (!adsClient.IsConnected)
{
adsClient.Connect(moBFNodeInfo.IP, moBFNodeInfo.Port);
}
adsClient.AdsNotificationEx += new AdsNotificationExEventHandler(adsClient_AdsNotificationEx);
iHandle = adsClient.CreateVariableHandle(moBFNodeInfo.NodeName);
if (moBFNodeInfo.ReceiveType != 1)
{
notificationHandle = adsClient.AddDeviceNotificationEx(moBFNodeInfo.NodeName, AdsTransMode.OnChange, 10, 0, objUserData, typeof(T));
}
return true;
}
public override bool DisConnectOpc()
{
try
{
DeleteNotification();
adsClient.Dispose();
iHandle = 0;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
return true;
}
public override bool IsConnectOpc()
{
return adsClient.IsConnected;
}
public override bool CreateNotification()
{
try
{
notificationHandle = adsClient.AddDeviceNotificationEx(moBFNodeInfo.NodeName, AdsTransMode.OnChange, 10, 0, objUserData, typeof(T));
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
return true;
}
public override bool DeleteNotification()
{
try
{
if (notificationHandle != 0)
{
adsClient.DeleteDeviceNotification(notificationHandle);
notificationHandle = 0;
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
return true;
}
private void adsClient_AdsNotificationEx(object sender, AdsNotificationExEventArgs e)
{
if (!e.NotificationHandle.Equals(notificationHandle))
return;
strValue = (T)e.Value;
redis.SetHash("plc_node", e.UserData.ToString(), strValue);
EventMessages.GetSingleton().Publish(e.UserData.ToString(), typeof(T).ToString(), e.Value.ToString());
}
public override void Set(object nodevalue, String datatype)
{
switch (datatype)
{
case "double":
adsClient.WriteAny(iHandle, Convert.ToDouble(nodevalue));
break;
case "int":
adsClient.WriteAny(iHandle, Convert.ToInt16(nodevalue));
break;
case "uint":
adsClient.WriteAny(iHandle, Convert.ToUInt16(nodevalue));
break;
case "dint":
adsClient.WriteAny(iHandle, Convert.ToInt32(nodevalue));
break;
case "word":
adsClient.WriteAny(iHandle, Convert.ToInt16(nodevalue));
break;
case "bool":
adsClient.WriteAny(iHandle, Convert.ToBoolean(nodevalue));
break;
case "byte":
adsClient.WriteAny(iHandle, Convert.ToByte(nodevalue));
break;
case "real":
adsClient.WriteAny(iHandle, Convert.ToSingle(nodevalue));
break;
default:
throw new IndexOutOfRangeException($"TwinCatAds get {objUserData} error, value = { Convert.ToSingle(nodevalue)}, no match type.");
//break;
};
}
public override object Get(out Type _type)
{
strValue = (T)adsClient.ReadAny(iHandle, typeof(T));
_type = typeof(T);
redis.SetHash("plc_node", objUserData.ToString(), strValue);
return strValue;
}
#endregion
}
}