Compare commits

..

9 Commits

Author SHA1 Message Date
Andrew Welker
ea6a7568fc Merge remote-tracking branch 'origin/feature/add-IKeyed-to-interfaces' into display-bridging 2025-10-09 16:08:17 -05:00
Andrew Welker
3a2a059ce1 fix: appdebug now has option for setting all sink levels 2025-10-09 16:07:25 -05:00
Andrew Welker
f9d9df9d5c docs: XML comments for Devices.Common 2025-10-09 13:18:36 -05:00
Neil Dorin
c284c4275f feat: Enhance UDPServer initialization in Connect method
Updated the `Connect` method in `GenericUdpServer.cs` to include error handling for hostname parsing. The method now attempts to create a `UDPServer` instance with specified parameters and falls back to default initialization if an error occurs. This improves flexibility and robustness in server setup.
2025-10-09 11:31:38 -06:00
Neil Dorin
0418f8a7cc fix: Fix typos and enhance item selection handling
Corrected parameter name in GenericUdpServer constructor.
Added new action for item selection in ISelectableItemsMessenger
with error handling for missing or invalid keys.
Updated SetItems method to improve clarity and ensure proper
clearing and re-adding of item actions.
2025-10-09 09:40:46 -06:00
Andrew Welker
a5d409e93a fix: analog input check uese correct comparison
input selection coming from SIMPL is 1-based, not 0-based. Comparison to input port array length needs to be <= instead of <
2025-10-09 08:36:26 -05:00
Andrew Welker
59944c0e2f refactor: split up classes to separate files 2025-10-09 08:33:22 -05:00
Neil Dorin
419177ccd5 fix: Add item management and update handling in messenger
Introduces a new private field `_itemKeys` to store item keys. Adds the `SetItems` method to manage item actions and update events, ensuring proper registration and cleanup. The `SendFullStatus` method is now invoked from a dedicated event handler `LocalItem_ItemUpdated`, improving the handling of item updates.
2025-10-08 12:24:17 -06:00
Neil Dorin
bd01e2bacc fix: Add KeyName class and update camera messaging
This commit introduces a new `KeyName` class implementing the `IKeyName` interface, enhancing the representation of camera data. The `CameraController_CameraSelected` and `SendFullStatus` methods are updated to utilize `KeyName` instances for selected and listed cameras, improving data encapsulation and consistency in the `IHasCamerasWithControlsStateMessage`. Additionally, new using directives for logging and core functionalities are added.
2025-10-07 17:10:11 -06:00
121 changed files with 6167 additions and 4501 deletions

View File

