mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-08 01:04:56 +00:00
Merge branch 'main' into feature/add-IHasCamerasMessenger
This commit is contained in:
@@ -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
|
||||
/// <summary>
|
||||
/// Abstract base class for display devices that provides common display functionality
|
||||
/// including power control, input switching, and routing capabilities.
|
||||
/// </summary>
|
||||
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;
|
||||
/// <summary>
|
||||
/// Gets or sets the current input port that is selected on the display.
|
||||
/// </summary>
|
||||
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;
|
||||
/// <summary>
|
||||
/// Event that is raised when the input changes on the display.
|
||||
/// </summary>
|
||||
public event InputChangedEventHandler InputChanged;
|
||||
|
||||
public string CurrentSourceInfoKey { get; set; }
|
||||
public SourceListItem CurrentSourceInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
return _CurrentSourceInfo;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == _CurrentSourceInfo) return;
|
||||
/// <summary>
|
||||
/// Event that is raised when the current source information changes.
|
||||
/// </summary>
|
||||
public event SourceInfoChangeHandler CurrentSourceChange;
|
||||
|
||||
var handler = CurrentSourceChange;
|
||||
/// <summary>
|
||||
/// Gets or sets the key of the current source information.
|
||||
/// </summary>
|
||||
public string CurrentSourceInfoKey { get; set; }
|
||||
|
||||
if (handler != null)
|
||||
handler(_CurrentSourceInfo, ChangeType.WillChange);
|
||||
/// <summary>
|
||||
/// Gets or sets the current source information for the display.
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<eRoutingSignalType, SourceListItem> CurrentSources { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<eRoutingSignalType, string> CurrentSourceKeys { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets feedback indicating whether the display is currently cooling down after being powered off.
|
||||
/// </summary>
|
||||
public BoolFeedback IsCoolingDownFeedback { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets feedback indicating whether the display is currently warming up after being powered on.
|
||||
/// </summary>
|
||||
public BoolFeedback IsWarmingUpFeedback { get; private set; }
|
||||
|
||||
public UsageTracking UsageTracker { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the usage tracking instance for monitoring display usage statistics.
|
||||
/// </summary>
|
||||
public UsageTracking UsageTracker { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the warmup time in milliseconds for the display to become ready after power on.
|
||||
/// </summary>
|
||||
public uint WarmupTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the cooldown time in milliseconds for the display to fully power down.
|
||||
/// </summary>
|
||||
public uint CooldownTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
abstract protected Func<bool> IsCoolingDownFeedbackFunc { get; }
|
||||
abstract protected Func<bool> IsWarmingUpFeedbackFunc { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Abstract function that must be implemented by derived classes to provide the warming up feedback value.
|
||||
/// Must be implemented by concrete sub-classes.
|
||||
/// </summary>
|
||||
abstract protected Func<bool> IsWarmingUpFeedbackFunc { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Timer used for managing display warmup timing.
|
||||
/// </summary>
|
||||
protected CTimer WarmupTimer;
|
||||
|
||||
/// <summary>
|
||||
/// Timer used for managing display cooldown timing.
|
||||
/// </summary>
|
||||
protected CTimer CooldownTimer;
|
||||
|
||||
#region IRoutingInputs Members
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of input ports available on this display device.
|
||||
/// </summary>
|
||||
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
protected DisplayBase(string key, string name)
|
||||
: base(key, name)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the DisplayBase class.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key identifier for this display device.</param>
|
||||
/// <param name="name">The friendly name for this display device.</param>
|
||||
protected DisplayBase(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
IsCoolingDownFeedback = new BoolFeedback("IsCoolingDown", IsCoolingDownFeedbackFunc);
|
||||
IsWarmingUpFeedback = new BoolFeedback("IsWarmingUp", IsWarmingUpFeedbackFunc);
|
||||
|
||||
InputPorts = new RoutingPortCollection<RoutingInputPort>();
|
||||
|
||||
CurrentSources = new Dictionary<eRoutingSignalType, SourceListItem>
|
||||
{
|
||||
{ eRoutingSignalType.Audio, null },
|
||||
{ eRoutingSignalType.Video, null },
|
||||
};
|
||||
|
||||
CurrentSourceKeys = new Dictionary<eRoutingSignalType, string>
|
||||
{
|
||||
{ eRoutingSignalType.Audio, string.Empty },
|
||||
{ eRoutingSignalType.Video, string.Empty },
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Powers on the display device. Must be implemented by derived classes.
|
||||
/// </summary>
|
||||
public abstract void PowerOn();
|
||||
|
||||
/// <summary>
|
||||
/// Powers off the display device. Must be implemented by derived classes.
|
||||
/// </summary>
|
||||
public abstract void PowerOff();
|
||||
|
||||
/// <summary>
|
||||
/// Toggles the power state of the display device. Must be implemented by derived classes.
|
||||
/// </summary>
|
||||
public abstract void PowerToggle();
|
||||
|
||||
public virtual FeedbackCollection<Feedback> Feedbacks
|
||||
/// <summary>
|
||||
/// Gets the collection of feedback objects for this display device.
|
||||
/// </summary>
|
||||
public virtual FeedbackCollection<Feedback> Feedbacks
|
||||
{
|
||||
get
|
||||
{
|
||||
return new FeedbackCollection<Feedback>
|
||||
return new FeedbackCollection<Feedback>
|
||||
{
|
||||
IsCoolingDownFeedback,
|
||||
IsWarmingUpFeedback
|
||||
@@ -112,30 +201,50 @@ namespace PepperDash.Essentials.Devices.Common.Displays
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void ExecuteSwitch(object selector);
|
||||
/// <summary>
|
||||
/// Executes a switch to the specified input on the display device. Must be implemented by derived classes.
|
||||
/// </summary>
|
||||
/// <param name="selector">The selector object that identifies which input to switch to.</param>
|
||||
public abstract void ExecuteSwitch(object selector);
|
||||
|
||||
protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, uint joinStart, string joinMapKey,
|
||||
EiscApiAdvanced bridge)
|
||||
{
|
||||
var joinMap = new DisplayControllerJoinMap(joinStart);
|
||||
/// <summary>
|
||||
/// Links the display device to an API using a trilist, join start, join map key, and bridge.
|
||||
/// This overload uses serialized join map configuration.
|
||||
/// </summary>
|
||||
/// <param name="displayDevice">The display device to link.</param>
|
||||
/// <param name="trilist">The BasicTriList for communication.</param>
|
||||
/// <param name="joinStart">The starting join number for the device.</param>
|
||||
/// <param name="joinMapKey">The key for the join map configuration.</param>
|
||||
/// <param name="bridge">The EISC API bridge instance.</param>
|
||||
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<DisplayControllerJoinMap>(joinMapSerialized);
|
||||
if (!string.IsNullOrEmpty(joinMapSerialized))
|
||||
joinMap = JsonConvert.DeserializeObject<DisplayControllerJoinMap>(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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Links the display device to an API using a trilist and join map.
|
||||
/// This overload uses a pre-configured join map instance.
|
||||
/// </summary>
|
||||
/// <param name="displayDevice">The display device to link.</param>
|
||||
/// <param name="trilist">The BasicTriList for communication.</param>
|
||||
/// <param name="joinMap">The join map configuration for the device.</param>
|
||||
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
|
||||
/// <summary>
|
||||
/// Abstract base class for two-way display devices that provide feedback capabilities.
|
||||
/// Extends DisplayBase with routing feedback and power control feedback functionality.
|
||||
/// </summary>
|
||||
public abstract class TwoWayDisplayBase : DisplayBase, IRoutingFeedback, IHasPowerControlWithFeedback
|
||||
{
|
||||
public StringFeedback CurrentInputFeedback { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets feedback for the current input selection on the display.
|
||||
/// </summary>
|
||||
public StringFeedback CurrentInputFeedback { get; private set; }
|
||||
|
||||
abstract protected Func<string> CurrentInputFeedbackFunc { get; }
|
||||
/// <summary>
|
||||
/// Abstract function that must be implemented by derived classes to provide the current input feedback value.
|
||||
/// Must be implemented by concrete sub-classes.
|
||||
/// </summary>
|
||||
abstract protected Func<string> CurrentInputFeedbackFunc { get; }
|
||||
|
||||
public BoolFeedback PowerIsOnFeedback { get; protected set; }
|
||||
/// <summary>
|
||||
/// Gets feedback indicating whether the display is currently powered on.
|
||||
/// </summary>
|
||||
public BoolFeedback PowerIsOnFeedback { get; protected set; }
|
||||
|
||||
abstract protected Func<bool> PowerIsOnFeedbackFunc { get; }
|
||||
/// <summary>
|
||||
/// Abstract function that must be implemented by derived classes to provide the power state feedback value.
|
||||
/// Must be implemented by concrete sub-classes.
|
||||
/// </summary>
|
||||
abstract protected Func<bool> PowerIsOnFeedbackFunc { get; }
|
||||
|
||||
|
||||
public static MockDisplay DefaultDisplay
|
||||
{
|
||||
get
|
||||
/// <summary>
|
||||
/// Gets the default mock display instance for testing and development purposes.
|
||||
/// </summary>
|
||||
public static MockDisplay DefaultDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_DefaultDisplay == null)
|
||||
_DefaultDisplay = new MockDisplay("default", "Default Display");
|
||||
return _DefaultDisplay;
|
||||
}
|
||||
}
|
||||
}
|
||||
static MockDisplay _DefaultDisplay;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the TwoWayDisplayBase class.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key identifier for this display device.</param>
|
||||
/// <param name="name">The friendly name for this display device.</param>
|
||||
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<RoutingNumericEventArgs> NumericSwitchChange;
|
||||
/// <summary>
|
||||
/// Event that is raised when a numeric switch change occurs on the display.
|
||||
/// </summary>
|
||||
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
|
||||
|
||||
/// <summary>
|
||||
/// Raise an event when the status of a switch object changes.
|
||||
/// </summary>
|
||||
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
|
||||
protected void OnSwitchChange(RoutingNumericEventArgs e)
|
||||
{
|
||||
var newEvent = NumericSwitchChange;
|
||||
if (newEvent != null) newEvent(this, e);
|
||||
}
|
||||
/// <summary>
|
||||
/// Raise an event when the status of a switch object changes.
|
||||
/// </summary>
|
||||
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
|
||||
protected void OnSwitchChange(RoutingNumericEventArgs e)
|
||||
{
|
||||
var newEvent = NumericSwitchChange;
|
||||
if (newEvent != null) newEvent(this, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user