| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 | using Aitex.Core.RT.Log;using MECF.Framework.Common.Beckhoff.IOAxis;using MECF.Framework.Common.Utilities;using System;using System.Collections.Generic;using System.Globalization;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;using TwinCAT.Ads;namespace MECF.Framework.Common.TwinCat{    public class TwincatCoeInterface    {        #region 常量        private const int INDEXGROUP_SDO_UPLOAD_DOWNLOAD = 0x0000f302;        #endregion        #region 内部变量        /// <summary>        /// ads COE对象        /// </summary>        private TcAdsClient _adsClientCOE;        /// <summary>        /// Net Id        /// </summary>        private string _netId;        /// <summary>        /// 端口号        /// </summary>        private int _port;        /// <summary>        /// 轴对象        /// </summary>        private BeckhoffAxis _axis;        /// <summary>        /// 连接输入变量(连接后读取变量)        /// </summary>        private BeckhoffAxisInput _connectInputVariable;        /// <summary>        /// 连接状态        /// </summary>        private bool _isConnected = false;        /// <summary>        /// coe输入变量(key-名称,value-输入变量对象)        /// </summary>        private Dictionary<string,BeckhoffAxisInput> _nameCoeInputDic = new Dictionary<string, BeckhoffAxisInput>();        /// <summary>        /// COE名称变量字典(key-名称,value-输出变量对象)        /// </summary>        private Dictionary<string, BeckhoffAxisOutput> _nameCoeOutputDic = new Dictionary<string, BeckhoffAxisOutput>();        /// <summary>        /// 连接是否完成        /// </summary>        private bool _isConnectComplete = false;        /// <summary>        /// 启动读取线程        /// </summary>        private Thread _startReadThread = null;        #endregion        /// <summary>        /// 模拟        /// </summary>        /// <param name="moduleName"></param>        /// <param name="netId"></param>        /// <param name="port"></param>        public TwincatCoeInterface(BeckhoffAxis beckhoffAxis)         {            _axis = beckhoffAxis;            _netId = beckhoffAxis.COEAddress;            _port = beckhoffAxis.COEPort;            AnalyseConnectInputVariable();            _adsClientCOE = new TcAdsClient();            _adsClientCOE.ConnectionStateChanged += AdsClientCOE_ConnectionStateChanged;        }        /// <summary>        /// 解析连接变量        /// </summary>        private void AnalyseConnectInputVariable()        {            foreach(BeckhoffAxisInput item in _axis.Inputs)            {                if(item.Address.StartsWith("0x"))                {                    _connectInputVariable = item;                    break;                }            }        }        /// <summary>        /// 初始化输入输出变量        /// </summary>        public void InnitialInputAndOutputVariable(BeckhoffAxis beckhoffAxis)        {            foreach (BeckhoffAxisInput item in beckhoffAxis.Inputs)            {                if (item.Address.StartsWith("0x"))                {                    _nameCoeInputDic[$"{beckhoffAxis.Name}.{item.Type}"] = item;                }            }            foreach(BeckhoffAxisOutput item in beckhoffAxis.Outputs)            {                if (item.Address.StartsWith("0x"))                {                    _nameCoeOutputDic[$"{beckhoffAxis.Name}.{item.Type}"] = item;                }            }        }        /// <summary>        /// 开启读取变量线程        /// </summary>        public void StartReadInputDataThread()        {            if (_startReadThread == null)            {                _startReadThread = new Thread(new ThreadStart(StartReadInputData));                _startReadThread.IsBackground = true;                _startReadThread.Start();            }        }        /// <summary>        /// 读取变量        /// </summary>        private void StartReadInputData()        {            DateTime dt = DateTime.Now;            while(true)            {                if(DateTime.Now.Subtract(dt).TotalSeconds>=5)                {                    break;                }                if(!_isConnectComplete)                {                    continue;                }                if(!_isConnected)                {                    continue;                }                if (_nameCoeInputDic.Count != 0)                {                    ReadAllCoeInputs();                    break;                }                else                {                    Thread.Sleep(500);                }            }                    }        /// <summary>        /// 读取所有COE变量        /// </summary>        private void ReadAllCoeInputs()        {            if(_nameCoeInputDic.Keys==null|| _nameCoeInputDic.Count==0)            {                return;            }            List<string> keys = _nameCoeInputDic.Keys.ToList();            foreach (string key in keys)            {                BeckhoffAxisInput item = _nameCoeInputDic[key];                Type type = DataTypeUtil.GetSystemDataTypeByBeckhoffDataType(item.DataType);                var sdoResult = AnalyseSdoIndex(item.Address);                if (sdoResult.Item1)                {                    object value = ReadCOEData(sdoResult.Item2, sdoResult.Item3, type);                    if (value != null)                    {                        BeckhoffAxisManager.Instance.SetAxisValue(key, value);                    }                    else                    {                        LOG.WriteLog(eEvent.ERR_TWINCAT, "System", $"read {key} error");                    }                }                Thread.Sleep(10);            }        }        /// <summary>        /// 连接状态变化        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void AdsClientCOE_ConnectionStateChanged(object sender, TwinCAT.ConnectionStateChangedEventArgs e)        {            if (e.NewState == TwinCAT.ConnectionState.Connected)            {                try                {                    if (_connectInputVariable != null)                    {                        var inputResult = AnalyseSdoIndex(_connectInputVariable.Address);                        if (inputResult.Item1)                        {                            object obj= ReadFirstCOEData(inputResult.Item2, inputResult.Item3, DataTypeUtil.GetSystemDataTypeByBeckhoffDataType(_connectInputVariable.DataType));                            if (obj != null)                            {                                _isConnected = true;                                _isConnectComplete = true;                            }                        }                    }                }                catch (Exception ex)                {                    _isConnectComplete = true;                    _isConnected = false;                    LOG.WriteLog(eEvent.ERR_TWINCAT, "System", $"Twincat connect{_netId}:{_port} error");                    return;                }            }            else            {                _isConnected = false;                LOG.WriteLog(eEvent.ERR_TWINCAT,"System", $"Twincat connect{_netId}:{_port} error");            }        }        /// <summary>        /// 连接        /// </summary>        /// <returns></returns>        public void Connect()        {            try            {                                _adsClientCOE.Connect(_netId, _port);            }            catch(Exception ex)            {                LOG.WriteLog(eEvent.ERR_TWINCAT, "System", ex.Message);            }        }        #region 写数据        /// <summary>        /// 写数据        /// </summary>        /// <param name="moduleName"></param>        /// <param name="variableName"></param>        /// <param name="value"></param>        /// <returns></returns>        public bool WriteModuleCoeData(string moduleName,string variableName,object value)        {            if(_isConnected)            {                string str = $"{moduleName}.{variableName}";                if(_nameCoeOutputDic.ContainsKey(str))                {                    BeckhoffAxisOutput output = _nameCoeOutputDic[str];                    try                    {                        var sdoResult = AnalyseSdoIndex(output.Address);                        if(sdoResult.Item1)                        {                            bool result=WriteCOEData(sdoResult.Item2, sdoResult.Item3, value);                            if (result&&_nameCoeInputDic.ContainsKey(str))                            {                                object rdValue = ReadCOEData(sdoResult.Item2, sdoResult.Item3, DataTypeUtil.GetSystemDataTypeByBeckhoffDataType(output.DataType));                                if (rdValue != null)                                {                                    BeckhoffAxisManager.Instance.SetAxisValue(str, rdValue);                                }                            }                            return true;                        }                        else                         {                            return false;                        }                    }                    catch(Exception ex)                    {                        LOG.WriteLog(eEvent.ERR_TWINCAT, "System", $"twincat cannot write COE data, message is [{ex.Message}]");                        return false;                    }                }                else                {                    LOG.WriteLog(eEvent.ERR_TWINCAT, "System", $"twincat doesnot have [{moduleName}.{variableName}] variable ,cannot write COE data");                    return false;                }            }            else            {                LOG.WriteLog(eEvent.ERR_TWINCAT, "System", "twincat connect failed,cannot write COE data");                return false;            }        }        /// <summary>        /// 解析Sdo索引        /// </summary>        /// <param name="address"></param>        /// <returns></returns>        private (bool,int,int) AnalyseSdoIndex(string address)        {            string[] strAry = address.Split(':');            if (strAry.Length != 2)            {                LOG.WriteLog(eEvent.ERR_TWINCAT, "System", $"twincat invalid address is {address}");                return (false,0,0);            }            else            {                                if (int.TryParse(strAry[0].Remove(0,2), System.Globalization.NumberStyles.HexNumber, System.Globalization.NumberFormatInfo.InvariantInfo, out int sdoIndex) &&                     int.TryParse(strAry[1], out int sdoSubIndex))                {                    return (true,sdoIndex,sdoSubIndex);                }                else                {                    LOG.WriteLog(eEvent.ERR_TWINCAT, "System", $"twincat invalid address is {address}");                    return (false,0,0);                }            }        }        /// <summary>        /// 写COE Byte数据        /// </summary>        /// <param name="sdoIndex"></param>        /// <param name="sdoSubIndex"></param>        /// <param name="value"></param>        private bool WriteCOEData(int sdoIndex,int sdoSubIndex,object value)        {            if (_isConnected)            {                int indexOffset = (int)sdoIndex * 65536 + sdoSubIndex;                try                {                    _adsClientCOE.WriteAny(INDEXGROUP_SDO_UPLOAD_DOWNLOAD, indexOffset, value);                    return true;                }                catch (Exception ex)                {                    LOG.WriteLog(eEvent.ERR_TWINCAT, "System", $"twincat write COE data failed {ex.Message}.IndexOffset:{sdoIndex}:{sdoSubIndex}");                    return false;                }            }            else            {                LOG.WriteLog(eEvent.ERR_TWINCAT, "System", "twincat connect failed,cannot write COE data");                return false;            }        }        #endregion        #region 读数据        /// <summary>        /// 读取COE Byte数据        /// </summary>        /// <param name="sdoIndex"></param>        /// <param name="sdoSubIndex"></param>        /// <returns></returns>        public object ReadCOEData(int sdoIndex,int sdoSubIndex,Type type)         {            if (_isConnected)            {                int indexOffset = (int)sdoIndex * 65536 + sdoSubIndex;                try                {                    return _adsClientCOE.ReadAny(INDEXGROUP_SDO_UPLOAD_DOWNLOAD, indexOffset, type);                }                catch(Exception ex)                {                    LOG.WriteLog(eEvent.ERR_TWINCAT, "System", $"twincat read COE data failed {ex.Message}.IndexOffset:{sdoIndex}:{sdoSubIndex}");                    return null;                }            }            else            {                LOG.WriteLog(eEvent.ERR_TWINCAT, "System", "twincat connect failed,cannot read COE data");                return null;            }        }        /// <summary>        /// 读取第一个COE数据        /// </summary>        /// <param name="sdoIndex"></param>        /// <param name="sdoSubIndex"></param>        /// <param name="type"></param>        /// <returns></returns>        private object ReadFirstCOEData(int sdoIndex, int sdoSubIndex, Type type)        {            int indexOffset = (int)sdoIndex * 65536 + sdoSubIndex;            try            {                return _adsClientCOE.ReadAny(INDEXGROUP_SDO_UPLOAD_DOWNLOAD, indexOffset, type);            }            catch (Exception ex)            {                LOG.WriteLog(eEvent.ERR_TWINCAT, "System", $"twincat read COE data failed {ex.Message}.IndexOffset:{sdoIndex}:{sdoSubIndex}");                return null;            }        }        #endregion    }}
 |