@@ -131,14 +131,14 @@ namespace PepperDash.Core
/// <param name="key"></param>
/// <param name="address"></param>
/// <param name="port"></param>
/// <param name="buffefSize"></param>
public GenericUdpServer(string key, string address, int port, int buffefSize)
/// <param name="bufferSize"></param>
public GenericUdpServer(string key, string address, int port, int bufferSize)
: base(key)
{
StreamDebugging = new CommunicationStreamDebugging(key);
Hostname = address;
Port = port;
BufferSize = buffefSize;
BufferSize = bufferSize;
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler);
@@ -194,7 +194,21 @@ namespace PepperDash.Core
{
if (Server == null)
{
Server = new UDPServer();
try
{
var address = IPAddress.Parse(Hostname);
Server = new UDPServer(address, Port, BufferSize);
}
catch (Exception ex)
{
this.LogError("Error parsing IP Address '{ipAddress}': message: {message}", Hostname, ex.Message);
this.LogInformation("Creating UDPServer with default buffersize");
Server = new UDPServer();
}
}
if (string.IsNullOrEmpty(Hostname))

View File

@@ -40,20 +40,20 @@ namespace PepperDash.Core
private static ILogger _logger;
private static readonly LoggingLevelSwitch _consoleLoggingLevelSwitch;
private static readonly LoggingLevelSwitch _consoleLogLevelSwitch;
private static readonly LoggingLevelSwitch _websocketLoggingLevelSwitch;
private static readonly LoggingLevelSwitch _websocketLogLevelSwitch;
private static readonly LoggingLevelSwitch _errorLogLevelSwitch;
private static readonly LoggingLevelSwitch _fileLevelSwitch;
private static readonly LoggingLevelSwitch _fileLogLevelSwitch;
/// <summary>
/// Gets the minimum log level for the websocket sink.
/// </summary>
public static LogEventLevel WebsocketMinimumLogLevel
{
get { return _websocketLoggingLevelSwitch.MinimumLevel; }
get { return _websocketLogLevelSwitch.MinimumLevel; }
}
private static readonly DebugWebsocketSink _websocketSink;
@@ -138,13 +138,13 @@ namespace PepperDash.Core
var defaultFileLogLevel = GetStoredLogEventLevel(FileLevelStoreKey);
_consoleLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultConsoleLevel);
_consoleLogLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultConsoleLevel);
_websocketLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultWebsocketLevel);
_websocketLogLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultWebsocketLevel);
_errorLogLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultErrorLogLevel);
_fileLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultFileLogLevel);
_fileLogLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultFileLogLevel);
_websocketSink = new DebugWebsocketSink(new JsonFormatter(renderMessage: true));
@@ -162,14 +162,14 @@ namespace PepperDash.Core
.MinimumLevel.Verbose()
.Enrich.FromLogContext()
.Enrich.With(new CrestronEnricher())
.WriteTo.Sink(new DebugConsoleSink(new ExpressionTemplate("[{@t:yyyy-MM-dd HH:mm:ss.fff}][{@l:u4}][{App}]{#if Key is not null}[{Key}]{#end} {@m}{#if @x is not null}\r\n{@x}{#end}")), levelSwitch: _consoleLoggingLevelSwitch)
.WriteTo.Sink(_websocketSink, levelSwitch: _websocketLoggingLevelSwitch)
.WriteTo.Sink(new DebugConsoleSink(new ExpressionTemplate("[{@t:yyyy-MM-dd HH:mm:ss.fff}][{@l:u4}][{App}]{#if Key is not null}[{Key}]{#end} {@m}{#if @x is not null}\r\n{@x}{#end}")), levelSwitch: _consoleLogLevelSwitch)
.WriteTo.Sink(_websocketSink, levelSwitch: _websocketLogLevelSwitch)
.WriteTo.Sink(new DebugErrorLogSink(new ExpressionTemplate(errorLogTemplate)), levelSwitch: _errorLogLevelSwitch)
.WriteTo.File(new RenderedCompactJsonFormatter(), logFilePath,
rollingInterval: RollingInterval.Day,
restrictedToMinimumLevel: LogEventLevel.Debug,
retainedFileCountLimit: CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? 30 : 60,
levelSwitch: _fileLevelSwitch
levelSwitch: _fileLogLevelSwitch
);
try
@@ -237,10 +237,13 @@ namespace PepperDash.Core
if (DoNotLoadConfigOnNextBoot)
CrestronConsole.PrintLine(string.Format("Program {0} will not load config after next boot. Use console command go:{0} to load the config manually", InitialParametersClass.ApplicationNumber));
_consoleLoggingLevelSwitch.MinimumLevelChanged += (sender, args) =>
_errorLogLevelSwitch.MinimumLevelChanged += (sender, args) =>
{
LogMessage(LogEventLevel.Information, "Console debug level set to {minimumLevel}", _consoleLoggingLevelSwitch.MinimumLevel);
LogMessage(LogEventLevel.Information, "Error log debug level set to {minimumLevel}", _errorLogLevelSwitch.MinimumLevel);
};
// Set initial error log level based on platform && stored level. If appliance, use stored level, otherwise default to verbose
SetErrorLogMinimumDebugLevel(CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? _errorLogLevelSwitch.MinimumLevel : LogEventLevel.Verbose);
}
/// <summary>
@@ -273,9 +276,9 @@ namespace PepperDash.Core
{
CrestronConsole.Print($"Unable to retrieve stored log level for {levelStoreKey}.\r\nError: {result}.\r\nSetting level to {LogEventLevel.Information}\r\n");
CrestronDataStoreStatic.SetLocalIntValue(levelStoreKey, (int)LogEventLevel.Information);
CrestronDataStoreStatic.SetLocalIntValue(levelStoreKey, levelStoreKey == ErrorLogLevelStoreKey ? (int)LogEventLevel.Warning : (int)LogEventLevel.Information);
return LogEventLevel.Information;
return levelStoreKey == ErrorLogLevelStoreKey ? LogEventLevel.Warning : LogEventLevel.Information;
}
if (logLevel < 0 || logLevel > 5)
@@ -284,6 +287,8 @@ namespace PepperDash.Core
return LogEventLevel.Information;
}
CrestronConsole.PrintLine($"Stored log level for {levelStoreKey} is {logLevel}");
return (LogEventLevel)logLevel;
}
catch (Exception ex)
@@ -349,7 +354,11 @@ namespace PepperDash.Core
if (levelString.Trim() == "?")
{
CrestronConsole.ConsoleCommandResponse(
"Used to set the minimum level of debug messages to be printed to the console:\r\n" +
"Used to set the minimum level of debug messages:\r\n" +
"Usage: appdebug:P [sink] [level]\r\n" +
" sink: console (default), errorlog, file, all\r\n" +
" all: sets all sinks to the specified level\r\n" +
" level: 0-5 or LogEventLevel name\r\n" +
$"{_logLevels[0]} = 0\r\n" +
$"{_logLevels[1]} = 1\r\n" +
$"{_logLevels[2]} = 2\r\n" +
@@ -361,32 +370,88 @@ namespace PepperDash.Core
if (string.IsNullOrEmpty(levelString.Trim()))
{
CrestronConsole.ConsoleCommandResponse("AppDebug level = {0}", _consoleLoggingLevelSwitch.MinimumLevel);
CrestronConsole.ConsoleCommandResponse("Console log level = {0}\r\n", _consoleLogLevelSwitch.MinimumLevel);
CrestronConsole.ConsoleCommandResponse("File log level = {0}\r\n", _fileLogLevelSwitch.MinimumLevel);
CrestronConsole.ConsoleCommandResponse("Error log level = {0}\r\n", _errorLogLevelSwitch.MinimumLevel);
return;
}
if (int.TryParse(levelString, out var levelInt))
// Parse tokens: first token is sink (defaults to console), second token is level
var tokens = levelString.Trim().Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
string sinkName;
string levelToken;
if (tokens.Length == 1)
{
// Single token - assume it's a level for console sink
sinkName = "console";
levelToken = tokens[0];
}
else if (tokens.Length == 2)
{
// Two tokens - first is sink, second is level
sinkName = tokens[0].ToLowerInvariant();
levelToken = tokens[1];
}
else
{
CrestronConsole.ConsoleCommandResponse("Usage: appdebug:P [sink] [level]");
return;
}
// Parse the level using the same logic as before
LogEventLevel level;
if (int.TryParse(levelToken, out var levelInt))
{
if (levelInt < 0 || levelInt > 5)
{
CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level. If using a number, value must be between 0-5");
CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelToken} to valid log level. If using a number, value must be between 0-5");
return;
}
SetDebugLevel((uint)levelInt);
return;
}
if (Enum.TryParse<LogEventLevel>(levelString, true, out var levelEnum))
if (!_logLevels.TryGetValue((uint)levelInt, out level))
{
level = LogEventLevel.Information;
CrestronConsole.ConsoleCommandResponse($"{levelInt} not valid. Setting level to {level}");
}
}
else if (Enum.TryParse(levelToken, true, out level))
{
SetDebugLevel(levelEnum);
// Successfully parsed as LogEventLevel enum
}
else
{
CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelToken} to valid log level");
return;
}
CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level");
// Set the level for the specified sink
switch (sinkName)
{
case "console":
SetDebugLevel(level);
break;
case "errorlog":
SetErrorLogMinimumDebugLevel(level);
break;
case "file":
SetFileMinimumDebugLevel(level);
break;
case "all":
SetDebugLevel(level);
SetErrorLogMinimumDebugLevel(level);
SetFileMinimumDebugLevel(level);
break;
default:
CrestronConsole.ConsoleCommandResponse($"Error: Unknown sink '{sinkName}'. Valid sinks: console, errorlog, file");
break;
}
}
catch
{
CrestronConsole.ConsoleCommandResponse("Usage: appdebug:P [0-5]");
CrestronConsole.ConsoleCommandResponse("Usage: appdebug:P [sink] [level]");
}
}
@@ -416,10 +481,10 @@ namespace PepperDash.Core
/// </summary>
public static void SetDebugLevel(LogEventLevel level)
{
_consoleLoggingLevelSwitch.MinimumLevel = level;
_consoleLogLevelSwitch.MinimumLevel = level;
CrestronConsole.ConsoleCommandResponse("[Application {0}], Debug level set to {1}\r\n",
InitialParametersClass.ApplicationNumber, _consoleLoggingLevelSwitch.MinimumLevel);
CrestronConsole.ConsoleCommandResponse("[Application {0}] Debug level set to {1}\r\n",
InitialParametersClass.ApplicationNumber, _consoleLogLevelSwitch.MinimumLevel);
CrestronConsole.ConsoleCommandResponse($"Storing level {level}:{(int)level}");
@@ -436,14 +501,14 @@ namespace PepperDash.Core
/// </summary>
public static void SetWebSocketMinimumDebugLevel(LogEventLevel level)
{
_websocketLoggingLevelSwitch.MinimumLevel = level;
_websocketLogLevelSwitch.MinimumLevel = level;
var err = CrestronDataStoreStatic.SetLocalUintValue(WebSocketLevelStoreKey, (uint)level);
if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
LogMessage(LogEventLevel.Information, "Error saving websocket debug level setting: {erro}", err);
LogMessage(LogEventLevel.Information, "Websocket debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel);
LogMessage(LogEventLevel.Information, "Websocket debug level set to {0}", _websocketLogLevelSwitch.MinimumLevel);
}
/// <summary>
@@ -453,12 +518,17 @@ namespace PepperDash.Core
{
_errorLogLevelSwitch.MinimumLevel = level;
var err = CrestronDataStoreStatic.SetLocalUintValue(ErrorLogLevelStoreKey, (uint)level);
CrestronConsole.ConsoleCommandResponse("[Application {0}] Error log level set to {1}\r\n",
InitialParametersClass.ApplicationNumber, _errorLogLevelSwitch.MinimumLevel);
CrestronConsole.ConsoleCommandResponse($"Storing level {level}:{(int)level}");
var err = CrestronDataStoreStatic.SetLocalIntValue(ErrorLogLevelStoreKey, (int)level);
CrestronConsole.ConsoleCommandResponse($"Store result: {err}:{(int)level}");
if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
LogMessage(LogEventLevel.Information, "Error saving Error Log debug level setting: {error}", err);
LogMessage(LogEventLevel.Information, "Error log debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel);
CrestronConsole.PrintLine($"Error saving error log debug level setting: {err}");
}
/// <summary>
@@ -466,14 +536,19 @@ namespace PepperDash.Core
/// </summary>
public static void SetFileMinimumDebugLevel(LogEventLevel level)
{
_errorLogLevelSwitch.MinimumLevel = level;
_fileLogLevelSwitch.MinimumLevel = level;
var err = CrestronDataStoreStatic.SetLocalUintValue(ErrorLogLevelStoreKey, (uint)level);
CrestronConsole.ConsoleCommandResponse("[Application {0}] File log level set to {1}\r\n",
InitialParametersClass.ApplicationNumber, _fileLogLevelSwitch.MinimumLevel);
CrestronConsole.ConsoleCommandResponse($"Storing level {level}:{(int)level}");
var err = CrestronDataStoreStatic.SetLocalIntValue(FileLevelStoreKey, (int)level);
CrestronConsole.ConsoleCommandResponse($"Store result: {err}:{(int)level}");
if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
LogMessage(LogEventLevel.Information, "Error saving File debug level setting: {error}", err);
LogMessage(LogEventLevel.Information, "File debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel);
CrestronConsole.PrintLine($"Error saving file debug level setting: {err}");
}
/// <summary>

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
@@ -17,48 +13,68 @@ namespace PepperDash.Essentials.Devices.Common
/// </summary>
public class GenericAudioOut : EssentialsDevice, IRoutingSink
{
public RoutingInputPort CurrentInputPort => AnyAudioIn;
/// <summary>
/// Gets the current input port
/// </summary>
public RoutingInputPort CurrentInputPort => AnyAudioIn;
public event SourceInfoChangeHandler CurrentSourceChange;
/// <summary>
/// Event fired when the current source changes
/// </summary>
public event SourceInfoChangeHandler CurrentSourceChange;
public string CurrentSourceInfoKey { get; set; }
public SourceListItem CurrentSourceInfo
{
get
{
return _CurrentSourceInfo;
}
set
{
if (value == _CurrentSourceInfo) return;
/// <summary>
/// Gets or sets the current source info key
/// </summary>
public string CurrentSourceInfoKey { get; set; }
/// <summary>
/// Gets or sets the current source info
/// </summary>
public SourceListItem CurrentSourceInfo
{
get
{
return _CurrentSourceInfo;
}
set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSourceChange;
var handler = CurrentSourceChange;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.WillChange);
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.WillChange);
_CurrentSourceInfo = value;
_CurrentSourceInfo = value;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.DidChange);
}
}
SourceListItem _CurrentSourceInfo;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.DidChange);
}
}
SourceListItem _CurrentSourceInfo;
/// <summary>
/// Gets or sets the AnyAudioIn
/// </summary>
/// <summary>
/// Gets or sets the AnyAudioIn
/// </summary>
public RoutingInputPort AnyAudioIn { get; private set; }
/// <summary>
/// Constructor for GenericAudioOut
/// </summary>
/// <param name="key">Device key</param>
/// <param name="name">Device name</param>
public GenericAudioOut(string key, string name)
: base(key, name)
{
AnyAudioIn = new RoutingInputPort(RoutingPortNames.AnyAudioIn, eRoutingSignalType.Audio,
AnyAudioIn = new RoutingInputPort(RoutingPortNames.AnyAudioIn, eRoutingSignalType.Audio,
eRoutingPortConnectionType.LineAudio, null, this);
}
#region IRoutingInputs Members
/// <summary>
/// Gets the collection of input ports
/// </summary>
public RoutingPortCollection<RoutingInputPort> InputPorts
{
get { return new RoutingPortCollection<RoutingInputPort> { AnyAudioIn }; }
@@ -68,23 +84,32 @@ namespace PepperDash.Essentials.Devices.Common
}
/// <summary>
/// Represents a GenericAudioOutWithVolume
/// </summary>
/// <summary>
/// Represents a GenericAudioOutWithVolume
/// </summary>
public class GenericAudioOutWithVolume : GenericAudioOut, IHasVolumeDevice
{
/// <summary>
/// Gets the volume device key
/// </summary>
public string VolumeDeviceKey { get; private set; }
/// <summary>
/// Gets the volume zone
/// </summary>
public uint VolumeZone { get; private set; }
/// <summary>
/// Gets the volume device
/// </summary>
public IBasicVolumeControls VolumeDevice
{
{
get
{
var dev = DeviceManager.GetDeviceForKey(VolumeDeviceKey);
if (dev is IAudioZones)
return (dev as IAudioZones).Zone[VolumeZone];
else return dev as IBasicVolumeControls;
}
}
}
/// <summary>
@@ -103,24 +128,30 @@ namespace PepperDash.Essentials.Devices.Common
}
public class GenericAudioOutWithVolumeFactory : EssentialsDeviceFactory<GenericAudioOutWithVolume>
{
public GenericAudioOutWithVolumeFactory()
{
TypeNames = new List<string>() { "genericaudiooutwithvolume" };
}
/// <summary>
/// Factory for creating GenericAudioOutWithVolume devices
/// </summary>
public class GenericAudioOutWithVolumeFactory : EssentialsDeviceFactory<GenericAudioOutWithVolume>
{
/// <summary>
/// Constructor for GenericAudioOutWithVolumeFactory
/// </summary>
public GenericAudioOutWithVolumeFactory()
{
TypeNames = new List<string>() { "genericaudiooutwithvolume" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new GenericAudioOutWithVolumeFactory Device");
var zone = dc.Properties.Value<uint>("zone");
return new GenericAudioOutWithVolume(dc.Key, dc.Name,
dc.Properties.Value<string>("volumeDeviceKey"), zone);
}
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new GenericAudioOutWithVolumeFactory Device");
var zone = dc.Properties.Value<uint>("zone");
return new GenericAudioOutWithVolume(dc.Key, dc.Name,
dc.Properties.Value<string>("volumeDeviceKey"), zone);
}
}
}

View File

@@ -1,18 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.Codec;
namespace PepperDash.Essentials.Devices.Common.AudioCodec
{
/// <summary>
/// Abstract base class for audio codec devices
/// </summary>
public abstract class AudioCodecBase : EssentialsDevice, IHasDialer, IUsageTracking, IAudioCodecInfo
{
/// <summary>
/// Event fired when call status changes
/// </summary>
public event EventHandler<CodecCallStatusItemChangeEventArgs> CallStatusChange;
/// <summary>
@@ -52,6 +54,11 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
/// </summary>
public List<CodecActiveCallItem> ActiveCalls { get; set; }
/// <summary>
/// Constructor for AudioCodecBase
/// </summary>
/// <param name="key">Device key</param>
/// <param name="name">Device name</param>
public AudioCodecBase(string key, string name)
: base(key, name)
{
@@ -70,11 +77,9 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
}
/// <summary>
///
/// Handles call status change events
/// </summary>
/// <param name="previousStatus"></param>
/// <param name="newStatus"></param>
/// <param name="item"></param>
/// <param name="item">The call item that changed status</param>
protected void OnCallStatusChange(CodecActiveCallItem item)
{
var handler = CallStatusChange;
@@ -92,16 +97,22 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
#region IHasDialer Members
/// <inheritdoc />
public abstract void Dial(string number);
/// <inheritdoc />
public abstract void EndCall(CodecActiveCallItem activeCall);
/// <inheritdoc />
public abstract void EndAllCalls();
/// <inheritdoc />
public abstract void AcceptCall(CodecActiveCallItem item);
/// <inheritdoc />
public abstract void RejectCall(CodecActiveCallItem item);
/// <inheritdoc />
public abstract void SendDtmf(string digit);
#endregion

View File

@@ -1,16 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Common.AudioCodec
namespace PepperDash.Essentials.Devices.Common.AudioCodec
{
/// <summary>
/// Implements a common set of data about a codec
/// </summary>
public interface IAudioCodecInfo
{
/// <summary>
/// Gets the codec information
/// </summary>
AudioCodecInfo CodecInfo { get; }
}
@@ -19,6 +16,9 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
/// </summary>
public abstract class AudioCodecInfo
{
/// <summary>
/// Gets or sets the phone number
/// </summary>
public abstract string PhoneNumber { get; set; }
}
}

View File

@@ -1,23 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.AudioCodec
{
/// <summary>
/// For rooms that have audio codec
/// </summary>
public interface IHasAudioCodec:IHasInCallFeedback
public interface IHasAudioCodec : IHasInCallFeedback
{
/// <summary>
/// Gets the audio codec device
/// </summary>
AudioCodecBase AudioCodec { get; }
/// <summary>
/// Make this more specific
/// </summary>
//List<PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem> ActiveCalls { get; }
}
}

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
@@ -17,6 +13,12 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
/// </summary>
public class MockAC : AudioCodecBase
{
/// <summary>
/// Constructor for MockAC
/// </summary>
/// <param name="key">Device key</param>
/// <param name="name">Device name</param>
/// <param name="props">MockAC properties configuration</param>
public MockAC(string key, string name, MockAcPropertiesConfig props)
: base(key, name)
{
@@ -109,13 +111,10 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
Debug.LogMessage(LogEventLevel.Debug, this, "BEEP BOOP SendDTMF: {0}", s);
}
/// <summary>
///
/// </summary>
/// <param name="url"></param>
/// <summary>
/// TestIncomingAudioCall method
/// </summary>
/// <param name="number">Phone number to call from</param>
public void TestIncomingAudioCall(string number)
{
Debug.LogMessage(LogEventLevel.Debug, this, "TestIncomingAudioCall from {0}", number);
@@ -133,6 +132,7 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
{
string _phoneNumber;
/// <inheritdoc />
public override string PhoneNumber
{
get
@@ -151,6 +151,9 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
/// </summary>
public class MockACFactory : EssentialsDeviceFactory<MockAC>
{
/// <summary>
/// Constructor for MockACFactory
/// </summary>
public MockACFactory()
{
TypeNames = new List<string>() { "mockac" };

View File

@@ -1,12 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.AudioCodec
{
@@ -15,10 +7,10 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
/// </summary>
public class MockAcPropertiesConfig
{
[JsonProperty("phoneNumber")]
/// <summary>
/// Gets or sets the PhoneNumber
/// </summary>
[JsonProperty("phoneNumber")]
public string PhoneNumber { get; set; }
}
}

View File

@@ -3,20 +3,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using System.Reflection;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Devices;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Devices;
using PepperDash.Essentials.Core.Presets;
using PepperDash.Essentials.Devices.Common.Codec;
using Newtonsoft.Json;
using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.Cameras
@@ -26,31 +20,52 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// </summary>
public enum eCameraCapabilities
{
/// <summary>
/// No camera capabilities
/// </summary>
None = 0,
/// <summary>
/// Camera supports pan movement
/// </summary>
Pan = 1,
Tilt = 2,
/// <summary>
/// Camera supports tilt movement
/// </summary>
Tilt = 2,
/// <summary>
/// Camera supports zoom functionality
/// </summary>
Zoom = 4,
/// <summary>
/// Camera supports focus adjustment
/// </summary>
Focus = 8
}
/// <summary>
/// Abstract base class for camera devices that provides common camera functionality and capabilities
/// </summary>
public abstract class CameraBase : ReconfigurableDevice, IRoutingOutputs
{
[JsonProperty("controlMode", NullValueHandling = NullValueHandling.Ignore)]
{
/// <summary>
/// Gets or sets the ControlMode
/// </summary>
[JsonProperty("controlMode", NullValueHandling = NullValueHandling.Ignore)]
public eCameraControlMode ControlMode { get; protected set; }
#region IRoutingOutputs Members
[JsonIgnore]
/// <summary>
/// Gets or sets the OutputPorts
/// </summary>
[JsonIgnore]
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; protected set; }
#endregion
/// <summary>
/// Gets a value indicating whether this camera supports pan movement
/// </summary>
[JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)]
public bool CanPan
{
@@ -59,6 +74,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
return (Capabilities & eCameraCapabilities.Pan) == eCameraCapabilities.Pan;
}
}
/// <summary>
/// Gets a value indicating whether this camera supports tilt movement
/// </summary>
[JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)]
public bool CanTilt
{
@@ -67,6 +86,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
return (Capabilities & eCameraCapabilities.Tilt) == eCameraCapabilities.Tilt;
}
}
/// <summary>
/// Gets a value indicating whether this camera supports zoom functionality
/// </summary>
[JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)]
public bool CanZoom
{
@@ -75,6 +98,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
return (Capabilities & eCameraCapabilities.Zoom) == eCameraCapabilities.Zoom;
}
}
/// <summary>
/// Gets a value indicating whether this camera supports focus adjustment
/// </summary>
[JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)]
public bool CanFocus
{
@@ -84,23 +111,42 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
}
}
// A bitmasked value to indicate the movement capabilites of this camera
/// <summary>
/// Gets or sets a bitmasked value to indicate the movement capabilities of this camera
/// </summary>
protected eCameraCapabilities Capabilities { get; set; }
protected CameraBase(DeviceConfig config) : base(config)
{
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
ControlMode = eCameraControlMode.Manual;
}
protected CameraBase(string key, string name) :
this (new DeviceConfig{Name = name, Key = key})
/// <summary>
/// Initializes a new instance of the CameraBase class with the specified device configuration
/// </summary>
/// <param name="config">The device configuration</param>
protected CameraBase(DeviceConfig config) : base(config)
{
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
ControlMode = eCameraControlMode.Manual;
}
/// <summary>
/// Initializes a new instance of the CameraBase class with the specified key and name
/// </summary>
/// <param name="key">The unique key for this camera device</param>
/// <param name="name">The friendly name for this camera device</param>
protected CameraBase(string key, string name) :
this(new DeviceConfig { Name = name, Key = key })
{
}
/// <summary>
/// Links the camera device to the API bridge for control and feedback
/// </summary>
/// <param name="cameraDevice">The camera device to link</param>
/// <param name="trilist">The trilist for communication</param>
/// <param name="joinStart">The starting join number for the camera controls</param>
/// <param name="joinMapKey">The join map key for custom join mappings</param>
/// <param name="bridge">The EiscApiAdvanced bridge for advanced join mapping</param>
protected void LinkCameraToApi(CameraBase cameraDevice, BasicTriList trilist, uint joinStart, string joinMapKey,
EiscApiAdvanced bridge)
{
@@ -240,13 +286,13 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
{
int tempNum = i;
trilist.SetSigTrueAction((ushort) (joinMap.PresetRecallStart.JoinNumber + tempNum), () =>
trilist.SetSigTrueAction((ushort)(joinMap.PresetRecallStart.JoinNumber + tempNum), () =>
{
presetsCamera.PresetSelect(tempNum);
});
trilist.SetSigTrueAction((ushort) (joinMap.PresetSaveStart.JoinNumber + tempNum), () =>
trilist.SetSigTrueAction((ushort)(joinMap.PresetSaveStart.JoinNumber + tempNum), () =>
{
var label = trilist.GetString((ushort) (joinMap.PresetLabelStart.JoinNumber + tempNum));
var label = trilist.GetString((ushort)(joinMap.PresetLabelStart.JoinNumber + tempNum));
presetsCamera.PresetStore(tempNum, label);
});
@@ -277,7 +323,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
trilist.SetString((ushort)(joinMap.PresetLabelStart.JoinNumber + tempNum), label);
}
}
}
}
/// <summary>
@@ -285,6 +331,13 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// </summary>
public class CameraPreset : PresetBase
{
/// <summary>
/// Initializes a new instance of the CameraPreset class
/// </summary>
/// <param name="id">The preset ID</param>
/// <param name="description">The preset description</param>
/// <param name="isDefined">Whether the preset is defined</param>
/// <param name="isDefinable">Whether the preset can be defined</param>
public CameraPreset(int id, string description, bool isDefined, bool isDefinable)
: base(id, description, isDefined, isDefinable)
{
@@ -293,37 +346,37 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
}
/// <summary>
/// Represents a CameraPropertiesConfig
/// </summary>
public class CameraPropertiesConfig
{
/// <summary>
/// Gets or sets the CommunicationMonitorProperties
/// </summary>
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
/// <summary>
/// Represents a CameraPropertiesConfig
/// </summary>
public class CameraPropertiesConfig
{
/// <summary>
/// Gets or sets the CommunicationMonitorProperties
/// </summary>
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
/// <summary>
/// Gets or sets the Control
/// </summary>
public ControlPropertiesConfig Control { get; set; }
/// <summary>
/// Gets or sets the Control
/// </summary>
public ControlPropertiesConfig Control { get; set; }
[JsonProperty("supportsAutoMode")]
/// <summary>
/// Gets or sets the SupportsAutoMode
/// </summary>
[JsonProperty("supportsAutoMode")]
public bool SupportsAutoMode { get; set; }
[JsonProperty("supportsOffMode")]
/// <summary>
/// Gets or sets the SupportsOffMode
/// </summary>
[JsonProperty("supportsOffMode")]
public bool SupportsOffMode { get; set; }
[JsonProperty("presets")]
/// <summary>
/// Gets or sets the Presets
/// </summary>
[JsonProperty("presets")]
public List<CameraPreset> Presets { get; set; }
}
}
}

View File

@@ -3,38 +3,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Devices.Common.Codec;
using System.Text.RegularExpressions;
using System.Reflection;
using Newtonsoft.Json;
using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.Cameras
{
/// <summary>
/// Represents a CameraVisca
/// </summary>
public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IHasPowerControlWithFeedback, IBridgeAdvanced, IHasCameraFocusControl, IHasAutoFocusMode
{
/// <summary>
/// Represents a CameraVisca
/// </summary>
public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IHasPowerControlWithFeedback, IBridgeAdvanced, IHasCameraFocusControl, IHasAutoFocusMode
{
private readonly CameraViscaPropertiesConfig PropertiesConfig;
/// <summary>
/// Gets or sets the Communication
/// </summary>
public IBasicCommunication Communication { get; private set; }
/// <summary>
/// Gets or sets the Communication
/// </summary>
public IBasicCommunication Communication { get; private set; }
/// <summary>
/// Gets or sets the CommunicationMonitor
/// </summary>
public StatusMonitorBase CommunicationMonitor { get; private set; }
/// <summary>
/// Gets or sets the CommunicationMonitor
/// </summary>
public StatusMonitorBase CommunicationMonitor { get; private set; }
/// <summary>
/// Used to store the actions to parse inquiry responses as the inquiries are sent
@@ -45,20 +40,41 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// Camera ID (Default 1)
/// </summary>
public byte ID = 0x01;
/// <summary>
/// Response ID used for VISCA communication
/// </summary>
public byte ResponseID;
/// <summary>
/// Slow speed value for pan movement
/// </summary>
public byte PanSpeedSlow = 0x10;
public byte PanSpeedSlow = 0x10;
public byte TiltSpeedSlow = 0x10;
/// <summary>
/// Slow speed value for tilt movement
/// </summary>
public byte TiltSpeedSlow = 0x10;
/// <summary>
/// Fast speed value for pan movement
/// </summary>
public byte PanSpeedFast = 0x13;
/// <summary>
/// Fast speed value for tilt movement
/// </summary>
public byte TiltSpeedFast = 0x13;
// private bool IsMoving;
private bool IsZooming;
private bool IsZooming;
bool _powerIsOn;
public bool PowerIsOn
/// <summary>
/// Gets or sets a value indicating whether the camera power is on
/// </summary>
public bool PowerIsOn
{
get
{
@@ -87,12 +103,23 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
long FastSpeedHoldTimeMs = 2000;
byte[] IncomingBuffer = new byte[] { };
public BoolFeedback PowerIsOnFeedback { get; private set; }
byte[] IncomingBuffer = new byte[] { };
/// <summary>
/// Feedback indicating whether the camera power is on
/// </summary>
public BoolFeedback PowerIsOnFeedback { get; private set; }
/// <summary>
/// Initializes a new instance of the CameraVisca class
/// </summary>
/// <param name="key">The unique key for this camera device</param>
/// <param name="name">The friendly name for this camera device</param>
/// <param name="comm">The communication interface for VISCA protocol</param>
/// <param name="props">The camera properties configuration</param>
public CameraVisca(string key, string name, IBasicCommunication comm, CameraViscaPropertiesConfig props) :
base(key, name)
{
base(key, name)
{
InquiryResponseQueue = new CrestronQueue<Action<byte[]>>(15);
Presets = props.Presets;
@@ -107,8 +134,8 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
OutputPorts.Add(new RoutingOutputPort("videoOut", eRoutingSignalType.Video, eRoutingPortConnectionType.None, null, this, true));
// Default to all capabilties
Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom | eCameraCapabilities.Focus;
Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom | eCameraCapabilities.Focus;
Communication = comm;
if (comm is ISocketStatus socket)
{
@@ -121,19 +148,19 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
}
Communication.BytesReceived += new EventHandler<GenericCommMethodReceiveBytesArgs>(Communication_BytesReceived);
PowerIsOnFeedback = new BoolFeedback(() => { return PowerIsOn; });
CameraIsOffFeedback = new BoolFeedback(() => { return !PowerIsOn; });
PowerIsOnFeedback = new BoolFeedback("powerIsOn", () => { return PowerIsOn; });
CameraIsOffFeedback = new BoolFeedback("cameraIsOff", () => { return !PowerIsOn; });
if (props.CommunicationMonitorProperties != null)
{
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties);
}
else
{
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 20000, 120000, 300000, "\x81\x09\x04\x00\xFF");
}
DeviceManager.AddDevice(CommunicationMonitor);
}
if (props.CommunicationMonitorProperties != null)
{
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties);
}
else
{
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 20000, 120000, 300000, "\x81\x09\x04\x00\xFF");
}
DeviceManager.AddDevice(CommunicationMonitor);
}
/// <summary>
@@ -165,57 +192,57 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
}
}
/// <summary>
/// CustomActivate method
/// </summary>
/// <inheritdoc />
public override bool CustomActivate()
{
Communication.Connect();
CommunicationMonitor.StatusChange += (o, a) => { Debug.LogMessage(LogEventLevel.Verbose, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
CommunicationMonitor.Start();
/// <summary>
/// CustomActivate method
/// </summary>
/// <inheritdoc />
public override bool CustomActivate()
{
Communication.Connect();
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
return true;
}
CommunicationMonitor.StatusChange += (o, a) => { Debug.LogMessage(LogEventLevel.Verbose, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
CommunicationMonitor.Start();
/// <summary>
/// LinkToApi method
/// </summary>
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
LinkCameraToApi(this, trilist, joinStart, joinMapKey, bridge);
}
void Socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
{
Debug.LogMessage(LogEventLevel.Verbose, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
return true;
}
if (e.Client.IsConnected)
{
}
else
{
/// <summary>
/// LinkToApi method
/// </summary>
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
LinkCameraToApi(this, trilist, joinStart, joinMapKey, bridge);
}
}
}
void Socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
{
Debug.LogMessage(LogEventLevel.Verbose, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
void SendBytes(byte[] b)
{
if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
Debug.LogMessage(LogEventLevel.Verbose, this, "Sending:{0}", ComTextHelper.GetEscapedText(b));
if (e.Client.IsConnected)
{
Communication.SendBytes(b);
}
}
else
{
void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e)
{
}
}
void SendBytes(byte[] b)
{
if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
Debug.LogMessage(LogEventLevel.Verbose, this, "Sending:{0}", ComTextHelper.GetEscapedText(b));
Communication.SendBytes(b);
}
void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e)
{
var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length];
try
@@ -355,10 +382,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// <summary>
/// Sends a pan/tilt command. If the command is not for fastSpeed then it starts a timer to initiate fast speed.
/// </summary>
/// <param name="cmd"></param>
/// <param name="fastSpeed"></param>
private void SendPanTiltCommand (byte[] cmd, bool fastSpeedEnabled)
{
/// <param name="cmd">The VISCA command to send</param>
/// <param name="fastSpeedEnabled">Whether fast speed is enabled for this command</param>
private void SendPanTiltCommand(byte[] cmd, bool fastSpeedEnabled)
{
SendBytes(GetPanTiltCommand(cmd, fastSpeedEnabled));
if (!fastSpeedEnabled)
@@ -372,7 +399,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
SpeedTimer = new CTimer((o) => SendPanTiltCommand(GetPanTiltCommand(cmd, true), true), FastSpeedHoldTimeMs);
}
}
}
private void StopSpeedTimer()
{
@@ -381,7 +408,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
SpeedTimer.Stop();
SpeedTimer.Dispose();
SpeedTimer = null;
}
}
}
/// <summary>
@@ -424,14 +451,14 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
InquiryResponseQueue.Enqueue(HandlePowerResponse);
}
/// <summary>
/// PowerOn method
/// </summary>
public void PowerOn()
{
SendBytes(new byte[] { ID, 0x01, 0x04, 0x00, 0x02, 0xFF });
/// <summary>
/// PowerOn method
/// </summary>
public void PowerOn()
{
SendBytes(new byte[] { ID, 0x01, 0x04, 0x00, 0x02, 0xFF });
SendPowerQuery();
}
}
void HandlePowerResponse(byte[] response)
{
@@ -450,12 +477,12 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
}
}
/// <summary>
/// PowerOff method
/// </summary>
public void PowerOff()
{
SendBytes(new byte[] {ID, 0x01, 0x04, 0x00, 0x03, 0xFF});
/// <summary>
/// PowerOff method
/// </summary>
public void PowerOff()
{
SendBytes(new byte[] { ID, 0x01, 0x04, 0x00, 0x03, 0xFF });
SendPowerQuery();
}
@@ -470,22 +497,22 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
PowerOn();
}
/// <summary>
/// PanLeft method
/// </summary>
public void PanLeft()
{
SendPanTiltCommand(new byte[] {0x01, 0x03}, false);
// IsMoving = true;
}
/// <summary>
/// PanRight method
/// </summary>
public void PanRight()
{
/// <summary>
/// PanLeft method
/// </summary>
public void PanLeft()
{
SendPanTiltCommand(new byte[] { 0x01, 0x03 }, false);
// IsMoving = true;
}
/// <summary>
/// PanRight method
/// </summary>
public void PanRight()
{
SendPanTiltCommand(new byte[] { 0x02, 0x03 }, false);
// IsMoving = true;
}
// IsMoving = true;
}
/// <summary>
/// PanStop method
/// </summary>
@@ -493,22 +520,22 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
{
Stop();
}
/// <summary>
/// TiltDown method
/// </summary>
public void TiltDown()
{
/// <summary>
/// TiltDown method
/// </summary>
public void TiltDown()
{
SendPanTiltCommand(new byte[] { 0x03, 0x02 }, false);
// IsMoving = true;
}
/// <summary>
/// TiltUp method
/// </summary>
public void TiltUp()
{
// IsMoving = true;
}
/// <summary>
/// TiltUp method
/// </summary>
public void TiltUp()
{
SendPanTiltCommand(new byte[] { 0x03, 0x01 }, false);
// IsMoving = true;
}
// IsMoving = true;
}
/// <summary>
/// TiltStop method
/// </summary>
@@ -517,28 +544,28 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
Stop();
}
private void SendZoomCommand (byte cmd)
{
SendBytes(new byte[] {ID, 0x01, 0x04, 0x07, cmd, 0xFF} );
}
private void SendZoomCommand(byte cmd)
{
SendBytes(new byte[] { ID, 0x01, 0x04, 0x07, cmd, 0xFF });
}
/// <summary>
/// ZoomIn method
/// </summary>
public void ZoomIn()
{
/// <summary>
/// ZoomIn method
/// </summary>
public void ZoomIn()
{
SendZoomCommand(ZoomInCmd);
IsZooming = true;
}
/// <summary>
/// ZoomOut method
/// </summary>
public void ZoomOut()
{
IsZooming = true;
}
/// <summary>
/// ZoomOut method
/// </summary>
public void ZoomOut()
{
SendZoomCommand(ZoomOutCmd);
IsZooming = true;
}
IsZooming = true;
}
/// <summary>
/// ZoomStop method
/// </summary>
@@ -547,23 +574,23 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
Stop();
}
/// <summary>
/// Stop method
/// </summary>
public void Stop()
{
if (IsZooming)
{
/// <summary>
/// Stop method
/// </summary>
public void Stop()
{
if (IsZooming)
{
SendZoomCommand(ZoomStopCmd);
IsZooming = false;
}
else
{
IsZooming = false;
}
else
{
StopSpeedTimer();
SendPanTiltCommand(new byte[] { 0x03, 0x03 }, false);
// IsMoving = false;
}
}
// IsMoving = false;
}
}
/// <summary>
/// PositionHome method
/// </summary>
@@ -572,33 +599,39 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
SendBytes(new byte[] { ID, 0x01, 0x06, 0x02, PanSpeedFast, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF });
SendBytes(new byte[] { ID, 0x01, 0x04, 0x47, 0x00, 0x00, 0x00, 0x00, 0xFF });
}
/// <summary>
/// RecallPreset method
/// </summary>
public void RecallPreset(int presetNumber)
{
SendBytes(new byte[] {ID, 0x01, 0x04, 0x3F, 0x02, (byte)presetNumber, 0xFF} );
}
/// <summary>
/// SavePreset method
/// </summary>
public void SavePreset(int presetNumber)
{
SendBytes(new byte[] { ID, 0x01, 0x04, 0x3F, 0x01, (byte)presetNumber, 0xFF });
}
/// <summary>
/// RecallPreset method
/// </summary>
public void RecallPreset(int presetNumber)
{
SendBytes(new byte[] { ID, 0x01, 0x04, 0x3F, 0x02, (byte)presetNumber, 0xFF });
}
/// <summary>
/// SavePreset method
/// </summary>
public void SavePreset(int presetNumber)
{
SendBytes(new byte[] { ID, 0x01, 0x04, 0x3F, 0x01, (byte)presetNumber, 0xFF });
}
#region IHasCameraPresets Members
/// <summary>
/// Event that is raised when the presets list has changed
/// </summary>
public event EventHandler<EventArgs> PresetsListHasChanged;
protected void OnPresetsListHasChanged()
{
var handler = PresetsListHasChanged;
if (handler == null)
return;
/// <summary>
/// Raises the PresetsListHasChanged event
/// </summary>
protected void OnPresetsListHasChanged()
{
var handler = PresetsListHasChanged;
if (handler == null)
return;
handler.Invoke(this, EventArgs.Empty);
}
handler.Invoke(this, EventArgs.Empty);
}
/// <summary>
/// Gets or sets the Presets
@@ -741,6 +774,9 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// </summary>
public class CameraViscaFactory : EssentialsDeviceFactory<CameraVisca>
{
/// <summary>
/// Initializes a new instance of the CameraViscaFactory class
/// </summary>
public CameraViscaFactory()
{
TypeNames = new List<string>() { "cameravisca" };
@@ -768,11 +804,9 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
{
/// <summary>
/// Control ID of the camera (1-7)
/// </summary>
[JsonProperty("id")]
/// <summary>
/// Gets or sets the Id
/// </summary>
[JsonProperty("id")]
public uint Id { get; set; }
/// <summary>
@@ -790,7 +824,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// <summary>
/// Slow tilt speed (0-18)
/// </summary>
[JsonProperty("tiltSpeedSlow")]
[JsonProperty("tiltSpeedSlow")]
public uint TiltSpeedSlow { get; set; }
/// <summary>

View File

@@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Common.Cameras
{
@@ -11,12 +8,27 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// </summary>
public interface IHasCameraPresets
{
/// <summary>
/// Event that is raised when the presets list has changed
/// </summary>
event EventHandler<EventArgs> PresetsListHasChanged;
/// <summary>
/// Gets the list of camera presets
/// </summary>
List<CameraPreset> Presets { get; }
/// <summary>
/// Selects the specified preset
/// </summary>
/// <param name="preset">The preset number to select</param>
void PresetSelect(int preset);
/// <summary>
/// Stores a preset at the specified location with the given description
/// </summary>
/// <param name="preset">The preset number to store</param>
/// <param name="description">The description for the preset</param>
void PresetStore(int preset, string description);
}
}

View File

@@ -0,0 +1,26 @@
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Represents a Call
/// </summary>
public class Call
{
/// <summary>
/// Gets or sets the Number
/// </summary>
public string Number { get; set; }
/// <summary>
/// Gets or sets the Protocol
/// </summary>
public string Protocol { get; set; }
/// <summary>
/// Gets or sets the CallRate
/// </summary>
public string CallRate { get; set; }
/// <summary>
/// Gets or sets the CallType
/// </summary>
public string CallType { get; set; }
}
}

View File

@@ -1,10 +1,5 @@
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
{

View File

@@ -1,10 +1,5 @@
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
{

View File

@@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
@@ -17,55 +13,55 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary>
public class CodecActiveCallItem
{
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
/// <summary>
/// Gets or sets the Name
/// </summary>
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }
[JsonProperty("number", NullValueHandling = NullValueHandling.Ignore)]
/// <summary>
/// Gets or sets the Number
/// </summary>
[JsonProperty("number", NullValueHandling = NullValueHandling.Ignore)]
public string Number { get; set; }
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))]
/// <summary>
/// Gets or sets the Type
/// </summary>
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))]
public eCodecCallType Type { get; set; }
[JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))]
/// <summary>
/// Gets or sets the Status
/// </summary>
[JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))]
public eCodecCallStatus Status { get; set; }
[JsonProperty("direction", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))]
/// <summary>
/// Gets or sets the Direction
/// </summary>
[JsonProperty("direction", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))]
public eCodecCallDirection Direction { get; set; }
[JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
/// <summary>
/// Gets or sets the Id
/// </summary>
[JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
public string Id { get; set; }
[JsonProperty("isOnHold", NullValueHandling = NullValueHandling.Ignore)]
/// <summary>
/// Gets or sets the IsOnHold
/// </summary>
[JsonProperty("isOnHold", NullValueHandling = NullValueHandling.Ignore)]
public bool IsOnHold { get; set; }
[JsonProperty("duration", NullValueHandling = NullValueHandling.Ignore)]
/// <summary>
/// Gets or sets the Duration
/// </summary>
[JsonProperty("duration", NullValueHandling = NullValueHandling.Ignore)]
public TimeSpan Duration { get; set; }
//public object CallMetaData { get; set; }
@@ -81,7 +77,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec
{
return !(Status == eCodecCallStatus.Disconnected
|| Status == eCodecCallStatus.Disconnecting
|| Status == eCodecCallStatus.Idle
|| Status == eCodecCallStatus.Idle
|| Status == eCodecCallStatus.Unknown);
}
}
@@ -97,6 +93,10 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary>
public CodecActiveCallItem CallItem { get; private set; }
/// <summary>
/// Initializes a new instance of the CodecCallStatusItemChangeEventArgs class
/// </summary>
/// <param name="item">The call item that changed</param>
public CodecCallStatusItemChangeEventArgs(CodecActiveCallItem item)
{
CallItem = item;

View File

@@ -0,0 +1,121 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Represents a codec directory
/// </summary>
public class CodecDirectory
{
/// <summary>
/// Represents the contents of the directory
/// We don't want to serialize this for messages to MobileControl. MC can combine Contacts and Folders to get the same data
/// </summary>
[JsonIgnore]
public List<DirectoryItem> CurrentDirectoryResults { get; private set; }
/// <summary>
/// Gets the Contacts in the CurrentDirectoryResults
/// </summary>
[JsonProperty("contacts")]
public List<DirectoryItem> Contacts
{
get
{
return CurrentDirectoryResults.OfType<DirectoryContact>().Cast<DirectoryItem>().ToList();
}
}
/// <summary>
/// Gets the Folders in the CurrentDirectoryResults
/// </summary>
[JsonProperty("folders")]
public List<DirectoryItem> Folders
{
get
{
return CurrentDirectoryResults.OfType<DirectoryFolder>().Cast<DirectoryItem>().ToList();
}
}
/// <summary>
/// Used to store the ID of the current folder for CurrentDirectoryResults
/// Gets or sets the ResultsFolderId
/// </summary>
[JsonProperty("resultsFolderId")]
public string ResultsFolderId { get; set; }
/// <summary>
/// Constructor for <see cref="CodecDirectory"/>
/// </summary>
public CodecDirectory()
{
CurrentDirectoryResults = new List<DirectoryItem>();
}
/// <summary>
/// Adds folders to the directory
/// </summary>
/// <param name="folders"></param>
public void AddFoldersToDirectory(List<DirectoryItem> folders)
{
if (folders != null)
CurrentDirectoryResults.AddRange(folders);
SortDirectory();
}
/// <summary>
/// Adds contacts to the directory
/// </summary>
/// <param name="contacts"></param>
public void AddContactsToDirectory(List<DirectoryItem> contacts)
{
if (contacts != null)
CurrentDirectoryResults.AddRange(contacts);
SortDirectory();
}
/// <summary>
/// Filters the CurrentDirectoryResults by the predicate
/// </summary>
/// <param name="predicate"></param>
public void FilterContacts(Func<DirectoryItem, bool> predicate)
{
CurrentDirectoryResults = CurrentDirectoryResults.Where(predicate).ToList();
}
/// <summary>
/// Sorts the DirectoryResults list to display all folders alphabetically, then all contacts alphabetically
/// </summary>
private void SortDirectory()
{
var sortedFolders = new List<DirectoryItem>();
sortedFolders.AddRange(CurrentDirectoryResults.Where(f => f is DirectoryFolder));
sortedFolders.OrderBy(f => f.Name);
var sortedContacts = new List<DirectoryItem>();
sortedContacts.AddRange(CurrentDirectoryResults.Where(c => c is DirectoryContact));
sortedFolders.OrderBy(c => c.Name);
CurrentDirectoryResults.Clear();
CurrentDirectoryResults.AddRange(sortedFolders);
CurrentDirectoryResults.AddRange(sortedContacts);
}
}
}

View File

@@ -0,0 +1,146 @@
using System;
using System.Collections.Generic;
using Crestron.SimplSharp;
using PepperDash.Core;
using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Represents a CodecScheduleAwareness
/// </summary>
public class CodecScheduleAwareness
{
List<Meeting> _meetings;
/// <summary>
/// Event that is raised when a meeting event changes
/// </summary>
public event EventHandler<MeetingEventArgs> MeetingEventChange;
/// <summary>
/// Event that is raised when the meetings list has changed
/// </summary>
public event EventHandler<EventArgs> MeetingsListHasChanged;
private int _meetingWarningMinutes = 5;
//private Meeting _previousChangedMeeting;
//private eMeetingEventChangeType _previousChangeType = eMeetingEventChangeType.Unknown;
/// <summary>
/// Gets or sets the number of minutes before a meeting to issue a warning
/// </summary>
public int MeetingWarningMinutes
{
get { return _meetingWarningMinutes; }
set { _meetingWarningMinutes = value; }
}
/// <summary>
/// Setter triggers MeetingsListHasChanged event
/// </summary>
public List<Meeting> Meetings
{
get
{
return _meetings;
}
set
{
_meetings = value;
MeetingsListHasChanged?.Invoke(this, new EventArgs());
}
}
private readonly CTimer _scheduleChecker;
/// <summary>
/// Initializes a new instance of the CodecScheduleAwareness class with default poll time
/// </summary>
public CodecScheduleAwareness()
{
Meetings = new List<Meeting>();
_scheduleChecker = new CTimer(CheckSchedule, null, 1000, 1000);
}
/// <summary>
/// Initializes a new instance of the CodecScheduleAwareness class with specified poll time
/// </summary>
/// <param name="pollTime">The poll time in milliseconds for checking schedule changes</param>
public CodecScheduleAwareness(long pollTime)
{
Meetings = new List<Meeting>();
_scheduleChecker = new CTimer(CheckSchedule, null, pollTime, pollTime);
}
/// <summary>
/// Helper method to fire MeetingEventChange. Should only fire once for each changeType on each meeting
/// </summary>
/// <param name="changeType"></param>
/// <param name="meeting"></param>
private void OnMeetingChange(eMeetingEventChangeType changeType, Meeting meeting)
{
Debug.LogMessage(LogEventLevel.Verbose, "*****************OnMeetingChange. id: {0} changeType: {1}**********************", meeting.Id, changeType);
if (changeType != (changeType & meeting.NotifiedChangeTypes))
{
// Add this change type to the NotifiedChangeTypes
meeting.NotifiedChangeTypes |= changeType;
MeetingEventChange?.Invoke(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting });
}
else
{
Debug.LogMessage(LogEventLevel.Verbose, "Meeting: {0} already notified of changeType: {1}", meeting.Id, changeType);
}
}
/// <summary>
/// Checks the schedule to see if any MeetingEventChange updates should be fired
/// </summary>
/// <param name="o"></param>
private void CheckSchedule(object o)
{
// Iterate the meeting list and check if any meeting need to do anything
const double meetingTimeEpsilon = 0.05;
foreach (var m in Meetings)
{
var changeType = eMeetingEventChangeType.Unknown;
if (eMeetingEventChangeType.MeetingStartWarning != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStartWarning) && m.TimeToMeetingStart.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingStart.Seconds > 0) // Meeting is about to start
{
Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingStartWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingStart.TotalMinutes, m.TimeToMeetingStart.Seconds);
changeType = eMeetingEventChangeType.MeetingStartWarning;
}
else if (eMeetingEventChangeType.MeetingStart != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStart) && Math.Abs(m.TimeToMeetingStart.TotalMinutes) < meetingTimeEpsilon) // Meeting Start
{
Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingStart");
changeType = eMeetingEventChangeType.MeetingStart;
}
else if (eMeetingEventChangeType.MeetingEndWarning != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingEndWarning) && m.TimeToMeetingEnd.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingEnd.Seconds > 0) // Meeting is about to end
{
Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingEndWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingEnd.TotalMinutes, m.TimeToMeetingEnd.Seconds);
changeType = eMeetingEventChangeType.MeetingEndWarning;
}
else if (eMeetingEventChangeType.MeetingEnd != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingEnd) && Math.Abs(m.TimeToMeetingEnd.TotalMinutes) < meetingTimeEpsilon) // Meeting has ended
{
Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingEnd");
changeType = eMeetingEventChangeType.MeetingEnd;
}
if (changeType != eMeetingEventChangeType.Unknown)
{
OnMeetingChange(changeType, m);
}
}
}
}
}

