mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-03-25 07:05:13 +00:00
Compare commits
41 Commits
plugin-min
...
unique-cli
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af82ba2351 | ||
|
|
505067f38f | ||
|
|
8b098aac2c | ||
|
|
5ff587a8c9 | ||
|
|
26c1baa1f8 | ||
|
|
2b15c2a56f | ||
|
|
a076d531bc | ||
|
|
5e880f0111 | ||
|
|
8f1fb86d37 | ||
|
|
471d5b701b | ||
|
|
96ac266d24 | ||
|
|
c1809459a6 | ||
|
|
1a9e1087de | ||
|
|
8d55615837 | ||
|
|
19e799f11d | ||
|
|
a3c1c444b7 | ||
|
|
c9b3205736 | ||
|
|
253b2cddaf | ||
|
|
d96edfa8d0 | ||
|
|
2fa297a204 | ||
|
|
95c1c01396 | ||
|
|
9c94806e4f | ||
|
|
183879f1c4 | ||
|
|
f3159738ce | ||
|
|
2c5cae9f41 | ||
|
|
7178d8e284 | ||
|
|
af98a92f8c | ||
|
|
0a6896910d | ||
|
|
9b1dd099f6 | ||
|
|
3f5269de2f | ||
|
|
60f1adcd35 | ||
|
|
12c8660015 | ||
|
|
e7c3fcbbd9 | ||
|
|
0c7ec82529 | ||
|
|
feb99ecbb6 | ||
|
|
d78b9ea313 | ||
|
|
15172a5509 | ||
|
|
a4de9f2241 | ||
|
|
13cd84b73d | ||
|
|
81a01b7960 | ||
|
|
d9dc70bea2 |
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
|
||||||
|
|||||||
@@ -11,35 +11,35 @@ namespace PepperDash.Core
|
|||||||
public class Device : IKeyName
|
public class Device : IKeyName
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unique Key
|
/// Unique Key
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Key { get; protected set; }
|
public string Key { get; protected set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Name of the devie
|
/// Name of the devie
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; protected set; }
|
public string Name { get; protected set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Enabled { get; protected set; }
|
public bool Enabled { get; protected set; }
|
||||||
|
|
||||||
///// <summary>
|
///// <summary>
|
||||||
///// A place to store reference to the original config object, if any. These values should
|
///// A place to store reference to the original config object, if any. These values should
|
||||||
///// NOT be used as properties on the device as they are all publicly-settable values.
|
///// NOT be used as properties on the device as they are all publicly-settable values.
|
||||||
///// </summary>
|
///// </summary>
|
||||||
//public DeviceConfig Config { get; private set; }
|
//public DeviceConfig Config { get; private set; }
|
||||||
///// <summary>
|
///// <summary>
|
||||||
///// Helper method to check if Config exists
|
///// Helper method to check if Config exists
|
||||||
///// </summary>
|
///// </summary>
|
||||||
//public bool HasConfig { get { return Config != null; } }
|
//public bool HasConfig { get { return Config != null; } }
|
||||||
|
|
||||||
List<Action> _PreActivationActions;
|
List<Action> _PreActivationActions;
|
||||||
List<Action> _PostActivationActions;
|
List<Action> _PostActivationActions;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Device DefaultDevice { get { return _DefaultDevice; } }
|
public static Device DefaultDevice { get { return _DefaultDevice; } }
|
||||||
static Device _DefaultDevice = new Device("Default", "Default");
|
static Device _DefaultDevice = new Device("Default", "Default");
|
||||||
|
|
||||||
@@ -54,27 +54,27 @@ namespace PepperDash.Core
|
|||||||
Name = "";
|
Name = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor with key and name
|
/// Constructor with key and name
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key"></param>
|
/// <param name="key"></param>
|
||||||
/// <param name="name"></param>
|
/// <param name="name"></param>
|
||||||
public Device(string key, string name) : this(key)
|
public Device(string key, string name) : this(key)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//public Device(DeviceConfig config)
|
//public Device(DeviceConfig config)
|
||||||
// : this(config.Key, config.Name)
|
// : this(config.Key, config.Name)
|
||||||
//{
|
//{
|
||||||
// Config = config;
|
// Config = config;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a pre activation action
|
/// Adds a pre activation action
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="act"></param>
|
/// <param name="act"></param>
|
||||||
public void AddPreActivationAction(Action act)
|
public void AddPreActivationAction(Action act)
|
||||||
{
|
{
|
||||||
if (_PreActivationActions == null)
|
if (_PreActivationActions == null)
|
||||||
@@ -82,10 +82,10 @@ namespace PepperDash.Core
|
|||||||
_PreActivationActions.Add(act);
|
_PreActivationActions.Add(act);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a post activation action
|
/// Adds a post activation action
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="act"></param>
|
/// <param name="act"></param>
|
||||||
public void AddPostActivationAction(Action act)
|
public void AddPostActivationAction(Action act)
|
||||||
{
|
{
|
||||||
if (_PostActivationActions == null)
|
if (_PostActivationActions == null)
|
||||||
@@ -93,55 +93,58 @@ namespace PepperDash.Core
|
|||||||
_PostActivationActions.Add(act);
|
_PostActivationActions.Add(act);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executes the preactivation actions
|
/// Executes the preactivation actions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void PreActivate()
|
public void PreActivate()
|
||||||
{
|
{
|
||||||
if (_PreActivationActions != null)
|
if (_PreActivationActions != null)
|
||||||
_PreActivationActions.ForEach(a => {
|
_PreActivationActions.ForEach(a =>
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
a.Invoke();
|
a.Invoke();
|
||||||
} catch (Exception e)
|
}
|
||||||
{
|
catch (Exception e)
|
||||||
|
{
|
||||||
Debug.LogMessage(e, "Error in PreActivationAction: " + e.Message, this);
|
Debug.LogMessage(e, "Error in PreActivationAction: " + e.Message, this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets this device ready to be used in the system. Runs any added pre-activation items, and
|
/// Gets this device ready to be used in the system. Runs any added pre-activation items, and
|
||||||
/// all post-activation at end. Classes needing additional logic to
|
/// all post-activation at end. Classes needing additional logic to
|
||||||
/// run should override CustomActivate()
|
/// run should override CustomActivate()
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Activate()
|
public bool Activate()
|
||||||
{
|
{
|
||||||
//if (_PreActivationActions != null)
|
//if (_PreActivationActions != null)
|
||||||
// _PreActivationActions.ForEach(a => a.Invoke());
|
// _PreActivationActions.ForEach(a => a.Invoke());
|
||||||
var result = CustomActivate();
|
var result = CustomActivate();
|
||||||
//if(result && _PostActivationActions != null)
|
//if(result && _PostActivationActions != null)
|
||||||
// _PostActivationActions.ForEach(a => a.Invoke());
|
// _PostActivationActions.ForEach(a => a.Invoke());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executes the postactivation actions
|
/// Executes the postactivation actions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void PostActivate()
|
public void PostActivate()
|
||||||
{
|
{
|
||||||
if (_PostActivationActions != null)
|
if (_PostActivationActions != null)
|
||||||
_PostActivationActions.ForEach(a => {
|
_PostActivationActions.ForEach(a =>
|
||||||
try
|
{
|
||||||
{
|
try
|
||||||
a.Invoke();
|
{
|
||||||
}
|
a.Invoke();
|
||||||
catch (Exception e)
|
}
|
||||||
{
|
catch (Exception e)
|
||||||
Debug.LogMessage(e, "Error in PostActivationAction: " + e.Message, this);
|
{
|
||||||
}
|
Debug.LogMessage(e, "Error in PostActivationAction: " + e.Message, this);
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called in between Pre and PostActivationActions when Activate() is called.
|
/// Called in between Pre and PostActivationActions when Activate() is called.
|
||||||
@@ -158,14 +161,14 @@ namespace PepperDash.Core
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual bool Deactivate() { return true; }
|
public virtual bool Deactivate() { return true; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Call this method to start communications with a device. Overriding classes do not need to call base.Initialize()
|
/// Call this method to start communications with a device. Overriding classes do not need to call base.Initialize()
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void Initialize()
|
public virtual void Initialize()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper method to check object for bool value false and fire an Action method
|
/// Helper method to check object for bool value false and fire an Action method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="o">Should be of type bool, others will be ignored</param>
|
/// <param name="o">Should be of type bool, others will be ignored</param>
|
||||||
@@ -175,5 +178,15 @@ namespace PepperDash.Core
|
|||||||
if (o is bool && !(bool)o) a();
|
if (o is bool && !(bool)o) a();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a string representation of the object, including its key and name.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>The returned string is formatted as "{Key} - {Name}". If the <c>Name</c> property is
|
||||||
|
/// null or empty, "---" is used in place of the name.</remarks>
|
||||||
|
/// <returns>A string that represents the object, containing the key and name in the format "{Key} - {Name}".</returns>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return string.Format("{0} - {1}", Key, string.IsNullOrEmpty(Name) ? "---" : Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This defines a device that has screens with layouts
|
||||||
|
/// Simply decorative
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasScreensWithLayouts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A dictionary of screens, keyed by screen ID, that contains information about each screen and its layouts.
|
||||||
|
/// </summary>
|
||||||
|
Dictionary<uint, ScreenInfo> Screens { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies a specific layout to a screen based on the provided screen ID and layout index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="screenId"></param>
|
||||||
|
/// <param name="layoutIndex"></param>
|
||||||
|
void ApplyLayout(uint screenId, uint layoutIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents information about a screen and its layouts.
|
||||||
|
/// </summary>
|
||||||
|
public class ScreenInfo
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the screen is enabled or not.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("enabled")]
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the screen.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The index of the screen.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("screenIndex")]
|
||||||
|
public int ScreenIndex { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A dictionary of layout information for the screen, keyed by layout ID.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("layouts")]
|
||||||
|
public Dictionary<uint, LayoutInfo> Layouts { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents information about a layout on a screen.
|
||||||
|
/// </summary>
|
||||||
|
public class LayoutInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the layout.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("layoutName")]
|
||||||
|
public string LayoutName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The index of the layout.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("layoutIndex")]
|
||||||
|
public int LayoutIndex { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of the layout, which can be "single", "double", "triple", or "quad".
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("layoutType")]
|
||||||
|
public string LayoutType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A dictionary of window configurations for the layout, keyed by window ID.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("windows")]
|
||||||
|
public Dictionary<uint, WindowConfig> Windows { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the configuration of a window within a layout on a screen.
|
||||||
|
/// </summary>
|
||||||
|
public class WindowConfig
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The display label for the window
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("label")]
|
||||||
|
public string Label { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The input for the window
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("input")]
|
||||||
|
public string Input { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -248,7 +248,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
foreach (var dev in Devices.Values.OfType<ICommunicationMonitor>())
|
foreach (var dev in Devices.Values.OfType<ICommunicationMonitor>())
|
||||||
{
|
{
|
||||||
CrestronConsole.ConsoleCommandResponse($"{dev}: {dev.CommunicationMonitor.Status}{Environment.NewLine}");
|
CrestronConsole.ConsoleCommandResponse($"{dev}: {dev.CommunicationMonitor.Status}\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,19 +20,20 @@ namespace PepperDash.Essentials.Core
|
|||||||
public event EventHandler Initialized;
|
public event EventHandler Initialized;
|
||||||
|
|
||||||
private bool _isInitialized;
|
private bool _isInitialized;
|
||||||
public bool IsInitialized {
|
public bool IsInitialized
|
||||||
|
{
|
||||||
get { return _isInitialized; }
|
get { return _isInitialized; }
|
||||||
private set
|
private set
|
||||||
{
|
{
|
||||||
if (_isInitialized == value) return;
|
if (_isInitialized == value) return;
|
||||||
|
|
||||||
_isInitialized = value;
|
_isInitialized = value;
|
||||||
|
|
||||||
if (_isInitialized)
|
if (_isInitialized)
|
||||||
{
|
{
|
||||||
Initialized?.Invoke(this, new EventArgs());
|
Initialized?.Invoke(this, new EventArgs());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EssentialsDevice(string key)
|
protected EssentialsDevice(string key)
|
||||||
@@ -80,8 +81,9 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Override this method to build and create custom Mobile Control Messengers during the Activation phase
|
/// Override this method to build and create custom Mobile Control Messengers during the Activation phase
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void CreateMobileControlMessengers() {
|
protected virtual void CreateMobileControlMessengers()
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,18 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// </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 +29,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 +131,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 +166,56 @@ namespace PepperDash.Essentials.Core
|
|||||||
[JsonProperty("disableSimpleRouting")]
|
[JsonProperty("disableSimpleRouting")]
|
||||||
public bool DisableSimpleRouting { get; set; }
|
public bool DisableSimpleRouting { 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></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 +225,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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extensions for IPAddress to provide additional functionality such as getting broadcast address, network address, and checking if two addresses are in the same subnet.
|
||||||
|
/// </summary>
|
||||||
|
public static class IPAddressExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get the broadcast address for a given IP address and subnet mask.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">Address to check</param>
|
||||||
|
/// <param name="subnetMask">Subnet mask in a.b.c.d format</param>
|
||||||
|
/// <returns>Broadcast address</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// If the input IP address is 192.168.1.100 and the subnet mask is 255.255.255.0, the broadcast address will be 192.168.1.255
|
||||||
|
/// </remarks>
|
||||||
|
/// <exception cref="ArgumentException"></exception>
|
||||||
|
public static IPAddress GetBroadcastAddress(this IPAddress address, IPAddress subnetMask)
|
||||||
|
{
|
||||||
|
byte[] ipAdressBytes = address.GetAddressBytes();
|
||||||
|
byte[] subnetMaskBytes = subnetMask.GetAddressBytes();
|
||||||
|
|
||||||
|
if (ipAdressBytes.Length != subnetMaskBytes.Length)
|
||||||
|
throw new ArgumentException("Lengths of IP address and subnet mask do not match.");
|
||||||
|
|
||||||
|
byte[] broadcastAddress = new byte[ipAdressBytes.Length];
|
||||||
|
for (int i = 0; i < broadcastAddress.Length; i++)
|
||||||
|
{
|
||||||
|
broadcastAddress[i] = (byte)(ipAdressBytes[i] | (subnetMaskBytes[i] ^ 255));
|
||||||
|
}
|
||||||
|
return new IPAddress(broadcastAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the network address for a given IP address and subnet mask.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">Address to check</param>
|
||||||
|
/// <param name="subnetMask">Subnet mask in a.b.c.d</param>
|
||||||
|
/// <returns>Network Address</returns>
|
||||||
|
/// /// <remarks>
|
||||||
|
/// If the input IP address is 192.168.1.100 and the subnet mask is 255.255.255.0, the network address will be 192.168.1.0
|
||||||
|
/// </remarks>
|
||||||
|
/// <exception cref="ArgumentException"></exception>
|
||||||
|
public static IPAddress GetNetworkAddress(this IPAddress address, IPAddress subnetMask)
|
||||||
|
{
|
||||||
|
byte[] ipAdressBytes = address.GetAddressBytes();
|
||||||
|
byte[] subnetMaskBytes = subnetMask.GetAddressBytes();
|
||||||
|
|
||||||
|
if (ipAdressBytes.Length != subnetMaskBytes.Length)
|
||||||
|
throw new ArgumentException("Lengths of IP address and subnet mask do not match.");
|
||||||
|
|
||||||
|
byte[] broadcastAddress = new byte[ipAdressBytes.Length];
|
||||||
|
for (int i = 0; i < broadcastAddress.Length; i++)
|
||||||
|
{
|
||||||
|
broadcastAddress[i] = (byte)(ipAdressBytes[i] & (subnetMaskBytes[i]));
|
||||||
|
}
|
||||||
|
return new IPAddress(broadcastAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determine if two IP addresses are in the same subnet.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address2">Address to check</param>
|
||||||
|
/// <param name="address">Second address to check</param>
|
||||||
|
/// <param name="subnetMask">Subnet mask to use to compare the 2 IP Address</param>
|
||||||
|
/// <returns>True if addresses are in the same subnet</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// If the input IP addresses are 192.168.1.100 and 192.168.1.200, and the subnet mask is 255.255.255.0, this will return true.
|
||||||
|
/// If the input IP addresses are 10.1.1.100 and 192.168.1.100, and the subnet mask is 255.255.255.0, this will return false.
|
||||||
|
/// </remarks>
|
||||||
|
public static bool IsInSameSubnet(this IPAddress address2, IPAddress address, IPAddress subnetMask)
|
||||||
|
{
|
||||||
|
IPAddress network1 = address.GetNetworkAddress(subnetMask);
|
||||||
|
IPAddress network2 = address2.GetNetworkAddress(subnetMask);
|
||||||
|
|
||||||
|
return network1.Equals(network2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,13 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a device that manages room combinations by controlling partitions and scenarios.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>The <see cref="EssentialsRoomCombiner"/> allows for dynamic configuration of room
|
||||||
|
/// combinations based on partition states and predefined scenarios. It supports both automatic and manual modes
|
||||||
|
/// for managing room combinations. In automatic mode, the device determines the current room combination scenario
|
||||||
|
/// based on partition sensor states. In manual mode, scenarios can be set explicitly by the user.</remarks>
|
||||||
public class EssentialsRoomCombiner : EssentialsDevice, IEssentialsRoomCombiner
|
public class EssentialsRoomCombiner : EssentialsDevice, IEssentialsRoomCombiner
|
||||||
{
|
{
|
||||||
private EssentialsRoomCombinerPropertiesConfig _propertiesConfig;
|
private EssentialsRoomCombinerPropertiesConfig _propertiesConfig;
|
||||||
@@ -18,6 +25,9 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
private List<IEssentialsRoom> _rooms;
|
private List<IEssentialsRoom> _rooms;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a list of rooms represented as key-name pairs.
|
||||||
|
/// </summary>
|
||||||
public List<IKeyName> Rooms
|
public List<IKeyName> Rooms
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -28,6 +38,12 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
private bool _isInAutoMode;
|
private bool _isInAutoMode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether the system is operating in automatic mode.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Changing this property triggers an update event via
|
||||||
|
/// <c>IsInAutoModeFeedback.FireUpdate()</c>. Ensure that any event listeners are properly configured to handle
|
||||||
|
/// this update.</remarks>
|
||||||
public bool IsInAutoMode
|
public bool IsInAutoMode
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -46,12 +62,36 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether automatic mode is disabled.
|
||||||
|
/// </summary>
|
||||||
|
public bool DisableAutoMode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _propertiesConfig.DisableAutoMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private CTimer _scenarioChangeDebounceTimer;
|
private CTimer _scenarioChangeDebounceTimer;
|
||||||
|
|
||||||
private int _scenarioChangeDebounceTimeSeconds = 10; // default to 10s
|
private int _scenarioChangeDebounceTimeSeconds = 10; // default to 10s
|
||||||
|
|
||||||
private Mutex _scenarioChange = new Mutex();
|
private Mutex _scenarioChange = new Mutex();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="EssentialsRoomCombiner"/> class, which manages room combination
|
||||||
|
/// scenarios and partition states.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>The <see cref="EssentialsRoomCombiner"/> class is designed to handle dynamic room
|
||||||
|
/// combination scenarios based on partition states. It supports both automatic and manual modes for managing
|
||||||
|
/// room combinations. By default, the instance starts in automatic mode unless the <paramref name="props"/>
|
||||||
|
/// specifies otherwise. After activation, the room combiner initializes partition state providers and sets up
|
||||||
|
/// the initial room configuration. Additionally, it subscribes to the <see
|
||||||
|
/// cref="DeviceManager.AllDevicesInitialized"/> event to ensure proper initialization of dependent devices
|
||||||
|
/// before determining or setting the room combination scenario.</remarks>
|
||||||
|
/// <param name="key">The unique identifier for the room combiner instance.</param>
|
||||||
|
/// <param name="props">The configuration properties for the room combiner, including default settings and debounce times.</param>
|
||||||
public EssentialsRoomCombiner(string key, EssentialsRoomCombinerPropertiesConfig props)
|
public EssentialsRoomCombiner(string key, EssentialsRoomCombinerPropertiesConfig props)
|
||||||
: base(key)
|
: base(key)
|
||||||
{
|
{
|
||||||
@@ -246,8 +286,16 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
#region IEssentialsRoomCombiner Members
|
#region IEssentialsRoomCombiner Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when the room combination scenario changes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This event is triggered whenever the configuration or state of the room combination
|
||||||
|
/// changes. Subscribers can use this event to update their logic or UI based on the new scenario.</remarks>
|
||||||
public event EventHandler<EventArgs> RoomCombinationScenarioChanged;
|
public event EventHandler<EventArgs> RoomCombinationScenarioChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current room combination scenario.
|
||||||
|
/// </summary>
|
||||||
public IRoomCombinationScenario CurrentScenario
|
public IRoomCombinationScenario CurrentScenario
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -256,10 +304,25 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the feedback indicating whether the system is currently in auto mode.
|
||||||
|
/// </summary>
|
||||||
public BoolFeedback IsInAutoModeFeedback { get; private set; }
|
public BoolFeedback IsInAutoModeFeedback { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables auto mode for the room combiner and its partitions, allowing automatic room combination scenarios to
|
||||||
|
/// be determined.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Auto mode allows the room combiner to automatically adjust its configuration based on
|
||||||
|
/// the state of its partitions. If auto mode is disabled in the configuration, this method logs a warning and
|
||||||
|
/// does not enable auto mode.</remarks>
|
||||||
public void SetAutoMode()
|
public void SetAutoMode()
|
||||||
{
|
{
|
||||||
|
if(_propertiesConfig.DisableAutoMode)
|
||||||
|
{
|
||||||
|
this.LogWarning("Auto mode is disabled for this room combiner. Cannot set to auto mode.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
IsInAutoMode = true;
|
IsInAutoMode = true;
|
||||||
|
|
||||||
foreach (var partition in Partitions)
|
foreach (var partition in Partitions)
|
||||||
@@ -270,6 +333,12 @@ namespace PepperDash.Essentials.Core
|
|||||||
DetermineRoomCombinationScenario();
|
DetermineRoomCombinationScenario();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Switches the system to manual mode, disabling automatic operations.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This method sets the system to manual mode by updating the mode state and propagates
|
||||||
|
/// the change to all partitions. Once in manual mode, automatic operations are disabled for the system and its
|
||||||
|
/// partitions.</remarks>
|
||||||
public void SetManualMode()
|
public void SetManualMode()
|
||||||
{
|
{
|
||||||
IsInAutoMode = false;
|
IsInAutoMode = false;
|
||||||
@@ -280,6 +349,11 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Toggles the current mode between automatic and manual.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>If the current mode is automatic, this method switches to manual mode. If the
|
||||||
|
/// current mode is manual, it switches to automatic mode.</remarks>
|
||||||
public void ToggleMode()
|
public void ToggleMode()
|
||||||
{
|
{
|
||||||
if (IsInAutoMode)
|
if (IsInAutoMode)
|
||||||
@@ -292,10 +366,22 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the collection of room combination scenarios.
|
||||||
|
/// </summary>
|
||||||
public List<IRoomCombinationScenario> RoomCombinationScenarios { get; private set; }
|
public List<IRoomCombinationScenario> RoomCombinationScenarios { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the collection of partition controllers managed by this instance.
|
||||||
|
/// </summary>
|
||||||
public List<IPartitionController> Partitions { get; private set; }
|
public List<IPartitionController> Partitions { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Toggles the state of the partition identified by the specified partition key.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>If no partition with the specified key exists, the method performs no
|
||||||
|
/// action.</remarks>
|
||||||
|
/// <param name="partitionKey">The key of the partition whose state is to be toggled. This value cannot be null or empty.</param>
|
||||||
public void TogglePartitionState(string partitionKey)
|
public void TogglePartitionState(string partitionKey)
|
||||||
{
|
{
|
||||||
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionKey));
|
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionKey));
|
||||||
@@ -306,6 +392,17 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the room combination scenario based on the specified scenario key.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This method manually adjusts the partition states according to the specified
|
||||||
|
/// scenario. If the application is in auto mode, the operation will not proceed, and a log message will be
|
||||||
|
/// generated indicating that the mode must be set to manual first. If the specified scenario key does not
|
||||||
|
/// match any existing scenario, a debug log message will be generated. For each partition state in the
|
||||||
|
/// scenario, the corresponding partition will be updated to either "Present" or "Not Present" based on the
|
||||||
|
/// scenario's configuration. If a partition key in the scenario cannot be found, a debug log message will be
|
||||||
|
/// generated.</remarks>
|
||||||
|
/// <param name="scenarioKey">The key identifying the room combination scenario to apply. This must match the key of an existing scenario.</param>
|
||||||
public void SetRoomCombinationScenario(string scenarioKey)
|
public void SetRoomCombinationScenario(string scenarioKey)
|
||||||
{
|
{
|
||||||
if (IsInAutoMode)
|
if (IsInAutoMode)
|
||||||
@@ -354,13 +451,32 @@ namespace PepperDash.Essentials.Core
|
|||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides a factory for creating instances of <see cref="EssentialsRoomCombiner"/> devices.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This factory is responsible for constructing <see cref="EssentialsRoomCombiner"/> devices
|
||||||
|
/// based on the provided configuration. It supports the type name "essentialsroomcombiner" for device
|
||||||
|
/// creation.</remarks>
|
||||||
public class EssentialsRoomCombinerFactory : EssentialsDeviceFactory<EssentialsRoomCombiner>
|
public class EssentialsRoomCombinerFactory : EssentialsDeviceFactory<EssentialsRoomCombiner>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="EssentialsRoomCombinerFactory"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This factory is used to create instances of room combiners with the specified type
|
||||||
|
/// names. By default, the factory includes the type name "essentialsroomcombiner".</remarks>
|
||||||
public EssentialsRoomCombinerFactory()
|
public EssentialsRoomCombinerFactory()
|
||||||
{
|
{
|
||||||
TypeNames = new List<string> { "essentialsroomcombiner" };
|
TypeNames = new List<string> { "essentialsroomcombiner" };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates and initializes a new instance of the <see cref="EssentialsRoomCombiner"/> device.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This method uses the provided device configuration to extract the properties and
|
||||||
|
/// create an <see cref="EssentialsRoomCombiner"/> device. Ensure that the configuration contains valid
|
||||||
|
/// properties for the device to be created successfully.</remarks>
|
||||||
|
/// <param name="dc">The device configuration containing the key and properties required to build the device.</param>
|
||||||
|
/// <returns>A new instance of <see cref="EssentialsRoomCombiner"/> initialized with the specified configuration.</returns>
|
||||||
public override EssentialsDevice BuildDevice(PepperDash.Essentials.Core.Config.DeviceConfig dc)
|
public override EssentialsDevice BuildDevice(PepperDash.Essentials.Core.Config.DeviceConfig dc)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new EssentialsRoomCombiner Device");
|
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new EssentialsRoomCombiner Device");
|
||||||
|
|||||||
@@ -1,10 +1,4 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
|
|
||||||
@@ -17,6 +11,14 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class EssentialsRoomCombinerPropertiesConfig
|
public class EssentialsRoomCombinerPropertiesConfig
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether the system operates in automatic mode.
|
||||||
|
/// <remarks>Some systems don't have partitions sensors, and show shouldn't allow auto mode to be turned on. When this is true in the configuration,
|
||||||
|
/// auto mode won't be allowed to be turned on.</remarks>
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("disableAutoMode")]
|
||||||
|
public bool DisableAutoMode { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of partitions that device the rooms
|
/// The list of partitions that device the rooms
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -47,6 +49,9 @@ namespace PepperDash.Essentials.Core
|
|||||||
[JsonProperty("defaultScenarioKey")]
|
[JsonProperty("defaultScenarioKey")]
|
||||||
public string defaultScenarioKey { get; set; }
|
public string defaultScenarioKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the debounce time, in seconds, for scenario changes.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("scenarioChangeDebounceTimeSeconds")]
|
[JsonProperty("scenarioChangeDebounceTimeSeconds")]
|
||||||
public int ScenarioChangeDebounceTimeSeconds { get; set; }
|
public int ScenarioChangeDebounceTimeSeconds { get; set; }
|
||||||
}
|
}
|
||||||
@@ -56,9 +61,15 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class PartitionConfig : IKeyName
|
public class PartitionConfig : IKeyName
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the unique key associated with the object.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("key")]
|
[JsonProperty("key")]
|
||||||
public string Key { get; set; }
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name associated with the object.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("name")]
|
[JsonProperty("name")]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
@@ -80,12 +91,21 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class RoomCombinationScenarioConfig : IKeyName
|
public class RoomCombinationScenarioConfig : IKeyName
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the key associated with the object.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("key")]
|
[JsonProperty("key")]
|
||||||
public string Key { get; set; }
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name associated with the object.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("name")]
|
[JsonProperty("name")]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the collection of partition states.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("partitionStates")]
|
[JsonProperty("partitionStates")]
|
||||||
public List<PartitionState> PartitionStates { get; set; }
|
public List<PartitionState> PartitionStates { get; set; }
|
||||||
|
|
||||||
@@ -95,9 +115,15 @@ namespace PepperDash.Essentials.Core
|
|||||||
[JsonProperty("uiMap")]
|
[JsonProperty("uiMap")]
|
||||||
public Dictionary<string, string> UiMap { get; set; }
|
public Dictionary<string, string> UiMap { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the list of actions to be performed during device activation.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("activationActions")]
|
[JsonProperty("activationActions")]
|
||||||
public List<DeviceActionWrapper> ActivationActions { get; set; }
|
public List<DeviceActionWrapper> ActivationActions { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the list of actions to be performed when a device is deactivated.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("deactivationActions")]
|
[JsonProperty("deactivationActions")]
|
||||||
public List<DeviceActionWrapper> DeactivationActions { get; set; }
|
public List<DeviceActionWrapper> DeactivationActions { get; set; }
|
||||||
}
|
}
|
||||||
@@ -107,9 +133,15 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class PartitionState
|
public class PartitionState
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the partition key used to group and organize data within a storage system.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("partitionKey")]
|
[JsonProperty("partitionKey")]
|
||||||
public string PartitionKey { get; set; }
|
public string PartitionKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether a partition is currently present.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("partitionSensedState")]
|
[JsonProperty("partitionSensedState")]
|
||||||
public bool PartitionPresent { get; set; }
|
public bool PartitionPresent { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,9 +28,20 @@ namespace PepperDash.Essentials.Core
|
|||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
BoolFeedback IsInAutoModeFeedback {get;}
|
BoolFeedback IsInAutoModeFeedback {get;}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the automatic mode is disabled.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("disableAutoMode")]
|
||||||
|
bool DisableAutoMode { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the system is operating in automatic mode.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("isInAutoMode")]
|
[JsonProperty("isInAutoMode")]
|
||||||
bool IsInAutoMode { get; }
|
bool IsInAutoMode { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the collection of rooms associated with the current object.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("rooms")]
|
[JsonProperty("rooms")]
|
||||||
List<IKeyName> Rooms { get; }
|
List<IKeyName> Rooms { get; }
|
||||||
|
|
||||||
@@ -74,6 +85,13 @@ namespace PepperDash.Essentials.Core
|
|||||||
void SetRoomCombinationScenario(string scenarioKey);
|
void SetRoomCombinationScenario(string scenarioKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a scenario for combining rooms, including activation, deactivation, and associated state.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This interface defines the behavior for managing room combination scenarios, including
|
||||||
|
/// activation and deactivation, tracking the active state, and managing related partition states and UI mappings.
|
||||||
|
/// Implementations of this interface are expected to handle the logic for room combinations based on the provided
|
||||||
|
/// partition states and UI mappings.</remarks>
|
||||||
public interface IRoomCombinationScenario : IKeyName
|
public interface IRoomCombinationScenario : IKeyName
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -82,6 +100,9 @@ namespace PepperDash.Essentials.Core
|
|||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
BoolFeedback IsActiveFeedback { get; }
|
BoolFeedback IsActiveFeedback { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the entity is active.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("isActive")]
|
[JsonProperty("isActive")]
|
||||||
bool IsActive { get; }
|
bool IsActive { get; }
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,15 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class Extensions
|
public static class Extensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Stores pending route requests, keyed by the destination device key.
|
||||||
|
/// Used primarily to handle routing requests while a device is cooling down.
|
||||||
|
/// </summary>
|
||||||
private static readonly Dictionary<string, RouteRequest> RouteRequests = new Dictionary<string, RouteRequest>();
|
private static readonly Dictionary<string, RouteRequest> RouteRequests = new Dictionary<string, RouteRequest>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A queue to process route requests and releases sequentially.
|
||||||
|
/// </summary>
|
||||||
private static readonly GenericQueue routeRequestQueue = new GenericQueue("routingQueue");
|
private static readonly GenericQueue routeRequestQueue = new GenericQueue("routingQueue");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -38,16 +45,49 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
ReleaseAndMakeRoute(destination, source, signalType, inputPort, outputPort);
|
ReleaseAndMakeRoute(destination, source, signalType, inputPort, outputPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Will release the existing route to the destination, if a route is found. This does not CLEAR the route, only stop counting usage time on any output ports that have a usage tracker set
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="destination">destination to clear</param>
|
||||||
public static void ReleaseRoute(this IRoutingInputs destination)
|
public static void ReleaseRoute(this IRoutingInputs destination)
|
||||||
{
|
{
|
||||||
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, string.Empty));
|
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, string.Empty, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Will release the existing route to the destination, if a route is found. This does not CLEAR the route, only stop counting usage time on any output ports that have a usage tracker set
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="destination">destination to clear</param>
|
||||||
|
/// <param name="inputPortKey">Input to use to find existing route</param>
|
||||||
public static void ReleaseRoute(this IRoutingInputs destination, string inputPortKey)
|
public static void ReleaseRoute(this IRoutingInputs destination, string inputPortKey)
|
||||||
{
|
{
|
||||||
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, inputPortKey));
|
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, inputPortKey, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears the route on the destination. This will remove any routes that are currently in use
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="destination">Destination</param>
|
||||||
|
public static void ClearRoute(this IRoutingInputs destination)
|
||||||
|
{
|
||||||
|
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, string.Empty, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears the route on the destination. This will remove any routes that are currently in use
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="destination">destination</param>
|
||||||
|
/// <param name="inputPortKey">input to use to find existing route</param>
|
||||||
|
public static void ClearRoute(this IRoutingInputs destination, string inputPortKey)
|
||||||
|
{
|
||||||
|
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, inputPortKey, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the route request for the destination. This will remove any routes that are currently in use
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="destinationKey">destination device key</param>
|
||||||
public static void RemoveRouteRequestForDestination(string destinationKey)
|
public static void RemoveRouteRequestForDestination(string destinationKey)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Removing route request for {destination}", null, destinationKey);
|
Debug.LogMessage(LogEventLevel.Information, "Removing route request for {destination}", null, destinationKey);
|
||||||
@@ -130,6 +170,15 @@ namespace PepperDash.Essentials.Core
|
|||||||
return (audioRouteDescriptor, videoRouteDescriptor);
|
return (audioRouteDescriptor, videoRouteDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Internal method to handle the logic for releasing an existing route and making a new one.
|
||||||
|
/// Handles devices with cooling states by queueing the request.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="destination">The destination device.</param>
|
||||||
|
/// <param name="source">The source device.</param>
|
||||||
|
/// <param name="signalType">The type of signal to route.</param>
|
||||||
|
/// <param name="destinationPort">The specific destination input port (optional).</param>
|
||||||
|
/// <param name="sourcePort">The specific source output port (optional).</param>
|
||||||
private static void ReleaseAndMakeRoute(IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort = null, RoutingOutputPort sourcePort = null)
|
private static void ReleaseAndMakeRoute(IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort = null, RoutingOutputPort sourcePort = null)
|
||||||
{
|
{
|
||||||
if (destination == null) throw new ArgumentNullException(nameof(destination));
|
if (destination == null) throw new ArgumentNullException(nameof(destination));
|
||||||
@@ -184,11 +233,16 @@ namespace PepperDash.Essentials.Core
|
|||||||
Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is NOT cooling down. Removing stored route request and routing to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key);
|
Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is NOT cooling down. Removing stored route request and routing to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination,destinationPort?.Key ?? string.Empty));
|
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination,destinationPort?.Key ?? string.Empty, false));
|
||||||
|
|
||||||
routeRequestQueue.Enqueue(new RouteRequestQueueItem(RunRouteRequest, routeRequest));
|
routeRequestQueue.Enqueue(new RouteRequestQueueItem(RunRouteRequest, routeRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes the actual routing based on a <see cref="RouteRequest"/>.
|
||||||
|
/// Finds the route path, adds it to the collection, and executes the switches.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">The route request details.</param>
|
||||||
private static void RunRouteRequest(RouteRequest request)
|
private static void RunRouteRequest(RouteRequest request)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -216,14 +270,15 @@ namespace PepperDash.Essentials.Core
|
|||||||
{
|
{
|
||||||
Debug.LogMessage(ex, "Exception Running Route Request {request}", null, request);
|
Debug.LogMessage(ex, "Exception Running Route Request {request}", null, request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Will release the existing route on the destination, if it is found in
|
/// Will release the existing route on the destination, if it is found in RouteDescriptorCollection.DefaultCollection
|
||||||
/// RouteDescriptorCollection.DefaultCollection
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="destination"></param>
|
/// <param name="destination"></param>
|
||||||
private static void ReleaseRouteInternal(IRoutingInputs destination, string inputPortKey)
|
/// <param name="inputPortKey"> The input port key to use to find the route. If empty, will use the first available input port</param>
|
||||||
|
/// <param name="clearRoute"> If true, will clear the route on the destination. This will remove any routes that are currently in use</param>
|
||||||
|
private static void ReleaseRouteInternal(IRoutingInputs destination, string inputPortKey, bool clearRoute)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -242,7 +297,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
if (current != null)
|
if (current != null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Releasing current route: {0}", destination, current.Source.Key);
|
Debug.LogMessage(LogEventLevel.Information, "Releasing current route: {0}", destination, current.Source.Key);
|
||||||
current.ReleaseRoutes();
|
current.ReleaseRoutes(clearRoute);
|
||||||
}
|
}
|
||||||
} catch (Exception ex)
|
} catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,8 +7,14 @@
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For fixed-source endpoint devices with an input port
|
||||||
|
/// </summary>
|
||||||
public interface IRoutingSinkWithInputPort :IRoutingSink
|
public interface IRoutingSinkWithInputPort :IRoutingSink
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current input port for this routing sink.
|
||||||
|
/// </summary>
|
||||||
RoutingInputPort CurrentInputPort { get; }
|
RoutingInputPort CurrentInputPort { get; }
|
||||||
}
|
}
|
||||||
/*/// <summary>
|
/*/// <summary>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines an IRoutingOutputs devices as being a source - the start of the chain
|
/// Marker interface to identify a device that acts as the origin of a signal path (<see cref="IRoutingOutputs"/>).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IRoutingSource : IRoutingOutputs
|
public interface IRoutingSource : IRoutingOutputs
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines a routing device (<see cref="IRouting"/>) that supports explicitly clearing a route on an output.
|
||||||
|
/// </summary>
|
||||||
public interface IRoutingWithClear : IRouting
|
public interface IRoutingWithClear : IRouting
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -3,14 +3,25 @@ using System;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate for handling route change events on devices implementing <see cref="IRoutingWithFeedback"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="midpoint">The routing device where the change occurred.</param>
|
||||||
|
/// <param name="newRoute">A descriptor of the new route that was established.</param>
|
||||||
public delegate void RouteChangedEventHandler(IRoutingWithFeedback midpoint, RouteSwitchDescriptor newRoute);
|
public delegate void RouteChangedEventHandler(IRoutingWithFeedback midpoint, RouteSwitchDescriptor newRoute);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines an IRouting with a feedback event
|
/// Defines a routing device (<see cref="IRouting"/>) that provides feedback about its current routes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IRoutingWithFeedback : IRouting
|
public interface IRoutingWithFeedback : IRouting
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a list describing the currently active routes on this device.
|
||||||
|
/// </summary>
|
||||||
List<RouteSwitchDescriptor> CurrentRoutes { get; }
|
List<RouteSwitchDescriptor> CurrentRoutes { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when a route changes on this device.
|
||||||
|
/// </summary>
|
||||||
event RouteChangedEventHandler RouteChanged;
|
event RouteChangedEventHandler RouteChanged;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,18 @@
|
|||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a routing device (typically a transmitter or source) that provides numeric feedback for its current route.
|
||||||
|
/// Extends <see cref="IRoutingNumeric"/>.
|
||||||
|
/// </summary>
|
||||||
public interface ITxRouting : IRoutingNumeric
|
public interface ITxRouting : IRoutingNumeric
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Feedback indicating the currently routed video source by its numeric identifier.
|
||||||
|
/// </summary>
|
||||||
IntFeedback VideoSourceNumericFeedback { get; }
|
IntFeedback VideoSourceNumericFeedback { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Feedback indicating the currently routed audio source by its numeric identifier.
|
||||||
|
/// </summary>
|
||||||
IntFeedback AudioSourceNumericFeedback { get; }
|
IntFeedback AudioSourceNumericFeedback { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Crestron.SimplSharpPro;
|
using Crestron.SimplSharpPro;
|
||||||
|
|
||||||
@@ -9,35 +10,63 @@ using Serilog.Events;
|
|||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an collection of individual route steps between Source and Destination
|
/// Represents a collection of individual route steps between a Source and a Destination device for a specific signal type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class RouteDescriptor
|
public class RouteDescriptor
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The destination device (sink or midpoint) for the route.
|
||||||
|
/// </summary>
|
||||||
public IRoutingInputs Destination { get; private set; }
|
public IRoutingInputs Destination { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The specific input port on the destination device used for this route. Can be null if not specified or applicable.
|
||||||
|
/// </summary>
|
||||||
public RoutingInputPort InputPort { get; private set; }
|
public RoutingInputPort InputPort { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The source device for the route.
|
||||||
|
/// </summary>
|
||||||
public IRoutingOutputs Source { get; private set; }
|
public IRoutingOutputs Source { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of signal being routed (e.g., Audio, Video). This descriptor represents a single signal type.
|
||||||
|
/// </summary>
|
||||||
public eRoutingSignalType SignalType { get; private set; }
|
public eRoutingSignalType SignalType { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A list of individual switching steps required to establish the route.
|
||||||
|
/// </summary>
|
||||||
public List<RouteSwitchDescriptor> Routes { get; private set; }
|
public List<RouteSwitchDescriptor> Routes { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RouteDescriptor"/> class for a route without a specific destination input port.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">The source device.</param>
|
||||||
|
/// <param name="destination">The destination device.</param>
|
||||||
|
/// <param name="signalType">The type of signal being routed.</param>
|
||||||
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType) : this(source, destination, null, signalType)
|
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType) : this(source, destination, null, signalType)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RouteDescriptor"/> class for a route with a specific destination input port.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">The source device.</param>
|
||||||
|
/// <param name="destination">The destination device.</param>
|
||||||
|
/// <param name="inputPort">The destination input port (optional).</param>
|
||||||
|
/// <param name="signalType">The signal type for this route.</param>
|
||||||
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, RoutingInputPort inputPort, eRoutingSignalType signalType)
|
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, RoutingInputPort inputPort, eRoutingSignalType signalType)
|
||||||
{
|
{
|
||||||
Destination = destination;
|
Destination = destination;
|
||||||
|
InputPort = inputPort;
|
||||||
Source = source;
|
Source = source;
|
||||||
SignalType = signalType;
|
SignalType = signalType;
|
||||||
InputPort = inputPort;
|
|
||||||
Routes = new List<RouteSwitchDescriptor>();
|
Routes = new List<RouteSwitchDescriptor>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executes all routes described in this collection. Typically called via
|
/// Executes all the switching steps defined in the <see cref="Routes"/> list.
|
||||||
/// extension method IRoutingInputs.ReleaseAndMakeRoute()
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ExecuteRoutes()
|
public void ExecuteRoutes()
|
||||||
{
|
{
|
||||||
@@ -63,15 +92,27 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Releases all routes in this collection. Typically called via
|
/// Releases the usage tracking for the route and optionally clears the route on the switching devices.
|
||||||
/// extension method IRoutingInputs.ReleaseAndMakeRoute()
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ReleaseRoutes()
|
/// <param name="clearRoute">If true, attempts to clear the route on the switching devices (e.g., set input to null/0).</param>
|
||||||
|
public void ReleaseRoutes(bool clearRoute = false)
|
||||||
{
|
{
|
||||||
foreach (var route in Routes.Where(r => r.SwitchingDevice is IRouting))
|
foreach (var route in Routes.Where(r => r.SwitchingDevice is IRouting))
|
||||||
{
|
{
|
||||||
if (route.SwitchingDevice is IRouting switchingDevice)
|
if (route.SwitchingDevice is IRouting switchingDevice)
|
||||||
{
|
{
|
||||||
|
if(clearRoute)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switchingDevice.ExecuteSwitch(null, route.OutputPort.Selector, SignalType);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError("Error executing switch: {exception}", e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (route.OutputPort == null)
|
if (route.OutputPort == null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -90,6 +131,10 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a string representation of the route descriptor, including source, destination, and individual route steps.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string describing the route.</returns>
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
var routesText = Routes.Select(r => r.ToString()).ToArray();
|
var routesText = Routes.Select(r => r.ToString()).ToArray();
|
||||||
|
|||||||
@@ -4,15 +4,42 @@ using System;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a request to establish a route between a source and a destination device.
|
||||||
|
/// </summary>
|
||||||
public class RouteRequest
|
public class RouteRequest
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The specific input port on the destination device to use for the route. Can be null if the port should be automatically determined or is not applicable.
|
||||||
|
/// </summary>
|
||||||
public RoutingInputPort DestinationPort { get; set; }
|
public RoutingInputPort DestinationPort { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The specific output port on the source device to use for the route. Can be null if the port should be automatically determined or is not applicable.
|
||||||
|
/// </summary>
|
||||||
public RoutingOutputPort SourcePort { get; set; }
|
public RoutingOutputPort SourcePort { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The destination device (sink or midpoint) for the route.
|
||||||
|
/// </summary>
|
||||||
public IRoutingInputs Destination { get; set; }
|
public IRoutingInputs Destination { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The source device for the route.
|
||||||
|
/// </summary>
|
||||||
public IRoutingOutputs Source { get; set; }
|
public IRoutingOutputs Source { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of signal being routed (e.g., Audio, Video, AudioVideo).
|
||||||
|
/// </summary>
|
||||||
public eRoutingSignalType SignalType { get; set; }
|
public eRoutingSignalType SignalType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the route request after a device's cooldown period has finished.
|
||||||
|
/// This method is typically subscribed to the IsCoolingDownFeedback.OutputChange event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The object that triggered the event (usually the cooling device).</param>
|
||||||
|
/// <param name="args">Event arguments indicating the cooldown state change.</param>
|
||||||
public void HandleCooldown(object sender, FeedbackEventArgs args)
|
public void HandleCooldown(object sender, FeedbackEventArgs args)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -39,6 +66,10 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a string representation of the route request.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string describing the source and destination of the route request.</returns>
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"Route {Source?.Key ?? "No Source Device"}:{SourcePort?.Key ?? "auto"} to {Destination?.Key ?? "No Destination Device"}:{DestinationPort?.Key ?? "auto"}";
|
return $"Route {Source?.Key ?? "No Source Device"}:{SourcePort?.Key ?? "auto"} to {Destination?.Key ?? "No Destination Device"}:{DestinationPort?.Key ?? "auto"}";
|
||||||
|
|||||||
@@ -5,17 +5,34 @@ using Serilog.Events;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core.Routing
|
namespace PepperDash.Essentials.Core.Routing
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an item in the route request queue.
|
||||||
|
/// </summary>
|
||||||
public class RouteRequestQueueItem : IQueueMessage
|
public class RouteRequestQueueItem : IQueueMessage
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The action to perform for the route request.
|
||||||
|
/// </summary>
|
||||||
private readonly Action<RouteRequest> action;
|
private readonly Action<RouteRequest> action;
|
||||||
|
/// <summary>
|
||||||
|
/// The route request data.
|
||||||
|
/// </summary>
|
||||||
private readonly RouteRequest routeRequest;
|
private readonly RouteRequest routeRequest;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RouteRequestQueueItem"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="routeAction">The action to perform.</param>
|
||||||
|
/// <param name="request">The route request data.</param>
|
||||||
public RouteRequestQueueItem(Action<RouteRequest> routeAction, RouteRequest request)
|
public RouteRequestQueueItem(Action<RouteRequest> routeAction, RouteRequest request)
|
||||||
{
|
{
|
||||||
action = routeAction;
|
action = routeAction;
|
||||||
routeRequest = request;
|
routeRequest = request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dispatches the route request action.
|
||||||
|
/// </summary>
|
||||||
public void Dispatch()
|
public void Dispatch()
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Dispatching route request {routeRequest}", null, routeRequest);
|
Debug.LogMessage(LogEventLevel.Information, "Dispatching route request {routeRequest}", null, routeRequest);
|
||||||
@@ -23,23 +40,50 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an item in the queue for releasing a route.
|
||||||
|
/// </summary>
|
||||||
public class ReleaseRouteQueueItem : IQueueMessage
|
public class ReleaseRouteQueueItem : IQueueMessage
|
||||||
{
|
{
|
||||||
private readonly Action<IRoutingInputs, string> action;
|
/// <summary>
|
||||||
|
/// The action to perform for releasing the route.
|
||||||
|
/// </summary>
|
||||||
|
private readonly Action<IRoutingInputs, string, bool> action;
|
||||||
|
/// <summary>
|
||||||
|
/// The destination device whose route is being released.
|
||||||
|
/// </summary>
|
||||||
private readonly IRoutingInputs destination;
|
private readonly IRoutingInputs destination;
|
||||||
|
/// <summary>
|
||||||
|
/// The specific input port key on the destination to release, or null/empty for any/default.
|
||||||
|
/// </summary>
|
||||||
private readonly string inputPortKey;
|
private readonly string inputPortKey;
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether to clear the route (send null) or just release the usage tracking.
|
||||||
|
/// </summary>
|
||||||
|
private readonly bool clearRoute;
|
||||||
|
|
||||||
public ReleaseRouteQueueItem(Action<IRoutingInputs, string> action, IRoutingInputs destination, string inputPortKey)
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ReleaseRouteQueueItem"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">The action to perform.</param>
|
||||||
|
/// <param name="destination">The destination device.</param>
|
||||||
|
/// <param name="inputPortKey">The input port key.</param>
|
||||||
|
/// <param name="clearRoute">True to clear the route, false to just release.</param>
|
||||||
|
public ReleaseRouteQueueItem(Action<IRoutingInputs, string, bool> action, IRoutingInputs destination, string inputPortKey, bool clearRoute)
|
||||||
{
|
{
|
||||||
this.action = action;
|
this.action = action;
|
||||||
this.destination = destination;
|
this.destination = destination;
|
||||||
this.inputPortKey = inputPortKey;
|
this.inputPortKey = inputPortKey;
|
||||||
|
this.clearRoute = clearRoute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dispatches the release route action.
|
||||||
|
/// </summary>
|
||||||
public void Dispatch()
|
public void Dispatch()
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Dispatching release route request for {destination}:{inputPortKey}", null, destination?.Key ?? "no destination", string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
|
Debug.LogMessage(LogEventLevel.Information, "Dispatching release route request for {destination}:{inputPortKey}", null, destination?.Key ?? "no destination", string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
|
||||||
action(destination, inputPortKey);
|
action(destination, inputPortKey, clearRoute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,47 @@
|
|||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an individual link for a route
|
/// Represents a single switching step within a larger route, detailing the switching device, input port, and optionally the output port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class RouteSwitchDescriptor
|
public class RouteSwitchDescriptor
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The device performing the switch (derived from the InputPort's parent).
|
||||||
|
/// </summary>
|
||||||
public IRoutingInputs SwitchingDevice { get { return InputPort?.ParentDevice; } }
|
public IRoutingInputs SwitchingDevice { get { return InputPort?.ParentDevice; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The output port being switched from (relevant for matrix switchers). Null for sink devices.
|
||||||
|
/// </summary>
|
||||||
public RoutingOutputPort OutputPort { get; set; }
|
public RoutingOutputPort OutputPort { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// The input port being switched to.
|
||||||
|
/// </summary>
|
||||||
public RoutingInputPort InputPort { get; set; }
|
public RoutingInputPort InputPort { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RouteSwitchDescriptor"/> class for sink devices (no output port).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputPort">The input port being switched to.</param>
|
||||||
public RouteSwitchDescriptor(RoutingInputPort inputPort)
|
public RouteSwitchDescriptor(RoutingInputPort inputPort)
|
||||||
{
|
{
|
||||||
InputPort = inputPort;
|
InputPort = inputPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RouteSwitchDescriptor"/> class for matrix switchers.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="outputPort">The output port being switched from.</param>
|
||||||
|
/// <param name="inputPort">The input port being switched to.</param>
|
||||||
public RouteSwitchDescriptor(RoutingOutputPort outputPort, RoutingInputPort inputPort)
|
public RouteSwitchDescriptor(RoutingOutputPort outputPort, RoutingInputPort inputPort)
|
||||||
{
|
{
|
||||||
InputPort = inputPort;
|
InputPort = inputPort;
|
||||||
OutputPort = outputPort;
|
OutputPort = outputPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a string representation of the route switch descriptor.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string describing the switch operation.</returns>
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
if (SwitchingDevice is IRouting)
|
if (SwitchingDevice is IRouting)
|
||||||
|
|||||||
@@ -5,8 +5,17 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core.Routing
|
namespace PepperDash.Essentials.Core.Routing
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Manages routing feedback by subscribing to route changes on midpoint and sink devices,
|
||||||
|
/// tracing the route back to the original source, and updating the CurrentSourceInfo on sink devices.
|
||||||
|
/// </summary>
|
||||||
public class RoutingFeedbackManager:EssentialsDevice
|
public class RoutingFeedbackManager:EssentialsDevice
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RoutingFeedbackManager"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique key for this manager device.</param>
|
||||||
|
/// <param name="name">The name of this manager device.</param>
|
||||||
public RoutingFeedbackManager(string key, string name): base(key, name)
|
public RoutingFeedbackManager(string key, string name): base(key, name)
|
||||||
{
|
{
|
||||||
AddPreActivationAction(SubscribeForMidpointFeedback);
|
AddPreActivationAction(SubscribeForMidpointFeedback);
|
||||||
@@ -14,6 +23,9 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Subscribes to the RouteChanged event on all devices implementing <see cref="IRoutingWithFeedback"/>.
|
||||||
|
/// </summary>
|
||||||
private void SubscribeForMidpointFeedback()
|
private void SubscribeForMidpointFeedback()
|
||||||
{
|
{
|
||||||
var midpointDevices = DeviceManager.AllDevices.OfType<IRoutingWithFeedback>();
|
var midpointDevices = DeviceManager.AllDevices.OfType<IRoutingWithFeedback>();
|
||||||
@@ -24,6 +36,9 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Subscribes to the InputChanged event on all devices implementing <see cref="IRoutingSinkWithSwitchingWithInputPort"/>.
|
||||||
|
/// </summary>
|
||||||
private void SubscribeForSinkFeedback()
|
private void SubscribeForSinkFeedback()
|
||||||
{
|
{
|
||||||
var sinkDevices = DeviceManager.AllDevices.OfType<IRoutingSinkWithSwitchingWithInputPort>();
|
var sinkDevices = DeviceManager.AllDevices.OfType<IRoutingSinkWithSwitchingWithInputPort>();
|
||||||
@@ -34,6 +49,12 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the RouteChanged event from a midpoint device.
|
||||||
|
/// Triggers an update for all sink devices.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="midpoint">The midpoint device that reported a route change.</param>
|
||||||
|
/// <param name="newRoute">The descriptor of the new route.</param>
|
||||||
private void HandleMidpointUpdate(IRoutingWithFeedback midpoint, RouteSwitchDescriptor newRoute)
|
private void HandleMidpointUpdate(IRoutingWithFeedback midpoint, RouteSwitchDescriptor newRoute)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -51,6 +72,12 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the InputChanged event from a sink device.
|
||||||
|
/// Triggers an update for the specific sink device.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The sink device that reported an input change.</param>
|
||||||
|
/// <param name="currentInputPort">The new input port selected on the sink device.</param>
|
||||||
private void HandleSinkUpdate(IRoutingSinkWithSwitching sender, RoutingInputPort currentInputPort)
|
private void HandleSinkUpdate(IRoutingSinkWithSwitching sender, RoutingInputPort currentInputPort)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -63,6 +90,12 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the CurrentSourceInfo and CurrentSourceInfoKey properties on a destination (sink) device
|
||||||
|
/// based on its currently selected input port by tracing the route back through tie lines.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="destination">The destination sink device to update.</param>
|
||||||
|
/// <param name="inputPort">The currently selected input port on the destination device.</param>
|
||||||
private void UpdateDestination(IRoutingSinkWithSwitching destination, RoutingInputPort inputPort)
|
private void UpdateDestination(IRoutingSinkWithSwitching destination, RoutingInputPort inputPort)
|
||||||
{
|
{
|
||||||
// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Updating destination {destination} with inputPort {inputPort}", this,destination?.Key, inputPort?.Key);
|
// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Updating destination {destination} with inputPort {inputPort}", this,destination?.Key, inputPort?.Key);
|
||||||
@@ -199,6 +232,12 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recursively traces a route back from a given tie line to find the root source tie line.
|
||||||
|
/// It navigates through midpoint devices (<see cref="IRoutingWithFeedback"/>) by checking their current routes.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tieLine">The starting tie line (typically connected to a sink or midpoint).</param>
|
||||||
|
/// <returns>The <see cref="TieLine"/> connected to the original source device, or null if the source cannot be determined.</returns>
|
||||||
private TieLine GetRootTieLine(TieLine tieLine)
|
private TieLine GetRootTieLine(TieLine tieLine)
|
||||||
{
|
{
|
||||||
TieLine nextTieLine = null;
|
TieLine nextTieLine = null;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using System;
|
|||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Basic RoutingInput with no statuses.
|
/// Represents a basic routing input port on a device.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class RoutingInputPort : RoutingPort
|
public class RoutingInputPort : RoutingPort
|
||||||
{
|
{
|
||||||
@@ -41,6 +41,10 @@ namespace PepperDash.Essentials.Core
|
|||||||
ParentDevice = parent;
|
ParentDevice = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a string representation of the input port.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string in the format "ParentDeviceKey|PortKey|SignalType|ConnectionType".</returns>
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{ParentDevice.Key}|{Key}|{Type}|{ConnectionType}";
|
return $"{ParentDevice.Key}|{Key}|{Type}|{ConnectionType}";
|
||||||
|
|||||||
@@ -1,24 +1,25 @@
|
|||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A RoutingInputPort for devices like DM-TX and DM input cards.
|
/// Represents a routing input port that provides video status feedback (e.g., sync, resolution).
|
||||||
/// Will provide video statistics on connected signals
|
/// Suitable for devices like DM transmitters or DM input cards.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class RoutingInputPortWithVideoStatuses : RoutingInputPort
|
public class RoutingInputPortWithVideoStatuses : RoutingInputPort
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Video statuses attached to this port
|
/// Provides feedback outputs for video statuses associated with this port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public VideoStatusOutputs VideoStatus { get; private set; }
|
public VideoStatusOutputs VideoStatus { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor
|
/// Initializes a new instance of the <see cref="RoutingInputPortWithVideoStatuses"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="selector">An object used to refer to this port in the IRouting device's ExecuteSwitch method.
|
/// <param name="key">The unique key for this port.</param>
|
||||||
/// May be string, number, whatever</param>
|
/// <param name="type">The signal type supported by this port.</param>
|
||||||
/// <param name="parent">The IRoutingInputs object this lives on</param>
|
/// <param name="connType">The physical connection type of this port.</param>
|
||||||
/// <param name="funcs">A VideoStatusFuncsWrapper used to assign the callback funcs that will get
|
/// <param name="selector">An object used to refer to this port in the parent device's ExecuteSwitch method.</param>
|
||||||
/// the values for the various stats</param>
|
/// <param name="parent">The <see cref="IRoutingInputs"/> device this port belongs to.</param>
|
||||||
|
/// <param name="funcs">A <see cref="VideoStatusFuncsWrapper"/> containing delegates to retrieve video status values.</param>
|
||||||
public RoutingInputPortWithVideoStatuses(string key,
|
public RoutingInputPortWithVideoStatuses(string key,
|
||||||
eRoutingSignalType type, eRoutingPortConnectionType connType, object selector,
|
eRoutingSignalType type, eRoutingPortConnectionType connType, object selector,
|
||||||
IRoutingInputs parent, VideoStatusFuncsWrapper funcs) :
|
IRoutingInputs parent, VideoStatusFuncsWrapper funcs) :
|
||||||
|
|||||||
@@ -3,32 +3,72 @@
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides event arguments for routing changes, potentially including numeric or port object references.
|
||||||
|
/// </summary>
|
||||||
public class RoutingNumericEventArgs : EventArgs
|
public class RoutingNumericEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The numeric representation of the output, if applicable.
|
||||||
|
/// </summary>
|
||||||
public uint? Output { get; set; }
|
public uint? Output { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// The numeric representation of the input, if applicable.
|
||||||
|
/// </summary>
|
||||||
public uint? Input { get; set; }
|
public uint? Input { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of signal involved in the routing change.
|
||||||
|
/// </summary>
|
||||||
public eRoutingSignalType SigType { get; set; }
|
public eRoutingSignalType SigType { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// The input port involved in the routing change, if applicable.
|
||||||
|
/// </summary>
|
||||||
public RoutingInputPort InputPort { get; set; }
|
public RoutingInputPort InputPort { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// The output port involved in the routing change, if applicable.
|
||||||
|
/// </summary>
|
||||||
public RoutingOutputPort OutputPort { get; set; }
|
public RoutingOutputPort OutputPort { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RoutingNumericEventArgs"/> class using numeric identifiers.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="output">The numeric output identifier.</param>
|
||||||
|
/// <param name="input">The numeric input identifier.</param>
|
||||||
|
/// <param name="sigType">The signal type.</param>
|
||||||
public RoutingNumericEventArgs(uint output, uint input, eRoutingSignalType sigType) : this(output, input, null, null, sigType)
|
public RoutingNumericEventArgs(uint output, uint input, eRoutingSignalType sigType) : this(output, input, null, null, sigType)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RoutingNumericEventArgs"/> class using port objects.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="outputPort">The output port object.</param>
|
||||||
|
/// <param name="inputPort">The input port object.</param>
|
||||||
|
/// <param name="sigType">The signal type.</param>
|
||||||
public RoutingNumericEventArgs(RoutingOutputPort outputPort, RoutingInputPort inputPort,
|
public RoutingNumericEventArgs(RoutingOutputPort outputPort, RoutingInputPort inputPort,
|
||||||
eRoutingSignalType sigType)
|
eRoutingSignalType sigType)
|
||||||
: this(null, null, outputPort, inputPort, sigType)
|
: this(null, null, outputPort, inputPort, sigType)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RoutingNumericEventArgs"/> class with default values.
|
||||||
|
/// </summary>
|
||||||
public RoutingNumericEventArgs()
|
public RoutingNumericEventArgs()
|
||||||
: this(null, null, null, null, 0)
|
: this(null, null, null, null, 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RoutingNumericEventArgs"/> class with potentially mixed identifiers.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="output">The numeric output identifier (optional).</param>
|
||||||
|
/// <param name="input">The numeric input identifier (optional).</param>
|
||||||
|
/// <param name="outputPort">The output port object (optional).</param>
|
||||||
|
/// <param name="inputPort">The input port object (optional).</param>
|
||||||
|
/// <param name="sigType">The signal type.</param>
|
||||||
public RoutingNumericEventArgs(uint? output, uint? input, RoutingOutputPort outputPort,
|
public RoutingNumericEventArgs(uint? output, uint? input, RoutingOutputPort outputPort,
|
||||||
RoutingInputPort inputPort, eRoutingSignalType sigType)
|
RoutingInputPort inputPort, eRoutingSignalType sigType)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,29 +4,46 @@ using System;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a basic routing output port on a device.
|
||||||
|
/// </summary>
|
||||||
public class RoutingOutputPort : RoutingPort
|
public class RoutingOutputPort : RoutingPort
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The IRoutingOutputs object this port lives on
|
/// The IRoutingOutputs object this port lives on.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
///
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IRoutingOutputs ParentDevice { get; private set; }
|
public IRoutingOutputs ParentDevice { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tracks which destinations are currently using this output port.
|
||||||
|
/// </summary>
|
||||||
public InUseTracking InUseTracker { get; private set; }
|
public InUseTracking InUseTracker { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RoutingOutputPort"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="selector">An object used to refer to this port in the IRouting device's ExecuteSwitch method.
|
/// <param name="key">The unique key for this port.</param>
|
||||||
/// May be string, number, whatever</param>
|
/// <param name="type">The signal type supported by this port.</param>
|
||||||
/// <param name="parent">The IRoutingOutputs object this port lives on</param>
|
/// <param name="connType">The physical connection type of this port.</param>
|
||||||
|
/// <param name="selector">An object used to refer to this port in the parent device's ExecuteSwitch method.</param>
|
||||||
|
/// <param name="parent">The <see cref="IRoutingOutputs"/> device this port belongs to.</param>
|
||||||
public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType,
|
public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType,
|
||||||
object selector, IRoutingOutputs parent)
|
object selector, IRoutingOutputs parent)
|
||||||
: this(key, type, connType, selector, parent, false)
|
: this(key, type, connType, selector, parent, false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RoutingOutputPort"/> class, potentially marking it as internal.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique key for this port.</param>
|
||||||
|
/// <param name="type">The signal type supported by this port.</param>
|
||||||
|
/// <param name="connType">The physical connection type of this port.</param>
|
||||||
|
/// <param name="selector">An object used to refer to this port in the parent device's ExecuteSwitch method.</param>
|
||||||
|
/// <param name="parent">The <see cref="IRoutingOutputs"/> device this port belongs to.</param>
|
||||||
|
/// <param name="isInternal">True if this port represents an internal connection within a device (e.g., card to backplane).</param>
|
||||||
public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType,
|
public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType,
|
||||||
object selector, IRoutingOutputs parent, bool isInternal)
|
object selector, IRoutingOutputs parent, bool isInternal)
|
||||||
: base(key, type, connType, selector, isInternal)
|
: base(key, type, connType, selector, isInternal)
|
||||||
@@ -35,6 +52,10 @@ namespace PepperDash.Essentials.Core
|
|||||||
InUseTracker = new InUseTracking();
|
InUseTracker = new InUseTracking();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a string representation of the output port.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string in the format "ParentDeviceKey|PortKey|SignalType|ConnectionType".</returns>
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{ParentDevice.Key}|{Key}|{Type}|{ConnectionType}";
|
return $"{ParentDevice.Key}|{Key}|{Type}|{ConnectionType}";
|
||||||
|
|||||||
@@ -4,18 +4,47 @@
|
|||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base class for RoutingInput and Output ports
|
/// Base class for <see cref="RoutingInputPort"/> and <see cref="RoutingOutputPort"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class RoutingPort : IKeyed
|
public abstract class RoutingPort : IKeyed
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The unique key identifying this port within its parent device.
|
||||||
|
/// </summary>
|
||||||
public string Key { get; private set; }
|
public string Key { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// The type of signal this port handles (e.g., Audio, Video, AudioVideo).
|
||||||
|
/// </summary>
|
||||||
public eRoutingSignalType Type { get; private set; }
|
public eRoutingSignalType Type { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// The physical connection type of this port (e.g., Hdmi, Rca, Dm).
|
||||||
|
/// </summary>
|
||||||
public eRoutingPortConnectionType ConnectionType { get; private set; }
|
public eRoutingPortConnectionType ConnectionType { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// An object (often a number or string) used by the parent routing device to select this port during switching.
|
||||||
|
/// </summary>
|
||||||
public readonly object Selector;
|
public readonly object Selector;
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if this port represents an internal connection within a device (e.g., card to backplane).
|
||||||
|
/// </summary>
|
||||||
public bool IsInternal { get; private set; }
|
public bool IsInternal { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// An object used to match feedback values to this port, if applicable.
|
||||||
|
/// </summary>
|
||||||
public object FeedbackMatchObject { get; set; }
|
public object FeedbackMatchObject { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// A reference to the underlying hardware port object (e.g., SimplSharpPro Port), if applicable.
|
||||||
|
/// </summary>
|
||||||
public object Port { get; set; }
|
public object Port { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RoutingPort"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique key for this port.</param>
|
||||||
|
/// <param name="type">The signal type supported by this port.</param>
|
||||||
|
/// <param name="connType">The physical connection type of this port.</param>
|
||||||
|
/// <param name="selector">The selector object for switching.</param>
|
||||||
|
/// <param name="isInternal">True if this port is internal.</param>
|
||||||
public RoutingPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, object selector, bool isInternal)
|
public RoutingPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, object selector, bool isInternal)
|
||||||
{
|
{
|
||||||
Key = key;
|
Key = key;
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ using Crestron.SimplSharp;
|
|||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// These should correspond directly with the portNames var in the config tool.
|
/// Defines constant string values for common routing port keys.
|
||||||
|
/// These should correspond directly with the portNames var in the config tool.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class RoutingPortNames
|
public class RoutingPortNames
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,14 +4,23 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a connection (tie line) between a <see cref="RoutingOutputPort"/> and a <see cref="RoutingInputPort"/>.
|
||||||
|
/// </summary>
|
||||||
public class TieLine
|
public class TieLine
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The source output port of the tie line.
|
||||||
|
/// </summary>
|
||||||
public RoutingOutputPort SourcePort { get; private set; }
|
public RoutingOutputPort SourcePort { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// The destination input port of the tie line.
|
||||||
|
/// </summary>
|
||||||
public RoutingInputPort DestinationPort { get; private set; }
|
public RoutingInputPort DestinationPort { get; private set; }
|
||||||
//public int InUseCount { get { return DestinationUsingThis.Count; } }
|
//public int InUseCount { get { return DestinationUsingThis.Count; } }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the type of this tie line. Will either be the type of the desination port
|
/// Gets the type of this tie line. Will either be the type of the destination port
|
||||||
/// or the type of OverrideType when it is set.
|
/// or the type of OverrideType when it is set.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public eRoutingSignalType Type
|
public eRoutingSignalType Type
|
||||||
@@ -35,20 +44,27 @@ namespace PepperDash.Essentials.Core
|
|||||||
//List<IRoutingInputs> DestinationUsingThis = new List<IRoutingInputs>();
|
//List<IRoutingInputs> DestinationUsingThis = new List<IRoutingInputs>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For tie lines that represent internal links, like from cards to the matrix in a DM.
|
/// Gets a value indicating whether this tie line represents an internal connection within a device (both source and destination ports are internal).
|
||||||
/// This property is true if SourcePort and DestinationPort IsInternal
|
|
||||||
/// property are both true
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsInternal { get { return SourcePort.IsInternal && DestinationPort.IsInternal; } }
|
public bool IsInternal { get { return SourcePort.IsInternal && DestinationPort.IsInternal; } }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the signal types of the source and destination ports differ.
|
||||||
|
/// </summary>
|
||||||
public bool TypeMismatch { get { return SourcePort.Type != DestinationPort.Type; } }
|
public bool TypeMismatch { get { return SourcePort.Type != DestinationPort.Type; } }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the connection types of the source and destination ports differ.
|
||||||
|
/// </summary>
|
||||||
public bool ConnectionTypeMismatch { get { return SourcePort.ConnectionType != DestinationPort.ConnectionType; } }
|
public bool ConnectionTypeMismatch { get { return SourcePort.ConnectionType != DestinationPort.ConnectionType; } }
|
||||||
|
/// <summary>
|
||||||
|
/// A descriptive note about any type mismatch, if applicable.
|
||||||
|
/// </summary>
|
||||||
public string TypeMismatchNote { get; set; }
|
public string TypeMismatchNote { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Initializes a new instance of the <see cref="TieLine"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sourcePort"></param>
|
/// <param name="sourcePort">The source output port.</param>
|
||||||
/// <param name="destinationPort"></param>
|
/// <param name="destinationPort">The destination input port.</param>
|
||||||
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort)
|
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort)
|
||||||
{
|
{
|
||||||
if (sourcePort == null || destinationPort == null)
|
if (sourcePort == null || destinationPort == null)
|
||||||
@@ -58,9 +74,11 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a tie line with an overriding Type. See help for OverrideType property for info
|
/// Creates a tie line with an overriding Type. See help for OverrideType property for info.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="overrideType">The signal type to limit the link to. Overrides DestinationPort.Type</param>
|
/// <param name="sourcePort">The source output port.</param>
|
||||||
|
/// <param name="destinationPort">The destination input port.</param>
|
||||||
|
/// <param name="overrideType">The signal type to limit the link to. Overrides DestinationPort.Type for routing calculations.</param>
|
||||||
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType? overrideType) :
|
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType? overrideType) :
|
||||||
this(sourcePort, destinationPort)
|
this(sourcePort, destinationPort)
|
||||||
{
|
{
|
||||||
@@ -68,9 +86,11 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a tie line with an overriding Type. See help for OverrideType property for info
|
/// Creates a tie line with an overriding Type. See help for OverrideType property for info.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="overrideType">The signal type to limit the link to. Overrides DestinationPort.Type</param>
|
/// <param name="sourcePort">The source output port.</param>
|
||||||
|
/// <param name="destinationPort">The destination input port.</param>
|
||||||
|
/// <param name="overrideType">The signal type to limit the link to. Overrides DestinationPort.Type for routing calculations.</param>
|
||||||
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType overrideType) :
|
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType overrideType) :
|
||||||
this(sourcePort, destinationPort)
|
this(sourcePort, destinationPort)
|
||||||
{
|
{
|
||||||
@@ -78,18 +98,25 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Will link up video status from supporting inputs to connected outputs
|
/// Will link up video status from supporting inputs to connected outputs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Activate()
|
public void Activate()
|
||||||
{
|
{
|
||||||
// Now does nothing
|
// Now does nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deactivates the tie line.
|
||||||
|
/// </summary>
|
||||||
public void Deactivate()
|
public void Deactivate()
|
||||||
{
|
{
|
||||||
// Now does nothing
|
// Now does nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a string representation of the tie line.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string describing the source, destination, and type of the tie line.</returns>
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return string.Format("Tie line: {0}:{1} --> {2}:{3} {4}", SourcePort.ParentDevice.Key, SourcePort.Key,
|
return string.Format("Tie line: {0}:{1} --> {2}:{3} {4}", SourcePort.ParentDevice.Key, SourcePort.Key,
|
||||||
@@ -99,8 +126,14 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
//********************************************************************************
|
//********************************************************************************
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a collection of <see cref="TieLine"/> objects.
|
||||||
|
/// </summary>
|
||||||
public class TieLineCollection : List<TieLine>
|
public class TieLineCollection : List<TieLine>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the default singleton instance of the <see cref="TieLineCollection"/>.
|
||||||
|
/// </summary>
|
||||||
public static TieLineCollection Default
|
public static TieLineCollection Default
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -111,6 +144,9 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Backing field for the singleton instance.
|
||||||
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
private static TieLineCollection _Default;
|
private static TieLineCollection _Default;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
using Crestron.SimplSharp.CrestronIO;
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
@@ -15,15 +13,44 @@ using Serilog.Events;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core.Config
|
namespace PepperDash.Essentials.Core.Config
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the configuration data for a single tie line between two routing ports.
|
||||||
|
/// </summary>
|
||||||
public class TieLineConfig
|
public class TieLineConfig
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The key of the source device.
|
||||||
|
/// </summary>
|
||||||
public string SourceKey { get; set; }
|
public string SourceKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The key of the source card (if applicable, e.g., in a modular chassis).
|
||||||
|
/// </summary>
|
||||||
public string SourceCard { get; set; }
|
public string SourceCard { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The key of the source output port.
|
||||||
|
/// </summary>
|
||||||
public string SourcePort { get; set; }
|
public string SourcePort { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The key of the destination device.
|
||||||
|
/// </summary>
|
||||||
public string DestinationKey { get; set; }
|
public string DestinationKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The key of the destination card (if applicable).
|
||||||
|
/// </summary>
|
||||||
public string DestinationCard { get; set; }
|
public string DestinationCard { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The key of the destination input port.
|
||||||
|
/// </summary>
|
||||||
public string DestinationPort { get; set; }
|
public string DestinationPort { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional override for the signal type of the tie line. If set, this overrides the destination port's type for routing calculations.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
[JsonConverter(typeof(StringEnumConverter))]
|
[JsonConverter(typeof(StringEnumConverter))]
|
||||||
public eRoutingSignalType? OverrideType { get; set; }
|
public eRoutingSignalType? OverrideType { get; set; }
|
||||||
@@ -73,11 +100,19 @@ namespace PepperDash.Essentials.Core.Config
|
|||||||
return new TieLine(sourceOutputPort, destinationInputPort, OverrideType);
|
return new TieLine(sourceOutputPort, destinationInputPort, OverrideType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logs an error message related to creating this tie line configuration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="msg">The specific error message.</param>
|
||||||
void LogError(string msg)
|
void LogError(string msg)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Error, "WARNING: Cannot create tie line: {message}:\r {tieLineConfig}",null, msg, this);
|
Debug.LogMessage(LogEventLevel.Error, "WARNING: Cannot create tie line: {message}:\r {tieLineConfig}",null, msg, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a string representation of the tie line configuration.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string describing the source and destination of the configured tie line.</returns>
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return string.Format("{0}.{1}.{2} --> {3}.{4}.{5}", SourceKey, SourceCard, SourcePort,
|
return string.Format("{0}.{1}.{2} --> {3}.{4}.{5}", SourceKey, SourceCard, SourcePort,
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
|
|
||||||
SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist);
|
SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist);
|
||||||
|
|
||||||
for (int i = 0; i < joinMap.NumberOfPresets.JoinSpan; i++)
|
for (int i = 0; i < joinMap.PresetRecallStart.JoinSpan; i++)
|
||||||
{
|
{
|
||||||
int tempNum = i;
|
int tempNum = i;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Devices.Common.Codec.Cisco
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the available tracking modes for a Cisco codec's Presenter Track feature.
|
||||||
|
/// </summary>
|
||||||
|
public enum ePresenterTrackMode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Presenter Track is turned off.
|
||||||
|
/// </summary>
|
||||||
|
Off,
|
||||||
|
/// <summary>
|
||||||
|
/// Presenter Track follows the speaker's movements.
|
||||||
|
/// </summary>
|
||||||
|
Follow,
|
||||||
|
/// <summary>
|
||||||
|
/// Presenter Track is set to background mode, where it tracks the speaker but does not actively follow.
|
||||||
|
/// </summary>
|
||||||
|
Background,
|
||||||
|
/// <summary>
|
||||||
|
/// Presenter Track is set to persistent mode, where it maintains a fixed position or focus on the speaker.
|
||||||
|
/// </summary>
|
||||||
|
Persistent
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the Presenter Track controls for a Cisco codec.
|
||||||
|
/// </summary>
|
||||||
|
public interface IPresenterTrack : IKeyed
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
bool PresenterTrackAvailability { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Feedback indicating whether Presenter Track is available.
|
||||||
|
/// </summary>
|
||||||
|
BoolFeedback PresenterTrackAvailableFeedback { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Feedback indicating the current status of Presenter Track is off
|
||||||
|
/// </summary>
|
||||||
|
BoolFeedback PresenterTrackStatusOffFeedback { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Feedback indicating the current status of Presenter Track is follow
|
||||||
|
/// </summary>
|
||||||
|
BoolFeedback PresenterTrackStatusFollowFeedback { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Feedback indicating the current status of Presenter Track is background
|
||||||
|
/// </summary>
|
||||||
|
BoolFeedback PresenterTrackStatusBackgroundFeedback { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Feedback indicating the current status of Presenter Track is persistent
|
||||||
|
/// </summary>
|
||||||
|
BoolFeedback PresenterTrackStatusPersistentFeedback { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates the current status of Presenter Track.
|
||||||
|
/// </summary>
|
||||||
|
bool PresenterTrackStatus { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Turns off Presenter Track.
|
||||||
|
/// </summary>
|
||||||
|
void PresenterTrackOff();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Turns on Presenter Track in follow mode.
|
||||||
|
/// </summary>
|
||||||
|
void PresenterTrackFollow();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Turns on Presenter Track in background mode.
|
||||||
|
/// </summary>
|
||||||
|
void PresenterTrackBackground();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Turns on Presenter Track in persistent mode.
|
||||||
|
/// </summary>
|
||||||
|
void PresenterTrackPersistent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Devices.Common.Codec.Cisco
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the available tracking modes for a Cisco codec
|
||||||
|
/// </summary>
|
||||||
|
public interface ISpeakerTrack : IKeyed
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether Speaker Track is available on the codec.
|
||||||
|
/// </summary>
|
||||||
|
bool SpeakerTrackAvailability { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
BoolFeedback SpeakerTrackAvailableFeedback { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Feedback indicating the current status of Speaker Track is off
|
||||||
|
/// </summary>
|
||||||
|
bool SpeakerTrackStatus { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Turns Speaker Track off
|
||||||
|
/// </summary>
|
||||||
|
void SpeakerTrackOff();
|
||||||
|
/// <summary>
|
||||||
|
/// Turns Speaker Track on
|
||||||
|
/// </summary>
|
||||||
|
void SpeakerTrackOn();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,9 +18,13 @@ namespace PepperDash.Essentials.Devices.Common.DSP
|
|||||||
|
|
||||||
public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
|
public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
|
||||||
|
|
||||||
public DspBase(string key, string name) :
|
public DspBase(string key, string name) :
|
||||||
base(key, name)
|
base(key, name)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
LevelControlPoints = new Dictionary<string, IBasicVolumeWithFeedback>();
|
||||||
|
DialerControlPoints = new Dictionary<string, DspControlPoint>();
|
||||||
|
SwitcherControlPoints = new Dictionary<string, DspControlPoint>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.Generic
|
namespace PepperDash.Essentials.Devices.Common.Generic
|
||||||
{
|
{
|
||||||
public class GenericSink : EssentialsDevice, IRoutingSink
|
public class GenericSink : EssentialsDevice, IRoutingSinkWithInputPort
|
||||||
{
|
{
|
||||||
public GenericSink(string key, string name) : base(key, name)
|
public GenericSink(string key, string name) : base(key, name)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,9 +8,10 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.SoftCodec
|
namespace PepperDash.Essentials.Devices.Common.SoftCodec
|
||||||
{
|
{
|
||||||
public class GenericSoftCodec : EssentialsDevice, IRoutingSource, IRoutingOutputs, IRoutingSinkWithSwitching
|
public class GenericSoftCodec : EssentialsDevice, IRoutingSource, IRoutingSinkWithSwitchingWithInputPort
|
||||||
{
|
{
|
||||||
private RoutingInputPort _currentInputPort;
|
private RoutingInputPort _currentInputPort;
|
||||||
|
|
||||||
public RoutingInputPort CurrentInputPort {
|
public RoutingInputPort CurrentInputPort {
|
||||||
get => _currentInputPort;
|
get => _currentInputPort;
|
||||||
set
|
set
|
||||||
|
|||||||
@@ -12,20 +12,45 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IHasCodecRoomPresets
|
public interface IHasCodecRoomPresets
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Event that is raised when the list of room presets has changed.
|
||||||
|
/// </summary>
|
||||||
event EventHandler<EventArgs> CodecRoomPresetsListHasChanged;
|
event EventHandler<EventArgs> CodecRoomPresetsListHasChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// List of near end presets that can be recalled.
|
||||||
|
/// </summary>
|
||||||
List<CodecRoomPreset> NearEndPresets { get; }
|
List<CodecRoomPreset> NearEndPresets { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// List of far end presets that can be recalled.
|
||||||
|
/// </summary>
|
||||||
List<CodecRoomPreset> FarEndRoomPresets { get; }
|
List<CodecRoomPreset> FarEndRoomPresets { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Selects a near end preset by its ID.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="preset"></param>
|
||||||
void CodecRoomPresetSelect(int preset);
|
void CodecRoomPresetSelect(int preset);
|
||||||
|
|
||||||
void CodecRoomPresetStore(int preset, string description);
|
/// <summary>
|
||||||
|
/// Stores a near end preset with the given ID and description.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="preset"></param>
|
||||||
|
/// <param name="description"></param>
|
||||||
|
void CodecRoomPresetStore(int preset, string description);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Selects a far end preset by its ID. This is typically used to recall a preset that has been defined on the far end codec.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="preset"></param>
|
||||||
void SelectFarEndPreset(int preset);
|
void SelectFarEndPreset(int preset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class RoomPresets
|
/// <summary>
|
||||||
|
/// Static class for converting non-generic RoomPresets to generic CameraPresets.
|
||||||
|
/// </summary>
|
||||||
|
public static class RoomPresets
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts non-generic RoomPresets to generic CameraPresets
|
/// Converts non-generic RoomPresets to generic CameraPresets
|
||||||
@@ -47,6 +72,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CodecRoomPreset : PresetBase
|
public class CodecRoomPreset : PresetBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <param name="description"></param>
|
||||||
|
/// <param name="def"></param>
|
||||||
|
/// <param name="isDef"></param>
|
||||||
public CodecRoomPreset(int id, string description, bool def, bool isDef)
|
public CodecRoomPreset(int id, string description, bool def, bool isDef)
|
||||||
: base(id, description, def, isDef)
|
: base(id, description, def, isDef)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,29 +3,51 @@ using PepperDash.Essentials.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer
|
namespace PepperDash.Essentials.AppServer
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the content of a source selection message
|
||||||
|
/// </summary>
|
||||||
public class SourceSelectMessageContent
|
public class SourceSelectMessageContent
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the key of the source list item to select
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("sourceListItemKey")]
|
[JsonProperty("sourceListItemKey")]
|
||||||
public string SourceListItemKey { get; set; }
|
public string SourceListItemKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the key of the source list containing the item
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("sourceListKey")]
|
[JsonProperty("sourceListKey")]
|
||||||
public string SourceListKey { get; set; }
|
public string SourceListKey { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a direct routing operation between a source and destination
|
||||||
|
/// </summary>
|
||||||
public class DirectRoute
|
public class DirectRoute
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the key of the source device
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("sourceKey")]
|
[JsonProperty("sourceKey")]
|
||||||
public string SourceKey { get; set; }
|
public string SourceKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the key of the destination device
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("destinationKey")]
|
[JsonProperty("destinationKey")]
|
||||||
public string DestinationKey { get; set; }
|
public string DestinationKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the type of routing signal (Audio, Video, etc.)
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("signalType")]
|
[JsonProperty("signalType")]
|
||||||
public eRoutingSignalType SignalType { get; set; }
|
public eRoutingSignalType SignalType { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Delegate for press and hold actions with boolean state parameter
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="b"></param>
|
/// <param name="b">The state of the press and hold action</param>
|
||||||
public delegate void PressAndHoldAction(bool b);
|
public delegate void PressAndHoldAction(bool b);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,35 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Core.Logging;
|
using PepperDash.Core.Logging;
|
||||||
using PepperDash.Essentials.AppServer;
|
using PepperDash.Essentials.AppServer;
|
||||||
using PepperDash.Essentials.AppServer.Messengers;
|
using PepperDash.Essentials.AppServer.Messengers;
|
||||||
using System.Linq;
|
|
||||||
using DisplayBase = PepperDash.Essentials.Devices.Common.Displays.DisplayBase;
|
using DisplayBase = PepperDash.Essentials.Devices.Common.Displays.DisplayBase;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Room.MobileControl
|
namespace PepperDash.Essentials.Room.MobileControl
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger that provides mobile control interface for display devices
|
||||||
|
/// </summary>
|
||||||
public class DisplayBaseMessenger : MessengerBase
|
public class DisplayBaseMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The display device this messenger is associated with
|
||||||
|
/// </summary>
|
||||||
private readonly DisplayBase display;
|
private readonly DisplayBase display;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the DisplayBaseMessenger class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique key for this messenger</param>
|
||||||
|
/// <param name="messagePath">The message path for routing display control messages</param>
|
||||||
|
/// <param name="device">The display device to control</param>
|
||||||
public DisplayBaseMessenger(string key, string messagePath, DisplayBase device) : base(key, messagePath, device)
|
public DisplayBaseMessenger(string key, string messagePath, DisplayBase device) : base(key, messagePath, device)
|
||||||
{
|
{
|
||||||
display = device;
|
display = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|||||||
@@ -4,15 +4,28 @@ using PepperDash.Essentials.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Room.MobileControl
|
namespace PepperDash.Essentials.Room.MobileControl
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger that provides mobile control interface for devices with channel control functionality
|
||||||
|
/// </summary>
|
||||||
public class IChannelMessenger : MessengerBase
|
public class IChannelMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The channel control device this messenger is associated with
|
||||||
|
/// </summary>
|
||||||
private readonly IChannel channelDevice;
|
private readonly IChannel channelDevice;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the IChannelMessenger class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique key for this messenger</param>
|
||||||
|
/// <param name="messagePath">The message path for routing channel control messages</param>
|
||||||
|
/// <param name="device">The device that implements channel control functionality</param>
|
||||||
public IChannelMessenger(string key, string messagePath, IChannel device) : base(key, messagePath, device as IKeyName)
|
public IChannelMessenger(string key, string messagePath, IChannel device) : base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
channelDevice = device;
|
channelDevice = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|||||||
@@ -4,14 +4,25 @@ using PepperDash.Essentials.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Room.MobileControl
|
namespace PepperDash.Essentials.Room.MobileControl
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger for devices that implement IColor interface
|
||||||
|
/// </summary>
|
||||||
public class IColorMessenger : MessengerBase
|
public class IColorMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly IColor colorDevice;
|
private readonly IColor colorDevice;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the IColorMessenger class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
|
/// <param name="device">Device that implements IColor</param>
|
||||||
public IColorMessenger(string key, string messagePath, IColor device) : base(key, messagePath, device as IKeyName)
|
public IColorMessenger(string key, string messagePath, IColor device) : base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
colorDevice = device as IColor;
|
colorDevice = device as IColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|||||||
@@ -4,15 +4,28 @@ using PepperDash.Essentials.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Room.MobileControl
|
namespace PepperDash.Essentials.Room.MobileControl
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger that provides mobile control interface for devices with directional pad functionality
|
||||||
|
/// </summary>
|
||||||
public class IDPadMessenger : MessengerBase
|
public class IDPadMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The directional pad device this messenger is associated with
|
||||||
|
/// </summary>
|
||||||
private readonly IDPad dpadDevice;
|
private readonly IDPad dpadDevice;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the IDPadMessenger class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique key for this messenger</param>
|
||||||
|
/// <param name="messagePath">The message path for routing directional pad messages</param>
|
||||||
|
/// <param name="device">The device that implements directional pad functionality</param>
|
||||||
public IDPadMessenger(string key, string messagePath, IDPad device) : base(key, messagePath, device as IKeyName)
|
public IDPadMessenger(string key, string messagePath, IDPad device) : base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
dpadDevice = device;
|
dpadDevice = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|||||||
@@ -4,14 +4,25 @@ using PepperDash.Essentials.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Room.MobileControl
|
namespace PepperDash.Essentials.Room.MobileControl
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger for devices that implement IDvr interface
|
||||||
|
/// </summary>
|
||||||
public class IDvrMessenger : MessengerBase
|
public class IDvrMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly IDvr dvrDevice;
|
private readonly IDvr dvrDevice;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the IDvrMessenger class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
|
/// <param name="device">Device that implements IDvr</param>
|
||||||
public IDvrMessenger(string key, string messagePath, IDvr device) : base(key, messagePath, device as IKeyName)
|
public IDvrMessenger(string key, string messagePath, IDvr device) : base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
dvrDevice = device;
|
dvrDevice = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|||||||
@@ -4,14 +4,28 @@ using PepperDash.Essentials.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Room.MobileControl
|
namespace PepperDash.Essentials.Room.MobileControl
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger that provides mobile control interface for devices with power control functionality
|
||||||
|
/// </summary>
|
||||||
public class IHasPowerMessenger : MessengerBase
|
public class IHasPowerMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The power control device this messenger is associated with
|
||||||
|
/// </summary>
|
||||||
private readonly IHasPowerControl powerDevice;
|
private readonly IHasPowerControl powerDevice;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the IHasPowerMessenger class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique key for this messenger</param>
|
||||||
|
/// <param name="messagePath">The message path for routing power control messages</param>
|
||||||
|
/// <param name="device">The device that implements power control functionality</param>
|
||||||
public IHasPowerMessenger(string key, string messagePath, IHasPowerControl device) : base(key, messagePath, device as IKeyName)
|
public IHasPowerMessenger(string key, string messagePath, IHasPowerControl device) : base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
powerDevice = device;
|
powerDevice = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|||||||
@@ -4,14 +4,28 @@ using PepperDash.Essentials.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Room.MobileControl
|
namespace PepperDash.Essentials.Room.MobileControl
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger that provides mobile control interface for devices with numeric keypad functionality
|
||||||
|
/// </summary>
|
||||||
public class INumericKeypadMessenger : MessengerBase
|
public class INumericKeypadMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The numeric keypad device this messenger is associated with
|
||||||
|
/// </summary>
|
||||||
private readonly INumericKeypad keypadDevice;
|
private readonly INumericKeypad keypadDevice;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the INumericKeypadMessenger class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique key for this messenger</param>
|
||||||
|
/// <param name="messagePath">The message path for routing numeric keypad messages</param>
|
||||||
|
/// <param name="device">The device that implements numeric keypad functionality</param>
|
||||||
public INumericKeypadMessenger(string key, string messagePath, INumericKeypad device) : base(key, messagePath, device as IKeyName)
|
public INumericKeypadMessenger(string key, string messagePath, INumericKeypad device) : base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
keypadDevice = device;
|
keypadDevice = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|||||||
@@ -4,14 +4,25 @@ using PepperDash.Essentials.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Room.MobileControl
|
namespace PepperDash.Essentials.Room.MobileControl
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger for devices that implement ISetTopBoxControls interface
|
||||||
|
/// </summary>
|
||||||
public class ISetTopBoxControlsMessenger : MessengerBase
|
public class ISetTopBoxControlsMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly ISetTopBoxControls stbDevice;
|
private readonly ISetTopBoxControls stbDevice;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the ISetTopBoxControlsMessenger class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
|
/// <param name="device">Device that implements ISetTopBoxControls</param>
|
||||||
public ISetTopBoxControlsMessenger(string key, string messagePath, ISetTopBoxControls device) : base(key, messagePath, device as IKeyName)
|
public ISetTopBoxControlsMessenger(string key, string messagePath, ISetTopBoxControls device) : base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
stbDevice = device;
|
stbDevice = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
@@ -32,6 +43,9 @@ namespace PepperDash.Essentials.Room.MobileControl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// State message for set top box controls
|
||||||
|
/// </summary>
|
||||||
public class SetTopBoxControlsState : DeviceStateMessageBase
|
public class SetTopBoxControlsState : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -4,14 +4,28 @@ using PepperDash.Essentials.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Room.MobileControl
|
namespace PepperDash.Essentials.Room.MobileControl
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger that provides mobile control interface for devices with transport control functionality
|
||||||
|
/// </summary>
|
||||||
public class ITransportMessenger : MessengerBase
|
public class ITransportMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The transport control device this messenger is associated with
|
||||||
|
/// </summary>
|
||||||
private readonly ITransport transportDevice;
|
private readonly ITransport transportDevice;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the ITransportMessenger class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique key for this messenger</param>
|
||||||
|
/// <param name="messagePath">The message path for routing transport control messages</param>
|
||||||
|
/// <param name="device">The device that implements transport control functionality</param>
|
||||||
public ITransportMessenger(string key, string messagePath, ITransport device) : base(key, messagePath, device as IKeyName)
|
public ITransportMessenger(string key, string messagePath, ITransport device) : base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
transportDevice = device;
|
transportDevice = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Essentials.Devices.Common.AudioCodec;
|
using PepperDash.Essentials.Devices.Common.AudioCodec;
|
||||||
using PepperDash.Essentials.Devices.Common.Codec;
|
using PepperDash.Essentials.Devices.Common.Codec;
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
@@ -29,12 +29,16 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
codec.CallStatusChange += Codec_CallStatusChange;
|
codec.CallStatusChange += Codec_CallStatusChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers actions for handling audio codec operations.
|
||||||
|
/// Includes call control, status reporting, and audio codec management.
|
||||||
|
/// </summary>
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
|
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|
||||||
AddAction("/fullStatus", (id, content) => SendAtcFullMessageObject());
|
AddAction("/fullStatus", (id, content) => SendAtcFullMessageObject(id));
|
||||||
AddAction("/dial", (id, content) =>
|
AddAction("/dial", (id, content) =>
|
||||||
{
|
{
|
||||||
var msg = content.ToObject<MobileControlSimpleContent<string>>();
|
var msg = content.ToObject<MobileControlSimpleContent<string>>();
|
||||||
@@ -97,7 +101,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
/// Helper method to build call status for vtc
|
/// Helper method to build call status for vtc
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private void SendAtcFullMessageObject()
|
private void SendAtcFullMessageObject(string id = null)
|
||||||
{
|
{
|
||||||
var info = Codec.CodecInfo;
|
var info = Codec.CodecInfo;
|
||||||
|
|
||||||
@@ -109,7 +113,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
{
|
{
|
||||||
phoneNumber = info.PhoneNumber
|
phoneNumber = info.PhoneNumber
|
||||||
}
|
}
|
||||||
})
|
}), clientId: id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using PepperDash.Essentials.Devices.Common.Cameras;
|
using PepperDash.Essentials.Devices.Common.Cameras;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides messaging capabilities for camera control operations.
|
||||||
|
/// Handles camera movement, zoom, preset management, and camera status reporting.
|
||||||
|
/// </summary>
|
||||||
public class CameraBaseMessenger : MessengerBase
|
public class CameraBaseMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -45,11 +49,15 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers actions for handling camera control operations.
|
||||||
|
/// Includes camera movement, zoom, preset management, and full status reporting.
|
||||||
|
/// </summary>
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|
||||||
AddAction("/fullStatus", (id, content) => SendCameraFullMessageObject());
|
AddAction("/fullStatus", (id, content) => SendCameraFullMessageObject(id));
|
||||||
|
|
||||||
|
|
||||||
if (Camera is IHasCameraPtzControl ptzCamera)
|
if (Camera is IHasCameraPtzControl ptzCamera)
|
||||||
@@ -166,7 +174,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper method to update the full status of the camera
|
/// Helper method to update the full status of the camera
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void SendCameraFullMessageObject()
|
private void SendCameraFullMessageObject(string id = null)
|
||||||
{
|
{
|
||||||
var presetList = new List<CameraPreset>();
|
var presetList = new List<CameraPreset>();
|
||||||
|
|
||||||
@@ -181,7 +189,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
cameraMode = GetCameraMode(),
|
cameraMode = GetCameraMode(),
|
||||||
hasPresets = Camera is IHasCameraPresets,
|
hasPresets = Camera is IHasCameraPresets,
|
||||||
presets = presetList
|
presets = presetList
|
||||||
})
|
}), clientId: id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,41 +1,93 @@
|
|||||||
using Newtonsoft.Json;
|
using System.Timers;
|
||||||
|
using Independentsoft.Exchange;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core.DeviceInfo;
|
using PepperDash.Essentials.Core.DeviceInfo;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Facilitates communication of device information by providing mechanisms for status updates and device
|
||||||
|
/// information reporting.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>The <see cref="DeviceInfoMessenger"/> class integrates with an <see
|
||||||
|
/// cref="IDeviceInfoProvider"/> to manage device-specific information. It uses a debounce timer to limit the
|
||||||
|
/// frequency of updates, ensuring efficient communication. The timer is initialized with a 1-second interval and
|
||||||
|
/// is disabled by default. This class also subscribes to device information change events and provides actions for
|
||||||
|
/// reporting full device status and triggering updates.</remarks>
|
||||||
public class DeviceInfoMessenger : MessengerBase
|
public class DeviceInfoMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly IDeviceInfoProvider _deviceInfoProvider;
|
private readonly IDeviceInfoProvider _deviceInfoProvider;
|
||||||
|
|
||||||
|
private readonly Timer debounceTimer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="DeviceInfoMessenger"/> class, which facilitates communication
|
||||||
|
/// of device information.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>The messenger uses a debounce timer to limit the frequency of certain operations. The
|
||||||
|
/// timer is initialized with a 1-second interval and is disabled by default.</remarks>
|
||||||
|
/// <param name="key">A unique identifier for the messenger instance.</param>
|
||||||
|
/// <param name="messagePath">The path used for sending and receiving messages.</param>
|
||||||
|
/// <param name="device">An implementation of <see cref="IDeviceInfoProvider"/> that provides device-specific information.</param>
|
||||||
public DeviceInfoMessenger(string key, string messagePath, IDeviceInfoProvider device) : base(key, messagePath, device as Device)
|
public DeviceInfoMessenger(string key, string messagePath, IDeviceInfoProvider device) : base(key, messagePath, device as Device)
|
||||||
{
|
{
|
||||||
_deviceInfoProvider = device;
|
_deviceInfoProvider = device;
|
||||||
|
|
||||||
|
debounceTimer = new Timer(1000)
|
||||||
|
{
|
||||||
|
Enabled = false,
|
||||||
|
AutoReset = false
|
||||||
|
};
|
||||||
|
|
||||||
|
debounceTimer.Elapsed += DebounceTimer_Elapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DebounceTimer_Elapsed(object sender, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
PostStatusMessage(JToken.FromObject(new
|
||||||
|
{
|
||||||
|
deviceInfo = _deviceInfoProvider.DeviceInfo
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers actions and event handlers for device information updates and status reporting.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This method sets up actions for handling device status updates and reporting full
|
||||||
|
/// device status. It also subscribes to the <see cref="IDeviceInfoProvider.DeviceInfoChanged"/> event to
|
||||||
|
/// trigger debounced updates when the device information changes.</remarks>
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|
||||||
_deviceInfoProvider.DeviceInfoChanged += (o, a) =>
|
_deviceInfoProvider.DeviceInfoChanged += (o, a) =>
|
||||||
{
|
{
|
||||||
PostStatusMessage(JToken.FromObject(new
|
debounceTimer.Stop();
|
||||||
{
|
debounceTimer.Start();
|
||||||
deviceInfo = a.DeviceInfo
|
|
||||||
}));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
AddAction("/fullStatus", (id, context) => PostStatusMessage(new DeviceInfoStateMessage
|
AddAction("/fullStatus", (id, context) => PostStatusMessage(new DeviceInfoStateMessage
|
||||||
{
|
{
|
||||||
DeviceInfo = _deviceInfoProvider.DeviceInfo
|
DeviceInfo = _deviceInfoProvider.DeviceInfo
|
||||||
}));
|
}, id));
|
||||||
|
|
||||||
AddAction("/update", (id, context) => _deviceInfoProvider.UpdateDeviceInfo());
|
AddAction("/update", (id, context) => _deviceInfoProvider.UpdateDeviceInfo());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a message containing the state information of a device, including detailed device information.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This class is used to encapsulate the state of a device along with its associated
|
||||||
|
/// information. It extends <see cref="DeviceStateMessageBase"/> to provide additional details about the
|
||||||
|
/// device.</remarks>
|
||||||
public class DeviceInfoStateMessage : DeviceStateMessageBase
|
public class DeviceInfoStateMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the device information.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("deviceInfo")]
|
[JsonProperty("deviceInfo")]
|
||||||
public DeviceInfo DeviceInfo { get; set; }
|
public DeviceInfo DeviceInfo { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,40 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Core.Logging;
|
using PepperDash.Core.Logging;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||||
using PepperDash.Essentials.Core.Presets;
|
using PepperDash.Essentials.Core.Presets;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides messaging capabilities for device preset management operations.
|
||||||
|
/// Handles preset selection, recall, and preset list management.
|
||||||
|
/// </summary>
|
||||||
public class DevicePresetsModelMessenger : MessengerBase
|
public class DevicePresetsModelMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly ITvPresetsProvider _presetsDevice;
|
private readonly ITvPresetsProvider _presetsDevice;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="DevicePresetsModelMessenger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique identifier for this messenger instance.</param>
|
||||||
|
/// <param name="messagePath">The message path for preset control messages.</param>
|
||||||
|
/// <param name="presetsDevice">The device that provides preset functionality.</param>
|
||||||
public DevicePresetsModelMessenger(string key, string messagePath, ITvPresetsProvider presetsDevice)
|
public DevicePresetsModelMessenger(string key, string messagePath, ITvPresetsProvider presetsDevice)
|
||||||
: base(key, messagePath, presetsDevice as Device)
|
: base(key, messagePath, presetsDevice as Device)
|
||||||
{
|
{
|
||||||
_presetsDevice = presetsDevice;
|
_presetsDevice = presetsDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendPresets()
|
private void SendPresets(string id = null)
|
||||||
{
|
{
|
||||||
PostStatusMessage(new PresetStateMessage
|
PostStatusMessage(new PresetStateMessage
|
||||||
{
|
{
|
||||||
Favorites = _presetsDevice.TvPresets.PresetsList
|
Favorites = _presetsDevice.TvPresets.PresetsList
|
||||||
});
|
}, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecallPreset(ISetTopBoxNumericKeypad device, string channel)
|
private void RecallPreset(ISetTopBoxNumericKeypad device, string channel)
|
||||||
@@ -40,6 +50,10 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
|
|
||||||
#region Overrides of MessengerBase
|
#region Overrides of MessengerBase
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers actions for handling device preset operations.
|
||||||
|
/// Includes preset selection, recall, and full status reporting.
|
||||||
|
/// </summary>
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -48,7 +62,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
this.LogInformation("getting full status for client {id}", id);
|
this.LogInformation("getting full status for client {id}", id);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SendPresets();
|
SendPresets(id);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -83,17 +97,32 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a preset channel message for device preset operations.
|
||||||
|
/// </summary>
|
||||||
public class PresetChannelMessage
|
public class PresetChannelMessage
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the preset channel information.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("preset")]
|
[JsonProperty("preset")]
|
||||||
public PresetChannel Preset;
|
public PresetChannel Preset;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the device key associated with the preset.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("deviceKey")]
|
[JsonProperty("deviceKey")]
|
||||||
public string DeviceKey;
|
public string DeviceKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a preset state message containing favorite presets.
|
||||||
|
/// </summary>
|
||||||
public class PresetStateMessage : DeviceStateMessageBase
|
public class PresetStateMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the list of favorite preset channels.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("favorites", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("favorites", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public List<PresetChannel> Favorites { get; set; } = new List<PresetChannel>();
|
public List<PresetChannel> Favorites { get; set; } = new List<PresetChannel>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,33 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides messaging capabilities for device volume control operations.
|
||||||
|
/// Handles volume level adjustment, mute control, and volume status reporting.
|
||||||
|
/// </summary>
|
||||||
public class DeviceVolumeMessenger : MessengerBase
|
public class DeviceVolumeMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly IBasicVolumeWithFeedback _localDevice;
|
private readonly IBasicVolumeWithFeedback _localDevice;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="DeviceVolumeMessenger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique identifier for this messenger instance.</param>
|
||||||
|
/// <param name="messagePath">The message path for volume control messages.</param>
|
||||||
|
/// <param name="device">The device that provides volume control functionality.</param>
|
||||||
public DeviceVolumeMessenger(string key, string messagePath, IBasicVolumeWithFeedback device)
|
public DeviceVolumeMessenger(string key, string messagePath, IBasicVolumeWithFeedback device)
|
||||||
: base(key, messagePath, device as IKeyName)
|
: base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
_localDevice = device;
|
_localDevice = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendStatus()
|
private void SendStatus(string id = null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -37,7 +47,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
messageObj.Volume.Units = volumeAdvanced.Units;
|
messageObj.Volume.Units = volumeAdvanced.Units;
|
||||||
}
|
}
|
||||||
|
|
||||||
PostStatusMessage(messageObj);
|
PostStatusMessage(messageObj, id);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -48,9 +58,13 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
#region Overrides of MessengerBase
|
#region Overrides of MessengerBase
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers actions for handling volume control operations.
|
||||||
|
/// Includes volume level adjustment, mute control, and full status reporting.
|
||||||
|
/// </summary>
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
AddAction("/fullStatus", (id, content) => SendStatus());
|
AddAction("/fullStatus", (id, content) => SendStatus(id));
|
||||||
|
|
||||||
AddAction("/level", (id, content) =>
|
AddAction("/level", (id, content) =>
|
||||||
{
|
{
|
||||||
@@ -142,29 +156,56 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a volume state message containing volume information.
|
||||||
|
/// </summary>
|
||||||
public class VolumeStateMessage : DeviceStateMessageBase
|
public class VolumeStateMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the volume information.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("volume", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("volume", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public Volume Volume { get; set; }
|
public Volume Volume { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents volume control information including level, mute status, and units.
|
||||||
|
/// </summary>
|
||||||
public class Volume
|
public class Volume
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the volume level.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public int? Level { get; set; }
|
public int? Level { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether the device has mute capability.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("hasMute", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("hasMute", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? HasMute { get; set; }
|
public bool? HasMute { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether the device is currently muted.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("muted", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("muted", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? Muted { get; set; }
|
public bool? Muted { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the volume label for display purposes.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("label", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("label", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string Label { get; set; }
|
public string Label { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the raw volume value as a string.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("rawValue", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("rawValue", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string RawValue { get; set; }
|
public string RawValue { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the volume level units.
|
||||||
|
/// </summary>
|
||||||
[JsonConverter(typeof(StringEnumConverter))]
|
[JsonConverter(typeof(StringEnumConverter))]
|
||||||
[JsonProperty("units", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("units", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public eVolumeLevelUnits? Units { get; set; }
|
public eVolumeLevelUnits? Units { get; set; }
|
||||||
|
|||||||
@@ -2,24 +2,34 @@
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Generic messenger for basic device communication
|
||||||
|
/// </summary>
|
||||||
public class GenericMessenger : MessengerBase
|
public class GenericMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the GenericMessenger class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
|
/// <param name="device">Device to communicate with</param>
|
||||||
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
public GenericMessenger(string key, EssentialsDevice device, string messagePath) : base(key, messagePath, device)
|
public GenericMessenger(string key, EssentialsDevice device, string messagePath) : base(key, messagePath, device)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|
||||||
AddAction("/fullStatus", (id, content) => SendFullStatus());
|
AddAction("/fullStatus", (id, content) => SendFullStatus(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendFullStatus()
|
private void SendFullStatus(string id = null)
|
||||||
{
|
{
|
||||||
var state = new DeviceStateMessageBase();
|
var state = new DeviceStateMessageBase();
|
||||||
|
|
||||||
PostStatusMessage(state);
|
PostStatusMessage(state, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,15 +6,29 @@ using PepperDash.Essentials.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides messaging capabilities for communication monitoring operations.
|
||||||
|
/// Handles communication status reporting and monitoring feedback.
|
||||||
|
/// </summary>
|
||||||
public class ICommunicationMonitorMessenger : MessengerBase
|
public class ICommunicationMonitorMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly ICommunicationMonitor _communicationMonitor;
|
private readonly ICommunicationMonitor _communicationMonitor;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ICommunicationMonitorMessenger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique identifier for this messenger instance.</param>
|
||||||
|
/// <param name="messagePath">The message path for communication monitor messages.</param>
|
||||||
|
/// <param name="device">The device that provides communication monitoring functionality.</param>
|
||||||
public ICommunicationMonitorMessenger(string key, string messagePath, ICommunicationMonitor device) : base(key, messagePath, device as IKeyName)
|
public ICommunicationMonitorMessenger(string key, string messagePath, ICommunicationMonitor device) : base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
_communicationMonitor = device;
|
_communicationMonitor = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers actions for handling communication monitoring operations.
|
||||||
|
/// Includes full status reporting for communication monitoring data.
|
||||||
|
/// </summary>
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
@@ -28,7 +42,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
IsOnline = _communicationMonitor.CommunicationMonitor.IsOnline,
|
IsOnline = _communicationMonitor.CommunicationMonitor.IsOnline,
|
||||||
Status = _communicationMonitor.CommunicationMonitor.Status
|
Status = _communicationMonitor.CommunicationMonitor.Status
|
||||||
}
|
}
|
||||||
});
|
}, id);
|
||||||
});
|
});
|
||||||
|
|
||||||
_communicationMonitor.CommunicationMonitor.StatusChange += (sender, args) =>
|
_communicationMonitor.CommunicationMonitor.StatusChange += (sender, args) =>
|
||||||
@@ -50,11 +64,17 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CommunicationMonitorState : DeviceStateMessageBase
|
public class CommunicationMonitorState : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the communication monitor properties.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("commMonitor", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("commMonitor", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public CommunicationMonitorProps CommunicationMonitor { get; set; }
|
public CommunicationMonitorProps CommunicationMonitor { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the properties of a communication monitor.
|
||||||
|
/// </summary>
|
||||||
public class CommunicationMonitorProps
|
public class CommunicationMonitorProps
|
||||||
{ /// <summary>
|
{ /// <summary>
|
||||||
/// For devices that implement ICommunicationMonitor, reports the online status of the device
|
/// For devices that implement ICommunicationMonitor, reports the online status of the device
|
||||||
|
|||||||
@@ -1,20 +1,34 @@
|
|||||||
using Newtonsoft.Json;
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides messaging capabilities for DSP preset management operations.
|
||||||
|
/// Handles DSP preset selection, recall, and preset list management.
|
||||||
|
/// </summary>
|
||||||
public class IDspPresetsMessenger : MessengerBase
|
public class IDspPresetsMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly IDspPresets device;
|
private readonly IDspPresets device;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="IDspPresetsMessenger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique identifier for this messenger instance.</param>
|
||||||
|
/// <param name="messagePath">The message path for DSP preset control messages.</param>
|
||||||
|
/// <param name="device">The device that provides DSP preset functionality.</param>
|
||||||
public IDspPresetsMessenger(string key, string messagePath, IDspPresets device)
|
public IDspPresetsMessenger(string key, string messagePath, IDspPresets device)
|
||||||
: base(key, messagePath, device as IKeyName)
|
: base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
this.device = device;
|
this.device = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers actions for handling DSP preset operations.
|
||||||
|
/// Includes preset selection, recall, and full status reporting.
|
||||||
|
/// </summary>
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
@@ -26,7 +40,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
Presets = device.Presets
|
Presets = device.Presets
|
||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(message);
|
PostStatusMessage(message, id);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddAction("/recallPreset", (id, content) =>
|
AddAction("/recallPreset", (id, content) =>
|
||||||
@@ -42,8 +56,14 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a DSP presets state message containing available presets.
|
||||||
|
/// </summary>
|
||||||
public class IHasDspPresetsStateMessage : DeviceStateMessageBase
|
public class IHasDspPresetsStateMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the dictionary of available DSP presets.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("presets")]
|
[JsonProperty("presets")]
|
||||||
public Dictionary<string, IKeyName> Presets { get; set; }
|
public Dictionary<string, IKeyName> Presets { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,52 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Core.Logging;
|
using PepperDash.Core.Logging;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides messaging functionality for managing room combination scenarios and partition states in an <see
|
||||||
|
/// cref="IEssentialsRoomCombiner"/> instance. Enables external systems to interact with the room combiner via
|
||||||
|
/// predefined actions and status updates.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This class facilitates communication with an <see cref="IEssentialsRoomCombiner"/> by
|
||||||
|
/// exposing actions for toggling modes, managing partitions, and setting room combination scenarios. It also
|
||||||
|
/// listens for feedback changes and broadcasts status updates to connected systems. Typical usage involves
|
||||||
|
/// registering actions for external commands and handling feedback events to synchronize state changes.</remarks>
|
||||||
public class IEssentialsRoomCombinerMessenger : MessengerBase
|
public class IEssentialsRoomCombinerMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly IEssentialsRoomCombiner _roomCombiner;
|
private readonly IEssentialsRoomCombiner _roomCombiner;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="IEssentialsRoomCombinerMessenger"/> class, which facilitates
|
||||||
|
/// messaging for an <see cref="IEssentialsRoomCombiner"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This class is designed to enable communication and interaction with an <see
|
||||||
|
/// cref="IEssentialsRoomCombiner"/> through the specified messaging path. Ensure that the <paramref
|
||||||
|
/// name="roomCombiner"/> parameter is not null when creating an instance.</remarks>
|
||||||
|
/// <param name="key">The unique key identifying this messenger instance.</param>
|
||||||
|
/// <param name="messagePath">The path used for messaging operations.</param>
|
||||||
|
/// <param name="roomCombiner">The <see cref="IEssentialsRoomCombiner"/> instance associated with this messenger.</param>
|
||||||
public IEssentialsRoomCombinerMessenger(string key, string messagePath, IEssentialsRoomCombiner roomCombiner)
|
public IEssentialsRoomCombinerMessenger(string key, string messagePath, IEssentialsRoomCombiner roomCombiner)
|
||||||
: base(key, messagePath, roomCombiner as IKeyName)
|
: base(key, messagePath, roomCombiner as IKeyName)
|
||||||
{
|
{
|
||||||
_roomCombiner = roomCombiner;
|
_roomCombiner = roomCombiner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers actions and event handlers for managing room combination scenarios and partition states.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This method sets up various actions that can be triggered via specific endpoints,
|
||||||
|
/// such as toggling modes, setting room combination scenarios, and managing partition states. It also
|
||||||
|
/// subscribes to feedback events to update the status when changes occur in room combination scenarios or
|
||||||
|
/// partition states.</remarks>
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
AddAction("/fullStatus", (id, content) => SendFullStatus());
|
AddAction("/fullStatus", (id, content) => SendFullStatus(id));
|
||||||
|
|
||||||
AddAction("/setAutoMode", (id, content) =>
|
AddAction("/setAutoMode", (id, content) =>
|
||||||
{
|
{
|
||||||
@@ -94,7 +120,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendFullStatus()
|
private void SendFullStatus(string id = null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -107,6 +133,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
|
|
||||||
var message = new IEssentialsRoomCombinerStateMessage
|
var message = new IEssentialsRoomCombinerStateMessage
|
||||||
{
|
{
|
||||||
|
DisableAutoMode = _roomCombiner.DisableAutoMode,
|
||||||
IsInAutoMode = _roomCombiner.IsInAutoMode,
|
IsInAutoMode = _roomCombiner.IsInAutoMode,
|
||||||
CurrentScenario = _roomCombiner.CurrentScenario,
|
CurrentScenario = _roomCombiner.CurrentScenario,
|
||||||
Rooms = rooms,
|
Rooms = rooms,
|
||||||
@@ -114,7 +141,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
Partitions = _roomCombiner.Partitions
|
Partitions = _roomCombiner.Partitions
|
||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(message);
|
PostStatusMessage(message, id);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -132,20 +159,48 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the state message for a room combiner system, providing information about the current configuration,
|
||||||
|
/// operational mode, and associated rooms, partitions, and scenarios.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This class is used to encapsulate the state of a room combiner system, including its current
|
||||||
|
/// mode of operation, active room combination scenario, and the list of rooms and partitions involved. It is
|
||||||
|
/// typically serialized and transmitted to communicate the state of the system.</remarks>
|
||||||
public class IEssentialsRoomCombinerStateMessage : DeviceStateMessageBase
|
public class IEssentialsRoomCombinerStateMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether automatic mode is disabled.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("disableAutoMode", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public bool DisableAutoMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether the system is operating in automatic mode.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("isInAutoMode", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("isInAutoMode", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool IsInAutoMode { get; set; }
|
public bool IsInAutoMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the current room combination scenario.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("currentScenario", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("currentScenario", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public IRoomCombinationScenario CurrentScenario { get; set; }
|
public IRoomCombinationScenario CurrentScenario { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the collection of rooms associated with the entity.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("rooms", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("rooms", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public List<IKeyName> Rooms { get; set; }
|
public List<IKeyName> Rooms { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the collection of room combination scenarios.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("roomCombinationScenarios", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("roomCombinationScenarios", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public List<IRoomCombinationScenario> RoomCombinationScenarios { get; set; }
|
public List<IRoomCombinationScenario> RoomCombinationScenarios { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the collection of partition controllers.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("partitions", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("partitions", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public List<IPartitionController> Partitions { get; set; }
|
public List<IPartitionController> Partitions { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,25 @@ using PepperDash.Essentials.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger for devices that implement IHasCurrentSourceInfoChange interface
|
||||||
|
/// </summary>
|
||||||
public class IHasCurrentSourceInfoMessenger : MessengerBase
|
public class IHasCurrentSourceInfoMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly IHasCurrentSourceInfoChange sourceDevice;
|
private readonly IHasCurrentSourceInfoChange sourceDevice;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the IHasCurrentSourceInfoMessenger class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
|
/// <param name="device">Device that implements IHasCurrentSourceInfoChange</param>
|
||||||
public IHasCurrentSourceInfoMessenger(string key, string messagePath, IHasCurrentSourceInfoChange device) : base(key, messagePath, device as IKeyName)
|
public IHasCurrentSourceInfoMessenger(string key, string messagePath, IHasCurrentSourceInfoChange device) : base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
sourceDevice = device;
|
sourceDevice = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
@@ -25,7 +36,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
CurrentSource = sourceDevice.CurrentSourceInfo
|
CurrentSource = sourceDevice.CurrentSourceInfo
|
||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(message);
|
PostStatusMessage(message, id);
|
||||||
});
|
});
|
||||||
|
|
||||||
sourceDevice.CurrentSourceChange += (sender, e) =>
|
sourceDevice.CurrentSourceChange += (sender, e) =>
|
||||||
@@ -46,11 +57,20 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// State message for current source information
|
||||||
|
/// </summary>
|
||||||
public class CurrentSourceStateMessage : DeviceStateMessageBase
|
public class CurrentSourceStateMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the current source key
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("currentSourceKey", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("currentSourceKey", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string CurrentSourceKey { get; set; }
|
public string CurrentSourceKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the current source information
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("currentSource")]
|
[JsonProperty("currentSource")]
|
||||||
public SourceListItem CurrentSource { get; set; }
|
public SourceListItem CurrentSource { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,40 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Core.Logging;
|
using PepperDash.Core.Logging;
|
||||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger for devices that implement IHasInputs interface
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey">Type of the key used for inputs</typeparam>
|
||||||
public class IHasInputsMessenger<TKey> : MessengerBase
|
public class IHasInputsMessenger<TKey> : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly IHasInputs<TKey> itemDevice;
|
private readonly IHasInputs<TKey> itemDevice;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a messenger for a device that implements IHasInputs<typeparamref name="TKey"/>
|
/// Constructs a messenger for a device that implements IHasInputs<typeparamref name="TKey"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key"></param>
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
/// <param name="messagePath"></param>
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
/// <param name="device"></param>
|
/// <param name="device">Device that implements IHasInputs</param>
|
||||||
public IHasInputsMessenger(string key, string messagePath, IHasInputs<TKey> device) : base(key, messagePath, device)
|
public IHasInputsMessenger(string key, string messagePath, IHasInputs<TKey> device) : base(key, messagePath, device)
|
||||||
{
|
{
|
||||||
itemDevice = device;
|
itemDevice = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|
||||||
AddAction("/fullStatus", (id, context) =>
|
AddAction("/fullStatus", (id, context) =>
|
||||||
{
|
{
|
||||||
SendFullStatus();
|
SendFullStatus(id);
|
||||||
});
|
});
|
||||||
|
|
||||||
itemDevice.Inputs.ItemsUpdated += (sender, args) =>
|
itemDevice.Inputs.ItemsUpdated += (sender, args) =>
|
||||||
@@ -59,7 +64,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendFullStatus()
|
private void SendFullStatus(string id = null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -74,7 +79,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(stateObject);
|
PostStatusMessage(stateObject, id);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -83,17 +88,34 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// State message for devices with inputs
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey">Type of the key used for inputs</typeparam>
|
||||||
public class IHasInputsStateMessage<TKey> : DeviceStateMessageBase
|
public class IHasInputsStateMessage<TKey> : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the inputs
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("inputs")]
|
[JsonProperty("inputs")]
|
||||||
public Inputs<TKey> Inputs { get; set; }
|
public Inputs<TKey> Inputs { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a collection of inputs
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey">Type of the key used for inputs</typeparam>
|
||||||
public class Inputs<TKey>
|
public class Inputs<TKey>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the items dictionary
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("items")]
|
[JsonProperty("items")]
|
||||||
public Dictionary<TKey, ISelectableItem> Items { get; set; }
|
public Dictionary<TKey, ISelectableItem> Items { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the current item
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("currentItem")]
|
[JsonProperty("currentItem")]
|
||||||
public TKey CurrentItem { get; set; }
|
public TKey CurrentItem { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,31 +5,48 @@ using PepperDash.Essentials.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides messaging capabilities for power control operations with feedback.
|
||||||
|
/// Handles power on/off commands and power state feedback reporting.
|
||||||
|
/// </summary>
|
||||||
public class IHasPowerControlWithFeedbackMessenger : MessengerBase
|
public class IHasPowerControlWithFeedbackMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly IHasPowerControlWithFeedback _powerControl;
|
private readonly IHasPowerControlWithFeedback _powerControl;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="IHasPowerControlWithFeedbackMessenger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique identifier for this messenger instance.</param>
|
||||||
|
/// <param name="messagePath">The message path for power control messages.</param>
|
||||||
|
/// <param name="powerControl">The device that provides power control functionality.</param>
|
||||||
public IHasPowerControlWithFeedbackMessenger(string key, string messagePath, IHasPowerControlWithFeedback powerControl)
|
public IHasPowerControlWithFeedbackMessenger(string key, string messagePath, IHasPowerControlWithFeedback powerControl)
|
||||||
: base(key, messagePath, powerControl as IKeyName)
|
: base(key, messagePath, powerControl as IKeyName)
|
||||||
{
|
{
|
||||||
_powerControl = powerControl;
|
_powerControl = powerControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendFullStatus()
|
/// <summary>
|
||||||
|
/// Sends the full power control status to connected clients.
|
||||||
|
/// </summary>
|
||||||
|
public void SendFullStatus(string id = null)
|
||||||
{
|
{
|
||||||
var messageObj = new PowerControlWithFeedbackStateMessage
|
var messageObj = new PowerControlWithFeedbackStateMessage
|
||||||
{
|
{
|
||||||
PowerState = _powerControl.PowerIsOnFeedback.BoolValue
|
PowerState = _powerControl.PowerIsOnFeedback.BoolValue
|
||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(messageObj);
|
PostStatusMessage(messageObj, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers actions for handling power control operations.
|
||||||
|
/// Includes power on, power off, power toggle, and full status reporting.
|
||||||
|
/// </summary>
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|
||||||
AddAction("/fullStatus", (id, content) => SendFullStatus());
|
AddAction("/fullStatus", (id, content) => SendFullStatus(id));
|
||||||
|
|
||||||
_powerControl.PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange; ;
|
_powerControl.PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange; ;
|
||||||
}
|
}
|
||||||
@@ -44,8 +61,14 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a power control state message containing power state information.
|
||||||
|
/// </summary>
|
||||||
public class PowerControlWithFeedbackStateMessage : DeviceStateMessageBase
|
public class PowerControlWithFeedbackStateMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the power state of the device.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("powerState", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("powerState", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? PowerState { get; set; }
|
public bool? PowerState { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,28 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Devices.Common.Codec;
|
using PepperDash.Essentials.Devices.Common.Codec;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger for devices that implement IHasScheduleAwareness interface
|
||||||
|
/// </summary>
|
||||||
public class IHasScheduleAwarenessMessenger : MessengerBase
|
public class IHasScheduleAwarenessMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the schedule source device
|
||||||
|
/// </summary>
|
||||||
public IHasScheduleAwareness ScheduleSource { get; private set; }
|
public IHasScheduleAwareness ScheduleSource { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the IHasScheduleAwarenessMessenger class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
|
/// <param name="scheduleSource">Device that implements IHasScheduleAwareness</param>
|
||||||
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
public IHasScheduleAwarenessMessenger(string key, IHasScheduleAwareness scheduleSource, string messagePath)
|
public IHasScheduleAwarenessMessenger(string key, IHasScheduleAwareness scheduleSource, string messagePath)
|
||||||
: base(key, messagePath, scheduleSource as IKeyName)
|
: base(key, messagePath, scheduleSource as IKeyName)
|
||||||
{
|
{
|
||||||
@@ -19,9 +31,10 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
ScheduleSource.CodecSchedule.MeetingEventChange += new EventHandler<MeetingEventArgs>(CodecSchedule_MeetingEventChange);
|
ScheduleSource.CodecSchedule.MeetingEventChange += new EventHandler<MeetingEventArgs>(CodecSchedule_MeetingEventChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
AddAction("/schedule/fullStatus", (id, content) => SendFullScheduleObject());
|
AddAction("/schedule/fullStatus", (id, content) => SendFullScheduleObject(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CodecSchedule_MeetingEventChange(object sender, MeetingEventArgs e)
|
private void CodecSchedule_MeetingEventChange(object sender, MeetingEventArgs e)
|
||||||
@@ -45,36 +58,60 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper method to send the full schedule data
|
/// Helper method to send the full schedule data
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void SendFullScheduleObject()
|
private void SendFullScheduleObject(string id = null)
|
||||||
{
|
{
|
||||||
PostStatusMessage(new FullScheduleMessage
|
PostStatusMessage(new FullScheduleMessage
|
||||||
{
|
{
|
||||||
Meetings = ScheduleSource.CodecSchedule.Meetings,
|
Meetings = ScheduleSource.CodecSchedule.Meetings,
|
||||||
MeetingWarningMinutes = ScheduleSource.CodecSchedule.MeetingWarningMinutes
|
MeetingWarningMinutes = ScheduleSource.CodecSchedule.MeetingWarningMinutes
|
||||||
});
|
}, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Full schedule message containing meetings and warning minutes
|
||||||
|
/// </summary>
|
||||||
public class FullScheduleMessage : DeviceStateMessageBase
|
public class FullScheduleMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the list of meetings
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("meetings", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("meetings", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public List<Meeting> Meetings { get; set; }
|
public List<Meeting> Meetings { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the meeting warning minutes
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("meetingWarningMinutes", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("meetingWarningMinutes", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public int MeetingWarningMinutes { get; set; }
|
public int MeetingWarningMinutes { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Message containing meeting change information
|
||||||
|
/// </summary>
|
||||||
public class MeetingChangeMessage
|
public class MeetingChangeMessage
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the meeting change details
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("meetingChange", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("meetingChange", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public MeetingChange MeetingChange { get; set; }
|
public MeetingChange MeetingChange { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a meeting change with type and meeting details
|
||||||
|
/// </summary>
|
||||||
public class MeetingChange
|
public class MeetingChange
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the change type
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("changeType", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("changeType", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string ChangeType { get; set; }
|
public string ChangeType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the meeting details
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("meeting", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("meeting", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public Meeting Meeting { get; set; }
|
public Meeting Meeting { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
@@ -19,19 +19,19 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|
||||||
AddAction("/fullStatus", (id, content) => SendFullStatus());
|
AddAction("/fullStatus", (id, content) => SendFullStatus(id));
|
||||||
|
|
||||||
device.HumidityFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>((o, a) => SendFullStatus());
|
device.HumidityFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>((o, a) => SendFullStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendFullStatus()
|
private void SendFullStatus(string id = null)
|
||||||
{
|
{
|
||||||
var state = new IHumiditySensorStateMessage
|
var state = new IHumiditySensorStateMessage
|
||||||
{
|
{
|
||||||
Humidity = string.Format("{0}%", device.HumidityFeedback.UShortValue)
|
Humidity = string.Format("{0}%", device.HumidityFeedback.UShortValue)
|
||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(state);
|
PostStatusMessage(state, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,31 @@
|
|||||||
using Newtonsoft.Json;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger for devices that implement ILevelControls interface
|
||||||
|
/// </summary>
|
||||||
public class ILevelControlsMessenger : MessengerBase
|
public class ILevelControlsMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private ILevelControls levelControlsDevice;
|
private ILevelControls levelControlsDevice;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the ILevelControlsMessenger class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
|
/// <param name="device">Device that implements ILevelControls</param>
|
||||||
public ILevelControlsMessenger(string key, string messagePath, ILevelControls device) : base(key, messagePath, device as IKeyName)
|
public ILevelControlsMessenger(string key, string messagePath, ILevelControls device) : base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
levelControlsDevice = device;
|
levelControlsDevice = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
@@ -26,7 +37,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
Levels = levelControlsDevice.LevelControlPoints.ToDictionary(kv => kv.Key, kv => new Volume { Level = kv.Value.VolumeLevelFeedback.IntValue, Muted = kv.Value.MuteFeedback.BoolValue })
|
Levels = levelControlsDevice.LevelControlPoints.ToDictionary(kv => kv.Key, kv => new Volume { Level = kv.Value.VolumeLevelFeedback.IntValue, Muted = kv.Value.MuteFeedback.BoolValue })
|
||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(message);
|
PostStatusMessage(message, id);
|
||||||
});
|
});
|
||||||
|
|
||||||
foreach (var levelControl in levelControlsDevice.LevelControlPoints)
|
foreach (var levelControl in levelControlsDevice.LevelControlPoints)
|
||||||
@@ -74,17 +85,32 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// State message for level controls
|
||||||
|
/// </summary>
|
||||||
public class LevelControlStateMessage : DeviceStateMessageBase
|
public class LevelControlStateMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the level controls
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("levelControls")]
|
[JsonProperty("levelControls")]
|
||||||
public Dictionary<string, Volume> Levels { get; set; }
|
public Dictionary<string, Volume> Levels { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Request message for level control operations
|
||||||
|
/// </summary>
|
||||||
public class LevelControlRequestMessage
|
public class LevelControlRequestMessage
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the control key
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("key")]
|
[JsonProperty("key")]
|
||||||
public string Key { get; set; }
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the level
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public ushort? Level { get; set; }
|
public ushort? Level { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using PepperDash.Essentials.Core.Routing;
|
using PepperDash.Essentials.Core.Routing;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
@@ -16,11 +16,19 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
public class IMatrixRoutingMessenger : MessengerBase
|
public class IMatrixRoutingMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly IMatrixRouting matrixDevice;
|
private readonly IMatrixRouting matrixDevice;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the IMatrixRoutingMessenger class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
|
/// <param name="device">Device that implements IMatrixRouting</param>
|
||||||
public IMatrixRoutingMessenger(string key, string messagePath, IMatrixRouting device) : base(key, messagePath, device as IKeyName)
|
public IMatrixRoutingMessenger(string key, string messagePath, IMatrixRouting device) : base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
matrixDevice = device;
|
matrixDevice = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
@@ -37,7 +45,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
PostStatusMessage(message);
|
PostStatusMessage(message, id);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -82,86 +90,159 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// State message for matrix routing information
|
||||||
|
/// </summary>
|
||||||
public class MatrixStateMessage : DeviceStateMessageBase
|
public class MatrixStateMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the outputs dictionary
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("outputs")]
|
[JsonProperty("outputs")]
|
||||||
public Dictionary<string, RoutingOutput> Outputs;
|
public Dictionary<string, RoutingOutput> Outputs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the inputs dictionary
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("inputs")]
|
[JsonProperty("inputs")]
|
||||||
public Dictionary<string, RoutingInput> Inputs;
|
public Dictionary<string, RoutingInput> Inputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a routing input slot
|
||||||
|
/// </summary>
|
||||||
public class RoutingInput
|
public class RoutingInput
|
||||||
{
|
{
|
||||||
private IRoutingInputSlot _input;
|
private IRoutingInputSlot _input;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the transmit device key
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("txDeviceKey", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("txDeviceKey", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string TxDeviceKey => _input?.TxDeviceKey;
|
public string TxDeviceKey => _input?.TxDeviceKey;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the slot number
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("slotNumber", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("slotNumber", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public int? SlotNumber => _input?.SlotNumber;
|
public int? SlotNumber => _input?.SlotNumber;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the supported signal types
|
||||||
|
/// </summary>
|
||||||
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
|
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
|
||||||
[JsonProperty("supportedSignalTypes", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("supportedSignalTypes", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public eRoutingSignalType? SupportedSignalTypes => _input?.SupportedSignalTypes;
|
public eRoutingSignalType? SupportedSignalTypes => _input?.SupportedSignalTypes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string Name => _input?.Name;
|
public string Name => _input?.Name;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the online status
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("isOnline", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("isOnline", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? IsOnline => _input?.IsOnline.BoolValue;
|
public bool? IsOnline => _input?.IsOnline.BoolValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the video sync detected status
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("videoSyncDetected", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("videoSyncDetected", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
|
||||||
public bool? VideoSyncDetected => _input?.VideoSyncDetected;
|
public bool? VideoSyncDetected => _input?.VideoSyncDetected;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the key
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string Key => _input?.Key;
|
public string Key => _input?.Key;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the RoutingInput class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">The input slot</param>
|
||||||
public RoutingInput(IRoutingInputSlot input)
|
public RoutingInput(IRoutingInputSlot input)
|
||||||
{
|
{
|
||||||
_input = input;
|
_input = input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a routing output slot
|
||||||
|
/// </summary>
|
||||||
public class RoutingOutput
|
public class RoutingOutput
|
||||||
{
|
{
|
||||||
private IRoutingOutputSlot _output;
|
private IRoutingOutputSlot _output;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the RoutingOutput class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="output">The output slot</param>
|
||||||
public RoutingOutput(IRoutingOutputSlot output)
|
public RoutingOutput(IRoutingOutputSlot output)
|
||||||
{
|
{
|
||||||
_output = output;
|
_output = output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the receive device key
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("rxDeviceKey")]
|
[JsonProperty("rxDeviceKey")]
|
||||||
public string RxDeviceKey => _output.RxDeviceKey;
|
public string RxDeviceKey => _output.RxDeviceKey;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current routes
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("currentRoutes")]
|
[JsonProperty("currentRoutes")]
|
||||||
public Dictionary<string, RoutingInput> CurrentRoutes => _output.CurrentRoutes.ToDictionary(kvp => kvp.Key.ToString(), kvp => new RoutingInput(kvp.Value));
|
public Dictionary<string, RoutingInput> CurrentRoutes => _output.CurrentRoutes.ToDictionary(kvp => kvp.Key.ToString(), kvp => new RoutingInput(kvp.Value));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the slot number
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("slotNumber")]
|
[JsonProperty("slotNumber")]
|
||||||
public int SlotNumber => _output.SlotNumber;
|
public int SlotNumber => _output.SlotNumber;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the supported signal types
|
||||||
|
/// </summary>
|
||||||
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
|
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
|
||||||
[JsonProperty("supportedSignalTypes")]
|
[JsonProperty("supportedSignalTypes")]
|
||||||
public eRoutingSignalType SupportedSignalTypes => _output.SupportedSignalTypes;
|
public eRoutingSignalType SupportedSignalTypes => _output.SupportedSignalTypes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("name")]
|
[JsonProperty("name")]
|
||||||
public string Name => _output.Name;
|
public string Name => _output.Name;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the key
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("key")]
|
[JsonProperty("key")]
|
||||||
public string Key => _output.Key;
|
public string Key => _output.Key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Request for matrix routing
|
||||||
|
/// </summary>
|
||||||
public class MatrixRouteRequest
|
public class MatrixRouteRequest
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the output key
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("outputKey")]
|
[JsonProperty("outputKey")]
|
||||||
public string OutputKey { get; set; }
|
public string OutputKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the input key
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("inputKey")]
|
[JsonProperty("inputKey")]
|
||||||
public string InputKey { get; set; }
|
public string InputKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the route type
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("routeType")]
|
[JsonProperty("routeType")]
|
||||||
public eRoutingSignalType RouteType { get; set; }
|
public eRoutingSignalType RouteType { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
@@ -21,7 +21,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|
||||||
AddAction("/fullStatus", (id, content) => SendFullStatus());
|
AddAction("/fullStatus", (id, content) => SendFullStatus(id));
|
||||||
|
|
||||||
AddAction("/raise", (id, content) =>
|
AddAction("/raise", (id, content) =>
|
||||||
{
|
{
|
||||||
@@ -50,7 +50,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
PostStatusMessage(JToken.FromObject(state));
|
PostStatusMessage(JToken.FromObject(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendFullStatus()
|
private void SendFullStatus(string id = null)
|
||||||
{
|
{
|
||||||
var state = new ScreenLiftStateMessage
|
var state = new ScreenLiftStateMessage
|
||||||
{
|
{
|
||||||
@@ -59,7 +59,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
DisplayDeviceKey = device.DisplayDeviceKey
|
DisplayDeviceKey = device.DisplayDeviceKey
|
||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(state);
|
PostStatusMessage(state, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Core.Logging;
|
using PepperDash.Core.Logging;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using System;
|
|
||||||
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger for routing actions
|
||||||
|
/// </summary>
|
||||||
public class RunRouteActionMessenger : MessengerBase
|
public class RunRouteActionMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -14,6 +17,13 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public IRunRouteAction RoutingDevice { get; private set; }
|
public IRunRouteAction RoutingDevice { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RunRouteActionMessenger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
|
/// <param name="routingDevice">Device that implements IRunRouteAction</param>
|
||||||
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
|
/// <exception cref="ArgumentNullException">Thrown when routingDevice is null</exception>
|
||||||
public RunRouteActionMessenger(string key, IRunRouteAction routingDevice, string messagePath)
|
public RunRouteActionMessenger(string key, IRunRouteAction routingDevice, string messagePath)
|
||||||
: base(key, messagePath, routingDevice as IKeyName)
|
: base(key, messagePath, routingDevice as IKeyName)
|
||||||
{
|
{
|
||||||
@@ -31,9 +41,10 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
SendRoutingFullMessageObject();
|
SendRoutingFullMessageObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
AddAction("/fullStatus", (id, content) => SendRoutingFullMessageObject());
|
AddAction("/fullStatus", (id, content) => SendRoutingFullMessageObject(id));
|
||||||
|
|
||||||
AddAction("/source", (id, content) =>
|
AddAction("/source", (id, content) =>
|
||||||
{
|
{
|
||||||
@@ -59,7 +70,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper method to update full status of the routing device
|
/// Helper method to update full status of the routing device
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void SendRoutingFullMessageObject()
|
private void SendRoutingFullMessageObject(string id = null)
|
||||||
{
|
{
|
||||||
if (RoutingDevice is IRoutingSink sinkDevice)
|
if (RoutingDevice is IRoutingSink sinkDevice)
|
||||||
{
|
{
|
||||||
@@ -71,13 +82,19 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
PostStatusMessage(new RoutingStateMessage
|
PostStatusMessage(new RoutingStateMessage
|
||||||
{
|
{
|
||||||
SelectedSourceKey = sourceKey
|
SelectedSourceKey = sourceKey
|
||||||
});
|
}, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Message class for routing state
|
||||||
|
/// </summary>
|
||||||
public class RoutingStateMessage : DeviceStateMessageBase
|
public class RoutingStateMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the selected source key
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("selectedSourceKey")]
|
[JsonProperty("selectedSourceKey")]
|
||||||
public string SelectedSourceKey { get; set; }
|
public string SelectedSourceKey { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Core.Logging;
|
using PepperDash.Core.Logging;
|
||||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger for devices that implement ISelectableItems interface
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey">Type of the key used for selectable items</typeparam>
|
||||||
public class ISelectableItemsMessenger<TKey> : MessengerBase
|
public class ISelectableItemsMessenger<TKey> : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly ISelectableItems<TKey> itemDevice;
|
private readonly ISelectableItems<TKey> itemDevice;
|
||||||
|
|
||||||
private readonly string _propName;
|
private readonly string _propName;
|
||||||
@@ -16,23 +20,24 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a messenger for a device that implements ISelectableItems<typeparamref name="TKey"/>
|
/// Constructs a messenger for a device that implements ISelectableItems<typeparamref name="TKey"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key"></param>
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
/// <param name="messagePath"></param>
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
/// <param name="device"></param>
|
/// <param name="device">Device that implements ISelectableItems</param>
|
||||||
/// <param name="propName"></param>
|
/// <param name="propName">Property name for JSON serialization</param>
|
||||||
public ISelectableItemsMessenger(string key, string messagePath, ISelectableItems<TKey> device, string propName) : base(key, messagePath, device as IKeyName)
|
public ISelectableItemsMessenger(string key, string messagePath, ISelectableItems<TKey> device, string propName) : base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
itemDevice = device;
|
itemDevice = device;
|
||||||
_propName = propName;
|
_propName = propName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|
||||||
AddAction("/fullStatus", (id, context) =>
|
AddAction("/fullStatus", (id, context) =>
|
||||||
{
|
{
|
||||||
SendFullStatus();
|
SendFullStatus(id);
|
||||||
});
|
});
|
||||||
|
|
||||||
itemDevice.ItemsUpdated += (sender, args) =>
|
itemDevice.ItemsUpdated += (sender, args) =>
|
||||||
@@ -62,7 +67,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendFullStatus()
|
private void SendFullStatus(string id = null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -74,7 +79,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
CurrentItem = itemDevice.CurrentItem
|
CurrentItem = itemDevice.CurrentItem
|
||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(stateObject);
|
PostStatusMessage(stateObject, id);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -83,11 +88,21 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// State message for selectable items
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey">Type of the key used for selectable items</typeparam>
|
||||||
public class ISelectableItemsStateMessage<TKey> : DeviceStateMessageBase
|
public class ISelectableItemsStateMessage<TKey> : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the items dictionary
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("items")]
|
[JsonProperty("items")]
|
||||||
public Dictionary<TKey, ISelectableItem> Items { get; set; }
|
public Dictionary<TKey, ISelectableItem> Items { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the current item
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("currentItem")]
|
[JsonProperty("currentItem")]
|
||||||
public TKey CurrentItem { get; set; }
|
public TKey CurrentItem { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,16 +5,26 @@ using PepperDash.Essentials.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger for the shutdown prompt timer
|
||||||
|
/// </summary>
|
||||||
public class IShutdownPromptTimerMessenger : MessengerBase
|
public class IShutdownPromptTimerMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly IShutdownPromptTimer _room;
|
private readonly IShutdownPromptTimer _room;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="IShutdownPromptTimerMessenger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
|
/// <param name="room">Room that implements IShutdownPromptTimer</param>
|
||||||
public IShutdownPromptTimerMessenger(string key, string messagePath, IShutdownPromptTimer room)
|
public IShutdownPromptTimerMessenger(string key, string messagePath, IShutdownPromptTimer room)
|
||||||
: base(key, messagePath, room as IKeyName)
|
: base(key, messagePath, room as IKeyName)
|
||||||
{
|
{
|
||||||
_room = room;
|
_room = room;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
AddAction("/status", (id, content) =>
|
AddAction("/status", (id, content) =>
|
||||||
@@ -65,7 +75,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendFullStatus()
|
private void SendFullStatus(string id = null)
|
||||||
{
|
{
|
||||||
var status = new IShutdownPromptTimerStateMessage
|
var status = new IShutdownPromptTimerStateMessage
|
||||||
{
|
{
|
||||||
@@ -74,7 +84,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
PercentageRemaining = _room.ShutdownPromptTimer.PercentFeedback.UShortValue
|
PercentageRemaining = _room.ShutdownPromptTimer.PercentFeedback.UShortValue
|
||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(status);
|
PostStatusMessage(status, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,39 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core.CrestronIO;
|
using PepperDash.Essentials.Core.CrestronIO;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger for ISwitchedOutput devices
|
||||||
|
/// </summary>
|
||||||
public class ISwitchedOutputMessenger : MessengerBase
|
public class ISwitchedOutputMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
|
|
||||||
private readonly ISwitchedOutput device;
|
private readonly ISwitchedOutput device;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ISwitchedOutputMessenger"/> class.
|
||||||
|
/// This messenger provides mobile control interface for switched output devices.
|
||||||
|
/// It allows sending commands to turn the output on or off, and provides feedback on the
|
||||||
|
/// current state of the output.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
|
/// <param name="device">Device that implements ISwitchedOutput</param>
|
||||||
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
public ISwitchedOutputMessenger(string key, ISwitchedOutput device, string messagePath)
|
public ISwitchedOutputMessenger(string key, ISwitchedOutput device, string messagePath)
|
||||||
: base(key, messagePath, device as IKeyName)
|
: base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
this.device = device;
|
this.device = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|
||||||
AddAction("/fullStatus", (id, content) => SendFullStatus());
|
AddAction("/fullStatus", (id, content) => SendFullStatus(id));
|
||||||
|
|
||||||
AddAction("/on", (id, content) =>
|
AddAction("/on", (id, content) =>
|
||||||
{
|
{
|
||||||
@@ -39,19 +52,29 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
device.OutputIsOnFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>((o, a) => SendFullStatus());
|
device.OutputIsOnFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>((o, a) => SendFullStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendFullStatus()
|
private void SendFullStatus(string id = null)
|
||||||
{
|
{
|
||||||
var state = new ISwitchedOutputStateMessage
|
var state = new ISwitchedOutputStateMessage
|
||||||
{
|
{
|
||||||
IsOn = device.OutputIsOnFeedback.BoolValue
|
IsOn = device.OutputIsOnFeedback.BoolValue
|
||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(state);
|
PostStatusMessage(state, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// State message for ISwitchedOutput devices
|
||||||
|
/// This message contains the current state of the switched output, specifically whether it is on or off.
|
||||||
|
/// It is used to communicate the state of the output to clients that subscribe to this messenger.
|
||||||
|
/// </summary>
|
||||||
public class ISwitchedOutputStateMessage : DeviceStateMessageBase
|
public class ISwitchedOutputStateMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether the switched output is currently on.
|
||||||
|
/// This property is used to convey the current state of the output to clients.
|
||||||
|
/// A value of true indicates that the output is on, while false indicates it is off.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("isOn")]
|
[JsonProperty("isOn")]
|
||||||
public bool IsOn { get; set; }
|
public bool IsOn { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,22 +4,32 @@ using PepperDash.Essentials.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger for devices that implement ITechPassword interface
|
||||||
|
/// </summary>
|
||||||
public class ITechPasswordMessenger : MessengerBase
|
public class ITechPasswordMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly ITechPassword _room;
|
private readonly ITechPassword _room;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the ITechPasswordMessenger class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
|
/// <param name="room">Room that implements ITechPassword</param>
|
||||||
public ITechPasswordMessenger(string key, string messagePath, ITechPassword room)
|
public ITechPasswordMessenger(string key, string messagePath, ITechPassword room)
|
||||||
: base(key, messagePath, room as IKeyName)
|
: base(key, messagePath, room as IKeyName)
|
||||||
{
|
{
|
||||||
_room = room;
|
_room = room;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
|
|
||||||
AddAction("/status", (id, content) =>
|
AddAction("/status", (id, content) =>
|
||||||
{
|
{
|
||||||
SendFullStatus();
|
SendFullStatus(id);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddAction("/validateTechPassword", (id, content) =>
|
AddAction("/validateTechPassword", (id, content) =>
|
||||||
@@ -52,35 +62,56 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendFullStatus()
|
private void SendFullStatus(string id = null)
|
||||||
{
|
{
|
||||||
var status = new ITechPasswordStateMessage
|
var status = new ITechPasswordStateMessage
|
||||||
{
|
{
|
||||||
TechPasswordLength = _room.TechPasswordLength
|
TechPasswordLength = _room.TechPasswordLength
|
||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(status);
|
PostStatusMessage(status, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// State message for tech password information
|
||||||
|
/// </summary>
|
||||||
public class ITechPasswordStateMessage : DeviceStateMessageBase
|
public class ITechPasswordStateMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the tech password length
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("techPasswordLength", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("techPasswordLength", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public int? TechPasswordLength { get; set; }
|
public int? TechPasswordLength { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event message for tech password validation result
|
||||||
|
/// </summary>
|
||||||
public class ITechPasswordEventMessage : DeviceEventMessageBase
|
public class ITechPasswordEventMessage : DeviceEventMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets whether the password is valid
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("isValid", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("isValid", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? IsValid { get; set; }
|
public bool? IsValid { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Content for setting tech password
|
||||||
|
/// </summary>
|
||||||
internal class SetTechPasswordContent
|
internal class SetTechPasswordContent
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the old password
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("oldPassword")]
|
[JsonProperty("oldPassword")]
|
||||||
public string OldPassword { get; set; }
|
public string OldPassword { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the new password
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("newPassword")]
|
[JsonProperty("newPassword")]
|
||||||
public string NewPassword { get; set; }
|
public string NewPassword { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,37 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger for temperature sensor devices
|
||||||
|
/// </summary>
|
||||||
public class ITemperatureSensorMessenger : MessengerBase
|
public class ITemperatureSensorMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly ITemperatureSensor device;
|
private readonly ITemperatureSensor device;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the ITemperatureSensorMessenger class
|
||||||
|
/// This messenger provides a mobile control interface for temperature sensor devices.
|
||||||
|
/// It allows clients to retrieve the current temperature and change the temperature format between Celsius and Fahrenheit.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
|
/// <param name="device">Device that implements ITemperatureSensor</param>
|
||||||
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
public ITemperatureSensorMessenger(string key, ITemperatureSensor device, string messagePath)
|
public ITemperatureSensorMessenger(string key, ITemperatureSensor device, string messagePath)
|
||||||
: base(key, messagePath, device as IKeyName)
|
: base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
this.device = device;
|
this.device = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|
||||||
AddAction("/fullStatus", (id, content) => SendFullStatus());
|
AddAction("/fullStatus", (id, content) => SendFullStatus(id));
|
||||||
|
|
||||||
AddAction("/setTemperatureUnitsToCelcius", (id, content) =>
|
AddAction("/setTemperatureUnitsToCelcius", (id, content) =>
|
||||||
{
|
{
|
||||||
@@ -35,7 +47,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
device.TemperatureInCFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>((o, a) => SendFullStatus());
|
device.TemperatureInCFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>((o, a) => SendFullStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendFullStatus()
|
private void SendFullStatus(string id = null)
|
||||||
{
|
{
|
||||||
// format the temperature to a string with one decimal place
|
// format the temperature to a string with one decimal place
|
||||||
var tempString = string.Format("{0}.{1}", device.TemperatureFeedback.UShortValue / 10, device.TemperatureFeedback.UShortValue % 10);
|
var tempString = string.Format("{0}.{1}", device.TemperatureFeedback.UShortValue / 10, device.TemperatureFeedback.UShortValue % 10);
|
||||||
@@ -46,15 +58,27 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
TemperatureInCelsius = device.TemperatureInCFeedback.BoolValue
|
TemperatureInCelsius = device.TemperatureInCFeedback.BoolValue
|
||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(state);
|
PostStatusMessage(state, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// State message for temperature sensor devices
|
||||||
|
/// </summary>
|
||||||
public class ITemperatureSensorStateMessage : DeviceStateMessageBase
|
public class ITemperatureSensorStateMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the current temperature reading from the sensor.
|
||||||
|
/// The temperature is represented as a string formatted to one decimal place.
|
||||||
|
/// For example, "22.5" for 22.5 degrees.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("temperature")]
|
[JsonProperty("temperature")]
|
||||||
public string Temperature { get; set; }
|
public string Temperature { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether the temperature is in Celsius.
|
||||||
|
/// This property is true if the temperature is in Celsius, and false if it is in Fahrenheit.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("temperatureInCelsius")]
|
[JsonProperty("temperatureInCelsius")]
|
||||||
public bool TemperatureInCelsius { get; set; }
|
public bool TemperatureInCelsius { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,25 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core.Lighting;
|
using PepperDash.Essentials.Core.Lighting;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger for lighting scenes devices
|
||||||
|
/// </summary>
|
||||||
public class ILightingScenesMessenger : MessengerBase
|
public class ILightingScenesMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private ILightingScenes lightingScenesDevice;
|
private ILightingScenes lightingScenesDevice;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ILightingScenesMessenger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
|
/// <param name="device">Device that implements ILightingScenes</param>
|
||||||
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
|
/// <exception cref="ArgumentNullException">Thrown when device is null</exception>
|
||||||
public ILightingScenesMessenger(string key, ILightingScenes device, string messagePath)
|
public ILightingScenesMessenger(string key, ILightingScenes device, string messagePath)
|
||||||
: base(key, messagePath, device as IKeyName)
|
: base(key, messagePath, device as IKeyName)
|
||||||
{
|
{
|
||||||
@@ -28,11 +38,12 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
PostStatusMessage(state);
|
PostStatusMessage(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|
||||||
AddAction("/fullStatus", (id, content) => SendFullStatus());
|
AddAction("/fullStatus", (id, content) => SendFullStatus(id));
|
||||||
|
|
||||||
AddAction("/selectScene", (id, content) =>
|
AddAction("/selectScene", (id, content) =>
|
||||||
{
|
{
|
||||||
@@ -40,14 +51,14 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
lightingScenesDevice.SelectScene(s);
|
lightingScenesDevice.SelectScene(s);
|
||||||
});
|
});
|
||||||
|
|
||||||
if(!(lightingScenesDevice is ILightingScenesDynamic lightingScenesDynamic))
|
if (!(lightingScenesDevice is ILightingScenesDynamic lightingScenesDynamic))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lightingScenesDynamic.LightingScenesUpdated += (s, e) => SendFullStatus();
|
lightingScenesDynamic.LightingScenesUpdated += (s, e) => SendFullStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void SendFullStatus()
|
private void SendFullStatus(string id = null)
|
||||||
{
|
{
|
||||||
var state = new LightingBaseStateMessage
|
var state = new LightingBaseStateMessage
|
||||||
{
|
{
|
||||||
@@ -55,7 +66,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
CurrentLightingScene = lightingScenesDevice.CurrentLightingScene
|
CurrentLightingScene = lightingScenesDevice.CurrentLightingScene
|
||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(state);
|
PostStatusMessage(state, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,41 +1,57 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Core.Logging;
|
using PepperDash.Core.Logging;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides a messaging bridge
|
/// Provides a messaging bridge between mobile control clients and Essentials devices.
|
||||||
|
/// This abstract base class handles message routing, action registration, and status updates.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class MessengerBase : EssentialsDevice, IMobileControlMessenger
|
public abstract class MessengerBase : EssentialsDevice, IMobileControlMessenger
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The device that this messenger is associated with
|
||||||
|
/// </summary>
|
||||||
protected IKeyName _device;
|
protected IKeyName _device;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// List of interfaces implemented by the associated device
|
||||||
|
/// </summary>
|
||||||
private readonly List<string> _deviceInterfaces;
|
private readonly List<string> _deviceInterfaces;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dictionary of registered actions, keyed by path
|
||||||
|
/// </summary>
|
||||||
private readonly Dictionary<string, Action<string, JToken>> _actions = new Dictionary<string, Action<string, JToken>>();
|
private readonly Dictionary<string, Action<string, JToken>> _actions = new Dictionary<string, Action<string, JToken>>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the key of the associated device
|
||||||
|
/// </summary>
|
||||||
public string DeviceKey => _device?.Key ?? "";
|
public string DeviceKey => _device?.Key ?? "";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Gets the mobile control app server controller
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
||||||
public IMobileControl AppServerController { get; private set; }
|
public IMobileControl AppServerController { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the message path for this messenger
|
||||||
|
/// </summary>
|
||||||
public string MessagePath { get; private set; }
|
public string MessagePath { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Initializes a new instance of the MessengerBase class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key"></param>
|
/// <param name="key">The unique key for this messenger</param>
|
||||||
/// <param name="messagePath"></param>
|
/// <param name="messagePath">The message path for routing messages</param>
|
||||||
|
/// <exception cref="ArgumentException">Thrown when messagePath is null or empty</exception>
|
||||||
protected MessengerBase(string key, string messagePath)
|
protected MessengerBase(string key, string messagePath)
|
||||||
: base(key)
|
: base(key)
|
||||||
{
|
{
|
||||||
@@ -47,6 +63,12 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
MessagePath = messagePath;
|
MessagePath = messagePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the MessengerBase class with an associated device
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique key for this messenger</param>
|
||||||
|
/// <param name="messagePath">The message path for routing messages</param>
|
||||||
|
/// <param name="device">The device to associate with this messenger</param>
|
||||||
protected MessengerBase(string key, string messagePath, IKeyName device)
|
protected MessengerBase(string key, string messagePath, IKeyName device)
|
||||||
: this(key, messagePath)
|
: this(key, messagePath)
|
||||||
{
|
{
|
||||||
@@ -56,7 +78,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the interfaces implmented on the device
|
/// Gets the interfaces implented on the device
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="device"></param>
|
/// <param name="device"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
@@ -93,6 +115,11 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
action(id, content);
|
action(id, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds an action to be executed when a message is received at the specified path
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path to register the action for</param>
|
||||||
|
/// <param name="action">The action to execute when the path is matched</param>
|
||||||
protected void AddAction(string path, Action<string, JToken> action)
|
protected void AddAction(string path, Action<string, JToken> action)
|
||||||
{
|
{
|
||||||
if (_actions.ContainsKey(path))
|
if (_actions.ContainsKey(path))
|
||||||
@@ -104,11 +131,19 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
_actions.Add(path, action);
|
_actions.Add(path, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a list of all registered action paths
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A list of action paths</returns>
|
||||||
public List<string> GetActionPaths()
|
public List<string> GetActionPaths()
|
||||||
{
|
{
|
||||||
return _actions.Keys.ToList();
|
return _actions.Keys.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes an action from the specified path
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path to remove the action from</param>
|
||||||
protected void RemoveAction(string path)
|
protected void RemoveAction(string path)
|
||||||
{
|
{
|
||||||
if (!_actions.ContainsKey(path))
|
if (!_actions.ContainsKey(path))
|
||||||
@@ -122,7 +157,6 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implemented in extending classes. Wire up API calls and feedback here
|
/// Implemented in extending classes. Wire up API calls and feedback here
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="appServerController"></param>
|
|
||||||
protected virtual void RegisterActions()
|
protected virtual void RegisterActions()
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -131,8 +165,8 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper for posting status message
|
/// Helper for posting status message
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="type"></param>
|
/// <param name="message">The device state message to post</param>
|
||||||
/// <param name="message"></param>
|
/// <param name="clientId">Optional client ID to send the message to a specific client</param>
|
||||||
protected void PostStatusMessage(DeviceStateMessageBase message, string clientId = null)
|
protected void PostStatusMessage(DeviceStateMessageBase message, string clientId = null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -153,16 +187,22 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
|
|
||||||
message.Name = _device.Name;
|
message.Name = _device.Name;
|
||||||
|
|
||||||
var token = JToken.FromObject(message);
|
var token = JToken.FromObject(message);
|
||||||
|
|
||||||
PostStatusMessage(token, MessagePath, clientId);
|
PostStatusMessage(token, MessagePath, clientId);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
this.LogError(ex, "Exception posting status message for {messagePath} to {clientId}", MessagePath, clientId ?? "all clients");
|
this.LogError(ex, "Exception posting status message for {messagePath} to {clientId}", MessagePath, clientId ?? "all clients");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Posts a status message with a specific message type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The message type to send</param>
|
||||||
|
/// <param name="deviceState">The device state message to post</param>
|
||||||
|
/// <param name="clientId">Optional client ID to send the message to a specific client</param>
|
||||||
protected void PostStatusMessage(string type, DeviceStateMessageBase deviceState, string clientId = null)
|
protected void PostStatusMessage(string type, DeviceStateMessageBase deviceState, string clientId = null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -182,10 +222,16 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
this.LogError(ex, "Exception posting status message for {type} to {clientId}", type, clientId ?? "all clients");
|
this.LogError(ex, "Exception posting status message for {type} to {clientId}", type, clientId ?? "all clients");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Posts a status message with JSON content
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">The JSON content to send</param>
|
||||||
|
/// <param name="type">The message type (defaults to MessagePath if empty)</param>
|
||||||
|
/// <param name="clientId">Optional client ID to send the message to a specific client</param>
|
||||||
protected void PostStatusMessage(JToken content, string type = "", string clientId = null)
|
protected void PostStatusMessage(JToken content, string type = "", string clientId = null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -198,6 +244,10 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Posts an event message for the device
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The device event message to post</param>
|
||||||
protected void PostEventMessage(DeviceEventMessageBase message)
|
protected void PostEventMessage(DeviceEventMessageBase message)
|
||||||
{
|
{
|
||||||
message.Key = _device.Key;
|
message.Key = _device.Key;
|
||||||
@@ -211,6 +261,11 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Posts an event message with a specific event type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The device event message to post</param>
|
||||||
|
/// <param name="eventType">The event type to use</param>
|
||||||
protected void PostEventMessage(DeviceEventMessageBase message, string eventType)
|
protected void PostEventMessage(DeviceEventMessageBase message, string eventType)
|
||||||
{
|
{
|
||||||
message.Key = _device.Key;
|
message.Key = _device.Key;
|
||||||
@@ -226,6 +281,10 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Posts an event message with only an event type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eventType">The event type to post</param>
|
||||||
protected void PostEventMessage(string eventType)
|
protected void PostEventMessage(string eventType)
|
||||||
{
|
{
|
||||||
AppServerController?.SendMessageObject(new MobileControlMessage
|
AppServerController?.SendMessageObject(new MobileControlMessage
|
||||||
@@ -237,6 +296,9 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Base class for device messages containing common properties like key, name, and message type
|
||||||
|
/// </summary>
|
||||||
public abstract class DeviceMessageBase
|
public abstract class DeviceMessageBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -257,21 +319,28 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
[JsonProperty("messageType")]
|
[JsonProperty("messageType")]
|
||||||
public string MessageType => GetType().Name;
|
public string MessageType => GetType().Name;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the base path for the message
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("messageBasePath")]
|
[JsonProperty("messageBasePath")]
|
||||||
public string MessageBasePath { get; set; }
|
public string MessageBasePath { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base class for state messages that includes the type of message and the implmented interfaces
|
/// Base class for state messages that includes the type of message and the implemented interfaces
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DeviceStateMessageBase : DeviceMessageBase
|
public class DeviceStateMessageBase : DeviceMessageBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The interfaces implmented by the device sending the messsage
|
/// The interfaces implented by the device sending the messsage
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("interfaces")]
|
[JsonProperty("interfaces")]
|
||||||
public List<string> Interfaces { get; private set; }
|
public List<string> Interfaces { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the interfaces implemented by the device
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="interfaces">List of interface names to set</param>
|
||||||
public void SetInterfaces(List<string> interfaces)
|
public void SetInterfaces(List<string> interfaces)
|
||||||
{
|
{
|
||||||
Interfaces = interfaces;
|
Interfaces = interfaces;
|
||||||
|
|||||||
@@ -1,19 +1,34 @@
|
|||||||
using Crestron.SimplSharp;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Static handler for managing press and hold button actions with automatic timeout functionality
|
||||||
|
/// </summary>
|
||||||
public static class PressAndHoldHandler
|
public static class PressAndHoldHandler
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The interval in milliseconds for button heartbeat timeout
|
||||||
|
/// </summary>
|
||||||
private const long ButtonHeartbeatInterval = 1000;
|
private const long ButtonHeartbeatInterval = 1000;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dictionary of active timers for pressed actions, keyed by device key
|
||||||
|
/// </summary>
|
||||||
private static readonly Dictionary<string, CTimer> _pushedActions = new Dictionary<string, CTimer>();
|
private static readonly Dictionary<string, CTimer> _pushedActions = new Dictionary<string, CTimer>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dictionary of action handlers for different button states
|
||||||
|
/// </summary>
|
||||||
private static readonly Dictionary<string, Action<string, Action<bool>>> _pushedActionHandlers;
|
private static readonly Dictionary<string, Action<string, Action<bool>>> _pushedActionHandlers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Static constructor that initializes the action handlers for different button states
|
||||||
|
/// </summary>
|
||||||
static PressAndHoldHandler()
|
static PressAndHoldHandler()
|
||||||
{
|
{
|
||||||
_pushedActionHandlers = new Dictionary<string, Action<string, Action<bool>>>
|
_pushedActionHandlers = new Dictionary<string, Action<string, Action<bool>>>
|
||||||
@@ -24,6 +39,11 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a timer for a device key and executes the action with true state
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deviceKey">The unique key for the device</param>
|
||||||
|
/// <param name="action">The action to execute with boolean state</param>
|
||||||
private static void AddTimer(string deviceKey, Action<bool> action)
|
private static void AddTimer(string deviceKey, Action<bool> action)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to add timer for {deviceKey}", deviceKey);
|
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to add timer for {deviceKey}", deviceKey);
|
||||||
@@ -50,6 +70,11 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
_pushedActions.Add(deviceKey, cancelTimer);
|
_pushedActions.Add(deviceKey, cancelTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resets an existing timer for the specified device key
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deviceKey">The unique key for the device</param>
|
||||||
|
/// <param name="action">The action associated with the timer</param>
|
||||||
private static void ResetTimer(string deviceKey, Action<bool> action)
|
private static void ResetTimer(string deviceKey, Action<bool> action)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to reset timer for {deviceKey}", deviceKey);
|
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to reset timer for {deviceKey}", deviceKey);
|
||||||
@@ -65,6 +90,11 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
cancelTimer.Reset(ButtonHeartbeatInterval);
|
cancelTimer.Reset(ButtonHeartbeatInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stops and removes the timer for the specified device key
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deviceKey">The unique key for the device</param>
|
||||||
|
/// <param name="action">The action to execute with false state before stopping</param>
|
||||||
private static void StopTimer(string deviceKey, Action<bool> action)
|
private static void StopTimer(string deviceKey, Action<bool> action)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to stop timer for {deviceKey}", deviceKey);
|
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to stop timer for {deviceKey}", deviceKey);
|
||||||
@@ -82,6 +112,11 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
_pushedActions.Remove(deviceKey);
|
_pushedActions.Remove(deviceKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the appropriate press and hold handler for the specified value
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The button state value (pressed, held, released)</param>
|
||||||
|
/// <returns>The handler action for the specified state, or null if not found</returns>
|
||||||
public static Action<string, Action<bool>> GetPressAndHoldHandler(string value)
|
public static Action<string, Action<bool>> GetPressAndHoldHandler(string value)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Getting press and hold handler for {value}", value);
|
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Getting press and hold handler for {value}", value);
|
||||||
@@ -97,6 +132,12 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles press and hold messages by parsing the content and executing the appropriate handler
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deviceKey">The unique key for the device</param>
|
||||||
|
/// <param name="content">The JSON content containing the button state</param>
|
||||||
|
/// <param name="action">The action to execute with boolean state</param>
|
||||||
public static void HandlePressAndHold(string deviceKey, JToken content, Action<bool> action)
|
public static void HandlePressAndHold(string deviceKey, JToken content, Action<bool> action)
|
||||||
{
|
{
|
||||||
var msg = content.ToObject<MobileControlSimpleContent<string>>();
|
var msg = content.ToObject<MobileControlSimpleContent<string>>();
|
||||||
|
|||||||
@@ -1,18 +1,30 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Core.Logging;
|
using PepperDash.Core.Logging;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using PepperDash.Essentials.Room.Config;
|
using PepperDash.Essentials.Room.Config;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Messenger for managing scheduled events in a room.
|
||||||
|
/// This class handles saving scheduled events and sending the current schedule state to clients.
|
||||||
|
/// It listens for changes in the scheduled events and updates clients accordingly.
|
||||||
|
/// </summary>
|
||||||
public class RoomEventScheduleMessenger : MessengerBase
|
public class RoomEventScheduleMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly IRoomEventSchedule _room;
|
private readonly IRoomEventSchedule _room;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RoomEventScheduleMessenger"/> class.
|
||||||
|
/// This constructor sets up the messenger with a unique key, message path, and the room event schedule interface.
|
||||||
|
/// It registers actions for saving scheduled events and sending the current schedule state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
|
/// <param name="room">Room event schedule interface</param>
|
||||||
public RoomEventScheduleMessenger(string key, string messagePath, IRoomEventSchedule room)
|
public RoomEventScheduleMessenger(string key, string messagePath, IRoomEventSchedule room)
|
||||||
: base(key, messagePath, room as IKeyName)
|
: base(key, messagePath, room as IKeyName)
|
||||||
{
|
{
|
||||||
@@ -21,6 +33,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
|
|
||||||
#region Overrides of MessengerBase
|
#region Overrides of MessengerBase
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
AddAction("/saveScheduledEvents", (id, content) => SaveScheduledEvents(content.ToObject<List<ScheduledEventConfig>>()));
|
AddAction("/saveScheduledEvents", (id, content) => SaveScheduledEvents(content.ToObject<List<ScheduledEventConfig>>()));
|
||||||
@@ -28,7 +41,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
{
|
{
|
||||||
var events = _room.GetScheduledEvents();
|
var events = _room.GetScheduledEvents();
|
||||||
|
|
||||||
SendFullStatus(events);
|
SendFullStatus(events, id);
|
||||||
});
|
});
|
||||||
|
|
||||||
_room.ScheduledEventsChanged += (sender, args) => SendFullStatus(args.ScheduledEvents);
|
_room.ScheduledEventsChanged += (sender, args) => SendFullStatus(args.ScheduledEvents);
|
||||||
@@ -52,11 +65,11 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
this.LogException(ex,"Exception saving event");
|
this.LogException(ex, "Exception saving event");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendFullStatus(List<ScheduledEventConfig> events)
|
private void SendFullStatus(List<ScheduledEventConfig> events, string id = null)
|
||||||
{
|
{
|
||||||
|
|
||||||
var message = new RoomEventScheduleStateMessage
|
var message = new RoomEventScheduleStateMessage
|
||||||
@@ -64,12 +77,22 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
ScheduleEvents = events,
|
ScheduleEvents = events,
|
||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(message);
|
PostStatusMessage(message, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the state message for room event schedules.
|
||||||
|
/// This message contains a list of scheduled events configured for the room.
|
||||||
|
/// It is used to communicate the current schedule state to clients.
|
||||||
|
/// </summary>
|
||||||
public class RoomEventScheduleStateMessage : DeviceStateMessageBase
|
public class RoomEventScheduleStateMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the list of scheduled events for the room.
|
||||||
|
/// This property contains the configuration of scheduled events that are set up in the room.
|
||||||
|
/// Each event includes details such as the event name, start time, end time, and recurrence pattern.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("scheduleEvents")]
|
[JsonProperty("scheduleEvents")]
|
||||||
public List<ScheduledEventConfig> ScheduleEvents { get; set; }
|
public List<ScheduledEventConfig> ScheduleEvents { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,39 @@
|
|||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using PepperDash.Essentials.Devices.Common.Codec;
|
using PepperDash.Essentials.Devices.Common.Codec;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// SIMPL messenger for audio-only conference devices that provides audio calling functionality
|
||||||
|
/// </summary>
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public class SIMPLAtcMessenger : MessengerBase
|
public class SIMPLAtcMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The EISC (Ethernet Intersystem Communication) device
|
||||||
|
/// </summary>
|
||||||
private readonly BasicTriList _eisc;
|
private readonly BasicTriList _eisc;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the join map for SIMPL ATC operations
|
||||||
|
/// </summary>
|
||||||
public SIMPLAtcJoinMap JoinMap { get; private set; }
|
public SIMPLAtcJoinMap JoinMap { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// The current active call item for audio calls
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly CodecActiveCallItem _currentCallItem;
|
private readonly CodecActiveCallItem _currentCallItem;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Initializes a new instance of the SIMPLAtcMessenger class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key"></param>
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
/// <param name="eisc"></param>
|
/// <param name="eisc">The EISC device for communication</param>
|
||||||
/// <param name="messagePath"></param>
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
public SIMPLAtcMessenger(string key, BasicTriList eisc, string messagePath)
|
public SIMPLAtcMessenger(string key, BasicTriList eisc, string messagePath)
|
||||||
: base(key, messagePath)
|
: base(key, messagePath)
|
||||||
{
|
{
|
||||||
@@ -38,7 +45,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Sends the current status of the audio conference device to connected clients
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void SendFullStatus()
|
private void SendFullStatus()
|
||||||
{
|
{
|
||||||
@@ -53,9 +60,8 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Registers actions and feedback handlers for the SIMPL ATC messenger
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="appServerController"></param>
|
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
//EISC.SetStringSigAction(SCurrentDialString, s => PostStatusMessage(new { currentDialString = s }));
|
//EISC.SetStringSigAction(SCurrentDialString, s => PostStatusMessage(new { currentDialString = s }));
|
||||||
@@ -133,7 +139,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Sends the current calls list to connected clients
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void SendCallsList()
|
private void SendCallsList()
|
||||||
{
|
{
|
||||||
@@ -145,9 +151,9 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Turns the
|
/// Gets the current call list based on the call status
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns>A list containing the current call item if connected, or an empty list if disconnected</returns>
|
||||||
private List<CodecActiveCallItem> GetCurrentCallList()
|
private List<CodecActiveCallItem> GetCurrentCallList()
|
||||||
{
|
{
|
||||||
return _currentCallItem.Status == eCodecCallStatus.Disconnected
|
return _currentCallItem.Status == eCodecCallStatus.Disconnected
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
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.Devices.Common.Cameras;
|
using PepperDash.Essentials.Devices.Common.Cameras;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides messaging capabilities for camera control operations in SIMPL-based systems.
|
||||||
|
/// Handles camera movement, zoom, preset management, and mode control.
|
||||||
|
/// </summary>
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public class SIMPLCameraMessenger : MessengerBase
|
public class SIMPLCameraMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
@@ -16,7 +20,13 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
|
|
||||||
private readonly CameraControllerJoinMap _joinMap;
|
private readonly CameraControllerJoinMap _joinMap;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SIMPLCameraMessenger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique identifier for this messenger instance.</param>
|
||||||
|
/// <param name="eisc">The basic tri-list for SIMPL communication.</param>
|
||||||
|
/// <param name="messagePath">The message path for camera control messages.</param>
|
||||||
|
/// <param name="joinStart">The starting join number for SIMPL signal mapping.</param>
|
||||||
public SIMPLCameraMessenger(string key, BasicTriList eisc, string messagePath, uint joinStart)
|
public SIMPLCameraMessenger(string key, BasicTriList eisc, string messagePath, uint joinStart)
|
||||||
: base(key, messagePath)
|
: base(key, messagePath)
|
||||||
{
|
{
|
||||||
@@ -32,6 +42,10 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers actions for handling camera control operations.
|
||||||
|
/// Includes camera movement, zoom, preset management, and mode control actions.
|
||||||
|
/// </summary>
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
AddAction("/fullStatus", (id, content) => SendCameraFullMessageObject());
|
AddAction("/fullStatus", (id, content) => SendCameraFullMessageObject());
|
||||||
|
|||||||
@@ -1,19 +1,35 @@
|
|||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
using System.Collections.Generic;
|
||||||
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides messaging capabilities for direct routing operations in SIMPL-based systems.
|
||||||
|
/// Handles source selection, destination routing, and advanced sharing mode functionality.
|
||||||
|
/// </summary>
|
||||||
public class SimplDirectRouteMessenger : MessengerBase
|
public class SimplDirectRouteMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly BasicTriList _eisc;
|
private readonly BasicTriList _eisc;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the join map for SIMPL direct route actions.
|
||||||
|
/// </summary>
|
||||||
public MobileControlSIMPLRunDirectRouteActionJoinMap JoinMap { get; private set; }
|
public MobileControlSIMPLRunDirectRouteActionJoinMap JoinMap { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the dictionary of destination items for routing operations.
|
||||||
|
/// </summary>
|
||||||
public Dictionary<string, DestinationListItem> DestinationList { get; set; }
|
public Dictionary<string, DestinationListItem> DestinationList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SimplDirectRouteMessenger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique identifier for this messenger instance.</param>
|
||||||
|
/// <param name="eisc">The basic tri-list for SIMPL communication.</param>
|
||||||
|
/// <param name="messagePath">The message path for routing messages.</param>
|
||||||
public SimplDirectRouteMessenger(string key, BasicTriList eisc, string messagePath) : base(key, messagePath)
|
public SimplDirectRouteMessenger(string key, BasicTriList eisc, string messagePath) : base(key, messagePath)
|
||||||
{
|
{
|
||||||
_eisc = eisc;
|
_eisc = eisc;
|
||||||
@@ -25,6 +41,10 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
|
|
||||||
#region Overrides of MessengerBase
|
#region Overrides of MessengerBase
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers actions for handling direct route messaging operations.
|
||||||
|
/// Includes audio source selection, full status reporting, and advanced sharing mode controls.
|
||||||
|
/// </summary>
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
Debug.Console(2, "********** Direct Route Messenger CustomRegisterWithAppServer **********");
|
Debug.Console(2, "********** Direct Route Messenger CustomRegisterWithAppServer **********");
|
||||||
@@ -92,6 +112,10 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers routing actions for each destination in the destination list.
|
||||||
|
/// Sets up feedback handlers and source selection actions for individual destinations.
|
||||||
|
/// </summary>
|
||||||
public void RegisterForDestinationPaths()
|
public void RegisterForDestinationPaths()
|
||||||
{
|
{
|
||||||
//handle routing feedback from SIMPL
|
//handle routing feedback from SIMPL
|
||||||
@@ -114,6 +138,11 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the source selection for a specific destination and posts a status message.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sourceKey">The key of the selected source.</param>
|
||||||
|
/// <param name="destKey">The key of the destination being updated.</param>
|
||||||
private void UpdateSourceForDestination(string sourceKey, string destKey)
|
private void UpdateSourceForDestination(string sourceKey, string destKey)
|
||||||
{
|
{
|
||||||
PostStatusMessage(JToken.FromObject(new
|
PostStatusMessage(JToken.FromObject(new
|
||||||
|
|||||||
@@ -6,21 +6,34 @@ using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides messaging capabilities for routing operations in SIMPL-based systems.
|
||||||
|
/// Handles source selection and routing status feedback.
|
||||||
|
/// </summary>
|
||||||
public class SIMPLRouteMessenger : MessengerBase
|
public class SIMPLRouteMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly BasicTriList _eisc;
|
private readonly BasicTriList _eisc;
|
||||||
|
|
||||||
private readonly uint _joinStart;
|
private readonly uint _joinStart;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the string join mappings for SIMPL routing operations.
|
||||||
|
/// </summary>
|
||||||
public class StringJoin
|
public class StringJoin
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 1
|
/// Join number for current source information (1).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const uint CurrentSource = 1;
|
public const uint CurrentSource = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SIMPLRouteMessenger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique identifier for this messenger instance.</param>
|
||||||
|
/// <param name="eisc">The basic tri-list for SIMPL communication.</param>
|
||||||
|
/// <param name="messagePath">The message path for routing messages.</param>
|
||||||
|
/// <param name="joinStart">The starting join number for SIMPL signal mapping.</param>
|
||||||
public SIMPLRouteMessenger(string key, BasicTriList eisc, string messagePath, uint joinStart)
|
public SIMPLRouteMessenger(string key, BasicTriList eisc, string messagePath, uint joinStart)
|
||||||
: base(key, messagePath)
|
: base(key, messagePath)
|
||||||
{
|
{
|
||||||
@@ -30,6 +43,10 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
_eisc.SetStringSigAction(_joinStart + StringJoin.CurrentSource, SendRoutingFullMessageObject);
|
_eisc.SetStringSigAction(_joinStart + StringJoin.CurrentSource, SendRoutingFullMessageObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers actions for handling routing operations and status reporting.
|
||||||
|
/// Includes full status requests and source selection actions.
|
||||||
|
/// </summary>
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
AddAction("/fullStatus",
|
AddAction("/fullStatus",
|
||||||
@@ -43,6 +60,11 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unregisters this messenger from the mobile control app server.
|
||||||
|
/// Removes all registered actions and clears SIMPL signal actions.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="appServerController">The mobile control app server controller.</param>
|
||||||
public void CustomUnregisterWithAppServer(IMobileControl appServerController)
|
public void CustomUnregisterWithAppServer(IMobileControl appServerController)
|
||||||
{
|
{
|
||||||
appServerController.RemoveAction(MessagePath + "/fullStatus");
|
appServerController.RemoveAction(MessagePath + "/fullStatus");
|
||||||
|
|||||||
@@ -1,33 +1,51 @@
|
|||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using PepperDash.Essentials.Devices.Common.Cameras;
|
using PepperDash.Essentials.Devices.Common.Cameras;
|
||||||
using PepperDash.Essentials.Devices.Common.Codec;
|
using PepperDash.Essentials.Devices.Common.Codec;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// SIMPL messenger for video conference devices that provides video calling and camera control functionality
|
||||||
|
/// </summary>
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public class SIMPLVtcMessenger : MessengerBase
|
public class SIMPLVtcMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The EISC (Ethernet Intersystem Communication) device
|
||||||
|
/// </summary>
|
||||||
private readonly BasicTriList _eisc;
|
private readonly BasicTriList _eisc;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the join map for SIMPL VTC operations
|
||||||
|
/// </summary>
|
||||||
public SIMPLVtcJoinMap JoinMap { get; private set; }
|
public SIMPLVtcJoinMap JoinMap { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current active call item for video calls
|
||||||
|
/// </summary>
|
||||||
private readonly CodecActiveCallItem _currentCallItem;
|
private readonly CodecActiveCallItem _currentCallItem;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The incoming call item for video calls
|
||||||
|
/// </summary>
|
||||||
private CodecActiveCallItem _incomingCallItem;
|
private CodecActiveCallItem _incomingCallItem;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The previous directory length for tracking changes
|
||||||
|
/// </summary>
|
||||||
private ushort _previousDirectoryLength = 701;
|
private ushort _previousDirectoryLength = 701;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Initializes a new instance of the SIMPLVtcMessenger class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key"></param>
|
/// <param name="key">Unique identifier for the messenger</param>
|
||||||
/// <param name="eisc"></param>
|
/// <param name="eisc">The EISC device for communication</param>
|
||||||
/// <param name="messagePath"></param>
|
/// <param name="messagePath">Path for message routing</param>
|
||||||
public SIMPLVtcMessenger(string key, BasicTriList eisc, string messagePath)
|
public SIMPLVtcMessenger(string key, BasicTriList eisc, string messagePath)
|
||||||
: base(key, messagePath)
|
: base(key, messagePath)
|
||||||
{
|
{
|
||||||
@@ -39,9 +57,8 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Registers actions and feedback handlers for the SIMPL VTC messenger
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="appServerController"></param>
|
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
_eisc.SetStringSigAction(JoinMap.HookState.JoinNumber, s =>
|
_eisc.SetStringSigAction(JoinMap.HookState.JoinNumber, s =>
|
||||||
|
|||||||
@@ -1,25 +1,39 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core.Shades;
|
using PepperDash.Essentials.Core.Shades;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides messaging capabilities for shade control operations.
|
||||||
|
/// Handles shade open, close, and stop commands for shades that support these operations.
|
||||||
|
/// </summary>
|
||||||
public class IShadesOpenCloseStopMessenger : MessengerBase
|
public class IShadesOpenCloseStopMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly IShadesOpenCloseStop device;
|
private readonly IShadesOpenCloseStop device;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="IShadesOpenCloseStopMessenger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique identifier for this messenger instance.</param>
|
||||||
|
/// <param name="shades">The shade device that provides open/close/stop functionality.</param>
|
||||||
|
/// <param name="messagePath">The message path for shade control messages.</param>
|
||||||
public IShadesOpenCloseStopMessenger(string key, IShadesOpenCloseStop shades, string messagePath)
|
public IShadesOpenCloseStopMessenger(string key, IShadesOpenCloseStop shades, string messagePath)
|
||||||
: base(key, messagePath, shades as IKeyName)
|
: base(key, messagePath, shades as IKeyName)
|
||||||
{
|
{
|
||||||
device = shades;
|
device = shades;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers actions for handling shade control operations.
|
||||||
|
/// Includes shade open, close, stop, and full status reporting.
|
||||||
|
/// </summary>
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|
||||||
AddAction("/fullStatus", (id, content) => SendFullStatus());
|
AddAction("/fullStatus", (id, content) => SendFullStatus(id));
|
||||||
|
|
||||||
AddAction("/shadeUp", (id, content) =>
|
AddAction("/shadeUp", (id, content) =>
|
||||||
{
|
{
|
||||||
@@ -72,7 +86,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void SendFullStatus()
|
private void SendFullStatus(string id = null)
|
||||||
{
|
{
|
||||||
var state = new ShadeBaseStateMessage();
|
var state = new ShadeBaseStateMessage();
|
||||||
|
|
||||||
@@ -82,18 +96,30 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
state.IsClosed = feedbackDevice.ShadeIsClosedFeedback.BoolValue;
|
state.IsClosed = feedbackDevice.ShadeIsClosedFeedback.BoolValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
PostStatusMessage(state);
|
PostStatusMessage(state, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a shade state message containing shade status and control information.
|
||||||
|
/// </summary>
|
||||||
public class ShadeBaseStateMessage : DeviceStateMessageBase
|
public class ShadeBaseStateMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the label for the middle button control.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("middleButtonLabel", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("middleButtonLabel", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string MiddleButtonLabel { get; set; }
|
public string MiddleButtonLabel { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether the shade is open.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("isOpen", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("isOpen", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? IsOpen { get; set; }
|
public bool? IsOpen { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether the shade is closed.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("isClosed", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("isClosed", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? IsClosed { get; set; }
|
public bool? IsClosed { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,28 @@
|
|||||||
using Crestron.SimplSharp;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core.Monitoring;
|
using PepperDash.Essentials.Core.Monitoring;
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides messaging capabilities for system monitoring operations.
|
||||||
|
/// Handles system performance metrics, program status reporting, and monitoring data communication.
|
||||||
|
/// </summary>
|
||||||
public class SystemMonitorMessenger : MessengerBase
|
public class SystemMonitorMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly SystemMonitorController systemMonitor;
|
private readonly SystemMonitorController systemMonitor;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SystemMonitorMessenger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique identifier for this messenger instance.</param>
|
||||||
|
/// <param name="sysMon">The system monitor controller for monitoring operations.</param>
|
||||||
|
/// <param name="messagePath">The message path for system monitor messages.</param>
|
||||||
|
/// <exception cref="ArgumentNullException">Thrown when sysMon is null.</exception>
|
||||||
public SystemMonitorMessenger(string key, SystemMonitorController sysMon, string messagePath)
|
public SystemMonitorMessenger(string key, SystemMonitorController sysMon, string messagePath)
|
||||||
: base(key, messagePath, sysMon)
|
: base(key, messagePath, sysMon)
|
||||||
{
|
{
|
||||||
@@ -53,20 +64,20 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
SendSystemMonitorStatusMessage();
|
SendSystemMonitorStatusMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendFullStatusMessage()
|
private void SendFullStatusMessage(string id = null)
|
||||||
{
|
{
|
||||||
SendSystemMonitorStatusMessage();
|
SendSystemMonitorStatusMessage(id);
|
||||||
|
|
||||||
foreach (var p in systemMonitor.ProgramStatusFeedbackCollection)
|
foreach (var p in systemMonitor.ProgramStatusFeedbackCollection)
|
||||||
{
|
{
|
||||||
PostStatusMessage(JToken.FromObject(p.Value.ProgramInfo));
|
PostStatusMessage(JToken.FromObject(p.Value.ProgramInfo), id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendSystemMonitorStatusMessage()
|
private void SendSystemMonitorStatusMessage(string id = null)
|
||||||
{
|
{
|
||||||
// This takes a while, launch a new thread
|
// This takes a while, launch a new thread
|
||||||
|
|
||||||
Task.Run(() => PostStatusMessage(JToken.FromObject(new SystemMonitorStateMessage
|
Task.Run(() => PostStatusMessage(JToken.FromObject(new SystemMonitorStateMessage
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -76,33 +87,58 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
SnmpVersion = systemMonitor.SnmpVersionFeedback.StringValue,
|
SnmpVersion = systemMonitor.SnmpVersionFeedback.StringValue,
|
||||||
BacnetVersion = systemMonitor.BaCnetAppVersionFeedback.StringValue,
|
BacnetVersion = systemMonitor.BaCnetAppVersionFeedback.StringValue,
|
||||||
ControllerVersion = systemMonitor.ControllerVersionFeedback.StringValue
|
ControllerVersion = systemMonitor.ControllerVersionFeedback.StringValue
|
||||||
})
|
}), id
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers actions for handling system monitor operations.
|
||||||
|
/// Includes full status reporting for system monitoring data.
|
||||||
|
/// </summary>
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
AddAction("/fullStatus", (id, content) => SendFullStatusMessage());
|
AddAction("/fullStatus", (id, content) => SendFullStatusMessage(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the system monitor state message containing system information and version details.
|
||||||
|
/// </summary>
|
||||||
public class SystemMonitorStateMessage
|
public class SystemMonitorStateMessage
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the system time zone offset.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public int TimeZone { get; set; }
|
public int TimeZone { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the system time zone name.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string TimeZoneName { get; set; }
|
public string TimeZoneName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the IO controller version information.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string IoControllerVersion { get; set; }
|
public string IoControllerVersion { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the SNMP version information.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string SnmpVersion { get; set; }
|
public string SnmpVersion { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the BACnet version information.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string BacnetVersion { get; set; }
|
public string BacnetVersion { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the controller version information.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string ControllerVersion { get; set; }
|
public string ControllerVersion { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,27 @@ using PepperDash.Essentials.Devices.Common.Displays;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides messaging capabilities for two-way display control operations.
|
||||||
|
/// Handles display input changes, power state, and cooling/warming status.
|
||||||
|
/// This class extends the MessengerBase to facilitate communication between the display and the mobile control interface.
|
||||||
|
/// </summary>
|
||||||
public class TwoWayDisplayBaseMessenger : MessengerBase
|
public class TwoWayDisplayBaseMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
private readonly TwoWayDisplayBase _display;
|
private readonly TwoWayDisplayBase _display;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="TwoWayDisplayBaseMessenger"/> class.
|
||||||
|
/// This constructor sets up the messenger with a key, message path, and the display instance
|
||||||
|
/// that it will control and monitor.
|
||||||
|
/// The display instance should implement the TwoWayDisplayBase interface to provide the necessary feedback and
|
||||||
|
/// control methods for the display device.
|
||||||
|
/// The messenger will listen for changes in the display's state and send updates to the mobile control interface.
|
||||||
|
/// It also allows for sending commands to the display, such as changing inputs or toggling power states.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique identifier for this messenger instance.</param>
|
||||||
|
/// <param name="messagePath">The message path for display control messages.</param>
|
||||||
|
/// <param name="display">The display instance to control and monitor.</param>
|
||||||
public TwoWayDisplayBaseMessenger(string key, string messagePath, TwoWayDisplayBase display)
|
public TwoWayDisplayBaseMessenger(string key, string messagePath, TwoWayDisplayBase display)
|
||||||
: base(key, messagePath, display)
|
: base(key, messagePath, display)
|
||||||
{
|
{
|
||||||
@@ -17,7 +34,8 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
|
|
||||||
#region Overrides of MessengerBase
|
#region Overrides of MessengerBase
|
||||||
|
|
||||||
public void SendFullStatus()
|
|
||||||
|
private void SendFullStatus(string id = null)
|
||||||
{
|
{
|
||||||
var messageObj = new TwoWayDisplayBaseStateMessage
|
var messageObj = new TwoWayDisplayBaseStateMessage
|
||||||
{
|
{
|
||||||
@@ -25,16 +43,20 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
CurrentInput = _display.CurrentInputFeedback.StringValue
|
CurrentInput = _display.CurrentInputFeedback.StringValue
|
||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(messageObj);
|
PostStatusMessage(messageObj, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers actions for handling two-way display operations.
|
||||||
|
/// This includes sending full status updates and handling input changes, cooling, and warming feedback.
|
||||||
|
/// The actions are registered to respond to specific commands sent from the mobile control interface.
|
||||||
|
/// </summary>
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
base.RegisterActions();
|
base.RegisterActions();
|
||||||
|
|
||||||
AddAction("/fullStatus", (id, content) => SendFullStatus());
|
AddAction("/fullStatus", (id, content) => SendFullStatus(id));
|
||||||
|
|
||||||
//_display.PowerIsOnFeedback.OutputChange += PowerIsOnFeedbackOnOutputChange;
|
|
||||||
_display.CurrentInputFeedback.OutputChange += CurrentInputFeedbackOnOutputChange;
|
_display.CurrentInputFeedback.OutputChange += CurrentInputFeedbackOnOutputChange;
|
||||||
_display.IsCoolingDownFeedback.OutputChange += IsCoolingFeedbackOnOutputChange;
|
_display.IsCoolingDownFeedback.OutputChange += IsCoolingFeedbackOnOutputChange;
|
||||||
_display.IsWarmingUpFeedback.OutputChange += IsWarmingFeedbackOnOutputChange;
|
_display.IsWarmingUpFeedback.OutputChange += IsWarmingFeedbackOnOutputChange;
|
||||||
@@ -49,16 +71,6 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//private void PowerIsOnFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs)
|
|
||||||
//{
|
|
||||||
// PostStatusMessage(JToken.FromObject(new
|
|
||||||
// {
|
|
||||||
// powerState = feedbackEventArgs.BoolValue
|
|
||||||
// })
|
|
||||||
// );
|
|
||||||
//}
|
|
||||||
|
|
||||||
private void IsWarmingFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs)
|
private void IsWarmingFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs)
|
||||||
{
|
{
|
||||||
PostStatusMessage(JToken.FromObject(new
|
PostStatusMessage(JToken.FromObject(new
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
using Crestron.SimplSharp;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
@@ -9,9 +13,6 @@ using PepperDash.Essentials.Devices.Common.Cameras;
|
|||||||
using PepperDash.Essentials.Devices.Common.Codec;
|
using PepperDash.Essentials.Devices.Common.Codec;
|
||||||
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||||
using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces;
|
using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
@@ -21,18 +22,18 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
public class VideoCodecBaseMessenger : MessengerBase
|
public class VideoCodecBaseMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// The video codec device being managed by this messenger.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected VideoCodecBase Codec { get; private set; }
|
protected VideoCodecBase Codec { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Initializes a new instance of the <see cref="VideoCodecBaseMessenger"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key"></param>
|
/// <param name="key">The unique identifier for the messenger.</param>
|
||||||
/// <param name="codec"></param>
|
/// <param name="codec">The video codec device to be managed.</param>
|
||||||
/// <param name="messagePath"></param>
|
/// <param name="messagePath">The message path for communication.</param>
|
||||||
|
/// <exception cref="ArgumentNullException">Thrown when codec is null</exception>
|
||||||
public VideoCodecBaseMessenger(string key, VideoCodecBase codec, string messagePath)
|
public VideoCodecBaseMessenger(string key, VideoCodecBase codec, string messagePath)
|
||||||
: base(key, messagePath, codec)
|
: base(key, messagePath, codec)
|
||||||
{
|
{
|
||||||
@@ -70,11 +71,6 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
PostEventMessage(eventMsg);
|
PostEventMessage(eventMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender"></param>
|
|
||||||
/// <param name="e"></param>
|
|
||||||
private void CallHistory_RecentCallsListHasChanged(object sender, EventArgs e)
|
private void CallHistory_RecentCallsListHasChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -98,10 +94,10 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Handles the event when a directory result is returned from the codec.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender"></param>
|
/// <param name="sender">The source of the event.</param>
|
||||||
/// <param name="e"></param>
|
/// <param name="e">The directory event arguments.</param>
|
||||||
protected virtual void DirCodec_DirectoryResultReturned(object sender, DirectoryEventArgs e)
|
protected virtual void DirCodec_DirectoryResultReturned(object sender, DirectoryEventArgs e)
|
||||||
{
|
{
|
||||||
if (Codec is IHasDirectory)
|
if (Codec is IHasDirectory)
|
||||||
@@ -109,8 +105,9 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Posts the current directory
|
/// Sends the current directory structure to the mobile control interface.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="directory">The directory structure to send.</param>
|
||||||
protected void SendDirectory(CodecDirectory directory)
|
protected void SendDirectory(CodecDirectory directory)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -134,11 +131,6 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender"></param>
|
|
||||||
/// <param name="e"></param>
|
|
||||||
private void Codec_IsReadyChange(object sender, EventArgs e)
|
private void Codec_IsReadyChange(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -151,16 +143,14 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
PostStatusMessage(state);
|
PostStatusMessage(state);
|
||||||
|
|
||||||
SendFullStatus();
|
SendFullStatus();
|
||||||
} catch (Exception ex)
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
this.LogError(ex, "Error sending codec ready status");
|
this.LogError(ex, "Error sending codec ready status");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// Called from base's RegisterWithAppServer method
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="appServerController"></param>
|
|
||||||
protected override void RegisterActions()
|
protected override void RegisterActions()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -169,7 +159,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
|
|
||||||
AddAction("/isReady", (id, content) => SendIsReady());
|
AddAction("/isReady", (id, content) => SendIsReady());
|
||||||
|
|
||||||
AddAction("/fullStatus", (id, content) => SendFullStatus());
|
AddAction("/fullStatus", (id, content) => SendFullStatus(id));
|
||||||
|
|
||||||
AddAction("/dial", (id, content) =>
|
AddAction("/dial", (id, content) =>
|
||||||
{
|
{
|
||||||
@@ -369,7 +359,8 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(state);
|
PostStatusMessage(state);
|
||||||
} catch (Exception ex)
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
this.LogError(ex, "Error posting sharing source");
|
this.LogError(ex, "Error posting sharing source");
|
||||||
}
|
}
|
||||||
@@ -385,7 +376,8 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(state);
|
PostStatusMessage(state);
|
||||||
} catch (Exception ex)
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
this.LogError(ex, "Error posting sharing content");
|
this.LogError(ex, "Error posting sharing content");
|
||||||
}
|
}
|
||||||
@@ -435,15 +427,13 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
{
|
{
|
||||||
MapCameraActions();
|
MapCameraActions();
|
||||||
PostSelectedCamera();
|
PostSelectedCamera();
|
||||||
} catch(Exception ex)
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
this.LogError(ex, "Exception handling camera selected event");
|
this.LogError(ex, "Exception handling camera selected event");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Maps the camera control actions to the current selected camera on the codec
|
|
||||||
/// </summary>
|
|
||||||
private void MapCameraActions()
|
private void MapCameraActions()
|
||||||
{
|
{
|
||||||
if (Codec is IHasCameras cameraCodec && cameraCodec.SelectedCamera != null)
|
if (Codec is IHasCameras cameraCodec && cameraCodec.SelectedCamera != null)
|
||||||
@@ -599,7 +589,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var codec = (Codec as IHasCallHistory);
|
var codec = Codec as IHasCallHistory;
|
||||||
|
|
||||||
if (codec != null)
|
if (codec != null)
|
||||||
{
|
{
|
||||||
@@ -621,20 +611,11 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Helper to grab a call with string ID
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private CodecActiveCallItem GetCallWithId(string id)
|
private CodecActiveCallItem GetCallWithId(string id)
|
||||||
{
|
{
|
||||||
return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id);
|
return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
private void GetDirectory(string id)
|
private void GetDirectory(string id)
|
||||||
{
|
{
|
||||||
if (!(Codec is IHasDirectory dirCodec))
|
if (!(Codec is IHasDirectory dirCodec))
|
||||||
@@ -644,10 +625,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
dirCodec.GetDirectoryFolderContents(id);
|
dirCodec.GetDirectoryFolderContents(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
private void GetDirectoryRoot(string id = null)
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
private void GetDirectoryRoot()
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -675,9 +653,6 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Requests the parent folder contents
|
|
||||||
/// </summary>
|
|
||||||
private void GetPreviousDirectory()
|
private void GetPreviousDirectory()
|
||||||
{
|
{
|
||||||
if (!(Codec is IHasDirectory dirCodec))
|
if (!(Codec is IHasDirectory dirCodec))
|
||||||
@@ -688,17 +663,11 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
dirCodec.GetDirectoryParentFolderContents();
|
dirCodec.GetDirectoryParentFolderContents();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handler for codec changes
|
|
||||||
/// </summary>
|
|
||||||
private void Codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
|
private void Codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
|
||||||
{
|
{
|
||||||
SendFullStatus();
|
SendFullStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
private void SendIsReady()
|
private void SendIsReady()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -719,9 +688,9 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper method to build call status for vtc
|
/// Gets the current status of the video codec.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns> The current status of the video codec.</returns>
|
||||||
protected VideoCodecBaseStateMessage GetStatus()
|
protected VideoCodecBaseStateMessage GetStatus()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -780,14 +749,18 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void SendFullStatus()
|
/// <summary>
|
||||||
|
/// Sends the full status of the codec.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The unique identifier for the status message.</param>
|
||||||
|
protected virtual void SendFullStatus(string id = null)
|
||||||
{
|
{
|
||||||
if (!Codec.IsReady)
|
if (!Codec.IsReady)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CrestronInvoke.BeginInvoke((o) => PostStatusMessage(GetStatus()));
|
Task.Run(() => PostStatusMessage(GetStatus(), id));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PostReceivingContent(bool receivingContent)
|
private void PostReceivingContent(bool receivingContent)
|
||||||
@@ -800,7 +773,8 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
};
|
};
|
||||||
|
|
||||||
PostStatusMessage(state);
|
PostStatusMessage(state);
|
||||||
} catch(Exception ex)
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
this.LogError(ex, "Error posting receiving content");
|
this.LogError(ex, "Error posting receiving content");
|
||||||
}
|
}
|
||||||
@@ -824,9 +798,6 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
private void PostCameraMode()
|
private void PostCameraMode()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -928,164 +899,324 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
public class VideoCodecBaseStateMessage : DeviceStateMessageBase
|
public class VideoCodecBaseStateMessage : DeviceStateMessageBase
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of active calls on the codec.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("calls", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("calls", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public List<CodecActiveCallItem> Calls { get; set; }
|
public List<CodecActiveCallItem> Calls { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current mode of the camera.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("cameraMode", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("cameraMode", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string CameraMode { get; set; }
|
public string CameraMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera self-view is enabled.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("cameraSelfView", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("cameraSelfView", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? CameraSelfViewIsOn { get; set; }
|
public bool? CameraSelfViewIsOn { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current status of the cameras.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("cameras", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("cameras", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public CameraStatus Cameras { get; set; }
|
public CameraStatus Cameras { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera supports auto mode.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("cameraSupportsAutoMode", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("cameraSupportsAutoMode", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? CameraSupportsAutoMode { get; set; }
|
public bool? CameraSupportsAutoMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera supports off mode.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("cameraSupportsOffMode", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("cameraSupportsOffMode", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? CameraSupportsOffMode { get; set; }
|
public bool? CameraSupportsOffMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current dial string for the codec.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("currentDialString", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("currentDialString", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string CurrentDialString { get; set; }
|
public string CurrentDialString { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current directory for the codec.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("currentDirectory", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("currentDirectory", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public CodecDirectory CurrentDirectory { get; set; }
|
public CodecDirectory CurrentDirectory { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the selected folder name in the directory.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("directorySelectedFolderName", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("directorySelectedFolderName", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string DirectorySelectedFolderName { get; set; }
|
public string DirectorySelectedFolderName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the codec has active camera streams.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("hasCameras", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("hasCameras", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? HasCameras { get; set; }
|
public bool? HasCameras { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the codec has a directory.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("hasDirectory", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("hasDirectory", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? HasDirectory { get; set; }
|
public bool? HasDirectory { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the codec supports directory search functionality.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("hasDirectorySearch", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("hasDirectorySearch", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? HasDirectorySearch { get; set; }
|
public bool? HasDirectorySearch { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the codec has presets.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("hasPresets", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("hasPresets", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? HasPresets { get; set; }
|
public bool? HasPresets { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the codec has recent calls.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("hasRecents", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("hasRecents", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? HasRecents { get; set; }
|
public bool? HasRecents { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the initial phonebook sync is complete.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("initialPhonebookSyncComplete", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("initialPhonebookSyncComplete", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? InitialPhonebookSyncComplete { get; set; }
|
public bool? InitialPhonebookSyncComplete { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the information about the video codec.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("info", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("info", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public VideoCodecInfo Info { get; set; }
|
public VideoCodecInfo Info { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the codec is currently in a call.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("isInCall", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("isInCall", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? IsInCall { get; set; }
|
public bool? IsInCall { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the codec is ready.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("isReady", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("isReady", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? IsReady { get; set; }
|
public bool? IsReady { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the codec is a Zoom Room.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("isZoomRoom", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("isZoomRoom", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? IsZoomRoom { get; set; }
|
public bool? IsZoomRoom { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the meeting information for the codec, if available.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("meetingInfo", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("meetingInfo", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public MeetingInfo MeetingInfo { get; set; }
|
public MeetingInfo MeetingInfo { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of presets for the codec.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("presets", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("presets", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public List<CodecRoomPreset> Presets { get; set; }
|
public List<CodecRoomPreset> Presets { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the privacy mode is currently enabled.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("privacyModeIsOn", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("privacyModeIsOn", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? PrivacyModeIsOn { get; set; }
|
public bool? PrivacyModeIsOn { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the codec is currently receiving content.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("receivingContent", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("receivingContent", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? ReceivingContent { get; set; }
|
public bool? ReceivingContent { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of recent calls for the codec, if available.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("recentCalls", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("recentCalls", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public List<CodecCallHistory.CallHistoryEntry> RecentCalls { get; set; }
|
public List<CodecCallHistory.CallHistoryEntry> RecentCalls { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the codec is currently sharing content.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("sharingContentIsOn", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("sharingContentIsOn", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? SharingContentIsOn { get; set; }
|
public bool? SharingContentIsOn { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the source of the shared content, if available.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("sharingSource", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("sharingSource", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string SharingSource { get; set; }
|
public string SharingSource { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the cameras should be shown when not in a call.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("showCamerasWhenNotInCall", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("showCamerasWhenNotInCall", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? ShowCamerasWhenNotInCall { get; set; }
|
public bool? ShowCamerasWhenNotInCall { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the self-view is shown by default.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("showSelfViewByDefault", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("showSelfViewByDefault", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? ShowSelfViewByDefault { get; set; }
|
public bool? ShowSelfViewByDefault { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the codec is currently in standby mode.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("standbyIsOn", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("standbyIsOn", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? StandbyIsOn { get; set; }
|
public bool? StandbyIsOn { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the codec supports ad-hoc meetings.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("supportsAdHocMeeting", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("supportsAdHocMeeting", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? SupportsAdHocMeeting { get; set; }
|
public bool? SupportsAdHocMeeting { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the status of the camera.
|
||||||
|
/// </summary>
|
||||||
public class CameraStatus
|
public class CameraStatus
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera manual control is supported.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("cameraManualSupported", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("cameraManualSupported", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? CameraManualIsSupported { get; set; }
|
public bool? CameraManualIsSupported { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera auto control is supported.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("cameraAutoSupported", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("cameraAutoSupported", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? CameraAutoIsSupported { get; set; }
|
public bool? CameraAutoIsSupported { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera off control is supported.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("cameraOffSupported", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("cameraOffSupported", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? CameraOffIsSupported { get; set; }
|
public bool? CameraOffIsSupported { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates the current mode of the camera.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("cameraMode", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("cameraMode", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string CameraMode { get; set; }
|
public string CameraMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the list of cameras available.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("cameraList", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("cameraList", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public List<CameraBase> Cameras { get; set; }
|
public List<CameraBase> Cameras { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the currently selected camera.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("selectedCamera", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("selectedCamera", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public Camera SelectedCamera { get; set; }
|
public Camera SelectedCamera { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a camera in the video codec system.
|
||||||
|
/// </summary>
|
||||||
public class Camera
|
public class Camera
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The unique identifier for the camera.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string Key { get; set; }
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the camera.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera is a far-end camera.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("isFarEnd", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("isFarEnd", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? IsFarEnd { get; set; }
|
public bool? IsFarEnd { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the capabilities of the camera.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("capabilities", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("capabilities", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public CameraCapabilities Capabilities { get; set; }
|
public CameraCapabilities Capabilities { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the capabilities of the camera.
|
||||||
|
/// </summary>
|
||||||
public class CameraCapabilities
|
public class CameraCapabilities
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera can pan.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? CanPan { get; set; }
|
public bool? CanPan { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera can tilt.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? CanTilt { get; set; }
|
public bool? CanTilt { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera can zoom.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? CanZoom { get; set; }
|
public bool? CanZoom { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera can focus.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool? CanFocus { get; set; }
|
public bool? CanFocus { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a video codec event message.
|
||||||
|
/// </summary>
|
||||||
public class VideoCodecBaseEventMessage : DeviceEventMessageBase
|
public class VideoCodecBaseEventMessage : DeviceEventMessageBase
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a password prompt event message.
|
||||||
|
/// </summary>
|
||||||
public class PasswordPromptEventMessage : VideoCodecBaseEventMessage
|
public class PasswordPromptEventMessage : VideoCodecBaseEventMessage
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The message to display in the password prompt.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("message", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("message", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the last password attempt was incorrect.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("lastAttemptWasIncorrect", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("lastAttemptWasIncorrect", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool LastAttemptWasIncorrect { get; set; }
|
public bool LastAttemptWasIncorrect { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the login attempt failed.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("loginAttemptFailed", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("loginAttemptFailed", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool LoginAttemptFailed { get; set; }
|
public bool LoginAttemptFailed { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the login attempt was cancelled.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("loginAttemptCancelled", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("loginAttemptCancelled", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool LoginAttemptCancelled { get; set; }
|
public bool LoginAttemptCancelled { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,26 @@ using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer.Messengers
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a mobile control message that can be sent between clients and the system
|
||||||
|
/// </summary>
|
||||||
public class MobileControlMessage : IMobileControlMessage
|
public class MobileControlMessage : IMobileControlMessage
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the message type/path for routing
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("type")]
|
[JsonProperty("type")]
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the client ID this message is intended for (null for broadcast)
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("clientId")]
|
[JsonProperty("clientId")]
|
||||||
public string ClientId { get; set; }
|
public string ClientId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the JSON content of the message
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("content")]
|
[JsonProperty("content")]
|
||||||
public JToken Content { get; set; }
|
public JToken Content { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,15 @@
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.AppServer
|
namespace PepperDash.Essentials.AppServer
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Generic container for simple mobile control message content with a single value
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of the value contained in the message</typeparam>
|
||||||
public class MobileControlSimpleContent<T>
|
public class MobileControlSimpleContent<T>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the value of the message content
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("value", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("value", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public T Value { get; set; }
|
public T Value { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
74
src/PepperDash.Essentials.MobileControl/MessageToClients.cs
Normal file
74
src/PepperDash.Essentials.MobileControl/MessageToClients.cs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Core.Logging;
|
||||||
|
using PepperDash.Essentials.AppServer.Messengers;
|
||||||
|
using PepperDash.Essentials.Core.Queues;
|
||||||
|
using PepperDash.Essentials.WebSocketServer;
|
||||||
|
using Serilog.Events;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials
|
||||||
|
{
|
||||||
|
public class MessageToClients : IQueueMessage
|
||||||
|
{
|
||||||
|
private readonly MobileControlWebsocketServer _server;
|
||||||
|
private readonly object msgToSend;
|
||||||
|
|
||||||
|
public MessageToClients(object msg, MobileControlWebsocketServer server)
|
||||||
|
{
|
||||||
|
_server = server;
|
||||||
|
msgToSend = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageToClients(DeviceStateMessageBase msg, MobileControlWebsocketServer server)
|
||||||
|
{
|
||||||
|
_server = server;
|
||||||
|
msgToSend = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Implementation of IQueueMessage
|
||||||
|
|
||||||
|
public void Dispatch()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_server == null)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Warning, "Cannot send message. Server is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var message = JsonConvert.SerializeObject(msgToSend, Formatting.None,
|
||||||
|
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Converters = { new IsoDateTimeConverter() } });
|
||||||
|
|
||||||
|
var clientSpecificMessage = msgToSend as MobileControlMessage;
|
||||||
|
if (clientSpecificMessage.ClientId != null)
|
||||||
|
{
|
||||||
|
var clientId = clientSpecificMessage.ClientId;
|
||||||
|
|
||||||
|
_server.LogVerbose("Message TX To client {clientId} Message: {message}", clientId, message);
|
||||||
|
|
||||||
|
_server.SendMessageToClient(clientId, message);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_server.SendMessageToAllClients(message);
|
||||||
|
|
||||||
|
_server.LogVerbose("Message TX To all clients: {message}", message);
|
||||||
|
}
|
||||||
|
catch (ThreadAbortException)
|
||||||
|
{
|
||||||
|
//Swallowing this exception, as it occurs on shutdown and there's no need to print out a scary stack trace
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(ex, "Caught an exception in the Transmit Processor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,10 @@
|
|||||||
using Crestron.SimplSharp;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
using Crestron.SimplSharp.CrestronIO;
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
using Crestron.SimplSharp.Net.Http;
|
using Crestron.SimplSharp.Net.Http;
|
||||||
using Crestron.SimplSharp.WebScripting;
|
using Crestron.SimplSharp.WebScripting;
|
||||||
@@ -30,12 +36,6 @@ using PepperDash.Essentials.RoomBridges;
|
|||||||
using PepperDash.Essentials.Services;
|
using PepperDash.Essentials.Services;
|
||||||
using PepperDash.Essentials.WebApiHandlers;
|
using PepperDash.Essentials.WebApiHandlers;
|
||||||
using PepperDash.Essentials.WebSocketServer;
|
using PepperDash.Essentials.WebSocketServer;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using WebSocketSharp;
|
using WebSocketSharp;
|
||||||
|
|
||||||
namespace PepperDash.Essentials
|
namespace PepperDash.Essentials
|
||||||
@@ -570,7 +570,7 @@ namespace PepperDash.Essentials
|
|||||||
{
|
{
|
||||||
this.LogVerbose(
|
this.LogVerbose(
|
||||||
"Adding ISetTopBoxControlMessenger for {deviceKey}"
|
"Adding ISetTopBoxControlMessenger for {deviceKey}"
|
||||||
);
|
);
|
||||||
|
|
||||||
var messenger = new ISetTopBoxControlsMessenger(
|
var messenger = new ISetTopBoxControlsMessenger(
|
||||||
$"{device.Key}-stb-{Key}",
|
$"{device.Key}-stb-{Key}",
|
||||||
@@ -587,7 +587,7 @@ namespace PepperDash.Essentials
|
|||||||
{
|
{
|
||||||
this.LogVerbose(
|
this.LogVerbose(
|
||||||
"Adding IChannelMessenger for {deviceKey}", device.Key
|
"Adding IChannelMessenger for {deviceKey}", device.Key
|
||||||
);
|
);
|
||||||
|
|
||||||
var messenger = new IChannelMessenger(
|
var messenger = new IChannelMessenger(
|
||||||
$"{device.Key}-channel-{Key}",
|
$"{device.Key}-channel-{Key}",
|
||||||
@@ -602,7 +602,7 @@ namespace PepperDash.Essentials
|
|||||||
|
|
||||||
if (device is IColor colorDevice)
|
if (device is IColor colorDevice)
|
||||||
{
|
{
|
||||||
this.LogVerbose("Adding IColorMessenger for {deviceKey}", device.Key);
|
this.LogVerbose("Adding IColorMessenger for {deviceKey}", device.Key);
|
||||||
|
|
||||||
var messenger = new IColorMessenger(
|
var messenger = new IColorMessenger(
|
||||||
$"{device.Key}-color-{Key}",
|
$"{device.Key}-color-{Key}",
|
||||||
@@ -617,7 +617,7 @@ namespace PepperDash.Essentials
|
|||||||
|
|
||||||
if (device is IDPad dPadDevice)
|
if (device is IDPad dPadDevice)
|
||||||
{
|
{
|
||||||
this.LogVerbose("Adding IDPadMessenger for {deviceKey}", device.Key);
|
this.LogVerbose("Adding IDPadMessenger for {deviceKey}", device.Key);
|
||||||
|
|
||||||
var messenger = new IDPadMessenger(
|
var messenger = new IDPadMessenger(
|
||||||
$"{device.Key}-dPad-{Key}",
|
$"{device.Key}-dPad-{Key}",
|
||||||
@@ -632,7 +632,7 @@ namespace PepperDash.Essentials
|
|||||||
|
|
||||||
if (device is INumericKeypad nkDevice)
|
if (device is INumericKeypad nkDevice)
|
||||||
{
|
{
|
||||||
this.LogVerbose("Adding INumericKeyapdMessenger for {deviceKey}", device.Key);
|
this.LogVerbose("Adding INumericKeyapdMessenger for {deviceKey}", device.Key);
|
||||||
|
|
||||||
var messenger = new INumericKeypadMessenger(
|
var messenger = new INumericKeypadMessenger(
|
||||||
$"{device.Key}-numericKeypad-{Key}",
|
$"{device.Key}-numericKeypad-{Key}",
|
||||||
@@ -647,7 +647,7 @@ namespace PepperDash.Essentials
|
|||||||
|
|
||||||
if (device is IHasPowerControl pcDevice)
|
if (device is IHasPowerControl pcDevice)
|
||||||
{
|
{
|
||||||
this.LogVerbose("Adding IHasPowerControlMessenger for {deviceKey}", device.Key);
|
this.LogVerbose("Adding IHasPowerControlMessenger for {deviceKey}", device.Key);
|
||||||
|
|
||||||
var messenger = new IHasPowerMessenger(
|
var messenger = new IHasPowerMessenger(
|
||||||
$"{device.Key}-powerControl-{Key}",
|
$"{device.Key}-powerControl-{Key}",
|
||||||
@@ -681,7 +681,7 @@ namespace PepperDash.Essentials
|
|||||||
{
|
{
|
||||||
this.LogVerbose(
|
this.LogVerbose(
|
||||||
"Adding ITransportMessenger for {deviceKey}", device.Key
|
"Adding ITransportMessenger for {deviceKey}", device.Key
|
||||||
);
|
);
|
||||||
|
|
||||||
var messenger = new ITransportMessenger(
|
var messenger = new ITransportMessenger(
|
||||||
$"{device.Key}-transport-{Key}",
|
$"{device.Key}-transport-{Key}",
|
||||||
@@ -1619,12 +1619,12 @@ Mobile Control Direct Server Information:
|
|||||||
Tokens Defined: {0}
|
Tokens Defined: {0}
|
||||||
Clients Connected: {1}
|
Clients Connected: {1}
|
||||||
",
|
",
|
||||||
_directServer.UiClients.Count,
|
_directServer.UiClientContexts.Count,
|
||||||
_directServer.ConnectedUiClientsCount
|
_directServer.ConnectedUiClientsCount
|
||||||
);
|
);
|
||||||
|
|
||||||
var clientNo = 1;
|
var clientNo = 1;
|
||||||
foreach (var clientContext in _directServer.UiClients)
|
foreach (var clientContext in _directServer.UiClientContexts)
|
||||||
{
|
{
|
||||||
var isAlive = false;
|
var isAlive = false;
|
||||||
var duration = "Not Connected";
|
var duration = "Not Connected";
|
||||||
@@ -2238,7 +2238,7 @@ Mobile Control Direct Server Infromation:
|
|||||||
{
|
{
|
||||||
this.LogInformation("-- Warning: Incoming message has no registered handler {type}", message.Type);
|
this.LogInformation("-- Warning: Incoming message has no registered handler {type}", message.Type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var handler in handlers)
|
foreach (var handler in handlers)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -491,7 +491,7 @@ namespace PepperDash.Essentials.Touchpanel
|
|||||||
{
|
{
|
||||||
public MobileControlTouchpanelControllerFactory()
|
public MobileControlTouchpanelControllerFactory()
|
||||||
{
|
{
|
||||||
TypeNames = new List<string>() { "mccrestronapp", "mctsw550", "mctsw750", "mctsw1050", "mctsw560", "mctsw760", "mctsw1060", "mctsw570", "mctsw770", "mcts770", "mctsw1070", "mcts1070", "mcxpanel" };
|
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";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,7 +555,10 @@ namespace PepperDash.Essentials.Touchpanel
|
|||||||
return new Tsw1070(id, Global.ControlSystem);
|
return new Tsw1070(id, Global.ControlSystem);
|
||||||
else if (type == "ts1070")
|
else if (type == "ts1070")
|
||||||
return new Ts1070(id, Global.ControlSystem);
|
return new Ts1070(id, Global.ControlSystem);
|
||||||
else
|
else if (type == "dge1000")
|
||||||
|
return new Dge1000(id, Global.ControlSystem);
|
||||||
|
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);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Core.Logging;
|
|
||||||
using PepperDash.Essentials.AppServer.Messengers;
|
using PepperDash.Essentials.AppServer.Messengers;
|
||||||
using PepperDash.Essentials.Core.Queues;
|
using PepperDash.Essentials.Core.Queues;
|
||||||
using PepperDash.Essentials.WebSocketServer;
|
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using WebSocketSharp;
|
using WebSocketSharp;
|
||||||
|
|
||||||
namespace PepperDash.Essentials
|
namespace PepperDash.Essentials
|
||||||
@@ -65,66 +62,4 @@ namespace PepperDash.Essentials
|
|||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class MessageToClients : IQueueMessage
|
|
||||||
{
|
|
||||||
private readonly MobileControlWebsocketServer _server;
|
|
||||||
private readonly object msgToSend;
|
|
||||||
|
|
||||||
public MessageToClients(object msg, MobileControlWebsocketServer server)
|
|
||||||
{
|
|
||||||
_server = server;
|
|
||||||
msgToSend = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageToClients(DeviceStateMessageBase msg, MobileControlWebsocketServer server)
|
|
||||||
{
|
|
||||||
_server = server;
|
|
||||||
msgToSend = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Implementation of IQueueMessage
|
|
||||||
|
|
||||||
public void Dispatch()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_server == null)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Warning, "Cannot send message. Server is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var message = JsonConvert.SerializeObject(msgToSend, Formatting.None,
|
|
||||||
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Converters = { new IsoDateTimeConverter() } });
|
|
||||||
|
|
||||||
var clientSpecificMessage = msgToSend as MobileControlMessage;
|
|
||||||
if (clientSpecificMessage.ClientId != null)
|
|
||||||
{
|
|
||||||
var clientId = clientSpecificMessage.ClientId;
|
|
||||||
|
|
||||||
_server.LogVerbose("Message TX To client {clientId} Message: {message}", clientId, message);
|
|
||||||
|
|
||||||
_server.SendMessageToClient(clientId, message);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_server.SendMessageToAllClients(message);
|
|
||||||
|
|
||||||
_server.LogVerbose("Message TX To all clients: {message}", message);
|
|
||||||
}
|
|
||||||
catch (ThreadAbortException)
|
|
||||||
{
|
|
||||||
//Swallowing this exception, as it occurs on shutdown and there's no need to print out a scary stack trace
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(ex, "Caught an exception in the Transmit Processor");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
using Crestron.SimplSharp.WebScripting;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Crestron.SimplSharp.WebScripting;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Core.Web.RequestHandlers;
|
using PepperDash.Core.Web.RequestHandlers;
|
||||||
using PepperDash.Essentials.Core.Config;
|
using PepperDash.Essentials.Core.Config;
|
||||||
using PepperDash.Essentials.WebSocketServer;
|
using PepperDash.Essentials.WebSocketServer;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.WebApiHandlers
|
namespace PepperDash.Essentials.WebApiHandlers
|
||||||
{
|
{
|
||||||
@@ -99,13 +99,13 @@ namespace PepperDash.Essentials.WebApiHandlers
|
|||||||
public int ServerPort => directServer.Port;
|
public int ServerPort => directServer.Port;
|
||||||
|
|
||||||
[JsonProperty("tokensDefined")]
|
[JsonProperty("tokensDefined")]
|
||||||
public int TokensDefined => directServer.UiClients.Count;
|
public int TokensDefined => directServer.UiClientContexts.Count;
|
||||||
|
|
||||||
[JsonProperty("clientsConnected")]
|
[JsonProperty("clientsConnected")]
|
||||||
public int ClientsConnected => directServer.ConnectedUiClientsCount;
|
public int ClientsConnected => directServer.ConnectedUiClientsCount;
|
||||||
|
|
||||||
[JsonProperty("clients")]
|
[JsonProperty("clients")]
|
||||||
public List<MobileControlDirectClient> Clients => directServer.UiClients.Select((c, i) => { return new MobileControlDirectClient(c, i, directServer.UserAppUrlPrefix); }).ToList();
|
public List<MobileControlDirectClient> Clients => directServer.UiClientContexts.Select((c, i) => { return new MobileControlDirectClient(c, i, directServer.UserAppUrlPrefix); }).ToList();
|
||||||
|
|
||||||
public MobileControlDirectServer(MobileControlWebsocketServer server)
|
public MobileControlDirectServer(MobileControlWebsocketServer server)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ namespace PepperDash.Essentials.WebApiHandlers
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!server.UiClients.TryGetValue(request.Token, out UiClientContext clientContext))
|
if (!server.UiClientContexts.TryGetValue(request.Token, out UiClientContext clientContext))
|
||||||
{
|
{
|
||||||
var response = new ClientResponse
|
var response = new ClientResponse
|
||||||
{
|
{
|
||||||
@@ -131,7 +131,7 @@ namespace PepperDash.Essentials.WebApiHandlers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
server.UiClients.Remove(request.Token);
|
server.UiClientContexts.Remove(request.Token);
|
||||||
|
|
||||||
server.UpdateSecret();
|
server.UpdateSecret();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.WebSocketServer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the structure of the join response
|
||||||
|
/// </summary>
|
||||||
|
public class JoinResponse
|
||||||
|
{
|
||||||
|
[JsonProperty("clientId")]
|
||||||
|
public string ClientId { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("roomKey")]
|
||||||
|
public string RoomKey { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("systemUUid")]
|
||||||
|
public string SystemUuid { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("roomUUid")]
|
||||||
|
public string RoomUuid { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("config")]
|
||||||
|
public object Config { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("codeExpires")]
|
||||||
|
public DateTime CodeExpires { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("userCode")]
|
||||||
|
public string UserCode { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("userAppUrl")]
|
||||||
|
public string UserAppUrl { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("enableDebug")]
|
||||||
|
public bool EnableDebug { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using Independentsoft.Exchange;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.WebSocketServer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a join token with the associated properties
|
||||||
|
/// </summary>
|
||||||
|
public class JoinToken
|
||||||
|
{
|
||||||
|
public string Code { get; set; }
|
||||||
|
|
||||||
|
public string RoomKey { get; set; }
|
||||||
|
|
||||||
|
public string Uuid { get; set; }
|
||||||
|
|
||||||
|
public string TouchpanelKey { get; set; } = "";
|
||||||
|
|
||||||
|
public string Token { get; set; } = null;
|
||||||
|
|
||||||
|
public string Id { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,21 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.WebSocketServer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the data structure for the grant code and UiClient tokens to be stored in the secrets manager
|
||||||
|
/// </summary>
|
||||||
|
public class ServerTokenSecrets
|
||||||
|
{
|
||||||
|
public string GrantCode { get; set; }
|
||||||
|
|
||||||
|
public Dictionary<string, JoinToken> Tokens { get; set; }
|
||||||
|
|
||||||
|
public ServerTokenSecrets(string grantCode)
|
||||||
|
{
|
||||||
|
GrantCode = grantCode;
|
||||||
|
Tokens = new Dictionary<string, JoinToken>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.AppServer.Messengers;
|
||||||
|
using PepperDash.Essentials.RoomBridges;
|
||||||
|
using Serilog.Events;
|
||||||
|
using WebSocketSharp;
|
||||||
|
using WebSocketSharp.Server;
|
||||||
|
using ErrorEventArgs = WebSocketSharp.ErrorEventArgs;
|
||||||
|
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.WebSocketServer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the behaviour to associate with a UiClient for WebSocket communication
|
||||||
|
/// </summary>
|
||||||
|
public class UiClient : WebSocketBehavior
|
||||||
|
{
|
||||||
|
public MobileControlSystemController Controller { get; set; }
|
||||||
|
|
||||||
|
public string RoomKey { get; set; }
|
||||||
|
|
||||||
|
public string ClientId
|
||||||
|
{
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DateTime _connectionTime;
|
||||||
|
|
||||||
|
public TimeSpan ConnectedDuration
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Context.WebSocket.IsAlive)
|
||||||
|
{
|
||||||
|
return DateTime.Now - _connectionTime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new TimeSpan(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UiClient(string clientId)
|
||||||
|
{
|
||||||
|
ClientId = clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnOpen()
|
||||||
|
{
|
||||||
|
base.OnOpen();
|
||||||
|
|
||||||
|
var url = Context.WebSocket.Url;
|
||||||
|
Debug.LogMessage(LogEventLevel.Verbose, "New WebSocket Connection from: {0}", null, url);
|
||||||
|
|
||||||
|
var match = Regex.Match(url.AbsoluteUri, "(?:ws|wss):\\/\\/.*(?:\\/mc\\/api\\/ui\\/join\\/)(.*)");
|
||||||
|
|
||||||
|
if (!match.Success)
|
||||||
|
{
|
||||||
|
_connectionTime = DateTime.Now;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var clientId = ClientId;
|
||||||
|
|
||||||
|
if (Controller == null)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Verbose, "WebSocket UiClient Controller is null");
|
||||||
|
_connectionTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
var clientJoinedMessage = new MobileControlMessage
|
||||||
|
{
|
||||||
|
Type = "/system/clientJoined",
|
||||||
|
Content = JToken.FromObject(new
|
||||||
|
{
|
||||||
|
clientId,
|
||||||
|
roomKey = RoomKey,
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
Controller.HandleClientMessage(JsonConvert.SerializeObject(clientJoinedMessage));
|
||||||
|
|
||||||
|
var bridge = Controller.GetRoomBridge(RoomKey);
|
||||||
|
|
||||||
|
if (bridge == null) return;
|
||||||
|
|
||||||
|
SendUserCodeToClient(bridge, clientId);
|
||||||
|
|
||||||
|
bridge.UserCodeChanged -= Bridge_UserCodeChanged;
|
||||||
|
bridge.UserCodeChanged += Bridge_UserCodeChanged;
|
||||||
|
|
||||||
|
// TODO: Future: Check token to see if there's already an open session using that token and reject/close the session
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Bridge_UserCodeChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
SendUserCodeToClient((MobileControlEssentialsRoomBridge)sender, ClientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SendUserCodeToClient(MobileControlBridgeBase bridge, string clientId)
|
||||||
|
{
|
||||||
|
var content = new
|
||||||
|
{
|
||||||
|
userCode = bridge.UserCode,
|
||||||
|
qrUrl = bridge.QrCodeUrl,
|
||||||
|
};
|
||||||
|
|
||||||
|
var message = new MobileControlMessage
|
||||||
|
{
|
||||||
|
Type = "/system/userCodeChanged",
|
||||||
|
ClientId = clientId,
|
||||||
|
Content = JToken.FromObject(content)
|
||||||
|
};
|
||||||
|
|
||||||
|
Controller.SendMessageObjectToDirectClient(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnMessage(MessageEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnMessage(e);
|
||||||
|
|
||||||
|
if (e.IsText && e.Data.Length > 0 && Controller != null)
|
||||||
|
{
|
||||||
|
// Forward the message to the controller to be put on the receive queue
|
||||||
|
Controller.HandleClientMessage(e.Data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnClose(CloseEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnClose(e);
|
||||||
|
|
||||||
|
Debug.LogMessage(LogEventLevel.Verbose, "WebSocket UiClient Closing: {0} reason: {1}", null, e.Code, e.Reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnError(ErrorEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnError(e);
|
||||||
|
|
||||||
|
Debug.LogMessage(LogEventLevel.Verbose, "WebSocket UiClient Error: {exception} message: {message}", e.Exception, e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
namespace PepperDash.Essentials.WebSocketServer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an instance of a UiClient and the associated Token
|
||||||
|
/// </summary>
|
||||||
|
public class UiClientContext
|
||||||
|
{
|
||||||
|
public UiClient Client { get; private set; }
|
||||||
|
public JoinToken Token { get; private set; }
|
||||||
|
|
||||||
|
public UiClientContext(JoinToken token)
|
||||||
|
{
|
||||||
|
Token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetClient(UiClient client)
|
||||||
|
{
|
||||||
|
Client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.WebSocketServer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Class to describe the server version info
|
||||||
|
/// </summary>
|
||||||
|
public class Version
|
||||||
|
{
|
||||||
|
[JsonProperty("serverVersion")]
|
||||||
|
public string ServerVersion { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("serverIsRunningOnProcessorHardware")]
|
||||||
|
public bool ServerIsRunningOnProcessorHardware { get; private set; }
|
||||||
|
|
||||||
|
public Version()
|
||||||
|
{
|
||||||
|
ServerIsRunningOnProcessorHardware = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user