//-------------------------------------------------------------------------------------------------//
        public virtual string ExecuteXmlRequest(string xmlRequest)
        {
            string strXmlResponse = string.Empty;

            const string STRLOG_MethodName = "ExecuteXmlRequest";

            Logfile.WriteCalled(this.logLevel, STRLOG_ClassName, STRLOG_MethodName);

            try
            {
                bool success = true;
                string errorMessage = string.Empty;
                ExecuteCommandInfo executeCommandInfo = null;
                ExecuteCommandInfo executeResultInfo = null;

                //
                // Create the XML response
                //
                XmlDocument xmlResponseDocument = new XmlDocument();
                XmlElement xmlElement = xmlResponseDocument.CreateElement(Consts.STRXML_Response);
                xmlResponseDocument.AppendChild(xmlElement);

                //
                // Add success of command execution and update later
                //
                xmlElement = xmlResponseDocument.CreateElement(Consts.STRXML_RspSuccess);
                xmlElement.InnerText = success.ToString();
                xmlResponseDocument.DocumentElement.AppendChild(xmlElement);

                //
                // Parse XML request for the command
                //
                XmlDocument xmlRequestDocument = new XmlDocument();
                xmlRequestDocument.LoadXml(xmlRequest);
                XmlNode xmlRequestNode = XmlUtilities.GetXmlRootNode(xmlRequestDocument, Consts.STRXML_Request);
                string strCommand = XmlUtilities.GetXmlValue(xmlRequestNode, Consts.STRXML_Command, false);

                NonExecuteCommands nonExecuteCommand = (NonExecuteCommands)(-1);
                ExecuteCommands executeCommand = (ExecuteCommands)(-1);
                try
                {
                    //
                    // Try to convert to a non-execute command type that doesn't require powerdown to be suspended
                    //
                    nonExecuteCommand = (NonExecuteCommands)Enum.Parse(typeof(NonExecuteCommands), strCommand);
                    Logfile.Write(STRLOG_Command + nonExecuteCommand.ToString());
                }
                catch
                {
                    try
                    {
                        //
                        // Try to convert to an execute command type that does require powerdown to be suspended
                        //
                        executeCommand = (ExecuteCommands)Enum.Parse(typeof(ExecuteCommands), strCommand);
                        Logfile.Write(STRLOG_Command + executeCommand.ToString());

                        //
                        // Check that powerdown has been suspended before executing the command
                        //
                        if (this.labEquipmentEngine.IsPowerdownSuspended == false)
                        {
                            //
                            // Unable to execute the command
                            //
                            success = false;
                            errorMessage = STRERR_PowerdownMustBeSuspended + executeCommand.ToString();
                        }
                    }
                    catch
                    {
                        //
                        // Unknown command
                        //
                        success = false;
                        errorMessage = STRERR_UnknownCommand + strCommand;
                    }
                }

                if (success == true && nonExecuteCommand != (NonExecuteCommands)(-1))
                {
                    //
                    // Process the non-execute command
                    //
                    switch (nonExecuteCommand)
                    {
                        case NonExecuteCommands.GetTime:

                            //
                            // Add time to response
                            //
                            xmlElement = xmlResponseDocument.CreateElement("Time");
                            xmlElement.InnerText = DateTime.Now.ToShortTimeString();
                            xmlResponseDocument.DocumentElement.AppendChild(xmlElement);
                            break;
                    }
                }
                else if (success == true && executeCommand != (ExecuteCommands)(-1))
                {
                    //
                    // Only one execute command allowed at a time
                    //
                    lock (this.managerLock)
                    {
                        //
                        // Create an instance of the command info ready to fill in
                        //
                        executeCommandInfo = new ExecuteCommandInfo(executeCommand);

                        //
                        // Process the execute command
                        //
                        switch (executeCommand)
                        {
                            case ExecuteCommands.SetTime:

                                //
                                // Pretend to change the time
                                //
                                executeCommandInfo.parameters = new object[] { DateTime.Now };
                                executeCommandInfo.timeout = 20;
                                executeResultInfo = this.labEquipmentEngine.ExecuteCommand(executeCommandInfo);
                                if (executeResultInfo.success == true)
                                {
                                    DateTime dateTime = (DateTime)executeCommandInfo.results[0];
                                }
                                break;
                        }
                    }
                }

                //
                // Update success of command execution
                //
                XmlNode xmlResponseNode = XmlUtilities.GetXmlRootNode(xmlResponseDocument, Engine.Consts.STRXML_Response);
                XmlUtilities.SetXmlValue(xmlResponseNode, Engine.Consts.STRXML_RspSuccess, executeResultInfo.success.ToString(), false);
                if (success == false)
                {
                    //
                    // Create error response
                    //
                    xmlElement = xmlResponseDocument.CreateElement(Engine.Consts.STRXML_RspErrorMessage);
                    xmlElement.InnerText = executeResultInfo.errorMessage;
                    xmlResponseDocument.DocumentElement.AppendChild(xmlElement);
                }
                strXmlResponse = xmlResponseDocument.InnerXml;

            }
            catch (Exception ex)
            {
                Logfile.Write(ex.Message);
            }

            Logfile.WriteCompleted(this.logLevel, STRLOG_ClassName, STRLOG_MethodName);

            return strXmlResponse;
        }
        //-------------------------------------------------------------------------------------------------//
        public override ExecuteCommandInfo ProcessCommand(ExecuteCommandInfo executeCommandInfo)
        {
            const string STRLOG_MethodName = "ProcessCommand";

            Logfile.WriteCalled(STRLOG_ClassName, STRLOG_MethodName);

            CommandInfo commandInfo = (CommandInfo)executeCommandInfo;

            bool success = true;
            string errorMessage = null;

            try
            {
                //
                // Process the execute command
                //
                ExecuteCommands executeCommand = (ExecuteCommands)commandInfo.command;

                switch (executeCommand)
                {
                    //
                    // YOUR CODE HERE
                    //
                    case ExecuteCommands.DoSomething:
                        // Remove this command in your implementation
                        break;

                    default:

                        //
                        // Unknown command
                        //
                        errorMessage = STRERR_UnknownCommand + executeCommand.ToString();
                        success = false;
                        break;
                }
            }
            catch (Exception ex)
            {
                success = false;
                errorMessage = ex.Message;
            }

            //
            // Update success of command execution
            //
            executeCommandInfo.success = success;

            string logMessage = STRLOG_Success + success.ToString();
            if (success == false)
            {
                executeCommandInfo.errorMessage = errorMessage;
                logMessage += Logfile.STRLOG_Spacer + STRLOG_ErrorMessage + errorMessage;
            }

            Logfile.WriteCompleted(STRLOG_ClassName, STRLOG_MethodName, logMessage);

            return executeCommandInfo;
        }
        //-------------------------------------------------------------------------------------------------//
        public override ExecuteCommandInfo ProcessCommand(ExecuteCommandInfo executeCommandInfo)
        {
            const string STRLOG_MethodName = "ProcessCommand";

            Logfile.WriteCalled(STRLOG_ClassName, STRLOG_MethodName);

            CommandInfo commandInfo = (CommandInfo)executeCommandInfo;

            bool success = false;
            string errorMessage = null;

            try
            {
                //
                // Process the execute command
                //
                ExecuteCommands executeCommand = (ExecuteCommands)commandInfo.command;

                switch (executeCommand)
                {
                    case ExecuteCommands.StartExecution:
                        //
                        // Get the specification in XML format from the parameters and parse
                        //
                        string xmlSpecification = (string)commandInfo.parameters[0];
                        Specification specification = new Specification(this.xmlNodeEquipmentConfig);
                        ValidationReport validationReport = specification.Parse(xmlSpecification);
                        if (validationReport.accepted == false)
                        {
                            errorMessage = validationReport.errorMessage;
                            break;
                        }

                        //
                        // Create an instance of the driver for the specified setup
                        // and then start the driver with the specification
                        //
                        if (specification.SetupId.Equals(Consts.STRXML_SetupId_OpenCircuitVaryField) == true)
                        {
                            this.driverMachine = new DriverMachine_OCVF(this.xmlNodeEquipmentConfig, specification);
                        }
                        else if (specification.SetupId.Equals(Consts.STRXML_SetupId_OpenCircuitVarySpeed) == true)
                        {
                            this.driverMachine = new DriverMachine_OCVS(this.xmlNodeEquipmentConfig, specification);
                        }
                        else if (specification.SetupId.Equals(Consts.STRXML_SetupId_ShortCircuitVaryField) == true)
                        {
                            this.driverMachine = new DriverMachine_SCVF(this.xmlNodeEquipmentConfig, specification);
                        }
                        else if (specification.SetupId.Equals(Consts.STRXML_SetupId_PreSynchronisation) == true)
                        {
                            this.driverMachine = new DriverMachine_PreSync(this.xmlNodeEquipmentConfig, specification);
                        }
                        else if (specification.SetupId.Equals(Consts.STRXML_SetupId_Synchronisation) == true)
                        {
                            this.driverMachine = new DriverMachine_Sync(this.xmlNodeEquipmentConfig, specification);
                        }
                        else
                        {
                            //
                            // Unknown SetupId
                            //
                            throw new Exception(STRERR_UnknownSetupId + specification.SetupId);
                        }

                        //
                        // Start execution of the specified setup
                        //
                        if ((success = this.driverMachine.Start()) == false)
                        {
                            errorMessage = this.driverMachine.LastError;
                        }
                        break;

                    default:
                        //
                        // Unknown command
                        //
                        throw new Exception(STRERR_UnknownCommand + executeCommand.ToString());
                }
            }
            catch (Exception ex)
            {
                success = false;
                errorMessage = ex.Message;
            }

            //
            // Update success of command execution
            //
            executeCommandInfo.success = success;

            string logMessage = STRLOG_Success + success.ToString();
            if (success == false)
            {
                executeCommandInfo.errorMessage = errorMessage;
                logMessage += Logfile.STRLOG_Spacer + STRLOG_ErrorMessage + errorMessage;
            }

            Logfile.WriteCompleted(STRLOG_ClassName, STRLOG_MethodName, logMessage);

            return executeCommandInfo;
        }
        //-------------------------------------------------------------------------------------------------//

        public virtual string ExecuteXmlRequest(string xmlRequest)
        {
            string strXmlResponse = string.Empty;

            const string STRLOG_MethodName = "ExecuteXmlRequest";

            Logfile.WriteCalled(this.logLevel, STRLOG_ClassName, STRLOG_MethodName);

            try
            {
                bool               success            = true;
                string             errorMessage       = string.Empty;
                ExecuteCommandInfo executeCommandInfo = null;
                ExecuteCommandInfo executeResultInfo  = null;

                //
                // Create the XML response
                //
                XmlDocument xmlResponseDocument = new XmlDocument();
                XmlElement  xmlElement          = xmlResponseDocument.CreateElement(Consts.STRXML_Response);
                xmlResponseDocument.AppendChild(xmlElement);

                //
                // Add success of command execution and update later
                //
                xmlElement           = xmlResponseDocument.CreateElement(Consts.STRXML_RspSuccess);
                xmlElement.InnerText = success.ToString();
                xmlResponseDocument.DocumentElement.AppendChild(xmlElement);

                //
                // Parse XML request for the command
                //
                XmlDocument xmlRequestDocument = new XmlDocument();
                xmlRequestDocument.LoadXml(xmlRequest);
                XmlNode xmlRequestNode = XmlUtilities.GetXmlRootNode(xmlRequestDocument, Consts.STRXML_Request);
                string  strCommand     = XmlUtilities.GetXmlValue(xmlRequestNode, Consts.STRXML_Command, false);

                NonExecuteCommands nonExecuteCommand = (NonExecuteCommands)(-1);
                ExecuteCommands    executeCommand    = (ExecuteCommands)(-1);
                try
                {
                    //
                    // Try to convert to a non-execute command type that doesn't require powerdown to be suspended
                    //
                    nonExecuteCommand = (NonExecuteCommands)Enum.Parse(typeof(NonExecuteCommands), strCommand);
                    Logfile.Write(STRLOG_Command + nonExecuteCommand.ToString());
                }
                catch
                {
                    try
                    {
                        //
                        // Try to convert to an execute command type that does require powerdown to be suspended
                        //
                        executeCommand = (ExecuteCommands)Enum.Parse(typeof(ExecuteCommands), strCommand);
                        Logfile.Write(STRLOG_Command + executeCommand.ToString());

                        //
                        // Check that powerdown has been suspended before executing the command
                        //
                        if (this.labEquipmentEngine.IsPowerdownSuspended == false)
                        {
                            //
                            // Unable to execute the command
                            //
                            success      = false;
                            errorMessage = STRERR_PowerdownMustBeSuspended + executeCommand.ToString();
                        }
                    }
                    catch
                    {
                        //
                        // Unknown command
                        //
                        success      = false;
                        errorMessage = STRERR_UnknownCommand + strCommand;
                    }
                }

                if (success == true && nonExecuteCommand != (NonExecuteCommands)(-1))
                {
                    //
                    // Process the non-execute command
                    //
                    switch (nonExecuteCommand)
                    {
                    case NonExecuteCommands.GetTime:

                        //
                        // Add time to response
                        //
                        xmlElement           = xmlResponseDocument.CreateElement("Time");
                        xmlElement.InnerText = DateTime.Now.ToShortTimeString();
                        xmlResponseDocument.DocumentElement.AppendChild(xmlElement);
                        break;
                    }
                }
                else if (success == true && executeCommand != (ExecuteCommands)(-1))
                {
                    //
                    // Only one execute command allowed at a time
                    //
                    lock (this.managerLock)
                    {
                        //
                        // Create an instance of the command info ready to fill in
                        //
                        executeCommandInfo = new ExecuteCommandInfo(executeCommand);

                        //
                        // Process the execute command
                        //
                        switch (executeCommand)
                        {
                        case ExecuteCommands.SetTime:

                            //
                            // Pretend to change the time
                            //
                            executeCommandInfo.parameters = new object[] { DateTime.Now };
                            executeCommandInfo.timeout    = 20;
                            executeResultInfo             = this.labEquipmentEngine.ExecuteCommand(executeCommandInfo);
                            if (executeResultInfo.success == true)
                            {
                                DateTime dateTime = (DateTime)executeCommandInfo.results[0];
                            }
                            break;
                        }
                    }
                }

                //
                // Update success of command execution
                //
                XmlNode xmlResponseNode = XmlUtilities.GetXmlRootNode(xmlResponseDocument, Engine.Consts.STRXML_Response);
                XmlUtilities.SetXmlValue(xmlResponseNode, Engine.Consts.STRXML_RspSuccess, executeResultInfo.success.ToString(), false);
                if (success == false)
                {
                    //
                    // Create error response
                    //
                    xmlElement           = xmlResponseDocument.CreateElement(Engine.Consts.STRXML_RspErrorMessage);
                    xmlElement.InnerText = executeResultInfo.errorMessage;
                    xmlResponseDocument.DocumentElement.AppendChild(xmlElement);
                }
                strXmlResponse = xmlResponseDocument.InnerXml;
            }
            catch (Exception ex)
            {
                Logfile.Write(ex.Message);
            }

            Logfile.WriteCompleted(this.logLevel, STRLOG_ClassName, STRLOG_MethodName);

            return(strXmlResponse);
        }
        //-------------------------------------------------------------------------------------------------//
        public override ExecuteCommandInfo ProcessCommand(ExecuteCommandInfo executeCommandInfo)
        {
            const string STRLOG_MethodName = "ProcessCommand";

            Logfile.WriteCalled(STRLOG_ClassName, STRLOG_MethodName);

            CommandInfo commandInfo = (CommandInfo)executeCommandInfo;

            bool success = true;
            string errorMessage = null;

            try
            {
                //
                // Process the execute command
                //
                ExecuteCommands executeCommand = (ExecuteCommands)commandInfo.command;

                switch (executeCommand)
                {
                    case ExecuteCommands.GetTimeOfDay:

                        //
                        // Get server URL from parameters
                        //
                        string serverUrl = (string)commandInfo.parameters[0];

                        //
                        // Get the time-of-day
                        //
                        DateTime dateTime = DateTime.MinValue;
                        if ((success = this.timeOfDay.GetTimeOfDay(serverUrl, ref dateTime)) == false)
                        {
                            errorMessage = this.timeOfDay.GetLastError();
                        }
                        else
                        {
                            //
                            // Add the measurement values to results
                            //
                            commandInfo.results = new object[] {
                                dateTime
                            };
                        }
                        break;

                    default:

                        //
                        // Unknown command
                        //
                        errorMessage = STRERR_UnknownCommand + executeCommand.ToString();
                        success = false;
                        break;
                }
            }
            catch (Exception ex)
            {
                success = false;
                errorMessage = ex.Message;
            }

            //
            // Update success of command execution
            //
            executeCommandInfo.success = success;

            string logMessage = STRLOG_Success + success.ToString();
            if (success == false)
            {
                executeCommandInfo.errorMessage = errorMessage;
                logMessage += Logfile.STRLOG_Spacer + STRLOG_ErrorMessage + errorMessage;
            }

            Logfile.WriteCompleted(STRLOG_ClassName, STRLOG_MethodName, logMessage);

            return executeCommandInfo;
        }
        //-------------------------------------------------------------------------------------------------//
        public override ExecuteCommandInfo ProcessCommand(ExecuteCommandInfo executeCommandInfo)
        {
            const string STRLOG_MethodName = "ProcessCommand";

            Logfile.WriteCalled(STRLOG_ClassName, STRLOG_MethodName);

            CommandInfo commandInfo = (CommandInfo)executeCommandInfo;

            bool success = true;
            string errorMessage = null;

            try
            {
                //
                // Process the execute command
                //
                ExecuteCommands executeCommand = (ExecuteCommands)commandInfo.command;

                switch (executeCommand)
                {
                    case ExecuteCommands.CreateConnection:

                        //
                        // Create a connection to the RedLion controller
                        //
                        if ((success = this.redLion.CreateConnection()) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.CloseConnection:

                        //
                        // Close the connection to the RedLion controller
                        //
                        if ((success = this.redLion.CloseConnection()) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.ResetACDrive:

                        //
                        // Reset the AC drive controller
                        //
                        if ((success = this.redLion.ResetACDrive()) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.ConfigureACDrive:

                        //
                        // Get AC drive configuration from parameters
                        //
                        RedLion.ACDriveConfigs acDriveConfig = (RedLion.ACDriveConfigs)commandInfo.parameters[0];

                        //
                        // Configure the AC drive
                        //
                        if ((success = this.redLion.ConfigureACDrive(acDriveConfig)) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.StartACDrive:

                        //
                        // Get AC drive mode from parameters
                        //
                        RedLion.ACDriveModes acDriveMode = (RedLion.ACDriveModes)commandInfo.parameters[0];

                        //
                        // Start the AC drive
                        //
                        if ((success = this.redLion.StartACDrive(acDriveMode)) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.StopACDrive:

                        //
                        // Get AC drive mode from parameters
                        //
                        acDriveMode = (RedLion.ACDriveModes)commandInfo.parameters[0];

                        //
                        // Stop the AC drive
                        //
                        if ((success = this.redLion.StopACDrive(acDriveMode)) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.TakeMeasurement:

                        //
                        // Take a measurement
                        //
                        RedLion.Measurements measurement = new RedLion.Measurements();
                        if ((success = this.redLion.TakeMeasurement(ref measurement)) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        else
                        {
                            //
                            // Add the measurement values to results - ensure the order of the measurement values is the
                            // same as in EquipmentManager.cs
                            //
                            commandInfo.results = new object[] {
                                measurement.voltageMut,
                                measurement.currentMut,
                                measurement.powerFactorMut,
                                measurement.voltageVsd,
                                measurement.currentVsd,
                                measurement.powerFactorVsd,
                                measurement.speed,
                                measurement.torque
                            };
                        }
                        break;

                    default:

                        //
                        // Unknown command
                        //
                        errorMessage = STRERR_UnknownCommand + executeCommand.ToString();
                        success = false;
                        break;
                }
            }
            catch (Exception ex)
            {
                success = false;
                errorMessage = ex.Message;
            }

            //
            // Update success of command execution
            //
            executeCommandInfo.success = success;

            string logMessage = STRLOG_Success + success.ToString();
            if (success == false)
            {
                executeCommandInfo.errorMessage = errorMessage;
                logMessage += Logfile.STRLOG_Spacer + STRLOG_ErrorMessage + errorMessage;
            }

            Logfile.WriteCompleted(STRLOG_ClassName, STRLOG_MethodName, logMessage);

            return executeCommandInfo;
        }
        //-------------------------------------------------------------------------------------------------//
        public override ExecuteCommandInfo ProcessCommand(ExecuteCommandInfo executeCommandInfo)
        {
            const string STRLOG_MethodName = "ProcessCommand";

            Logfile.WriteCalled(STRLOG_ClassName, STRLOG_MethodName);

            CommandInfo commandInfo = (CommandInfo)executeCommandInfo;

            bool success = true;
            string errorMessage = null;

            try
            {
                //
                // Process the execute command
                //
                ExecuteCommands executeCommand = (ExecuteCommands)commandInfo.command;

                switch (executeCommand)
                {
                    case ExecuteCommands.SetTubeDistance:

                        //
                        // Set tube distance
                        //
                        int tubeDistance = (int)commandInfo.parameters[0];
                        if ((success = this.flexMotion.SetTubeDistance(tubeDistance)) == false)
                        {
                            errorMessage = this.flexMotion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.SetSourceLocation:

                        //
                        // Set source location
                        //
                        char sourceLocation = (char)commandInfo.parameters[0];
                        if ((success = this.flexMotion.SetSourceLocation(sourceLocation)) == false)
                        {
                            errorMessage = this.flexMotion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.SetAbsorberLocation:

                        //
                        // Set absorber location
                        //
                        char absorberLocation = (char)commandInfo.parameters[0];
                        if ((success = this.flexMotion.SetAbsorberLocation(absorberLocation)) == false)
                        {
                            errorMessage = this.flexMotion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.GetCaptureData:

                        //
                        // Get duration from parameters
                        //
                        int duration = (int)commandInfo.parameters[0];

                        //
                        // Get radiation count
                        //
                        int count = -1;
                        if (this.radiationCounterType == RadiationCounterTypes.ST360)
                        {
                            int[] counts = new int[1];
                            if (this.st360Counter.CaptureData(duration, counts) == true)
                            {
                                count = counts[0];
                            }
                        }
                        else if (this.radiationCounterType == RadiationCounterTypes.Physics)
                        {
                            count = this.physicsCounter.CaptureData(duration);
                        }

                        //
                        // Add radiation count to results
                        //
                        commandInfo.results = new object[] { count };
                        break;

                    case ExecuteCommands.WriteLcdLine:

                        //
                        // Get LCD line number from request
                        //
                        int lcdLineNo = (int)commandInfo.parameters[0];

                        //
                        // Get LCD message from request and 'URL Decode' to preserve spaces
                        //
                        string lcdMessage = (string)commandInfo.parameters[1];
                        lcdMessage = HttpUtility.UrlDecode(lcdMessage);

                        //
                        // Write message to LCD
                        //
                        if ((success = this.serialLcd.WriteLine(lcdLineNo, lcdMessage)) == false)
                        {
                            errorMessage = this.serialLcd.GetLastError();
                        }
                        break;

                    default:

                        //
                        // Unknown command
                        //
                        errorMessage = STRERR_UnknownCommand + executeCommand.ToString();
                        success = false;
                        break;
                }
            }
            catch (Exception ex)
            {
                success = false;
                errorMessage = ex.Message;
            }

            //
            // Update success of command execution
            //
            executeCommandInfo.success = success;

            string logMessage = STRLOG_Success + success.ToString();
            if (success == false)
            {
                executeCommandInfo.errorMessage = errorMessage;
                logMessage += Logfile.STRLOG_Spacer + STRLOG_ErrorMessage + errorMessage;
            }

            Logfile.WriteCompleted(STRLOG_ClassName, STRLOG_MethodName, logMessage);

            return executeCommandInfo;
        }
        //-------------------------------------------------------------------------------------------------//
        public virtual ExecuteCommandInfo ProcessCommand(ExecuteCommandInfo executeCommandInfo)
        {
            const string STRLOG_MethodName = "ProcessCommand";

            Logfile.WriteCalled(this.logLevel, STRLOG_ClassName, STRLOG_MethodName);

            bool success = true;
            string errorMessage = null;

            //
            // Process the execute command
            //
            ExecuteCommands executeCommand = (ExecuteCommands)executeCommandInfo.command;

            switch (executeCommand)
            {
                case ExecuteCommands.SetTime:

                    //
                    // Pretending to change the time, so nothing to do here
                    //
                    DateTime dateTime = (DateTime)executeCommandInfo.parameters[0];
                    Logfile.Write(" parameters: dateTime -> " + dateTime.ToString());

                    //
                    // Create some dummy results
                    //
                    executeCommandInfo.results = new object[] { DateTime.Now };
                    dateTime = (DateTime)executeCommandInfo.results[0];
                    Logfile.Write(" results: dateTime -> " + dateTime.ToString());
                    break;

                default:
                    //
                    // Unknown command
                    //
                    errorMessage = STRERR_UnknownCommand + executeCommand.ToString();
                    success = false;
                    break;
            }

            //
            // Update success of command execution
            //
            executeCommandInfo.success = success;

            string logMessage = STRLOG_Success + success.ToString();
            if (success == false)
            {
                executeCommandInfo.errorMessage = errorMessage;
                logMessage += Logfile.STRLOG_Spacer + STRLOG_ErrorMessage + errorMessage;
            }

            Logfile.WriteCompleted(this.logLevel, STRLOG_ClassName, STRLOG_MethodName, logMessage);

            return executeCommandInfo;
        }
        //-------------------------------------------------------------------------------------------------//
        public ExecuteCommandInfo ExecuteCommand(ExecuteCommandInfo executeCommandInfo)
        {
            const string STRLOG_MethodName = "ExecuteCommand";

            Logfile.WriteCalled(this.logLevel, STRLOG_ClassName, STRLOG_MethodName);

            if (this.disposed == false)
            {
                //
                // Determine the timeout for waiting on the result
                //
                int timeout = executeCommandInfo.timeout;
                timeout = timeout * 1000 / DELAY_MS_SignalResultCheck;

                //
                // Save the info and signal LabEquipmentEngine thread to execute the command
                //
                lock (this.signalCommand)
                {
                    lock (this.executeCommandLock)
                    {
                        this.executeResultInfo = null;
                        this.executeCommandInfo = executeCommandInfo;
                    }
                    Monitor.Pulse(this.signalCommand);
                }

                //
                // Wait for the LabEquipmentEngine thread to execute the command and return the results
                //
                do
                {
                    lock (this.signalResult)
                    {
                        if (Monitor.Wait(this.signalResult, DELAY_MS_SignalResultCheck) == true)
                        {
                            Trace.WriteLine("Result received...");
                        }
                    }

                    lock (this.executeCommandLock)
                    {
                        if (this.executeResultInfo != null)
                        {
                            break;
                        }
                    }
                }
                while (--timeout > 0);
            }

            Logfile.WriteCompleted(this.logLevel, STRLOG_ClassName, STRLOG_MethodName);

            return this.executeResultInfo;
        }
        //-------------------------------------------------------------------------------------------------//
        private void LabEquipmentEngineThread()
        {
            const string STRLOG_MethodName = "LabEquipmentEngineThread";

            Logfile.WriteCalled(this.logLevel, STRLOG_ClassName, STRLOG_MethodName);

            //
            // Initialise state machine
            //
            int retryPowerOnInit = RETRY_PowerOnInit;
            bool retry = false;
            States state = States.sPowerInit;
            States lastState = States.sExitThread;
            this.slOnline = true;
            this.Running = true;

            try
            {
                //
                // State machine loop
                //
                while (this.Running == true)
                {
                    //
                    // Display message on each state change
                    //
                    if (state != lastState)
                    {
                        string logMessage = " [ " + STRLOG_MethodName + ": " + lastState.ToString() + " -> " + state.ToString() + " ]";
                        Logfile.Write(this.logLevel, logMessage);
                        Trace.WriteLine(logMessage);

                        lastState = state;
                    }

                    switch (state)
                    {
                        case States.sPowerInit:

                            lock (this.statusLock)
                            {
                                this.slStatusMessage = STR_PoweringUp;

                                // Initialise powerup delay
                                this.slPowerupTimeRemaining = this.powerupDelay;
                            }

                            // Powerup the equipment
                            if (PowerupEquipment() == false)
                            {
                                this.slOnline = false;
                                this.slStatusMessage = STR_NotInitialised;
                                state = States.sExitThread;
                                break;
                            }

                            state = States.sPowerUpDelay;
                            break;

                        case States.sPowerUpDelay:

                            // Wait a bit
                            Thread.Sleep(1000);

                            lock (this.statusLock)
                            {
                                // Check timeout
                                if (--this.slPowerupTimeRemaining > 0)
                                {
                                    // Equipment is still powering up
                                    Trace.Write("u");
                                    continue;
                                }
                            }

                            // Equipment is now powered up
                            state = States.sPowerOnInit;
                            break;

                        case States.sPowerOnInit:

                            // Set the power intialisation start time
                            lock (this.statusLock)
                            {
                                this.slStatusMessage = STR_Initialising;
                                this.slPowerupInitialiseStartTime = DateTime.Now;
                            }

                            //
                            // Initialise the equipment
                            //
                            retry = false;
                            if (InitialiseEquipment() == false || this.debug_Retry == true)
                            {
                                if (--retryPowerOnInit >= 0)
                                {
                                    retry = true;

                                    Logfile.WriteError(
                                        String.Format(STRERR_InitiliaseFailedRetrying_arg2, RETRY_PowerOnInit - retryPowerOnInit, RETRY_PowerOnInit));

                                    //
                                    // Equipment failed to initialise, powerdown the equipment and try again
                                    //
                                    lock (this.statusLock)
                                    {
                                        this.slPowerupTimeRemaining = this.PoweroffDelay + this.PowerupDelay;
                                    }
                                    PowerdownEquipment();
                                    state = States.sPowerOffDelay;
                                }
                                else
                                {
                                    Logfile.WriteError(
                                        String.Format(STRERR_InitiliaseFailedAfterRetrying_arg, RETRY_PowerOnInit + 1));

                                    //
                                    // Could initialise the equipment after retrying, powerdown the equipment and exit
                                    //
                                    this.slOnline = false;
                                    this.slStatusMessage = STR_NotInitialised;
                                    PowerdownEquipment();
                                    state = States.sExitThread;
                                }
                                break;
                            }

                            lock (this.statusLock)
                            {
                                // Equipment is now ready to use
                                this.slStatusMessage = STR_Ready;
                                this.slIsReady = true;

                                // Initialise powerdown timeout
                                this.slPowerdownTimeRemaining = this.powerdownTimeout;
                            }

                            // Check if powerdown is enabled
                            if (this.powerdownEnabled == false)
                            {
                                this.PowerdownSuspended = true;
                            }
                            else
                            {
                                // Log the time remaining before power is removed
                                LogPowerDown(this.powerdownTimeout, true);
                            }
                            state = States.sPowerOnReady;
                            break;

                        case States.sPowerOnReady:

                            // Wait a bit
                            Thread.Sleep(1000);

                            //
                            // Check if equipment powerdown should be suspended
                            //
                            if (this.PowerdownSuspended == true)
                            {
                                lock (this.statusLock)
                                {
                                    this.slPowerdownIsSuspended = true;
                                }
                                state = States.sPowerSuspended;
                                break;
                            }

                            //
                            // Log the time remaining before power is removed
                            //
                            int timeRemaining;
                            lock (this.statusLock)
                            {
                                timeRemaining = this.slPowerdownTimeRemaining;
                            }
                            LogPowerDown(timeRemaining);

                            lock (this.statusLock)
                            {
                                // Check timeout
                                if (--this.slPowerdownTimeRemaining > 0)
                                {
                                    // Timeout is still counting down
                                    Trace.Write("t");
                                    continue;
                                }

                                //
                                // Equipment is powering down, determine the time before the equipment
                                // can be powered up again
                                //
                                this.slPowerupTimeRemaining = this.PoweroffDelay + this.PowerupDelay;
                                this.slIsReady = false;
                                this.slStatusMessage = STR_PoweringDown;
                            }

                            // Powerdown the equipment
                            PowerdownEquipment();

                            state = States.sPowerOffDelay;
                            break;

                        case States.sPowerSuspended:

                            //
                            // Check if there is a command to execute
                            //
                            lock (this.signalCommand)
                            {
                                if (Monitor.Wait(this.signalCommand, DELAY_MS_SignalCommandCheck) == true)
                                {
                                    Trace.WriteLine("Command received...");
                                }

                                //
                                // Whether we timed out or not, check for a command
                                //
                                lock (this.executeCommandLock)
                                {
                                    if (this.executeCommandInfo != null)
                                    {
                                        state = States.sProcessCommand;
                                        break;
                                    }
                                }
                            }

                            // Check if equipment powerdown is resumed
                            if (this.PowerdownSuspended == false)
                            {
                                // Log the time remaining before power is removed
                                LogPowerDown(this.powerdownTimeout, true);

                                lock (this.statusLock)
                                {
                                    // Reset the powerdown timeout
                                    this.slPowerdownTimeRemaining = this.powerdownTimeout;
                                    this.slPowerdownIsSuspended = false;
                                }
                                state = States.sPowerOnReady;
                            }
                            break;

                        case States.sProcessCommand:

                            ExecuteCommandInfo executeResultInfo = ProcessCommand(this.executeCommandInfo);

                            lock (this.signalResult)
                            {
                                lock (this.executeCommandLock)
                                {
                                    this.executeCommandInfo = null;
                                    this.executeResultInfo = executeResultInfo;
                                }
                                Monitor.Pulse(this.signalResult);
                            }

                            state = States.sPowerSuspended;
                            break;

                        case States.sPowerOffDelay:

                            // Wait a bit
                            Thread.Sleep(1000);

                            // Check timeout
                            lock (this.statusLock)
                            {
                                if (--this.slPowerupTimeRemaining > this.powerupDelay)
                                {
                                    // Equipment is still powering off
                                    Trace.Write("o");
                                }
                                else
                                {
                                    // Check if powerup has been requested
                                    if (this.slPowerdownSuspended == true)
                                    {
                                        state = States.sPowerInit;
                                    }
                                    else
                                    {
                                        // Powerdown has completed
                                        this.slStatusMessage = STR_PoweredDown;

                                        //
                                        // Check if retrying
                                        //
                                        if (retry == true)
                                        {
                                            state = States.sPowerInit;
                                        }
                                        else
                                        {
                                            state = States.sExitThread;
                                        }
                                    }
                                }
                            }
                            break;

                        case States.sExitThread:

                            //
                            // Thread is no longer running
                            //
                            this.Running = false;
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                Logfile.WriteError(ex.Message);
            }

            Trace.WriteLine(STRLOG_MethodName + ": Exiting");

            Logfile.WriteCompleted(this.logLevel, STRLOG_ClassName, STRLOG_MethodName);
        }
        //-------------------------------------------------------------------------------------------------//
        public override ExecuteCommandInfo ProcessCommand(ExecuteCommandInfo executeCommandInfo)
        {
            const string STRLOG_MethodName = "ProcessCommand";

            Logfile.WriteCalled(this.logLevel, STRLOG_ClassName, STRLOG_MethodName);

            CommandInfo commandInfo = (CommandInfo)executeCommandInfo;

            bool success = true;
            string errorMessage = null;

            try
            {
                //
                // Process the execute command
                //
                ExecuteCommands executeCommand = (ExecuteCommands)commandInfo.command;

                switch (executeCommand)
                {
                    case ExecuteCommands.CreateConnection:

                        //
                        // Create a connection to the RedLion controller
                        //
                        if ((success = this.redLion.CreateConnection()) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.CloseConnection:

                        //
                        // Close the connection to the RedLion controller
                        //
                        if ((success = this.redLion.CloseConnection()) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.ResetACDrive:

                        //
                        // Reset the AC drive
                        //
                        if ((success = this.redLion.ResetACDrive()) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.ConfigureACDrive:

                        //
                        // Get AC drive configuration from parameters
                        //
                        RedLion.ACDriveConfigs acCDriveConfig = (RedLion.ACDriveConfigs)commandInfo.parameters[0];

                        //
                        // Configure the AC drive with the specified configuration
                        //
                        if ((success = this.redLion.ConfigureACDrive(acCDriveConfig)) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.StartACDrive:

                        //
                        // Start the AC drive
                        //
                        if ((success = this.redLion.StartACDrive()) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.StopACDrive:

                        //
                        // Stop the AC drive
                        //
                        if ((success = this.redLion.StopACDrive()) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.ResetDCDriveMut:

                        //
                        // Reset the DC drive
                        //
                        if ((success = this.redLion.ResetDCDriveMut()) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.ConfigureDCDriveMut:

                        //
                        // Get DC drive configuration from parameters
                        //
                        RedLion.DCDriveMutConfigs dcDriveMutConfig = (RedLion.DCDriveMutConfigs)commandInfo.parameters[0];

                        //
                        // Configure the AC drive with the specified configuration
                        //
                        if ((success = this.redLion.ConfigureDCDriveMut(dcDriveMutConfig)) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.StartDCDriveMut:

                        //
                        // Get DC drive mode from parameters
                        //
                        RedLion.DCDriveMutModes dcDriveMutMode = (RedLion.DCDriveMutModes)commandInfo.parameters[0];

                        //
                        // Start the DC drive
                        //
                        if ((success = this.redLion.StartDCDriveMut(dcDriveMutMode)) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.StopDCDriveMut:

                        //
                        // Stop the DC drive
                        //
                        if ((success = this.redLion.StopDCDriveMut()) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.SetSpeedACDrive:

                        //
                        // Get speed from parameters
                        //
                        int speedACDrive = (int)commandInfo.parameters[0];

                        //
                        // Set the speed of the AC drive
                        //
                        if ((success = this.redLion.SetSpeedACDrive(speedACDrive)) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.SetSpeedDCDriveMut:

                        //
                        // Get speed from parameters
                        //
                        int speedDCDriveMut = (int)commandInfo.parameters[0];

                        //
                        // Set the speed of the DC drive
                        //
                        if ((success = this.redLion.SetSpeedDCDriveMut(speedDCDriveMut)) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.SetTorqueDCDriveMut:

                        //
                        // Get torque from parameters
                        //
                        int torqueDCDriveMut = (int)commandInfo.parameters[0];

                        //
                        // Set the torque of the DC drive
                        //
                        if ((success = this.redLion.SetTorqueDCDriveMut(torqueDCDriveMut)) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.SetFieldDCDriveMut:

                        //
                        // Get torque from parameters
                        //
                        int fieldDCDriveMut = (int)commandInfo.parameters[0];

                        //
                        // Set the field of the DC drive
                        //
                        if ((success = this.redLion.SetFieldDCDriveMut(fieldDCDriveMut)) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        break;

                    case ExecuteCommands.TakeMeasurement:

                        //
                        // Take a measurement
                        //
                        RedLion.Measurements measurement = new RedLion.Measurements();
                        if ((success = this.redLion.TakeMeasurement(ref measurement)) == false)
                        {
                            errorMessage = this.redLion.GetLastError();
                        }
                        else
                        {
                            //
                            // Add the measurement values to results
                            //
                            commandInfo.results = new object[] {
                                measurement.speed,
                                measurement.voltage,
                                measurement.fieldCurrent,
                                measurement.load
                            };
                        }
                        break;

                    default:

                        //
                        // Unknown command
                        //
                        errorMessage = STRERR_UnknownCommand + executeCommand.ToString();
                        success = false;
                        break;
                }
            }
            catch (Exception ex)
            {
                success = false;
                errorMessage = ex.Message;
            }

            //
            // Update success of command execution
            //
            executeCommandInfo.success = success;

            string logMessage = STRLOG_Success + success.ToString();
            if (success == false)
            {
                executeCommandInfo.errorMessage = errorMessage;
                logMessage += Logfile.STRLOG_Spacer + STRLOG_ErrorMessage + errorMessage;
            }

            Logfile.WriteCompleted(this.logLevel, STRLOG_ClassName, STRLOG_MethodName, logMessage);

            return executeCommandInfo;
        }