예제 #1
0
 public NotifyEventArgs(
     NotificationType notificationType,
     UpsContext upsContext)
 {
     this.NotificationType = notificationType;
     this.UpsContext       = upsContext;
 }
예제 #2
0
        private static Ups GetOrCreateState(UpsContext ctx)
        {
            if (ctx.State != null)
            {
                return(ctx.State);
            }

            return(Ups.Create(
                       ctx.Name,
                       ctx.ServerState,
                       new Dictionary <string, string>()));
        }
예제 #3
0
        private static bool IsUpsDead(UpsContext upsContext)
        {
            // If we lost communication with the UPS and it has been longer than DEADTIME seconds
            // and the last known status is OnBattery, assume that the UPS is dead.

            return(upsContext.ServerState.ConnectionStatus == ServerConnectionStatus.LostConnection &&
                   upsContext.LastNoCommNotifyTime.HasValue &&
                   upsContext.LastNoCommNotifyTime.Value.OlderThan(
                       TimeSpan.FromSeconds(
                           ServiceRuntime.Instance.Configuration.ServiceConfiguration
                           .ServerNotRespondingTimeInSeconds)));
        }
예제 #4
0
        private void InitializeFromConfiguration()
        {
            foreach (UpsConfiguration upsConfiguration in
                     ServiceRuntime.Instance.Configuration.UpsConfigurations)
            {
                Logger.Info($"Loading server {upsConfiguration.DeviceName} from configuration");

                try
                {
                    upsConfiguration.ValidateProperties();
                }
                catch (Exception exception)
                {
                    Logger.Error(
                        "An error occurred while loading the configuration for the UPS '{0}' on server '{1}. The error was: {2}",
                        upsConfiguration.DeviceName,
                        upsConfiguration.ServerConfiguration.DisplayName,
                        exception.Message);

                    Logger.Info("Exception during upsContext load. {0}", exception);
                }

                if (ServiceRuntime.Instance.UpsContexts.Any(
                        s => string.Equals(
                            s.QualifiedName,
                            upsConfiguration.GetQualifiedName())))
                {
                    throw new WingnutException("The device already exists");
                }

                Server server = Server.CreateFromConfiguration(
                    upsConfiguration.ServerConfiguration);

                UpsContext upsContext = new UpsContext(
                    upsConfiguration,
                    server);

                ServiceRuntime.Instance.UpsContexts.Add(upsContext);

                Logger.Info($"Ups '{upsContext.Name}' successfully loaded from configuration");
            }

            Logger.Info(
                "Finished loading {0} devices from configuration",
                ServiceRuntime.Instance.Configuration.UpsConfigurations.Count);
        }
예제 #5
0
        public void Notify(
            UpsContext upsContext,
            NotificationType notification)
        {
            if (this.OnNotify == null)
            {
                return;
            }

            foreach (EventHandler <NotifyEventArgs> notifyDelegate in this.OnNotify.GetInvocationList())
            {
                notifyDelegate.BeginInvoke(
                    this,
                    new NotifyEventArgs(
                        notification,
                        upsContext),
                    ar =>
                {
                    EventHandler <NotifyEventArgs> thisDelegate = (EventHandler <NotifyEventArgs>)ar.AsyncState;
                    thisDelegate.EndInvoke(ar);
                },
                    notifyDelegate);
            }
        }
예제 #6
0
        public Ups AddUps(
            Server server,
            string password,
            string upsName,
            int numPowerSupplies,
            bool monitorOnly,
            bool force)
        {
            // Update the password on the server object since it can't be passed as a SecureString
            // over the WCF channel
            server.Password = SecureStringExtensions.FromString(password);
            ServerConfiguration serverConfiguration = ServerConfiguration.CreateFromServer(server);

            serverConfiguration.ValidateProperties();

            // Recreate the server object to ensure that it matches what would be created when it
            // is read from configuration at startup.
            server = Server.CreateFromConfiguration(serverConfiguration);

            UpsConfiguration upsConfiguration = new UpsConfiguration()
            {
                DeviceName          = upsName,
                MonitorOnly         = monitorOnly,
                NumPowerSupplies    = numPowerSupplies,
                ServerConfiguration = serverConfiguration
            };

            try
            {
                ServerConnection serverConnection = new ServerConnection(server);

                serverConnection.ConnectAsync(CancellationToken.None).Wait();

                Dictionary <string, string> upsVars =
                    serverConnection
                    .ListVarsAsync(upsName, CancellationToken.None).Result;

                Ups ups = Ups.Create(upsName, server, upsVars);

                // Success. Add the configuration and save
                ServiceRuntime.Instance.Configuration.UpsConfigurations.Add(
                    upsConfiguration);

                ServiceRuntime.Instance.SaveConfiguration();

                // Add to the running instances
                UpsContext upsContext = new UpsContext(upsConfiguration, server)
                {
                    State = ups
                };

                ServiceRuntime.Instance.UpsContexts.Add(upsContext);

#pragma warning disable 4014
                Task.Run(() =>
                {
                    foreach (IManagementCallback callbackChannel in
                             ServiceRuntime.Instance.ClientCallbackChannels)
                    {
                        try
                        {
                            callbackChannel.UpsDeviceAdded(ups);
                        }
                        catch (Exception e)
                        {
                            Logger.Error("Caught exception while updating device. " + e.Message);
                            ServiceRuntime.Instance.ClientCallbackChannels.Remove(callbackChannel);
                            break;
                        }
                    }
                });
#pragma warning restore 4014

                return(ups);
            }
            catch (Exception exception)
            {
                Logger.Error("Exception while adding UPS device. {0}", exception.Message);

                if (force)
                {
                    // Add the configuration and save
                    ServiceRuntime.Instance.Configuration.UpsConfigurations.Add(
                        upsConfiguration);

                    ServiceRuntime.Instance.SaveConfiguration();

                    return(null);
                }

                throw;
            }
        }
예제 #7
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));
            }
        }