using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms.VisualStyles; using Aitex.Core.RT.Log; using Aitex.Core.RT.PLC; using Aitex.Core.Util; namespace Aitex.Core.RT.IOCore { public class IOGroupManager { public const int DioBlockLength = 200; public const int AioBlockLength = 200; private Dictionary _ioDefine = new Dictionary(); private object _iomapLocker = new object(); private Dictionary _ioMap = new Dictionary(); private Dictionary _di = new Dictionary(); private Dictionary _do = new Dictionary(); private Dictionary _ai = new Dictionary(); private Dictionary _ao = new Dictionary(); private InterlockManager _interlock = new InterlockManager(); private PeriodicJob _monitorThread; private Dictionary _dicPlcIoBaseAddress = new Dictionary(); public void Initialize(Dictionary ioDefineXmlFile, string interlockConfigFile, Dictionary plcIoBaseAddress, List logicDi) { _dicPlcIoBaseAddress = plcIoBaseAddress; try { foreach (var item in ioDefineXmlFile) { if (!File.Exists(item.Value)) throw new Exception(string.Format("IO item define file not exist, {0}", item.Value)); _ioDefine[item.Key] = CustomXmlSerializer.Deserialize(new FileInfo(item.Value)); _di[item.Key] = new bool[DioBlockLength]; _do[item.Key] = new bool[DioBlockLength]; _ai[item.Key] = new float[AioBlockLength]; _ao[item.Key] = new float[AioBlockLength]; IOMapping(item.Key, plcIoBaseAddress[item.Key]); } } catch (Exception ex) { LOG.Write(ex); throw new Exception(string.Format("IO define file found error, \r\n {0}", ex.Message)); } _di["logic"] = new bool[DioBlockLength]; int index = 0; foreach (var diName in logicDi) { DIAccessor diAccessor = new DIAccessor(diName, index, _di["logic"], _di["logic"]); _ioMap[diName] = diAccessor; diAccessor.IoTableIndex = index; index++; } string reason = string.Empty; if (!_interlock.Initialize(interlockConfigFile, _ioMap, out reason)) { throw new Exception(string.Format("interlock define file found error: \r\n {0}", reason)); } _monitorThread = new PeriodicJob(200, OnTimer, "IO Monitor Thread", true); } private bool OnTimer() { try { _interlock.Monitor(); } catch (Exception ex) { LOG.Write(ex); } return true; } public void Update(string group, IDataBuffer buf) where T : struct where V : struct { buf.UpdateDI(_di[group]); buf.UpdateDO(_do[group]); buf.UpdateAI(_ai[group]); buf.UpdateAO(_ao[group]); } 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; } private void IOMapping(string group, int[] plcIoBaseAddress) { lock (_iomapLocker) { //DI foreach (DI_ITEM item in _ioDefine[group].Dig_In) { if (string.IsNullOrEmpty(item.Name)) continue; int index = GetIndex(item.Addr, plcIoBaseAddress[0]); if (index > 200) { LOG.Write(String.Format("DI {0} mapping index larger than buffer, addr is {1}", item.Index, item.Addr)); } if (index >= 0) { DIAccessor diAccessor = new DIAccessor(item.Name, index, _di[group], _di[group]); _ioMap[item.Name] = diAccessor; diAccessor.IoTableIndex = item.Index; //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[group].Dig_Out) { if (string.IsNullOrEmpty(item.Name)) continue; int index = GetIndex(item.Addr, plcIoBaseAddress[1]); if (index > 200) { LOG.Write(String.Format("DO {0} mapping index larger than buffer, addr is {1}", item.Index, item.Addr)); } if (index >= 0) { DOAccessor doAccessor = new DOAccessor(item.Name, index, _do[group]); _ioMap[item.Name] = doAccessor; doAccessor.IoTableIndex = item.Index; //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[group].Ana_In) { if (string.IsNullOrEmpty(item.Name)) continue; int index = GetIndex(item.Addr, plcIoBaseAddress[2]); if (index > 200) { LOG.Write(String.Format("AI {0} mapping index larger than buffer, addr is {1}", item.Index, item.Addr)); } if (index >= 0) { AIAccessor aiAccessor = new AIAccessor(item.Name, index, _ai[group]); _ioMap[item.Name] = aiAccessor; aiAccessor.IoTableIndex = item.Index; //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[group].Ana_Out) { if (string.IsNullOrEmpty(item.Name)) continue; int index = GetIndex(item.Addr, plcIoBaseAddress[3]); if (index > 200) { LOG.Write(String.Format("AO {0} mapping index larger than buffer, addr is {1}", item.Index, item.Addr)); } if (index >= 0) { AOAccessor aoAccessor = new AOAccessor(item.Name, index, _ao[group]); _ioMap[item.Name] = aoAccessor; aoAccessor.IoTableIndex = item.Index; //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)); } } } } 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; } public bool CanSetDo(string doName, bool onOff, out string reason) { return _interlock.CanSetDo(doName, onOff, out reason); } public List> GetIONameList(string group, IOType ioType) { List> result = new List>(); if (!_dicPlcIoBaseAddress.ContainsKey(group)) return result; int[] plcIoBaseAddress = _dicPlcIoBaseAddress[group]; switch (ioType) { case IOType.AI: foreach (AI_ITEM item in _ioDefine[group].Ana_In) { if (string.IsNullOrEmpty(item.Name)) continue; result.Add(Tuple.Create(item.Index, GetIndex(item.Addr, plcIoBaseAddress[2]), item.Name)); } break; case IOType.AO: foreach (AO_ITEM item in _ioDefine[group].Ana_Out) { if (string.IsNullOrEmpty(item.Name)) continue; result.Add(Tuple.Create(item.Index, GetIndex(item.Addr, plcIoBaseAddress[3]), item.Name)); } break; case IOType.DI: foreach (DI_ITEM item in _ioDefine[group].Dig_In) { if (string.IsNullOrEmpty(item.Name)) continue; result.Add(Tuple.Create(item.Index, GetIndex(item.Addr, plcIoBaseAddress[0]), item.Name)); } break; case IOType.DO: foreach (DO_ITEM item in _ioDefine[group].Dig_Out) { if (string.IsNullOrEmpty(item.Name)) continue; result.Add(Tuple.Create(item.Index, GetIndex(item.Addr, plcIoBaseAddress[1]), item.Name)); } break; } return result; } public void Terminate() { try { _monitorThread.Stop(); } catch (Exception ex) { LOG.Write(ex); } } } }