using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using Aitex.Core.RT.Log; using Aitex.Core.RT.PLC; using Aitex.Core.Util; using Aitex.Core.RT.DataCenter; namespace Aitex.Core.RT.IOCore { public class IOManager { private IO_DEFINE _ioDefine; private Interlock _interlock = null; private Dictionary _dicScale = new Dictionary(); /// /// IO Mapping /// private object _iomapLocker; private Dictionary _ioMap; private string _interlockFile; /// /// IO Memory buffer for Update /// #region IOUpdate private int len = 200; private bool[] _di; private bool[] _do; private float[] _ai; private float[] _ao; #endregion public IOManager() { _interlock = new Interlock(); _iomapLocker = new object(); _ioMap = new Dictionary(); //DI/DO/AI/AO _di = new bool[len]; _do = new bool[len]; _ai = new float[len]; _ao = new float[len]; } public bool Initialize(string ioDefineXmlFile, string interlockConfigFile) { try { _ioDefine = CustomXmlSerializer.Deserialize(new FileInfo(ioDefineXmlFile)); } catch (Exception ex) { LOG.Error("IODefine文件格式不对," + ioDefineXmlFile + "," + ex.Message); return false; } IOMapping(); _interlockFile = interlockConfigFile; string reason; if (!InitializeInterlock(out reason)) { LOG.Error("Interlock file has error." + reason); return false; } return true; } public bool InitializeInterlock(out string reason) { List> doMap = GetIONameList(IOType.DO); List> diMap = GetIONameList(IOType.DI); List> list = new List>(); for (int i = 0; i < 1000; i++) { int idx = _ioDefine.Dig_Out[i].Safe_Feedback_Index; if (idx >= 0 && !String.IsNullOrWhiteSpace(_ioDefine.Dig_Out[i].Name)) { list.Add(Tuple.Create(IO.DO[doMap[i].Item3], IO.DI[diMap[idx].Item3])); } } _interlock.InitSafeDO(list); return _interlock.Init(_interlockFile, diMap, doMap, out reason); } public void Terminate() { } public void Monitor() { if (_interlock != null) _interlock.Monitor(); } //buf中的数据 /// /// 更新buf中的数据 /// /// /// /// public void Update(IDataBuffer buf) where T : struct where V : struct { buf.UpdateDI(_di); buf.UpdateDO(_do); buf.UpdateAI(_ai); buf.UpdateAO(_ao); } /// public T GetIO(string name) where T : class { T obj = null; lock (_iomapLocker) { if (_ioMap.ContainsKey(name)) obj = _ioMap[name] as T; } if (obj == null) { if(!String.IsNullOrWhiteSpace(name)) LOG.Error(string.Format("IO not match, can not find {0}",name)); } return obj; } /// /// 返回IO的(io define index,name)列表 /// /// /// iodefine index /// buffer index /// iodefine name /// /// /// /// public List> GetIONameList(IOType ioType) { List> result = new List>(); switch (ioType) { case IOType.AI: foreach (AI_ITEM item in _ioDefine.Ana_In) { if (string.IsNullOrEmpty(item.Name)) continue; result.Add(Tuple.Create(item.Index, GetIndex(item.Addr, 2000), item.Name)); } break; case IOType.AO: foreach (AO_ITEM item in _ioDefine.Ana_Out) { if (string.IsNullOrEmpty(item.Name)) continue; result.Add(Tuple.Create(item.Index, GetIndex(item.Addr, 1000), item.Name)); } break; case IOType.DI: foreach (DI_ITEM item in _ioDefine.Dig_In) { if (string.IsNullOrEmpty(item.Name)) continue; result.Add(Tuple.Create(item.Index, GetIndex(item.Addr, 0), item.Name)); } break; case IOType.DO: foreach (DO_ITEM item in _ioDefine.Dig_Out) { if (string.IsNullOrEmpty(item.Name)) continue; result.Add(Tuple.Create(item.Index, GetIndex(item.Addr, 0), item.Name)); } break; } return result; } private void IOMapping() { lock (_iomapLocker) { //DI foreach (DI_ITEM item in _ioDefine.Dig_In) { if (string.IsNullOrEmpty(item.Name)) continue; int index = GetIndex(item.Addr, 0); if (index >= 0) { DIAccessor diAccessor = new DIAccessor(item.Name, index, _di, _di); _ioMap[item.Name] = diAccessor; //DATA.Subscribe(String.Format("IO.DI.{0}", item.Name), () => { return diAccessor.Value; }); } else { LOG.Write(String.Format("DI{0} mapping error, addr is {1}", item.Index, item.Addr)); } } //DO foreach (DO_ITEM item in _ioDefine.Dig_Out) { if (string.IsNullOrEmpty(item.Name)) continue; int index = GetIndex(item.Addr, 0); if (index >= 0) { DOAccessor doAccessor = new DOAccessor(item.Name, index, _do); _ioMap[item.Name] = doAccessor; //DATA.Subscribe(String.Format("IO.DO.{0}", item.Name), () => { return doAccessor.Value; }); } else { LOG.Write(String.Format("DO{0} mapping error, addr is {1}", item.Index, item.Addr)); } } //AI foreach (AI_ITEM item in _ioDefine.Ana_In) { if (string.IsNullOrEmpty(item.Name)) continue; int index = GetIndex(item.Addr, 2000); if (index >= 0) { AIAccessor aiAccessor = new AIAccessor(item.Name, index, _ai); _ioMap[item.Name] = aiAccessor; //DATA.Subscribe(String.Format("IO.AI.{0}", item.Name), () => { return aiAccessor.Value; }); } else { LOG.Write(String.Format("AI{0} mapping error, addr is {1}", item.Index, item.Addr)); } } //AO foreach (AO_ITEM item in _ioDefine.Ana_Out) { if (string.IsNullOrEmpty(item.Name)) continue; int index = GetIndex(item.Addr, 1000); if (index >= 0) { AOAccessor aoAccessor = new AOAccessor(item.Name, index, _ao); _ioMap[item.Name] = aoAccessor; //DATA.Subscribe(String.Format("IO.AO.{0}", item.Name), () => { return aoAccessor.Value; }); } else { LOG.Write(String.Format("AO{0} mapping error, addr is {1}", item.Index, item.Addr)); } } } } public bool CanSetDo(string doName, bool onOff, out string reason) { return _interlock.CanSetDo(doName, onOff, out reason); } public void SetScale(string ioName, double logicalMin, double logicalMax, double physicalMin, double physicalMax) { _dicScale[ioName] = new IOScale(ioName, logicalMin, logicalMax, physicalMin, physicalMax); } public Dictionary GetScale() { return _dicScale; } private int GetIndex(string addr, int first) { if (String.IsNullOrEmpty(addr)) { LOG.Write("GetIndex addr is empty"); return -1; } string[] parts = addr.Trim().ToUpper().Split('.'); int len = parts.Length; if (len == 1) { string ch = parts[0].TrimStart('D'); int index = Convert.ToUInt16(ch); return (index - first)/2; } if (len == 2) { char[] trim = {'W','C','I','O',' '}; string ch = parts[0].TrimStart(trim); int index = Convert.ToUInt16(ch); int bit = Convert.ToUInt16(parts[1]); return (index - first)*16 + bit; } LOG.Info("IOManager GetIndex error"); return -1; } } }