// UNCLASSIFIED /*------------------------------------------------------------------------- RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON COMPANY. THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT. UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. -------------------------------------------------------------------------*/ using System; using System.Threading; using ChillerCartMeasurementManagerLib; using NLog; using Raytheon.Instruments; namespace MeasurementManagerLib { /// /// This class manages chiller instruments and provides an abstraction /// public class ChillerCartMeasurementManager : IDisposable { #region PublicMembers public delegate void ChillerDelegate(double temperature, double coolantSetpoint, int errorCode); public delegate void FlowMeterDelegate(double flow, int errorCode); public delegate void TemperatureDelegate(double temperature, int errorCode); #endregion #region PrivateMembers private readonly IChiller _chiller; private readonly IFlowMeter _flowMeter; private readonly ITempMonitor _tempMonitor; private ChillerDataLogWorker _chillerDataLogWorker; private Thread _chillerDataLogThread; private FlowMeterDataLogWorker _flowMeterDataLogWorker; private Thread _flowMeterDataLogThread; private TempDataLogWorker _tempMonDataLogWorker; private Thread _tempMonDataLogThread; private static NLog.ILogger _logger; #endregion #region PrivateFunctions /// /// Dispose of this object's resources /// /// Currently disposing protected virtual void Dispose(bool disposing) { if (disposing) { // stop the logging if it is still running try { ChillerLogStop(); } catch (Exception err) { _logger?.Error(err.Message + "\r\n" + err.StackTrace); } // stop the logging if it is still running try { FlowMeterLogStop(); } catch (Exception err) { _logger?.Error(err.Message + "\r\n" + err.StackTrace); } // stop the logging if it is still running try { TemperatureSensorLogStop(); } catch (Exception err) { _logger?.Error(err.Message + "\r\n" + err.StackTrace); } // dispose the thread try { if (_chillerDataLogWorker != null) { _chillerDataLogWorker.Dispose(); } } catch (Exception err) { _logger?.Error(err.Message + "\r\n" + err.StackTrace); } // dispose the thread try { if (_flowMeterDataLogWorker != null) { _flowMeterDataLogWorker.Dispose(); } } catch (Exception err) { _logger?.Error(err.Message + "\r\n" + err.StackTrace); } // dispose the thread try { if (_tempMonDataLogWorker != null) { _tempMonDataLogWorker.Dispose(); } } catch (Exception err) { _logger?.Error(err.Message + "\r\n" + err.StackTrace); } // dispose other resources if (_chiller != null) { try { _chiller.Shutdown(); } catch (Exception err) { _logger?.Error(err.Message + "\r\n" + err.StackTrace); } } if (_flowMeter != null) { try { _flowMeter.Shutdown(); } catch (Exception err) { _logger?.Error(err.Message + "\r\n" + err.StackTrace); } } if (_tempMonitor != null) { try { _tempMonitor.Shutdown(); } catch (Exception err) { _logger?.Error(err.Message + "\r\n" + err.StackTrace); } } } } /// /// The Finalizer /// ~ChillerCartMeasurementManager() { Dispose(false); } #endregion #region PublicFunctions /// /// constructor that uses instrument manager to create an instrument /// /// /// /// /// /// /// public ChillerCartMeasurementManager(IInstrumentManager instrumentManager, string chillerName, string flowMeeterName, string tempSensorName, string errorLog) { try { _logger = LogManager.GetCurrentClassLogger(); // these gets created in the start logging functions _chillerDataLogWorker = null; _chillerDataLogThread = null; _flowMeterDataLogWorker = null; _flowMeterDataLogThread = null; _tempMonDataLogWorker = null; _tempMonDataLogThread = null; _chiller = null; _flowMeter = null; _tempMonitor = null; if (!string.IsNullOrEmpty(chillerName)) { _chiller = instrumentManager.GetInstrument(chillerName); _chiller?.Initialize(); } if (!string.IsNullOrEmpty(flowMeeterName)) { _flowMeter = instrumentManager.GetInstrument(flowMeeterName); _flowMeter?.Initialize(); } if (!string.IsNullOrEmpty(tempSensorName)) { _tempMonitor = instrumentManager.GetInstrument(tempSensorName); _tempMonitor?.Initialize(); } } catch (Exception) { Dispose(true); throw; } } /// /// /// /// public double ChillerGetCoolantTemperature() { return _chiller.GetCoolantTemperature(); } /// /// /// /// public double ChillerGetCoolantTemperatureSetpoint() { return _chiller.GetCoolantSetpoint(); } /// /// /// public void ChillerDisableFlow() { _chiller.DisableFlow(); } /// /// /// public void ChillerEnableFlow() { _chiller.EnableFlow(); } /// /// /// /// /// /// An optional delegate for the host to receive the data public void ChillerLogStart(string filename, int threadRestTimeMs, ChillerCartMeasurementManager.ChillerDelegate callback) { if (_chillerDataLogWorker != null) { //Should not be logging. Stop Logger ChillerLogStop(); _chillerDataLogWorker.Dispose(); } //Start logging on a new thread. Also, start calling callback with requested data _chillerDataLogWorker = new ChillerDataLogWorker(this, filename, threadRestTimeMs, callback); _chillerDataLogThread = new Thread(_chillerDataLogWorker.DoWork); _chillerDataLogThread.Start(); } /// /// /// public void ChillerLogStop() { const int THREAD_QUIT_TIMEOUT = 3000; //Is the logger running if (_chillerDataLogWorker != null) { _chillerDataLogWorker.QuitWork(); if ((_chillerDataLogThread != null) && (_chillerDataLogThread.IsAlive)) { bool didThreadQuit = _chillerDataLogThread.Join(THREAD_QUIT_TIMEOUT); if (didThreadQuit == false) { _logger?.Error("Logging Thread did not quit as expected, aborting it"); _chillerDataLogThread.Abort(); } else { _logger?.Info("Logging Thread quit successfully after join"); } } else { _logger?.Info("Logging Thread quit successfully"); } } } /// /// /// /// public void ChillerSetCoolantTemperature(double setpoint) { _chiller.SetCoolantTemperature(setpoint); } /// /// /// public void Dispose() { try { Dispose(true); GC.SuppressFinalize(this); } catch (Exception err) { try { _logger?.Error(err.Message + "\r\n" + err.StackTrace); } catch (Exception) { //Do not rethrow. Exception from error logger that has already been garbage collected } } } /// /// /// /// /// /// An optional delegate for the host to receive the data public void FlowMeterLogStart(string filename, int threadRestTimeMs, ChillerCartMeasurementManager.FlowMeterDelegate callback) { if (_flowMeterDataLogWorker != null) { //Should not be logging. Stop logger FlowMeterLogStop(); _flowMeterDataLogWorker.Dispose(); } //Start logging on a new thread. Also, start calling callback with requested data _flowMeterDataLogWorker = new FlowMeterDataLogWorker(this, filename, threadRestTimeMs, callback); _flowMeterDataLogThread = new Thread(_flowMeterDataLogWorker.DoWork); _flowMeterDataLogThread.Start(); } /// /// /// public void FlowMeterLogStop() { const int THREAD_QUIT_TIMEOUT = 5000; //Are we logging if (_flowMeterDataLogWorker != null) { _flowMeterDataLogWorker.QuitWork(); if ((_flowMeterDataLogThread != null) && (_flowMeterDataLogThread.IsAlive)) { bool didThreadQuit = _flowMeterDataLogThread.Join(THREAD_QUIT_TIMEOUT); if (didThreadQuit == false) { _logger?.Error("Logging Thread did not quit as expected, aborting it"); _flowMeterDataLogThread.Abort(); } else { _logger?.Info("Logging Thread quit successfully after join"); } } else { _logger?.Info("Logging Thread quit successfully"); } } } /// /// /// /// public double FlowMeterReadFlow() { return _flowMeter.ReadFlow(); } /// /// /// /// public double TemperatureSensorReadTemperature() { return _tempMonitor.ReadTemperature(); } /// /// Start the temperature sensor log thread /// /// /// /// An optional delegate for the host to receive the data public void TemperatureSensorLogStart(string filename, int threadRestTimeMs, ChillerCartMeasurementManager.TemperatureDelegate callback) { if (_tempMonDataLogWorker != null) { //Should not be logging. Stop logger TemperatureSensorLogStop(); _tempMonDataLogWorker.Dispose(); } //Start logging on a new thread. Also, start calling callback with requested data _tempMonDataLogWorker = new TempDataLogWorker(this, filename, threadRestTimeMs, callback); _tempMonDataLogThread = new Thread(_tempMonDataLogWorker.DoWork); _tempMonDataLogThread.Start(); } /// /// Stop the temperature sensor log thread /// public void TemperatureSensorLogStop() { const int THREAD_QUIT_TIMEOUT = 3000; //Are we logging if (_tempMonDataLogWorker != null) { _tempMonDataLogWorker.QuitWork(); if ((_tempMonDataLogThread != null) && (_tempMonDataLogThread.IsAlive)) { bool didThreadQuit = _tempMonDataLogThread.Join(THREAD_QUIT_TIMEOUT); if (didThreadQuit == false) { _logger?.Error("Logging Thread did not quit as expected, aborting it"); _tempMonDataLogThread.Abort(); } else { _logger?.Info("Logging Thread quit successfully after join"); } } else { _logger?.Info("Logging Thread quit successfully"); } } } #endregion } }