View File

@@ -0,0 +1,37 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Represents a ContactMethod
/// </summary>
public class ContactMethod
{
/// <summary>
/// Gets or sets the ContactMethodId
/// </summary>
[JsonProperty("contactMethodId")]
public string ContactMethodId { get; set; }
/// <summary>
/// Gets or sets the Number
/// </summary>
[JsonProperty("number")]
public string Number { get; set; }
/// <summary>
/// Gets or sets the Device
/// </summary>
[JsonProperty("device")]
[JsonConverter(typeof(StringEnumConverter))]
public eContactMethodDevice Device { get; set; }
/// <summary>
/// Gets or sets the CallType
/// </summary>
[JsonProperty("callType")]
[JsonConverter(typeof(StringEnumConverter))]
public eContactMethodCallType CallType { get; set; }
}
}

View File

@@ -0,0 +1,39 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Represents a DirectoryContact
/// </summary>
public class DirectoryContact : DirectoryItem
{
/// <summary>
/// Gets or sets the ContactId
/// </summary>
[JsonProperty("contactId")]
public string ContactId { get; set; }
/// <summary>
/// Gets or sets the Title
/// </summary>
[JsonProperty("title")]
public string Title { get; set; }
/// <summary>
/// Gets or sets the ContactMethods
/// </summary>
[JsonProperty("contactMethods")]
public List<ContactMethod> ContactMethods { get; set; }
/// <summary>
/// Constructor for <see cref="DirectoryContact"/>
/// </summary>
public DirectoryContact()
{
ContactMethods = new List<ContactMethod>();
}
}
}

View File

@@ -0,0 +1,21 @@
using System;
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Represents a DirectoryEventArgs
/// </summary>
public class DirectoryEventArgs : EventArgs
{
/// <summary>
/// Gets or sets the Directory
/// </summary>
public CodecDirectory Directory { get; set; }
/// <summary>
/// Gets or sets the DirectoryIsOnRoot
/// </summary>
public bool DirectoryIsOnRoot { get; set; }
}
}

View File

@@ -0,0 +1,27 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Represents a DirectoryFolder
/// </summary>
public class DirectoryFolder : DirectoryItem
{
/// <summary>
/// Gets or sets the Contacts
/// </summary>
[JsonProperty("contacts")]
public List<DirectoryContact> Contacts { get; set; }
/// <summary>
/// Constructor for <see cref="DirectoryFolder"/>
/// </summary>
public DirectoryFolder()
{
Contacts = new List<DirectoryContact>();
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Represents a DirectoryItem
/// </summary>
public class DirectoryItem : ICloneable
{
/// <summary>
/// Clone method
/// </summary>
public object Clone()
{
return MemberwiseClone();
}
/// <summary>
/// Gets or sets the FolderId
/// </summary>
[JsonProperty("folderId")]
public string FolderId { get; set; }
/// <summary>
/// Gets or sets the Name
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// Gets or sets the ParentFolderId
/// </summary>
[JsonProperty("parentFolderId")]
public string ParentFolderId { get; set; }
}
}

View File

@@ -1,31 +1,65 @@
using Crestron.SimplSharpPro;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PepperDash.Essentials.Devices.Common.Codec
{
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Describes a cisco codec device that can allow configuration of cameras
/// </summary>
public interface ICiscoCodecCameraConfig
{
/// <summary>
/// Sets the assigned serial number for the specified camera
/// </summary>
/// <param name="cameraId">The camera identifier</param>
/// <param name="serialNumber">The serial number to assign</param>
void SetCameraAssignedSerialNumber(uint cameraId, string serialNumber);
/// <summary>
/// Sets the name for the camera on the specified video connector
/// </summary>
/// <param name="videoConnectorId">The video connector identifier</param>
/// <param name="name">The name to assign</param>
void SetCameraName(uint videoConnectorId, string name);
/// <summary>
/// Sets the input source type for the specified video connector
/// </summary>
/// <param name="videoConnectorId">The video connector identifier</param>
/// <param name="sourceType">The source type to set</param>
void SetInputSourceType(uint videoConnectorId, eCiscoCodecInputSourceType sourceType);
}
/// <summary>
/// Enumeration of Cisco codec input source types
/// </summary>
public enum eCiscoCodecInputSourceType
{
/// <summary>
/// PC source type
/// </summary>
PC,
/// <summary>
/// Camera source type
/// </summary>
camera,
/// <summary>
/// Document camera source type
/// </summary>
document_camera,
/// <summary>
/// Media player source type
/// </summary>
mediaplayer,
/// <summary>
/// Other source type
/// </summary>
other,
/// <summary>
/// Whiteboard source type
/// </summary>
whiteboard
}
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Common.Codec
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Defines the contract for IHasCallHold

View File

@@ -0,0 +1,14 @@
using System.Collections.Generic;
using PepperDash.Essentials.Devices.Common.Codec;
/// <summary>
/// Defines the contract for IHasDirectoryHistoryStack
/// </summary>
public interface IHasDirectoryHistoryStack : IHasDirectory
{
/// <summary>
/// Gets the DirectoryBrowseHistoryStack
/// </summary>
Stack<CodecDirectory> DirectoryBrowseHistoryStack { get; }
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.Codec
{
@@ -34,6 +28,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec
void ToggleDoNotDisturbMode();
}
/// <summary>
/// Defines the contract for devices that support Do Not Disturb mode with timeout functionality
/// </summary>
public interface IHasDoNotDisturbModeWithTimeout : IHasDoNotDisturbMode
{
/// <summary>

View File

@@ -1,25 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco;
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Defines the contract for IHasExternalSourceSwitching
/// </summary>
/// <summary>
/// Defines the contract for IHasExternalSourceSwitching
/// </summary>
public interface IHasExternalSourceSwitching
{
/// <summary>
/// Gets a value indicating whether the external source list is enabled
/// </summary>
bool ExternalSourceListEnabled { get; }
string ExternalSourceInputPort { get; }
/// <summary>
/// Gets the external source input port identifier
/// </summary>
string ExternalSourceInputPort { get; }
/// <summary>
/// Adds an external source to the available sources
/// </summary>
/// <param name="connectorId">The connector identifier</param>
/// <param name="key">The unique key for the source</param>
/// <param name="name">The display name for the source</param>
/// <param name="type">The type of external source</param>
void AddExternalSource(string connectorId, string key, string name, eExternalSourceType type);
/// <summary>
/// Sets the state of the specified external source
/// </summary>
/// <param name="key">The unique key of the external source</param>
/// <param name="mode">The mode to set for the source</param>
void SetExternalSourceState(string key, eExternalSourceMode mode);
/// <summary>
/// Clears all external sources from the list
/// </summary>
void ClearExternalSources();
void SetSelectedSource(string key);
Action<string, string> RunRouteAction { set;}
/// <summary>
/// Sets the selected source by its key
/// </summary>
/// <param name="key">The unique key of the source to select</param>
void SetSelectedSource(string key);
/// <summary>
/// Sets the action to run when routing between sources
/// </summary>
Action<string, string> RunRouteAction { set; }
}
}

View File

@@ -0,0 +1,13 @@
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Defines the contract for IInvitableContact
/// </summary>
public interface IInvitableContact
{
/// <summary>
/// Gets a value indicating whether this contact is invitable
/// </summary>
bool IsInvitableContact { get; }
}
}

View File

@@ -0,0 +1,22 @@
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Represents an InvitableDirectoryContact
/// </summary>
public class InvitableDirectoryContact : DirectoryContact, IInvitableContact
{
/// <summary>
/// Gets a value indicating whether this contact is invitable
/// </summary>
[JsonProperty("isInvitableContact")]
public bool IsInvitableContact
{
get
{
return this is IInvitableContact;
}
}
}
}

View File

@@ -0,0 +1,182 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Represents a Meeting
/// </summary>
public class Meeting
{
/// <summary>
/// Minutes before the meeting to show warning
/// </summary>
[JsonProperty("minutesBeforeMeeting")]
public int MinutesBeforeMeeting;
/// <summary>
/// Gets or sets the meeting ID
/// </summary>
[JsonProperty("id")]
public string Id { get; set; }
/// <summary>
/// Gets or sets the meeting organizer
/// </summary>
[JsonProperty("organizer")]
public string Organizer { get; set; }
/// <summary>
/// Gets or sets the Title
/// </summary>
[JsonProperty("title")]
public string Title { get; set; }
/// <summary>
/// Gets or sets the Agenda
/// </summary>
[JsonProperty("agenda")]
public string Agenda { get; set; }
/// <summary>
/// Gets the meeting warning time span in minutes before the meeting starts
/// </summary>
[JsonProperty("meetingWarningMinutes")]
public TimeSpan MeetingWarningMinutes
{
get { return TimeSpan.FromMinutes(MinutesBeforeMeeting); }
}
/// <summary>
/// Gets the time remaining until the meeting starts
/// </summary>
[JsonProperty("timeToMeetingStart")]
public TimeSpan TimeToMeetingStart
{
get
{
return StartTime - DateTime.Now;
}
}
/// <summary>
/// Gets the time remaining until the meeting ends
/// </summary>
[JsonProperty("timeToMeetingEnd")]
public TimeSpan TimeToMeetingEnd
{
get
{
return EndTime - DateTime.Now;
}
}
/// <summary>
/// Gets or sets the StartTime
/// </summary>
[JsonProperty("startTime")]
public DateTime StartTime { get; set; }
/// <summary>
/// Gets or sets the EndTime
/// </summary>
[JsonProperty("endTime")]
public DateTime EndTime { get; set; }
/// <summary>
/// Gets the duration of the meeting
/// </summary>
[JsonProperty("duration")]
public TimeSpan Duration
{
get
{
return EndTime - StartTime;
}
}
/// <summary>
/// Gets or sets the Privacy
/// </summary>
[JsonProperty("privacy")]
public eMeetingPrivacy Privacy { get; set; }
/// <summary>
/// Gets a value indicating whether the meeting can be joined
/// </summary>
[JsonProperty("joinable")]
public bool Joinable
{
get
{
var joinable = StartTime.AddMinutes(-MinutesBeforeMeeting) <= DateTime.Now
&& DateTime.Now <= EndTime.AddSeconds(-_joinableCooldownSeconds);
//Debug.LogMessage(LogEventLevel.Verbose, "Meeting Id: {0} joinable: {1}", Id, joinable);
return joinable;
}
}
/// <summary>
/// Gets or sets the Dialable
/// </summary>
[JsonProperty("dialable")]
public bool Dialable { get; set; }
//public string ConferenceNumberToDial { get; set; }
/// <summary>
/// Gets or sets the ConferencePassword
/// </summary>
[JsonProperty("conferencePassword")]
public string ConferencePassword { get; set; }
/// <summary>
/// Gets or sets the IsOneButtonToPushMeeting
/// </summary>
[JsonProperty("isOneButtonToPushMeeting")]
public bool IsOneButtonToPushMeeting { get; set; }
/// <summary>
/// Gets or sets the Calls
/// </summary>
[JsonProperty("calls")]
public List<Call> Calls { get; private set; }
/// <summary>
/// Tracks the change types that have already been notified for
/// Gets or sets the NotifiedChangeTypes
/// </summary>
[JsonIgnore]
public eMeetingEventChangeType NotifiedChangeTypes { get; set; }
[JsonIgnore] private readonly int _joinableCooldownSeconds;
/// <summary>
/// Constructor for Meeting <see cref="Meeting"/>
/// </summary>
public Meeting()
{
Calls = new List<Call>();
_joinableCooldownSeconds = 300;
}
/// <summary>
/// Constructor for Meeting <see cref="Meeting"/>
/// </summary>
/// <param name="joinableCooldownSeconds">Number of seconds after meeting start when it is no longer joinable</param>
public Meeting(int joinableCooldownSeconds)
{
Calls = new List<Call>();
_joinableCooldownSeconds = joinableCooldownSeconds;
}
#region Overrides of Object
/// <summary>
/// ToString method
/// </summary>
/// <inheritdoc />
public override string ToString()
{
return string.Format("{0}:{1}: {2}-{3}", Title, Agenda, StartTime, EndTime);
}
#endregion
}
}

View File

@@ -0,0 +1,22 @@
using System;
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Represents a MeetingEventArgs
/// </summary>
public class MeetingEventArgs : EventArgs
{
/// <summary>
/// Gets or sets the ChangeType
/// </summary>
public eMeetingEventChangeType ChangeType { get; set; }
/// <summary>
/// Gets or sets the Meeting
/// </summary>
public Meeting Meeting { get; set; }
}
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Common.Codec
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
@@ -12,7 +6,20 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary>
public enum eCodecCallDirection
{
Unknown = 0, Incoming, Outgoing
/// <summary>
/// Unknown call direction
/// </summary>
Unknown = 0,
/// <summary>
/// Incoming call direction
/// </summary>
Incoming,
/// <summary>
/// Outgoing call direction
/// </summary>
Outgoing
}
/// <summary>

View File

@@ -1,27 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Common.Codec
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Enumeration of eCodecCallStatus values
/// </summary>
public enum eCodecCallStatus
{
/// <summary>
/// Unknown call status
/// </summary>
Unknown = 0,
Connected,
Connecting,
Dialing,
/// <summary>
/// Call is connected
/// </summary>
Connected,
/// <summary>
/// Call is connecting
/// </summary>
Connecting,
/// <summary>
/// Call is dialing
/// </summary>
Dialing,
/// <summary>
/// Call is disconnected
/// </summary>
Disconnected,
Disconnecting,
EarlyMedia,
/// <summary>
/// Call is disconnecting
/// </summary>
Disconnecting,
/// <summary>
/// Early media is being sent/received
/// </summary>
EarlyMedia,
/// <summary>
/// Call is idle
/// </summary>
Idle,
OnHold,
Ringing,
Preserved,
/// <summary>
/// Call is on hold
/// </summary>
OnHold,
/// <summary>
/// Call is ringing
/// </summary>
Ringing,
/// <summary>
/// Call is preserved
/// </summary>
Preserved,
/// <summary>
/// Call is remote preserved
/// </summary>
RemotePreserved,
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Common.Codec
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
@@ -12,10 +6,29 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary>
public enum eCodecCallType
{
Unknown = 0,
Audio,
Video,
AudioCanEscalate,
/// <summary>
/// Unknown call type
/// </summary>
Unknown = 0,
/// <summary>
/// Audio-only call type
/// </summary>
Audio,
/// <summary>
/// Video call type
/// </summary>
Video,
/// <summary>
/// Audio call that can be escalated to video
/// </summary>
AudioCanEscalate,
/// <summary>
/// Forward all call type
/// </summary>
ForwardAllCall
}

View File

@@ -0,0 +1,21 @@
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Enumeration of eContactMethodCallType values
/// </summary>
public enum eContactMethodCallType
{
/// <summary>
/// Unknown call type
/// </summary>
Unknown = 0,
/// <summary>
/// Audio call type
/// </summary>
Audio,
/// <summary>
/// Video call type
/// </summary>
Video
}
}

View File

@@ -0,0 +1,29 @@
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Enumeration of eContactMethodDevice values
/// </summary>
public enum eContactMethodDevice
{
/// <summary>
/// Unknown contact method
/// </summary>
Unknown = 0,
/// <summary>
/// Mobile contact method
/// </summary>
Mobile,
/// <summary>
/// Other contact method
/// </summary>
Other,
/// <summary>
/// Telephone contact method
/// </summary>
Telephone,
/// <summary>
/// Video contact method
/// </summary>
Video
}
}

View File

@@ -0,0 +1,35 @@
using System;
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Enumeration of eMeetingEventChangeType values
/// </summary>
[Flags]
public enum eMeetingEventChangeType
{
/// <summary>
/// Unknown change type
/// </summary>
Unknown = 0,
/// <summary>
/// Meeting start warning
/// </summary>
MeetingStartWarning = 1,
/// <summary>
/// Meeting start
/// </summary>
MeetingStart = 2,
/// <summary>
/// Meeting end warning
/// </summary>
MeetingEndWarning = 4,
/// <summary>
/// Meeting end
/// </summary>
MeetingEnd = 8
}
}

View File

