123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- using Aitex.Core.RT.IOCore;
- using Aitex.Core.RT.Log;
- using Aitex.Core.Util;
- using DocumentFormat.OpenXml.Wordprocessing;
- using System;
- using System.Collections;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Runtime.InteropServices;
- using System.Text;
- using System.Threading.Tasks;
- using TwinCAT.Ads;
- using Venus_Core;
- namespace MECF.Framework.Common.Twincat
- {
- /// <summary>
- /// 变量数值发生变化委托声明
- /// </summary>
- /// <param name="variableName"></param>
- /// <param name="value"></param>
- public delegate void OnUpdateModuleVariableValue(string variableName, object value);
- /// <summary>
- /// Twicat Ado通信
- /// </summary>
- public class TwincatAdoManager
- {
- #region 内部变量
- /// <summary>
- /// IO长度字典(key-变量名称,value-变量数据长度)
- /// </summary>
- private ConcurrentDictionary<string, int> _ioLengthDic = new ConcurrentDictionary<string, int>();
- /// <summary>
- /// 输出变量集合
- /// </summary>
- private ConcurrentBag<string> _outputBag = new ConcurrentBag<string>();
- /// <summary>
- /// 主动读取变量集合
- /// </summary>
- private ConcurrentBag<string> _inputBag = new ConcurrentBag<string>();
- /// <summary>
- /// Twincat 对象
- /// </summary>
- private TcAdsClient _adsClient = null;
- /// <summary>
- /// 地址
- /// </summary>
- private string _ipAddress = "";
- /// <summary>
- /// 端口号
- /// </summary>
- private int _port = 851;
- /// <summary>
- /// 句柄变量名称字典(key-创建句柄,value-变量名称)
- /// </summary>
- private Dictionary<int, string> _notificationHandleNameDic = new Dictionary<int, string>();
- /// <summary>
- /// 模块变量更新委托字典(key-模块.变量,value-变量委托事件
- /// </summary>
- private Dictionary<string, OnUpdateModuleVariableValue> _moduleVariableActionDic = new Dictionary<string, OnUpdateModuleVariableValue>();
- /// <summary>
- /// 写变更名称句柄字典(key-变量名称,value-创建句柄)
- /// </summary>
- private Dictionary<string, int> _writeNameHandleDic = new Dictionary<string, int>();
- /// <summary>
- /// 主动读取名称字典(key-变量名称,value-创建句柄)
- /// </summary>
- private Dictionary<string, int> _readNameHandleDic = new Dictionary<string, int>();
- private AdsStream _adsStream;
- private BinaryReader _reader;
- /// <summary>
- /// 连接状态
- /// </summary>
- private bool _isConnected;
- #endregion
- /// <summary>
- /// 订阅变量
- /// </summary>
- /// <param name="itemName"></param>
- /// <param name="itemLength"></param>
- public void Subscribe(string itemName,int itemLength, OnUpdateModuleVariableValue onUpdateModuleVariableValue)
- {
- _ioLengthDic[itemName] = itemLength;
- _moduleVariableActionDic[itemName] = onUpdateModuleVariableValue;
- }
- /// <summary>
- /// 订阅输出变量名称
- /// </summary>
- /// <param name="itemName"></param>
- public void SubscribeOutput(string itemName)
- {
- _outputBag.Add(itemName);
- }
- /// <summary>
- /// 订阅主动读取变量名称
- /// </summary>
- /// <param name="itemName"></param>
- public void SubscribeInput(string itemName)
- {
- _inputBag.Add(itemName);
- }
- /// <summary>
- /// 初始化
- /// </summary>
- /// <param name="ipAddress"></param>
- /// <param name="port"></param>
- public void Initialize(string ipAddress,int port)
- {
- _ipAddress = ipAddress;
- _port = port;
- }
- /// <summary>
- /// 获取所有数据长度
- /// </summary>
- /// <returns></returns>
- private int GetAllSize()
- {
- int size = 0;
- foreach(string item in _ioLengthDic.Keys)
- {
- size+= _ioLengthDic[item];
- }
- return size;
- }
- /// <summary>
- /// ADO变量变化通知,twincat->上位机
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void AdsClient_AdsNotification(object sender, AdsNotificationEventArgs e)
- {
- try
- {
- if (_notificationHandleNameDic.ContainsKey(e.NotificationHandle))
- {
- string item = _notificationHandleNameDic[e.NotificationHandle];
- if(!_ioLengthDic.ContainsKey(item))
- {
- LOG.Write(eEvent.ERR_TWINCAT, "System", $"{item} not in twincat io list");
- return;
- }
- int size = _ioLengthDic[item];
- e.DataStream.Position = e.Offset;
- if(size==1)
- {
- bool boolValue = _reader.ReadBoolean();
- if(_moduleVariableActionDic.ContainsKey(item))
- {
- _moduleVariableActionDic[item].Invoke(item, boolValue);
- }
- }
- else if(size==4)
- {
- float floatValue= _reader.ReadSingle();
- if (_moduleVariableActionDic.ContainsKey(item))
- {
- _moduleVariableActionDic[item].Invoke(item, floatValue);
- }
- }
- else
- {
- byte[] byt = new byte[size];
- var value = _reader.Read(byt, 0, byt.Length);
- if (_moduleVariableActionDic.ContainsKey(item))
- {
- _moduleVariableActionDic[item].Invoke(item, byt);
- }
- //LOG.Write(eEvent.ERR_TWINCAT, "System", $"{item} size is invalid");
- }
- }
- }
- catch (Exception ex)
- {
- LOG.Write(eEvent.ERR_TWINCAT, "System", ex.Message);
- }
- }
- /// <summary>
- /// 连接状态变化
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void AdsClient_ConnectionStateChanged(object sender, TwinCAT.ConnectionStateChangedEventArgs e)
- {
- if (e.NewState == TwinCAT.ConnectionState.Connected)
- {
- try
- {
- StateInfo stateInfo = _adsClient.ReadState();
- CreateWriteHandle();
- CreateReadHandle();
- SubscribeNotification();
- _isConnected = true;
- }
- catch (Exception ex)
- {
- _isConnected = false;
- LOG.Write(eEvent.ERR_TWINCAT, "System", $"Twincat connect{_ipAddress}:{_port} error");
- return;
- }
- }
- else
- {
- _isConnected = false;
- LOG.Write(eEvent.ERR_TWINCAT, "System", $"Twincat connect{_ipAddress}:{_port} error");
- }
- }
- /// <summary>
- /// 启动
- /// </summary>
- public void Start()
- {
- _adsClient = new TcAdsClient();
- _adsClient.ConnectionStateChanged += AdsClient_ConnectionStateChanged;
- _adsClient.AdsNotification += AdsClient_AdsNotification;
- _adsStream = new AdsStream(GetAllSize());
- _reader = new BinaryReader(_adsStream);
- try
- {
- _adsClient.Connect(_ipAddress, _port);
- }
- catch
- {
- LOG.Write(eEvent.ERR_TWINCAT, "System", $"Twincat connect{_ipAddress}:{_port} error");
- }
- }
- /// <summary>
- /// 创建写入句柄
- /// </summary>
- private void CreateWriteHandle()
- {
- _writeNameHandleDic.Clear();
- foreach (string item in _outputBag)
- {
- try
- {
- int handle = _adsClient.CreateVariableHandle(item);
- _writeNameHandleDic[item] = handle;
- }
- catch
- {
- LOG.Write(eEvent.ERR_TWINCAT, "System", $"Twincat create variable handle {item} error");
- }
- }
- }
- /// <summary>
- /// 创建主动读取句柄
- /// </summary>
- private void CreateReadHandle()
- {
- _readNameHandleDic.Clear();
- foreach (string item in _inputBag)
- {
- try
- {
- int handle = _adsClient.CreateVariableHandle(item);
- _readNameHandleDic[item] = handle;
- }
- catch
- {
- LOG.Write(eEvent.ERR_TWINCAT, "System", $"Twincat create variable handle {item} error");
- }
- }
- }
- /// <summary>
- /// 订阅变量
- /// </summary>
- private void SubscribeNotification()
- {
- _notificationHandleNameDic.Clear();
- int count = 0;
- foreach (string item in _ioLengthDic.Keys)
- {
- int size = _ioLengthDic[item];
- try
- {
- int handle = _adsClient.AddDeviceNotification(item, _adsStream, count, size, AdsTransMode.OnChange, 0, 0, null);
- _notificationHandleNameDic[handle] = item;
- count += size;
- }
- catch
- {
- LOG.Write(eEvent.ERR_TWINCAT, "System", $"Twincat add variable {item} error");
- }
- }
- }
- /// <summary>
- /// 写入数值
- /// </summary>
- /// <param name="name"></param>
- /// <param name="value"></param>
- /// <returns></returns>
- public (bool success,int status) WriteValue(string name, object value)
- {
- if (_writeNameHandleDic.ContainsKey(name))
- {
- if (!_isConnected)
- {
- LOG.Write(eEvent.ERR_TWINCAT, "System", $"Twincat connected failed, write variable {name} error");
- return (false,0);
- }
- try
- {
- int handle = _writeNameHandleDic[name];
- _adsClient.WriteAny(handle, value);
- if (value.ToString() == "System.Byte[]")
- {
- byte[] result = ((byte[])value).Where(b => b != 0).ToArray();
- string _value = System.Text.Encoding.UTF8.GetString(result);
- LOG.Write(eEvent.EV_TWINCAT, "System", $"Twincat write variable {name} value {_value}");
- }
- else
- {
- LOG.Write(eEvent.EV_TWINCAT, "System", $"Twincat write variable {name} value {value}");
- }
- return (true,0);
- }
- catch (Exception ex)
- {
- LOG.Write(eEvent.ERR_TWINCAT, "System", $"Twincat write variable {name} error {ex.Message}");
- return (false,1);
- }
- }
- else
- {
- LOG.Write(eEvent.ERR_TWINCAT, "System", $"Twincat doesnot has {name} variable");
- return (false, 0);
- }
- }
- /// <summary>
- /// 主动读取
- /// </summary>
- /// <param name="name"></param>
- /// <param name="type"></param>
- /// <returns></returns>
- public (bool success,object obj) ReadValue(string name,Type type)
- {
- if (_readNameHandleDic.ContainsKey(name))
- {
- if (!_isConnected)
- {
- LOG.Write(eEvent.ERR_TWINCAT, "System", $"Twincat connected failed, read variable {name} error");
- return (false, null);
- }
- try
- {
- int handle = _readNameHandleDic[name];
- return (true, _adsClient.ReadAny(handle,type));
- }
- catch (Exception ex)
- {
- LOG.Write(eEvent.ERR_TWINCAT, "System", $"Twincat write variable {name} error {ex.Message}");
- return (false, null);
- }
- }
- else
- {
- LOG.Write(eEvent.ERR_TWINCAT, "System", $"Twincat doesnot has {name} variable");
- return (false, null);
- }
- }
- #region 支持写入结构体
- /* T必须字段必须为连续地址,
- * [StructLayout(LayoutKind.Sequential)]
- public class Tag
- {
- [MarshalAs(UnmanagedType.I1)]
- public bool DO_PVN21;
- [MarshalAs(UnmanagedType.I1)]
- public bool DO_PV11;
- [MarshalAs(UnmanagedType.R4)]
- public float AI_Chamber_Pressure_10t;
- }
- * */
- /// <summary>
- /// 写入类
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="name"></param>
- /// <param name="data"></param>
- /// <returns></returns>
- public (bool success,int status) WriteStruct<T>(string name,T data)
- {
- if (_writeNameHandleDic.ContainsKey(name))
- {
- if (!_isConnected)
- {
- LOG.Write(eEvent.ERR_TWINCAT, "System", $"Twincat connected failed, write variable {name} error");
- return (false, 0);
- }
- try
- {
- int handle = _writeNameHandleDic[name];
-
- _adsClient.WriteAny(handle, data);
- LOG.Write(eEvent.EV_TWINCAT, "System", $"Twincat write variable {name} value {data}");
- return (true, 0);
- }
- catch (Exception ex)
- {
- LOG.Write(eEvent.ERR_TWINCAT, "System", $"Twincat write variable {name} error {ex.Message}");
- return (false, 1);
- }
- }
- else
- {
- LOG.Write(eEvent.ERR_TWINCAT, "System", $"Twincat doesnot has {name} variable");
- return (false, 0);
- }
- }
- #endregion
- }
- }
|