mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-01-11 19:44:52 +00:00
Merge pull request #1293 from PepperDash/to-dev
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -393,4 +393,5 @@ essentials-framework/Essentials Interfaces/PepperDash_Essentials_Interfaces/Pepp
|
|||||||
/._PepperDash.Essentials.sln
|
/._PepperDash.Essentials.sln
|
||||||
.vscode/settings.json
|
.vscode/settings.json
|
||||||
_site/
|
_site/
|
||||||
api/
|
api/
|
||||||
|
*.DS_Store
|
||||||
|
|||||||
9
.vscode/extensions.json
vendored
Normal file
9
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"ms-dotnettools.vscode-dotnet-runtime",
|
||||||
|
"ms-dotnettools.csharp",
|
||||||
|
"ms-dotnettools.csdevkit",
|
||||||
|
"vivaxy.vscode-conventional-commits",
|
||||||
|
"mhutchie.git-graph"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -2,7 +2,14 @@
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||||
{
|
{
|
||||||
public interface IDisplay: IHasFeedback, IRoutingSinkWithSwitching, IHasPowerControl, IWarmingCooling, IUsageTracking, IKeyName
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
public interface IDisplay : IHasFeedback, IRoutingSinkWithSwitching, IHasPowerControl, IWarmingCooling, IUsageTracking, IKeyName
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for devices that provide audio meter feedback.
|
||||||
|
/// This interface is used to standardize access to meter feedback across different devices.
|
||||||
|
/// </summary>
|
||||||
|
public interface IMeterFeedback
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the meter feedback for the device.
|
||||||
|
/// This property provides an IntFeedback that represents the current audio level or meter value.
|
||||||
|
/// </summary>
|
||||||
|
IntFeedback MeterFeedback { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using Crestron.SimplSharpPro;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
@@ -33,11 +35,11 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
|||||||
|
|
||||||
string SystemUuid { get; }
|
string SystemUuid { get; }
|
||||||
|
|
||||||
BoolFeedback ApiOnlineAndAuthorized { get;}
|
BoolFeedback ApiOnlineAndAuthorized { get; }
|
||||||
|
|
||||||
void SendMessageObject(IMobileControlMessage o);
|
void SendMessageObject(IMobileControlMessage o);
|
||||||
|
|
||||||
void AddAction<T>(T messenger, Action<string, string, JToken> action) where T:IMobileControlMessenger;
|
void AddAction<T>(T messenger, Action<string, string, JToken> action) where T : IMobileControlMessenger;
|
||||||
|
|
||||||
void RemoveAction(string key);
|
void RemoveAction(string key);
|
||||||
|
|
||||||
@@ -45,14 +47,14 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
|||||||
|
|
||||||
bool CheckForDeviceMessenger(string key);
|
bool CheckForDeviceMessenger(string key);
|
||||||
|
|
||||||
IMobileControlRoomMessenger GetRoomMessenger(string key);
|
IMobileControlRoomMessenger GetRoomMessenger(string key);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Describes a mobile control messenger
|
/// Describes a mobile control messenger
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IMobileControlMessenger: IKeyed
|
public interface IMobileControlMessenger : IKeyed
|
||||||
{
|
{
|
||||||
IMobileControl AppServerController { get; }
|
IMobileControl AppServerController { get; }
|
||||||
string MessagePath { get; }
|
string MessagePath { get; }
|
||||||
@@ -104,16 +106,47 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
|||||||
|
|
||||||
public interface IMobileControlAction
|
public interface IMobileControlAction
|
||||||
{
|
{
|
||||||
IMobileControlMessenger Messenger { get; }
|
IMobileControlMessenger Messenger { get; }
|
||||||
|
|
||||||
Action<string,string, JToken> Action { get; }
|
Action<string, string, JToken> Action { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes a MobileControl Touchpanel Controller
|
||||||
|
/// </summary>
|
||||||
public interface IMobileControlTouchpanelController : IKeyed
|
public interface IMobileControlTouchpanelController : IKeyed
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The default room key for the controller
|
||||||
|
/// </summary>
|
||||||
string DefaultRoomKey { get; }
|
string DefaultRoomKey { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the application URL for the controller
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="url">The application URL</param>
|
||||||
void SetAppUrl(string url);
|
void SetAppUrl(string url);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the controller uses a direct server connection
|
||||||
|
/// </summary>
|
||||||
bool UseDirectServer { get; }
|
bool UseDirectServer { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the controller is a Zoom Room controller
|
||||||
|
/// </summary>
|
||||||
bool ZoomRoomController { get; }
|
bool ZoomRoomController { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes a MobileControl Crestron Touchpanel Controller
|
||||||
|
/// This interface extends the IMobileControlTouchpanelController to include connected IP information
|
||||||
|
/// </summary>
|
||||||
|
public interface IMobileControlCrestronTouchpanelController : IMobileControlTouchpanelController
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a collection of connected IP information for the touchpanel controller
|
||||||
|
/// </summary>
|
||||||
|
ReadOnlyCollection<ConnectedIpInformation> ConnectedIps { get; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
using Crestron.SimplSharpPro.DM.Streaming;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a collection of network port information and provides notifications when the information changes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This interface is designed to provide access to a list of network port details and to notify
|
||||||
|
/// subscribers when the port information is updated. Implementations of this interface should ensure that the <see
|
||||||
|
/// cref="PortInformationChanged"/> event is raised whenever the <see cref="NetworkPorts"/> collection
|
||||||
|
/// changes.</remarks>
|
||||||
|
public interface INvxNetworkPortInformation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when the port information changes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This event is triggered whenever there is a change in the port information, such as
|
||||||
|
/// updates to port settings or status. Subscribers can handle this event to respond to such changes.</remarks>
|
||||||
|
event EventHandler PortInformationChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the collection of network port information associated with the current instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>The collection provides information about the network ports, such as their status,
|
||||||
|
/// configuration, or other relevant details. The returned list is read-only and cannot be modified
|
||||||
|
/// directly.</remarks>
|
||||||
|
List<NvxNetworkPortInformation> NetworkPorts { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents information about a network port, including its configuration and associated system details.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This class provides properties to describe various attributes of a network port, such as its
|
||||||
|
/// name, description, VLAN configuration, and management IP address. It is typically used to store and retrieve
|
||||||
|
/// metadata about network ports in a managed environment.</remarks>
|
||||||
|
public class NvxNetworkPortInformation
|
||||||
|
{
|
||||||
|
private readonly DmNvxBaseClass.DmNvx35xNetwork.DmNvxNetworkLldpPort port;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the index of the device port.
|
||||||
|
/// </summary>
|
||||||
|
public uint DevicePortIndex { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of the port used for communication.
|
||||||
|
/// </summary>
|
||||||
|
public string PortName => port.PortNameFeedback.StringValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the description of the port.
|
||||||
|
/// </summary>
|
||||||
|
public string PortDescription => port.PortNameDescriptionFeedback.StringValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of the VLAN (Virtual Local Area Network).
|
||||||
|
/// </summary>
|
||||||
|
public string VlanName => port.VlanNameFeedback.StringValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the IP management address associated with the port.
|
||||||
|
/// </summary>
|
||||||
|
public string IpManagementAddress => port.IpManagementAddressFeedback.StringValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the system as reported by the associated port.
|
||||||
|
/// </summary>
|
||||||
|
public string SystemName => port.SystemNameFeedback.StringValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the description of the system name.
|
||||||
|
/// </summary>
|
||||||
|
public string SystemNameDescription => port.SystemNameDescriptionFeedback.StringValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="NvxNetworkPortInformation"/> class with the specified network port
|
||||||
|
/// and device port index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="port">The network port associated with the device. Cannot be <see langword="null"/>.</param>
|
||||||
|
/// <param name="devicePortIndex">The index of the device port.</param>
|
||||||
|
/// <exception cref="ArgumentNullException">Thrown if <paramref name="port"/> is <see langword="null"/>.</exception>
|
||||||
|
public NvxNetworkPortInformation(DmNvxBaseClass.DmNvx35xNetwork.DmNvxNetworkLldpPort port, uint devicePortIndex)
|
||||||
|
{
|
||||||
|
this.port = port ?? throw new ArgumentNullException(nameof(port), "Port cannot be null");
|
||||||
|
DevicePortIndex = devicePortIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for devices that provide state feedback.
|
||||||
|
/// This interface is used to standardize access to state feedback across different devices.
|
||||||
|
/// </summary>
|
||||||
|
public interface IStateFeedback
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the state feedback for the device.
|
||||||
|
/// This property provides a BoolFeedback that represents the current state (on/off) of the device.
|
||||||
|
/// </summary>
|
||||||
|
BoolFeedback StateFeedback { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,19 +5,34 @@ using PepperDash.Essentials.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
public class DestinationListItem
|
public class DestinationListItem
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the key identifier for the sink device that this destination represents.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("sinkKey")]
|
[JsonProperty("sinkKey")]
|
||||||
public string SinkKey { get; set; }
|
public string SinkKey { get; set; }
|
||||||
|
|
||||||
private EssentialsDevice _sinkDevice;
|
private EssentialsDevice _sinkDevice;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the actual device instance for this destination.
|
||||||
|
/// Lazily loads the device from the DeviceManager using the SinkKey.
|
||||||
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public EssentialsDevice SinkDevice
|
public EssentialsDevice SinkDevice
|
||||||
{
|
{
|
||||||
get { return _sinkDevice ?? (_sinkDevice = DeviceManager.GetDeviceForKey(SinkKey) as EssentialsDevice); }
|
get { return _sinkDevice ?? (_sinkDevice = DeviceManager.GetDeviceForKey(SinkKey) as EssentialsDevice); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("preferredName")]
|
[JsonProperty("preferredName")]
|
||||||
public string PreferredName
|
public string PreferredName
|
||||||
{
|
{
|
||||||
@@ -32,31 +47,78 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the custom name for this destination.
|
||||||
|
/// If set, this name will be used as the PreferredName instead of the device name.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("name")]
|
[JsonProperty("name")]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this destination should be included in destination lists.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("includeInDestinationList")]
|
[JsonProperty("includeInDestinationList")]
|
||||||
public bool IncludeInDestinationList { get; set; }
|
public bool IncludeInDestinationList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the display order for this destination in lists.
|
||||||
|
/// Lower values appear first in sorted lists.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("order")]
|
[JsonProperty("order")]
|
||||||
public int Order { get; set; }
|
public int Order { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the surface location identifier for this destination.
|
||||||
|
/// Used to specify which surface or screen this destination is located on.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("surfaceLocation")]
|
[JsonProperty("surfaceLocation")]
|
||||||
public int SurfaceLocation { get; set; }
|
public int SurfaceLocation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the vertical location position for this destination.
|
||||||
|
/// Used for spatial positioning in multi-display configurations.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("verticalLocation")]
|
[JsonProperty("verticalLocation")]
|
||||||
public int VerticalLocation { get; set; }
|
public int VerticalLocation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the horizontal location position for this destination.
|
||||||
|
/// Used for spatial positioning in multi-display configurations.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("horizontalLocation")]
|
[JsonProperty("horizontalLocation")]
|
||||||
public int HorizontalLocation { get; set; }
|
public int HorizontalLocation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the signal type that this destination can receive (Audio, Video, AudioVideo, etc.).
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("sinkType")]
|
[JsonProperty("sinkType")]
|
||||||
public eRoutingSignalType SinkType { get; set; }
|
public eRoutingSignalType SinkType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this destination is used for codec content sharing.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("isCodecContentDestination")]
|
[JsonProperty("isCodecContentDestination")]
|
||||||
public bool isCodecContentDestination { get; set; }
|
public bool isCodecContentDestination { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this destination is used for program audio output.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("isProgramAudioDestination")]
|
[JsonProperty("isProgramAudioDestination")]
|
||||||
public bool isProgramAudioDestination { get; set; }
|
public bool isProgramAudioDestination { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("supportsUsb")]
|
||||||
|
public bool SupportsUsb { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The key of the destination port associated with this destination item
|
||||||
|
/// This is used to identify the specific port on the destination device that this item refers to for advanced routing
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("destinationPortKey")]
|
||||||
|
public string DestinationPortKey { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,10 +9,15 @@ using PepperDash.Essentials.Core.Devices;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a level control item in a list, which can be used to control volume or mute functionality.
|
||||||
|
/// </summary>
|
||||||
public class LevelControlListItem : AudioControlListItemBase
|
public class LevelControlListItem : AudioControlListItemBase
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A reference to the IBasicVolumeWithFeedback device for control.
|
||||||
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IBasicVolumeWithFeedback LevelControl
|
public IBasicVolumeWithFeedback LevelControl
|
||||||
{
|
{
|
||||||
@@ -55,7 +60,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if(string.IsNullOrEmpty(ItemKey)) return ParentDeviceKey;
|
if (string.IsNullOrEmpty(ItemKey)) return ParentDeviceKey;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return DeviceManager.AllDevices.
|
return DeviceManager.AllDevices.
|
||||||
@@ -70,13 +75,39 @@ namespace PepperDash.Essentials.Core
|
|||||||
[JsonProperty("type")]
|
[JsonProperty("type")]
|
||||||
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
|
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
|
||||||
public eLevelControlType Type { get; set; }
|
public eLevelControlType Type { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if the item is a mic or not.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("isMic", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public bool? IsMic { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if the item should show the raw level in the UI.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("showRawLevel", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public bool? ShowRawLevel { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates the type of level control item.
|
||||||
|
/// </summary>
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum eLevelControlType
|
public enum eLevelControlType
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the item is a level control only
|
||||||
|
/// </summary>
|
||||||
Level = 1,
|
Level = 1,
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the item is a mute control only
|
||||||
|
/// </summary>
|
||||||
Mute = 2,
|
Mute = 2,
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the item is both a level and mute control
|
||||||
|
/// </summary>
|
||||||
LevelAndMute = Level | Mute,
|
LevelAndMute = Level | Mute,
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,29 @@
|
|||||||
using Newtonsoft.Json;
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// 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.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum eSourceListItemType
|
public enum eSourceListItemType
|
||||||
{
|
{
|
||||||
Route, Off, Other, SomethingAwesomerThanThese
|
/// <summary>
|
||||||
|
/// Represents a typical route.
|
||||||
|
/// </summary>
|
||||||
|
Route,
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an off route.
|
||||||
|
/// </summary>
|
||||||
|
Off,
|
||||||
|
/// <summary>
|
||||||
|
/// Represents some other type of route
|
||||||
|
/// </summary>
|
||||||
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -18,6 +31,9 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SourceListItem
|
public class SourceListItem
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The key of the source item, which is used to identify it in the DeviceManager
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("sourceKey")]
|
[JsonProperty("sourceKey")]
|
||||||
public string SourceKey { get; set; }
|
public string SourceKey { get; set; }
|
||||||
|
|
||||||
@@ -117,6 +133,9 @@ namespace PepperDash.Essentials.Core
|
|||||||
[JsonProperty("disableRoutedSharing")]
|
[JsonProperty("disableRoutedSharing")]
|
||||||
public bool DisableRoutedSharing { get; set; }
|
public bool DisableRoutedSharing { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("destinations")]
|
[JsonProperty("destinations")]
|
||||||
public List<eSourceListItemDestinationTypes> Destinations { get; set; }
|
public List<eSourceListItemDestinationTypes> Destinations { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -149,31 +168,76 @@ namespace PepperDash.Essentials.Core
|
|||||||
[JsonProperty("disableSimpleRouting")]
|
[JsonProperty("disableSimpleRouting")]
|
||||||
public bool DisableSimpleRouting { get; set; }
|
public bool DisableSimpleRouting { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The key of the device that provides video sync for this source item
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("syncProviderDeviceKey")]
|
||||||
|
public string SyncProviderDeviceKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if the source supports USB connections
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("supportsUsb")]
|
||||||
|
public bool SupportsUsb { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The key of the source port associated with this source item
|
||||||
|
/// This is used to identify the specific port on the source device that this item refers to for advanced routing
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("sourcePortKey")]
|
||||||
|
public string SourcePortKey { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default constructor for SourceListItem, initializes the Icon to "Blank"
|
||||||
|
/// </summary>
|
||||||
public SourceListItem()
|
public SourceListItem()
|
||||||
{
|
{
|
||||||
Icon = "Blank";
|
Icon = "Blank";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a string representation of the SourceListItem, including the SourceKey and Name
|
||||||
|
/// </summary>
|
||||||
|
/// <returns> A string representation of the SourceListItem</returns>
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{SourceKey}:{Name}";
|
return $"{SourceKey}:{Name}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a route in a source list item, which defines the source and destination keys and the type of signal being routed
|
||||||
|
/// </summary>
|
||||||
public class SourceRouteListItem
|
public class SourceRouteListItem
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The key of the source device to route from
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("sourceKey")]
|
[JsonProperty("sourceKey")]
|
||||||
public string SourceKey { get; set; }
|
public string SourceKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The key of the source port to route from
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("sourcePortKey")]
|
[JsonProperty("sourcePortKey")]
|
||||||
public string SourcePortKey { get; set; }
|
public string SourcePortKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The key of the destination device to route to
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("destinationKey")]
|
[JsonProperty("destinationKey")]
|
||||||
public string DestinationKey { get; set; }
|
public string DestinationKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The key of the destination port to route to
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("destinationPortKey")]
|
[JsonProperty("destinationPortKey")]
|
||||||
public string DestinationPortKey { get; set; }
|
public string DestinationPortKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of signal being routed, such as audio or video
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("type")]
|
[JsonProperty("type")]
|
||||||
public eRoutingSignalType Type { get; set; }
|
public eRoutingSignalType Type { get; set; }
|
||||||
}
|
}
|
||||||
@@ -183,15 +247,85 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public enum eSourceListItemDestinationTypes
|
public enum eSourceListItemDestinationTypes
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Default display, used for the main video output in a room
|
||||||
|
/// </summary>
|
||||||
defaultDisplay,
|
defaultDisplay,
|
||||||
|
/// <summary>
|
||||||
|
/// Left display
|
||||||
|
/// </summary>
|
||||||
leftDisplay,
|
leftDisplay,
|
||||||
|
/// <summary>
|
||||||
|
/// Right display
|
||||||
|
/// </summary>
|
||||||
rightDisplay,
|
rightDisplay,
|
||||||
|
/// <summary>
|
||||||
|
/// Center display
|
||||||
|
/// </summary>
|
||||||
centerDisplay,
|
centerDisplay,
|
||||||
|
/// <summary>
|
||||||
|
/// Program audio, used for the main audio output in a room
|
||||||
|
/// </summary>
|
||||||
programAudio,
|
programAudio,
|
||||||
|
/// <summary>
|
||||||
|
/// Codec content, used for sharing content to the far end in a video call
|
||||||
|
/// </summary>
|
||||||
codecContent,
|
codecContent,
|
||||||
|
/// <summary>
|
||||||
|
/// Front left display, used for rooms with multiple displays
|
||||||
|
/// </summary>
|
||||||
frontLeftDisplay,
|
frontLeftDisplay,
|
||||||
|
/// <summary>
|
||||||
|
/// Front right display, used for rooms with multiple displays
|
||||||
|
/// </summary>
|
||||||
frontRightDisplay,
|
frontRightDisplay,
|
||||||
|
/// <summary>
|
||||||
|
/// Rear left display, used for rooms with multiple displays
|
||||||
|
/// </summary>
|
||||||
rearLeftDisplay,
|
rearLeftDisplay,
|
||||||
|
/// <summary>
|
||||||
|
/// Rear right display, used for rooms with multiple displays
|
||||||
|
/// </summary>
|
||||||
rearRightDisplay,
|
rearRightDisplay,
|
||||||
|
/// <summary>
|
||||||
|
/// Auxiliary display 1, used for additional displays in a room
|
||||||
|
/// </summary>
|
||||||
|
auxDisplay1,
|
||||||
|
/// <summary>
|
||||||
|
/// Auxiliary display 2, used for additional displays in a room
|
||||||
|
/// </summary>
|
||||||
|
auxDisplay2,
|
||||||
|
/// <summary>
|
||||||
|
/// Auxiliary display 3, used for additional displays in a room
|
||||||
|
/// </summary>
|
||||||
|
auxDisplay3,
|
||||||
|
/// <summary>
|
||||||
|
/// Auxiliary display 4, used for additional displays in a room
|
||||||
|
/// </summary>
|
||||||
|
auxDisplay4,
|
||||||
|
/// <summary>
|
||||||
|
/// Auxiliary display 5, used for additional displays in a room
|
||||||
|
/// </summary>
|
||||||
|
auxDisplay5,
|
||||||
|
/// <summary>
|
||||||
|
/// Auxiliary display 6, used for additional displays in a room
|
||||||
|
/// </summary>
|
||||||
|
auxDisplay6,
|
||||||
|
/// <summary>
|
||||||
|
/// Auxiliary display 7, used for additional displays in a room
|
||||||
|
/// </summary>
|
||||||
|
auxDisplay7,
|
||||||
|
/// <summary>
|
||||||
|
/// Auxiliary display 8, used for additional displays in a room
|
||||||
|
/// </summary>
|
||||||
|
auxDisplay8,
|
||||||
|
/// <summary>
|
||||||
|
/// Auxiliary display 9, used for additional displays in a room
|
||||||
|
/// </summary>
|
||||||
|
auxDisplay9,
|
||||||
|
/// <summary>
|
||||||
|
/// Auxiliary display 10, used for additional displays in a room
|
||||||
|
/// </summary>
|
||||||
|
auxDisplay10,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
29
src/PepperDash.Essentials.Core/Routing/ICurrentSources.cs
Normal file
29
src/PepperDash.Essentials.Core/Routing/ICurrentSources.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using PepperDash.Essentials.Core;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.Routing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The current sources for the room, keyed by eRoutingSignalType.
|
||||||
|
/// This allows for multiple sources to be tracked, such as audio and video.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// 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.
|
||||||
|
/// </remarks>
|
||||||
|
public interface ICurrentSources
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
Dictionary<eRoutingSignalType, SourceListItem> CurrentSources { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
Dictionary<eRoutingSignalType, string> CurrentSourceKeys { get; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,8 @@ using PepperDash.Essentials.Core.Routing;
|
|||||||
using PepperDash.Essentials.Core.Routing;
|
using PepperDash.Essentials.Core.Routing;
|
||||||
using PepperDash.Essentials.Core.Routing.Interfaces
|
using PepperDash.Essentials.Core.Routing.Interfaces
|
||||||
*/
|
*/
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -21,10 +23,24 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// For rooms with a single presentation source, change event
|
/// For rooms with a single presentation source, change event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("Use ICurrentSources instead")]
|
||||||
public interface IHasCurrentSourceInfoChange
|
public interface IHasCurrentSourceInfoChange
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The key for the current source info, used to look up the source in the SourceList
|
||||||
|
/// </summary>
|
||||||
string CurrentSourceInfoKey { get; set; }
|
string CurrentSourceInfoKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current source info for the room, used to look up the source in the SourceList
|
||||||
|
/// </summary>
|
||||||
SourceListItem CurrentSourceInfo { get; set; }
|
SourceListItem CurrentSourceInfo { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
event SourceInfoChangeHandler CurrentSourceChange;
|
event SourceInfoChangeHandler CurrentSourceChange;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,29 @@
|
|||||||
namespace PepperDash.Essentials.Core
|
using PepperDash.Essentials.Core.Routing;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For fixed-source endpoint devices
|
/// For fixed-source endpoint devices
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IRoutingSink : IRoutingInputs, IHasCurrentSourceInfoChange
|
public interface IRoutingSink : IRoutingInputs, IHasCurrentSourceInfoChange
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IRoutingSinkWithInputPort :IRoutingSink
|
/// <summary>
|
||||||
|
/// For fixed-source endpoint devices with an input port
|
||||||
|
/// </summary>
|
||||||
|
public interface IRoutingSinkWithInputPort : IRoutingSink
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current input port for this routing sink.
|
||||||
|
/// </summary>
|
||||||
RoutingInputPort CurrentInputPort { get; }
|
RoutingInputPort CurrentInputPort { get; }
|
||||||
}
|
}
|
||||||
/*/// <summary>
|
|
||||||
/// For fixed-source endpoint devices
|
|
||||||
/// </summary>
|
|
||||||
public interface IRoutingSink<TSelector> : IRoutingInputs<TSelector>, IHasCurrentSourceInfoChange
|
|
||||||
{
|
|
||||||
void UpdateRouteRequest<TOutputSelector>(RouteRequest<TSelector, TOutputSelector> request);
|
|
||||||
|
|
||||||
RouteRequest<TSelector, TOutputSelector> GetRouteRequest<TOutputSelector>();
|
/// <summary>
|
||||||
}*/
|
/// Interface for routing sinks that have access to the current source information.
|
||||||
|
/// </summary>
|
||||||
|
public interface IRoutingSinkWithCurrentSources : IRoutingSink, ICurrentSources
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,110 +1,199 @@
|
|||||||
using Crestron.SimplSharp;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using PepperDash.Essentials.Core.Bridges;
|
using PepperDash.Essentials.Core.Bridges;
|
||||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||||
|
using PepperDash.Essentials.Core.Routing;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Feedback = PepperDash.Essentials.Core.Feedback;
|
using Feedback = PepperDash.Essentials.Core.Feedback;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.Displays
|
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;
|
private RoutingInputPort _currentInputPort;
|
||||||
public RoutingInputPort CurrentInputPort
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _currentInputPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected set
|
/// <summary>
|
||||||
{
|
/// Gets or sets the current input port that is selected on the display.
|
||||||
if (_currentInputPort == value) return;
|
/// </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; }
|
/// <summary>
|
||||||
public SourceListItem CurrentSourceInfo
|
/// Event that is raised when the current source information changes.
|
||||||
{
|
/// </summary>
|
||||||
get
|
public event SourceInfoChangeHandler CurrentSourceChange;
|
||||||
{
|
|
||||||
return _CurrentSourceInfo;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value == _CurrentSourceInfo) return;
|
|
||||||
|
|
||||||
var handler = CurrentSourceChange;
|
/// <summary>
|
||||||
|
/// Gets or sets the key of the current source information.
|
||||||
|
/// </summary>
|
||||||
|
public string CurrentSourceInfoKey { get; set; }
|
||||||
|
|
||||||
if (handler != null)
|
/// <summary>
|
||||||
handler(_CurrentSourceInfo, ChangeType.WillChange);
|
/// 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)
|
if (handler != null)
|
||||||
handler(_CurrentSourceInfo, ChangeType.DidChange);
|
handler(_CurrentSourceInfo, ChangeType.WillChange);
|
||||||
}
|
|
||||||
}
|
|
||||||
SourceListItem _CurrentSourceInfo;
|
|
||||||
|
|
||||||
|
_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; }
|
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 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; }
|
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; }
|
public uint CooldownTime { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Bool Func that will provide a value for the PowerIsOn Output. Must be implemented
|
/// Abstract function that must be implemented by derived classes to provide the cooling down feedback value.
|
||||||
/// by concrete sub-classes
|
/// Must be implemented by concrete sub-classes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
abstract protected Func<bool> IsCoolingDownFeedbackFunc { get; }
|
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;
|
protected CTimer WarmupTimer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Timer used for managing display cooldown timing.
|
||||||
|
/// </summary>
|
||||||
protected CTimer CooldownTimer;
|
protected CTimer CooldownTimer;
|
||||||
|
|
||||||
#region IRoutingInputs Members
|
#region IRoutingInputs Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the collection of input ports available on this display device.
|
||||||
|
/// </summary>
|
||||||
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
|
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
protected DisplayBase(string key, string name)
|
/// <summary>
|
||||||
: base(key, name)
|
/// 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);
|
IsCoolingDownFeedback = new BoolFeedback("IsCoolingDown", IsCoolingDownFeedbackFunc);
|
||||||
IsWarmingUpFeedback = new BoolFeedback("IsWarmingUp", IsWarmingUpFeedbackFunc);
|
IsWarmingUpFeedback = new BoolFeedback("IsWarmingUp", IsWarmingUpFeedbackFunc);
|
||||||
|
|
||||||
InputPorts = new RoutingPortCollection<RoutingInputPort>();
|
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();
|
public abstract void PowerOn();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Powers off the display device. Must be implemented by derived classes.
|
||||||
|
/// </summary>
|
||||||
public abstract void PowerOff();
|
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 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
|
get
|
||||||
{
|
{
|
||||||
return new FeedbackCollection<Feedback>
|
return new FeedbackCollection<Feedback>
|
||||||
{
|
{
|
||||||
IsCoolingDownFeedback,
|
IsCoolingDownFeedback,
|
||||||
IsWarmingUpFeedback
|
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,
|
/// <summary>
|
||||||
EiscApiAdvanced bridge)
|
/// Links the display device to an API using a trilist, join start, join map key, and bridge.
|
||||||
{
|
/// This overload uses serialized join map configuration.
|
||||||
var joinMap = new DisplayControllerJoinMap(joinStart);
|
/// </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))
|
if (!string.IsNullOrEmpty(joinMapSerialized))
|
||||||
joinMap = JsonConvert.DeserializeObject<DisplayControllerJoinMap>(joinMapSerialized);
|
joinMap = JsonConvert.DeserializeObject<DisplayControllerJoinMap>(joinMapSerialized);
|
||||||
|
|
||||||
if (bridge != null)
|
if (bridge != null)
|
||||||
{
|
{
|
||||||
bridge.AddJoinMap(Key, joinMap);
|
bridge.AddJoinMap(Key, joinMap);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information,this,"Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
|
Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkDisplayToApi(displayDevice, trilist, joinMap);
|
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)
|
protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, DisplayControllerJoinMap joinMap)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
|
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]);
|
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; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
public static MockDisplay DefaultDisplay
|
/// Gets the default mock display instance for testing and development purposes.
|
||||||
{
|
/// </summary>
|
||||||
get
|
public static MockDisplay DefaultDisplay
|
||||||
|
{
|
||||||
|
get
|
||||||
{
|
{
|
||||||
if (_DefaultDisplay == null)
|
if (_DefaultDisplay == null)
|
||||||
_DefaultDisplay = new MockDisplay("default", "Default Display");
|
_DefaultDisplay = new MockDisplay("default", "Default Display");
|
||||||
return _DefaultDisplay;
|
return _DefaultDisplay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static MockDisplay _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)
|
public TwoWayDisplayBase(string key, string name)
|
||||||
: base(key, name)
|
: base(key, name)
|
||||||
{
|
{
|
||||||
CurrentInputFeedback = new StringFeedback(CurrentInputFeedbackFunc);
|
CurrentInputFeedback = new StringFeedback(CurrentInputFeedbackFunc);
|
||||||
|
|
||||||
WarmupTime = 7000;
|
WarmupTime = 7000;
|
||||||
CooldownTime = 15000;
|
CooldownTime = 15000;
|
||||||
|
|
||||||
PowerIsOnFeedback = new BoolFeedback("PowerOnFeedback", PowerIsOnFeedbackFunc);
|
PowerIsOnFeedback = new BoolFeedback("PowerOnFeedback", PowerIsOnFeedbackFunc);
|
||||||
|
|
||||||
Feedbacks.Add(CurrentInputFeedback);
|
Feedbacks.Add(CurrentInputFeedback);
|
||||||
Feedbacks.Add(PowerIsOnFeedback);
|
Feedbacks.Add(PowerIsOnFeedback);
|
||||||
|
|
||||||
PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange;
|
PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PowerIsOnFeedback_OutputChange(object sender, EventArgs e)
|
void PowerIsOnFeedback_OutputChange(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (UsageTracker != null)
|
if (UsageTracker != null)
|
||||||
{
|
{
|
||||||
if (PowerIsOnFeedback.BoolValue)
|
if (PowerIsOnFeedback.BoolValue)
|
||||||
UsageTracker.StartDeviceUsage();
|
UsageTracker.StartDeviceUsage();
|
||||||
else
|
else
|
||||||
UsageTracker.EndDeviceUsage();
|
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>
|
/// <summary>
|
||||||
/// Raise an event when the status of a switch object changes.
|
/// Raise an event when the status of a switch object changes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
|
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
|
||||||
protected void OnSwitchChange(RoutingNumericEventArgs e)
|
protected void OnSwitchChange(RoutingNumericEventArgs e)
|
||||||
{
|
{
|
||||||
var newEvent = NumericSwitchChange;
|
var newEvent = NumericSwitchChange;
|
||||||
if (newEvent != null) newEvent(this, e);
|
if (newEvent != null) newEvent(this, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
using Crestron.SimplSharpPro;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
|
using Crestron.SimplSharpPro;
|
||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
using Crestron.SimplSharpPro.UI;
|
using Crestron.SimplSharpPro.UI;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
@@ -10,64 +14,105 @@ using PepperDash.Essentials.Core.Config;
|
|||||||
using PepperDash.Essentials.Core.DeviceInfo;
|
using PepperDash.Essentials.Core.DeviceInfo;
|
||||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||||
using PepperDash.Essentials.Core.UI;
|
using PepperDash.Essentials.Core.UI;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Feedback = PepperDash.Essentials.Core.Feedback;
|
using Feedback = PepperDash.Essentials.Core.Feedback;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Touchpanel
|
namespace PepperDash.Essentials.Touchpanel
|
||||||
{
|
{
|
||||||
//public interface IMobileControlTouchpanelController
|
/// <summary>
|
||||||
//{
|
/// Mobile Control touchpanel controller that provides app control, Zoom integration,
|
||||||
// StringFeedback AppUrlFeedback { get; }
|
/// and mobile control functionality for Crestron touchpanels.
|
||||||
// string DefaultRoomKey { get; }
|
/// </summary>
|
||||||
// string DeviceKey { get; }
|
public class MobileControlTouchpanelController : TouchpanelBase, IHasFeedback, ITswAppControl, ITswZoomControl, IDeviceInfoProvider, IMobileControlCrestronTouchpanelController, ITheme
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
public class MobileControlTouchpanelController : TouchpanelBase, IHasFeedback, ITswAppControl, ITswZoomControl, IDeviceInfoProvider, IMobileControlTouchpanelController, ITheme
|
|
||||||
{
|
{
|
||||||
private readonly MobileControlTouchpanelProperties localConfig;
|
private readonly MobileControlTouchpanelProperties localConfig;
|
||||||
private IMobileControlRoomMessenger _bridge;
|
private IMobileControlRoomMessenger _bridge;
|
||||||
|
|
||||||
private string _appUrl;
|
private string _appUrl;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets feedback for the current application URL.
|
||||||
|
/// </summary>
|
||||||
public StringFeedback AppUrlFeedback { get; private set; }
|
public StringFeedback AppUrlFeedback { get; private set; }
|
||||||
|
|
||||||
private readonly StringFeedback QrCodeUrlFeedback;
|
private readonly StringFeedback QrCodeUrlFeedback;
|
||||||
private readonly StringFeedback McServerUrlFeedback;
|
private readonly StringFeedback McServerUrlFeedback;
|
||||||
private readonly StringFeedback UserCodeFeedback;
|
private readonly StringFeedback UserCodeFeedback;
|
||||||
|
|
||||||
private readonly BoolFeedback _appOpenFeedback;
|
private readonly BoolFeedback _appOpenFeedback;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets feedback indicating whether an application is currently open on the touchpanel.
|
||||||
|
/// </summary>
|
||||||
public BoolFeedback AppOpenFeedback => _appOpenFeedback;
|
public BoolFeedback AppOpenFeedback => _appOpenFeedback;
|
||||||
|
|
||||||
private readonly BoolFeedback _zoomIncomingCallFeedback;
|
private readonly BoolFeedback _zoomIncomingCallFeedback;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets feedback indicating whether there is an incoming Zoom call.
|
||||||
|
/// </summary>
|
||||||
public BoolFeedback ZoomIncomingCallFeedback => _zoomIncomingCallFeedback;
|
public BoolFeedback ZoomIncomingCallFeedback => _zoomIncomingCallFeedback;
|
||||||
|
|
||||||
private readonly BoolFeedback _zoomInCallFeedback;
|
private readonly BoolFeedback _zoomInCallFeedback;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event that is raised when device information changes.
|
||||||
|
/// </summary>
|
||||||
public event DeviceInfoChangeHandler DeviceInfoChanged;
|
public event DeviceInfoChangeHandler DeviceInfoChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets feedback indicating whether a Zoom call is currently active.
|
||||||
|
/// </summary>
|
||||||
public BoolFeedback ZoomInCallFeedback => _zoomInCallFeedback;
|
public BoolFeedback ZoomInCallFeedback => _zoomInCallFeedback;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the collection of feedback objects for this touchpanel controller.
|
||||||
|
/// </summary>
|
||||||
public FeedbackCollection<Feedback> Feedbacks { get; private set; }
|
public FeedbackCollection<Feedback> Feedbacks { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the collection of Zoom-related feedback objects.
|
||||||
|
/// </summary>
|
||||||
public FeedbackCollection<Feedback> ZoomFeedbacks { get; private set; }
|
public FeedbackCollection<Feedback> ZoomFeedbacks { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the default room key for this touchpanel controller.
|
||||||
|
/// </summary>
|
||||||
public string DefaultRoomKey => _config.DefaultRoomKey;
|
public string DefaultRoomKey => _config.DefaultRoomKey;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether to use direct server communication.
|
||||||
|
/// </summary>
|
||||||
public bool UseDirectServer => localConfig.UseDirectServer;
|
public bool UseDirectServer => localConfig.UseDirectServer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether this touchpanel acts as a Zoom Room controller.
|
||||||
|
/// </summary>
|
||||||
public bool ZoomRoomController => localConfig.ZoomRoomController;
|
public bool ZoomRoomController => localConfig.ZoomRoomController;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current theme for the touchpanel interface.
|
||||||
|
/// </summary>
|
||||||
public string Theme => localConfig.Theme;
|
public string Theme => localConfig.Theme;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets feedback for the current theme setting.
|
||||||
|
/// </summary>
|
||||||
public StringFeedback ThemeFeedback { get; private set; }
|
public StringFeedback ThemeFeedback { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets device information including MAC address and IP address.
|
||||||
|
/// </summary>
|
||||||
public DeviceInfo DeviceInfo => new DeviceInfo();
|
public DeviceInfo DeviceInfo => new DeviceInfo();
|
||||||
|
|
||||||
|
public ReadOnlyCollection<ConnectedIpInformation> ConnectedIps => Panel.ConnectedIpList;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the MobileControlTouchpanelController class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique key identifier for this touchpanel controller.</param>
|
||||||
|
/// <param name="name">The friendly name for this touchpanel controller.</param>
|
||||||
|
/// <param name="panel">The touchpanel hardware device.</param>
|
||||||
|
/// <param name="config">The configuration properties for this controller.</param>
|
||||||
public MobileControlTouchpanelController(string key, string name, BasicTriListWithSmartObject panel, MobileControlTouchpanelProperties config) : base(key, name, panel, config)
|
public MobileControlTouchpanelController(string key, string name, BasicTriListWithSmartObject panel, MobileControlTouchpanelProperties config) : base(key, name, panel, config)
|
||||||
{
|
{
|
||||||
localConfig = config;
|
localConfig = config;
|
||||||
@@ -139,6 +184,10 @@ namespace PepperDash.Essentials.Touchpanel
|
|||||||
RegisterForExtenders();
|
RegisterForExtenders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the theme setting for this touchpanel controller and persists the change to configuration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="theme">The new theme identifier to apply.</param>
|
||||||
public void UpdateTheme(string theme)
|
public void UpdateTheme(string theme)
|
||||||
{
|
{
|
||||||
localConfig.Theme = theme;
|
localConfig.Theme = theme;
|
||||||
@@ -271,6 +320,11 @@ namespace PepperDash.Essentials.Touchpanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs custom activation setup for the touchpanel controller, including
|
||||||
|
/// registering messengers and linking to mobile control.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if activation was successful; otherwise, false.</returns>
|
||||||
public override bool CustomActivate()
|
public override bool CustomActivate()
|
||||||
{
|
{
|
||||||
var appMessenger = new ITswAppControlMessenger($"appControlMessenger-{Key}", $"/device/{Key}", this);
|
var appMessenger = new ITswAppControlMessenger($"appControlMessenger-{Key}", $"/device/{Key}", this);
|
||||||
@@ -300,12 +354,20 @@ namespace PepperDash.Essentials.Touchpanel
|
|||||||
return base.CustomActivate();
|
return base.CustomActivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles device extender signal changes for system reserved signals.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="currentDeviceExtender">The device extender that generated the signal change.</param>
|
||||||
|
/// <param name="args">The signal event arguments containing the changed signal information.</param>
|
||||||
protected override void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
|
protected override void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"System Device Extender args: ${args.Event}:${args.Sig}");
|
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"System Device Extender args: ${args.Event}:${args.Sig}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets up the panel drivers and signal mappings for the specified room.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="roomKey">The room key to configure the panel drivers for.</param>
|
||||||
protected override void SetupPanelDrivers(string roomKey)
|
protected override void SetupPanelDrivers(string roomKey)
|
||||||
{
|
{
|
||||||
AppUrlFeedback.LinkInputSig(Panel.StringInput[1]);
|
AppUrlFeedback.LinkInputSig(Panel.StringInput[1]);
|
||||||
@@ -366,6 +428,10 @@ namespace PepperDash.Essentials.Touchpanel
|
|||||||
SetAppUrl(_bridge.AppUrl);
|
SetAppUrl(_bridge.AppUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the application URL and updates the corresponding feedback.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="url">The new application URL to set.</param>
|
||||||
public void SetAppUrl(string url)
|
public void SetAppUrl(string url)
|
||||||
{
|
{
|
||||||
_appUrl = url;
|
_appUrl = url;
|
||||||
@@ -391,6 +457,9 @@ namespace PepperDash.Essentials.Touchpanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hides the currently open application on the touchpanel.
|
||||||
|
/// </summary>
|
||||||
public void HideOpenApp()
|
public void HideOpenApp()
|
||||||
{
|
{
|
||||||
if (Panel is TswX70Base x70Panel)
|
if (Panel is TswX70Base x70Panel)
|
||||||
@@ -406,6 +475,9 @@ namespace PepperDash.Essentials.Touchpanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Opens an application on the touchpanel. Note: X60 panels do not support Zoom app opening.
|
||||||
|
/// </summary>
|
||||||
public void OpenApp()
|
public void OpenApp()
|
||||||
{
|
{
|
||||||
if (Panel is TswX70Base x70Panel)
|
if (Panel is TswX70Base x70Panel)
|
||||||
@@ -421,6 +493,9 @@ namespace PepperDash.Essentials.Touchpanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Closes the currently open application on the touchpanel.
|
||||||
|
/// </summary>
|
||||||
public void CloseOpenApp()
|
public void CloseOpenApp()
|
||||||
{
|
{
|
||||||
if (Panel is TswX70Base x70Panel)
|
if (Panel is TswX70Base x70Panel)
|
||||||
@@ -436,6 +511,9 @@ namespace PepperDash.Essentials.Touchpanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ends the current Zoom call on the touchpanel.
|
||||||
|
/// </summary>
|
||||||
public void EndZoomCall()
|
public void EndZoomCall()
|
||||||
{
|
{
|
||||||
if (Panel is TswX70Base x70Panel)
|
if (Panel is TswX70Base x70Panel)
|
||||||
@@ -451,6 +529,10 @@ namespace PepperDash.Essentials.Touchpanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the device information (MAC address and IP address) from the touchpanel
|
||||||
|
/// and raises the DeviceInfoChanged event.
|
||||||
|
/// </summary>
|
||||||
public void UpdateDeviceInfo()
|
public void UpdateDeviceInfo()
|
||||||
{
|
{
|
||||||
if (Panel is TswXX70Base x70Panel)
|
if (Panel is TswXX70Base x70Panel)
|
||||||
@@ -487,14 +569,27 @@ namespace PepperDash.Essentials.Touchpanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Factory class for creating MobileControlTouchpanelController instances from device configuration.
|
||||||
|
/// Supports various Crestron touchpanel models including TSW, TS, CrestronApp, XPanel, and DGE series.
|
||||||
|
/// </summary>
|
||||||
public class MobileControlTouchpanelControllerFactory : EssentialsPluginDeviceFactory<MobileControlTouchpanelController>
|
public class MobileControlTouchpanelControllerFactory : EssentialsPluginDeviceFactory<MobileControlTouchpanelController>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the MobileControlTouchpanelControllerFactory class.
|
||||||
|
/// Sets up supported device type names and minimum framework version requirements.
|
||||||
|
/// </summary>
|
||||||
public MobileControlTouchpanelControllerFactory()
|
public MobileControlTouchpanelControllerFactory()
|
||||||
{
|
{
|
||||||
TypeNames = new List<string>() { "mccrestronapp", "mctsw550", "mctsw750", "mctsw1050", "mctsw560", "mctsw760", "mctsw1060", "mctsw570", "mctsw770", "mcts770", "mctsw1070", "mcts1070", "mcxpanel", "mcdge1000" };
|
TypeNames = new List<string>() { "mccrestronapp", "mctsw550", "mctsw750", "mctsw1050", "mctsw560", "mctsw760", "mctsw1060", "mctsw570", "mctsw770", "mcts770", "mctsw1070", "mcts1070", "mcxpanel", "mcdge1000" };
|
||||||
MinimumEssentialsFrameworkVersion = "2.0.0";
|
MinimumEssentialsFrameworkVersion = "2.0.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Builds a MobileControlTouchpanelController device from the provided device configuration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dc">The device configuration containing the device properties and settings.</param>
|
||||||
|
/// <returns>A configured MobileControlTouchpanelController instance.</returns>
|
||||||
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
||||||
{
|
{
|
||||||
var comm = CommFactory.GetControlPropertiesConfig(dc);
|
var comm = CommFactory.GetControlPropertiesConfig(dc);
|
||||||
@@ -557,7 +652,7 @@ namespace PepperDash.Essentials.Touchpanel
|
|||||||
return new Ts1070(id, Global.ControlSystem);
|
return new Ts1070(id, Global.ControlSystem);
|
||||||
else if (type == "dge1000")
|
else if (type == "dge1000")
|
||||||
return new Dge1000(id, Global.ControlSystem);
|
return new Dge1000(id, Global.ControlSystem);
|
||||||
else
|
else
|
||||||
|
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "WARNING: Cannot create TSW controller with type '{0}'", type);
|
Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "WARNING: Cannot create TSW controller with type '{0}'", type);
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
using Crestron.SimplSharp;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
using Crestron.SimplSharp.WebScripting;
|
using Crestron.SimplSharp.WebScripting;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
@@ -9,12 +15,6 @@ using PepperDash.Essentials.Core.Web;
|
|||||||
using PepperDash.Essentials.RoomBridges;
|
using PepperDash.Essentials.RoomBridges;
|
||||||
using PepperDash.Essentials.WebApiHandlers;
|
using PepperDash.Essentials.WebApiHandlers;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Text;
|
|
||||||
using WebSocketSharp;
|
using WebSocketSharp;
|
||||||
using WebSocketSharp.Net;
|
using WebSocketSharp.Net;
|
||||||
using WebSocketSharp.Server;
|
using WebSocketSharp.Server;
|
||||||
@@ -60,7 +60,7 @@ namespace PepperDash.Essentials.WebSocketServer
|
|||||||
|
|
||||||
private string lanIpAddress => CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetLANAdapter));
|
private string lanIpAddress => CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetLANAdapter));
|
||||||
|
|
||||||
private System.Net.IPAddress csIpAddress;
|
private System.Net.IPAddress csIpAddress;
|
||||||
|
|
||||||
private System.Net.IPAddress csSubnetMask;
|
private System.Net.IPAddress csSubnetMask;
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ namespace PepperDash.Essentials.WebSocketServer
|
|||||||
_parent = parent;
|
_parent = parent;
|
||||||
|
|
||||||
// Set the default port to be 50000 plus the slot number of the program
|
// Set the default port to be 50000 plus the slot number of the program
|
||||||
Port = 50000 + (int)Global.ControlSystem.ProgramNumber;
|
Port = 50000 + (int)Global.ControlSystem.ProgramNumber;
|
||||||
|
|
||||||
if (customPort != 0)
|
if (customPort != 0)
|
||||||
{
|
{
|
||||||
@@ -156,9 +156,9 @@ namespace PepperDash.Essentials.WebSocketServer
|
|||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var csAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetCSAdapter);
|
var csAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetCSAdapter);
|
||||||
var csSubnetMask = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, csAdapterId);
|
var csSubnetMask = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, csAdapterId);
|
||||||
var csIpAddress = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, csAdapterId);
|
var csIpAddress = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, csAdapterId);
|
||||||
|
|
||||||
this.csSubnetMask = System.Net.IPAddress.Parse(csSubnetMask);
|
this.csSubnetMask = System.Net.IPAddress.Parse(csSubnetMask);
|
||||||
@@ -298,8 +298,6 @@ namespace PepperDash.Essentials.WebSocketServer
|
|||||||
|
|
||||||
var processorIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, lanAdapterId);
|
var processorIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, lanAdapterId);
|
||||||
|
|
||||||
this.LogVerbose("Processor IP: {processorIp}", processorIp);
|
|
||||||
|
|
||||||
foreach (var touchpanel in touchpanels.Select(tp =>
|
foreach (var touchpanel in touchpanels.Select(tp =>
|
||||||
{
|
{
|
||||||
var token = _secret.Tokens.FirstOrDefault((t) => t.Value.TouchpanelKey.Equals(tp.Key, StringComparison.InvariantCultureIgnoreCase));
|
var token = _secret.Tokens.FirstOrDefault((t) => t.Value.TouchpanelKey.Equals(tp.Key, StringComparison.InvariantCultureIgnoreCase));
|
||||||
@@ -321,11 +319,25 @@ namespace PepperDash.Essentials.WebSocketServer
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var appUrl = $"http://{processorIp}:{_parent.Config.DirectServer.Port}/mc/app?token={touchpanel.Key}";
|
string ip = processorIp;
|
||||||
|
if (touchpanel.Touchpanel is IMobileControlCrestronTouchpanelController crestronTouchpanel)
|
||||||
|
{
|
||||||
|
ip = crestronTouchpanel.ConnectedIps.Any(ipInfo =>
|
||||||
|
{
|
||||||
|
if (System.Net.IPAddress.TryParse(ipInfo.DeviceIpAddress, out var parsedIp))
|
||||||
|
{
|
||||||
|
return csIpAddress.IsInSameSubnet(parsedIp, csSubnetMask);
|
||||||
|
}
|
||||||
|
this.LogWarning("Invalid IP address: {deviceIpAddress}", ipInfo.DeviceIpAddress);
|
||||||
|
return false;
|
||||||
|
}) ? csIpAddress.ToString() : processorIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
var appUrl = $"http://{ip}:{_parent.Config.DirectServer.Port}/mc/app?token={touchpanel.Key}";
|
||||||
|
|
||||||
this.LogVerbose("Sending URL {appUrl}", appUrl);
|
this.LogVerbose("Sending URL {appUrl}", appUrl);
|
||||||
|
|
||||||
touchpanel.Messenger.UpdateAppUrl($"http://{processorIp}:{_parent.Config.DirectServer.Port}/mc/app?token={touchpanel.Key}");
|
touchpanel.Messenger.UpdateAppUrl($"http://{ip}:{_parent.Config.DirectServer.Port}/mc/app?token={touchpanel.Key}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,7 +361,7 @@ namespace PepperDash.Essentials.WebSocketServer
|
|||||||
if (!Directory.Exists($"{userAppPath}{localConfigFolderName}"))
|
if (!Directory.Exists($"{userAppPath}{localConfigFolderName}"))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory($"{userAppPath}{localConfigFolderName}");
|
Directory.CreateDirectory($"{userAppPath}{localConfigFolderName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var sw = new StreamWriter(File.Open($"{userAppPath}{localConfigFolderName}{Global.DirectorySeparator}{appConfigFileName}", FileMode.Create, FileAccess.ReadWrite)))
|
using (var sw = new StreamWriter(File.Open($"{userAppPath}{localConfigFolderName}{Global.DirectorySeparator}{appConfigFileName}", FileMode.Create, FileAccess.ReadWrite)))
|
||||||
{
|
{
|
||||||
@@ -358,7 +370,7 @@ namespace PepperDash.Essentials.WebSocketServer
|
|||||||
|
|
||||||
this.LogDebug("LAN Adapter ID: {lanAdapterId}", lanAdapterId);
|
this.LogDebug("LAN Adapter ID: {lanAdapterId}", lanAdapterId);
|
||||||
|
|
||||||
var processorIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, lanAdapterId);
|
var processorIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, lanAdapterId);
|
||||||
|
|
||||||
var config = GetApplicationConfig(processorIp);
|
var config = GetApplicationConfig(processorIp);
|
||||||
|
|
||||||
@@ -378,7 +390,7 @@ namespace PepperDash.Essentials.WebSocketServer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(csAdapterId == -1)
|
if (csAdapterId == -1)
|
||||||
{
|
{
|
||||||
this.LogDebug("CS LAN Adapter not found");
|
this.LogDebug("CS LAN Adapter not found");
|
||||||
return;
|
return;
|
||||||
@@ -389,8 +401,8 @@ namespace PepperDash.Essentials.WebSocketServer
|
|||||||
using (var sw = new StreamWriter(File.Open($"{userAppPath}{localConfigFolderName}{Global.DirectorySeparator}{appConfigCsFileName}", FileMode.Create, FileAccess.ReadWrite)))
|
using (var sw = new StreamWriter(File.Open($"{userAppPath}{localConfigFolderName}{Global.DirectorySeparator}{appConfigCsFileName}", FileMode.Create, FileAccess.ReadWrite)))
|
||||||
{
|
{
|
||||||
// Write the CS application configuration file. Used when a request comes in for the application config from the CS
|
// Write the CS application configuration file. Used when a request comes in for the application config from the CS
|
||||||
var processorIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, csAdapterId);
|
var processorIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, csAdapterId);
|
||||||
|
|
||||||
var config = GetApplicationConfig(processorIp);
|
var config = GetApplicationConfig(processorIp);
|
||||||
|
|
||||||
var contents = JsonConvert.SerializeObject(config, Formatting.Indented);
|
var contents = JsonConvert.SerializeObject(config, Formatting.Indented);
|
||||||
@@ -400,7 +412,7 @@ namespace PepperDash.Essentials.WebSocketServer
|
|||||||
}
|
}
|
||||||
|
|
||||||
private MobileControlApplicationConfig GetApplicationConfig(string processorIp)
|
private MobileControlApplicationConfig GetApplicationConfig(string processorIp)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var config = new MobileControlApplicationConfig
|
var config = new MobileControlApplicationConfig
|
||||||
@@ -430,10 +442,10 @@ namespace PepperDash.Essentials.WebSocketServer
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
this.LogError(ex, "Error getting application configuration");
|
this.LogError(ex, "Error getting application configuration");
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -572,7 +584,7 @@ namespace PepperDash.Essentials.WebSocketServer
|
|||||||
|
|
||||||
var values = s.Split(' ');
|
var values = s.Split(' ');
|
||||||
|
|
||||||
if(values.Length < 2)
|
if (values.Length < 2)
|
||||||
{
|
{
|
||||||
CrestronConsole.ConsoleCommandResponse("Invalid number of arguments. Please provide a room key and a grant code");
|
CrestronConsole.ConsoleCommandResponse("Invalid number of arguments. Please provide a room key and a grant code");
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user