@@ -1,18 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Common.Codec
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Enumeration of eMeetingPrivacy values
/// </summary>
public enum eMeetingPrivacy
{
/// <summary>
/// Unknown meeting privacy level
/// </summary>
Unknown = 0,
/// <summary>
/// Public meeting
/// </summary>
Public,
/// <summary>
/// Private meeting
/// </summary>
Private
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.Codec
{

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using System.Collections.Generic;
namespace PepperDash.Essentials.Devices.Common.Codec
{
@@ -11,6 +7,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary>
public interface IHasCallFavorites
{
/// <summary>
/// Gets the call favorites for this device
/// </summary>
CodecCallFavorites CallFavorites { get; }
}
@@ -24,6 +23,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary>
public List<CodecActiveCallItem> Favorites { get; set; }
/// <summary>
/// Initializes a new instance of the CodecCallFavorites class
/// </summary>
public CodecCallFavorites()
{
Favorites = new List<CodecActiveCallItem>();

View File

@@ -2,10 +2,9 @@
using System;
using System.Collections.Generic;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using PepperDash.Essentials.Devices.Common.VideoCodec;
namespace PepperDash.Essentials.Devices.Common.Codec
{
@@ -15,8 +14,15 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary>
public interface IHasCallHistory
{
/// <summary>
/// Gets the call history for this device
/// </summary>
CodecCallHistory CallHistory { get; }
/// <summary>
/// Removes the specified call history entry
/// </summary>
/// <param name="entry">The call history entry to remove</param>
void RemoveCallHistoryEntry(CodecCallHistory.CallHistoryEntry entry);
}
@@ -25,9 +31,24 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary>
public enum eCodecOccurrenceType
{
/// <summary>
/// Unknown occurrence type
/// </summary>
Unknown = 0,
/// <summary>
/// Call was placed (outgoing)
/// </summary>
Placed = 1,
/// <summary>
/// Call was received (incoming)
/// </summary>
Received = 2,
/// <summary>
/// Call received no answer
/// </summary>
NoAnswer = 3,
}
@@ -36,6 +57,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary>
public class CodecCallHistory
{
/// <summary>
/// Event that is raised when the recent calls list has changed
/// </summary>
public event EventHandler<EventArgs> RecentCallsListHasChanged;
/// <summary>
@@ -48,6 +72,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary>
CallHistoryEntry ListEmptyEntry;
/// <summary>
/// Initializes a new instance of the CodecCallHistory class
/// </summary>
public CodecCallHistory()
{
ListEmptyEntry = new CallHistoryEntry() { Name = "No Recent Calls" };
@@ -80,15 +107,22 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary>
public class CallHistoryEntry : CodecActiveCallItem
{
[JsonConverter(typeof(IsoDateTimeConverter))]
[JsonProperty("startTime")]
/// <summary>
/// Gets or sets the StartTime
/// </summary>
[JsonConverter(typeof(IsoDateTimeConverter))]
[JsonProperty("startTime")]
public DateTime StartTime { get; set; }
/// <summary>
/// Gets or sets the occurrence type for this call history entry
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
[JsonProperty("occurrenceType")]
public eCodecOccurrenceType OccurrenceType { get; set; }
/// <summary>
/// Gets or sets the occurrence history identifier
/// </summary>
[JsonProperty("occurrenceHistoryId")]
public string OccurrenceHistoryId { get; set; }
}
@@ -119,7 +153,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec
}
// Check if list is empty and if so, add an item to display No Recent Calls
if(genericEntries.Count == 0)
if (genericEntries.Count == 0)
genericEntries.Add(ListEmptyEntry);
RecentCalls = genericEntries;

View File

@@ -1,11 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.Codec
@@ -15,12 +8,29 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary>
public interface IHasContentSharing
{
/// <summary>
/// Gets feedback indicating whether content sharing is currently active
/// </summary>
BoolFeedback SharingContentIsOnFeedback { get; }
/// <summary>
/// Gets feedback about the current sharing source
/// </summary>
StringFeedback SharingSourceFeedback { get; }
/// <summary>
/// Gets a value indicating whether content should be automatically shared while in a call
/// </summary>
bool AutoShareContentWhileInCall { get; }
/// <summary>
/// Starts content sharing
/// </summary>
void StartSharing();
/// <summary>
/// Stops content sharing
/// </summary>
void StopSharing();
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.Codec
{
@@ -15,15 +9,49 @@ namespace PepperDash.Essentials.Devices.Common.Codec
{
// Add requirements for Dialer functionality
/// <summary>
/// Event that is raised when call status changes
/// </summary>
event EventHandler<CodecCallStatusItemChangeEventArgs> CallStatusChange;
/// <summary>
/// Dials the specified number
/// </summary>
/// <param name="number">The number to dial</param>
void Dial(string number);
/// <summary>
/// Ends the specified active call
/// </summary>
/// <param name="activeCall">The active call to end</param>
void EndCall(CodecActiveCallItem activeCall);
/// <summary>
/// Ends all active calls
/// </summary>
void EndAllCalls();
/// <summary>
/// Accepts the specified incoming call
/// </summary>
/// <param name="item">The call item to accept</param>
void AcceptCall(CodecActiveCallItem item);
/// <summary>
/// Rejects the specified incoming call
/// </summary>
/// <param name="item">The call item to reject</param>
void RejectCall(CodecActiveCallItem item);
/// <summary>
/// Sends DTMF digits during a call
/// </summary>
/// <param name="digit">The DTMF digit(s) to send</param>
void SendDtmf(string digit);
/// <summary>
/// Gets a value indicating whether the device is currently in a call
/// </summary>
bool IsInCall { get; }
}

View File

@@ -1,319 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.VideoCodec;
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Defines the API for codecs with a directory
/// </summary>
/// <summary>
/// Defines the API for codecs with a directory
/// </summary>
public interface IHasDirectory
{
/// <summary>
/// Event that fires when a directory result is returned from the codec
/// </summary>
event EventHandler<DirectoryEventArgs> DirectoryResultReturned;
/// <summary>
/// Gets the DirectoryRoot
/// </summary>
CodecDirectory DirectoryRoot { get; }
/// <summary>
/// Gets the CurrentDirectoryResult
/// </summary>
CodecDirectory CurrentDirectoryResult { get; }
/// <summary>
/// Gets the PhonebookSyncState
/// </summary>
CodecPhonebookSyncState PhonebookSyncState { get; }
/// <summary>
/// Method to initiate a search of the directory on the server
/// </summary>
void SearchDirectory(string searchString);
/// <summary>
/// Method to get the contents of a specific folder in the directory on the server
/// </summary>
void GetDirectoryFolderContents(string folderId);
/// <summary>
/// Method to set the current directory to the root folder
/// </summary>
void SetCurrentDirectoryToRoot();
/// <summary>
/// Method to get the contents of the parent folder in the directory on the server
/// </summary>
void GetDirectoryParentFolderContents();
/// <summary>
/// Gets the CurrentDirectoryResultIsNotDirectoryRoot
/// </summary>
BoolFeedback CurrentDirectoryResultIsNotDirectoryRoot { get; }
}
/// <summary>
/// Defines the contract for IHasDirectoryHistoryStack
/// </summary>
public interface IHasDirectoryHistoryStack : IHasDirectory
{
Stack<CodecDirectory> DirectoryBrowseHistoryStack { get; }
}
/// <summary>
/// Represents a DirectoryEventArgs
/// </summary>
public class DirectoryEventArgs : EventArgs
{
/// <summary>
/// Gets or sets the Directory
/// </summary>
public CodecDirectory Directory { get; set; }
/// <summary>
/// Gets or sets the DirectoryIsOnRoot
/// </summary>
public bool DirectoryIsOnRoot { get; set; }
}
/// <summary>
/// Represents a codec directory
/// </summary>
public class CodecDirectory
{
/// <summary>
/// Represents the contents of the directory
/// We don't want to serialize this for messages to MobileControl. MC can combine Contacts and Folders to get the same data
/// </summary>
[JsonIgnore]
public List<DirectoryItem> CurrentDirectoryResults { get; private set; }
[JsonProperty("contacts")]
public List<DirectoryItem> Contacts
{
get
{
return CurrentDirectoryResults.OfType<DirectoryContact>().Cast<DirectoryItem>().ToList();
}
}
[JsonProperty("folders")]
public List<DirectoryItem> Folders
{
get
{
return CurrentDirectoryResults.OfType<DirectoryFolder>().Cast<DirectoryItem>().ToList();
}
}
/// <summary>
/// Used to store the ID of the current folder for CurrentDirectoryResults
/// </summary>
[JsonProperty("resultsFolderId")]
/// <summary>
/// Gets or sets the ResultsFolderId
/// </summary>
public string ResultsFolderId { get; set; }
public CodecDirectory()
{
CurrentDirectoryResults = new List<DirectoryItem>();
}
/// <summary>
/// Adds folders to the directory
/// </summary>
/// <param name="folders"></param>
/// <summary>
/// AddFoldersToDirectory method
/// </summary>
public void AddFoldersToDirectory(List<DirectoryItem> folders)
{
if(folders != null)
CurrentDirectoryResults.AddRange(folders);
SortDirectory();
}
/// <summary>
/// Adds contacts to the directory
/// </summary>
/// <param name="contacts"></param>
/// <summary>
/// AddContactsToDirectory method
/// </summary>
public void AddContactsToDirectory(List<DirectoryItem> contacts)
{
if(contacts != null)
CurrentDirectoryResults.AddRange(contacts);
SortDirectory();
}
/// <summary>
/// Filters the CurrentDirectoryResults by the predicate
/// </summary>
/// <param name="predicate"></param>
/// <summary>
/// FilterContacts method
/// </summary>
public void FilterContacts(Func<DirectoryItem, bool> predicate)
{
CurrentDirectoryResults = CurrentDirectoryResults.Where(predicate).ToList();
}
/// <summary>
/// Sorts the DirectoryResults list to display all folders alphabetically, then all contacts alphabetically
/// </summary>
private void SortDirectory()
{
var sortedFolders = new List<DirectoryItem>();
sortedFolders.AddRange(CurrentDirectoryResults.Where(f => f is DirectoryFolder));
sortedFolders.OrderBy(f => f.Name);
var sortedContacts = new List<DirectoryItem>();
sortedContacts.AddRange(CurrentDirectoryResults.Where(c => c is DirectoryContact));
sortedFolders.OrderBy(c => c.Name);
CurrentDirectoryResults.Clear();
CurrentDirectoryResults.AddRange(sortedFolders);
CurrentDirectoryResults.AddRange(sortedContacts);
}
}
/// <summary>
/// Defines the contract for IInvitableContact
/// </summary>
public interface IInvitableContact
{
bool IsInvitableContact { get; }
}
public class InvitableDirectoryContact : DirectoryContact, IInvitableContact
{
[JsonProperty("isInvitableContact")]
public bool IsInvitableContact
{
get
{
return this is IInvitableContact;
}
}
}
/// <summary>
/// Represents a DirectoryItem
/// </summary>
public class DirectoryItem : ICloneable
{
/// <summary>
/// Clone method
/// </summary>
public object Clone()
{
return this.MemberwiseClone();
}
[JsonProperty("folderId")]
public string FolderId { get; set; }
[JsonProperty("name")]
/// <summary>
/// Gets or sets the Name
/// </summary>
public string Name { get; set; }
[JsonProperty("parentFolderId")]
/// <summary>
/// Gets or sets the ParentFolderId
/// </summary>
public string ParentFolderId { get; set; }
}
/// <summary>
/// Represents a DirectoryFolder
/// </summary>
public class DirectoryFolder : DirectoryItem
{
[JsonProperty("contacts")]
/// <summary>
/// Gets or sets the Contacts
/// </summary>
public List<DirectoryContact> Contacts { get; set; }
public DirectoryFolder()
{
Contacts = new List<DirectoryContact>();
}
}
/// <summary>
/// Represents a DirectoryContact
/// </summary>
public class DirectoryContact : DirectoryItem
{
[JsonProperty("contactId")]
/// <summary>
/// Gets or sets the ContactId
/// </summary>
public string ContactId { get; set; }
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("contactMethods")]
public List<ContactMethod> ContactMethods { get; set; }
public DirectoryContact()
{
ContactMethods = new List<ContactMethod>();
}
}
/// <summary>
/// Represents a ContactMethod
/// </summary>
public class ContactMethod
{
[JsonProperty("contactMethodId")]
/// <summary>
/// Gets or sets the ContactMethodId
/// </summary>
public string ContactMethodId { get; set; }
[JsonProperty("number")]
public string Number { get; set; }
[JsonProperty("device")]
[JsonConverter(typeof(StringEnumConverter))]
/// <summary>
/// Gets or sets the Device
/// </summary>
public eContactMethodDevice Device { get; set; }
[JsonProperty("callType")]
[JsonConverter(typeof(StringEnumConverter))]
/// <summary>
/// Gets or sets the CallType
/// </summary>
public eContactMethodCallType CallType { get; set; }
}
/// <summary>
/// Enumeration of eContactMethodDevice values
/// </summary>
public enum eContactMethodDevice
{
Unknown = 0,
Mobile,
Other,
Telephone,
Video
}
/// <summary>
/// Enumeration of eContactMethodCallType values
/// </summary>
public enum eContactMethodCallType
{
Unknown = 0,
Audio,
Video
}
}

View File

@@ -1,339 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using Newtonsoft.Json;
using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.Codec
namespace PepperDash.Essentials.Devices.Common.Codec
{
[Flags]
/// <summary>
/// Enumeration of eMeetingEventChangeType values
/// </summary>
public enum eMeetingEventChangeType
{
Unknown = 0,
MeetingStartWarning = 1,
MeetingStart = 2,
MeetingEndWarning = 4,
MeetingEnd = 8
}
/// <summary>
/// Defines the contract for IHasScheduleAwareness
/// </summary>
public interface IHasScheduleAwareness
{
/// <summary>
/// Gets the CodecScheduleAwareness instance
/// </summary>
CodecScheduleAwareness CodecSchedule { get; }
/// <summary>
/// Method to initiate getting the schedule from the server
/// </summary>
void GetSchedule();
}
/// <summary>
/// Represents a CodecScheduleAwareness
/// </summary>
public class CodecScheduleAwareness
{
List<Meeting> _meetings;
public event EventHandler<MeetingEventArgs> MeetingEventChange;
public event EventHandler<EventArgs> MeetingsListHasChanged;
private int _meetingWarningMinutes = 5;
//private Meeting _previousChangedMeeting;
//private eMeetingEventChangeType _previousChangeType = eMeetingEventChangeType.Unknown;
public int MeetingWarningMinutes
{
get { return _meetingWarningMinutes; }
set { _meetingWarningMinutes = value; }
}
/// <summary>
/// Setter triggers MeetingsListHasChanged event
/// </summary>
public List<Meeting> Meetings
{
get
{
return _meetings;
}
set
{
_meetings = value;
MeetingsListHasChanged?.Invoke(this, new EventArgs());
}
}
private readonly CTimer _scheduleChecker;
public CodecScheduleAwareness()
{
Meetings = new List<Meeting>();
_scheduleChecker = new CTimer(CheckSchedule, null, 1000, 1000);
}
public CodecScheduleAwareness(long pollTime)
{
Meetings = new List<Meeting>();
_scheduleChecker = new CTimer(CheckSchedule, null, pollTime, pollTime);
}
/// <summary>
/// Helper method to fire MeetingEventChange. Should only fire once for each changeType on each meeting
/// </summary>
/// <param name="changeType"></param>
/// <param name="meeting"></param>
private void OnMeetingChange(eMeetingEventChangeType changeType, Meeting meeting)
{
Debug.LogMessage(LogEventLevel.Verbose, "*****************OnMeetingChange. id: {0} changeType: {1}**********************", meeting.Id, changeType);
if (changeType != (changeType & meeting.NotifiedChangeTypes))
{
// Add this change type to the NotifiedChangeTypes
meeting.NotifiedChangeTypes |= changeType;
MeetingEventChange?.Invoke(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting });
}
else
{
Debug.LogMessage(LogEventLevel.Verbose, "Meeting: {0} already notified of changeType: {1}", meeting.Id, changeType);
}
}
/// <summary>
/// Checks the schedule to see if any MeetingEventChange updates should be fired
/// </summary>
/// <param name="o"></param>
private void CheckSchedule(object o)
{
// Iterate the meeting list and check if any meeting need to do anything
const double meetingTimeEpsilon = 0.05;
foreach (var m in Meetings)
{
var changeType = eMeetingEventChangeType.Unknown;
if (eMeetingEventChangeType.MeetingStartWarning != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStartWarning) && m.TimeToMeetingStart.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingStart.Seconds > 0) // Meeting is about to start
{
Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingStartWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingStart.TotalMinutes, m.TimeToMeetingStart.Seconds);
changeType = eMeetingEventChangeType.MeetingStartWarning;
}
else if (eMeetingEventChangeType.MeetingStart != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStart) && Math.Abs(m.TimeToMeetingStart.TotalMinutes) < meetingTimeEpsilon) // Meeting Start
{
Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingStart");
changeType = eMeetingEventChangeType.MeetingStart;
}
else if (eMeetingEventChangeType.MeetingEndWarning != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingEndWarning) && m.TimeToMeetingEnd.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingEnd.Seconds > 0) // Meeting is about to end
{
Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingEndWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingEnd.TotalMinutes, m.TimeToMeetingEnd.Seconds);
changeType = eMeetingEventChangeType.MeetingEndWarning;
}
else if (eMeetingEventChangeType.MeetingEnd != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingEnd) && Math.Abs(m.TimeToMeetingEnd.TotalMinutes) < meetingTimeEpsilon) // Meeting has ended
{
Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingEnd");
changeType = eMeetingEventChangeType.MeetingEnd;
}
if (changeType != eMeetingEventChangeType.Unknown)
{
OnMeetingChange(changeType, m);
}
}
}
}
/// <summary>
/// Represents a Meeting
/// </summary>
public class Meeting
{
[JsonProperty("minutesBeforeMeeting")]
public int MinutesBeforeMeeting;
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("organizer")]
public string Organizer { get; set; }
[JsonProperty("title")]
/// <summary>
/// Gets or sets the Title
/// </summary>
public string Title { get; set; }
[JsonProperty("agenda")]
/// <summary>
/// Gets or sets the Agenda
/// </summary>
public string Agenda { get; set; }
[JsonProperty("meetingWarningMinutes")]
public TimeSpan MeetingWarningMinutes
{
get { return TimeSpan.FromMinutes(MinutesBeforeMeeting); }
}
[JsonProperty("timeToMeetingStart")]
public TimeSpan TimeToMeetingStart
{
get
{
return StartTime - DateTime.Now;
}
}
[JsonProperty("timeToMeetingEnd")]
public TimeSpan TimeToMeetingEnd
{
get
{
return EndTime - DateTime.Now;
}
}
[JsonProperty("startTime")]
/// <summary>
/// Gets or sets the StartTime
/// </summary>
public DateTime StartTime { get; set; }
[JsonProperty("endTime")]
/// <summary>
/// Gets or sets the EndTime
/// </summary>
public DateTime EndTime { get; set; }
[JsonProperty("duration")]
public TimeSpan Duration
{
get
{
return EndTime - StartTime;
}
}
[JsonProperty("privacy")]
/// <summary>
/// Gets or sets the Privacy
/// </summary>
public eMeetingPrivacy Privacy { get; set; }
[JsonProperty("joinable")]
public bool Joinable
{
get
{
var joinable = StartTime.AddMinutes(-MinutesBeforeMeeting) <= DateTime.Now
&& DateTime.Now <= EndTime.AddSeconds(-_joinableCooldownSeconds);
//Debug.LogMessage(LogEventLevel.Verbose, "Meeting Id: {0} joinable: {1}", Id, joinable);
return joinable;
}
}
[JsonProperty("dialable")]
/// <summary>
/// Gets or sets the Dialable
/// </summary>
public bool Dialable { get; set; }
//public string ConferenceNumberToDial { get; set; }
[JsonProperty("conferencePassword")]
/// <summary>
/// Gets or sets the ConferencePassword
/// </summary>
public string ConferencePassword { get; set; }
[JsonProperty("isOneButtonToPushMeeting")]
/// <summary>
/// Gets or sets the IsOneButtonToPushMeeting
/// </summary>
public bool IsOneButtonToPushMeeting { get; set; }
[JsonProperty("calls")]
/// <summary>
/// Gets or sets the Calls
/// </summary>
public List<Call> Calls { get; private set; }
/// <summary>
/// Tracks the change types that have already been notified for
/// </summary>
[JsonIgnore]
/// <summary>
/// Gets or sets the NotifiedChangeTypes
/// </summary>
public eMeetingEventChangeType NotifiedChangeTypes { get; set; }
[JsonIgnore] private readonly int _joinableCooldownSeconds;
public Meeting()
{
Calls = new List<Call>();
_joinableCooldownSeconds = 300;
}
public Meeting(int joinableCooldownSeconds)
{
Calls = new List<Call>();
_joinableCooldownSeconds = joinableCooldownSeconds;
}
#region Overrides of Object
/// <summary>
/// ToString method
/// </summary>
/// <inheritdoc />
public override string ToString()
{
return String.Format("{0}:{1}: {2}-{3}", Title, Agenda, StartTime, EndTime);
}
#endregion
}
/// <summary>
/// Represents a Call
/// </summary>
public class Call
{
/// <summary>
/// Gets or sets the Number
/// </summary>
public string Number { get; set; }
/// <summary>
/// Gets or sets the Protocol
/// </summary>
public string Protocol { get; set; }
/// <summary>
/// Gets or sets the CallRate
/// </summary>
public string CallRate { get; set; }
/// <summary>
/// Gets or sets the CallType
/// </summary>
public string CallType { get; set; }
}
/// <summary>
/// Represents a MeetingEventArgs
/// </summary>
public class MeetingEventArgs : EventArgs
{
/// <summary>
/// Gets or sets the ChangeType
/// </summary>
public eMeetingEventChangeType ChangeType { get; set; }
/// <summary>
/// Gets or sets the Meeting
/// </summary>
public Meeting Meeting { get; set; }
}
}

View File

@@ -1,61 +1,84 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials.Devices.Common.DSP
{
public abstract class DspBase : EssentialsDevice, ILevelControls
{
public Dictionary<string,IBasicVolumeWithFeedback> LevelControlPoints { get; private set; }
/// <summary>
/// Base class for DSP devices
/// </summary>
public abstract class DspBase : EssentialsDevice, ILevelControls
{
/// <summary>
/// Gets the collection of level control points
/// </summary>
public Dictionary<string, IBasicVolumeWithFeedback> LevelControlPoints { get; private set; }
/// <summary>
/// Gets the collection of dialer control points
/// </summary>
public Dictionary<string, DspControlPoint> DialerControlPoints { get; private set; }
/// <summary>
/// Gets the collection of switcher control points
/// </summary>
public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
public DspBase(string key, string name) :
base(key, name)
{
/// <summary>
/// Initializes a new instance of the DspBase class
/// </summary>
/// <param name="key">The device key</param>
/// <param name="name">The device name</param>
public DspBase(string key, string name) :
base(key, name)
{
LevelControlPoints = new Dictionary<string, IBasicVolumeWithFeedback>();
DialerControlPoints = new Dictionary<string, DspControlPoint>();
SwitcherControlPoints = new Dictionary<string, DspControlPoint>();
}
LevelControlPoints = new Dictionary<string, IBasicVolumeWithFeedback>();
DialerControlPoints = new Dictionary<string, DspControlPoint>();
SwitcherControlPoints = new Dictionary<string, DspControlPoint>();
}
// in audio call feedback
// in audio call feedback
// VOIP
// Phone dialer
// VOIP
// Phone dialer
}
}
// Fusion
// Privacy state
// Online state
// level/mutes ?
// AC Log call stats
// Typical presets:
// call default preset to restore levels and mutes
// Fusion
// Privacy state
// Online state
// level/mutes ?
public abstract class DspControlPoint :IKeyed
{
// AC Log call stats
// Typical presets:
// call default preset to restore levels and mutes
/// <summary>
/// Base class for DSP control points
/// </summary>
public abstract class DspControlPoint : IKeyed
{
/// <summary>
/// Gets or sets the Key
/// </summary>
public string Key { get; }
/// <summary>
/// Initializes a new instance of the DspControlPoint class
/// </summary>
/// <param name="key">The control point key</param>
protected DspControlPoint(string key) => Key = key;
}
}
public abstract class DspLevelControlPoint :DspControlPoint, IBasicVolumeWithFeedback
/// <summary>
/// Base class for DSP level control points with volume and mute functionality
/// </summary>
public abstract class DspLevelControlPoint : DspControlPoint, IBasicVolumeWithFeedback
{
/// <summary>
/// Gets or sets the MuteFeedback
@@ -66,30 +89,63 @@ namespace PepperDash.Essentials.Devices.Common.DSP
/// </summary>
public IntFeedback VolumeLevelFeedback { get; }
/// <summary>
/// Initializes a new instance of the DspLevelControlPoint class
/// </summary>
/// <param name="key">The control point key</param>
/// <param name="muteFeedbackFunc">Function to get mute status</param>
/// <param name="volumeLevelFeedbackFunc">Function to get volume level</param>
protected DspLevelControlPoint(string key, Func<bool> muteFeedbackFunc, Func<int> volumeLevelFeedbackFunc) : base(key)
{
MuteFeedback = new BoolFeedback(muteFeedbackFunc);
VolumeLevelFeedback = new IntFeedback(volumeLevelFeedbackFunc);
MuteFeedback = new BoolFeedback("mute", muteFeedbackFunc);
VolumeLevelFeedback = new IntFeedback("volume", volumeLevelFeedbackFunc);
}
/// <summary>
/// Turns mute off
/// </summary>
public abstract void MuteOff();
/// <summary>
/// Turns mute on
/// </summary>
public abstract void MuteOn();
/// <summary>
/// Toggles mute state
/// </summary>
public abstract void MuteToggle();
/// <summary>
/// Sets the volume level
/// </summary>
/// <param name="level">The volume level to set</param>
public abstract void SetVolume(ushort level);
/// <summary>
/// Decreases volume
/// </summary>
/// <param name="pressRelease">True when pressed, false when released</param>
public abstract void VolumeDown(bool pressRelease);
/// <summary>
/// Increases volume
/// </summary>
/// <param name="pressRelease">True when pressed, false when released</param>
public abstract void VolumeUp(bool pressRelease);
}
public abstract class DspDialerBase:DspControlPoint
{
/// <summary>
/// Base class for DSP dialer control points
/// </summary>
public abstract class DspDialerBase : DspControlPoint
{
/// <summary>
/// Initializes a new instance of the DspDialerBase class
/// </summary>
/// <param name="key">The dialer control point key</param>
protected DspDialerBase(string key) : base(key) { }
}
}
// Main program
// VTC
// ATC
// Mics, unusual
// Main program
// VTC
// ATC
// Mics, unusual
}

View File

