| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495 | using Aitex.Core.RT.Event;using Aitex.Core.RT.IOCore;using Aitex.Core.RT.Log;using Aitex.Core.Util;using MECF.Framework.Common.Beckhoff.IOAxis;using MECF.Framework.Common.IOCore;using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Xml;using TwinCAT;using TwinCAT.Ads;using TwinCAT.Ads.TypeSystem;using TwinCAT.Ads.ValueAccess;using TwinCAT.TypeSystem;namespace MECF.Framework.Common.TwinCat{    public class TwincatAdoManager : Singleton<TwincatAdoManager>    {        #region 内部变量        private TcAdsClient _adsClient = null;        private string _ipAddress = "";        private int _port = 851;        private BeckhoffCfg _cfg;        private Dictionary<int, BeckhoffItem> _handleItemDic = new Dictionary<int, BeckhoffItem>();        private Dictionary<string, int> _notificationNameHandleDic = new Dictionary<string, int>();        private Dictionary<string, int> _writeNameHandleDic = new Dictionary<string, int>();        private AdsStream _adsStream;        private BinaryReader _reader;        private bool _isConnected = false;        /// <summary>        /// BitOperated地址数值字典(key-BitOperated为true地址,value-数值)        /// </summary>        private Dictionary<string, byte> _bitOperatedAddressValueDic = new Dictionary<string, byte>();        /// <summary>        /// BitOperated锁        /// </summary>        private object _bitOperatedLocker = new object();        #endregion        #region 属性        public bool IsConnect        {            get { return _isConnected; }            set { _isConnected = value; }        }        #endregion        /// <summary>        /// 初始化        /// </summary>        public void Initialize()        {            int size=BeckhoffIOManager.Instance.Size+BeckhoffAxisManager.Instance.Size+BeckhoffCounterManager.Instance.Size;            Init(BeckhoffManager.Instance.BeckhoffCfg, size+100);        }        /// <summary>        /// 初始化        /// </summary>        /// <param name="ipAddress"></param>        /// <param name="port"></param>        private void Init(BeckhoffCfg beckhoffCfg,int size)        {            _adsClient = new TcAdsClient();            _adsClient.ConnectionStateChanged += AdsClient_ConnectionStateChanged;            _cfg = beckhoffCfg;            _ipAddress = beckhoffCfg.Controller.IPAddress;            _port = int.Parse(beckhoffCfg.Controller.PortAddress);            _adsStream = new AdsStream(size);            _reader=new BinaryReader(_adsStream);            _adsClient.AdsNotification += AdsClient_AdsNotification;            _adsClient.AdsNotificationError += AdsClient_AdsNotificationError;            Start();        }        private void AdsClient_AdsNotificationError(object sender, AdsNotificationErrorEventArgs e)        {        }        /// <summary>        /// 连接状态变化        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void AdsClient_ConnectionStateChanged(object sender, TwinCAT.ConnectionStateChangedEventArgs e)        {            LOG.WriteLog(eEvent.INFO_TWINCAT, "System", $"Twincat connect{_cfg.Controller.IPAddress}:{_cfg.Controller.PortAddress} stated changed from {e.OldState} to {e.NewState}");            if (e.NewState==TwinCAT.ConnectionState.Connected)            {                try                {                    StateInfo stateInfo = _adsClient.ReadState();                    CreateWriteHandle();                    SubscribeNotification();                                        _isConnected = true;                    BeckhoffAxisManager.Instance.StartCoeInterface();                }                catch(Exception ex)                {                    _isConnected = false;                    LOG.WriteLog(eEvent.ERR_TWINCAT,"System",$"Twincat connect{_cfg.Controller.IPAddress}:{_cfg.Controller.PortAddress} error");                    return;                }            }            else            {                _isConnected = false;                LOG.WriteLog(eEvent.ERR_TWINCAT, "System", $"Twincat connect{_cfg.Controller.IPAddress}:{_cfg.Controller.PortAddress} error");            }        }        /// <summary>        /// 启动        /// </summary>        public void Start()        {            try            {                _adsClient.Connect(_ipAddress, _port);            }            catch            {                LOG.WriteLog(eEvent.ERR_TWINCAT, "System", $"Twincat connect{_cfg.Controller.IPAddress}:{_cfg.Controller.PortAddress} error");            }        }        /// <summary>        /// 订阅变量        /// </summary>        private void SubscribeNotification()        {            _notificationNameHandleDic.Clear();            _handleItemDic.Clear();            int count = 0;            List<BeckhoffItem> beckhoffItems = BeckhoffItemManager.Instance.GetIOItems();            foreach(BeckhoffItem item in beckhoffItems)            {                try                {                    int handle = _adsClient.AddDeviceNotification(item.Address, _adsStream, count, item.Size, AdsTransMode.OnChange, 0, 0, item);                    _notificationNameHandleDic[item.Name] = handle;                    _handleItemDic[handle] = item;                    count += item.Size;                }                catch(Exception ex)                {                    LOG.WriteLog(eEvent.ERR_TWINCAT, "System", $"Twincat add variable {item.Name} error");                }            }        }        /// <summary>        /// 创建写入句柄        /// </summary>        private void CreateWriteHandle()        {            _writeNameHandleDic.Clear();            foreach(BeckhoffItem item in  BeckhoffItemManager.Instance.GetWriteItems())            {                try                {                    int handle = _adsClient.CreateVariableHandle(item.Address);                    _writeNameHandleDic[item.Name] = handle;                }                catch                {                    LOG.WriteLog(eEvent.ERR_TWINCAT, "System", $"Twincat create variable handle {item.Name} error");                }            }        }        /// <summary>        /// 写入数值        /// </summary>        /// <param name="name"></param>        /// <param name="value"></param>        /// <returns></returns>        public bool WriteValue(string name,object value)        {            if(_writeNameHandleDic.ContainsKey(name))            {                if(!_isConnected)                {                    LOG.WriteLog(eEvent.ERR_TWINCAT,"System", $"Twincat connected failed, write variable {name} error");                    return false;                }                int handle = _writeNameHandleDic[name];                BeckhoffItem item = BeckhoffItemManager.Instance.GetIOBeckhoffItem(name);                object convertedValue = value;                                try                {                    if (item != null && item.BitOperated)                    {                        if (item.Invert && convertedValue is bool)                        {                            convertedValue = !(bool)convertedValue;                        }                        lock (_bitOperatedLocker)                        {                            convertedValue = GetBeckoffItemValue(item, convertedValue);                            _adsClient.WriteAny(handle, convertedValue);                            _bitOperatedAddressValueDic[item.Address] = (byte)convertedValue;                        }                    }                    else                    {                        _adsClient.WriteAny(handle, convertedValue);                    }                    LOG.WriteLog(eEvent.INFO_TWINCAT, "System", $"Twincat write variable {name} value {convertedValue}");                    return true;                }                catch(Exception ex)                {                    LOG.WriteLog(eEvent.ERR_TWINCAT,"System", $"Twincat write variable {name} error {ex.Message}");                    return false;                }            }            else            {                LOG.WriteLog(eEvent.ERR_TWINCAT,"System", $"Twincat doesnot has {name} variable");            }            return false;        }        /// <summary>        /// 获取Beckhoff项数值(用于解决BitOperated为true)        /// </summary>        /// <param name="name"></param>        /// <param name="value"></param>        /// <returns></returns>        private object GetBeckoffItemValue(BeckhoffItem item,object value)        {            if (_bitOperatedAddressValueDic.ContainsKey(item.Address))            {                byte addressValue = _bitOperatedAddressValueDic[item.Address];                bool[] boolArray = Converter.GetboolArrayByByte(addressValue);                bool boolValue = (bool)value;                if (item.Bit < boolArray.Length)                {                    boolArray[item.Bit] = boolValue;                }                byte byt = Converter.GetByteValueByBoolArray(boolArray);                return byt;            }            else            {                return value;            }        }        /// <summary>        /// 变量数值发生变化事件        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void AdsClient_AdsNotification(object sender, AdsNotificationEventArgs e)        {            try            {                BeckhoffItem item = null;                if (_handleItemDic.ContainsKey(e.NotificationHandle))                {                    item = _handleItemDic[e.NotificationHandle];                }                else                {                    item = (BeckhoffItem)e.UserData;                }                e.DataStream.Position = e.Offset;                if (item != null)                {                    switch (item.IoType)                    {                        case "di":                            BeckhoffDIAccessor diAccessor = BeckhoffIOManager.Instance.GetDIAccessor(item.Name);                            if (diAccessor != null)                            {                                diAccessor.Value = _reader.ReadBoolean();                                if (item.Invert)                                {                                    IOModuleManager.Instance.UpdateIoValue(item.Name, !diAccessor.Value);                                }                                else                                {                                    IOModuleManager.Instance.UpdateIoValue(item.Name, diAccessor.Value);                                }                            }                            break;                        case "do":                            BeckhoffDOAccessor doAccessor = BeckhoffIOManager.Instance.GetDOAccessor(item.Name);                            if (doAccessor != null)                            {                                if (item.BitOperated)                                {                                    byte byt = _reader.ReadByte();                                    lock (_bitOperatedLocker)                                    {                                        _bitOperatedAddressValueDic[doAccessor.Address] = byt;                                    }                                    doAccessor.Value = ((byt >> item.Bit) & 0x01) == 0x01;                                }                                else                                {                                    doAccessor.Value = _reader.ReadBoolean();                                }                                if (item.Invert)                                {                                    IOModuleManager.Instance.UpdateIoValue(item.Name, !doAccessor.Value);                                }                                else                                {                                    IOModuleManager.Instance.UpdateIoValue(item.Name, doAccessor.Value);                                }                            }                            break;                        case "ai":                            BeckhoffAIAccessor aiAccessor = BeckhoffIOManager.Instance.GetAIAccessor(item.Name);                            if (aiAccessor != null)                            {                                double twincatValue = GetAnalogValue(item.DataType);                                var result = ScalingManager.Instance.CalculateValueByTwincatVariable(item.Name, twincatValue);                                if (result.Item1)                                {                                    aiAccessor.Value = result.Item2;                                }                                else                                {                                    aiAccessor.Value = twincatValue;                                }                                IOModuleManager.Instance.UpdateIoValue(item.Name, aiAccessor.Value);                            }                            break;                        case "ao":                            BeckhoffAOAccessor aoAccessor = BeckhoffIOManager.Instance.GetAOAccesssor(item.Name);                            if (aoAccessor != null)                            {                                double twincatValue = GetAnalogValue(item.DataType);                                var result = ScalingManager.Instance.CalculateValueByTwincatVariable(item.Name, twincatValue);                                if (result.Item1)                                {                                    aoAccessor.Value = result.Item2;                                }                                else                                {                                    aoAccessor.Value = twincatValue;                                }                                IOModuleManager.Instance.UpdateIoValue(item.Name, aoAccessor.Value);                            }                            break;                        case "axis":                            object itemValue = GetDataTypeValue(item.DataType);                            if (item.Invert)                            {                                bool boolValue = (bool)itemValue;                                BeckhoffAxisManager.Instance.SetAxisValue(item.Name, !boolValue);                            }                            else                            {                                BeckhoffAxisManager.Instance.SetAxisValue(item.Name, itemValue);                            }                            break;                        case "counter":                            if (item.Invert)                            {                                object counterItemValue = GetDataTypeValue(item.DataType);                                bool boolValue = (bool)counterItemValue;                                BeckhoffCounterManager.Instance.SetCounterValue(item.Name, !boolValue);                            }                            else                            {                                                                object counterItemValue = GetDataTypeValue(item.DataType);                                BeckhoffCounterManager.Instance.SetCounterValue(item.Name, counterItemValue);                            }                            break;                    }                }            }            catch(Exception ex)            {                LOG.WriteLog(eEvent.ERR_TWINCAT, "System", ex.Message);            }        }        /// <summary>        /// 获取模拟数量数值         /// </summary>        /// <param name="dataType"></param>        /// <returns></returns>        private double GetAnalogValue(string dataType)        {            return double.Parse(GetDataTypeValue(dataType).ToString());        }        /// <summary>        /// 获取数据类型数值        /// </summary>        /// <param name="dataType"></param>        /// <returns></returns>        private object GetDataTypeValue(string dataType)        {            switch (dataType)            {                case "byte":                    return _reader.ReadByte();                case "sint":                    return _reader.ReadSByte();                case "usint":                    return _reader.ReadByte();                case "short":                    return _reader.ReadInt16();                case "int":                    return _reader.ReadInt16();                case "uint":                    return _reader.ReadUInt16();                case "dint":                    return _reader.ReadInt32();                case "udint":                    return _reader.ReadUInt32();                case "long":                    return _reader.ReadInt64();                case "float":                    return _reader.ReadSingle();                case "ulong":                    return _reader.ReadUInt64();                case "double":                    return _reader.ReadDouble();                case "bool":                    return _reader.ReadBoolean();                default:                    return _reader.ReadDouble();            }        }        /// <summary>        /// 停止        /// </summary>        public void Stop()        {            _adsClient.Dispose();        }        #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.WriteLog(eEvent.ERR_TWINCAT, "System", $"Twincat connected failed, write variable {name} error");                    return (false, 0);                }                try                {                    int handle = _writeNameHandleDic[name];                    _adsClient.WriteAny(handle, data);                    LOG.WriteLog(eEvent.INFO_TWINCAT, "System", $"Twincat write variable {name} value {data}");                    return (true, 0);                }                catch (Exception ex)                {                    LOG.WriteLog(eEvent.ERR_TWINCAT, "System", $"Twincat write variable {name} error {ex.Message}");                    return (false, 1);                }            }            else            {                LOG.WriteLog(eEvent.ERR_TWINCAT, "System", $"Twincat doesnot has {name} variable");                return (false, 0);            }        }        #endregion    }}
 |