/// <summary>
        /// Gets the battery status
        /// </summary>
        /// <returns></returns>
        internal virtual BatteryStatusPacket GetBatteryStatus()
        {
            BatteryStatusPacket infoPacket = new BatteryStatusPacket();

            // Indicate no battery present by default
            infoPacket.Presence       = 0;
            infoPacket.CompletionCode = CompletionCode.UnspecifiedError;

            return(infoPacket);
        }
        /// <summary>
        /// Gets the battery status
        /// </summary>
        /// <returns></returns>
        internal virtual BatteryStatusPacket GetBatteryStatus()
        {
            BatteryStatusPacket infoPacket = new BatteryStatusPacket();

            // Indicate no battery present by default
            infoPacket.Presence = 0;
            infoPacket.CompletionCode = CompletionCode.UnspecifiedError;

            return infoPacket;
        }
        /// <summary>
        /// Checks for faults on each PSU
        /// </summary>
        private static Dictionary <byte, PsuAlertFaultType> PsuAlertInvestigate()
        {
            Dictionary <byte, PsuAlertFaultType> failures = new Dictionary <byte, PsuAlertFaultType>();

            // Check status for all PSU
            foreach (PsuBase psu in ChassisState.Psu)
            {
                // If firmware update is in progress, skip this PSU
                if (ChassisState.PsuFwUpdateInProgress[psu.PsuId - 1])
                {
                    continue;
                }

                lock (ChassisState.psuLock[psu.PsuId - 1])
                {
                    PsuStatusPacket psuStatus = psu.GetPsuStatus();
                    if (psuStatus.CompletionCode != CompletionCode.Success)
                    {
                        Tracer.WriteError("PsuAlertInvestigate: GetPsuStatus on PSU ({0}) failed with return code {1}",
                                          psu.PsuId, psuStatus.CompletionCode);
                        failures.Add(psu.PsuId, PsuAlertFaultType.PsuFailure);
                    }
                    else
                    {
                        if (psuStatus.PsuStatus != (byte)Contracts.PowerState.ON)
                        {
                            // PSU is completely turned off
                            failures.Add(psu.PsuId, PsuAlertFaultType.PsuFailure);
                        }
                        else if ((ConfigLoaded.BatteryMonitoringEnabled) && (ChassisState.Psu[psu.PsuId - 1] is EmersonPsu))
                        {
                            // Check battery status for Emerson PSU
                            EmersonPsu emersonPsu = (EmersonPsu)psu;

                            // Get battery status and health
                            BatteryStatusPacket battStatus = emersonPsu.GetBatteryStatus();
                            EmersonPsu.BatteryHealthStatusPacket battHealth = emersonPsu.GetBatteryHealthStatus();

                            if ((battStatus.CompletionCode == CompletionCode.Success) &&
                                (battHealth.CompletionCode == CompletionCode.Success))
                            {
                                // Update chassis energy storage variables
                                bool batteryPresent          = (battStatus.Presence == 1) ? true : false;
                                bool batteryFault            = (battStatus.FaultDetected == 1) ? true : false;
                                EnergyStorageState battState = EnergyStorageState.Unknown;

                                if (batteryPresent)
                                {
                                    if (batteryFault)
                                    {
                                        // Battery Fault Detected.
                                        failures.Add(emersonPsu.PsuId, PsuAlertFaultType.BatteryFault);
                                        Tracer.WriteError("PsuAlertInvestigate Battery Fault Detected. PsuId {0}", emersonPsu.PsuId);
                                    }
                                    else // if no fault detected, check if system is on battery.
                                    {
                                        // Determine battery state
                                        if (battHealth.Discharging == 0)
                                        {
                                            battState = EnergyStorageState.Charging;

                                            // We are charging, reset the timer.
                                            if (BatteryDischargeTimer.IsRunning)
                                            {
                                                BatteryDischargeTimer.Reset();
                                            }
                                        }
                                        else
                                        {
                                            // Emerson stated that we can have discharging even when on AC since the charger will have hysteresis.
                                            // Hence we need to check Discharging and Battery Power Output to determine if we are on Battery.
                                            if (battStatus.BatteryPowerOutput != 0)
                                            {
                                                battState = EnergyStorageState.Discharging;
                                            }
                                            else
                                            {
                                                battState = EnergyStorageState.Floating;
                                            }
                                        }

                                        if (battState == EnergyStorageState.Discharging)
                                        {
                                            // Start the timer if not already running.
                                            if (!BatteryDischargeTimer.IsRunning)
                                            {
                                                BatteryDischargeTimer.Start();
                                            }

                                            // Psu Battery is Discharging. System is on battery.
                                            // Log it as a failure for processing in PsuAlertRemediate() which is called outside this method
                                            failures.Add(emersonPsu.PsuId, PsuAlertFaultType.OnBattery);
                                            Tracer.WriteInfo("PsuAlertInvestigate Psu Battery discharging.  PsuId {0}", emersonPsu.PsuId);
                                        }
                                    }
                                }
                                else
                                {
                                    Tracer.WriteInfo("PsuAlertInvestigate, no battery present for Psu: {0}", emersonPsu.PsuId);
                                }

                                // Update chassis energy storage values
                                ChassisEnergyStorageStatus chassisEnergyStatus =
                                    new ChassisEnergyStorageStatus(batteryPresent, battState,
                                                                   battStatus.BatteryChargeLevel, battStatus.BatteryPowerOutput, batteryFault);
                                if (!ChassisState.SetEnergyStorageStatus(emersonPsu.PsuId, chassisEnergyStatus))
                                {
                                    Tracer.WriteError(
                                        string.Format("PsuAlertInvestigate: SetEnergyStorageStatus failed for BatteryId {0}", emersonPsu.PsuId));
                                }
                            }
                            else
                            {
                                // Failed to get battery status or health. Log as battery fault
                                failures.Add(emersonPsu.PsuId, PsuAlertFaultType.BatteryFault);
                                Tracer.WriteError("PsuAlertInvestigate failed to get Battery Status. PsuId {0} Status Completion Code: {1}  Health Completion Code: {2}",
                                                  emersonPsu.PsuId, battStatus.CompletionCode, battHealth.CompletionCode);
                            }
                        }

                        // If PSU is on and there are no battery faults, check if other faults are present
                        // Add PSU to failure list so that we can log it in PsuAlertRemediate()
                        if ((!failures.ContainsKey(psu.PsuId)) && (psuStatus.FaultPresent))
                        {
                            failures.Add(psu.PsuId, PsuAlertFaultType.PsuFaultPresent);
                        }
                    }
                } // lock...
            }     // foreach...

            return(failures);
        }
        /// <summary>
        /// Gets the battery status
        /// </summary>
        /// <returns></returns>
        internal override BatteryStatusPacket GetBatteryStatus()
        {
            BatteryStatusPacket infoPacket = new BatteryStatusPacket();
            infoPacket.CompletionCode = CompletionCode.Success;

            // Indicate that battery is present
            infoPacket.Presence = 1;

            // Get battery power output
            BatteryPowerPacket batteryPowerPacket = GetBatteryPowerOut();
            if (batteryPowerPacket.CompletionCode != CompletionCode.Success)
            {
                Tracer.WriteWarning("GetBatteryPowerOut failed for battery: " + this.PsuId);
            }
            else
            {
                infoPacket.BatteryPowerOutput = batteryPowerPacket.BatteryPower;
            }

            // Get battery charge level
            BatteryChargeLevelPacket batteryChargeLevelPacket = GetBatteryChargeLevel();
            if (batteryChargeLevelPacket.CompletionCode != CompletionCode.Success)
            {
                Tracer.WriteWarning("GetBatteryChargeLevel failed for battery: " + this.PsuId);
            }
            else
            {
                infoPacket.BatteryChargeLevel = batteryChargeLevelPacket.BatteryChargeLevel;
            }

            // Get battery fault indicator
            BatteryFaultIndicatorPacket batteryFaultIndicatorPacket = GetBatteryFaultIndicator();
            if (batteryFaultIndicatorPacket.CompletionCode != CompletionCode.Success)
            {
                Tracer.WriteWarning("GetBatteryFaultIndicator failed for battery: " + this.PsuId);
            }
            else
            {
                infoPacket.FaultDetected = batteryFaultIndicatorPacket.BatteryFault;
            }
            // Clear fault indicator after reading it. If the fault is still present, the fault bit will still be asserted in the PSU.
            CompletionCode returnPacket = new CompletionCode();
            returnPacket = ClearBatteryFaultIndicator();
            if (returnPacket != CompletionCode.Success)
            {
                Tracer.WriteWarning("ClearBatteryFaultIndicator failed for battery: " + this.PsuId);
            }

            return infoPacket;
        }
        /// <summary>
        /// Gets the battery status
        /// </summary>
        /// <returns></returns>
        internal override BatteryStatusPacket GetBatteryStatus()
        {
            BatteryStatusPacket infoPacket = new BatteryStatusPacket();
            infoPacket.CompletionCode = CompletionCode.Success;
            bool statusReadFailure = false;

            // Indicate that battery is present
            infoPacket.Presence = (byte)(this.batteryPresent == true? 1 : 0);

            if (this.batteryPresent)
            {
                // Get battery power output
                BatteryPowerPacket batteryPowerPacket = GetBatteryPowerOut();
                if (batteryPowerPacket.CompletionCode != CompletionCode.Success)
                {
                    Tracer.WriteWarning("GetBatteryPowerOut failed for battery: " + this.PsuId);
                    statusReadFailure = true;
                }
                else
                {
                    infoPacket.BatteryPowerOutput = batteryPowerPacket.BatteryPower;
                }

                // Get battery charge level
                BatteryChargeLevelPacket batteryChargeLevelPacket = GetBatteryChargeLevel();
                if (batteryChargeLevelPacket.CompletionCode != CompletionCode.Success)
                {
                    Tracer.WriteWarning("GetBatteryChargeLevel failed for battery: " + this.PsuId);
                    statusReadFailure = true;
                }
                else
                {
                    infoPacket.BatteryChargeLevel = batteryChargeLevelPacket.BatteryChargeLevel;
                }

                // Get battery fault indicator
                BatteryFaultIndicatorPacket batteryFaultIndicatorPacket = GetBatteryFaultIndicator();
                if (batteryFaultIndicatorPacket.CompletionCode != CompletionCode.Success)
                {
                    Tracer.WriteWarning("GetBatteryFaultIndicator failed for battery: " + this.PsuId);
                    statusReadFailure = true;
                }
                else
                {
                    infoPacket.FaultDetected = batteryFaultIndicatorPacket.BatteryFault;
                }
                // Clear fault indicator after reading it. If the fault is still present, the fault bit will still be asserted in the PSU.
                CompletionCode returnPacket = ClearBatteryFaultIndicator();
                if (returnPacket != CompletionCode.Success)
                {
                    Tracer.WriteWarning("ClearBatteryFaultIndicator failed for battery: " + this.PsuId);
                    statusReadFailure = true;
                }
            }
            else
            {
                statusReadFailure = true;
            }

            if (statusReadFailure)
            {
                infoPacket.CompletionCode = CompletionCode.UnspecifiedError;
            }

            return infoPacket;
        }