using System; using System.Collections.Generic; using DTS.Common.Interface.DASFactory; using DTS.Common.Utilities.Logging; using DTS.DASLib.Service; using System.Threading; using System.Linq; using DTS.Common.SharedResource.Strings; using DTS.Common.DataModel.Common; using DTS.Common.Enums.TSRAIRGo; using DTS.Common.Constant.DASSpecific; using DTS.Common.DataModel.Classes.TSRAIRGo; namespace DataPROWin7.DataModel.Classes { public class Arming { readonly Configuration configuration = new Configuration(); public Arming() { } public bool SetConfigAndFlashClear(DataModel.TestTemplate currentTest, List dasList, Dictionary dasSampleRateList, double duration, StatusHelpers.SetProgressValueDelegate setProgressFunction, ServiceBase.ServiceCallbackErrorEventHandler onError) { return SetConfigAndStartFlashClear(currentTest, dasList, dasSampleRateList, duration, false, setProgressFunction, onError); } private bool SetConfigAndStartFlashClear(DataModel.TestTemplate currentTest, List dasList, Dictionary dasSampleRateList, double duration, bool diagnosticsVoltage, StatusHelpers.SetProgressValueDelegate setProgressFunction, ServiceBase.ServiceCallbackErrorEventHandler onError) { foreach (var das in dasList) { foreach (var mod in das.ConfigData.Modules) { mod.PostTriggerSeconds = duration; mod.PreTriggerSeconds = (double)TSRAIR.TSRAIR_MAX_PRE_TRIGGER_SAMPLES / Convert.ToInt32(dasSampleRateList[das.SerialNumber]); //FB 26980 mod.NumberOfEvents has already a correct value but override it to make sure the value is there mod.NumberOfEvents = currentTest.NumberOfEvents; mod.WakeUpMotionTimeout = currentTest.WakeUpMotionTimeout; //10? } } try { foreach (var das in dasList) { setProgressFunction(das, 0D, TSRAIRGoStatus.StatusTypes.PREPARING_FOR_ARMING); } configuration.SetConfig(currentTest, dasList, diagnosticsVoltage, setProgressFunction); foreach (var das in dasList) { setProgressFunction(das, 0D, TSRAIRGoStatus.StatusTypes.PREPARING_DATA_MEMORY); } return StartFlashClear(dasList, setProgressFunction, currentTest, onError); } catch (Exception ex) { onError?.Invoke(this, $"{StringResources.FailedToArm}: {ex.Message}", ex); APILogger.Log(ex.Message); return false; } } protected bool StartFlashClear(List dasList, StatusHelpers.SetProgressValueDelegate setProgressFunction, DataModel.TestTemplate currentTest, ServiceBase.ServiceCallbackErrorEventHandler onError) { return FlashErase(dasList, setProgressFunction, currentTest, onError); } protected bool FlashErase(List dasList, StatusHelpers.SetProgressValueDelegate setProgressFunction, DataModel.TestTemplate currentTest, ServiceBase.ServiceCallbackErrorEventHandler onError) { var cancelEvent = new ManualResetEvent(false); var resetEvent = new ManualResetEvent(false); var bFailed = false; var flashDevices = new List(dasList); var failureToClearFlashDevices = new List(); lock (DASHardware.GetArmStatusLock) { if (flashDevices.Any()) { using (var armingService = new ArmingService()) { armingService.AggregateProgress = false; var done = new ManualResetEvent(false); var timeWaited = 0; armingService.BeginFlashErase(flashDevices, delegate (ServiceBase.CallbackData cbd) { switch (cbd.Status) { case ServiceBase.CallbackData.CallbackStatus.Failure: bFailed = true; //39345 Don't hang if Flash Erase fails cbd.Target.DASArmStatus.FaultMessage = StringResources.ArmSystem_FailedToClearFlash; cbd.Target.SetDASArmStatus(); onError?.Invoke(this, string.Format(StringResources.ArmSystem_FailedToClearFlash, cbd.Target.SerialNumber), null); failureToClearFlashDevices.Add(cbd.Target); break; case ServiceBase.CallbackData.CallbackStatus.AllFinished: done.Set(); break; case ServiceBase.CallbackData.CallbackStatus.Success: break; } }, flashDevices, false); while (!cancelEvent.WaitOne(0, false) && !done.WaitOne(50, false)) { timeWaited += 50; } } } //39345 Don't hang if Flash Erase fails if (bFailed) { return false; } if (flashDevices.Any()) { using (var armingService = new ArmingService()) { armingService.AggregateProgress = false; var bDone = false; var flashStatus = new Dictionary(); foreach (var das in flashDevices) { flashStatus[das] = false; } while (!bDone) { var done = new ManualResetEvent(false); var timeWaited = 0; armingService.GetFlashEraseStatus(flashDevices, delegate (ServiceBase.CallbackData cbd) { switch (cbd.Status) { case ServiceBase.CallbackData.CallbackStatus.Failure: bFailed = true; flashStatus[cbd.Target] = true; failureToClearFlashDevices.Add(cbd.Target); onError?.Invoke(this, string.Format(StringResources.ArmSystem_FailedToClearFlash, cbd.Target.SerialNumber), cbd.ErrorException); break; case ServiceBase.CallbackData.CallbackStatus.Success: flashStatus[cbd.Target] = true; break; case ServiceBase.CallbackData.CallbackStatus.AllFinished: { using (var enumeratorFlashStatus = flashStatus.GetEnumerator()) { var b = true; while (enumeratorFlashStatus.MoveNext()) { if (!enumeratorFlashStatus.Current.Value) { b = false; } } bDone = b; } } done.Set(); break; case ServiceBase.CallbackData.CallbackStatus.Progress: StatusHelpers.SetStatus2(cbd.Target, cbd.ProgressValue, TSRAIRGoStatus.StatusTypes.PREPARING_DATA_MEMORY, setProgressFunction); if (100 <= cbd.ProgressValue) { flashStatus[cbd.Target] = true; } break; } }, flashDevices); while (!cancelEvent.WaitOne(0, false) && !done.WaitOne(50, false)) { timeWaited += 50; } if (cancelEvent.WaitOne(0, false)) { bDone = true; } } } //39345 Don't hang if Flash Erase fails if (bFailed) { return false; } } } if (!cancelEvent.WaitOne(0, false) && !bFailed) { return PrepareArmFunc(dasList, setProgressFunction, currentTest, onError); } else if (bFailed) { resetEvent.Set(); cancelEvent.Set(); return false; } return true; } protected bool PrepareArmFunc(List dasList, StatusHelpers.SetProgressValueDelegate setProgressFunction, DataModel.TestTemplate currentTest, ServiceBase.ServiceCallbackErrorEventHandler onError ) { const int ARM_NOW_TIMEOUT = 30000; var cancelEvent = new ManualResetEvent(false); var g = Guid.NewGuid(); var bFailedPrepareArm = false; lock (DASHardware.GetArmStatusLock) { if (currentTest.LevelTriggerChannels.Count > 0) { using (var armService = new ArmingService()) { var mre = new ManualResetEvent(false); armService.CheckAlreadyLevelTriggered(dasList, delegate (ServiceBase.CallbackData cbd) { switch (cbd.Status) { case ServiceBase.CallbackData.CallbackStatus.Failure: onError(this, $"{StringResources.ArmSystem_FailedArm} {cbd.ErrorMessage} - {cbd.Target.SerialNumber}", cbd.ErrorException); bFailedPrepareArm = true; break; case ServiceBase.CallbackData.CallbackStatus.AllFinished: mre.Set(); break; } }, dasList); mre.WaitOne(); var alreadyLevelTriggeredChannels = (from das in dasList where null != das.ConfigData from m in das.ConfigData.Modules from ch in m.Channels where ch is AnalogInputDASChannel let aCh = ch as AnalogInputDASChannel where aCh.AlreadyLevelTriggered select $"{das.SerialNumber} {1 + aCh.Number}").ToList(); if (alreadyLevelTriggeredChannels.Count > 0) { bFailedPrepareArm = true; var errors = new List(); errors.Add(StringResources.AlreadyLevelTriggeredChannels); errors.AddRange(alreadyLevelTriggeredChannels.ToArray()); } } } if (!bFailedPrepareArm) { using (var armService = new ArmingService()) { var done = new ManualResetEvent(false); var timeWaited = 0; armService.ReadyForArm(dasList, delegate (ServiceBase.CallbackData cbd) { switch (cbd.Status) { case ServiceBase.CallbackData.CallbackStatus.AllFinished: done.Set(); break; case ServiceBase.CallbackData.CallbackStatus.Progress: StatusHelpers.SetStatus2(cbd.Target, cbd.ProgressValue, TSRAIRGoStatus.StatusTypes.PREPARING_FOR_ARMING, setProgressFunction); break; case ServiceBase.CallbackData.CallbackStatus.Success: break; case ServiceBase.CallbackData.CallbackStatus.Failure: bFailedPrepareArm = true; onError(this, $"{StringResources.ArmSystem_FailedArm} {cbd.ErrorMessage} - {cbd.Target.SerialNumber}", cbd.ErrorException); break; } }, dasList, 600000, false, currentTest.NumberOfEvents, 0, g, false, dasList.Count > 1); while (!cancelEvent.WaitOne(0, false) && !done.WaitOne(50, false)) { timeWaited += 50; } } } if (!bFailedPrepareArm) { using (var armService = new ArmingService()) { var done = new ManualResetEvent(false); var timeWaited = 0; armService.PrepareForArmNow(dasList, delegate (ServiceBase.CallbackData cbd) { switch (cbd.Status) { case ServiceBase.CallbackData.CallbackStatus.AllFinished: done.Set(); break; case ServiceBase.CallbackData.CallbackStatus.Failure: onError(this, $"{StringResources.ArmSystem_FailedArm} {cbd.ErrorMessage} - {cbd.Target.SerialNumber}", cbd.ErrorException); bFailedPrepareArm = true; break; case ServiceBase.CallbackData.CallbackStatus.Success: break; case ServiceBase.CallbackData.CallbackStatus.Progress: StatusHelpers.SetStatus2(cbd.Target, cbd.ProgressValue, TSRAIRGoStatus.StatusTypes.PREPARING_FOR_ARMING, setProgressFunction); break; } }, dasList, ARM_NOW_TIMEOUT, false, currentTest.NumberOfEvents, g, dasList.Count > 1/* && CurrentTest.CommonLine*/); while (!cancelEvent.WaitOne(0, false) && !done.WaitOne(50, false)) { timeWaited += 50; } if (!cancelEvent.WaitOne(0, false)) { done.Reset(); } } if (bFailedPrepareArm) { cancelEvent.Set(); return false; } } else { cancelEvent.Set(); return false; } } return ArmNowFunc(dasList, setProgressFunction, currentTest, onError); } protected bool ArmNowFunc(List dasList, StatusHelpers.SetProgressValueDelegate setProgressFunction, DataModel.TestTemplate currentTest, ServiceBase.ServiceCallbackErrorEventHandler onError) { var cancelEvent = new ManualResetEvent(false); if (Common.SerializedSettings.StoreTestHistoryInDb) { //add code here? } var g = Guid.NewGuid(); var bFailedArm = false; lock (DASHardware.GetArmStatusLock) { var bSomeoneArmed = false; using (var armService = new ArmingService()) { var done = new ManualResetEvent(false); var timeWaited = 0; done.Reset(); var disarmList = new List(); PreparedArmNowFunc(dasList, g, ref bSomeoneArmed, ref bFailedArm, ref timeWaited, ref disarmList, setProgressFunction, currentTest, onError); //for safety reasons, make a disarm call to _everybody_ that "failed to arm", incase a module armed but the rack didn't //http://fogbugz/fogbugz/default.asp?4527 if (done.WaitOne(0, false) && disarmList.Count > 0) { done.Reset(); bSomeoneArmed = false; using (var aService = new ArmingService()) { aService.Disarm(dasList, delegate (ServiceBase.CallbackData cbd) { switch (cbd.Status) { case ServiceBase.CallbackData.CallbackStatus.AllFinished: done.Set(); break; } } , dasList); } while (!cancelEvent.WaitOne(0, false) && !done.WaitOne(50, false)) { } } } if (bSomeoneArmed) { if (!cancelEvent.WaitOne(0, false)) { var das = new List(dasList); for (var i = das.Count - 1; i >= 0; i--) { if (null == das[i].DASArmStatus || das[i].DASArmStatus.IsArmed == false) { das.RemoveAt(i); } else { if (null != das[i].ConfigData && das[i].ConfigData.NumberOfConfiguredChannels() == 0 /*&& CareAboutNumberOfConfiguredChannels(das[i])*/) { das.RemoveAt(i); } } } var bFailedEnableFaultChecking = false; var faultCheckingErrors = new List(); //keeps track of whether we need to restore semaphores //15630 limit EnableFaultChecking to single unit at a time for TDAS when there's a rack involved if (das.Count > 1) { using (var armService = new ArmingService()) { var done = new ManualResetEvent(false); var timeWaited = 0; armService.EnableFaultChecking(dasList, delegate (ServiceBase.CallbackData cbd) { switch (cbd.Status) { case ServiceBase.CallbackData.CallbackStatus.AllFinished: done.Set(); break; case ServiceBase.CallbackData.CallbackStatus.Failure: bFailedEnableFaultChecking = true; faultCheckingErrors.Add($"{cbd.Target.SerialNumber} {StringResources.FailedEnableFaultChecking}"); onError(this, $"{StringResources.ArmSystem_FailedArm} {cbd.ErrorMessage} - {cbd.Target.SerialNumber}", cbd.ErrorException); break; } }, das); while (!cancelEvent.WaitOne(0, false) && !done.WaitOne(50, false)) { timeWaited += 50; } } } //15267 Stop on ERR response from TDAS ARM RF if (bFailedEnableFaultChecking) { DisarmAll(dasList); cancelEvent.Set(); return false; } } } else if (bFailedArm) { cancelEvent.Set(); return false; } } return true; } private void DisarmAll(List das) { var mre = new ManualResetEvent(false); using (var aService = new ArmingService()) { aService.Disarm(das, delegate (ServiceBase.CallbackData cbd) { switch (cbd.Status) { case ServiceBase.CallbackData.CallbackStatus.AllFinished: mre.Set(); break; } } , das); } mre.WaitOne(); } private void PreparedArmNowFunc(List dasList, Guid g, ref bool bSomeoneArmed, ref bool bFailedArm, ref int timeWaited, ref List lDisarmList, StatusHelpers.SetProgressValueDelegate setProgressFunction, DataModel.TestTemplate currentTest, ServiceBase.ServiceCallbackErrorEventHandler onError) { var someoneArmed = false; var failedArm = false; var disarmList = new List(); var doneEvent = new ManualResetEvent(false); var cancelEvent = new ManualResetEvent(false); var done = doneEvent; using (var armService = new ArmingService()) { armService.PreparedArmNow(dasList, delegate (ServiceBase.CallbackData cbd) { switch (cbd.Status) { case ServiceBase.CallbackData.CallbackStatus.AllFinished: done.Set(); break; case ServiceBase.CallbackData.CallbackStatus.Failure: onError(this, $"{StringResources.ArmSystem_FailedArm} {cbd.ErrorMessage} - {cbd.Target.SerialNumber}", cbd.ErrorException); disarmList.Add(cbd.Target); failedArm = true; break; case ServiceBase.CallbackData.CallbackStatus.Success: if (!cbd.Target.IsEthernetDistributor()) { someoneArmed = true; try { if (null == cbd.Target.DASArmStatus) { cbd.Target.DASArmStatus = new ArmStatus(); } cbd.Target.DASArmStatus.IsArmed = true; cbd.Target.SetDASArmStatus(); } catch (Exception ex) { APILogger.Log(ex.Message); } } break; case ServiceBase.CallbackData.CallbackStatus.Progress: StatusHelpers.SetStatus2(cbd.Target, cbd.ProgressValue, TSRAIRGoStatus.StatusTypes.PREPARING_FOR_ARMING, setProgressFunction); break; } }, dasList, 30000, false, currentTest.NumberOfEvents, g, dasList.Count > 1); ///////////fix the 30000 and 1 (at least) } while (!cancelEvent.WaitOne(0, false) && !done.WaitOne(50, false)) { timeWaited += 50; } bSomeoneArmed = bSomeoneArmed || someoneArmed; bFailedArm = bFailedArm || failedArm; lDisarmList.AddRange(disarmList); doneEvent = done; } public void SoftwareTrigger(List dasList) { try { using (var armingService = new ArmingService()) { lock (DASHardware.GetArmStatusLock) { var mre = new ManualResetEvent(false); armingService.Trigger(dasList, delegate (ServiceBase.CallbackData data) { switch (data.Status) { case ServiceBase.CallbackData.CallbackStatus.AllFinished: mre.Set(); break; case ServiceBase.CallbackData.CallbackStatus.Failure: APILogger.Log(data.ErrorMessage); break; } }, dasList); while (!mre.WaitOne(10, false)) { } } } } catch (Exception ex) { APILogger.Log("Failure in Software Trigger"); APILogger.Log(ex); } } public void DisarmAsync(List dasList) { Disarm(dasList); } private void Disarm(List dasList) { DisarmSync(dasList); } private void DisarmSync(List dasList) { var mre = new ManualResetEvent(false); using (var armingService = new ArmingService()) { lock (DASHardware.GetArmStatusLock) { armingService.Disarm( dasList, delegate (ServiceBase.CallbackData data) { switch (data.Status) { case ServiceBase.CallbackData.CallbackStatus.AllFinished: mre.Set(); break; case ServiceBase.CallbackData.CallbackStatus.Canceled: break; case ServiceBase.CallbackData.CallbackStatus.Failure: break; case ServiceBase.CallbackData.CallbackStatus.Progress: break; case ServiceBase.CallbackData.CallbackStatus.Success: break; } }, dasList); while (!mre.WaitOne(10, false)) { } } } } } }