using Aurora; using Aurora.Api; using Aurora.Api.Manager; using AuroraACS; using AuroraDeviceCommon.Utils; using AuroraIO.AJINEXTEK; using AuroraIO.Vendor.ACS; using AuroraIO.Vendor.PAIX; using Hermes; using System; using System.Collections.Generic; using System.IO; using static AuroraIO.Vendor.PAIX.PAIXIO; using ACSIO = AuroraIO.Vendor.ACS.ACSIO; namespace AuroraIO { public enum eIOBoardType { Ajin, PAIX, ACS } public partial class IODevice : Device { protected Logger Log = new Logger("IODevcie"); private IConnConfig _connConfig; protected readonly IAuroraEnvironment _auroraEnv; private readonly bool _IsSimulBySetting; public MicroTimer _monitorIOInterfaceMap = new MicroTimer(); private readonly Device _refDevice; #warning IO Unit은 Interface만 담당해야 함으로 IO 정보를 가진 데이터는 IODevice에서 관리하도록 하는게 나을 것으로 생각 private bool[] _DI; private bool[] _DO; public IOUnit _iOUnit { get; set; } public IODevice(IAuroraEnvironment auroraEnv, string deviceId, bool isSimul) { _auroraEnv = auroraEnv; _IsSimulBySetting = isSimul; DeviceId = deviceId; //monitorIOInterfaceMap.OnTimeout = MonitorIOInterfaceMap; } public IODevice(IAuroraEnvironment auroraEnv, string deviceId, bool isSimul, Device refDevice = null) { _auroraEnv = auroraEnv; _IsSimulBySetting = isSimul; DeviceId = deviceId; _refDevice = refDevice; //monitorIOInterfaceMap.OnTimeout = MonitorIOInterfaceMap; } public class ChangeChecker { private static Dictionary mapping = new Dictionary(); public static bool IsChangedBool(string Resource, bool value, bool defaultVal = false) { if (mapping.ContainsKey(Resource) == false) { mapping[Resource] = defaultVal; return false; } if (mapping[Resource] == value) { return false; } mapping[Resource] = value; return true; } public static bool IsChangedBoolMonitoring(string Resource, bool value, bool MonitoringValue, bool defaultVal = false) { if (mapping.ContainsKey(Resource) == false) { mapping[Resource] = defaultVal; return false; } if (mapping[Resource] == value) { return false; } mapping[Resource] = value; if (mapping[Resource] == MonitoringValue) return true; return false; } } private void MonitorIOInterfaceMap() { //함수 내부에 IO 시나리오에 맞게 구현 필요, 인터락 처리 등.. //EMO Check, Main N2/CDA Alarm Check if (_iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.EMOSwitchFront))) || _iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.EMOSwitchBack))) || _iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.MainCDAAlarm))) || _iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.MainN2Alarm)))) { _iOUnit.WriteDoBit((Convert.ToInt32(ePDOAddress.BuzzerOn)), true); _iOUnit.WriteDoBit((Convert.ToInt32(ePDOAddress.TowerLampREDOn)), true); _iOUnit.WriteDoBit((Convert.ToInt32(ePDOAddress.TowerLampGREENOn)), false); _auroraEnv.ViewManager.SetTowerLamp(eTowerLamp.RED); } else { _iOUnit.WriteDoBit((Convert.ToInt32(ePDOAddress.BuzzerOn)), false); _iOUnit.WriteDoBit((Convert.ToInt32(ePDOAddress.TowerLampREDOn)), false); } //Door Open Check, Panel Temp Alarm, Fan Alarmm, Motor MC Check => Warning if (_iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.DoorLockOpen1))) || _iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.DoorLockOpen2))) || _iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.DoorLockOpen3))) || _iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.DoorLockOpen4))) || _iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.PanelTempAlarm))) || _iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.FanAlarm5))) || _iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.FanAlarm6))) || _iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.FanAlarm7))) || _iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.FanAlarm8))) || !_iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.L2MotorMCOn))) ) { _iOUnit.WriteDoBit((Convert.ToInt32(ePDOAddress.TowerLampYELLOWOn)), true); _iOUnit.WriteDoBit((Convert.ToInt32(ePDOAddress.TowerLampGREENOn)), false); _auroraEnv.ViewManager.SetTowerLamp(eTowerLamp.ORANGE); } else { _iOUnit.WriteDoBit((Convert.ToInt32(ePDOAddress.TowerLampYELLOWOn)), false); _iOUnit.WriteDoBit((Convert.ToInt32(ePDOAddress.TowerLampGREENOn)), true); _auroraEnv.ViewManager.SetTowerLamp(eTowerLamp.GREEN); } //Door Lock Check if (_iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.DoorLockCloseMonitoring)))) { _auroraEnv.ViewManager.DoorLock(true); } else { _auroraEnv.ViewManager.DoorLock(false); } //Door Open PM bool DoorOpen = _iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.DoorLockOpen1))) || _iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.DoorLockOpen2))) || _iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.DoorLockOpen3))) || _iOUnit.ReadDiBit((Convert.ToInt32(ePDIAddress.DoorLockOpen4))); if (ChangeChecker.IsChangedBool("Door", DoorOpen)) { //EventID Class를 ILSOS에서 받아올수 없을듯.. IODef에 EventID를 선언해주고 ILSOS에 넘겨주자.. EventPublisher.Publish(new EventMessage("DoorInterlock", IODef.EVENT_DOOR_INTERLOCK, DoorOpen)); } } protected override int DoActivate(IDeviceConfig config) { _connConfig = config.ConnConfig; var m_IOUnitConfig = config as IOUnitConfig; IsSimul = m_IOUnitConfig.IsDeviceSimul || _IsSimulBySetting; if (IsSimul) { //test용 if (m_IOUnitConfig.BoardType == eIOBoardType.Ajin) _iOUnit = new AjinIO(); else if (m_IOUnitConfig.BoardType == eIOBoardType.PAIX) _iOUnit = new PAIXIO(); else if (m_IOUnitConfig.BoardType == eIOBoardType.ACS) _iOUnit = new ACSIO(_refDevice, m_IOUnitConfig); LoadIOTable(); return E1.OK; } else { if (m_IOUnitConfig.BoardType == eIOBoardType.Ajin) { _iOUnit = new AjinIO(); } else if (m_IOUnitConfig.BoardType == eIOBoardType.PAIX) { _iOUnit = new PAIXIO(); } else if (m_IOUnitConfig.BoardType == eIOBoardType.ACS) { _iOUnit = new ACSIO(_refDevice, m_IOUnitConfig); } else { Log.I(string.Format("")); } } int nRet = _iOUnit.Open(m_IOUnitConfig.DIDOIP); if (nRet != 0) return nRet; LoadIOTable(); nRet = _iOUnit.Initialize(); if (_iOUnit.IsConnected() && m_IOUnitConfig.BoardType == eIOBoardType.PAIX) { //monitorTimer는 우선 하드코딩으로 구성, Config로 받아와도 됨 //_monitorIOInterfaceMap.UpdateRateUS = 50 * 1000; //IO쪽 완료 되기 전까지 주석처리 //_monitorIOInterfaceMap.Start(); //SetMonitoringService(MonitorIOInterfaceMap, 100); //StartMonitoringService(); } if (_iOUnit.IsConnected() && m_IOUnitConfig.BoardType == eIOBoardType.ACS) { SetMonitoringService(Monitoring, 50); StartMonitoringService(); } return nRet; } private void Monitoring() { ACSDevice acs = _refDevice as ACSDevice; if (!acs.IsActivated) return; if (_iOUnit.GetDiArray(ref _DI) != E1.OK) return; if (_iOUnit.GetDoArray(ref _DO) != E1.OK) return; } public bool ReadDI(int index) => _iOUnit.ReadDiBit(index); // >> _ID 호출해도됨 _DI[index] public bool ReadDO(int index) => _iOUnit.ReadDoBit(index); // >> _DO 호출해도됨 _DO[index] public void WriteDO(int index, bool on) => _iOUnit.WriteDoBit(index, on); protected override int DoDeactivate() { if (_iOUnit != null) { _iOUnit.ClearList(); _iOUnit.Close(); } StopMonitoringService(); return E1.OK; } public bool IsConnected() { if (_iOUnit == null) { return false; } return _iOUnit.IsConnected(); } public int LoadIOTable() { foreach (InfoIO.IoType type in Enum.GetValues(typeof(InfoIO.IoType))) { if (type == InfoIO.IoType.EnumSize || type == InfoIO.IoType.AO || type == InfoIO.IoType.AI) continue; MappingDIO(type); } return 0; } public int MappingDIO(InfoIO.IoType type) { try { string fileName = ""; var m_connConfig = _connConfig as IOUnitConnConfig; switch (type) { case InfoIO.IoType.DI: fileName = m_connConfig.IOInterfaceMapDI; break; case InfoIO.IoType.DO: fileName = m_connConfig.IOInterfaceMapDO; break; //case InfoIO.IoType.AI: // fileName = m_connConfig.IOInterfaceMapAI; // break; //case InfoIO.IoType.AO: // fileName = m_connConfig.IOInterfaceMapAO; // break; default: break; //case InfoPlcIO.PlcIoType.SI: // fileName = m_connConfig.PLCInterfaceMapSI; // break; //case InfoPlcIO.PlcIoType.SO: // fileName = m_connConfig.PLCInterfaceMapSO; // break; } FileInfo fi = new FileInfo(fileName); if (!fi.Directory.Exists) { fi.Directory.Create(); } if (File.Exists(fileName) == false) { Log.I(string.Format($"파일({fileName})이 존재하지 않습니다. Device Config의 File 경로를 확인하세요.")); return 0; //StreamWriter writer = new StreamWriter(fileName, false, System.Text.Encoding.Unicode); //writer.WriteLine("Index,Address,ID,IoType,ActiveLevel,BoardNo,Description,HighNecCond,LowNecCond,HighSensor,LowSensor,WaitInterlockTimeOut,WaitSensorTimeOut,HighSufCond,LowSufCond"); //writer.Close(); } StreamReader sr = new StreamReader(fileName, System.Text.Encoding.Default); string header = sr.ReadLine(); int index = 0; while (sr.Peek() > -1) { InfoIO dio = new InfoIO(); string[] temp = sr.ReadLine().ToString().Split(','); if (dio.ConvertIOInfo(temp) == false) { throw new Exception(string.Format("{0}.csv file {1}line data length wrong!!")); } if (type == InfoIO.IoType.DI) _iOUnit.ListDI.Add(dio); else if (type == InfoIO.IoType.DO) _iOUnit.ListDO.Add(dio); //else if (type == InfoIO.IoType.AI) // ListAI.Add(dio); //else if (type == InfoIO.IoType.AO) // ListAO.Add(dio); index++; } sr.Close(); return 0; } catch { throw; } } } }