@@ -14,7 +14,9 @@ namespace PepperDash.Essentials.Devices.Common
/// </summary>
public class DeviceFactory
{
/// <summary>
/// Initializes a new instance of the DeviceFactory class
/// </summary>
public DeviceFactory()
{
var assy = Assembly.GetExecutingAssembly();

View File

@@ -11,37 +11,53 @@ using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.Displays
{
/// <summary>
/// Represents a BasicIrDisplay
/// </summary>
public class BasicIrDisplay : DisplayBase, IBasicVolumeControls, IBridgeAdvanced
/// <summary>
/// Represents a BasicIrDisplay
/// </summary>
public class BasicIrDisplay : DisplayBase, IBasicVolumeControls, IBridgeAdvanced
{
/// <summary>
/// Gets or sets the IrPort
/// </summary>
/// <summary>
/// Gets or sets the IrPort
/// </summary>
public IrOutputPortController IrPort { get; private set; }
/// <summary>
/// Gets or sets the IrPulseTime
/// </summary>
/// <summary>
/// Gets or sets the IrPulseTime
/// </summary>
public ushort IrPulseTime { get; set; }
protected Func<bool> PowerIsOnFeedbackFunc
{
get { return () => _PowerIsOn; }
}
/// <summary>
/// Gets the power is on feedback function
/// </summary>
protected Func<bool> PowerIsOnFeedbackFunc
{
get { return () => _PowerIsOn; }
}
/// <summary>
/// Gets the is cooling down feedback function
/// </summary>
protected override Func<bool> IsCoolingDownFeedbackFunc
{
get { return () => _IsCoolingDown; }
}
/// <summary>
/// Gets the is warming up feedback function
/// </summary>
protected override Func<bool> IsWarmingUpFeedbackFunc
{
get { return () => _IsWarmingUp; }
}
bool _PowerIsOn;
bool _PowerIsOn;
bool _IsWarmingUp;
bool _IsCoolingDown;
/// <summary>
/// Initializes a new instance of the BasicIrDisplay class
/// </summary>
/// <param name="key">The device key</param>
/// <param name="name">The device name</param>
/// <param name="port">The IR output port</param>
/// <param name="irDriverFilepath">The path to the IR driver file</param>
public BasicIrDisplay(string key, string name, IROutputPort port, string irDriverFilepath)
: base(key, name)
{
@@ -53,74 +69,74 @@ namespace PepperDash.Essentials.Devices.Common.Displays
InputPorts.AddRange(new RoutingPortCollection<RoutingInputPort>
{
new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video,
new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Hdmi1), this, false),
new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video,
new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Hdmi2), this, false),
new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.Audio | eRoutingSignalType.Video,
new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Hdmi3), this, false),
new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.Audio | eRoutingSignalType.Video,
new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Hdmi4), this, false),
new RoutingInputPort(RoutingPortNames.ComponentIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
new RoutingInputPort(RoutingPortNames.ComponentIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Component1), this, false),
new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Video1), this, false),
new RoutingInputPort(RoutingPortNames.AntennaIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
new RoutingInputPort(RoutingPortNames.AntennaIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Antenna), this, false),
});
}
/// <summary>
/// Hdmi1 method
/// </summary>
/// <summary>
/// Hdmi1 method
/// </summary>
public void Hdmi1()
{
IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_1, IrPulseTime);
}
/// <summary>
/// Hdmi2 method
/// </summary>
/// <summary>
/// Hdmi2 method
/// </summary>
public void Hdmi2()
{
IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_2, IrPulseTime);
}
/// <summary>
/// Hdmi3 method
/// </summary>
/// <summary>
/// Hdmi3 method
/// </summary>
public void Hdmi3()
{
IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_3, IrPulseTime);
}
/// <summary>
/// Hdmi4 method
/// </summary>
/// <summary>
/// Hdmi4 method
/// </summary>
public void Hdmi4()
{
IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_4, IrPulseTime);
}
/// <summary>
/// Component1 method
/// </summary>
/// <summary>
/// Component1 method
/// </summary>
public void Component1()
{
IrPort.Pulse(IROutputStandardCommands.IROut_COMPONENT_1, IrPulseTime);
}
/// <summary>
/// Video1 method
/// </summary>
/// <summary>
/// Video1 method
/// </summary>
public void Video1()
{
IrPort.Pulse(IROutputStandardCommands.IROut_VIDEO_1, IrPulseTime);
}
/// <summary>
/// Antenna method
/// </summary>
/// <summary>
/// Antenna method
/// </summary>
public void Antenna()
{
IrPort.Pulse(IROutputStandardCommands.IROut_ANTENNA, IrPulseTime);
@@ -128,31 +144,31 @@ namespace PepperDash.Essentials.Devices.Common.Displays
#region IPower Members
/// <summary>
/// PowerOn method
/// </summary>
/// <inheritdoc />
/// <summary>
/// PowerOn method
/// </summary>
/// <inheritdoc />
public override void PowerOn()
{
IrPort.Pulse(IROutputStandardCommands.IROut_POWER_ON, IrPulseTime);
_PowerIsOn = true;
_PowerIsOn = true;
}
/// <summary>
/// PowerOff method
/// </summary>
/// <summary>
/// PowerOff method
/// </summary>
public override void PowerOff()
{
_PowerIsOn = false;
_PowerIsOn = false;
IrPort.Pulse(IROutputStandardCommands.IROut_POWER_OFF, IrPulseTime);
}
/// <summary>
/// PowerToggle method
/// </summary>
/// <summary>
/// PowerToggle method
/// </summary>
public override void PowerToggle()
{
_PowerIsOn = false;
_PowerIsOn = false;
IrPort.Pulse(IROutputStandardCommands.IROut_POWER, IrPulseTime);
}
@@ -160,25 +176,25 @@ namespace PepperDash.Essentials.Devices.Common.Displays
#region IBasicVolumeControls Members
/// <summary>
/// VolumeUp method
/// </summary>
/// <summary>
/// VolumeUp method
/// </summary>
public void VolumeUp(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_VOL_PLUS, pressRelease);
}
/// <summary>
/// VolumeDown method
/// </summary>
/// <summary>
/// VolumeDown method
/// </summary>
public void VolumeDown(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_VOL_MINUS, pressRelease);
}
/// <summary>
/// MuteToggle method
/// </summary>
/// <summary>
/// MuteToggle method
/// </summary>
public void MuteToggle()
{
IrPort.Pulse(IROutputStandardCommands.IROut_MUTE, 200);
@@ -190,7 +206,8 @@ namespace PepperDash.Essentials.Devices.Common.Displays
{
_IsWarmingUp = true;
IsWarmingUpFeedback.FireUpdate();
new CTimer(o => {
new CTimer(o =>
{
_IsWarmingUp = false;
IsWarmingUpFeedback.FireUpdate();
}, 10000);
@@ -213,13 +230,13 @@ namespace PepperDash.Essentials.Devices.Common.Displays
/// Typically called by the discovery routing algorithm.
/// </summary>
/// <param name="inputSelector">A delegate containing the input selector method to call</param>
/// <summary>
/// ExecuteSwitch method
/// </summary>
/// <inheritdoc />
/// <summary>
/// ExecuteSwitch method
/// </summary>
/// <inheritdoc />
public override void ExecuteSwitch(object inputSelector)
{
Debug.LogMessage(LogEventLevel.Verbose, this, "Switching to input '{0}'", (inputSelector as Action).ToString());
Debug.LogMessage(LogEventLevel.Verbose, this, "Switching to input '{0}'", (inputSelector as Action).ToString());
Action finishSwitch = () =>
{
@@ -246,42 +263,45 @@ namespace PepperDash.Essentials.Devices.Common.Displays
#endregion
/// <summary>
/// LinkToApi method
/// </summary>
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge);
}
/// <summary>
/// LinkToApi method
/// </summary>
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge);
}
}
/// <summary>
/// Represents a BasicIrDisplayFactory
/// </summary>
public class BasicIrDisplayFactory : EssentialsDeviceFactory<BasicIrDisplay>
{
public BasicIrDisplayFactory()
{
TypeNames = new List<string>() { "basicirdisplay" };
}
/// <summary>
/// Represents a BasicIrDisplayFactory
/// </summary>
public class BasicIrDisplayFactory : EssentialsDeviceFactory<BasicIrDisplay>
{
/// <summary>
/// Initializes a new instance of the BasicIrDisplayFactory class
/// </summary>
public BasicIrDisplayFactory()
{
TypeNames = new List<string>() { "basicirdisplay" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new BasicIrDisplay Device");
var ir = IRPortHelper.GetIrPort(dc.Properties);
if (ir != null)
{
var display = new BasicIrDisplay(dc.Key, dc.Name, ir.Port, ir.FileName);
display.IrPulseTime = 200; // Set default pulse time for IR commands.
return display;
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new BasicIrDisplay Device");
var ir = IRPortHelper.GetIrPort(dc.Properties);
if (ir != null)
{
var display = new BasicIrDisplay(dc.Key, dc.Name, ir.Port, ir.FileName);
display.IrPulseTime = 200; // Set default pulse time for IR commands.
return display;
}
return null;
}
}
return null;
}
}
}

View File

@@ -19,7 +19,7 @@ namespace PepperDash.Essentials.Devices.Common.Displays
/// Abstract base class for display devices that provides common display functionality
/// including power control, input switching, and routing capabilities.
/// </summary>
public abstract class DisplayBase : EssentialsDevice, IDisplay, ICurrentSources
public abstract class DisplayBase : EssentialsDevice, IDisplay, ICurrentSources, IHasFeedback
{
private RoutingInputPort _currentInputPort;
@@ -73,13 +73,11 @@ namespace PepperDash.Essentials.Devices.Common.Displays
var handler = CurrentSourceChange;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.WillChange);
handler?.Invoke(_CurrentSourceInfo, ChangeType.WillChange);
_CurrentSourceInfo = value;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.DidChange);
handler?.Invoke(_CurrentSourceInfo, ChangeType.DidChange);
}
}
SourceListItem _CurrentSourceInfo;
@@ -160,6 +158,9 @@ namespace PepperDash.Essentials.Devices.Common.Displays
IsCoolingDownFeedback = new BoolFeedback("IsCoolingDown", IsCoolingDownFeedbackFunc);
IsWarmingUpFeedback = new BoolFeedback("IsWarmingUp", IsWarmingUpFeedbackFunc);
Feedbacks.Add(IsCoolingDownFeedback);
Feedbacks.Add(IsWarmingUpFeedback);
InputPorts = new RoutingPortCollection<RoutingInputPort>();
CurrentSources = new Dictionary<eRoutingSignalType, SourceListItem>
@@ -194,17 +195,8 @@ namespace PepperDash.Essentials.Devices.Common.Displays
/// Gets the collection of feedback objects for this display device.
/// </summary>
/// <inheritdoc />
public virtual FeedbackCollection<Feedback> Feedbacks
{
get
{
return new FeedbackCollection<Feedback>
{
IsCoolingDownFeedback,
IsWarmingUpFeedback
};
}
}
public virtual FeedbackCollection<Feedback> Feedbacks { get; private set; } = new FeedbackCollection<Feedback>();
/// <summary>
/// Executes a switch to the specified input on the display device. Must be implemented by derived classes.
@@ -252,47 +244,35 @@ namespace PepperDash.Essentials.Devices.Common.Displays
/// <param name="joinMap">The join map configuration for the device.</param>
protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, DisplayControllerJoinMap joinMap)
{
Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.LogMessage(LogEventLevel.Information, "Linking to Display: {0}", displayDevice.Name);
this.LogDebug("Linking to Trilist {ipId}", trilist.ID.ToString("X"));
this.LogDebug("Linking to Display: {displayName}", displayDevice.Name);
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = displayDevice.Name;
var commMonitor = displayDevice as ICommunicationMonitor;
if (commMonitor != null)
if (displayDevice is ICommunicationMonitor commMonitor)
{
commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
}
// TODO: revisit this as there could be issues with this approach
var inputNumber = 0;
var inputKeys = new List<string>();
var inputNumberFeedback = new IntFeedback(() => inputNumber);
var inputNumberFeedback = new IntFeedback("inputNumber", () => inputNumber);
// Two way feedbacks
var twoWayDisplay = displayDevice as TwoWayDisplayBase;
// Add input number feedback to the device feedback collection to keep it around...
Feedbacks.Add(inputNumberFeedback);
if (twoWayDisplay != null)
// Two way feedbacks
if (displayDevice is TwoWayDisplayBase twoWayDisplay)
{
trilist.SetBool(joinMap.IsTwoWayDisplay.JoinNumber, true);
twoWayDisplay.CurrentInputFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Information, "CurrentInputFeedback_OutputChange {0}", a.StringValue);
twoWayDisplay.CurrentInputFeedback.OutputChange += (o, a) => this.LogDebug("CurrentInputFeedback_OutputChange {input}", a.StringValue);
inputNumberFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputSelect.JoinNumber]);
}
// Power Off
trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () =>
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOff();
});
var twoWayDisplayDevice = displayDevice as TwoWayDisplayBase;
if (twoWayDisplayDevice != null)
{
twoWayDisplayDevice.PowerIsOnFeedback.OutputChange += (o, a) =>
twoWayDisplay.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (!a.BoolValue)
{
@@ -307,10 +287,18 @@ namespace PepperDash.Essentials.Devices.Common.Displays
}
};
twoWayDisplayDevice.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]);
twoWayDisplayDevice.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]);
twoWayDisplay.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]);
twoWayDisplay.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]);
}
// Power Off
trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () =>
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOff();
});
// PowerOn
trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () =>
{
@@ -320,44 +308,61 @@ namespace PepperDash.Essentials.Devices.Common.Displays
});
for (int i = 0; i < displayDevice.InputPorts.Count; i++)
{
if (i < joinMap.InputNamesOffset.JoinSpan)
var localindex = i;
if (localindex >= joinMap.InputNamesOffset.JoinSpan)
{
inputKeys.Add(displayDevice.InputPorts[i].Key);
var tempKey = inputKeys.ElementAt(i);
trilist.SetSigTrueAction((ushort)(joinMap.InputSelectOffset.JoinNumber + i),
() => displayDevice.ExecuteSwitch(displayDevice.InputPorts[tempKey].Selector));
Debug.LogMessage(LogEventLevel.Verbose, displayDevice, "Setting Input Select Action on Digital Join {0} to Input: {1}",
joinMap.InputSelectOffset.JoinNumber + i, displayDevice.InputPorts[tempKey].Key.ToString());
trilist.StringInput[(ushort)(joinMap.InputNamesOffset.JoinNumber + i)].StringValue = displayDevice.InputPorts[i].Key.ToString();
this.LogWarning("Device has {inputCount} inputs. The Join Map allows up to {joinSpan} inputs. Discarding inputs {discardStart} - {discardEnd} from bridge.",
displayDevice.InputPorts.Count, joinMap.InputNamesOffset.JoinSpan, localindex + 1, displayDevice.InputPorts.Count);
continue;
}
else
Debug.LogMessage(LogEventLevel.Information, displayDevice, "Device has {0} inputs. The Join Map allows up to {1} inputs. Discarding inputs {2} - {3} from bridge.",
displayDevice.InputPorts.Count, joinMap.InputNamesOffset.JoinSpan, i + 1, displayDevice.InputPorts.Count);
{
inputKeys.Add(displayDevice.InputPorts[localindex].Key);
var tempKey = inputKeys.ElementAt(localindex);
trilist.SetSigTrueAction((ushort)(joinMap.InputSelectOffset.JoinNumber + localindex), () => displayDevice.ExecuteSwitch(displayDevice.InputPorts[tempKey].Selector));
this.LogDebug("Setting Input Select Action on Digital Join {joinNumber} to Input: {input}", joinMap.InputSelectOffset.JoinNumber + localindex, displayDevice.InputPorts[tempKey].Key);
trilist.SetString((uint)(joinMap.InputNamesOffset.JoinNumber + localindex), displayDevice.InputPorts[localindex].Key);
}
}
Debug.LogMessage(LogEventLevel.Verbose, displayDevice, "Setting Input Select Action on Analog Join {0}", joinMap.InputSelect);
trilist.SetUShortSigAction(joinMap.InputSelect.JoinNumber, (a) =>
this.LogDebug("Setting Input Select Action on Analog Join {inputSelectJoin}", joinMap.InputSelect);
trilist.SetUShortSigAction(joinMap.InputSelect.JoinNumber, (requestedInput) =>
{
if (a == 0)
if (requestedInput == 0)
{
displayDevice.PowerOff();
inputNumber = 0;
return;
}
else if (a > 0 && a < displayDevice.InputPorts.Count && a != inputNumber)
// using 1-based indexing for inputs coming from SIMPL, so need to check if the input is <= the count, not <
if (requestedInput > 0 && requestedInput <= displayDevice.InputPorts.Count && requestedInput != inputNumber)
{
displayDevice.ExecuteSwitch(displayDevice.InputPorts.ElementAt(a - 1).Selector);
inputNumber = a;
displayDevice.ExecuteSwitch(displayDevice.InputPorts.ElementAt(requestedInput - 1).Selector);
inputNumber = requestedInput;
return;
}
else if (a == 102)
if (requestedInput == 102)
{
displayDevice.PowerToggle();
return;
}
if (displayDevice is TwoWayDisplayBase)
{
inputNumberFeedback?.FireUpdate();
}
if (twoWayDisplay != null)
inputNumberFeedback.FireUpdate();
});
@@ -430,95 +435,4 @@ namespace PepperDash.Essentials.Devices.Common.Displays
}
}
/// <summary>
/// Abstract base class for two-way display devices that provide feedback capabilities.
/// Extends DisplayBase with routing feedback and power control feedback functionality.
/// </summary>
public abstract class TwoWayDisplayBase : DisplayBase, IRoutingFeedback, IHasPowerControlWithFeedback
{
/// <summary>
/// Gets feedback for the current input selection on the display.
/// </summary>
public StringFeedback CurrentInputFeedback { get; private set; }
/// <summary>
/// Abstract function that must be implemented by derived classes to provide the current input feedback value.
/// Must be implemented by concrete sub-classes.
/// </summary>
abstract protected Func<string> CurrentInputFeedbackFunc { get; }
/// <summary>
/// Gets feedback indicating whether the display is currently powered on.
/// </summary>
public BoolFeedback PowerIsOnFeedback { get; protected set; }
/// <summary>
/// Abstract function that must be implemented by derived classes to provide the power state feedback value.
/// Must be implemented by concrete sub-classes.
/// </summary>
abstract protected Func<bool> PowerIsOnFeedbackFunc { get; }
/// <summary>
/// Gets the default mock display instance for testing and development purposes.
/// </summary>
public static MockDisplay DefaultDisplay
{
get
{
if (_DefaultDisplay == null)
_DefaultDisplay = new MockDisplay("default", "Default Display");
return _DefaultDisplay;
}
}
static MockDisplay _DefaultDisplay;
/// <summary>
/// Initializes a new instance of the TwoWayDisplayBase class.
/// </summary>
/// <param name="key">The unique key identifier for this display device.</param>
/// <param name="name">The friendly name for this display device.</param>
public TwoWayDisplayBase(string key, string name)
: base(key, name)
{
CurrentInputFeedback = new StringFeedback(CurrentInputFeedbackFunc);
WarmupTime = 7000;
CooldownTime = 15000;
PowerIsOnFeedback = new BoolFeedback("PowerOnFeedback", PowerIsOnFeedbackFunc);
Feedbacks.Add(CurrentInputFeedback);
Feedbacks.Add(PowerIsOnFeedback);
PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange;
}
void PowerIsOnFeedback_OutputChange(object sender, EventArgs e)
{
if (UsageTracker != null)
{
if (PowerIsOnFeedback.BoolValue)
UsageTracker.StartDeviceUsage();
else
UsageTracker.EndDeviceUsage();
}
}
/// <summary>
/// Event that is raised when a numeric switch change occurs on the display.
/// </summary>
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
protected void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
}
}

View File

@@ -1,38 +1,89 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Displays
{
/// <summary>
/// Defines the contract for IInputHdmi1
/// </summary>
public interface IInputHdmi1 { void InputHdmi1(); }
[Obsolete()]
public interface IInputHdmi1
{
/// <summary>
/// Switches to HDMI 1 input
/// </summary>
void InputHdmi1();
}
/// <summary>
/// Defines the contract for IInputHdmi2
/// </summary>
public interface IInputHdmi2 { void InputHdmi2(); }
[Obsolete()]
public interface IInputHdmi2
{
/// <summary>
/// Switches to HDMI 2 input
/// </summary>
void InputHdmi2();
}
/// <summary>
/// Defines the contract for IInputHdmi3
/// </summary>
public interface IInputHdmi3 { void InputHdmi3(); }
[Obsolete()]
public interface IInputHdmi3
{
/// <summary>
/// Switches to HDMI 3 input
/// </summary>
void InputHdmi3();
}
/// <summary>
/// Defines the contract for IInputHdmi4
/// </summary>
public interface IInputHdmi4 { void InputHdmi4(); }
[Obsolete()]
public interface IInputHdmi4
{
/// <summary>
/// Switches to HDMI 4 input
/// </summary>
void InputHdmi4();
}
/// <summary>
/// Defines the contract for IInputDisplayPort1
/// </summary>
public interface IInputDisplayPort1 { void InputDisplayPort1(); }
[Obsolete()]
public interface IInputDisplayPort1
{
/// <summary>
/// Switches to DisplayPort 1 input
/// </summary>
void InputDisplayPort1();
}
/// <summary>
/// Defines the contract for IInputDisplayPort2
/// </summary>
public interface IInputDisplayPort2 { void InputDisplayPort2(); }
[Obsolete()]
public interface IInputDisplayPort2
{
/// <summary>
/// Switches to DisplayPort 2 input
/// </summary>
void InputDisplayPort2();
}
/// <summary>
/// Defines the contract for IInputVga1
/// </summary>
public interface IInputVga1 { void InputVga1(); }
[Obsolete()]
public interface IInputVga1
{
/// <summary>
/// Switches to VGA 1 input
/// </summary>
void InputVga1();
}
}

View File

@@ -16,16 +16,19 @@ namespace PepperDash.Essentials.Devices.Common.Displays
/// Represents a MockDisplay
/// </summary>
public class MockDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, IBridgeAdvanced, IHasInputs<string>, IRoutingSinkWithSwitchingWithInputPort, IHasPowerControlWithFeedback
{
{
/// <summary>
/// Gets or sets the Inputs
/// </summary>
public ISelectableItems<string> Inputs { get; private set; }
bool _PowerIsOn;
bool _IsWarmingUp;
bool _IsCoolingDown;
bool _PowerIsOn;
bool _IsWarmingUp;
bool _IsCoolingDown;
/// <summary>
/// Gets the power is on feedback function
/// </summary>
protected override Func<bool> PowerIsOnFeedbackFunc
{
get
@@ -34,8 +37,12 @@ namespace PepperDash.Essentials.Devices.Common.Displays
{
return _PowerIsOn;
};
} }
protected override Func<bool> IsCoolingDownFeedbackFunc
}
}
/// <summary>
/// Gets the is cooling down feedback function
/// </summary>
protected override Func<bool> IsCoolingDownFeedbackFunc
{
get
{
@@ -45,7 +52,10 @@ namespace PepperDash.Essentials.Devices.Common.Displays
};
}
}
protected override Func<bool> IsWarmingUpFeedbackFunc
/// <summary>
/// Gets the is warming up feedback function
/// </summary>
protected override Func<bool> IsWarmingUpFeedbackFunc
{
get
{
@@ -55,120 +65,128 @@ namespace PepperDash.Essentials.Devices.Common.Displays
};
}
}
/// <summary>
/// Gets the current input feedback function
/// </summary>
protected override Func<string> CurrentInputFeedbackFunc { get { return () => Inputs.CurrentItem; } }
int VolumeHeldRepeatInterval = 200;
ushort VolumeInterval = 655;
ushort _FakeVolumeLevel = 31768;
bool _IsMuted;
ushort _FakeVolumeLevel = 31768;
bool _IsMuted;
public MockDisplay(string key, string name)
: base(key, name)
{
/// <summary>
/// Initializes a new instance of the MockDisplay class
/// </summary>
/// <param name="key">The device key</param>
/// <param name="name">The device name</param>
public MockDisplay(string key, string name)
: base(key, name)
{
Inputs = new MockDisplayInputs
{
Items = new Dictionary<string, ISelectableItem>
{
{ "HDMI1", new MockDisplayInput ( "HDMI1", "HDMI 1",this ) },
{ "HDMI2", new MockDisplayInput ("HDMI2", "HDMI 2",this ) },
{ "HDMI3", new MockDisplayInput ("HDMI3", "HDMI 3",this ) },
{ "HDMI4", new MockDisplayInput ("HDMI4", "HDMI 4",this )},
{ "DP", new MockDisplayInput ("DP", "DisplayPort", this ) }
}
{
{ "HDMI1", new MockDisplayInput ( "HDMI1", "HDMI 1",this ) },
{ "HDMI2", new MockDisplayInput ("HDMI2", "HDMI 2",this ) },
{ "HDMI3", new MockDisplayInput ("HDMI3", "HDMI 3",this ) },
{ "HDMI4", new MockDisplayInput ("HDMI4", "HDMI 4",this )},
{ "DP", new MockDisplayInput ("DP", "DisplayPort", this ) }
}
};
Inputs.CurrentItemChanged += (o, a) => CurrentInputFeedback.FireUpdate();
var hdmiIn1 = new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, "HDMI1", this);
var hdmiIn2 = new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, "HDMI2", this);
var hdmiIn3 = new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, "HDMI3", this);
var hdmiIn4 = new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, "HDMI4", this);
var dpIn = new RoutingInputPort(RoutingPortNames.DisplayPortIn, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.DisplayPort, "DP", this);
InputPorts.AddRange(new[] { hdmiIn1, hdmiIn2, hdmiIn3, hdmiIn4, dpIn });
Inputs.CurrentItemChanged += (o, a) => CurrentInputFeedback.FireUpdate();
VolumeLevelFeedback = new IntFeedback(() => { return _FakeVolumeLevel; });
MuteFeedback = new BoolFeedback("MuteOn", () => _IsMuted);
var hdmiIn1 = new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, "HDMI1", this);
var hdmiIn2 = new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, "HDMI2", this);
var hdmiIn3 = new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, "HDMI3", this);
var hdmiIn4 = new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, "HDMI4", this);
var dpIn = new RoutingInputPort(RoutingPortNames.DisplayPortIn, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.DisplayPort, "DP", this);
InputPorts.AddRange(new[] { hdmiIn1, hdmiIn2, hdmiIn3, hdmiIn4, dpIn });
VolumeLevelFeedback = new IntFeedback("volume", () => { return _FakeVolumeLevel; });
MuteFeedback = new BoolFeedback("muteOn", () => _IsMuted);
WarmupTime = 10000;
CooldownTime = 10000;
}
}
/// <summary>
/// PowerOn method
/// </summary>
/// <inheritdoc />
public override void PowerOn()
{
if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
{
_IsWarmingUp = true;
IsWarmingUpFeedback.InvokeFireUpdate();
// Fake power-up cycle
WarmupTimer = new CTimer(o =>
{
_IsWarmingUp = false;
_PowerIsOn = true;
IsWarmingUpFeedback.InvokeFireUpdate();
PowerIsOnFeedback.InvokeFireUpdate();
}, WarmupTime);
}
}
/// <summary>
/// PowerOn method
/// </summary>
/// <inheritdoc />
public override void PowerOn()
{
if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
{
_IsWarmingUp = true;
IsWarmingUpFeedback.InvokeFireUpdate();
// Fake power-up cycle
WarmupTimer = new CTimer(o =>
{
_IsWarmingUp = false;
_PowerIsOn = true;
IsWarmingUpFeedback.InvokeFireUpdate();
PowerIsOnFeedback.InvokeFireUpdate();
}, WarmupTime);
}
}
/// <summary>
/// PowerOff method
/// </summary>
/// <inheritdoc />
public override void PowerOff()
{
// If a display has unreliable-power off feedback, just override this and
// remove this check.
if (PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
{
_IsCoolingDown = true;
IsCoolingDownFeedback.InvokeFireUpdate();
// Fake cool-down cycle
CooldownTimer = new CTimer(o =>
{
Debug.LogMessage(LogEventLevel.Verbose, "Cooldown timer ending", this);
_IsCoolingDown = false;
IsCoolingDownFeedback.InvokeFireUpdate();
/// <summary>
/// PowerOff method
/// </summary>
/// <inheritdoc />
public override void PowerOff()
{
// If a display has unreliable-power off feedback, just override this and
// remove this check.
if (PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
{
_IsCoolingDown = true;
IsCoolingDownFeedback.InvokeFireUpdate();
// Fake cool-down cycle
CooldownTimer = new CTimer(o =>
{
Debug.LogMessage(LogEventLevel.Verbose, "Cooldown timer ending", this);
_IsCoolingDown = false;
IsCoolingDownFeedback.InvokeFireUpdate();
_PowerIsOn = false;
PowerIsOnFeedback.InvokeFireUpdate();
}, CooldownTime);
}
}
/// <summary>
/// PowerToggle method
/// </summary>
/// <inheritdoc />
public override void PowerToggle()
{
if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue)
PowerOff();
else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue)
PowerOn();
}
}, CooldownTime);
}
}
/// <summary>
/// ExecuteSwitch method
/// </summary>
/// <inheritdoc />
public override void ExecuteSwitch(object selector)
{
/// <summary>
/// PowerToggle method
/// </summary>
/// <inheritdoc />
public override void PowerToggle()
{
if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue)
PowerOff();
else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue)
PowerOn();
}
/// <summary>
/// ExecuteSwitch method
/// </summary>
/// <inheritdoc />
public override void ExecuteSwitch(object selector)
{
try
{
Debug.LogMessage(LogEventLevel.Verbose, "ExecuteSwitch: {0}", this, selector);
if (!_PowerIsOn)
{
PowerOn();
}
if (!_PowerIsOn)
{
PowerOn();
}
if (!Inputs.Items.TryGetValue(selector.ToString(), out var input))
return;
@@ -184,13 +202,14 @@ namespace PepperDash.Essentials.Devices.Common.Displays
if (inputPort == null)
{
Debug.LogMessage(LogEventLevel.Verbose, "Unable to find input port for selector {selector}", this, selector);
Debug.LogMessage(LogEventLevel.Verbose, "Unable to find input port for selector {selector}", this, selector);
return;
}
Debug.LogMessage(LogEventLevel.Verbose, "Setting current input port to {inputPort}", this, inputPort);
CurrentInputPort = inputPort;
} catch (Exception ex)
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Error making switch: {Exception}", this, ex);
}
@@ -201,14 +220,14 @@ namespace PepperDash.Essentials.Devices.Common.Displays
/// </summary>
public void SetInput(string selector)
{
ISelectableItem currentInput = null;
ISelectableItem currentInput = null;
try
{
currentInput = Inputs.Items.SingleOrDefault(Inputs => Inputs.Value.IsSelected).Value;
}
catch { }
try
{
currentInput = Inputs.Items.SingleOrDefault(Inputs => Inputs.Value.IsSelected).Value;
}
catch { }
if (currentInput != null)
{
@@ -216,12 +235,12 @@ namespace PepperDash.Essentials.Devices.Common.Displays
currentInput.IsSelected = false;
}
if (!Inputs.Items.TryGetValue(selector, out var input))
if (!Inputs.Items.TryGetValue(selector, out var input))
return;
input.IsSelected = true;
input.IsSelected = true;
Inputs.CurrentItem = selector;
Inputs.CurrentItem = selector;
}
@@ -232,37 +251,37 @@ namespace PepperDash.Essentials.Devices.Common.Displays
/// </summary>
public IntFeedback VolumeLevelFeedback { get; private set; }
/// <summary>
/// SetVolume method
/// </summary>
public void SetVolume(ushort level)
{
_FakeVolumeLevel = level;
VolumeLevelFeedback.InvokeFireUpdate();
}
/// <summary>
/// SetVolume method
/// </summary>
public void SetVolume(ushort level)
{
_FakeVolumeLevel = level;
VolumeLevelFeedback.InvokeFireUpdate();
}
/// <summary>
/// MuteOn method
/// </summary>
public void MuteOn()
{
_IsMuted = true;
MuteFeedback.InvokeFireUpdate();
}
/// <summary>
/// MuteOn method
/// </summary>
public void MuteOn()
{
_IsMuted = true;
MuteFeedback.InvokeFireUpdate();
}
/// <summary>
/// MuteOff method
/// </summary>
public void MuteOff()
{
_IsMuted = false;
MuteFeedback.InvokeFireUpdate();
}
/// <summary>
/// MuteOff method
/// </summary>
public void MuteOff()
{
_IsMuted = false;
MuteFeedback.InvokeFireUpdate();
}
/// <summary>
/// Gets or sets the MuteFeedback
/// </summary>
public BoolFeedback MuteFeedback { get; private set; }
/// <summary>
/// Gets or sets the MuteFeedback
/// </summary>
public BoolFeedback MuteFeedback { get; private set; }
#endregion
@@ -273,74 +292,77 @@ namespace PepperDash.Essentials.Devices.Common.Displays
/// VolumeUp method
/// </summary>
public void VolumeUp(bool pressRelease)
{
{
//while (pressRelease)
//{
Debug.LogMessage(LogEventLevel.Verbose, this, "Volume Down {0}", pressRelease);
if (pressRelease)
{
var newLevel = _FakeVolumeLevel + VolumeInterval;
SetVolume((ushort)newLevel);
CrestronEnvironment.Sleep(VolumeHeldRepeatInterval);
}
Debug.LogMessage(LogEventLevel.Verbose, this, "Volume Down {0}", pressRelease);
if (pressRelease)
{
var newLevel = _FakeVolumeLevel + VolumeInterval;
SetVolume((ushort)newLevel);
CrestronEnvironment.Sleep(VolumeHeldRepeatInterval);
}
//}
}
}
/// <summary>
/// VolumeDown method
/// </summary>
public void VolumeDown(bool pressRelease)
{
/// <summary>
/// VolumeDown method
/// </summary>
public void VolumeDown(bool pressRelease)
{
//while (pressRelease)
//{
Debug.LogMessage(LogEventLevel.Verbose, this, "Volume Up {0}", pressRelease);
if (pressRelease)
{
var newLevel = _FakeVolumeLevel - VolumeInterval;
SetVolume((ushort)newLevel);
CrestronEnvironment.Sleep(VolumeHeldRepeatInterval);
}
Debug.LogMessage(LogEventLevel.Verbose, this, "Volume Up {0}", pressRelease);
if (pressRelease)
{
var newLevel = _FakeVolumeLevel - VolumeInterval;
SetVolume((ushort)newLevel);
CrestronEnvironment.Sleep(VolumeHeldRepeatInterval);
}
//}
}
}
/// <summary>
/// MuteToggle method
/// </summary>
public void MuteToggle()
{
_IsMuted = !_IsMuted;
MuteFeedback.InvokeFireUpdate();
}
/// <summary>
/// MuteToggle method
/// </summary>
public void MuteToggle()
{
_IsMuted = !_IsMuted;
MuteFeedback.InvokeFireUpdate();
}
#endregion
#endregion
/// <summary>
/// LinkToApi method
/// </summary>
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge);
}
/// <summary>
/// LinkToApi method
/// </summary>
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge);
}
}
/// <summary>
/// Represents a MockDisplayFactory
/// </summary>
public class MockDisplayFactory : EssentialsDeviceFactory<MockDisplay>
{
public MockDisplayFactory()
{
TypeNames = new List<string>() { "mockdisplay" , "mockdisplay2" };
}
/// <summary>
/// Represents a MockDisplayFactory
/// </summary>
public class MockDisplayFactory : EssentialsDeviceFactory<MockDisplay>
{
/// <summary>
/// Initializes a new instance of the MockDisplayFactory class
/// </summary>
public MockDisplayFactory()
{
TypeNames = new List<string>() { "mockdisplay", "mockdisplay2" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Mock Display Device");
return new MockDisplay(dc.Key, dc.Name);
}
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Mock Display Device");
return new MockDisplay(dc.Key, dc.Name);
}
}
}

