/// Zeroes all sensors contained on the instrument. /// /// NOTE: THIS ROUTINE LOOKS LIKE IT CAN ZERO A SPECIFIC SENSOR /// BUT IN ACTUALITY, IT ALWAYS ZEROS ALL SENSORS. /// </summary> /// <param name="installedComponents">Contains InstalledComponents for the instrument being zeroed.</param> private void ZeroSensors( IEnumerable<InstalledComponent> installedComponents ) { Log.Debug( "ZEROING: Preparing to zero" ); // Indicate that the zeroing process is now in progress Master.Instance.ConsoleService.UpdateState( ConsoleState.CalibratingInstrument, ConsoleServiceResources.ZEROING ); // See if we have a CO2 sensor. If so, then we can only zero using zero air. // fresh air is NOT allowed. If no CO2 sensor is installed, then fresh // air may be used as an alternative to zero air, if zero air is not found. bool useZeroAirOnly = false; foreach ( InstalledComponent installedComponent in installedComponents ) { if ( installedComponent.Component.Type.Code == SensorCode.CO2 ) { Sensor sensor = (Sensor)installedComponent.Component; if ( !sensor.Enabled ) // if it's disabled, we won't be zeroing it. continue; Log.Debug( "ZEROING: Found CO2 sensor. Will not use fresh air to zero." ); useZeroAirOnly = true; break; } } GasEndPoint zeroEndPoint = null; DateTime startTime = DateTime.UtcNow; try { _zeroingUsedGasEndPoint = null; // Reset any previous setting (if any). zeroEndPoint = GetSensorZeroAir( null, useZeroAirOnly, false ); // Get the zeroing gas end point for this gas. _instrumentController.OpenGasEndPoint( zeroEndPoint, Pump.StandardFlowRate ); // ZeroSensor will return false if IDS times out before instrument finishes zeroing. // Return value does NOT indicate if zeroing was successful or not! if ( !_instrumentController.ZeroSensors( zeroEndPoint ) ) throw new UnableToZeroInstrumentSensorsException(); // SGF 14-Jun-2011 INS-1732 -- get sensor readings after zeroing has taken place foreach ( InstalledComponent ic in _returnEvent.DockedInstrument.InstalledComponents ) { if ( !( ic.Component is Sensor ) ) // Skip non-sensors. continue; Sensor sensor = (Sensor)ic.Component; if ( !sensor.Enabled ) // Skip disabled sensors continue; SensorGasResponse sgr = _returnEvent.GetSensorGasResponseByUid( sensor.Uid ); if ( sgr != null ) { sgr.ReadingAfterZeroing = _instrumentController.GetSensorReading( ic.Position, sensor.Resolution ); sgr.TimeAfterZeroing = DateTime.UtcNow; } } } catch ( Exception e ) { Log.Error( "Zeroing Sensor", e ); throw; } finally { Log.Debug( "ZEROING: Finished" ); _instrumentController.CloseGasEndPoint( zeroEndPoint ); if ( zeroEndPoint != null ) // how could this ever be null? _zeroingUsedGasEndPoint = new UsedGasEndPoint( zeroEndPoint, CylinderUsage.Zero, DateTime.UtcNow - startTime, 0 ); } }
/// <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(); } }