private static bool IsStatusTransition( UpsStatusChangeData changeData, DeviceStatusType status, bool requirePreviousState) { if (!requirePreviousState) { return(changeData.UpsContext.State.Status.HasFlag(status) && (changeData.PreviousState == null || !changeData.PreviousState.Status.HasFlag(status))); } if (changeData.PreviousState == null) { return(false); } return(changeData.UpsContext.State.Status.HasFlag(status) && !changeData.PreviousState.Status.HasFlag(status)); }
/// <summary> /// Process the status change for a single UPS. This method only logs events and performs /// notification. No actions are taken by this method. /// </summary> /// <param name="changeData">The change data</param> private void ProcessSingleUpsStatusChange(UpsStatusChangeData changeData) { // Alias the UpsContext to make the code here a bit cleaner UpsContext ctx = changeData.UpsContext; // First check if we do not have connectivity to the UPS, since we will want to // skip processing other state checks if this is the case if (ctx.ServerState.ConnectionStatus == ServerConnectionStatus.LostConnection) { if (ctx.LastNoCommNotifyTime == null) { string error = changeData.Exception == null ? "(none)" : changeData.Exception.Message; Logger.CommunicationLost(ctx.Name, ctx.ServerState.Name, error); ServiceRuntime.Instance.Notify(ctx, NotificationType.CommunicationLost); ctx.LastNoCommNotifyTime = DateTime.Now; } else if ( ctx.LastNoCommNotifyTime.Value.OlderThan( TimeSpan.FromSeconds( ServiceRuntime.Instance.Configuration.ServiceConfiguration.NoCommNotifyDelayInSeconds))) { string error = changeData.Exception == null ? "(none)" : changeData.Exception.Message; Logger.NoCommunication(ctx.Name, ctx.ServerState.Name, error); ServiceRuntime.Instance.Notify( ctx, NotificationType.NoCommunication); ctx.LastNoCommNotifyTime = DateTime.Now; } } else if (ctx.ServerState.ConnectionStatus == ServerConnectionStatus.Connected && ctx.LastNoCommNotifyTime != null) { ServiceRuntime.Instance.Notify( ctx, NotificationType.CommunicationRestored); Logger.CommunicationRestored(ctx.Name, ctx.ServerState.Name); Logger.Info("Communication with UPS {0} was restored", ctx.QualifiedName); ctx.LastNoCommNotifyTime = null; } if (IsStatusTransition(changeData, DeviceStatusType.Online, true)) { // The device is going from !Online to Online Logger.UpsOnline(ctx.Name, ctx.ServerState.Name); ServiceRuntime.Instance.Notify(ctx, NotificationType.Online); } if (IsStatusTransition(changeData, DeviceStatusType.OnBattery, false)) { // The device is going from !OnBattery to OnBattery Logger.UpsOnBattery(ctx.Name, ctx.ServerState.Name); ServiceRuntime.Instance.Notify(ctx, NotificationType.OnBattery); } if (IsStatusTransition(changeData, DeviceStatusType.LowBattery, true)) { // The device is going from !LowBattery to LowBattery Logger.UpsLowBattery(ctx.Name, ctx.ServerState.Name); ServiceRuntime.Instance.Notify(ctx, NotificationType.LowBattery); } if (ctx.State.Status.HasFlag(DeviceStatusType.ReplaceBattery)) { // The ReplaceBattery status is set. Check if we haven't yet logged an event // and notified for this, or if we have waited enough time to do it again. if (ctx.LastReplaceBatteryWarnTime == null || ctx.LastReplaceBatteryWarnTime.Value.OlderThan( TimeSpan.FromSeconds( ServiceRuntime.Instance.Configuration.ServiceConfiguration .ReplaceBatteryWarningTimeInSeconds))) { Logger.UpsReplaceBattery( ctx.Name, ctx.ServerState.Name, ctx.State.BatteryLastReplacement); Logger.Info( "The UPS {0} is reporting that the battery should be replaced. The last replacement date is {1}", ctx.QualifiedName, ctx.State.BatteryLastReplacement); ServiceRuntime.Instance.Notify( ctx, NotificationType.ReplaceBattery); ctx.LastReplaceBatteryWarnTime = DateTime.Now; } } DeviceSeverityType severity = Constants.Device.GetStatusSeverity( ctx.State.Status); if (changeData.PreviousState == null) { // This is the very first time polling this device, so log the initial status var newSetFlags = EnumExtensions.GetSetFlagNames <DeviceStatusType>( ctx.State.Status); Logger.Log( Constants.Device.DeviceSeverityToLogLevel(severity), "Initial status of UPS {0} is {1}", ctx.QualifiedName, string.Join("|", newSetFlags)); } else if (ctx.State.Status != changeData.PreviousState.Status) { // The status of the UPS has changed, so log the previous and new status var initialSetFlags = EnumExtensions.GetSetFlagNames <DeviceStatusType>( changeData.PreviousState.Status); var newSetFlags = EnumExtensions.GetSetFlagNames <DeviceStatusType>( ctx.State.Status); Logger.Log( Constants.Device.DeviceSeverityToLogLevel(severity), "Status of UPS {0} has changed from {1} to {2}", ctx.QualifiedName, string.Join("|", initialSetFlags), string.Join("|", newSetFlags)); } }
private void ProcessUpsStatusChanges(UpsStatusChangeData changeData) { Logger.Debug("ProcessUpsStatusChanges: Starting."); // Process the changes and send notification for the changes for this UPS this.ProcessSingleUpsStatusChange(changeData); // Calculate the current power value to determine if any actions need to be taken int newActivePowerValue = 0; foreach (UpsContext upsContext in ServiceRuntime.Instance.UpsContexts) { Logger.Debug($"Calculating power value for UPS {upsContext.QualifiedName}"); if (upsContext.State == null) { Logger.Debug($"Skipping UPS {upsContext.QualifiedName} since context has not yet been initialized"); continue; } if (upsContext.UpsConfiguration.MonitorOnly) { Logger.Debug("Skipping UPS. Ups is configured as MonitorOnly"); continue; } if (upsContext.State.Status.HasFlag(DeviceStatusType.OnBattery) && upsContext.State.Status.HasFlag(DeviceStatusType.LowBattery)) { Logger.Debug("Skipping UPS. State=OnBattery&LowBattery"); continue; } // If the UPS is considered dead (due to inability to contact it) and the last // known status of the UPS was OnBattery, assume that the UPS is in a LowBattery // state and do not count it towards the power value. if (IsUpsDead(upsContext) && upsContext.State.Status.HasFlag(DeviceStatusType.OnBattery)) { Logger.Debug("Skipping UPS. UPS is dead and State=OnBattery."); continue; } Logger.Debug( $"Finished calculating power value. Adding power value of {upsContext.UpsConfiguration.NumPowerSupplies}"); newActivePowerValue += upsContext.UpsConfiguration.NumPowerSupplies; } if (newActivePowerValue == this.ActivePowerValue) { Logger.Debug("Power value is unchanged ({0})", this.ActivePowerValue); } else { Logger.Info( "ActivePowerValue changing from {0} to {1}", this.ActivePowerValue, newActivePowerValue); this.ActivePowerValue = newActivePowerValue; } if (this.ActivePowerValue < ServiceRuntime.Instance.Configuration.ServiceConfiguration.MinimumPowerSupplies) { Logger.PowerValueBelowThreshold( this.ActivePowerValue, ServiceRuntime.Instance.Configuration.ServiceConfiguration.MinimumPowerSupplies); this.InitiateShutdown(); } Logger.Debug("ProcessUpsStatusChanges: Finished."); }