/// <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); }