Example #1
0
        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));
        }
Example #2
0
        /// <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));
            }
        }
Example #3
0
        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.");
        }