diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..48c5715a --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "ms-dotnettools.vscode-dotnet-runtime", + "ms-dotnettools.csharp", + "ms-dotnettools.csdevkit", + "vivaxy.vscode-conventional-commits", + "mhutchie.git-graph" + ] +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDisplay.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDisplay.cs index 9b82cacd..af3428f6 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDisplay.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDisplay.cs @@ -2,7 +2,14 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces { - public interface IDisplay: IHasFeedback, IRoutingSinkWithSwitching, IHasPowerControl, IWarmingCooling, IUsageTracking, IKeyName + /// + /// Interface for display devices that can be controlled and monitored. + /// This interface combines functionality for feedback, routing, power control, + /// warming/cooling, usage tracking, and key name management. + /// It is designed to be implemented by devices that require these capabilities, + /// such as projectors, displays, and other visual output devices. + /// + public interface IDisplay : IHasFeedback, IRoutingSinkWithSwitching, IHasPowerControl, IWarmingCooling, IUsageTracking, IKeyName { } } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMeterFeedback.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMeterFeedback.cs new file mode 100644 index 00000000..a4b935a5 --- /dev/null +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMeterFeedback.cs @@ -0,0 +1,18 @@ +using System; + +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +{ + + /// + /// Interface for devices that provide audio meter feedback. + /// This interface is used to standardize access to meter feedback across different devices. + /// + public interface IMeterFeedback + { + /// + /// Gets the meter feedback for the device. + /// This property provides an IntFeedback that represents the current audio level or meter value. + /// + IntFeedback MeterFeedback { get; } + } +} diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IStateFeedback.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IStateFeedback.cs new file mode 100644 index 00000000..a4f6c2bb --- /dev/null +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IStateFeedback.cs @@ -0,0 +1,18 @@ +using System; + +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +{ + + /// + /// Interface for devices that provide state feedback. + /// This interface is used to standardize access to state feedback across different devices. + /// + public interface IStateFeedback + { + /// + /// Gets the state feedback for the device. + /// This property provides a BoolFeedback that represents the current state (on/off) of the device. + /// + BoolFeedback StateFeedback { get; } + } +} diff --git a/src/PepperDash.Essentials.Core/Devices/DestinationListItem.cs b/src/PepperDash.Essentials.Core/Devices/DestinationListItem.cs index 0c21216a..c0837401 100644 --- a/src/PepperDash.Essentials.Core/Devices/DestinationListItem.cs +++ b/src/PepperDash.Essentials.Core/Devices/DestinationListItem.cs @@ -5,19 +5,34 @@ using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Core { + /// + /// Represents a destination item in a routing system that can receive audio/video signals. + /// Contains information about the destination device, its properties, and location settings. + /// public class DestinationListItem { + /// + /// Gets or sets the key identifier for the sink device that this destination represents. + /// [JsonProperty("sinkKey")] public string SinkKey { get; set; } private EssentialsDevice _sinkDevice; + /// + /// Gets the actual device instance for this destination. + /// Lazily loads the device from the DeviceManager using the SinkKey. + /// [JsonIgnore] public EssentialsDevice SinkDevice { get { return _sinkDevice ?? (_sinkDevice = DeviceManager.GetDeviceForKey(SinkKey) as EssentialsDevice); } } + /// + /// Gets the preferred display name for this destination. + /// Returns the custom Name if set, otherwise returns the SinkDevice name, or "---" if no device is found. + /// [JsonProperty("preferredName")] public string PreferredName { @@ -32,31 +47,71 @@ namespace PepperDash.Essentials.Core } } + /// + /// Gets or sets the custom name for this destination. + /// If set, this name will be used as the PreferredName instead of the device name. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets a value indicating whether this destination should be included in destination lists. + /// [JsonProperty("includeInDestinationList")] public bool IncludeInDestinationList { get; set; } + /// + /// Gets or sets the display order for this destination in lists. + /// Lower values appear first in sorted lists. + /// [JsonProperty("order")] public int Order { get; set; } + /// + /// Gets or sets the surface location identifier for this destination. + /// Used to specify which surface or screen this destination is located on. + /// [JsonProperty("surfaceLocation")] public int SurfaceLocation { get; set; } + /// + /// Gets or sets the vertical location position for this destination. + /// Used for spatial positioning in multi-display configurations. + /// [JsonProperty("verticalLocation")] public int VerticalLocation { get; set; } - + + /// + /// Gets or sets the horizontal location position for this destination. + /// Used for spatial positioning in multi-display configurations. + /// [JsonProperty("horizontalLocation")] public int HorizontalLocation { get; set; } + /// + /// Gets or sets the signal type that this destination can receive (Audio, Video, AudioVideo, etc.). + /// [JsonProperty("sinkType")] public eRoutingSignalType SinkType { get; set; } + /// + /// Gets or sets a value indicating whether this destination is used for codec content sharing. + /// [JsonProperty("isCodecContentDestination")] public bool isCodecContentDestination { get; set; } + /// + /// Gets or sets a value indicating whether this destination is used for program audio output. + /// [JsonProperty("isProgramAudioDestination")] public bool isProgramAudioDestination { get; set; } + + /// + /// Gets or sets a value indicating whether this destination supports USB connections. + /// Indicates if the destination can handle USB functionality, such as USB signal routing or device connections. + /// This property is used to determine compatibility with USB-based devices or systems. + /// + [JsonProperty("supportsUsb")] + public bool SupportsUsb { get; set; } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/SourceListItem.cs b/src/PepperDash.Essentials.Core/Devices/SourceListItem.cs index ae223005..3d08a218 100644 --- a/src/PepperDash.Essentials.Core/Devices/SourceListItem.cs +++ b/src/PepperDash.Essentials.Core/Devices/SourceListItem.cs @@ -1,12 +1,14 @@ -using Newtonsoft.Json; +using System.Collections.Generic; +using Newtonsoft.Json; using Newtonsoft.Json.Converters; using PepperDash.Core; -using System.Collections.Generic; namespace PepperDash.Essentials.Core { /// - /// + /// Defines the type of source list item, which can be a route, off, or other. + /// This is used to categorize the source list items in a room. + /// The type is serialized to JSON and can be used to determine how the item should be displayed or handled in the UI. /// public enum eSourceListItemType { @@ -166,6 +168,19 @@ namespace PepperDash.Essentials.Core [JsonProperty("disableSimpleRouting")] public bool DisableSimpleRouting { get; set; } + /// + /// The key of the device that provides video sync for this source item + /// + [JsonProperty("syncProviderDeviceKey")] + public string SyncProviderDeviceKey { get; set; } + + /// + /// Indicates if the source supports USB connections + /// + [JsonProperty("supportsUsb")] + public bool SupportsUsb { get; set; } + + /// /// Default constructor for SourceListItem, initializes the Icon to "Blank" /// @@ -177,7 +192,7 @@ namespace PepperDash.Essentials.Core /// /// Returns a string representation of the SourceListItem, including the SourceKey and Name /// - /// + /// A string representation of the SourceListItem public override string ToString() { return $"{SourceKey}:{Name}"; diff --git a/src/PepperDash.Essentials.Core/Routing/ICurrentSources.cs b/src/PepperDash.Essentials.Core/Routing/ICurrentSources.cs new file mode 100644 index 00000000..bef0fd95 --- /dev/null +++ b/src/PepperDash.Essentials.Core/Routing/ICurrentSources.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Core.Routing +{ + /// + /// The current sources for the room, keyed by eRoutingSignalType. + /// This allows for multiple sources to be tracked, such as audio and video. + /// + /// + /// This interface is used to provide access to the current sources in a room, + /// allowing for more complex routing scenarios where multiple signal types are involved. + /// + public interface ICurrentSources + { + /// + /// Gets the current sources for the room, keyed by eRoutingSignalType. + /// This dictionary contains the current source for each signal type, such as audio, video, and control signals. + /// + Dictionary CurrentSources { get; } + + /// + /// Gets the current source keys for the room, keyed by eRoutingSignalType. + /// This dictionary contains the keys for the current source for each signal type, such as audio, video, and control signals. + /// + Dictionary CurrentSourceKeys { get; } + + } +} diff --git a/src/PepperDash.Essentials.Core/Routing/IHasCurrentSourceInfoChange.cs b/src/PepperDash.Essentials.Core/Routing/IHasCurrentSourceInfoChange.cs index 505a8652..a8dbc594 100644 --- a/src/PepperDash.Essentials.Core/Routing/IHasCurrentSourceInfoChange.cs +++ b/src/PepperDash.Essentials.Core/Routing/IHasCurrentSourceInfoChange.cs @@ -9,6 +9,8 @@ using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Core.Routing.Interfaces */ +using System; + namespace PepperDash.Essentials.Core { /// @@ -21,10 +23,24 @@ namespace PepperDash.Essentials.Core /// /// For rooms with a single presentation source, change event /// + [Obsolete("Use ICurrentSources instead")] public interface IHasCurrentSourceInfoChange { + /// + /// The key for the current source info, used to look up the source in the SourceList + /// string CurrentSourceInfoKey { get; set; } + + /// + /// The current source info for the room, used to look up the source in the SourceList + /// SourceListItem CurrentSourceInfo { get; set; } + + /// + /// Event that is raised when the current source info changes. + /// This is used to notify the system of changes to the current source info. + /// The event handler receives the new source info and the type of change that occurred. + /// event SourceInfoChangeHandler CurrentSourceChange; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingSink.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingSink.cs index 59bcd65b..dd1d004e 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingSink.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingSink.cs @@ -1,29 +1,29 @@ -namespace PepperDash.Essentials.Core +using PepperDash.Essentials.Core.Routing; + +namespace PepperDash.Essentials.Core { /// /// For fixed-source endpoint devices /// public interface IRoutingSink : IRoutingInputs, IHasCurrentSourceInfoChange - { + { } /// /// For fixed-source endpoint devices with an input port /// - public interface IRoutingSinkWithInputPort :IRoutingSink + public interface IRoutingSinkWithInputPort : IRoutingSink { /// /// Gets the current input port for this routing sink. /// RoutingInputPort CurrentInputPort { get; } } - /*/// - /// For fixed-source endpoint devices - /// - public interface IRoutingSink : IRoutingInputs, IHasCurrentSourceInfoChange - { - void UpdateRouteRequest(RouteRequest request); - RouteRequest GetRouteRequest(); - }*/ + /// + /// Interface for routing sinks that have access to the current source information. + /// + public interface IRoutingSinkWithCurrentSources : IRoutingSink, ICurrentSources + { + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/DisplayBase.cs b/src/PepperDash.Essentials.Devices.Common/Displays/DisplayBase.cs index 24d55c2e..926fca04 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/DisplayBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/DisplayBase.cs @@ -1,110 +1,199 @@ -using Crestron.SimplSharp; +using System; +using System.Collections.Generic; +using System.Linq; +using Crestron.SimplSharp; using Crestron.SimplSharpPro.DeviceSupport; using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.DeviceTypeInterfaces; +using PepperDash.Essentials.Core.Routing; using Serilog.Events; -using System; -using System.Collections.Generic; -using System.Linq; using Feedback = PepperDash.Essentials.Core.Feedback; namespace PepperDash.Essentials.Devices.Common.Displays { - public abstract class DisplayBase : EssentialsDevice, IDisplay + /// + /// Abstract base class for display devices that provides common display functionality + /// including power control, input switching, and routing capabilities. + /// + public abstract class DisplayBase : EssentialsDevice, IDisplay, ICurrentSources { - private RoutingInputPort _currentInputPort; - public RoutingInputPort CurrentInputPort - { - get - { - return _currentInputPort; - } + private RoutingInputPort _currentInputPort; - protected set - { - if (_currentInputPort == value) return; + /// + /// Gets or sets the current input port that is selected on the display. + /// + public RoutingInputPort CurrentInputPort + { + get + { + return _currentInputPort; + } - _currentInputPort = value; + protected set + { + if (_currentInputPort == value) return; - InputChanged?.Invoke(this, _currentInputPort); - } - } + _currentInputPort = value; - public event InputChangedEventHandler InputChanged; + InputChanged?.Invoke(this, _currentInputPort); + } + } - public event SourceInfoChangeHandler CurrentSourceChange; + /// + /// Event that is raised when the input changes on the display. + /// + public event InputChangedEventHandler InputChanged; - public string CurrentSourceInfoKey { get; set; } - public SourceListItem CurrentSourceInfo - { - get - { - return _CurrentSourceInfo; - } - set - { - if (value == _CurrentSourceInfo) return; + /// + /// Event that is raised when the current source information changes. + /// + public event SourceInfoChangeHandler CurrentSourceChange; - var handler = CurrentSourceChange; + /// + /// Gets or sets the key of the current source information. + /// + public string CurrentSourceInfoKey { get; set; } - if (handler != null) - handler(_CurrentSourceInfo, ChangeType.WillChange); + /// + /// Gets or sets the current source information for the display. + /// + public SourceListItem CurrentSourceInfo + { + get + { + return _CurrentSourceInfo; + } + set + { + if (value == _CurrentSourceInfo) return; - _CurrentSourceInfo = value; + var handler = CurrentSourceChange; - if (handler != null) - handler(_CurrentSourceInfo, ChangeType.DidChange); - } - } - SourceListItem _CurrentSourceInfo; + if (handler != null) + handler(_CurrentSourceInfo, ChangeType.WillChange); + _CurrentSourceInfo = value; + + if (handler != null) + handler(_CurrentSourceInfo, ChangeType.DidChange); + } + } + SourceListItem _CurrentSourceInfo; + + /// + public Dictionary CurrentSources { get; private set; } + + /// + public Dictionary CurrentSourceKeys { get; private set; } + + /// + /// Gets feedback indicating whether the display is currently cooling down after being powered off. + /// public BoolFeedback IsCoolingDownFeedback { get; protected set; } + + /// + /// Gets feedback indicating whether the display is currently warming up after being powered on. + /// public BoolFeedback IsWarmingUpFeedback { get; private set; } - public UsageTracking UsageTracker { get; set; } + /// + /// Gets or sets the usage tracking instance for monitoring display usage statistics. + /// + public UsageTracking UsageTracker { get; set; } + /// + /// Gets or sets the warmup time in milliseconds for the display to become ready after power on. + /// public uint WarmupTime { get; set; } + + /// + /// Gets or sets the cooldown time in milliseconds for the display to fully power down. + /// public uint CooldownTime { get; set; } /// - /// Bool Func that will provide a value for the PowerIsOn Output. Must be implemented - /// by concrete sub-classes + /// Abstract function that must be implemented by derived classes to provide the cooling down feedback value. + /// Must be implemented by concrete sub-classes. /// abstract protected Func IsCoolingDownFeedbackFunc { get; } - abstract protected Func IsWarmingUpFeedbackFunc { get; } - + /// + /// Abstract function that must be implemented by derived classes to provide the warming up feedback value. + /// Must be implemented by concrete sub-classes. + /// + abstract protected Func IsWarmingUpFeedbackFunc { get; } + + /// + /// Timer used for managing display warmup timing. + /// protected CTimer WarmupTimer; + + /// + /// Timer used for managing display cooldown timing. + /// protected CTimer CooldownTimer; #region IRoutingInputs Members + /// + /// Gets the collection of input ports available on this display device. + /// public RoutingPortCollection InputPorts { get; private set; } #endregion - protected DisplayBase(string key, string name) - : base(key, name) + /// + /// Initializes a new instance of the DisplayBase class. + /// + /// The unique key identifier for this display device. + /// The friendly name for this display device. + protected DisplayBase(string key, string name) + : base(key, name) { IsCoolingDownFeedback = new BoolFeedback("IsCoolingDown", IsCoolingDownFeedbackFunc); IsWarmingUpFeedback = new BoolFeedback("IsWarmingUp", IsWarmingUpFeedbackFunc); InputPorts = new RoutingPortCollection(); + CurrentSources = new Dictionary + { + { eRoutingSignalType.Audio, null }, + { eRoutingSignalType.Video, null }, + }; + + CurrentSourceKeys = new Dictionary + { + { eRoutingSignalType.Audio, string.Empty }, + { eRoutingSignalType.Video, string.Empty }, + }; } + /// + /// Powers on the display device. Must be implemented by derived classes. + /// public abstract void PowerOn(); + + /// + /// Powers off the display device. Must be implemented by derived classes. + /// public abstract void PowerOff(); + + /// + /// Toggles the power state of the display device. Must be implemented by derived classes. + /// public abstract void PowerToggle(); - public virtual FeedbackCollection Feedbacks + /// + /// Gets the collection of feedback objects for this display device. + /// + public virtual FeedbackCollection Feedbacks { get { - return new FeedbackCollection + return new FeedbackCollection { IsCoolingDownFeedback, IsWarmingUpFeedback @@ -112,30 +201,50 @@ namespace PepperDash.Essentials.Devices.Common.Displays } } - public abstract void ExecuteSwitch(object selector); + /// + /// Executes a switch to the specified input on the display device. Must be implemented by derived classes. + /// + /// The selector object that identifies which input to switch to. + public abstract void ExecuteSwitch(object selector); - protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, uint joinStart, string joinMapKey, - EiscApiAdvanced bridge) - { - var joinMap = new DisplayControllerJoinMap(joinStart); + /// + /// Links the display device to an API using a trilist, join start, join map key, and bridge. + /// This overload uses serialized join map configuration. + /// + /// The display device to link. + /// The BasicTriList for communication. + /// The starting join number for the device. + /// The key for the join map configuration. + /// The EISC API bridge instance. + protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, uint joinStart, string joinMapKey, + EiscApiAdvanced bridge) + { + var joinMap = new DisplayControllerJoinMap(joinStart); - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - if (!string.IsNullOrEmpty(joinMapSerialized)) - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.LogMessage(LogEventLevel.Information,this,"Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } LinkDisplayToApi(displayDevice, trilist, joinMap); - } + } + /// + /// Links the display device to an API using a trilist and join map. + /// This overload uses a pre-configured join map instance. + /// + /// The display device to link. + /// The BasicTriList for communication. + /// The join map configuration for the device. protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, DisplayControllerJoinMap joinMap) { Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); @@ -268,68 +377,96 @@ namespace PepperDash.Essentials.Devices.Common.Displays volumeDisplayWithFeedback.MuteFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.VolumeMuteOff.JoinNumber]); } - } + } - public abstract class TwoWayDisplayBase : DisplayBase, IRoutingFeedback, IHasPowerControlWithFeedback + /// + /// Abstract base class for two-way display devices that provide feedback capabilities. + /// Extends DisplayBase with routing feedback and power control feedback functionality. + /// + public abstract class TwoWayDisplayBase : DisplayBase, IRoutingFeedback, IHasPowerControlWithFeedback { - public StringFeedback CurrentInputFeedback { get; private set; } + /// + /// Gets feedback for the current input selection on the display. + /// + public StringFeedback CurrentInputFeedback { get; private set; } - abstract protected Func CurrentInputFeedbackFunc { get; } + /// + /// Abstract function that must be implemented by derived classes to provide the current input feedback value. + /// Must be implemented by concrete sub-classes. + /// + abstract protected Func CurrentInputFeedbackFunc { get; } - public BoolFeedback PowerIsOnFeedback { get; protected set; } + /// + /// Gets feedback indicating whether the display is currently powered on. + /// + public BoolFeedback PowerIsOnFeedback { get; protected set; } - abstract protected Func PowerIsOnFeedbackFunc { get; } + /// + /// Abstract function that must be implemented by derived classes to provide the power state feedback value. + /// Must be implemented by concrete sub-classes. + /// + abstract protected Func PowerIsOnFeedbackFunc { get; } - - public static MockDisplay DefaultDisplay - { - get + /// + /// Gets the default mock display instance for testing and development purposes. + /// + public static MockDisplay DefaultDisplay + { + get { if (_DefaultDisplay == null) _DefaultDisplay = new MockDisplay("default", "Default Display"); return _DefaultDisplay; - } + } } static MockDisplay _DefaultDisplay; + /// + /// Initializes a new instance of the TwoWayDisplayBase class. + /// + /// The unique key identifier for this display device. + /// The friendly name for this display device. public TwoWayDisplayBase(string key, string name) : base(key, name) { - CurrentInputFeedback = new StringFeedback(CurrentInputFeedbackFunc); + CurrentInputFeedback = new StringFeedback(CurrentInputFeedbackFunc); WarmupTime = 7000; CooldownTime = 15000; - PowerIsOnFeedback = new BoolFeedback("PowerOnFeedback", PowerIsOnFeedbackFunc); + PowerIsOnFeedback = new BoolFeedback("PowerOnFeedback", PowerIsOnFeedbackFunc); - Feedbacks.Add(CurrentInputFeedback); - Feedbacks.Add(PowerIsOnFeedback); + Feedbacks.Add(CurrentInputFeedback); + Feedbacks.Add(PowerIsOnFeedback); - PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange; + PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange; } - void PowerIsOnFeedback_OutputChange(object sender, EventArgs e) - { - if (UsageTracker != null) - { - if (PowerIsOnFeedback.BoolValue) - UsageTracker.StartDeviceUsage(); - else - UsageTracker.EndDeviceUsage(); - } - } + void PowerIsOnFeedback_OutputChange(object sender, EventArgs e) + { + if (UsageTracker != null) + { + if (PowerIsOnFeedback.BoolValue) + UsageTracker.StartDeviceUsage(); + else + UsageTracker.EndDeviceUsage(); + } + } - public event EventHandler NumericSwitchChange; + /// + /// Event that is raised when a numeric switch change occurs on the display. + /// + public event EventHandler NumericSwitchChange; - /// - /// Raise an event when the status of a switch object changes. - /// - /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType - protected void OnSwitchChange(RoutingNumericEventArgs e) - { - var newEvent = NumericSwitchChange; - if (newEvent != null) newEvent(this, e); - } + /// + /// Raise an event when the status of a switch object changes. + /// + /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType + protected void OnSwitchChange(RoutingNumericEventArgs e) + { + var newEvent = NumericSwitchChange; + if (newEvent != null) newEvent(this, e); + } } } \ No newline at end of file