View File

@@ -1,10 +1,6 @@
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials.Devices.Common.Displays
{
@@ -15,6 +11,9 @@ namespace PepperDash.Essentials.Devices.Common.Displays
{
private Dictionary<string, ISelectableItem> _items;
/// <summary>
/// Gets or sets the collection of selectable items
/// </summary>
public Dictionary<string, ISelectableItem> Items
{
get
@@ -34,8 +33,11 @@ namespace PepperDash.Essentials.Devices.Common.Displays
private string _currentItem;
/// <summary>
/// Gets or sets the currently selected item
/// </summary>
public string CurrentItem
{
{
get
{
return _currentItem;
@@ -51,7 +53,13 @@ namespace PepperDash.Essentials.Devices.Common.Displays
}
}
/// <summary>
/// Occurs when the items collection is updated
/// </summary>
public event EventHandler ItemsUpdated;
/// <summary>
/// Occurs when the current item changes
/// </summary>
public event EventHandler CurrentItemChanged;
}
@@ -63,7 +71,10 @@ namespace PepperDash.Essentials.Devices.Common.Displays
private MockDisplay _parent;
private bool _isSelected;
/// <summary>
/// Gets or sets a value indicating whether this input is selected
/// </summary>
public bool IsSelected
{
get
@@ -91,8 +102,17 @@ namespace PepperDash.Essentials.Devices.Common.Displays
/// </summary>
public string Key { get; set; }
/// <summary>
/// Occurs when this item is updated
/// </summary>
public event EventHandler ItemUpdated;
/// <summary>
/// Initializes a new instance of the MockDisplayInput class
/// </summary>
/// <param name="key">The input key</param>
/// <param name="name">The input name</param>
/// <param name="parent">The parent mock display</param>
public MockDisplayInput(string key, string name, MockDisplay parent)
{
Key = key;
@@ -107,7 +127,7 @@ namespace PepperDash.Essentials.Devices.Common.Displays
{
if (!_parent.PowerIsOnFeedback.BoolValue) _parent.PowerOn();
foreach(var input in _parent.Inputs.Items)
foreach (var input in _parent.Inputs.Items)
{
input.Value.IsSelected = input.Key == this.Key;
}

View File

@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.CrestronIO;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Devices.Common;
using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.Shades
@@ -28,6 +25,9 @@ namespace PepperDash.Essentials.Devices.Common.Shades
ISwitchedOutput LowerRelay;
ISwitchedOutput LatchedRelay;
/// <summary>
/// Gets or sets the InUpPosition
/// </summary>
public bool InUpPosition
{
get { return _isInUpPosition; }
@@ -41,10 +41,12 @@ namespace PepperDash.Essentials.Devices.Common.Shades
}
private bool _isInUpPosition { get; set; }
/// <summary>
/// Gets or sets the Type
/// </summary>
public eScreenLiftControlType Type { get; private set; }
/// <summary>
/// Gets or sets the Mode
/// </summary>
@@ -54,13 +56,20 @@ namespace PepperDash.Essentials.Devices.Common.Shades
/// Gets or sets the DisplayDeviceKey
/// </summary>
public string DisplayDeviceKey { get; private set; }
/// <summary>
/// Gets or sets the IsInUpPosition
/// </summary>
public BoolFeedback IsInUpPosition { get; private set; }
/// <summary>
/// Event that fires when the position changes
/// </summary>
public event EventHandler<EventArgs> PositionChanged;
/// <summary>
/// Constructor for ScreenLiftController
/// </summary>
public ScreenLiftController(string key, string name, ScreenLiftControllerConfigProperties config)
: base(key, name)
{
@@ -69,7 +78,7 @@ namespace PepperDash.Essentials.Devices.Common.Shades
Mode = Config.Mode;
Type = Config.Type;
IsInUpPosition = new BoolFeedback(() => _isInUpPosition);
IsInUpPosition = new BoolFeedback("isInUpPosition", () => _isInUpPosition);
switch (Mode)
{
@@ -206,14 +215,14 @@ namespace PepperDash.Essentials.Devices.Common.Shades
/// <summary>
/// Attempts to get the port on teh specified device from config
/// </summary>
/// <param name="relayConfig"></param>
/// <param name="relayKey"></param>
/// <returns></returns>
ISwitchedOutput GetSwitchedOutputFromDevice(string relayKey)
{
var portDevice = DeviceManager.GetDeviceForKey(relayKey);
if (portDevice != null)
{
return (portDevice as ISwitchedOutput);
return portDevice as ISwitchedOutput;
}
else
{
@@ -238,58 +247,14 @@ namespace PepperDash.Essentials.Devices.Common.Shades
}
/// <summary>
/// Represents a ScreenLiftControllerConfigProperties
/// </summary>
public class ScreenLiftControllerConfigProperties
{
[JsonProperty("displayDeviceKey")]
/// <summary>
/// Gets or sets the DisplayDeviceKey
/// </summary>
public string DisplayDeviceKey { get; set; }
[JsonProperty("type")]
[JsonConverter(typeof(StringEnumConverter))]
/// <summary>
/// Gets or sets the Type
/// </summary>
public eScreenLiftControlType Type { get; set; }
[JsonProperty("mode")]
[JsonConverter(typeof(StringEnumConverter))]
/// <summary>
/// Gets or sets the Mode
/// </summary>
public eScreenLiftControlMode Mode { get; set; }
[JsonProperty("relays")]
public Dictionary<string,ScreenLiftRelaysConfig> Relays { get; set; }
}
/// <summary>
/// Represents a ScreenLiftRelaysConfig
/// </summary>
public class ScreenLiftRelaysConfig
{
[JsonProperty("deviceKey")]
/// <summary>
/// Gets or sets the DeviceKey
/// </summary>
public string DeviceKey { get; set; }
[JsonProperty("pulseTimeInMs")]
/// <summary>
/// Gets or sets the PulseTimeInMs
/// </summary>
public int PulseTimeInMs { get; set; }
}
/// <summary>
/// Represents a ScreenLiftControllerFactory
/// </summary>
public class ScreenLiftControllerFactory : EssentialsDeviceFactory<RelayControlledShade>
{
/// <summary>
/// Constructor for ScreenLiftControllerFactory
/// </summary>
public ScreenLiftControllerFactory()
{
TypeNames = new List<string>() { "screenliftcontroller" };
@@ -307,13 +272,4 @@ namespace PepperDash.Essentials.Devices.Common.Shades
return new ScreenLiftController(dc.Key, dc.Name, props);
}
}
/// <summary>
/// Enumeration of eScreenLiftControlMode values
/// </summary>
public enum eScreenLiftControlMode
{
momentary,
latched
}
}

View File

@@ -0,0 +1,41 @@
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials.Devices.Common.Shades
{
/// <summary>
/// Represents a ScreenLiftControllerConfigProperties
/// </summary>
public class ScreenLiftControllerConfigProperties
{
/// <summary>
/// Gets or sets the DisplayDeviceKey
/// </summary>
[JsonProperty("displayDeviceKey")]
public string DisplayDeviceKey { get; set; }
/// <summary>
/// Gets or sets the Type
/// </summary>
[JsonProperty("type")]
[JsonConverter(typeof(StringEnumConverter))]
public eScreenLiftControlType Type { get; set; }
/// <summary>
/// Gets or sets the Mode
/// </summary>
[JsonProperty("mode")]
[JsonConverter(typeof(StringEnumConverter))]
public eScreenLiftControlMode Mode { get; set; }
/// <summary>
/// Gets or sets the Relays
/// </summary>
[JsonProperty("relays")]
public Dictionary<string, ScreenLiftRelaysConfig> Relays { get; set; }
}
}

View File

@@ -0,0 +1,22 @@
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.Shades
{
/// <summary>
/// Represents a ScreenLiftRelaysConfig
/// </summary>
public class ScreenLiftRelaysConfig
{
/// <summary>
/// Gets or sets the DeviceKey
/// </summary>
[JsonProperty("deviceKey")]
public string DeviceKey { get; set; }
/// <summary>
/// Gets or sets the PulseTimeInMs
/// </summary>
[JsonProperty("pulseTimeInMs")]
public int PulseTimeInMs { get; set; }
}
}

View File

@@ -0,0 +1,95 @@
using System;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.Displays
{
/// <summary>
/// Abstract base class for two-way display devices that provide feedback capabilities.
/// Extends DisplayBase with routing feedback and power control feedback functionality.
/// </summary>
public abstract class TwoWayDisplayBase : DisplayBase, IRoutingFeedback, IHasPowerControlWithFeedback
{
/// <summary>
/// Gets feedback for the current input selection on the display.
/// </summary>
public StringFeedback CurrentInputFeedback { get; private set; }
/// <summary>
/// Abstract function that must be implemented by derived classes to provide the current input feedback value.
/// Must be implemented by concrete sub-classes.
/// </summary>
abstract protected Func<string> CurrentInputFeedbackFunc { get; }
/// <summary>
/// Gets feedback indicating whether the display is currently powered on.
/// </summary>
public BoolFeedback PowerIsOnFeedback { get; protected set; }
/// <summary>
/// Abstract function that must be implemented by derived classes to provide the power state feedback value.
/// Must be implemented by concrete sub-classes.
/// </summary>
abstract protected Func<bool> PowerIsOnFeedbackFunc { get; }
/// <summary>
/// Gets the default mock display instance for testing and development purposes.
/// </summary>
public static MockDisplay DefaultDisplay
{
get
{
if (_DefaultDisplay == null)
_DefaultDisplay = new MockDisplay("default", "Default Display");
return _DefaultDisplay;
}
}
static MockDisplay _DefaultDisplay;
/// <summary>
/// Initializes a new instance of the TwoWayDisplayBase class.
/// </summary>
/// <param name="key">The unique key identifier for this display device.</param>
/// <param name="name">The friendly name for this display device.</param>
public TwoWayDisplayBase(string key, string name)
: base(key, name)
{
CurrentInputFeedback = new StringFeedback("currentInput", CurrentInputFeedbackFunc);
WarmupTime = 7000;
CooldownTime = 15000;
PowerIsOnFeedback = new BoolFeedback("PowerOnFeedback", PowerIsOnFeedbackFunc);
Feedbacks.Add(CurrentInputFeedback);
Feedbacks.Add(PowerIsOnFeedback);
PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange;
}
void PowerIsOnFeedback_OutputChange(object sender, EventArgs e)
{
if (UsageTracker != null)
{
if (PowerIsOnFeedback.BoolValue)
UsageTracker.StartDeviceUsage();
else
UsageTracker.EndDeviceUsage();
}
}
/// <summary>
/// Event that is raised when a numeric switch change occurs on the display.
/// </summary>
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
protected void OnSwitchChange(RoutingNumericEventArgs e)
{
NumericSwitchChange?.Invoke(this, e);
}
}
}

View File

@@ -0,0 +1,17 @@
namespace PepperDash.Essentials.Devices.Common.Shades
{
/// <summary>
/// Enumeration of eScreenLiftControlMode values
/// </summary>
public enum eScreenLiftControlMode
{
/// <summary>
/// Momentary control mode for screen lift
/// </summary>
momentary,
/// <summary>
/// Latched control mode for screen lift
/// </summary>
latched
}
}

View File

@@ -1,9 +1,8 @@
using PepperDash.Core;
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using Serilog.Events;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.Devices.Common.Generic
{
@@ -12,11 +11,16 @@ namespace PepperDash.Essentials.Devices.Common.Generic
/// </summary>
public class GenericSink : EssentialsDevice, IRoutingSinkWithInputPort
{
/// <summary>
/// Initializes a new instance of the GenericSink class
/// </summary>
/// <param name="key">The device key</param>
/// <param name="name">The device name</param>
public GenericSink(string key, string name) : base(key, name)
{
InputPorts = new RoutingPortCollection<RoutingInputPort>();
var inputPort = new RoutingInputPort(RoutingPortNames.AnyVideoIn, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this);
var inputPort = new RoutingInputPort(RoutingPortNames.AnyVideoIn, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this);
InputPorts.Add(inputPort);
}
@@ -35,10 +39,12 @@ namespace PepperDash.Essentials.Devices.Common.Generic
/// <summary>
/// Gets or sets the CurrentSourceInfo
/// </summary>
public SourceListItem CurrentSourceInfo {
public SourceListItem CurrentSourceInfo
{
get => _currentSource;
set {
if(value == _currentSource)
set
{
if (value == _currentSource)
{
return;
}
@@ -51,8 +57,14 @@ namespace PepperDash.Essentials.Devices.Common.Generic
}
}
/// <summary>
/// Gets the current input port
/// </summary>
public RoutingInputPort CurrentInputPort => InputPorts[0];
/// <summary>
/// Event fired when the current source changes
/// </summary>
public event SourceInfoChangeHandler CurrentSourceChange;
}
@@ -61,6 +73,9 @@ namespace PepperDash.Essentials.Devices.Common.Generic
/// </summary>
public class GenericSinkFactory : EssentialsDeviceFactory<GenericSink>
{
/// <summary>
/// Initializes a new instance of the GenericSinkFactory class
/// </summary>
public GenericSinkFactory()
{
TypeNames = new List<string>() { "genericsink", "genericdestination" };

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
@@ -13,38 +7,43 @@ using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common
{
/// <summary>
/// Represents a GenericSource
/// </summary>
public class GenericSource : EssentialsDevice, IUiDisplayInfo, IRoutingSource, IUsageTracking
{
/// <summary>
/// Represents a GenericSource
/// </summary>
public class GenericSource : EssentialsDevice, IUiDisplayInfo, IRoutingSource, IUsageTracking
{
/// <summary>
/// Gets or sets the DisplayUiType
/// </summary>
public uint DisplayUiType { get { return DisplayUiConstants.TypeNoControls; } }
/// <summary>
/// Gets or sets the DisplayUiType
/// </summary>
public uint DisplayUiType { get { return DisplayUiConstants.TypeNoControls; } }
/// <summary>
/// Initializes a new instance of the GenericSource class
/// </summary>
/// <param name="key">The device key</param>
/// <param name="name">The device name</param>
public GenericSource(string key, string name)
: base(key, name)
{
: base(key, name)
{
AnyOut = new RoutingOutputPort(RoutingPortNames.AnyOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this);
OutputPorts = new RoutingPortCollection<RoutingOutputPort> { AnyOut };
}
AnyOut = new RoutingOutputPort(RoutingPortNames.AnyOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this);
OutputPorts = new RoutingPortCollection<RoutingOutputPort> { AnyOut };
}
#region IRoutingOutputs Members
#region IRoutingOutputs Members
/// <summary>
/// Gets or sets the AnyOut
/// </summary>
public RoutingOutputPort AnyOut { get; private set; }
/// <summary>
/// Gets or sets the OutputPorts
/// </summary>
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
/// <summary>
/// Gets or sets the AnyOut
/// </summary>
public RoutingOutputPort AnyOut { get; private set; }
/// <summary>
/// Gets or sets the OutputPorts
/// </summary>
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
#endregion
#endregion
#region IUsageTracking Members
@@ -54,13 +53,16 @@ namespace PepperDash.Essentials.Devices.Common
public UsageTracking UsageTracker { get; set; }
#endregion
}
}
/// <summary>
/// Represents a GenericSourceFactory
/// </summary>
public class GenericSourceFactory : EssentialsDeviceFactory<GenericSource>
{
/// <summary>
/// Initializes a new instance of the GenericSourceFactory class
/// </summary>
public GenericSourceFactory()
{
TypeNames = new List<string>() { "genericsource" };

View File

@@ -3,9 +3,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json;
using PepperDash.Core;
@@ -16,134 +13,165 @@ using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.Lighting
{
public abstract class LightingBase : EssentialsBridgeableDevice, ILightingScenes
{
#region ILightingScenes Members
public event EventHandler<LightingSceneChangeEventArgs> LightingSceneChange;
/// <summary>
/// Gets or sets the LightingScenes
/// </summary>
public List<LightingScene> LightingScenes { get; protected set; }
/// <summary>
/// Gets or sets the CurrentLightingScene
/// </summary>
public LightingScene CurrentLightingScene { get; protected set; }
/// <summary>
/// Gets or sets the CurrentLightingSceneFeedback
/// Base class for lighting devices that support scenes
/// </summary>
public IntFeedback CurrentLightingSceneFeedback { get; protected set; }
public abstract class LightingBase : EssentialsBridgeableDevice, ILightingScenes
{
#region ILightingScenes Members
#endregion
/// <summary>
/// Event fired when lighting scene changes
/// </summary>
public event EventHandler<LightingSceneChangeEventArgs> LightingSceneChange;
protected LightingBase(string key, string name)
: base(key, name)
{
LightingScenes = new List<LightingScene>();
/// <summary>
/// Gets or sets the LightingScenes
/// </summary>
public List<LightingScene> LightingScenes { get; protected set; }
CurrentLightingScene = new LightingScene();
//CurrentLightingSceneFeedback = new IntFeedback(() => { return int.Parse(this.CurrentLightingScene.ID); });
}
/// <summary>
/// Gets or sets the CurrentLightingScene
/// </summary>
public LightingScene CurrentLightingScene { get; protected set; }
public abstract void SelectScene(LightingScene scene);
/// <summary>
/// Gets or sets the CurrentLightingSceneFeedback
/// </summary>
public IntFeedback CurrentLightingSceneFeedback { get; protected set; }
/// <summary>
/// SimulateSceneSelect method
/// </summary>
public void SimulateSceneSelect(string sceneName)
{
Debug.LogMessage(LogEventLevel.Debug, this, "Simulating selection of scene '{0}'", sceneName);
#endregion
var scene = LightingScenes.FirstOrDefault(s => s.Name.Equals(sceneName));
/// <summary>
/// Initializes a new instance of the LightingBase class
/// </summary>
/// <param name="key">The device key</param>
/// <param name="name">The device name</param>
protected LightingBase(string key, string name)
: base(key, name)
{
LightingScenes = new List<LightingScene>();
if (scene != null)
{
CurrentLightingScene = scene;
OnLightingSceneChange();
}
}
CurrentLightingScene = new LightingScene();
//CurrentLightingSceneFeedback = new IntFeedback(() => { return int.Parse(this.CurrentLightingScene.ID); });
}
/// <summary>
/// Sets the IsActive property on each scene and fires the LightingSceneChange event
/// </summary>
protected void OnLightingSceneChange()
{
foreach (var scene in LightingScenes)
{
if (scene == CurrentLightingScene)
scene.IsActive = true;
else
scene.IsActive = false;
}
LightingSceneChange?.Invoke(this, new LightingSceneChangeEventArgs(CurrentLightingScene));
}
/// <summary>
/// Selects the specified lighting scene
/// </summary>
/// <param name="scene">The lighting scene to select</param>
public abstract void SelectScene(LightingScene scene);
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart,
string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new GenericLightingJoinMap(joinStart);
/// <summary>
/// SimulateSceneSelect method
/// </summary>
public void SimulateSceneSelect(string sceneName)
{
Debug.LogMessage(LogEventLevel.Debug, this, "Simulating selection of scene '{0}'", sceneName);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
var scene = LightingScenes.FirstOrDefault(s => s.Name.Equals(sceneName));
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<GenericLightingJoinMap>(joinMapSerialized);
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
return LinkLightingToApi(lightingDevice, trilist, joinMap);
}
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, GenericLightingJoinMap joinMap)
if (scene != null)
{
Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
CurrentLightingScene = scene;
OnLightingSceneChange();
}
}
Debug.LogMessage(LogEventLevel.Information, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString());
/// <summary>
/// Sets the IsActive property on each scene and fires the LightingSceneChange event
/// </summary>
protected void OnLightingSceneChange()
{
foreach (var scene in LightingScenes)
{
if (scene == CurrentLightingScene)
scene.IsActive = true;
// GenericLighitng Actions & FeedBack
trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u]));
else
scene.IsActive = false;
}
LightingSceneChange?.Invoke(this, new LightingSceneChangeEventArgs(CurrentLightingScene));
}
var sceneIndex = 0;
/// <summary>
/// Links the lighting device to API with join map configuration
/// </summary>
/// <param name="lightingDevice">The lighting device to link</param>
/// <param name="trilist">The trilist to link to</param>
/// <param name="joinStart">The starting join number</param>
/// <param name="joinMapKey">The join map key</param>
/// <param name="bridge">The EISC API bridge</param>
/// <returns>The configured join map</returns>
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart,
string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new GenericLightingJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<GenericLightingJoinMap>(joinMapSerialized);
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
return LinkLightingToApi(lightingDevice, trilist, joinMap);
}
/// <summary>
/// Links the lighting device to API using an existing join map
/// </summary>
/// <param name="lightingDevice">The lighting device to link</param>
/// <param name="trilist">The trilist to link to</param>
/// <param name="joinMap">The join map to use</param>
/// <returns>The join map used for linking</returns>
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, GenericLightingJoinMap joinMap)
{
Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.LogMessage(LogEventLevel.Information, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString());
// GenericLighitng Actions & FeedBack
trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u]));
var sceneIndex = 0;
foreach (var scene in lightingDevice.LightingScenes)
{
var index = sceneIndex;
trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + index), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[index]));
scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)]);
trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name;
trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true;
sceneIndex++;
}
trilist.OnlineStatusChange += (sender, args) =>
{
if (!args.DeviceOnLine) return;
sceneIndex = 0;
foreach (var scene in lightingDevice.LightingScenes)
{
var index = sceneIndex;
trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + index), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[index]));
scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)]);
trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name;
trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true;
scene.IsActiveFeedback.FireUpdate();
sceneIndex++;
}
};
trilist.OnlineStatusChange += (sender, args) =>
{
if (!args.DeviceOnLine) return;
sceneIndex = 0;
foreach (var scene in lightingDevice.LightingScenes)
{
var index = sceneIndex;
trilist.StringInput[(uint) (joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name;
trilist.BooleanInput[(uint) (joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true;
scene.IsActiveFeedback.FireUpdate();
sceneIndex++;
}
};
return joinMap;
}
return joinMap;
}
}
}

View File

@@ -9,10 +9,20 @@ namespace PepperDash.Essentials.Devices.Common.Room
public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IHasDefaultDisplay, IHasCurrentVolumeControls, IRoomOccupancy,
IEmergency, IMicrophonePrivacy
{
/// <summary>
/// Gets whether to exclude this room from global functions
/// </summary>
bool ExcludeFromGlobalFunctions { get; }
/// <summary>
/// Runs the route action for the given routeKey and sourceListKey
/// </summary>
/// <param name="routeKey">The route key</param>
void RunRouteAction(string routeKey);
/// <summary>
/// Gets the PropertiesConfig
/// </summary>
EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; }
}
}

View File

@@ -12,18 +12,40 @@ namespace PepperDash.Essentials.Devices.Common.Room
public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback,
IRoomOccupancy, IEmergency, IMicrophonePrivacy
{
/// <summary>
/// Gets the PropertiesConfig
/// </summary>
EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; }
/// <summary>
/// Gets whether to exclude this room from global functions
/// </summary>
bool ExcludeFromGlobalFunctions { get; }
/// <summary>
/// Runs the route action for the given routeKey and sourceListKey
/// </summary>
/// <param name="routeKey">The route key</param>
void RunRouteAction(string routeKey);
/// <summary>
/// Gets the ScheduleSource
/// </summary>
IHasScheduleAwareness ScheduleSource { get; }
/// <summary>
/// Gets the InCallFeedback
/// </summary>
new BoolFeedback InCallFeedback { get; }
/// <summary>
/// Gets the PrivacyModeIsOnFeedback
/// </summary>
new BoolFeedback PrivacyModeIsOnFeedback { get; }
/// <summary>
/// Gets the DefaultCodecRouteString
/// </summary>
string DefaultCodecRouteString { get; }
}
}

