public void ReforceCalibration() { // arrange dockingStation = Helper.GetDockingStationForTest(DeviceType.GBPRO); instrument = Helper.GetInstrumentForTest(DeviceType.GBPRO); List <InstalledComponent> installedComponents = Helper.GetSensorsForTest(new List <string>() { GasCode.CO }); instrument.InstalledComponents.AddRange(installedComponents); Initialize(); // act dsEvent = new NothingEvent(); CreateMasterForTest(); scheduler.ReForceEvent(new InstrumentCalibrationAction() { Trigger = TriggerType.Forced }); nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is InstrumentCalibrationAction); Xunit.Assert.True(nextAction.Trigger == TriggerType.Forced); }
public void GetCalibrationActionForSensorRemoved() { // arrange InstrumentCalibrationAction action = new InstrumentCalibrationAction(); instrument = Helper.GetInstrumentForTest(DeviceType.VPRO, DeviceSubType.VentisPro4); List <InstalledComponent> installedComponents = Helper.GetSensorsForTest(new List <string>() { GasCode.CO, GasCode.H2S, GasCode.O2, GasCode.CombustibleLEL }); dockingStation = Helper.GetDockingStationForTest(DeviceType.MX4); List <EventJournal> eventJournals = new List <EventJournal>(); eventJournals.Add(new EventJournal(EventCode.GetCachedCode(EventCode.InstrumentDiagnostics), instrument.SerialNumber, DateTime.Now.AddMonths(-1), DateTime.Now.AddMonths(-1), true, instrument.SoftwareVersion)); installedComponents.ForEach(comp => eventJournals.Add(new EventJournal(EventCode.Calibration, comp.Component.Uid, instrument.SerialNumber, DateTime.Now.AddMonths(-1), DateTime.Now.AddMonths(-1), true, comp.Position, instrument.SoftwareVersion))); installedComponents.Remove(installedComponents.Last()); instrument.InstalledComponents.AddRange(installedComponents); _eventJournalDataAccess.Setup(x => x.FindBySerialNumbers(It.IsAny <string[]>(), It.IsAny <IDataAccessTransaction>())).Returns(eventJournals); _eventJournalDataAccess.Setup(x => x.FindLastEventByInstrumentSerialNumber(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <IDataAccessTransaction>())).Returns(eventJournals); Initialize(); // act CreateMasterForTest(); schema.Setup(x => x.Activated).Returns(true); InstrumentCalibrationOperation operation = new InstrumentCalibrationOperation(action); dsEvent = new InstrumentCalibrationEvent(operation); nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is InstrumentCalibrationAction); }
public void GetNothingActionIfNoEventIsScheduled() { // arrange instrument = Helper.GetInstrumentForTest(DeviceType.VPRO, DeviceSubType.VentisPro4); dockingStation = Helper.GetDockingStationForTest(DeviceType.MX4); InstrumentAlarmEventsClearOperation operation = new InstrumentAlarmEventsClearOperation(); List <EventJournal> eventJournals = new List <EventJournal>(); eventJournals.Add(new EventJournal(EventCode.GetCachedCode(EventCode.InstrumentDiagnostics), instrument.SerialNumber, DateTime.Now.AddMonths(-1), DateTime.Now.AddMonths(-1), true, instrument.SoftwareVersion)); _eventJournalDataAccess.Setup(x => x.FindBySerialNumbers(It.IsAny <string[]>(), It.IsAny <IDataAccessTransaction>())).Returns(eventJournals); _eventJournalDataAccess.Setup(x => x.FindLastEventByInstrumentSerialNumber(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <IDataAccessTransaction>())).Returns(eventJournals); Initialize(); // act schema.Setup(x => x.Activated).Returns(true); dsEvent = new InstrumentAlarmEventsClearEvent(operation); CreateMasterForTest(); nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is NothingAction); }
public void InstrumentRequiresOperatorAction() { // arrange SettingsReadOperation operation = new SettingsReadOperation(); dsEvent = new SettingsReadEvent(operation); dockingStation = Helper.GetDockingStationForTest(DeviceType.MX4); instrument = Helper.GetInstrumentForTest(DeviceType.VPRO, DeviceSubType.VentisPro4); Initialize(); Sensor sensor = new Sensor(); sensor.Enabled = true; sensor.CalibrationStatus = Status.Failed; sensor.Type.Code = SensorCode.O3; InstalledComponent installedComponent = new InstalledComponent(); installedComponent.Position = 1; installedComponent.Component = sensor; instrument.InstalledComponents.Add(installedComponent); Configuration.DockingStation = dockingStation; CreateMasterForTest(); // act nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is ManualCalibrationRequiredAction); }
public void ReturnManualBumpTestRequiredActionForInstrumentWithBumpFailedSensor() { // arrange InstrumentBumpTestAction action = Helper.GetBumpTestAction(DeviceType.VPRO, new List <string>() { GasCode.CO, GasCode.H2S, GasCode.O3 }, DeviceSubType.VentisPro4); foreach (InstalledComponent installedComponent in action.Instrument.InstalledComponents.Where(comp => comp.Component is Sensor)) { Sensor sensor = installedComponent.Component as Sensor; sensor.BumpTestStatus = false; } instrument = action.Instrument; Initialize(); CreateMasterForTest(); // act InstrumentBumpTestOperation operation = new InstrumentBumpTestOperation(action); dsEvent = new InstrumentBumpTestEvent(operation); nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is ManualBumpTestRequiredAction); }
public void GetCalibrationActionforForcedBumpTestOnCalFailedSensors() { // arrange instrument = Helper.GetInstrumentForTest(DeviceType.VPRO, DeviceSubType.VentisPro4); List <InstalledComponent> installedComponents = Helper.GetSensorsForTest(new List <string>() { GasCode.CO, GasCode.H2S, GasCode.O2, GasCode.CombustibleLEL }); foreach (InstalledComponent installComp in installedComponents) { Sensor sensor = installComp.Component as Sensor; sensor.CalibrationStatus = Status.Failed; } instrument.InstalledComponents.AddRange(installedComponents); ScheduledNow scheduledNow = new ScheduledNow(0, 0, string.Empty, new EventCode(EventCode.BumpTest, 1, EquipmentTypeCode.Instrument, typeof(InstrumentBumpTestAction)), EquipmentTypeCode.VDS, null, false); scheduledNow.SerialNumbers.Add(instrument.SerialNumber); Initialize(); CreateMasterForTest(); // act dsEvent = new InstrumentBumpTestEvent(); scheduler.StackForcedSchedule(scheduledNow); nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is CalibrationFailureAction); }
public void GetScheduledInstrumentAlarmEventDownloadAction() { // arrange instrument = Helper.GetInstrumentForTest(DeviceType.VPRO, DeviceSubType.VentisPro4); dockingStation = Helper.GetDockingStationForTest(DeviceType.MX4); InstrumentAlarmEventsDownloadOperation operation = new InstrumentAlarmEventsDownloadOperation(); List <EventJournal> eventJournals = new List <EventJournal>(); eventJournals.Add(new EventJournal(EventCode.GetCachedCode(EventCode.InstrumentDiagnostics), instrument.SerialNumber, DateTime.Now.AddMonths(-1), DateTime.Now.AddMonths(-1), true, instrument.SoftwareVersion)); eventJournals.Add(new EventJournal(EventCode.GetCachedCode(EventCode.DownloadAlarmEvents), instrument.SerialNumber, DateTime.Now.AddMonths(-1), DateTime.Now.AddMonths(-1), true, instrument.SoftwareVersion)); _eventJournalDataAccess.Setup(x => x.FindBySerialNumbers(It.IsAny <string[]>(), It.IsAny <IDataAccessTransaction>())).Returns(eventJournals); _eventJournalDataAccess.Setup(x => x.FindLastEventByInstrumentSerialNumber(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <IDataAccessTransaction>())).Returns(eventJournals); _scheduleDailyAccess.Setup(x => x.FindGlobalSchedules(It.IsAny <IDataAccessTransaction>())).Returns(new List <Schedule>() { new ScheduledDaily(DomainModelConstant.NullId, DomainModelConstant.NullId, string.Empty, EventCode.GetCachedCode(EventCode.DownloadAlarmEvents), EquipmentTypeCode.Instrument, string.Empty, true, true, 1, DateTime.Now.AddYears(-1), new TimeSpan(9, 0, 0)) }); Initialize(); // act schema.Setup(x => x.Activated).Returns(true); dsEvent = new InstrumentAlarmEventsDownloadEvent(operation); CreateMasterForTest(); nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is InstrumentAlarmEventsDownloadAction); }
private DockingStationAction ExamineErrors(DockingStationEvent dsEvent, InetUploader inet) { DockingStationErrorLevel highestError = DockingStationErrorLevel.None; DockingStationAction dsAction = null; foreach (DockingStationError error in dsEvent.Errors) { highestError = (DockingStationErrorLevel)Math.Max((int)error.ErrorLevel, (int)highestError); } if (dsAction != null) { return(dsAction); } if (highestError >= DockingStationErrorLevel.Error) { dsAction = new UnavailableAction(); Log.Debug(string.Format("{0}Returning {1}", Name, dsAction.Name)); return(dsAction); } return(null); }
public void GetSettingsReadActionAsFollowUpActionForCylinderPressureReset() { // arrange CylinderPressureResetOperation operation = new CylinderPressureResetOperation(); dsEvent = new CylinderPressureResetEvent(operation); Initialize(); CreateMasterForTest(); // act nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is SettingsReadAction); }
public void GetSettingsReadActionAsFollowUpActionForSettingsUpdate() { // arrange SettingsUpdateOperation operation = new SettingsUpdateOperation(); dsEvent = new SettingsUpdateEvent(operation); Initialize(); CreateMasterForTest(); // act nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is SettingsReadAction); }
/// <summary> /// Returns a RebootAction if the passed in event is IRebootableEvent /// and its RebootRequired is true. /// </summary> /// <param name="dsEvent"></param> /// <returns></returns> private DockingStationAction CheckRebootableEvent(DockingStationEvent dsEvent) { if (!(dsEvent is IRebootableEvent)) { return(null); } if (((IRebootableEvent)dsEvent).RebootRequired) { Log.Info(string.Format("\"{0}\" requires a reboot!", dsEvent)); return(new RebootAction()); } Log.Info(string.Format("\"{0}\" does not require a reboot.", dsEvent)); return(null); }
public void GetForcedSettingsReadForDockingStation() { // arrange instrument = Helper.GetInstrumentForTest(DeviceType.VPRO, DeviceSubType.VentisPro4); ScheduledNow scheduledNow = new ScheduledNow(0, 0, string.Empty, new EventCode(EventCode.SettingsRead, 1, EquipmentTypeCode.VDS, typeof(SettingsReadAction)), EquipmentTypeCode.VDS, null, false); Initialize(); CreateMasterForTest(); // act dsEvent = new NothingEvent(); scheduler.StackForcedSchedule(scheduledNow); nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is SettingsReadAction); }
public void ForceCylinderResetEvent() { // arrange dockingStation = Helper.GetDockingStationForTest(DeviceType.SC); instrument = Helper.GetInstrumentForTest(DeviceType.SC); Initialize(); // act dsEvent = new NothingEvent(); CreateMasterForTest(); scheduler.ForceEvent(EventCode.CylinderPressureReset, true); nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is CylinderPressureResetAction); Xunit.Assert.True(nextAction.Trigger == TriggerType.Forced); }
public void ExecuteFollowUpAction() { // arrange SettingsUpdateOperation operation = new SettingsUpdateOperation(); dsEvent = new SettingsUpdateEvent(operation); Initialize(); dsEvent.Trigger = TriggerType.Scheduled; CreateMasterForTest(); // act nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is CylinderPressureResetAction); }
public void InitialReadingNeeded() { // arrange SettingsUpdateOperation operation = new SettingsUpdateOperation(); dsEvent = new SettingsUpdateEvent(operation); Initialize(); switchService.Setup(x => x.InitialReadSettingsNeeded).Returns(true); CreateMasterForTest(); // act nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is NothingAction); }
public void DSXNotSynchronized() { // arrange SettingsReadOperation operation = new SettingsReadOperation(); dsEvent = new SettingsReadEvent(operation); Mock <Schema> schema = new Mock <Schema>(); schema.Setup(x => x.Synchronized).Returns(false); Configuration.Schema = schema.Object; // act nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is NothingAction); }
public void GetScheduledInstrumentDiagnosticsAction() { // arrange instrument = Helper.GetInstrumentForTest(DeviceType.VPRO, DeviceSubType.VentisPro4); dockingStation = Helper.GetDockingStationForTest(DeviceType.MX4); InstrumentSettingsUpdateOperation operation = new InstrumentSettingsUpdateOperation(); Initialize(); // act schema.Setup(x => x.Activated).Returns(true); dsEvent = new InstrumentSettingsUpdateEvent(operation); CreateMasterForTest(); nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is InstrumentDiagnosticAction); }
public void GetDockingStationFirmwareUpgradeAction() { // arrange instrument = Helper.GetInstrumentForTest(DeviceType.MX6); List <InstalledComponent> installedComponents = Helper.GetSensorsForTest(new List <string>() { GasCode.CO, GasCode.H2S, GasCode.O2 }); instrument.InstalledComponents.AddRange(installedComponents); dockingStation = Helper.GetDockingStationForTest(DeviceType.MX6); dockingStation.SoftwareVersion = "7.6.0.1"; List <EventJournal> eventJournals = new List <EventJournal>(); eventJournals.Add(new EventJournal(EventCode.GetCachedCode(EventCode.InstrumentDiagnostics), instrument.SerialNumber, DateTime.Now.AddMonths(-1), DateTime.Now.AddMonths(-1), true, instrument.SoftwareVersion)); installedComponents.ForEach(installComp => eventJournals.Add(new EventJournal(EventCode.Calibration, installComp.Component.Uid, instrument.SerialNumber, DateTime.Now.AddMonths(-1), DateTime.Now.AddMonths(-1), true, installComp.Position, instrument.SoftwareVersion))); installedComponents.ForEach(installComp => eventJournals.Add(new EventJournal(EventCode.BumpTest, installComp.Component.Uid, instrument.SerialNumber, DateTime.Now.AddMonths(-1), DateTime.Now.AddMonths(-1), true, installComp.Position, instrument.SoftwareVersion))); List <Schedule> schedules = new List <Schedule>(); Schedule firmwareUpgrade = new ScheduledOnce(DomainModelConstant.NullId, DomainModelConstant.NullId, string.Empty, EventCode.GetCachedCode(EventCode.FirmwareUpgrade), dockingStation.Type.ToString(), null, true, DateTime.Now.AddYears(-1), new TimeSpan(9, 0, 0)); firmwareUpgrade.ScheduleProperties.Add(new ScheduleProperty(DomainModelConstant.NullId, ScheduleProperty.FirmwareUpgradeVersion, 0, "7.6.2.1")); schedules.Add(firmwareUpgrade); _scheduleUponDockingAccess.Setup(x => x.FindGlobalTypeSpecificSchedules(It.IsAny <string[]>(), It.IsAny <IDataAccessTransaction>())).Returns(schedules); _eventJournalDataAccess.Setup(x => x.FindBySerialNumbers(It.IsAny <string[]>(), It.IsAny <IDataAccessTransaction>())).Returns(eventJournals); _eventJournalDataAccess.Setup(x => x.FindLastEventByInstrumentSerialNumber(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <IDataAccessTransaction>())).Returns(eventJournals); _queueDataAccess.Setup(x => x.GetCount()).Returns(0); Initialize(); // act schema.Setup(x => x.Activated).Returns(true); schema.Setup(x => x.AccountNum).Returns("12345"); schema.Setup(x => x.ServiceCode).Returns("REPAIR"); controllerWrapper.Setup(x => x.FirmwareVersion).Returns("7.6.0.1"); CreateMasterForTest(); dsEvent = new NothingEvent(); nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is FirmwareUpgradeAction); }
public void InstrumentInSystemAlarm() { // arrange SettingsReadOperation operation = new SettingsReadOperation(); dsEvent = new SettingsReadEvent(operation); instrument = Helper.GetInstrumentForTest(DeviceType.VPRO, DeviceSubType.VentisPro4); dockingStation = Helper.GetDockingStationForTest(DeviceType.MX4); Initialize(); Configuration.DockingStation = dockingStation; switchService.Setup(x => x.IsInstrumentInSystemAlarm).Returns(true); CreateMasterForTest(); // act and assert Xunit.Assert.Throws <InstrumentSystemAlarmException>(() => scheduler.GetNextAction(dsEvent)); }
public void GetBadPumpTubingDetectedActionForCalibration() { // arrange InstrumentManualOperationsDownloadAction action = new InstrumentManualOperationsDownloadAction(); InstrumentManualOperationsDownloadOperation operation = new InstrumentManualOperationsDownloadOperation(action); dsEvent = new InstrumentManualOperationsDownloadEvent(operation); instrument = Helper.GetInstrumentForTest(DeviceType.VPRO, DeviceSubType.VentisPro4); Initialize(); switchService.Setup(x => x.BadPumpTubingDetectedDuringCal).Returns(true); CreateMasterForTest(); // act nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is BadPumpTubingDetectedAction); }
/// <summary> /// Logs the event's formatted Details string. /// </summary> /// <param name="dsEvent"></param> private void LogEventDetails(DockingStationEvent dsEvent) { // Keep the cached instrument info up to date. //if ( dsEvent is InstrumentSettingsReadEvent ) // SwitchService.DockedInstrument = (Instrument)( (InstrumentSettingsReadEvent)dsEvent ).DockedInstrument.Clone(); // Parse out details so we can send to debug port below string[] details = dsEvent.Details.Split(new char[] { '\n' }); Log.Debug(string.Format("{0}.Report uploading Event \"{1}\")", Name, dsEvent)); foreach (DockingStationError err in dsEvent.Errors) { Log.Debug(string.Format("{0}.Report attaching queued Error to event: \"{1}\"", Name, err.Description)); } foreach (string detail in details) { Log.Debug(detail); } }
public void GetNextForcedAction() { // arrange SettingsReadOperation operation = new SettingsReadOperation(); dsEvent = new SettingsReadEvent(operation); instrument = Helper.GetInstrumentForTest(DeviceType.VPRO, DeviceSubType.VentisPro4); Initialize(); // ScheduledNow nowSched = new ScheduledNow(DomainModelConstant.NullId, DomainModelConstant.NullId, string.Empty, EventCode.GetCachedCode(EventCode.Calibration), null, null, true); CreateMasterForTest(); // act scheduler.ForceEvent(EventCode.Calibration, false); nextAction = scheduler.GetNextAction(dsEvent); // assert Xunit.Assert.True(nextAction is InstrumentCalibrationAction); }
private void ExchangeInetStatus(DockingStationEvent dsEvent) { if (Configuration.DockingStation.SerialNumber == string.Empty) // not serialized for some reason? { return; } // SGF 18-Feb-2013 INS-3824 // In order to improve performance when processing a number of operations on instruments, // we will now limit the exchange status downloads so that they are performed as part of the // heart beats. This will prevent the repeated downloads that occur when several operations // are performed in sequence after an instrument has been docked. if (!(dsEvent is InstrumentNothingEvent || dsEvent is NothingEvent)) { Log.Debug(string.Format("\"{0}\" does not require an exchange status download.", dsEvent)); return; } else { Log.Debug(string.Format("Exchange status download will be performed for \"{0}\".", dsEvent)); } // Need to tell iNet what the current state of the docking station. string dsStatus = Master.Instance.ConsoleService.CurrentState.ToString(); ExchangeStatusEvent exchangeStatusEvent = new ExchangeStatusOperation(dsStatus, true).Execute() as ExchangeStatusEvent; // If the exchangeStatus operation encountered any errors with the data returned by iNet, // then make sure we inform iNet of those errors. foreach (DockingStationError error in exchangeStatusEvent.Errors) { ReportError(error); } return; }
/// <summary> /// Get instrument settings off of the docked instrument. /// </summary> private ISC.iNet.DS.DomainModel.Instrument ReadDockedInstrument() { DockingStationEvent dsEvent = null; try { dsEvent = new DiscoveryOperation().Execute(); } catch ( HardwareConfigurationException ) { // For docking station with cradle lids, we may get this exception when the docking station hardware is // not configured properly. Request the user to reconfigure the cradle, then we try to discover again. if ( IsDiffusionLidProperlyPositioned() ) dsEvent = new DiscoveryOperation().Execute(); } catch ( Exception e ) { Log.Error( e.ToString() ); dsEvent = null; } // InstrumentNothingEvent won't be returned by DiscoveryOperation if nothing is docked return ( dsEvent is InstrumentNothingEvent ) ? ( (InstrumentNothingEvent)dsEvent ).DockedInstrument : null; }
private bool SaveEventJournals(DockingStationEvent dsEvent, DateTime lastDockedTime, DataAccessTransaction trx) { if (dsEvent.EventCode == null) { return(true); } EventJournalDataAccess ejDataAccess = new EventJournalDataAccess(); EventJournal eventJournal = null; // If the event implements IPassed, then use the result of its // Passed property. Otherwise, just default to true. bool passed = ((dsEvent is IPassed)) ? ((IPassed)dsEvent).Passed : true; if (dsEvent is InstrumentEvent) { // special case for // bump & cals... need to save a separate // event journal for every sensor involved in gas operation. // Note that in this situation, we also do NOT save an entry for the instrument itself. if (dsEvent is InstrumentGasResponseEvent && !(dsEvent is InstrumentManualOperationsDownloadEvent)) { InstrumentGasResponseEvent gasResponseTestEvent = (InstrumentGasResponseEvent)dsEvent; if (gasResponseTestEvent.GasResponses.Count <= 0) { return(true); } bool allSaved = true; foreach (SensorGasResponse sgr in gasResponseTestEvent.GasResponses) { eventJournal = new EventJournal(gasResponseTestEvent.EventCode.Code, sgr.Uid, gasResponseTestEvent.DockedInstrument.SerialNumber, sgr.Time, dsEvent.Time, sgr.Passed, sgr.Position, gasResponseTestEvent.DockedInstrument.SoftwareVersion); allSaved &= ejDataAccess.Save(eventJournal, trx); } // If gasResponseEvent is a InstrumentBumpTestEvent, it might have calibration gas responses due to O2 high bump test failure. // If there are any gas responses in HighBumpFailCalGasResponses, store them to the event journals. foreach (SensorGasResponse sgr in gasResponseTestEvent.HighBumpFailCalGasResponses) { eventJournal = new EventJournal(EventCode.Calibration, sgr.Uid, gasResponseTestEvent.DockedInstrument.SerialNumber, sgr.Time, dsEvent.Time, sgr.Passed, sgr.Position, gasResponseTestEvent.DockedInstrument.SoftwareVersion); allSaved &= ejDataAccess.Save(eventJournal, trx); } return(allSaved); } else { eventJournal = new EventJournal(dsEvent.EventCode, ((InstrumentEvent)dsEvent).DockedInstrument.SerialNumber, dsEvent.Time, dsEvent.Time, passed, ((InstrumentEvent)dsEvent).DockedInstrument.SoftwareVersion); } } else // DockingStationEvent { eventJournal = new EventJournal(dsEvent.EventCode, dsEvent.DockingStation.SerialNumber, dsEvent.Time, dsEvent.Time, passed, dsEvent.DockingStation.SoftwareVersion); } return(ejDataAccess.Save(eventJournal, trx)); // Update/insert EventJournal record for the event. }
/// <summary> /// Determines if some specific action needs to be performed based /// on the event passed to it. (Some events require a specific /// followup action to be executed.) /// </summary> /// <param name="dsEvent"></param> /// <returns></returns> internal DockingStationAction GetFollowupAction(DockingStationEvent dsEvent) { // A SettingsUpdate is ALWAYS followed by a SettingsRead. if (dsEvent is SettingsUpdateEvent) { // If the SettingsUpdate was Scheduled, we want to inject a CylinderPressureReset before the SettingsRead. if (dsEvent.Trigger == TriggerType.Scheduled) { Log.Trace("EventProcessor returning CylinderPressureReset as followup to SettingsUpdate"); CylinderPressureResetAction cylPressureResetAction = new CylinderPressureResetAction(); // These values will be propogated to a followup SettingsRead. cylPressureResetAction.PostUpdate = true; cylPressureResetAction.SettingsRefId = ((SettingsUpdateEvent)dsEvent).DockingStation.RefId; return(cylPressureResetAction); } Log.Trace("EventProcessor returning SettingsRead as followup to SettingsUpdate"); SettingsReadAction settingsReadAction = new SettingsReadAction(); // Set the refId to indicate that this Read is occurring due to an Update that was just performed. settingsReadAction.PostUpdate = true; settingsReadAction.SettingsRefId = ((SettingsUpdateEvent)dsEvent).DockingStation.RefId; // Explicitly set the ChangedSmartCards to all falses so that no smart cards are read. settingsReadAction.ChangedSmartCards = new bool[Configuration.DockingStation.NumGasPorts]; return(settingsReadAction); } if (dsEvent is CylinderPressureResetEvent) { Log.Trace("EventProcessor returning SettingsRead as followup to CylinderPressureReset"); SettingsReadAction settingsReadAction = new SettingsReadAction(); // Copy the PostUpdate and SettingsRefId so it can be determined if the SettingsRead is // being run due to a SettingsUpdate that would have occurred before the CylinderPressureReset. settingsReadAction.PostUpdate = ((CylinderPressureResetEvent)dsEvent).PostUpdate; settingsReadAction.SettingsRefId = ((CylinderPressureResetEvent)dsEvent).SettingsRefId; // Explicitly set the ChangedSmartCards to null so all positions are read similar to startup. settingsReadAction.ChangedSmartCards = null; return(settingsReadAction); } // After downloading datalog, we clear it. if (dsEvent is InstrumentDatalogDownloadEvent) { InstrumentDatalogDownloadEvent datalogEvent = (InstrumentDatalogDownloadEvent)dsEvent; // D2G: Only clear the log if there is something to clear, or corruption was detected. if (datalogEvent.InstrumentSessions.Count > 0 || datalogEvent.Errors.Count > 0) { Log.Trace("EventProcessor returning InstrumentHygieneClearAction as followup to InstrumentHygieneDownloadEvent"); return(new InstrumentDatalogClearAction()); } else { Log.Debug("NO DATALOG TO CLEAR"); return(null); } } // After downloading alarm events, we clear them. if (dsEvent is InstrumentAlarmEventsDownloadEvent) { InstrumentAlarmEventsDownloadEvent alarmsEvent = (InstrumentAlarmEventsDownloadEvent)dsEvent; // D2G: Only clear the log if there is something to clear, or corruption was detected. if (alarmsEvent.AlarmEvents.Length > 0 || alarmsEvent.Errors.Count > 0) { Log.Trace("EventProcessor returning InstrumentAlarmEventsClearAction as followup to InstrumentAlarmEventsDownloadEvent"); return(new InstrumentAlarmEventsClearAction()); } else { Log.Debug("NO ALARM EVENTS TO CLEAR"); return(null); } } // After downloading alarm events, we clear them. if (dsEvent is InstrumentManualOperationsDownloadEvent) { InstrumentManualOperationsDownloadEvent manualOpsEvent = (InstrumentManualOperationsDownloadEvent)dsEvent; // D2G: Only clear the log if there is something to clear, or corruption was detected. if (manualOpsEvent.GasResponses.Count > 0 || manualOpsEvent.Errors.Count > 0) { Log.Trace("EventProcessor returning InstrumentManualOperationsDownloadAction as followup to InstrumentManualOperationsDownloadEvent"); return(new InstrumentManualOperationsClearAction()); } else { Log.Debug("NO MANUAL GAS OPERATIONS TO CLEAR"); return(null); } } if (dsEvent is InstrumentFirmwareUpgradeEvent) { if (((InstrumentFirmwareUpgradeEvent)dsEvent).UpgradeFailure) { Log.Trace("EventProcessor returning NothingAction as followup to InstrumentFirmwareUpgradeEvent due to an upgrade failure"); // Setting this to true will cause the docking station to go // into its UpgradingInstrumentError state. Master.Instance.SwitchService.InstrumentUpgradeError = true; // Return an action just to prevent further processing (there's no use // next letting the scheduler figure out what needs to be done next since // we know we're about to into the UpgradingInstrumentError state.) return(new NothingAction()); } } //Suresh 06-FEB-2012 INS-2622 //Check whether instrument is in critical error. if (dsEvent is InstrumentDiagnosticEvent) { InstrumentDiagnosticEvent diagnosticEvent = (InstrumentDiagnosticEvent)dsEvent; if (diagnosticEvent.InstrumentInCriticalError == true) { Log.Trace("EventProcessor returning NothingAction as followup to InstrumentDiagnosticEvent due to instrument having a critical error"); Master.Instance.SwitchService.Instrument.InstrumentInCriticalError = true; // INS-8446 RHP v7.6 - Set the SwitchService's InstrumentCriticalErrorCode to display the critical error code on LCD Log.Trace("EventProcessor identfied InstrumentDiagnosticEvent having a critical error code of " + diagnosticEvent.InstrumentCriticalErrorCode); Master.Instance.SwitchService.Instrument.InstrumentCriticalErrorCode = diagnosticEvent.InstrumentCriticalErrorCode; return(new NothingAction()); } } return(null); }
/// <summary> /// Reports a docking station event to the server. /// </summary> /// <param name="dockingStationEvent"> /// The event to be reported /// </param> /// <returns> /// A docking station action indicating the next task /// the docking station should perform. /// </returns> public DockingStationAction ReportEvent(DockingStationEvent dsEvent) { if (dsEvent == null) { return(null); } if (dsEvent.DockingStation.SerialNumber == string.Empty) { return(null); } LogEventDetails(dsEvent); DockingStationAction dsAction = null; // We don't yet instantiate the Uploader instance. We wait until we know for sure // we're going to use it. Note that it's Disposed of in the finally block below. InetUploader inetUploader = null; try { try { // It's now finally safe to log the event. _eventProcessor.Save(dsEvent, Master.Instance.SwitchService.DockedTime); // These upload calls won't actually try and upload if we're not associated with any account. // or even if we DO have an account number, it won't upload if we're not activated on iNet. // Yet it WILL upload if we're in Service mode, regardless if activated or not. // Confusing, eh? inetUploader = new InetUploader(); inetUploader.UploadEvent(dsEvent, Configuration.DockingStation.TimeZoneInfo); if (dsEvent is InstrumentGasResponseEvent) { // Print automated bumps and cals new PrintManager().Print((InstrumentGasResponseEvent)dsEvent); } // Only save event to USB drive when in Cal Station mode and not Service mode if (!Configuration.Schema.Activated && !Configuration.ServiceMode) { if (dsEvent is InstrumentDatalogDownloadEvent) { // if the full datalog can not be saved to the USB drive an exception will // be thrown to make the docking station go unavailable; this is to prevent // the DS from erasing the datalog when it wasn't able to save it new CsvFileManager().Save((InstrumentDatalogDownloadEvent)dsEvent); } else if (dsEvent is InstrumentGasResponseEvent) { // only bumps and cals are saved new CsvFileManager().Save((InstrumentGasResponseEvent)dsEvent); } } ReportQueuedErrors(inetUploader); // See if docking station needs to take any special action for any of the event's errors. dsAction = ExamineErrors(dsEvent, inetUploader); if (dsAction != null) { Log.Debug(string.Format("{0}: ExamineErrors returned {1}", Name, dsAction.Name)); return(dsAction); } } catch (Exception e) { Log.Error(Name, e); dsAction = new UnavailableAction(e); // DO NOT report the error. If we have an error uploading, then it makes // no sense to try and upload and error notifying of a problem trying to upload. //ProcessNotificationAction( dsAction, inet ); return(dsAction); } try { // Determine if the event that just transpired requires a followed up RebootAction. dsAction = CheckRebootableEvent(dsEvent); if (dsAction == null) { // Before determining our next action, make sure we have the most up-to-date // schedules and eventjournals, etc., from iNet. ExchangeInetStatus(dsEvent); // Find out what we're supposed to do next. dsAction = Master.Scheduler.GetNextAction(dsEvent); if (dsAction is InstrumentAction) { InstrumentAction instAction = (InstrumentAction)dsAction; if (instAction is InstrumentGasAction) { // Get the resources from the resource manager. StringBuilder explanation = new StringBuilder(); List <string> consoleMessages = new List <string>(); // SGF 20-Feb-2013 INS-3821 List <string> errorCodes = new List <string>(); // SGF 20-Feb-2013 INS-3821 InstrumentGasAction gasAction = instAction as InstrumentGasAction; string eventCode = null; if (gasAction is InstrumentBumpTestAction) { eventCode = EventCode.BumpTest; } else if (gasAction is InstrumentCalibrationAction) { eventCode = EventCode.Calibration; } else { throw new ArgumentOutOfRangeException("Unrecognized GasAction: " + gasAction.GetType().ToString()); } // SGF 20-Feb-2013 INS-3821 // SGF 03-Nov-2010 Single Sensor Cal and Bump gasAction.GasEndPoints = Master.Instance.ResourceService.GetGasEndPoints(eventCode, gasAction, explanation, consoleMessages, errorCodes); if (gasAction.GasEndPoints.Count == 0) { Log.Warning(string.Format("No gases for {0}. {1}", eventCode, explanation.ToString())); // Maintain the empty cylinder error state resulting from forced actions by re-forcing the action Master.Instance.Scheduler.ReForceEvent(instAction); dsAction = new ResourceUnavailableAction(errorCodes, consoleMessages); // SGF 20-Feb-2013 INS-3821 } } // For instrument firmware upgrades, we don't want to allow the upgrade to take place // if there's no gas to both calibrate and bump the instrument. This is because at the // end of the upgrade, the VDS will automatically calibrate then bump test the instrument. if (instAction is InstrumentFirmwareUpgradeAction) { StringBuilder explanation = new StringBuilder(); List <string> consoleMessages = new List <string>(); // SGF 20-Feb-2013 INS-3821 List <string> errorCodes = new List <string>(); // SGF 20-Feb-2013 INS-3821 // SGF 20-Feb-2013 INS-3821 // SGF 03-Nov-2010 Single Sensor Cal and Bump if (Master.Instance.ResourceService.GetGasEndPoints(EventCode.Calibration, instAction, explanation, consoleMessages, errorCodes).Count == 0) { Log.Warning(string.Format("No gases for firmware upgrade {0}. {1}", EventCode.Calibration, explanation.ToString())); dsAction = new ResourceUnavailableAction(errorCodes, consoleMessages); // SGF 20-Feb-2013 INS-3821 } else { explanation = new StringBuilder(); consoleMessages.Clear(); // SGF 20-Feb-2013 INS-3821 errorCodes.Clear(); // SGF 20-Feb-2013 INS-3821 // SGF 20-Feb-2013 INS-3821 // SGF 03-Nov-2010 Single Sensor Cal and Bump if (Master.Instance.ResourceService.GetGasEndPoints(EventCode.BumpTest, instAction, explanation, consoleMessages, errorCodes).Count == 0) { Log.Warning(string.Format("No gases for firmware upgrade {0}. {1}", EventCode.BumpTest, explanation.ToString())); dsAction = new ResourceUnavailableAction(errorCodes, consoleMessages); // SGF 20-Feb-2013 INS-3821 } } } } } } // INS-8228 RHP v7.6 Log and report InstrumentSystemAlarmException thrown from Scheduler catch (InstrumentSystemAlarmException e) { Log.Error(Name, e); Master.ConsoleService.UpdateState(ConsoleState.InstrumentSystemAlarm); Master.ExecuterService.ReportExceptionError(e); } catch (Exception e) { Log.Error(Name, e); dsAction = new UnavailableAction(e); } // If the scheduler says there's currently nothing to do, then check // if we have an illegal cylinder or not. Report an unsupported cylinder if so. if (dsAction is NothingAction) { DockingStationAction cylinderAction = ExamineGasEndPoints(); if (cylinderAction != null) { dsAction = cylinderAction; } } // If the action we're about to return is telling the VDS to display an error message, // then we should tell iNet the error too. We pass in our Uploader instance to re-use the // socket which should give a couple seconds performance benefit. ProcessNotificationAction(dsAction, inetUploader); } finally { if (inetUploader != null) { inetUploader.Dispose(); } } return(dsAction); }
/// <summary> /// This method implements the thread start for this service. /// </summary> protected override void Run() { try { bool activated = Configuration.Schema.Activated; bool synchronized = Configuration.Schema.Synchronized; //Suresh 13-APR-2012 INS-4519 (DEV JIRA) //If the docking station is Initialized and Activated, but not Synchronized then set the console state to Synchronization. //Note: We cannot do this after Discover() method, because ExecuterService.Discover() method and //ExecuterService.Run( ExchangeStatusOperation ) method runs on mutual-exclusion lock and that causes "Synchronization" state not to be changed //until ExchangeStatusOperation completely finishes but by that time Synchronization will be completed. if ((_initialized == true) && (activated == true || Configuration.ServiceMode) && (synchronized == false)) { bool online = Inet.IsOnline; Log.Trace("Schema is not synced with iNet. Connected=" + online); // We don't bother getting the current state (which does a 'lock') until we know AllSynced is false. ConsoleState state = Master.ConsoleService.CurrentState; if (state == ConsoleState.Ready || state == ConsoleState.Discovering || state == ConsoleState.Synchronization || state == ConsoleState.SynchronizationError) { Master.ConsoleService.UpdateState(online ? ConsoleState.Synchronization : ConsoleState.SynchronizationError); } } // Anytime an account number or activation changes, we need to do a re-discover and force another settings. // This is due to database being reset due to the account change, and the new database will no longer // have info regarding currenly attached cylinders. string curAccountNum = Configuration.Schema.AccountNum; if ((_wasAccountNum != curAccountNum) || (_wasActivated != activated)) { if (_wasAccountNum != curAccountNum) { Log.Info(string.Format("{0} detected changed Account. Old=\"{1}\", New=\"{2}\"", Name, _wasAccountNum, curAccountNum)); } if (_wasActivated != activated) { Log.Info(string.Format("{0} detected changed Activation. Old=\"{1}\", New=\"{2}\"", Name, _wasActivated, activated)); } _wasAccountNum = curAccountNum; _wasActivated = activated; Log.Debug(string.Format("{0} initiating Discovery (account/activation changed).", Name)); Master.ExecuterService.Discover(); _initialized = true; InitialReadSettingsNeeded = ReadSettingsNeeded = ReadAllCards = true; // need to do a full readsettings return; // Simply return. Yes, we need to perform a ReadSettings, but it'll happen the next time Run is called. } // Special handling for docking stations in manufacturing accounts... if (Configuration.Schema.IsManufacturing) { // If activated (not a Cal Station), and not online, then // display error message saying that it needs to be online. if (Configuration.Schema.Activated && !Inet.IsOnline) { Master.ConsoleService.UpdateState(ConsoleState.MfgNotConnected); return; } ConsoleState state = Master.ConsoleService.CurrentState; if (state == ConsoleState.MfgNotConnected) { Master.ConsoleService.UpdateState(ConsoleState.MfgConnected); } else if (state == ConsoleState.MfgConnected) { Master.ConsoleService.UpdateState(ConsoleState.Ready); } } // Until we find out that we've successfully connected to iNet // in order to obtain an account number, factory cylinder info, etc., // don't do anything more than a one-time Discover. The initial Discover // is also needed in order to jump start the ExecuterService's thread into // doing something. (It won't do anything on bootup as it's 'next action' is null.) if (!synchronized) { if (!_initialized) { Log.Debug(string.Format("{0} initiating initial Discovery (unsynchronized).", Name)); DockingStationEvent dsEvent = Master.ExecuterService.Discover(); Controller.LogDockingStation(dsEvent.DockingStation); _initialized = true; InitialReadSettingsNeeded = ReadSettingsNeeded = ReadAllCards = true; // need to do a full readsettings } return; // Simply return. Yes, we might need to perform a ReadSettings but, if needed, it'll happen the next time Run is called. } // Force a Discovery if we're just booting up. if (!_initialized) { Log.Debug(string.Format("{0} initiating initial Discovery.", Name)); DockingStationEvent dsEvent = Master.ExecuterService.Discover(); Controller.LogDockingStation(dsEvent.DockingStation); _initialized = true; return; } // Check if instrument has been docked or undocked and force a Discovery if something has been docked or undocked. if (!Master.Instance.SwitchService.InitialReadSettingsNeeded && CheckDockedStatus()) { Log.Debug(string.Format("{0} initiating Discovery.", Name)); Master.ExecuterService.Discover(); _initialized = true; return; } // Check card readers for card insertions / removals, and for pressure // switch changes. If any card or pressure switch changes detected, // then we need to force a Settings Read. ReadSettingsNeeded = CheckIgasPorts() || ReadSettingsNeeded; // When we first start up, we always want to perform a settings read operation, // and send the information to the server. if (ReadSettingsNeeded) { ReadSettings(ReadAllCards); ReadSettingsNeeded = ReadAllCards = false; } _lastCaughtException = null; // no error encountered on this iteration of Run(), so clear the last caught error. } catch (InstrumentSystemAlarmException systemalarmmex) // SGF Nov-23-2009 DSW-355 (DS2 v7.6) { Master.ConsoleService.UpdateState(ConsoleState.InstrumentSystemAlarm); //Suresh 06-FEB-2012 INS-2622 Master.ExecuterService.ReportExceptionError(systemalarmmex); //Suresh 15-SEPTEMBER-2011 INS-1593 } catch (HardwareConfigurationException hce) { // Set docked flag to false. Otherwise, if user just reconfigures the hardware on the // docking station without redocking the instrument, the IDS will think that it's already // docked and won't want to do a discover. _wasDocked = false; Master.ConsoleService.UpdateState(ConsoleService.MapHardwareConfigError(hce)); } catch (Exception e) { Log.Error(Name, e); // If the menu is currently active, then we don't want to interrupt what the user is doing for an error // that will likely be hit again in a few seconds and can be displayed when the menu is not active. // Viewing the Cylinders menu screen could be helpful for troubleshooting smart card issues. // The first DeviceDriverException should be uploaded to iNet. if (e is DeviceDriverException && Master.Instance.ConsoleService.CurrentState != ConsoleState.Menu) { // DeviceDriverExceptions that the SwitchService can encounter will be from checking smart card presence, // pressure switch presence, or pressure switch state. if (((DeviceDriverException)e).DeviceHardware == DeviceHardware.SmartCardPresence) { Master.Instance.ConsoleService.UpdateState(ConsoleState.IGasError, ConsoleServiceResources.IGASERROR_SMARTCARDS); } else { Master.Instance.ConsoleService.UpdateState(ConsoleState.IGasError, ConsoleServiceResources.IGASERROR_PRESSURESWITCHES); } // Give the ConsoleService time to display the error state. Thread.Sleep(3000); } // don't upload CommunicationAbortedException or InstrumentNotDockedException to iNet if (e is CommunicationAbortedException || e is InstrumentNotDockedException) { Master.Instance.ConsoleService.UpdateState(ConsoleState.UndockedInstrument); Thread.Sleep(3000); _wasDocked = false; // A heartbeat is called to get the executer service to update the LCD screen (to go idle) // in case the instrument remains undocked. Master.ExecuterService.HeartBeat(); } // Whenever we catch an exception, report it to iNet, but only if it's not // the same as the last error - to prevent a problem where we repeatedly get, // say, a device driver exception trying to check smart cards or pressure switches. // In that situation, we don't want to upload the error continuously to iNet. else if (_lastCaughtException == null || _lastCaughtException.GetType() != e.GetType()) { Master.ReporterService.ReportError(new DockingStationError(e, DockingStationErrorLevel.Warning)); Master.ExecuterService.HeartBeat(); // Perform one heartbeat to force the error to upload asap. _lastCaughtException = e; } } }
/// <summary> /// Saves/updates in the database whatever needs to be saved/updated based /// on the results of the passed-in event. /// Includes saving the event, updating installed cylinders, deleting ScheduledOnces. /// </summary> /// <param name="dsEvent"></param> /// <param name="lastDockedTime"></param> internal void Save(DockingStationEvent dsEvent, DateTime lastDockedTime) { // We don't want to start a transaction unless we know we're going to update // the database, since merely just beginning a writable transaction causes a write. // Not every event type will have a code. For those that don't, we don't // need the last run time saved (such as Nothing events or interactive diagnostics) if (dsEvent.EventCode == null) { return; } // Save event journals and installed cylinder updates all in a single transaction. // If this event was invoked by a run-once schedule, then that schedule is also // deleted in the same transaction. using (DataAccessTransaction trx = new DataAccessTransaction()) { // Save/update EventJournals for the event. bool saved = SaveEventJournals(dsEvent, lastDockedTime, trx); Log.Debug(string.Format("SaveEventJournals({0})={1}", dsEvent, saved)); // If this event was invoked by a run-once schedule, then delete the schedule // since, by definition, "run once" schedules are run once, then deleted. if ((dsEvent.Schedule != null) && (dsEvent.Schedule is ScheduledOnce)) { bool deleted = new ScheduledOnceDataAccess().DeleteById(dsEvent.Schedule.Id, trx); Log.Debug(string.Format("ScheduledOnceDataAccess.Delete({0})={1}", dsEvent.Schedule.Id, deleted)); } // If event is a SettingsRead, then SaveGasEndPoints will update the GasEndPoints // in the database based on what what cylinders the SettingsRead found attached to // the docking station. if (dsEvent is SettingsReadEvent) { SaveGasEndPoints((SettingsReadEvent)dsEvent, trx); // If this is a SettingsReadEvent, reload the GasEndPoints from the database // now that they've been saved and cache them in our global dockingstation. // This also has the side effect of setting ech of their 'Supported' properties // to null which will force a revalidation of their part numbers against the // known FactoryCylinder part numbers. Configuration.DockingStation.GasEndPoints = new GasEndPointDataAccess().FindAll(trx); } else if (dsEvent is InstrumentSettingsReadEvent) { // If this is a InstrumentSettingsReadEvent, then refresh the switch'service's // docked instrument information with the information from the event. // If we don't do this, then the switch service's information can become out of // date after Instrument Settings Updates are performed, or instrument firmware // is updated, etc. // // TODO: the following is probably not necessary anymore do to changes made for INS-3825. // InstrumentSettingsRead operation is now just returning a clone of SwitchService.Instrument. // So setting the SwitchService.Instrument to be a clone of what InstrumentSettingsRead // returned is pretty much just setting it to a clone of an exact copy of itself. // -- JMP, 2/13/2013. Master.Instance.SwitchService.Instrument = (DomainModel.Instrument)((InstrumentSettingsReadEvent)dsEvent).DockedInstrument.Clone(); //Suresh 05-JAN-2012 INS-2564 //During instrument setting read if we find any sensor in error state then we want to report it to iNet Master.Instance.ExecuterService.ReportDiscoveredInstrumentErrors((InstrumentEvent)dsEvent); } else if ((dsEvent is InstrumentCalibrationEvent) && (Master.Instance.SwitchService.Instrument.SerialNumber != string.Empty)) // can this happen here? { // Keep the Sensors in the cached instrument object updated with the status // of what happened during the calibration, for use by the scheduler. bool cylinderHoseProblem = false; UsedGasEndPoint gasEndPointUsedForCal = null; // INS-8446 RHP v7.6 foreach (SensorGasResponse sgr in (dsEvent as InstrumentCalibrationEvent).GasResponses) { // If any sensor failed calibration with a zero span reserve, then set the SwitchService's CylinderHoseProblem to true. // We don't do this for O2 sensors, though, as a O2 calibration failure with a zero span reserve would not indicate a // a problem with the hoses. - INS-1279, 6/20/2011, JMP // INETQA-4131 RHP v7.6 - Added Status.Failed condition check below. if (sgr.SensorCode != SensorCode.O2 && (sgr.Status == Status.SpanFailed || sgr.Status == Status.SpanFailedZeroFailed || sgr.Status == Status.Failed) && sgr.FullSpanReserve == 0.0) { cylinderHoseProblem = true; // INS-8446 RHP v7.6 - Save the Cylinder details which is expected to have hose problems. // Do a NULL to ensure that we identify the first gas response that failed a calibration with Zero Span reserve and fetch its gas end point being used. if (gasEndPointUsedForCal == null) { gasEndPointUsedForCal = sgr.UsedGasEndPoints.Find(uge => uge.Usage == CylinderUsage.Calibration && !uge.Cylinder.IsFreshAir && !uge.Cylinder.IsZeroAir); } } Sensor sensor = (Sensor)Master.Instance.SwitchService.Instrument.InstalledComponents.Find(ic => ic.Component.Uid == sgr.Uid).Component; if (sensor != null) { sensor.CalibrationStatus = sgr.Status; } } //Suresh 22-Feb-2012 INS-2705 //After calibration is completed , we need to update sensor bump test status because in scheduler we have logic //to force calibration based on sensor BumpTestStatus foreach (InstalledComponent installedComponent in (dsEvent as InstrumentCalibrationEvent).DockedInstrument.InstalledComponents) { if (!(installedComponent.Component is Sensor)) // Skip non-sensors. { continue; } if (!installedComponent.Component.Enabled) // Skip disabled sensors. { continue; } Sensor bumpTestedSensor = (Sensor)installedComponent.Component; Sensor sensor = (Sensor)Master.Instance.SwitchService.Instrument.InstalledComponents.Find(ic => ic.Component.Uid == bumpTestedSensor.Uid).Component; if (sensor != null) { sensor.BumpTestStatus = bumpTestedSensor.BumpTestStatus; } } // If at least one sensor had a status of InstrumentAborted, then we know the instrument reset. // The check cylinders message should not be shown on the LCD. foreach (SensorGasResponse sgr in (dsEvent as InstrumentCalibrationEvent).GasResponses) { if (sgr.Status == Status.InstrumentAborted) { cylinderHoseProblem = false; gasEndPointUsedForCal = null; break; } } Master.Instance.SwitchService.BadGasHookup = cylinderHoseProblem; // INS-8446 RHP v7.6 - Set the SwitchService's BadGasHookUpCylinderPartNumber which is expected to have hose problems to display the same on LCD Master.Instance.SwitchService.BadGasHookUpCylinderPartNumber = gasEndPointUsedForCal == null ? string.Empty : gasEndPointUsedForCal.Cylinder.PartNumber; Log.Debug(string.Format("EventProcessor : BadGasHookUpCylinderPartNumber identified cylinder with Part Number {0}", Master.Instance.SwitchService.BadGasHookUpCylinderPartNumber)); } //Suresh 22-Feb-2012 INS-2705 else if ((dsEvent is InstrumentBumpTestEvent) && (Master.Instance.SwitchService.Instrument.SerialNumber != string.Empty)) // can this happen here? { // Keep the Sensors in the cached instrument object updated with the status // of what happened during the bumptest, for use by the scheduler. foreach (InstalledComponent installedComponent in (dsEvent as InstrumentBumpTestEvent).DockedInstrument.InstalledComponents) { if (!(installedComponent.Component is Sensor)) // Skip non-sensors. { continue; } if (!installedComponent.Component.Enabled) // Skip disabled sensors. { continue; } Sensor bumpTestedSensor = (Sensor)installedComponent.Component; Sensor sensor = (Sensor)Master.Instance.SwitchService.Instrument.InstalledComponents.Find(ic => ic.Component.Uid == bumpTestedSensor.Uid).Component; if (sensor != null) { sensor.BumpTestStatus = bumpTestedSensor.BumpTestStatus; } } } trx.Commit(); } }