//---------------------------------------------------------------------------------------//
        /// <summary>
        /// 
        /// </summary>
        /// <param name="configProperties"></param>
        public LabEquipmentManager(ConfigProperties configProperties)
        {
            const string methodName = "LabEquipmentManager";
            Logfile.WriteCalled(Logfile.Level.Info, STR_ClassName, methodName);

            try
            {
                /*
                 * Check that parameters are valid
                 */
                if (configProperties == null)
                {
                    throw new ArgumentNullException(ConfigProperties.ClassName);
                }

                /*
                 * Create class instances and objects that are used by the LabEquipmentEngine
                 */
                this.labEquipmentConfiguration = new LabEquipmentConfiguration(configProperties);
                if (labEquipmentConfiguration == null)
                {
                    throw new ArgumentNullException(LabEquipmentConfiguration.ClassName);
                }
            }
            catch (Exception ex)
            {
                Logfile.WriteError(ex.Message);
                throw;
            }

            Logfile.WriteCompleted(Logfile.Level.Info, STR_ClassName, methodName);
        }
        //---------------------------------------------------------------------------------------//
        public EquipmentManager(ConfigProperties configProperties)
            : base(configProperties)
        {
            const String methodName = "EquipmentManager";
            Logfile.WriteCalled(logLevel, STR_ClassName, methodName);

            /*
             * Nothing to do here
             */

            Logfile.WriteCompleted(logLevel, STR_ClassName, methodName);
        }
        //-------------------------------------------------------------------------------------------------//
        /// <summary>
        /// Constructor - Parse the equipment configuration XML string for information specific to the LabEquipment.
        /// </summary>
        /// <param name="configProperties"></param>
        public LabEquipmentConfiguration(ConfigProperties configProperties)
        {
            const string methodName = "LabEquipmentConfiguration";
            Logfile.WriteCalled(logLevel, STR_ClassName, methodName);

            String logMessage = Logfile.STRLOG_Newline;

            try
            {
                /*
                 * Check that parameters are valid
                 */
                if (configProperties == null)
                {
                    throw new ArgumentNullException(ConfigProperties.ClassName);
                }
                if (configProperties.XmlEquipmentConfigPath == null)
                {
                    throw new ArgumentNullException(STRERR_XmlEquipmentConfigPath);
                }
                if (configProperties.XmlEquipmentConfigPath.Trim().Length == 0)
                {
                    throw new ArgumentException(String.Format(STRERR_NotSpecified_arg, STRERR_XmlEquipmentConfigPath));
                }
                this.filename = configProperties.XmlEquipmentConfigPath;

                /*
                 * Load the equipment configuration from the specified file
                 */
                XmlDocument xmlDocument = XmlUtilities.GetDocumentFromFile(this.filename);

                /*
                 * Get the document's root node
                 */
                XmlNode xmlNodeEquipmentConfiguration = XmlUtilities.GetRootNode(xmlDocument, LabConsts.STRXML_EquipmentConfig);

                logMessage += STRLOG_ParsingEquipmentConfiguration + Logfile.STRLOG_Newline;

                /*
                 * Get information from the equipment configuration node
                 */
                this.title = XmlUtilities.GetAttributeValue(xmlNodeEquipmentConfiguration, LabConsts.STRXML_ATTR_Title, false);
                this.version = XmlUtilities.GetAttributeValue(xmlNodeEquipmentConfiguration, LabConsts.STRXML_ATTR_Version, false);
                logMessage += String.Format(STRLOG_TitleVersion2_arg, this.title, this.version) + Logfile.STRLOG_Newline;

                /*
                 * Get powerup delay, may not be specified
                 */
                try
                {
                    this.powerupDelay = XmlUtilities.GetChildValueAsInt(xmlNodeEquipmentConfiguration, LabConsts.STRXML_PowerupDelay);
                    if (this.powerupDelay < 0)
                    {
                        throw new ArithmeticException(STRERR_NumberIsNegative);
                    }
                }
                catch (Exception)
                {
                    /*
                     * Powerup delay is not specified, use the default
                     */
                    this.powerupDelay = DELAY_SECS_PowerupDefault;
                }

                /*
                 * Get powerdown timeout, may not be specified
                 */
                try
                {
                    this.powerdownTimeout = XmlUtilities.GetChildValueAsInt(xmlNodeEquipmentConfiguration, LabConsts.STRXML_PowerdownTimeout);
                    if (this.powerdownTimeout < 0)
                    {
                        throw new ArithmeticException(STRERR_NumberIsNegative);
                    }

                    /*
                     * Powerdown timeout is specified so enable powerdown
                     */
                    this.powerdownEnabled = true;
                    this.poweroffDelay = DELAY_SECS_PoweroffMinimum;
                }
                catch (Exception)
                {
                    /*
                     * Powerdown timeout is not specified, disable powerdown
                     */
                    this.powerdownEnabled = false;
                    this.poweroffDelay = 0;
                }

                /*
                 * Log details
                 */
                logMessage += String.Format(STRLOG_PowerupDelay_arg, this.powerupDelay) + Logfile.STRLOG_Newline;

                if (this.powerdownEnabled == true)
                {
                    logMessage += String.Format(STRLOG_PowerdownTimeout_arg, this.powerdownTimeout) + Logfile.STRLOG_Newline;
                    logMessage += String.Format(STRLOG_PoweroffDelay_arg, this.poweroffDelay) + Logfile.STRLOG_Newline;
                }
                else
                {
                    logMessage += STRLOG_PowerdownDisabled + Logfile.STRLOG_Newline;
                }

                /*
                 * Get the device nodes and accumulate the initialise delay
                 */
                this.initialiseDelay = 0;
                this.mapDevices = new Dictionary<string, string>();
                XmlNode xmlNodeDevices = XmlUtilities.GetChildNode(xmlNodeEquipmentConfiguration, LabConsts.STRXML_Devices);
                ArrayList xmlNodeList = XmlUtilities.GetChildNodeList(xmlNodeDevices, LabConsts.STRXML_Device, false);
                for (int i = 0; i < xmlNodeList.Count; i++)
                {
                    XmlNode xmlNodeDevice = (XmlNode)xmlNodeList[i];

                    /*
                     * Check that the required device information exists
                     */
                    String name = XmlUtilities.GetAttributeValue(xmlNodeDevice, LabConsts.STRXML_ATTR_Name, false);
                    logMessage += String.Format(STRLOG_DeviceName_arg, name) + Logfile.STRLOG_Spacer;

                    /*
                     * Get the initialise delay and add to total
                     */
                    XmlNode xmlNodeInitialise = XmlUtilities.GetChildNode(xmlNodeDevice, LabConsts.STRXML_Initialise);
                    bool initialiseEnabled = XmlUtilities.GetChildValueAsBool(xmlNodeInitialise, LabConsts.STRXML_InitialiseEnabled);
                    if (initialiseEnabled == true)
                    {
                        int initialiseDelayDevice = XmlUtilities.GetChildValueAsInt(xmlNodeInitialise, LabConsts.STRXML_InitialiseDelay);
                        this.initialiseDelay += initialiseDelayDevice;
                        logMessage += String.Format(STRLOG_InitialiseDelay_arg, initialiseDelayDevice) + Logfile.STRLOG_Newline;
                    }

                    /*
                     * Add device XML to map
                     */
                    String xmlDevice = XmlUtilities.ToXmlString(xmlNodeDevice);
                    this.mapDevices.Add(name, xmlDevice);
                }

                /*
                 * Get the driver nodes
                 */
                this.mapDrivers = new Dictionary<string, string>();
                XmlNode xmlNodeDrivers = XmlUtilities.GetChildNode(xmlNodeEquipmentConfiguration, LabConsts.STRXML_Drivers);
                xmlNodeList = XmlUtilities.GetChildNodeList(xmlNodeDrivers, LabConsts.STRXML_Driver, false);
                for (int i = 0; i < xmlNodeList.Count; i++)
                {
                    XmlNode xmlNodeDriver = (XmlNode)xmlNodeList[i];

                    /*
                     * Check that the required driver information exists
                     */
                    String name = XmlUtilities.GetAttributeValue(xmlNodeDriver, LabConsts.STRXML_ATTR_Name, false);
                    logMessage += String.Format(STRLOG_DriverName_arg, name) + Logfile.STRLOG_Newline;

                    /*
                     * Add driver XML to map
                     */
                    String xmlDriver = XmlUtilities.ToXmlString(xmlNodeDriver);
                    this.mapDrivers.Add(name, xmlDriver);
                }

                /*
                 * Get the setup nodes
                 */
                this.mapSetups = new Dictionary<string, string>();
                XmlNode xmlNodeSetups = XmlUtilities.GetChildNode(xmlNodeEquipmentConfiguration, LabConsts.STRXML_Setups);
                xmlNodeList = XmlUtilities.GetChildNodeList(xmlNodeSetups, LabConsts.STRXML_Setup, false);
                for (int i = 0; i < xmlNodeList.Count; i++)
                {
                    XmlNode xmlNodeSetup = (XmlNode)xmlNodeList[i];

                    /*
                     * Get the setup id
                     */
                    String id = XmlUtilities.GetAttributeValue(xmlNodeSetup, LabConsts.STRXML_ATTR_Id, false);
                    logMessage += String.Format(STRLOG_SetupId_arg, id) + Logfile.STRLOG_Newline;

                    /*
                     * Get the driver and add to map
                     */
                    String strDriver = XmlUtilities.GetChildValue(xmlNodeSetup, LabConsts.STRXML_Driver);
                    this.mapSetups.Add(id, strDriver);
                }

                /*
                 * Get the validation node and save as an XML string
                 */
                XmlNode xmlNodeValidation = XmlUtilities.GetChildNode(xmlNodeEquipmentConfiguration, LabConsts.STRXML_Validation);
                this.xmlValidation = XmlUtilities.ToXmlString(xmlNodeValidation);

                Logfile.Write(logLevel, logMessage);
            }
            catch (Exception ex)
            {
                Logfile.WriteError(ex.Message);
                throw;
            }

            Logfile.WriteCompleted(logLevel, STR_ClassName, methodName);
        }
        //-------------------------------------------------------------------------------------------------//
        protected void Application_Start(object sender, EventArgs e)
        {
            const String methodName = "Application_Start";

            /*
             * Get the logfiles path
             */
            String logFilesPath;
            try
            {
                logFilesPath = AppSetting.GetAppSetting(LabConsts.STRCFG_LogFilesPath);
            }
            catch (Exception ex)
            {
                Logfile.Write(ex.Message);
                throw new ApplicationException(String.Format(STRERR_NotSpecified_arg, LabConsts.STRCFG_LogFilesPath));
            }
            if (logFilesPath == null)
            {
                throw new ApplicationException(String.Format(STRERR_NotSpecified_arg, LabConsts.STRCFG_LogFilesPath));
            }

            /*
             * Set the filepath for the log files
             */
            String rootFilePath = HostingEnvironment.ApplicationPhysicalPath;
            Logfile.SetFilePath(Path.Combine(rootFilePath, logFilesPath));

            /*
             * Set the logging level
             */
            try
            {
                String strLogLevel = AppSetting.GetAppSetting(LabConsts.STRCFG_LogLevel);
                Logfile.Level level = (Logfile.Level)Enum.Parse(typeof(Logfile.Level), strLogLevel, true);
                Logfile.SetLevel(level);
            }
            catch
            {
                Logfile.SetLevel(Logfile.Level.Info);
            }

            Logfile.Write(String.Empty);
            Logfile.WriteCalled(logLevel, STR_ClassName, methodName);

            /*
             * Get the equipment configuration filename
             */
            String xmlEquipmentConfigFilename;
            try
            {
                xmlEquipmentConfigFilename = AppSetting.GetAppSetting(LabConsts.STRCFG_XmlEquipmentConfigFilename);
            }
            catch (Exception ex)
            {
                Logfile.Write(ex.Message);
                throw new ApplicationException(String.Format(STRERR_NotSpecified_arg, LabConsts.STRCFG_XmlEquipmentConfigFilename));
            }
            if (xmlEquipmentConfigFilename == null)
            {
                throw new ApplicationException(String.Format(STRERR_NotSpecified_arg, LabConsts.STRCFG_XmlEquipmentConfigFilename));
            }

            try
            {
                /*
                 * Get configuration properties
                 */
                configProperties = new ConfigProperties();
                configProperties.XmlEquipmentConfigPath = Path.Combine(rootFilePath, xmlEquipmentConfigFilename);

                /*
                 * Create experiment manager and start it
                 */
                equipmentManager = new EquipmentManager(configProperties);
                if (equipmentManager.Create() == false)
                {
                    throw new ApplicationException(STRERR_EquipmentManagerCreateFailed);
                }
                if (equipmentManager.Start() == false)
                {
                    throw new ApplicationException(STRERR_EquipmentManagerStartFailed);
                }
            }
            catch (Exception ex)
            {
                this.Application_End(sender, e);
                throw ex;
            }
            Logfile.WriteCompleted(logLevel, STR_ClassName, methodName);
        }