View File

@@ -1,9 +1,4 @@
using PepperDash.Essentials.Room.Config;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PepperDash.Essentials.Devices.Common.Room
{
@@ -12,6 +7,9 @@ namespace PepperDash.Essentials.Devices.Common.Room
/// </summary>
public interface IEssentialsRoomPropertiesConfig
{
/// <summary>
/// Gets the PropertiesConfig
/// </summary>
EssentialsRoomPropertiesConfig PropertiesConfig { get; }
}
}

View File

@@ -1,9 +1,9 @@
using PepperDash.Essentials.Core;
using System.Collections.Generic;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Devices.Common.Displays;
using PepperDash.Essentials.Room.Config;
using System.Collections.Generic;
using TwoWayDisplayBase = PepperDash.Essentials.Devices.Common.Displays.TwoWayDisplayBase;
namespace PepperDash.Essentials.Devices.Common.Room
@@ -11,15 +11,31 @@ namespace PepperDash.Essentials.Devices.Common.Room
/// <summary>
/// Defines the contract for IEssentialsTechRoom
/// </summary>
public interface IEssentialsTechRoom:IEssentialsRoom, ITvPresetsProvider,IBridgeAdvanced,IRunDirectRouteAction
public interface IEssentialsTechRoom : IEssentialsRoom, ITvPresetsProvider, IBridgeAdvanced, IRunDirectRouteAction
{
/// <summary>
/// Gets the PropertiesConfig
/// </summary>
EssentialsTechRoomConfig PropertiesConfig { get; }
/// <summary>
/// Gets the Tuners
/// </summary>
Dictionary<string, IRSetTopBoxBase> Tuners { get; }
/// <summary>
/// Gets the Displays
/// </summary>
Dictionary<string, TwoWayDisplayBase> Displays { get; }
/// <summary>
/// Powers on the room
/// </summary>
void RoomPowerOn();
/// <summary>
/// Powers off the room
/// </summary>
void RoomPowerOff();
}
}

View File

@@ -0,0 +1,41 @@
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common
{
/// <summary>
/// Represents a IRSetTopBoxBaseFactory
/// </summary>
public class IRSetTopBoxBaseFactory : EssentialsDeviceFactory<IRSetTopBoxBase>
{
/// <summary>
/// Initializes a new instance of the <see cref="IRSetTopBoxBaseFactory"/> class
/// </summary>
public IRSetTopBoxBaseFactory()
{
TypeNames = new List<string>() { "settopbox" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new SetTopBox Device");
var irCont = IRPortHelper.GetIrOutputPortController(dc);
var config = dc.Properties.ToObject<SetTopBoxPropertiesConfig>();
var stb = new IRSetTopBoxBase(dc.Key, dc.Name, irCont, config);
var listName = dc.Properties.Value<string>("presetsList");
if (listName != null)
stb.LoadPresets(listName);
return stb;
}
}
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Core;
namespace PepperDash.Essentials.Devices.Common
{

View File

@@ -27,6 +27,12 @@ namespace PepperDash.Essentials.Devices.Common.Shades
/// </summary>
public string StopOrPresetButtonLabel { get; set; }
/// <summary>
/// Initializes a new instance of the RelayControlledShade class
/// </summary>
/// <param name="key">The device key</param>
/// <param name="name">The device name</param>
/// <param name="config">The relay controlled shade configuration</param>
public RelayControlledShade(string key, string name, RelayControlledShadeConfigProperties config)
: base(key, name)
{
@@ -157,6 +163,9 @@ namespace PepperDash.Essentials.Devices.Common.Shades
/// </summary>
public class RelayControlledShadeFactory : EssentialsDeviceFactory<RelayControlledShade>
{
/// <summary>
/// Initializes a new instance of the RelayControlledShadeFactory class
/// </summary>
public RelayControlledShadeFactory()
{
TypeNames = new List<string>() { "relaycontrolledshade" };

View File

@@ -1,10 +1,18 @@
using PepperDash.Essentials.Core.Shades;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Shades;
namespace PepperDash.Essentials.Devices.Common.Shades
{
/// <summary>
/// Base class for shade devices
/// </summary>
public abstract class ShadeBase : EssentialsDevice, IShadesOpenCloseStop
{
/// <summary>
/// Initializes a new instance of the ShadeBase class
/// </summary>
/// <param name="key">The device key</param>
/// <param name="name">The device name</param>
public ShadeBase(string key, string name)
: base(key, name)
{
@@ -13,8 +21,17 @@ namespace PepperDash.Essentials.Devices.Common.Shades
#region iShadesOpenClose Members
/// <summary>
/// Opens the shade
/// </summary>
public abstract void Open();
/// <summary>
/// Stops the shade
/// </summary>
public abstract void Stop();
/// <summary>
/// Closes the shade
/// </summary>
public abstract void Close();
#endregion

View File

@@ -14,8 +14,17 @@ namespace PepperDash.Essentials.Devices.Common.Shades
{
ShadeControllerConfigProperties Config;
/// <summary>
/// Gets the collection of shades controlled by this controller
/// </summary>
public List<IShadesOpenCloseStop> Shades { get; private set; }
/// <summary>
/// Initializes a new instance of the ShadeController class
/// </summary>
/// <param name="key">The device key</param>
/// <param name="name">The device name</param>
/// <param name="config">The shade controller configuration</param>
public ShadeController(string key, string name, ShadeControllerConfigProperties config)
: base(key, name)
{
@@ -76,6 +85,9 @@ namespace PepperDash.Essentials.Devices.Common.Shades
/// </summary>
public class ShadeControllerFactory : EssentialsDeviceFactory<ShadeController>
{
/// <summary>
/// Initializes a new instance of the ShadeControllerFactory class
/// </summary>
public ShadeControllerFactory()
{
TypeNames = new List<string>() { "shadecontroller" };

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using Crestron.SimplSharp;
using PepperDash.Core;
@@ -22,6 +21,9 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
/// </summary>
public RoutingInputPort AnyVideoIn { get; private set; }
/// <summary>
/// Gets the CurrentInputPort
/// </summary>
public RoutingInputPort CurrentInputPort => AnyVideoIn;
#region IRoutingInputs Members
@@ -33,6 +35,11 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
#endregion
/// <summary>
/// Initializes a new instance of the <see cref="BlueJeansPc"/> class
/// </summary>
/// <param name="key">The device key</param>
/// <param name="name">The device name</param>
public BlueJeansPc(string key, string name)
: base(key, name)
{
@@ -177,30 +184,12 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
}
SourceListItem _CurrentSourceInfo;
/// <summary>
/// Event fired when the current source changes
/// </summary>
public event SourceInfoChangeHandler CurrentSourceChange;
#endregion
}
/// <summary>
/// Represents a BlueJeansPcFactory
/// </summary>
public class BlueJeansPcFactory : EssentialsDeviceFactory<BlueJeansPc>
{
public BlueJeansPcFactory()
{
TypeNames = new List<string>() { "bluejeanspc" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new BlueJeansPc Device");
return new SoftCodec.BlueJeansPc(dc.Key, dc.Name);
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.SoftCodec
{
/// <summary>
/// Represents a BlueJeansPcFactory
/// </summary>
public class BlueJeansPcFactory : EssentialsDeviceFactory<BlueJeansPc>
{
/// <summary>
/// Initializes a new instance of the <see cref="BlueJeansPcFactory"/> class
/// </summary>
public BlueJeansPcFactory()
{
TypeNames = new List<string>() { "bluejeanspc" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new BlueJeansPc Device");
return new BlueJeansPc(dc.Key, dc.Name);
}
}
}

View File

@@ -1,10 +1,7 @@
using Newtonsoft.Json;
using System.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using Serilog.Events;
using System.Collections.Generic;
using System.Linq;
namespace PepperDash.Essentials.Devices.Common.SoftCodec
{
@@ -18,7 +15,8 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
/// <summary>
/// Gets or sets the CurrentInputPort
/// </summary>
public RoutingInputPort CurrentInputPort {
public RoutingInputPort CurrentInputPort
{
get => _currentInputPort;
set
{
@@ -28,19 +26,25 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
}
}
/// <summary>
/// Initializes a new instance of the <see cref="GenericSoftCodec"/> class
/// </summary>
/// <param name="key">The device key</param>
/// <param name="name">The device name</param>
/// <param name="props">The device properties</param>
public GenericSoftCodec(string key, string name, GenericSoftCodecProperties props) : base(key, name)
{
InputPorts = new RoutingPortCollection<RoutingInputPort>();
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
for(var i = 1; i <= props.OutputCount; i++)
for (var i = 1; i <= props.OutputCount; i++)
{
var outputPort = new RoutingOutputPort($"output{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this);
OutputPorts.Add(outputPort);
}
for(var i = 1; i<= props.ContentInputCount; i++)
for (var i = 1; i <= props.ContentInputCount; i++)
{
var inputPort = new RoutingInputPort($"contentInput{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, $"contentInput{i}", this);
@@ -52,7 +56,7 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
return;
}
for(var i = 1; i <=props.CameraInputCount; i++)
for (var i = 1; i <= props.CameraInputCount; i++)
{
var cameraPort = new RoutingInputPort($"cameraInput{i}", eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, $"cameraInput{i}", this);
@@ -72,7 +76,11 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
/// <summary>
/// Gets or sets the CurrentSourceInfoKey
/// </summary>
public string CurrentSourceInfoKey { get ; set; }
public string CurrentSourceInfoKey { get; set; }
/// <summary>
/// Gets or sets the CurrentSourceInfo
/// </summary>
public SourceListItem CurrentSourceInfo
{
get
@@ -97,7 +105,14 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
SourceListItem _CurrentSourceInfo;
/// <summary>
/// Event fired when the current source changes
/// </summary>
public event SourceInfoChangeHandler CurrentSourceChange;
/// <summary>
/// Event fired when the input changes
/// </summary>
public event InputChangedEventHandler InputChanged;
/// <summary>
@@ -107,7 +122,7 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
{
var inputPort = InputPorts.FirstOrDefault(p => p.Selector == inputSelector);
if(inputPort == null)
if (inputPort == null)
{
Debug.LogMessage(LogEventLevel.Warning, "No input port found for selector {inputSelector}", inputSelector);
return;
@@ -116,58 +131,4 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
CurrentInputPort = inputPort;
}
}
/// <summary>
/// Represents a GenericSoftCodecProperties
/// </summary>
public class GenericSoftCodecProperties
{
[JsonProperty("hasCameraInputs")]
/// <summary>
/// Gets or sets the HasCameraInputs
/// </summary>
public bool HasCameraInputs { get; set; }
[JsonProperty("cameraInputCount")]
/// <summary>
/// Gets or sets the CameraInputCount
/// </summary>
public int CameraInputCount { get; set; }
[JsonProperty("contentInputCount")]
/// <summary>
/// Gets or sets the ContentInputCount
/// </summary>
public int ContentInputCount { get; set; }
[JsonProperty("contentOutputCount")]
/// <summary>
/// Gets or sets the OutputCount
/// </summary>
public int OutputCount { get; set; }
}
/// <summary>
/// Represents a GenericSoftCodecFactory
/// </summary>
public class GenericSoftCodecFactory: EssentialsDeviceFactory<GenericSoftCodec>
{
public GenericSoftCodecFactory()
{
TypeNames = new List<string> { "genericsoftcodec" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Attempting to create new Generic SoftCodec Device");
var props = dc.Properties.ToObject<GenericSoftCodecProperties>();
return new GenericSoftCodec(dc.Key, dc.Name, props);
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.SoftCodec
{
/// <summary>
/// Represents a GenericSoftCodecFactory
/// </summary>
public class GenericSoftCodecFactory : EssentialsDeviceFactory<GenericSoftCodec>
{
/// <summary>
/// Initializes a new instance of the <see cref="GenericSoftCodecFactory"/> class
/// </summary>
public GenericSoftCodecFactory()
{
TypeNames = new List<string> { "genericsoftcodec" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Attempting to create new Generic SoftCodec Device");
var props = dc.Properties.ToObject<GenericSoftCodecProperties>();
return new GenericSoftCodec(dc.Key, dc.Name, props);
}
}
}

View File

@@ -0,0 +1,34 @@
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.SoftCodec
{
/// <summary>
/// Represents a GenericSoftCodecProperties
/// </summary>
public class GenericSoftCodecProperties
{
/// <summary>
/// Gets or sets the HasCameraInputs
/// </summary>
[JsonProperty("hasCameraInputs")]
public bool HasCameraInputs { get; set; }
/// <summary>
/// Gets or sets the CameraInputCount
/// </summary>
[JsonProperty("cameraInputCount")]
public int CameraInputCount { get; set; }
/// <summary>
/// Gets or sets the ContentInputCount
/// </summary>
[JsonProperty("contentInputCount")]
public int ContentInputCount { get; set; }
/// <summary>
/// Gets or sets the OutputCount
/// </summary>
[JsonProperty("contentOutputCount")]
public int OutputCount { get; set; }
}
}

View File

@@ -1,71 +1,74 @@
using System;
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using Serilog.Events;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.Sources
{
/// <summary>
/// Represents a InRoomPc
/// </summary>
public class InRoomPc : EssentialsDevice, IHasFeedback, IRoutingSource, IRoutingOutputs, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking
{
/// <summary>
/// Gets or sets the DisplayUiType
/// </summary>
public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } }
/// <summary>
/// Gets or sets the IconName
/// </summary>
public string IconName { get; set; }
/// <summary>
/// Gets or sets the HasPowerOnFeedback
/// </summary>
public BoolFeedback HasPowerOnFeedback { get; private set; }
/// <summary>
/// Represents a InRoomPc
/// </summary>
public class InRoomPc : EssentialsDevice, IHasFeedback, IRoutingSource, IRoutingOutputs, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking
{
/// <summary>
/// Gets or sets the DisplayUiType
/// </summary>
public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } }
/// <summary>
/// Gets or sets the IconName
/// </summary>
public string IconName { get; set; }
/// <summary>
/// Gets or sets the HasPowerOnFeedback
/// </summary>
public BoolFeedback HasPowerOnFeedback { get; private set; }
/// <summary>
/// Gets or sets the AnyVideoOut
/// </summary>
public RoutingOutputPort AnyVideoOut { get; private set; }
/// <summary>
/// Gets or sets the AnyVideoOut
/// </summary>
public RoutingOutputPort AnyVideoOut { get; private set; }
#region IRoutingOutputs Members
#region IRoutingOutputs Members
/// <summary>
/// Gets or sets the OutputPorts
/// </summary>
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
/// <summary>
/// Gets or sets the OutputPorts
/// </summary>
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
#endregion
#endregion
public InRoomPc(string key, string name)
: base(key, name)
{
IconName = "PC";
HasPowerOnFeedback = new BoolFeedback("HasPowerFeedback",
() => this.GetVideoStatuses() != VideoStatusOutputs.NoStatus);
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
OutputPorts.Add(AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.None, 0, this));
}
/// <summary>
/// Initializes a new instance of the <see cref="InRoomPc"/> class
/// </summary>
/// <param name="key"></param>
/// <param name="name"></param>
public InRoomPc(string key, string name)
: base(key, name)
{
IconName = "PC";
HasPowerOnFeedback = new BoolFeedback("HasPowerFeedback",
() => this.GetVideoStatuses() != VideoStatusOutputs.NoStatus);
#region IHasFeedback Members
OutputPorts = new RoutingPortCollection<RoutingOutputPort>
{
(AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.None, 0, this))
};
}
/// <summary>
/// Passes through the VideoStatuses list
/// </summary>
#region IHasFeedback Members
/// <summary>
/// Passes through the VideoStatuses list
/// </summary>
public FeedbackCollection<Feedback> Feedbacks
{
get
{
get
{
var newList = new FeedbackCollection<Feedback>();
newList.AddRange(this.GetVideoStatuses().ToList());
return newList;
}
}
}
#endregion
#endregion
#region IUsageTracking Members
@@ -75,27 +78,6 @@ namespace PepperDash.Essentials.Devices.Common.Sources
public UsageTracking UsageTracker { get; set; }
#endregion
}
/// <summary>
/// Represents a InRoomPcFactory
/// </summary>
public class InRoomPcFactory : EssentialsDeviceFactory<InRoomPc>
{
public InRoomPcFactory()
{
TypeNames = new List<string>() { "inroompc" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new InRoomPc Device");
return new InRoomPc(dc.Key, dc.Name);
}
}
}

View File

@@ -0,0 +1,33 @@
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.Sources
{
/// <summary>
/// Represents a InRoomPcFactory
/// </summary>
public class InRoomPcFactory : EssentialsDeviceFactory<InRoomPc>
{
/// <summary>
/// Initializes a new instance of the <see cref="InRoomPcFactory"/> class
/// </summary>
public InRoomPcFactory()
{
TypeNames = new List<string>() { "inroompc" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new InRoomPc Device");
return new InRoomPc(dc.Key, dc.Name);
}
}
}

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using Serilog.Events;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.Sources
{
@@ -11,54 +6,59 @@ namespace PepperDash.Essentials.Devices.Common.Sources
/// Represents a Laptop
/// </summary>
public class Laptop : EssentialsDevice, IHasFeedback, IRoutingSource, IRoutingOutputs, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking
{
/// <summary>
/// Gets or sets the DisplayUiType
/// </summary>
public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } }
/// <summary>
/// Gets or sets the IconName
/// </summary>
public string IconName { get; set; }
/// <summary>
/// Gets or sets the HasPowerOnFeedback
/// </summary>
public BoolFeedback HasPowerOnFeedback { get; private set; }
{
/// <summary>
/// Gets or sets the DisplayUiType
/// </summary>
public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } }
/// <summary>
/// Gets or sets the IconName
/// </summary>
public string IconName { get; set; }
/// <summary>
/// Gets or sets the HasPowerOnFeedback
/// </summary>
public BoolFeedback HasPowerOnFeedback { get; private set; }
/// <summary>
/// Gets or sets the AnyVideoOut
/// </summary>
public RoutingOutputPort AnyVideoOut { get; private set; }
/// <summary>
/// Gets or sets the AnyVideoOut
/// </summary>
public RoutingOutputPort AnyVideoOut { get; private set; }
#region IRoutingOutputs Members
#region IRoutingOutputs Members
/// <summary>
/// Gets or sets the OutputPorts
/// </summary>
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
/// <summary>
/// Gets or sets the OutputPorts
/// </summary>
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
#endregion
#endregion
public Laptop(string key, string name)
: base(key, name)
{
IconName = "Laptop";
/// <summary>
/// Initializes a new instance of the Laptop class
/// </summary>
/// <param name="key">The device key</param>
/// <param name="name">The device name</param>
public Laptop(string key, string name)
: base(key, name)
{
IconName = "Laptop";
HasPowerOnFeedback = new BoolFeedback("HasPowerFeedback",
() => this.GetVideoStatuses() != VideoStatusOutputs.NoStatus);
HasPowerOnFeedback = new BoolFeedback("HasPowerFeedback",
() => this.GetVideoStatuses() != VideoStatusOutputs.NoStatus);
OutputPorts = new RoutingPortCollection<RoutingOutputPort>
OutputPorts = new RoutingPortCollection<RoutingOutputPort>
{
(AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.None, 0, this))
};
}
}
#region IHasFeedback Members
#region IHasFeedback Members
/// <summary>
/// Passes through the VideoStatuses list
/// </summary>
/// <summary>
/// Passes through the VideoStatuses list
/// </summary>
public FeedbackCollection<Feedback> Feedbacks
{
get
@@ -69,7 +69,7 @@ namespace PepperDash.Essentials.Devices.Common.Sources
}
}
#endregion
#endregion
#region IUsageTracking Members
@@ -79,26 +79,5 @@ namespace PepperDash.Essentials.Devices.Common.Sources
public UsageTracking UsageTracker { get; set; }
#endregion
}
/// <summary>
/// Represents a LaptopFactory
/// </summary>
public class LaptopFactory : EssentialsDeviceFactory<Laptop>
{
public LaptopFactory()
{
TypeNames = new List<string>() { "laptop" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Laptop Device");
return new Laptop(dc.Key, dc.Name);
}
}
}

View File

@@ -0,0 +1,32 @@
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.Sources
{
/// <summary>
/// Represents a LaptopFactory
/// </summary>
public class LaptopFactory : EssentialsDeviceFactory<Laptop>
{
/// <summary>
/// Initializes a new instance of the <see cref="LaptopFactory"/> class
/// </summary>
public LaptopFactory()
{
TypeNames = new List<string>() { "laptop" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Laptop Device");
return new Laptop(dc.Key, dc.Name);
}
}
}

View File

@@ -1,60 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using System.Linq;
using System.Reflection;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Bridges;
using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common
{
/// <summary>
/// Represents a AppleTV
/// Wrapper class for an IR-Controlled AppleTV
/// </summary>
[Description("Wrapper class for an IR-Controlled AppleTV")]
/// <summary>
/// Represents a AppleTV
/// </summary>
public class AppleTV : EssentialsBridgeableDevice, IDPad, ITransport, IUiDisplayInfo, IRoutingSource, IRoutingOutputs
public class AppleTV : EssentialsBridgeableDevice, IDPad, ITransport, IUiDisplayInfo, IRoutingSource, IRoutingOutputs
{
/// <summary>
/// Gets or sets the IrPort
/// </summary>
/// <summary>
/// Gets or sets the IrPort
/// </summary>
public IrOutputPortController IrPort { get; private set; }
/// <summary>
/// Standard Driver Name
/// </summary>
public const string StandardDriverName = "Apple_AppleTV_4th_Gen_Essentials.ir";
/// <summary>
/// Gets or sets the DisplayUiType
/// </summary>
public uint DisplayUiType { get { return DisplayUiConstants.TypeAppleTv; } }
/// <summary>
/// Gets or sets the DisplayUiType
/// </summary>
public uint DisplayUiType { get { return DisplayUiConstants.TypeAppleTv; } }
public AppleTV(string key, string name, IrOutputPortController portCont)
: base(key, name)
{
IrPort = portCont;
DeviceManager.AddDevice(portCont);
/// <summary>
/// Initializes a new instance of the <see cref="AppleTV"/> class
/// </summary>
/// <param name="key">The device key</param>
/// <param name="name">The device name</param>
/// <param name="portCont">The IR output port controller</param>
public AppleTV(string key, string name, IrOutputPortController portCont)
: base(key, name)
{
IrPort = portCont;
DeviceManager.AddDevice(portCont);
HdmiOut = new RoutingOutputPort(RoutingPortNames.HdmiOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this);
AnyAudioOut = new RoutingOutputPort(RoutingPortNames.AnyAudioOut, eRoutingSignalType.Audio,
eRoutingPortConnectionType.DigitalAudio, null, this);
OutputPorts = new RoutingPortCollection<RoutingOutputPort> { HdmiOut, AnyAudioOut };
HdmiOut = new RoutingOutputPort(RoutingPortNames.HdmiOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this);
AnyAudioOut = new RoutingOutputPort(RoutingPortNames.AnyAudioOut, eRoutingSignalType.Audio,
eRoutingPortConnectionType.DigitalAudio, null, this);
OutputPorts = new RoutingPortCollection<RoutingOutputPort> { HdmiOut, AnyAudioOut };
PrintExpectedIrCommands();
}
}
/// <summary>
/// PrintExpectedIrCommands method
/// </summary>
public void PrintExpectedIrCommands()
{
var cmds = typeof (AppleTvIrCommands).GetFields(BindingFlags.Public | BindingFlags.Static);
var cmds = typeof(AppleTvIrCommands).GetFields(BindingFlags.Public | BindingFlags.Static);
foreach (var value in cmds.Select(cmd => cmd.GetValue(null)).OfType<string>())
{
@@ -64,151 +67,158 @@ namespace PepperDash.Essentials.Devices.Common
#region IDPad Members
/// <summary>
/// Up method
/// </summary>
public void Up(bool pressRelease)
{
IrPort.PressRelease(AppleTvIrCommands.Up, pressRelease);
}
/// <summary>
/// Up method
/// </summary>
public void Up(bool pressRelease)
{
IrPort.PressRelease(AppleTvIrCommands.Up, pressRelease);
}
/// <summary>
/// Down method
/// </summary>
public void Down(bool pressRelease)
{
IrPort.PressRelease(AppleTvIrCommands.Down, pressRelease);
}
/// <summary>
/// Down method
/// </summary>
public void Down(bool pressRelease)
{
IrPort.PressRelease(AppleTvIrCommands.Down, pressRelease);
}
/// <summary>
/// Left method
/// </summary>
public void Left(bool pressRelease)
{
IrPort.PressRelease(AppleTvIrCommands.Left, pressRelease);
}
/// <summary>
/// Left method
/// </summary>
public void Left(bool pressRelease)
{
IrPort.PressRelease(AppleTvIrCommands.Left, pressRelease);
}
/// <summary>
/// Right method
/// </summary>
public void Right(bool pressRelease)
{
IrPort.PressRelease(AppleTvIrCommands.Right, pressRelease);
}
/// <summary>
/// Right method
/// </summary>
public void Right(bool pressRelease)
{
IrPort.PressRelease(AppleTvIrCommands.Right, pressRelease);
}
/// <summary>
/// Select method
/// </summary>
public void Select(bool pressRelease)
{
IrPort.PressRelease(AppleTvIrCommands.Enter, pressRelease);
}
/// <summary>
/// Select method
/// </summary>
public void Select(bool pressRelease)
{
IrPort.PressRelease(AppleTvIrCommands.Enter, pressRelease);
}
/// <summary>
/// Menu method
/// </summary>
public void Menu(bool pressRelease)
{
IrPort.PressRelease(AppleTvIrCommands.Menu, pressRelease);
}
/// <summary>
/// Menu method
/// </summary>
public void Menu(bool pressRelease)
{
IrPort.PressRelease(AppleTvIrCommands.Menu, pressRelease);
}
/// <summary>
/// Exit method
/// </summary>
public void Exit(bool pressRelease)
{
/// <summary>
/// Exit method
/// </summary>
public void Exit(bool pressRelease)
{
}
}
#endregion
#endregion
#region ITransport Members
#region ITransport Members
/// <summary>
/// Play method
/// </summary>
public void Play(bool pressRelease)
{
IrPort.PressRelease(AppleTvIrCommands.PlayPause, pressRelease);
}
/// <summary>
/// Pause method
/// </summary>
public void Pause(bool pressRelease)
{
/// <summary>
/// Play method
/// </summary>
public void Play(bool pressRelease)
{
IrPort.PressRelease(AppleTvIrCommands.PlayPause, pressRelease);
}
}
/// <summary>
/// Not implemented
/// </summary>
/// <param name="pressRelease"></param>
/// <summary>
/// Rewind method
/// </summary>
public void Rewind(bool pressRelease)
{
}
/// <summary>
/// Pause method
/// </summary>
public void Pause(bool pressRelease)
{
IrPort.PressRelease(AppleTvIrCommands.PlayPause, pressRelease);
}
/// <summary>
/// Not implemented
/// </summary>
/// <param name="pressRelease"></param>
public void FFwd(bool pressRelease)
{
}
/// <summary>
/// Not implemented
/// </summary>
/// <param name="pressRelease"></param>
/// <summary>
/// Rewind method
/// </summary>
public void Rewind(bool pressRelease)
{
}
/// <summary>
/// Not implemented
/// </summary>
/// <param name="pressRelease"></param>
public void ChapMinus(bool pressRelease)
{
}
/// <summary>
/// Not implemented
/// </summary>
/// <param name="pressRelease"></param>
public void FFwd(bool pressRelease)
{
}
/// <summary>
/// Not implemented
/// </summary>
/// <param name="pressRelease"></param>
public void ChapPlus(bool pressRelease)
{
}
/// <summary>
/// Not implemented
/// </summary>
/// <param name="pressRelease"></param>
public void ChapMinus(bool pressRelease)
{
}
/// <summary>
/// Not implemented
/// </summary>
/// <param name="pressRelease"></param>
public void Stop(bool pressRelease)
{
}
/// <summary>
/// Not implemented
/// </summary>
/// <param name="pressRelease"></param>
public void ChapPlus(bool pressRelease)
{
}
/// <summary>
/// Not implemented
/// </summary>
/// <param name="pressRelease"></param>
public void Record(bool pressRelease)
{
}
/// <summary>
/// Not implemented
/// </summary>
/// <param name="pressRelease"></param>
public void Stop(bool pressRelease)
{
}
#endregion
/// <summary>
/// Not implemented
/// </summary>
/// <param name="pressRelease"></param>
public void Record(bool pressRelease)
{
}
#region IRoutingOutputs Members
#endregion
public RoutingOutputPort HdmiOut { get; private set; }
public RoutingOutputPort AnyAudioOut { get; private set; }
/// <summary>
/// Gets or sets the OutputPorts
/// </summary>
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
#region IRoutingOutputs Members
#endregion
/// <summary>
/// Gets the HdmiOut
/// </summary>
public RoutingOutputPort HdmiOut { get; private set; }
/// <summary>
/// LinkToApi method
/// </summary>
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
/// <summary>
/// Gets the AnyAudioOut
/// </summary>
public RoutingOutputPort AnyAudioOut { get; private set; }
/// <summary>
/// Gets or sets the OutputPorts
/// </summary>
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
#endregion
/// <summary>
/// LinkToApi method
/// </summary>
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new AppleTvJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
@@ -235,42 +245,6 @@ namespace PepperDash.Essentials.Devices.Common
trilist.SetBoolSigAction(joinMap.Select.JoinNumber, Select);
trilist.SetBoolSigAction(joinMap.Menu.JoinNumber, Menu);
trilist.SetBoolSigAction(joinMap.PlayPause.JoinNumber, Play);
}
}
/// <summary>
/// Represents a AppleTVFactory
/// </summary>
public class AppleTVFactory : EssentialsDeviceFactory<AppleTV>
{
public AppleTVFactory()
{
TypeNames = new List<string>() { "appletv" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new AppleTV Device");
var irCont = IRPortHelper.GetIrOutputPortController(dc);
return new AppleTV(dc.Key, dc.Name, irCont);
}
}
public static class AppleTvIrCommands
{
public static string Up = "+";
public static string Down = "-";
public static string Left = IROutputStandardCommands.IROut_TRACK_MINUS;
public static string Right = IROutputStandardCommands.IROut_TRACK_PLUS;
public static string Enter = IROutputStandardCommands.IROut_ENTER;
public static string PlayPause = "PLAY/PAUSE";
public static string Rewind = "REWIND";
public static string Menu = "Menu";
public static string FastForward = "FASTFORWARD";
}
}

View File

@@ -0,0 +1,33 @@
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common
{
/// <summary>
/// Represents a AppleTVFactory
/// </summary>
public class AppleTVFactory : EssentialsDeviceFactory<AppleTV>
{
/// <summary>
/// Initializes a new instance of the <see cref="AppleTVFactory"/> class
/// </summary>
public AppleTVFactory()
{
TypeNames = new List<string>() { "appletv" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new AppleTV Device");
var irCont = IRPortHelper.GetIrOutputPortController(dc);
return new AppleTV(dc.Key, dc.Name, irCont);
}
}
}

View File

@@ -0,0 +1,56 @@
using Crestron.SimplSharpPro;
namespace PepperDash.Essentials.Devices.Common
{
/// <summary>
/// Represents AppleTvIrCommands
/// </summary>
public static class AppleTvIrCommands
{
/// <summary>
/// Up command
/// </summary>
public static string Up = "+";
/// <summary>
/// Down command
/// </summary>
public static string Down = "-";
/// <summary>
/// Left command
/// </summary>
public static string Left = IROutputStandardCommands.IROut_TRACK_MINUS;
/// <summary>
/// Right command
/// </summary>
public static string Right = IROutputStandardCommands.IROut_TRACK_PLUS;
/// <summary>
/// Enter command
/// </summary>
public static string Enter = IROutputStandardCommands.IROut_ENTER;
/// <summary>
/// PlayPause command
/// </summary>
public static string PlayPause = "PLAY/PAUSE";
/// <summary>
/// Rewind command
/// </summary>
public static string Rewind = "REWIND";
/// <summary>
/// Menu command
/// </summary>
public static string Menu = "Menu";
/// <summary>
/// FastForward command
/// </summary>
public static string FastForward = "FASTFORWARD";
}
}

View File

@@ -1,107 +1,106 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using Crestron.SimplSharpPro;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common
{
[Description("Wrapper class for an IR-Controlled Roku")]
/// <summary>
/// Represents a Roku2
/// </summary>
/// <summary>
/// Represents a Roku2
/// Wrapper class for an IR-Controlled Roku
/// </summary>
[Description("Wrapper class for an IR-Controlled Roku")]
public class Roku2 : EssentialsDevice, IDPad, ITransport, IUiDisplayInfo, IRoutingSource, IRoutingOutputs
{
/// <summary>
/// Gets or sets the IrPort
/// </summary>
[Api]
/// <summary>
/// Gets or sets the IrPort
/// </summary>
public IrOutputPortController IrPort { get; private set; }
/// <summary>
/// Standard Driver Name
/// </summary>
public const string StandardDriverName = "Roku XD_S.ir";
/// <summary>
/// Gets or sets the DisplayUiType
/// </summary>
[Api]
/// <summary>
/// Gets or sets the DisplayUiType
/// </summary>
public uint DisplayUiType { get { return DisplayUiConstants.TypeRoku; } }
/// <summary>
/// Initializes a new instance of the <see cref="Roku2"/> class
/// </summary>
public Roku2(string key, string name, IrOutputPortController portCont)
: base(key, name)
{
IrPort = portCont;
DeviceManager.AddDevice(portCont);;
DeviceManager.AddDevice(portCont); ;
HdmiOut = new RoutingOutputPort(RoutingPortNames.HdmiOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
HdmiOut = new RoutingOutputPort(RoutingPortNames.HdmiOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this);
OutputPorts = new RoutingPortCollection<RoutingOutputPort> { HdmiOut };
}
#region IDPad Members
/// <summary>
/// Up method
/// </summary>
[Api]
/// <summary>
/// Up method
/// </summary>
public void Up(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_UP_ARROW, pressRelease);
}
/// <summary>
/// Down method
/// </summary>
[Api]
/// <summary>
/// Down method
/// </summary>
public void Down(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_DN_ARROW, pressRelease);
}
/// <summary>
/// Left method
/// </summary>
[Api]
/// <summary>
/// Left method
/// </summary>
public void Left(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_LEFT_ARROW, pressRelease);
}
/// <summary>
/// Right method
/// </summary>
[Api]
/// <summary>
/// Right method
/// </summary>
public void Right(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_RIGHT_ARROW, pressRelease);
}
/// <summary>
/// Select method
/// </summary>
[Api]
/// <summary>
/// Select method
/// </summary>
public void Select(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_ENTER, pressRelease);
}
/// <summary>
/// Menu method
/// </summary>
[Api]
/// <summary>
/// Menu method
/// </summary>
public void Menu(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_MENU, pressRelease);
}
/// <summary>
/// Exit method
/// </summary>
[Api]
/// <summary>
/// Exit method
/// </summary>
public void Exit(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_EXIT, pressRelease);
@@ -111,49 +110,46 @@ namespace PepperDash.Essentials.Devices.Common
#region ITransport Members
/// <summary>
/// Play method
/// </summary>
[Api]
/// <summary>
/// Play method
/// </summary>
public void Play(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_PLAY, pressRelease);
}
/// <summary>
/// Pause method
/// </summary>
[Api]
/// <summary>
/// Pause method
/// </summary>
public void Pause(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_PAUSE, pressRelease);
}
/// <summary>
/// Rewind method
/// </summary>
[Api]
/// <summary>
/// Rewind method
/// </summary>
public void Rewind(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_RSCAN, pressRelease);
}
/// <summary>
/// FFwd method
/// </summary>
[Api]
/// <summary>
/// FFwd method
/// </summary>
public void FFwd(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_FSCAN, pressRelease);
}
/// <summary>
/// Not implemented
/// ChapMinus method - Not implemented
/// </summary>
/// <param name="pressRelease"></param>
/// <summary>
/// ChapMinus method
/// </summary>
public void ChapMinus(bool pressRelease)
{
}
@@ -186,34 +182,18 @@ namespace PepperDash.Essentials.Devices.Common
#region IRoutingOutputs Members
/// <summary>
/// HdmiOut
/// </summary>
public RoutingOutputPort HdmiOut { get; private set; }
/// <summary>
/// OutputPorts
/// </summary>
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
#endregion
}
/// <summary>
/// Represents a Roku2Factory
/// </summary>
public class Roku2Factory : EssentialsDeviceFactory<Roku2>
{
public Roku2Factory()
{
TypeNames = new List<string>() { "roku" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Roku Device");
var irCont = IRPortHelper.GetIrOutputPortController(dc);
return new Roku2(dc.Key, dc.Name, irCont);
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common
{
/// <summary>
/// Represents a Roku2Factory
/// </summary>
public class Roku2Factory : EssentialsDeviceFactory<Roku2>
{
/// <summary>
/// Roku2Factory constructor
/// </summary>
public Roku2Factory()
{
TypeNames = new List<string>() { "roku" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Roku Device");
var irCont = IRPortHelper.GetIrOutputPortController(dc);
return new Roku2(dc.Key, dc.Name, irCont);
}
}
}

View File

@@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{

View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core.Presets;
namespace PepperDash.Essentials.Devices.Common.VideoCodec
@@ -38,19 +36,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
/// </summary>
/// <param name="preset"></param>
/// <param name="description"></param>
void CodecRoomPresetStore(int preset, string description);
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);
}
/// <summary>
/// Static class for converting non-generic RoomPresets to generic CameraPresets.
/// </summary>
public static class RoomPresets
public static class RoomPresets
{
/// <summary>
/// Converts non-generic RoomPresets to generic CameraPresets

View File

@@ -3,5 +3,23 @@
/// <summary>
/// Enumeration of eExternalSourceMode values
/// </summary>
public enum eExternalSourceMode {Ready, NotReady, Hidden, Error}
public enum eExternalSourceMode
{
/// <summary>
/// Ready state
/// </summary>
Ready,
/// <summary>
/// Not ready state
/// </summary>
NotReady,
/// <summary>
/// Hidden state
/// </summary>
Hidden,
/// <summary>
/// Error state
/// </summary>
Error
}
}

View File

@@ -3,5 +3,35 @@
/// <summary>
/// Enumeration of eExternalSourceType values
/// </summary>
public enum eExternalSourceType {camera, desktop, document_camera, mediaplayer, PC, whiteboard, other}
public enum eExternalSourceType
{
/// <summary>
/// Camera source type
/// </summary>
camera,
/// <summary>
/// Desktop source type
/// </summary>
desktop,
/// <summary>
/// Document camera source type
/// </summary>
document_camera,
/// <summary>
/// Media player source type
/// </summary>
mediaplayer,
/// <summary>
/// PC source type
/// </summary>
PC,
/// <summary>
/// Whiteboard source type
/// </summary>
whiteboard,
/// <summary>
/// Other source type
/// </summary>
other
}
}

View File

@@ -0,0 +1,31 @@
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
/// <summary>
/// Represents a CodecCommandWithLabel
/// </summary>
public class CodecCommandWithLabel
{
/// <summary>
/// Gets or sets the Command
/// </summary>
public string Command { get; private set; }
/// <summary>
/// Gets or sets the Label
/// </summary>
public string Label { get; private set; }
/// <summary>
/// Constructor for <see cref="CodecCommandWithLabel"/>
/// </summary>
/// <param name="command">Command string</param>
/// <param name="label">Label string</param>
public CodecCommandWithLabel(string command, string label)
{
Command = command;
Label = label;
}
}
}

View File

@@ -0,0 +1,150 @@
using System;
using PepperDash.Core;
using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
/// <summary>
/// Represents a CodecPhonebookSyncState
/// </summary>
public class CodecPhonebookSyncState : IKeyed
{
private bool _InitialSyncComplete;
/// <summary>
/// Constructor for CodecPhonebookSyncState
/// </summary>
/// <param name="key">Key for the codec phonebook sync state</param>
public CodecPhonebookSyncState(string key)
{
Key = key;
CodecDisconnected();
}
/// <summary>
/// Gets or sets the InitialSyncComplete
/// </summary>
public bool InitialSyncComplete
{
get { return _InitialSyncComplete; }
private set
{
if (value == true)
{
InitialSyncCompleted?.Invoke(this, new EventArgs());
}
_InitialSyncComplete = value;
}
}
/// <summary>
/// Gets or sets the InitialPhonebookFoldersWasReceived
/// </summary>
public bool InitialPhonebookFoldersWasReceived { get; private set; }
/// <summary>
/// Gets or sets the NumberOfContactsWasReceived
/// </summary>
public bool NumberOfContactsWasReceived { get; private set; }
/// <summary>
/// Gets or sets the PhonebookRootEntriesWasRecieved
/// </summary>
public bool PhonebookRootEntriesWasRecieved { get; private set; }
/// <summary>
/// Gets or sets the PhonebookHasFolders
/// </summary>
public bool PhonebookHasFolders { get; private set; }
/// <summary>
/// Gets or sets the NumberOfContacts
/// </summary>
public int NumberOfContacts { get; private set; }
#region IKeyed Members
/// <summary>
/// Gets or sets the Key
/// </summary>
public string Key { get; private set; }
#endregion
/// <summary>
/// Event InitialSyncCompleted
/// </summary>
public event EventHandler<EventArgs> InitialSyncCompleted;
/// <summary>
/// InitialPhonebookFoldersReceived method
/// </summary>
public void InitialPhonebookFoldersReceived()
{
InitialPhonebookFoldersWasReceived = true;
CheckSyncStatus();
}
/// <summary>
/// PhonebookRootEntriesReceived method
/// </summary>
public void PhonebookRootEntriesReceived()
{
PhonebookRootEntriesWasRecieved = true;
CheckSyncStatus();
}
/// <summary>
/// SetPhonebookHasFolders method
/// </summary>
public void SetPhonebookHasFolders(bool value)
{
PhonebookHasFolders = value;
Debug.LogMessage(LogEventLevel.Debug, this, "Phonebook has folders: {0}", PhonebookHasFolders);
}
/// <summary>
/// SetNumberOfContacts method
/// </summary>
public void SetNumberOfContacts(int contacts)
{
NumberOfContacts = contacts;
NumberOfContactsWasReceived = true;
Debug.LogMessage(LogEventLevel.Debug, this, "Phonebook contains {0} contacts.", NumberOfContacts);
CheckSyncStatus();
}
/// <summary>
/// CodecDisconnected method
/// </summary>
public void CodecDisconnected()
{
InitialPhonebookFoldersWasReceived = false;
PhonebookHasFolders = false;
NumberOfContacts = 0;
NumberOfContactsWasReceived = false;
}
private void CheckSyncStatus()
{
if (InitialPhonebookFoldersWasReceived && NumberOfContactsWasReceived && PhonebookRootEntriesWasRecieved)
{
InitialSyncComplete = true;
Debug.LogMessage(LogEventLevel.Debug, this, "Initial Phonebook Sync Complete!");
}
else
{
InitialSyncComplete = false;
}
}
}
}

View File

@@ -2,8 +2,15 @@
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
/// <summary>
/// Base class for presets that can be converted to PresetBase
/// </summary>
public abstract class ConvertiblePreset
{
/// <summary>
/// Converts the preset to a PresetBase
/// </summary>
/// <returns><see cref="PresetBase"/></returns>
public abstract PresetBase ConvertCodecPreset();
}
}

View File

@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{
/// <summary>
/// Represents a CodecParticipants
/// </summary>
public class CodecParticipants
{
private List<Participant> _currentParticipants;
/// <summary>
/// Gets or sets the CurrentParticipants
/// </summary>
public List<Participant> CurrentParticipants
{
get { return _currentParticipants; }
set
{
_currentParticipants = value;
OnParticipantsChanged();
}
}
/// <summary>
/// Gets the Host participant
/// </summary>
public Participant Host
{
get
{
return _currentParticipants.FirstOrDefault(p => p.IsHost);
}
}
/// <summary>
/// Event fired when the participants list has changed
/// </summary>
public event EventHandler<EventArgs> ParticipantsListHasChanged;
/// <summary>
/// Initializes a new instance of the CodecParticipants class
/// </summary>
public CodecParticipants()
{
_currentParticipants = new List<Participant>();
}
/// <summary>
/// OnParticipantsChanged method
/// </summary>
public void OnParticipantsChanged()
{
var handler = ParticipantsListHasChanged;
if (handler == null) return;
handler(this, new EventArgs());
}
}
}

View File

@@ -1,14 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using Newtonsoft.Json;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
@@ -17,10 +7,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
/// </summary>
public interface IHasCodecLayouts
{
/// <summary>
/// Feedback that indicates the current layout on the local display
/// </summary>
StringFeedback LocalLayoutFeedback { get; }
/// <summary>
/// Toggles the local layout
/// </summary>
void LocalLayoutToggle();
void LocalLayoutToggleSingleProminent();
void MinMaxLayoutToggle();
/// <summary>
/// Toggles the local layout to single prominent
/// </summary>
void LocalLayoutToggleSingleProminent();
/// <summary>
/// Toggle the MinMax layout
/// </summary>
void MinMaxLayoutToggle();
}
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
@@ -13,14 +7,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
/// </summary>
public interface IHasCodecSelfView
{
/// <summary>
/// Feedback that indicates whether Selfview is on
/// </summary>
BoolFeedback SelfviewIsOnFeedback { get; }
/// <summary>
/// Setting that indicates whether the device shows selfview by default
/// </summary>
bool ShowSelfViewByDefault { get; }
/// <summary>
/// Turns selfview on
/// </summary>
void SelfViewModeOn();
/// <summary>
/// Turns selfview off
/// </summary>
void SelfViewModeOff();
/// <summary>
/// Toggles selfview mode
/// </summary>
void SelfViewModeToggle();
}
}

View File

@@ -1,12 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{
@@ -15,94 +9,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
/// </summary>
public interface IHasMeetingInfo
{
/// <summary>
/// Raised when meeting info changes
/// </summary>
event EventHandler<MeetingInfoEventArgs> MeetingInfoChanged;
/// <summary>
/// Gets the current meeting information
/// </summary>
MeetingInfo MeetingInfo { get; }
}
/// <summary>
/// Represents a MeetingInfo
/// </summary>
public class MeetingInfo
{
[JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
/// <summary>
/// Gets or sets the Id
/// </summary>
public string Id { get; private set; }
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; private set; }
[JsonProperty("host", NullValueHandling = NullValueHandling.Ignore)]
public string Host { get; private set; }
[JsonProperty("password", NullValueHandling = NullValueHandling.Ignore)]
public string Password { get; private set; }
[JsonProperty("shareStatus", NullValueHandling = NullValueHandling.Ignore)]
/// <summary>
/// Gets or sets the ShareStatus
/// </summary>
public string ShareStatus { get; private set; }
[JsonProperty("isHost", NullValueHandling = NullValueHandling.Ignore)]
/// <summary>
/// Gets or sets the IsHost
/// </summary>
public Boolean IsHost { get; private set; }
[JsonProperty("isSharingMeeting", NullValueHandling = NullValueHandling.Ignore)]
/// <summary>
/// Gets or sets the IsSharingMeeting
/// </summary>
public Boolean IsSharingMeeting { get; private set; }
[JsonProperty("waitingForHost", NullValueHandling = NullValueHandling.Ignore)]
/// <summary>
/// Gets or sets the WaitingForHost
/// </summary>
public Boolean WaitingForHost { get; private set; }
[JsonProperty("isLocked", NullValueHandling = NullValueHandling.Ignore)]
/// <summary>
/// Gets or sets the IsLocked
/// </summary>
public Boolean IsLocked { get; private set; }
[JsonProperty("isRecording", NullValueHandling = NullValueHandling.Ignore)]
/// <summary>
/// Gets or sets the IsRecording
/// </summary>
public Boolean IsRecording { get; private set; }
[JsonProperty("canRecord", NullValueHandling = NullValueHandling.Ignore)]
/// <summary>
/// Gets or sets the CanRecord
/// </summary>
public Boolean CanRecord { get; private set; }
public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked, bool isRecording, bool canRecord)
{
Id = id;
Name = name;
Host = host;
Password = password;
ShareStatus = shareStatus;
IsHost = isHost;
IsSharingMeeting = isSharingMeeting;
WaitingForHost = waitingForHost;
IsLocked = isLocked;
IsRecording = isRecording;
CanRecord = CanRecord;
}
}
/// <summary>
/// Represents a MeetingInfoEventArgs
/// </summary>
public class MeetingInfoEventArgs : EventArgs
{
/// <summary>
/// Gets or sets the Info
/// </summary>
public MeetingInfo Info { get; private set; }
public MeetingInfoEventArgs(MeetingInfo info)
{
Info = info;
}
}
}

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{
@@ -12,10 +7,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
/// </summary>
public interface IHasMeetingLock
{
/// <summary>
/// Feedback that indicates whether the meeting is locked
/// </summary>
BoolFeedback MeetingIsLockedFeedback { get; }
/// <summary>
/// Locks the meeting
/// </summary>
void LockMeeting();
/// <summary>
/// Unlocks the meeting
/// </summary>
void UnLockMeeting();
/// <summary>
/// Toggles the meeting lock state
/// </summary>
void ToggleMeetingLock();
}
}

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{
@@ -12,24 +7,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
/// </summary>
public interface IHasMeetingRecording
{
/// <summary>
/// Feedback that indicates whether the meeting is being recorded
/// </summary>
BoolFeedback MeetingIsRecordingFeedback { get; }
/// <summary>
/// Starts recording the meeting
/// </summary>
void StartRecording();
void StopRecording();
void ToggleRecording();
}
/// <summary>
/// Defines the contract for IHasMeetingRecordingWithPrompt
/// </summary>
public interface IHasMeetingRecordingWithPrompt : IHasMeetingRecording
{
BoolFeedback RecordConsentPromptIsVisible { get; }
/// <summary>
/// Used to agree or disagree to the meeting being recorded when prompted
/// Stops recording the meeting
/// </summary>
/// <param name="agree"></param>
void RecordingPromptAcknowledgement(bool agree);
void StopRecording();
/// <summary>
/// Toggles recording the meeting
/// </summary>
void ToggleRecording();
}
}

View File

@@ -0,0 +1,21 @@
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{
/// <summary>
/// Defines the contract for IHasMeetingRecordingWithPrompt
/// </summary>
public interface IHasMeetingRecordingWithPrompt : IHasMeetingRecording
{
/// <summary>
/// Feedback that indicates whether the recording consent prompt is visible
/// </summary>
BoolFeedback RecordConsentPromptIsVisible { get; }
/// <summary>
/// Used to agree or disagree to the meeting being recorded when prompted
/// </summary>
/// <param name="agree"></param>
void RecordingPromptAcknowledgement(bool agree);
}
}

View File

@@ -0,0 +1,31 @@
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{
/// <summary>
/// Defines the contract for IHasParticipantAudioMute
/// </summary>
public interface IHasParticipantAudioMute : IHasParticipantVideoMute
{
/// <summary>
/// Mute audio of all participants
/// </summary>
void MuteAudioForAllParticipants();
/// <summary>
/// Mute audio for participant
/// </summary>
/// <param name="userId">The user ID of the participant to mute</param>
void MuteAudioForParticipant(int userId);
/// <summary>
/// Unmute audio for participant
/// </summary>
/// <param name="userId">The user ID of the participant to unmute</param>
void UnmuteAudioForParticipant(int userId);
/// <summary>
/// Toggles audio for participant
/// </summary>
/// <param name="userId">The user ID of the participant to toggle</param>
void ToggleAudioForParticipant(int userId);
}
}

View File

@@ -0,0 +1,40 @@
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{
/// <summary>
/// Defines the contract for IHasParticipantPinUnpin
/// </summary>
public interface IHasParticipantPinUnpin : IHasParticipants
{
/// <summary>
/// Feedback that indicates the number of screens available for pinning participants
/// </summary>
IntFeedback NumberOfScreensFeedback { get; }
/// <summary>
/// Gets the screen index to pin the user to
/// </summary>
int ScreenIndexToPinUserTo { get; }
/// <summary>
/// Pins a participant to a screen
/// </summary>
/// <param name="userId">The user ID of the participant to pin</param>
/// <param name="screenIndex">The screen index to pin the user to</param>
void PinParticipant(int userId, int screenIndex);
/// <summary>
/// Unpins a participant
/// </summary>
/// <param name="userId">The user ID of the participant to unpin</param>
void UnPinParticipant(int userId);
/// <summary>
/// Toggles the pin state of a participant
/// </summary>
/// <param name="userId">The user ID of the participant to toggle</param>
/// <param name="screenIndex">The screen index to pin the user to</param>
void ToggleParticipantPinState(int userId, int screenIndex);
}
}

Some files were not shown because too many files have changed in this diff Show More