Compare commits

..

70 Commits

Author SHA1 Message Date
Jason Alborough
9ea65883b7 Fixes DM Audio Routing 2021-04-30 14:58:39 -04:00
Andrew Welker
6b7c5c01f8 Merge pull request #693 from PepperDash/hotfix/console-response-crlf-fixes
Hotfix/console response crlf fixes
2021-04-28 21:58:44 -06:00
Andrew Welker
1a3eb9a546 Merge branch 'development' into hotfix/console-response-crlf-fixes 2021-04-28 09:54:39 -06:00
Alex Johnson
ae9833ffaa Changes cr to crlf for some console command responses 2021-04-23 08:58:43 -04:00
Andrew Welker
e6f5142fc3 Merge pull request #688 from PepperDash/feature/secretsManager
Feature/secrets manager
2021-04-16 12:13:38 -06:00
Trevor Payne
3c9ca1e527 Resoves #688
Added some QoL improvements to SecretsManager meant to protect the integrity of the providers dictionary from accidental manipulation

Debug statement improvements

Improvements to verbosity of console command returns for the SecretsManager
2021-04-16 12:29:41 -05:00
Trevor Payne
452d0a5a39 Changed DeviceFactory.GetSecret(SecretsPropertiesConfig data) to return an empty string instead of null on a failed retrieval 2021-04-16 09:59:58 -05:00
Trevor Payne
8643ed2caf #685 - Requested Fixes per AWelker 2021-04-15 19:14:24 -05:00
Trevor Payne
2787c7fc52 Close #685
Adds support for Secrets
2021-04-15 18:47:13 -05:00
Trevor Payne
babc3e4f1a fixed minor registration error 2021-04-15 14:36:43 -05:00
Trevor Payne
0a4ff82af0 Added SecretsManager
Added ISecrets

Added ISecretsProvider
2021-04-15 13:47:46 -05:00
Andrew Welker
b455e1af21 Merge pull request #684 from PepperDash/release/v1.8.3
add flags on both ends to prevent input switching loop
2021-04-09 16:50:54 -06:00
Andrew Welker
e12a5e95bf Merge pull request #683 from PepperDash/release/v1.8.3
add flags on both ends to prevent input switching loop
2021-04-09 16:50:44 -06:00
Andrew Welker
3e7144f7ef Merge branch 'main' into release/v1.8.3 2021-04-09 16:40:56 -06:00
Andrew Welker
19e070ed76 add flags on both ends to prevent input switching loop 2021-04-09 16:36:11 -06:00
Neil Dorin
b818c14713 Merge pull request #681 from PepperDash/release/v1.8.3
Release/v1.8.3
2021-04-09 15:31:02 -06:00
Andrew Welker
63e7866890 Merge pull request #680 from PepperDash/feature/imobilecontrolroombridge-upgrades
Feature/imobilecontrolroombridge upgrades
2021-04-08 16:26:47 -06:00
Neil Dorin
922d1d8133 Merge branch 'development' into feature/imobilecontrolroombridge-upgrades 2021-04-08 16:17:02 -06:00
Andrew Welker
d26ea01ed9 Merge pull request #673 from PepperDash/hotfix/genericqueue-dispose-issue
Hotfix/genericqueue dispose issue
2021-04-08 16:15:31 -06:00
Andrew Welker
4ebd1b53b5 Merge branch 'development' into hotfix/genericqueue-dispose-issue 2021-04-08 15:37:15 -06:00
Andrew Welker
0226b58b1e Merge pull request #672 from PepperDash/hotfix/genericqueue-dispose-issue
#671 switches to private Dispose() on program stop
2021-04-08 15:36:53 -06:00
Neil Dorin
be41922c54 Merge pull request #679 from PepperDash/feature/plugin-loading-issues
Clean up messaging
2021-04-08 14:43:43 -06:00
Andrew Welker
56f93c5491 Merge branch 'main' into hotfix/genericqueue-dispose-issue 2021-04-08 14:25:11 -06:00
Andrew Welker
8cfd58bb7e Fix error printing for plugin loading 2021-04-08 14:21:32 -06:00
Andrew Welker
6ddfdc4b38 Updating plugin loading mechanism to provide better feedback 2021-04-08 13:54:06 -06:00
Neil Dorin
7640b95701 Clears camera mute mode when turning camera auto mode off 2021-04-06 20:08:59 -06:00
Neil Dorin
6c2abc7abd Adds missing space in video mute command 2021-04-06 19:54:01 -06:00
Neil Dorin
1849d118b4 gets rid of console print when queue items are processed. 2021-04-06 18:15:37 -06:00
Neil Dorin
22e7f004a5 adds missing code parameter 2021-04-06 18:06:15 -06:00
Neil Dorin
0dcaacb038 Merge branch 'feature/multi-display-adds' into feature/imobilecontrolroombridge-upgrades 2021-04-06 16:37:17 -06:00
Neil Dorin
cf8e673677 Adds ClientJoined event 2021-04-06 12:25:33 -06:00
Neil Dorin
200080247a closes #671 and changes to aborting thread in Dispose instead of attempting to join 2021-04-06 10:38:39 -06:00
Neil Dorin
ba247ee8d6 removes commented code for clarity 2021-04-06 10:36:03 -06:00
Neil Dorin
b3617d04c8 Merge pull request #677 from PepperDash/hotfix/stream-debug-console-issues
Hotfix/stream debug console issues
2021-04-06 10:30:08 -06:00
Neil Dorin
85cf51876a Merge branch 'development' into hotfix/stream-debug-console-issues 2021-04-06 10:01:44 -06:00
Neil Dorin
b6f47168c0 Merge pull request #676 from PepperDash/hotfix/stream-debug-console-issues
Fix FormatException happening from fall-through
2021-04-06 10:01:07 -06:00
Neil Dorin
1e755df9bb #675 Adds UserPromptedForCode event and method to show code on CiscoSparkCodec 2021-04-05 17:01:34 -06:00
Neil Dorin
037f8ed043 #671 Updates to GenericQueue to resolve issues when stopping program 2021-04-02 17:07:06 -06:00
Neil Dorin
e327d2d359 passes true when disposing of generic queue in deconstructor 2021-04-02 16:09:54 -06:00
Andrew Welker
e832566168 change to CrestronConsole.ConsoleCommandResponse for help text 2021-04-02 09:44:02 -06:00
Andrew Welker
252d037380 change to method signature instead of lambda 2021-04-02 09:09:13 -06:00
Andrew Welker
dd0f7a586e fix Console statement and add help 2021-04-02 09:03:39 -06:00
Neil Dorin
2feec62052 Removes explicit call to dispose when program stops. Clears queue in dispose 2021-03-31 16:35:33 -06:00
Neil Dorin
33a1b1697a Removes call to dispose on program stop event. Adds debug statement in Dispose() 2021-03-31 15:29:55 -06:00
Neil Dorin
955d68b3f3 #671 switches to private Dispose() on program stop 2021-03-30 15:56:05 -06:00
Neil Dorin
0f28d46f34 #671 Calls the private dispose method on program stop 2021-03-30 15:53:10 -06:00
Andrew Welker
275759143b Merge branch 'development' into feature/multi-display-adds 2021-03-29 13:31:10 -06:00
Andrew Welker
3a4737b6f6 Merge pull request #670 from PepperDash/hotfix/dm-routing-issues
Hotfix/dm routing issues
2021-03-29 13:29:46 -06:00
Andrew Welker
2b2308d5c2 Merge branch 'development' into hotfix/dm-routing-issues 2021-03-29 13:18:00 -06:00
Andrew Welker
185f03065e Merge pull request #669 from PepperDash/hotfix/dm-routing-issues
Fix LinkToApi methods for chassis to use ExecuteNumericSwitch
2021-03-29 13:17:51 -06:00
Andrew Welker
3803263598 Merge branch 'development' into feature/multi-display-adds 2021-03-29 12:54:54 -06:00
Andrew Welker
358fa1a9c0 Merge pull request #667 from PepperDash/hotfix/generic-queue-disposed-check
Hotfix/generic queue disposed check
2021-03-29 12:53:43 -06:00
Andrew Welker
7fbbc9f2b8 Fix LinkToApi methods for chassis to use ExecuteNumericSwitch 2021-03-29 12:50:43 -06:00
Andrew Welker
f4f400f9b6 Merge branch 'development' into hotfix/generic-queue-disposed-check 2021-03-29 09:55:40 -06:00
Andrew Welker
d3383db890 Merge pull request #666 from PepperDash/hotfix/generic-queue-disposed-check
added a Disposed check and Debug Message to prevent enqueing messages…
2021-03-29 07:55:29 -06:00
Nick Genovese
139e5370ea added a Disposed check and Debug Message to prevent enqueing messages after the Generic Queue has been disposed; typically happens at program stop 2021-03-29 09:42:31 -04:00
Andrew Welker
4f9fa05e3f Merge branch 'development' into feature/multi-display-adds 2021-03-25 16:06:48 -06:00
Andrew Welker
7ab2574912 Merge pull request #662 from PepperDash/hotfix/scheduler-fixes
Hotfix/scheduler fixes
2021-03-25 16:05:25 -06:00
Andrew Welker
35167d77f9 Merge branch 'development' into hotfix/scheduler-fixes 2021-03-25 15:48:59 -06:00
Andrew Welker
bdd17dfa27 Merge pull request #661 from PepperDash/hotfix/scheduler-fixes
Hotfix/scheduler fixes
2021-03-25 15:48:45 -06:00
Andrew Welker
6443e00428 update back to latest builder image 2021-03-22 09:48:23 -06:00
Andrew Welker
008279e867 Initialize some properties that were causing a nullRef 2021-03-22 09:39:08 -06:00
Andrew Welker
c4a6d20791 fixing a nullref issue with cisco spark 2021-03-22 09:23:07 -06:00
Andrew Welker
61b4002e5a Fix to test build image again 2021-03-19 09:22:21 -06:00
Andrew Welker
da63d0917e Updates to test new builder image
this build WILL fail
2021-03-19 09:03:05 -06:00
Andrew Welker
0228fd1c0f fix a ; 2021-03-18 16:27:08 -06:00
Andrew Welker
085ba134c4 Set event to not be acknowledgable
Added logic to acknowledge event
Added debug statement to show that event was being fired
2021-03-18 12:44:20 -06:00
Andrew Welker
a9fce3237c Added check for key to Clear command
If the key was wrong or wasn't in the group, a `KeyNotFoundException` was thrown.

Also added acknowledgment of a successful deletion
2021-03-18 12:43:29 -06:00
Andrew Welker
840fb21e15 Added console command to list events for a group 2021-03-18 12:42:29 -06:00
Andrew Welker
8ed236abae Merge pull request #654 from PepperDash/hotfix/namespace-issues
Fix old/wrong namespace versions to have copies of types that are in the correct one
2021-03-12 16:48:01 -07:00
22 changed files with 2169 additions and 1480 deletions

View File

@@ -36,6 +36,7 @@ namespace PepperDash.Essentials
Thread.MaxNumberOfUserThreads = 400;
Global.ControlSystem = this;
DeviceManager.Initialize(this);
SecretsManager.Initialize();
SystemMonitor.ProgramInitialization.ProgramInitializationUnderUserControl = true;
}
@@ -71,7 +72,7 @@ namespace PepperDash.Essentials
CrestronConsole.AddNewConsoleCommand(s =>
{
foreach (var tl in TieLineCollection.Default)
CrestronConsole.ConsoleCommandResponse(" {0}\r", tl);
CrestronConsole.ConsoleCommandResponse(" {0}\r\n", tl);
},
"listtielines", "Prints out all tie lines", ConsoleAccessLevelEnum.AccessOperator);
@@ -85,8 +86,8 @@ namespace PepperDash.Essentials
CrestronConsole.AddNewConsoleCommand(s =>
{
CrestronConsole.ConsoleCommandResponse("This system can be found at the following URLs:\r" +
"System URL: {0}\r" +
CrestronConsole.ConsoleCommandResponse("This system can be found at the following URLs:\r\n" +
"System URL: {0}\r\n" +
"Template URL: {1}", ConfigReader.ConfigObject.SystemUrl, ConfigReader.ConfigObject.TemplateUrl);
}, "portalinfo", "Shows portal URLS from configuration", ConsoleAccessLevelEnum.AccessOperator);

View File

@@ -19,7 +19,8 @@ namespace PepperDash.Essentials
{
public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IHasCurrentSourceInfoChange,
IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback
{
{
private bool _codecExternalSourceChange;
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
public event SourceInfoChangeHandler CurrentSourceChange;
@@ -178,10 +179,12 @@ namespace PepperDash.Essentials
handler(_CurrentSourceInfo, ChangeType.DidChange);
var vc = VideoCodec as IHasExternalSourceSwitching;
if (vc != null)
if (vc != null && !_codecExternalSourceChange)
{
vc.SetSelectedSource(CurrentSourceInfoKey);
}
_codecExternalSourceChange = false;
}
}
SourceListItem _CurrentSourceInfo;
@@ -421,6 +424,12 @@ namespace PepperDash.Essentials
return true;
}
public void RunRouteActionCodec(string routeKey, string sourceListKey)
{
_codecExternalSourceChange = true;
RunRouteAction(routeKey, sourceListKey);
}
/// <summary>
///
/// </summary>
@@ -750,7 +759,7 @@ namespace PepperDash.Essentials
x => x.DestinationKey == VideoCodec.Key && x.DestinationPort == videoCodecWithExternalSwitching.ExternalSourceInputPort).DestinationPort;
videoCodecWithExternalSwitching.ClearExternalSources();
videoCodecWithExternalSwitching.RunRouteAction = RunRouteAction;
videoCodecWithExternalSwitching.RunRouteAction = RunRouteActionCodec;
var srcList = ConfigReader.ConfigObject.SourceLists.SingleOrDefault(x => x.Key == SourceListKey).Value.OrderBy(kv => kv.Value.Order); ;
foreach (var kvp in srcList)

View File

@@ -25,6 +25,7 @@ namespace PepperDash.Essentials.Core
public GenericComm(DeviceConfig config)
: base(config)
{
PropertiesConfig = CommFactory.GetControlPropertiesConfig(config);
var commPort = CommFactory.CreateCommForDevice(config);

View File

@@ -30,7 +30,19 @@ namespace PepperDash.Essentials.Core.Config
[JsonProperty("properties")]
[JsonConverter(typeof(DevicePropertiesConverter))]
public JToken Properties { get; set; }
public JToken Properties { get; set; }
public DeviceConfig(DeviceConfig dc)
{
Key = dc.Key;
Uid = dc.Uid;
Name = dc.Name;
Group = dc.Group;
Type = dc.Type;
Properties = JToken.FromObject(dc.Properties);
}
public DeviceConfig() {}
}
/// <summary>

View File

@@ -20,6 +20,10 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
{
event EventHandler<EventArgs> UserCodeChanged;
event EventHandler<EventArgs> UserPromptedForCode;
event EventHandler<EventArgs> ClientJoined;
string UserCode { get; }
string QrCodeUrl { get; }

View File

@@ -46,7 +46,7 @@ namespace PepperDash.Essentials.Core
CrestronConsole.AddNewConsoleCommand(SimulateComReceiveOnDevice, "devsimreceive",
"Simulates incoming data on a com device", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => SetDeviceStreamDebugging(s), "setdevicestreamdebug", "set comm debug [deviceKey] [off/rx/tx/both] ([minutes])", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(SetDeviceStreamDebugging, "setdevicestreamdebug", "set comm debug [deviceKey] [off/rx/tx/both] ([minutes])", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => DisableAllDeviceStreamDebugging(), "disableallstreamdebug", "disables stream debugging on all devices", ConsoleAccessLevelEnum.AccessOperator);
}
@@ -387,6 +387,15 @@ namespace PepperDash.Essentials.Core
/// <param name="s"></param>
public static void SetDeviceStreamDebugging(string s)
{
if (String.IsNullOrEmpty(s) || s.Contains("?"))
{
CrestronConsole.ConsoleCommandResponse(
@"SETDEVICESTREAMDEBUG [{deviceKey}] [OFF |TX | RX | BOTH] [timeOutInMinutes]
{deviceKey} [OFF | TX | RX | BOTH] - Device to set stream debugging on, and which setting to use
timeOutInMinutes - Set timeout for stream debugging. Default is 30 minutes");
return;
}
var args = s.Split(' ');
var deviceKey = args[0];
@@ -437,7 +446,7 @@ namespace PepperDash.Essentials.Core
else
{
device.StreamDebugging.SetDebuggingWithDefaultTimeout(debugSetting);
Debug.Console(0, "Device: '{0}' debug level set to {1) for default time (30 minutes)", deviceKey, debugSetting);
Debug.Console(0, "Device: '{0}' debug level set to {1} for default time (30 minutes)", deviceKey, debugSetting);
}
}

View File

@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace PepperDash.Essentials.Core
{
public static class JsonExtensions
{
public static List<JToken> FindTokens(this JToken containerToken, string name)
{
List<JToken> matches = new List<JToken>();
FindTokens(containerToken, name, matches);
return matches;
}
private static void FindTokens(JToken containerToken, string name, List<JToken> matches)
{
if (containerToken.Type == JTokenType.Object)
{
foreach (JProperty child in containerToken.Children<JProperty>())
{
if (child.Name == name)
{
matches.Add(child.Value);
}
FindTokens(child.Value, name, matches);
}
}
else if (containerToken.Type == JTokenType.Array)
{
foreach (JToken child in containerToken.Children())
{
FindTokens(child, name, matches);
}
}
}
}
}

View File

@@ -7,6 +7,8 @@ using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.GeneralIO;
using Crestron.SimplSharp.Reflection;
using PepperDash.Core;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.CrestronIO;
@@ -83,33 +85,81 @@ namespace PepperDash.Essentials.Core
var wrapper = new DeviceFactoryWrapper() { CType = cType, Description = description, FactoryMethod = method };
DeviceFactory.FactoryMethods.Add(typeName, wrapper);
}
/// <summary>
/// The factory method for Core "things". Also iterates the Factory methods that have
/// been loaded from plugins
/// </summary>
/// <param name="dc"></param>
/// <returns></returns>
public static IKeyed GetDevice(DeviceConfig dc)
{
var key = dc.Key;
var name = dc.Name;
var type = dc.Type;
var properties = dc.Properties;
var typeName = dc.Type.ToLower();
// Check for types that have been added by plugin dlls.
if (FactoryMethods.ContainsKey(typeName))
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading '{0}' from Essentials Core", dc.Type);
return FactoryMethods[typeName].FactoryMethod(dc);
}
return null;
}
}
private static void CheckForSecrets(IEnumerable<JProperty> obj)
{
foreach (var prop in obj.Where(prop => prop.Value as JObject != null))
{
if (prop.Name.ToLower() == "secret")
{
var secret = GetSecret(prop.Children().First().ToObject<SecretsPropertiesConfig>());
//var secret = GetSecret(JsonConvert.DeserializeObject<SecretsPropertiesConfig>(prop.Children().First().ToString()));
prop.Parent.Replace(secret);
}
var recurseProp = prop.Value as JObject;
if (recurseProp == null) return;
CheckForSecrets(recurseProp.Properties());
}
}
private static string GetSecret(SecretsPropertiesConfig data)
{
var secretProvider = SecretsManager.GetSecretProviderByKey(data.Provider);
if (secretProvider == null) return null;
var secret = secretProvider.GetSecret(data.Key);
if (secret != null) return (string) secret.Value;
Debug.Console(1,
"Unable to retrieve secret {0}{1} - Make sure you've added it to the secrets provider",
data.Provider, data.Key);
return String.Empty;
}
/// <summary>
/// The factory method for Core "things". Also iterates the Factory methods that have
/// been loaded from plugins
/// </summary>
/// <param name="dc"></param>
/// <returns></returns>
public static IKeyed GetDevice(DeviceConfig dc)
{
try
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading '{0}' from Essentials Core", dc.Type);
var localDc = new DeviceConfig(dc);
var key = localDc.Key;
var name = localDc.Name;
var type = localDc.Type;
var properties = localDc.Properties;
//var propRecurse = properties;
var typeName = localDc.Type.ToLower();
var jObject = properties as JObject;
if (jObject != null)
{
var jProp = jObject.Properties();
CheckForSecrets(jProp);
}
Debug.Console(2, "typeName = {0}", typeName);
// Check for types that have been added by plugin dlls.
return !FactoryMethods.ContainsKey(typeName) ? null : FactoryMethods[typeName].FactoryMethod(localDc);
}
catch (Exception ex)
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "Exception occurred while creating device {0}: {1}", dc.Key, ex.Message);
Debug.Console(2, "{0}", ex.StackTrace);
return null;
}
}
/// <summary>
/// Prints the type names and associated metadata from the FactoryMethods collection.
/// </summary>

View File

@@ -24,6 +24,10 @@ namespace PepperDash.Essentials.Core
CrestronConsole.AddNewConsoleCommand(ClearEventsFromGroup, "ClearAllEvents", "Clears all scheduled events for this group", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(ListAllEventGroups, "ListAllEventGroups", "Lists all the event groups by key", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(ListAllEventsForGroup, "ListEventsForGroup",
"Lists all events for the given group", ConsoleAccessLevelEnum.AccessOperator);
}
/// <summary>
@@ -32,12 +36,26 @@ namespace PepperDash.Essentials.Core
/// <param name="groupName"></param>
static void ClearEventsFromGroup(string groupName)
{
if (!EventGroups.ContainsKey(groupName))
{
Debug.Console(0,
"[Scheduler]: Unable to delete events from group '{0}'. Group not found in EventGroups dictionary.",
groupName);
return;
}
var group = EventGroups[groupName];
if (group != null)
{
group.ClearAllEvents();
Debug.Console(0, "[Scheduler]: All events deleted from group '{0}'", groupName);
}
else
Debug.Console(0, "[Scheduler]: Unable to delete events from group '{0}'. Group not found in EventGroups dictionary.", groupName);
Debug.Console(0,
"[Scheduler]: Unable to delete events from group '{0}'. Group not found in EventGroups dictionary.",
groupName);
}
static void ListAllEventGroups(string command)
@@ -49,6 +67,33 @@ namespace PepperDash.Essentials.Core
}
}
static void ListAllEventsForGroup(string args)
{
Debug.Console(0, "Getting events for group {0}...", args);
ScheduledEventGroup group;
if (!EventGroups.TryGetValue(args, out group))
{
Debug.Console(0, "Unabled to get event group for key {0}", args);
return;
}
foreach (var evt in group.ScheduledEvents)
{
Debug.Console(0,
@"
****Event key {0}****
Event date/time: {1}
Persistent: {2}
Acknowlegable: {3}
Recurrence: {4}
Recurrence Days: {5}
********************", evt.Key, evt.Value.DateAndTime, evt.Value.Persistent, evt.Value.Acknowledgeable,
evt.Value.Recurrence.Recurrence, evt.Value.Recurrence.RecurrenceDays);
}
}
/// <summary>
/// Adds the event group to the global list
/// </summary>

View File

@@ -209,6 +209,7 @@
<Compile Include="DeviceTypeInterfaces\IHasFarEndContentStatus.cs" />
<Compile Include="DeviceTypeInterfaces\IHasPhoneDialing.cs" />
<Compile Include="DeviceTypeInterfaces\IMobileControl.cs" />
<Compile Include="Extensions\JsonExtensions.cs" />
<Compile Include="Factory\DeviceFactory.cs" />
<Compile Include="Factory\IDeviceFactory.cs" />
<Compile Include="Factory\ReadyEventArgs.cs" />
@@ -320,6 +321,10 @@
<Compile Include="Feedbacks\BoolFeedbackPulseExtender.cs" />
<Compile Include="Routing\RoutingPortNames.cs" />
<Compile Include="Routing\TieLineConfig.cs" />
<Compile Include="Secrets\CrestronSecretsProvider.cs" />
<Compile Include="Secrets\Interfaces.cs" />
<Compile Include="Secrets\SecretsManager.cs" />
<Compile Include="Secrets\SecretsPropertiesConfig.cs" />
<Compile Include="Shades\Shade Interfaces.cs" />
<Compile Include="Shades\ShadeBase.cs" />
<Compile Include="Shades\ShadeController.cs" />

View File

@@ -358,14 +358,27 @@ namespace PepperDash.Essentials
try
{
var assy = loadedAssembly.Assembly;
var types = assy.GetTypes();
CType[] types = {};
try
{
types = assy.GetTypes();
}
catch (TypeLoadException e)
{
Debug.Console(0, Debug.ErrorLogLevel.Warning, "Unable to get types for assembly {0}: {1}",
loadedAssembly.Name, e.Message);
Debug.Console(2, e.StackTrace);
continue;
}
foreach (var type in types)
{
try
{
if (typeof(IPluginDeviceFactory).IsAssignableFrom(type))
if (typeof (IPluginDeviceFactory).IsAssignableFrom(type))
{
var plugin = (IPluginDeviceFactory)Crestron.SimplSharp.Reflection.Activator.CreateInstance(type);
var plugin =
(IPluginDeviceFactory) Crestron.SimplSharp.Reflection.Activator.CreateInstance(type);
LoadCustomPlugin(plugin, loadedAssembly);
}
else
@@ -378,6 +391,11 @@ namespace PepperDash.Essentials
}
}
}
catch (NotSupportedException e)
{
//this happens for dlls that aren't PD dlls, like ports of Mono classes into S#. Swallowing.
}
catch (Exception e)
{
Debug.Console(2, "Load Plugin not found. {0}.{2} is not a plugin factory. Exception: {1}",
@@ -389,7 +407,9 @@ namespace PepperDash.Essentials
}
catch (Exception e)
{
Debug.Console(2, "Error Loading Assembly: {0} Exception: {1} ", loadedAssembly.Name, e);
Debug.Console(0, Debug.ErrorLogLevel.Warning, "Error Loading assembly {0}: {1}",
loadedAssembly.Name, e.Message);
Debug.Console(2, "{0}", e.StackTrace);
continue;
}
}

View File

@@ -14,7 +14,7 @@ namespace PepperDash.Essentials.Core.Queues
protected readonly CrestronQueue<IQueueMessage> _queue;
protected readonly Thread _worker;
protected readonly CEvent _waitHandle = new CEvent();
private bool _delayEnabled;
private int _delayTime;
@@ -155,10 +155,10 @@ namespace PepperDash.Essentials.Core.Queues
if (programEvent != eProgramStatusEventType.Stopping)
return;
Dispose();
Dispose(true);
};
}
/// <summary>
/// Thread callback
/// </summary>
@@ -180,7 +180,7 @@ namespace PepperDash.Essentials.Core.Queues
{
try
{
Debug.Console(2, this, "Processing queue item: '{0}'", item.ToString());
//Debug.Console(2, this, "Processing queue item: '{0}'", item.ToString());
item.Dispatch();
if (_delayEnabled)
@@ -199,6 +199,12 @@ namespace PepperDash.Essentials.Core.Queues
public void Enqueue(IQueueMessage item)
{
if (Disposed)
{
Debug.Console(1, this, "I've been disposed so you can't enqueue any messages. Are you trying to dispatch a message while the program is stopping?");
return;
}
_queue.Enqueue(item);
_waitHandle.Set();
}
@@ -225,8 +231,13 @@ namespace PepperDash.Essentials.Core.Queues
if (disposing)
{
Enqueue(null);
_worker.Join();
Debug.Console(2, this, "Disposing...");
if (_queue != null && !_queue.Disposed)
{
_queue.Clear();
Enqueue(null);
}
_worker.Abort();
_waitHandle.Close();
}
@@ -235,7 +246,7 @@ namespace PepperDash.Essentials.Core.Queues
~GenericQueue()
{
Dispose(false);
Dispose(true);
}
/// <summary>
@@ -401,7 +412,7 @@ namespace PepperDash_Essentials_Core.Queues
if (programEvent != eProgramStatusEventType.Stopping)
return;
Dispose();
Dispose(true);
};
}
@@ -471,8 +482,13 @@ namespace PepperDash_Essentials_Core.Queues
if (disposing)
{
Enqueue(null);
_worker.Join();
Debug.Console(2, this, "Disposing...");
if (_queue != null && !_queue.Disposed)
{
_queue.Clear();
Enqueue(null);
}
_worker.Abort();
_waitHandle.Close();
}
@@ -481,7 +497,7 @@ namespace PepperDash_Essentials_Core.Queues
~GenericQueue()
{
Dispose(false);
Dispose(true);
}
/// <summary>

View File

@@ -169,10 +169,15 @@ namespace PepperDash.Essentials.Core
void FeatureEventGroup_UserGroupCallBack(ScheduledEvent SchEvent, ScheduledEventCommon.eCallbackReason type)
{
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "{0}:{1} @ {2}", SchEvent.Name, type, DateTime.Now);
if (type == ScheduledEventCommon.eCallbackReason.NormalExpiration)
{
SchEvent.Acknowledge();
if (SchEvent.Name == FeatureEnableEventName)
{
if (PropertiesConfig.EnableRoomOnWhenOccupied)
FeatureEnabled = true;
@@ -248,9 +253,8 @@ namespace PepperDash.Essentials.Core
schEvent = new ScheduledEvent(name, FeatureEventGroup);
// Set up its initial properties
if(!schEvent.Acknowledgeable)
schEvent.Acknowledgeable = true;
schEvent.Acknowledgeable = false;
if(!schEvent.Persistent)
schEvent.Persistent = true;
@@ -287,7 +291,7 @@ namespace PepperDash.Essentials.Core
Debug.Console(1, this, "Event '{0}' Absolute time set to {1}", schEvent.Name, schEvent.DateAndTime.ToString());
CalculateAndSetAcknowledgeExpirationTimeout(schEvent, FeatureEnabledTime, FeatureDisabledTime);
//CalculateAndSetAcknowledgeExpirationTimeout(schEvent, FeatureEnabledTime, FeatureDisabledTime);
schEvent.Recurrence.Weekly(eventRecurrennce);

View File

@@ -0,0 +1,97 @@
using System;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronDataStore;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
public class CrestronSecretsProvider : ISecretProvider
{
public string Key { get; set; }
//Added for reference
private static readonly bool SecureSupported;
public CrestronSecretsProvider(string key)
{
Key = key;
}
static CrestronSecretsProvider()
{
//Added for future encrypted reference
SecureSupported = CrestronSecureStorage.Supported;
CrestronDataStoreStatic.InitCrestronDataStore();
if (SecureSupported)
{
//doThingsFuture
}
}
/// <summary>
/// Set secret for item in the CrestronSecretsProvider
/// </summary>
/// <param name="key">Secret Key</param>
/// <param name="value">Secret Value</param>
public bool SetSecret(string key, object value)
{
var secret = value as string;
if (String.IsNullOrEmpty(secret))
{
Debug.Console(2, this, "Unable to set secret for {0}:{1} - value is empty.", Key, key);
return false;
}
var setErrorCode = CrestronDataStoreStatic.SetLocalStringValue(key, secret);
switch (setErrorCode)
{
case CrestronDataStore.CDS_ERROR.CDS_SUCCESS:
Debug.Console(1, this,"Secret Successfully Set for {0}:{1}", Key, key);
return true;
default:
Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Unable to set secret for {0}:{1} - {2}", Key, key, setErrorCode.ToString());
return false;
}
}
/// <summary>
/// Retrieve secret for item in the CrestronSecretsProvider
/// </summary>
/// <param name="key">Secret Key</param>
/// <returns>ISecret Object containing key, provider, and value</returns>
public ISecret GetSecret(string key)
{
string mySecret;
var getErrorCode = CrestronDataStoreStatic.GetLocalStringValue(key, out mySecret);
switch (getErrorCode)
{
case CrestronDataStore.CDS_ERROR.CDS_SUCCESS:
Debug.Console(2, this, "Secret Successfully retrieved for {0}:{1}", Key, key);
return new CrestronSecret(key, mySecret, this);
default:
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to retrieve secret for {0}:{1} - {2}",
Key, key, getErrorCode.ToString());
return null;
}
}
}
/// <summary>
/// Special container class for CrestronSecret provider
/// </summary>
public class CrestronSecret : ISecret
{
public ISecretProvider Provider { get; private set; }
public string Key { get; private set; }
public object Value { get; private set; }
public CrestronSecret(string key, string value, ISecretProvider provider)
{
Key = key;
Value = value;
Provider = provider;
}
}
}

View File

@@ -0,0 +1,24 @@
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// All ISecrecretProvider classes must implement this interface.
/// </summary>
public interface ISecretProvider : IKeyed
{
bool SetSecret(string key, object value);
ISecret GetSecret(string key);
}
/// <summary>
/// interface for delivering secrets in Essentials.
/// </summary>
public interface ISecret
{
ISecretProvider Provider { get; }
string Key { get; }
object Value { get; }
}
}

View File

@@ -0,0 +1,281 @@
using System;
using System.Collections.Generic;
using Crestron.SimplSharp;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
public static class SecretsManager
{
public static Dictionary<string, ISecretProvider> Secrets { get; private set; }
/// <summary>
/// Initialize the SecretsManager
/// </summary>
public static void Initialize()
{
AddSecretProvider("default", new CrestronSecretsProvider("default"));
CrestronConsole.AddNewConsoleCommand(SetSecretProcess, "setsecret",
"Adds secrets to secret provider",
ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(UpdateSecretProcess, "updatesecret",
"Updates secrets in secret provider",
ConsoleAccessLevelEnum.AccessAdministrator);
CrestronConsole.AddNewConsoleCommand(DeleteSecretProcess, "deletesecret",
"Deletes secrets in secret provider",
ConsoleAccessLevelEnum.AccessAdministrator);
}
static SecretsManager()
{
Secrets = new Dictionary<string, ISecretProvider>();
}
/// <summary>
/// Get Secret Provider from dictionary by key
/// </summary>
/// <param name="key">Dictionary Key for provider</param>
/// <returns>ISecretProvider</returns>
public static ISecretProvider GetSecretProviderByKey(string key)
{
ISecretProvider secret;
Secrets.TryGetValue(key, out secret);
if (secret == null)
{
Debug.Console(1, "SecretsManager unable to retrieve SecretProvider with the key '{0}'", key);
}
return secret;
}
/// <summary>
/// Add secret provider to secrets dictionary
/// </summary>
/// <param name="key">Key of new entry</param>
/// <param name="provider">New Provider Entry</param>
public static void AddSecretProvider(string key, ISecretProvider provider)
{
if (!Secrets.ContainsKey(key))
{
Secrets.Add(key, provider);
Debug.Console(1, "Secrets provider '{0}' added to SecretsManager", key);
}
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Unable to add Provider '{0}' to Secrets. Provider with that key already exists", key );
}
/// <summary>
/// Add secret provider to secrets dictionary, with optional overwrite parameter
/// </summary>
/// <param name="key">Key of new entry</param>
/// <param name="provider">New provider entry</param>
/// <param name="overwrite">true to overwrite any existing providers in the dictionary</param>
public static void AddSecretProvider(string key, ISecretProvider provider, bool overwrite)
{
if (!Secrets.ContainsKey(key))
{
Secrets.Add(key, provider);
Debug.Console(1, "Secrets provider '{0}' added to SecretsManager", key);
}
if (overwrite)
{
Secrets.Add(key, provider);
Debug.Console(1, Debug.ErrorLogLevel.Notice, "Provider with the key '{0}' already exists in secrets. Overwriting with new secrets provider.", key);
}
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Unable to add Provider '{0}' to Secrets. Provider with that key already exists", key);
}
private static void SetSecretProcess(string cmd)
{
string response;
var args = cmd.Split(' ');
if (args.Length == 0)
{
//some Instructional Text
response = "Adds secrets to secret provider. Format 'setsecret <provider> <secretKey> <secret>";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
if (args.Length == 1 && args[0] == "?")
{
response = "Adds secrets to secret provider. Format 'setsecret <provider> <secretKey> <secret>";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
if (args.Length < 3)
{
response = "Improper number of arguments";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
var provider = GetSecretProviderByKey(args[0]);
if (provider == null)
{
//someFail
response = "Provider key invalid";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
var key = args[1];
var secret = args[2];
if (provider.GetSecret(key) == null)
{
response = provider.SetSecret(key, secret)
? String.Format(
"Secret successfully set for {0}:{1}",
provider.Key, key)
: String.Format(
"Unable to set secret for {0}:{1}",
provider.Key, key);
CrestronConsole.ConsoleCommandResponse(response);
return;
}
response =
String.Format(
"Unable to set secret for {0}:{1} - Please use the 'UpdateSecret' command to modify it");
CrestronConsole.ConsoleCommandResponse(response);
}
private static void UpdateSecretProcess(string cmd)
{
string response;
var args = cmd.Split(' ');
if (args.Length == 0)
{
//some Instructional Text
response = "Updates secrets in secret provider. Format 'updatesecret <provider> <secretKey> <secret>";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
if (args.Length == 1 && args[0] == "?")
{
response = "Updates secrets in secret provider. Format 'updatesecret <provider> <secretKey> <secret>";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
if (args.Length < 3)
{
//someFail
response = "Improper number of arguments";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
var provider = GetSecretProviderByKey(args[0]);
if (provider == null)
{
//someFail
response = "Provider key invalid";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
var key = args[1];
var secret = args[2];
if (provider.GetSecret(key) != null)
{
response = provider.SetSecret(key, secret)
? String.Format(
"Secret successfully set for {0}:{1}",
provider.Key, key)
: String.Format(
"Unable to set secret for {0}:{1}",
provider.Key, key);
CrestronConsole.ConsoleCommandResponse(response);
return;
}
response =
String.Format(
"Unable to update secret for {0}:{1} - Please use the 'SetSecret' command to create a new secret");
CrestronConsole.ConsoleCommandResponse(response);
}
private static void DeleteSecretProcess(string cmd)
{
string response;
var args = cmd.Split(' ');
if (args.Length == 0)
{
//some Instructional Text
response = "Deletes secrets in secret provider. Format 'deletesecret <provider> <secretKey>";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
if (args.Length == 1 && args[0] == "?")
{
response = "Deletes secrets in secret provider. Format 'deletesecret <provider> <secretKey>";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
if (args.Length < 2)
{
//someFail
response = "Improper number of arguments";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
var provider = GetSecretProviderByKey(args[0]);
if (provider == null)
{
//someFail
response = "Provider key invalid";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
var key = args[1];
provider.SetSecret(key, "");
response = provider.SetSecret(key, "")
? String.Format(
"Secret successfully deleted for {0}:{1}",
provider.Key, key)
: String.Format(
"Unable to delete secret for {0}:{1}",
provider.Key, key);
CrestronConsole.ConsoleCommandResponse(response);
return;
}
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Provide a way to easily deserialize into a secret object from config
/// </summary>
public class SecretsPropertiesConfig
{
[JsonProperty("provider")]
public string Provider { get; set; }
[JsonProperty("key")]
public string Key { get; set; }
}
}

View File

@@ -671,7 +671,7 @@ namespace PepperDash.Essentials.DM {
var ioSlotJoin = ioSlot - 1;
// Control
trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin, o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Video));
trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin, o => ExecuteNumericSwitch(o, (ushort) ioSlot, eRoutingSignalType.Video));
if (TxDictionary.ContainsKey(ioSlot))
{

View File

@@ -228,9 +228,9 @@ namespace PepperDash.Essentials.DM
// Control
trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin,
o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Video));
o => ExecuteNumericSwitch(o, (ushort) ioSlot, eRoutingSignalType.Video));
trilist.SetUShortSigAction(joinMap.OutputAudio.JoinNumber + ioSlotJoin,
o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Audio));
o => ExecuteNumericSwitch(o, (ushort) ioSlot, eRoutingSignalType.Audio));
trilist.SetStringSigAction(joinMap.OutputNames.JoinNumber + ioSlotJoin, s =>
{

View File

@@ -30,6 +30,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
IHasScheduleAwareness, IOccupancyStatusProvider, IHasCodecLayouts, IHasCodecSelfView,
ICommunicationMonitor, IRouting, IHasCodecCameras, IHasCameraAutoMode, IHasCodecRoomPresets, IHasExternalSourceSwitching, IHasBranding, IHasCameraOff, IHasCameraMute
{
private bool _externalSourceChangeRequested;
public event EventHandler<DirectoryEventArgs> DirectoryResultReturned;
private CTimer _brandingTimer;
@@ -368,21 +370,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
CodecSchedule = new CodecScheduleAwareness();
//Set Feedback Actions
CodecStatus.Status.Audio.Volume.ValueChangedAction = VolumeLevelFeedback.FireUpdate;
CodecStatus.Status.Audio.VolumeMute.ValueChangedAction = MuteFeedback.FireUpdate;
CodecStatus.Status.Audio.Microphones.Mute.ValueChangedAction = PrivacyModeIsOnFeedback.FireUpdate;
CodecStatus.Status.Standby.State.ValueChangedAction = StandbyIsOnFeedback.FireUpdate;
CodecStatus.Status.RoomAnalytics.PeoplePresence.ValueChangedAction = RoomIsOccupiedFeedback.FireUpdate;
CodecStatus.Status.RoomAnalytics.PeopleCount.Current.ValueChangedAction = PeopleCountFeedback.FireUpdate;
CodecStatus.Status.Cameras.SpeakerTrack.Status.ValueChangedAction = CameraAutoModeIsOnFeedback.FireUpdate;
CodecStatus.Status.Video.Selfview.Mode.ValueChangedAction = SelfviewIsOnFeedback.FireUpdate;
CodecStatus.Status.Video.Selfview.PIPPosition.ValueChangedAction = ComputeSelfviewPipStatus;
CodecStatus.Status.Video.Layout.LayoutFamily.Local.ValueChangedAction = ComputeLocalLayout;
CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction = SharingContentIsOnFeedback.FireUpdate;
CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction = FarEndIsSharingContentFeedback.FireUpdate;
CodecStatus.Status.Video.Input.MainVideoMute.ValueChangedAction = CameraIsOffFeedback.FireUpdate;
SetFeedbackActions();
CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, eRoutingSignalType.Audio | eRoutingSignalType.Video,
CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(StopSharing), this);
HdmiIn2 = new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(SelectPresentationSource1), this);
@@ -418,7 +408,36 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
_brandingUrl = props.UiBranding.BrandingUrl;
}
/// <summary>
private void SetFeedbackActions()
{
CodecStatus.Status.Audio.Volume.ValueChangedAction = VolumeLevelFeedback.FireUpdate;
CodecStatus.Status.Audio.VolumeMute.ValueChangedAction = MuteFeedback.FireUpdate;
CodecStatus.Status.Audio.Microphones.Mute.ValueChangedAction = PrivacyModeIsOnFeedback.FireUpdate;
CodecStatus.Status.Standby.State.ValueChangedAction = StandbyIsOnFeedback.FireUpdate;
CodecStatus.Status.RoomAnalytics.PeoplePresence.ValueChangedAction = RoomIsOccupiedFeedback.FireUpdate;
CodecStatus.Status.RoomAnalytics.PeopleCount.Current.ValueChangedAction = PeopleCountFeedback.FireUpdate;
CodecStatus.Status.Cameras.SpeakerTrack.Status.ValueChangedAction = CameraAutoModeIsOnFeedback.FireUpdate;
CodecStatus.Status.Video.Selfview.Mode.ValueChangedAction = SelfviewIsOnFeedback.FireUpdate;
CodecStatus.Status.Video.Selfview.PIPPosition.ValueChangedAction = ComputeSelfviewPipStatus;
CodecStatus.Status.Video.Layout.LayoutFamily.Local.ValueChangedAction = ComputeLocalLayout;
CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction = SharingContentIsOnFeedback.FireUpdate;
CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction = FarEndIsSharingContentFeedback.FireUpdate;
try
{
CodecStatus.Status.Video.Input.MainVideoMute.ValueChangedAction = CameraIsOffFeedback.FireUpdate;
}
catch (Exception ex)
{
Debug.Console(0, this, "Error setting MainVideuMute Action: {0}", ex);
if (ex.InnerException != null)
{
Debug.Console(0, this, "Error setting MainVideuMute Action: {0}", ex);
}
}
}
/// <summary>
/// Creates the fake OSD source, and connects it's AudioVideo output to the CodecOsdIn input
/// to enable routing
/// </summary>
@@ -473,11 +492,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
Debug.Console(2, this, "Setting QR code URL: {0}", mcBridge.QrCodeUrl);
mcBridge.UserCodeChanged += (o, a) => SendMcBrandingUrl(mcBridge);
mcBridge.UserPromptedForCode += (o, a) => DisplayUserCode(mcBridge.UserCode);
SendMcBrandingUrl(mcBridge);
}
}
/// <summary>
/// Displays the code for the specified duration
/// </summary>
/// <param name="code">Mobile Control user code</param>
private void DisplayUserCode(string code)
{
SendText(string.Format("xcommand userinterface message alert display title:\"Mobile Control User Code:\" text:\"{0}\" duration: 30", code));
}
private void SendMcBrandingUrl(IMobileControlRoomBridge mcBridge)
{
if (mcBridge == null)
@@ -544,6 +573,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
prefix + "/Status/Standby" + Delimiter +
prefix + "/Status/Video/Selfview" + Delimiter +
prefix + "/Status/Video/Layout" + Delimiter +
prefix + "/Status/Video/Input/MainVideoMute" + Delimiter +
prefix + "/Bookings" + Delimiter +
prefix + "/Event/CallDisconnect" + Delimiter +
prefix + "/Event/Bookings" + Delimiter +
@@ -933,10 +963,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
JsonConvert.PopulateObject(response, eventReceived);
Debug.Console(2, this, "*** Got an External Source Selection {0} {1}", eventReceived, eventReceived.Event.UserInterface, eventReceived.Event.UserInterface.Presentation.ExternalSource.Selected.SourceIdentifier.Value);
if (RunRouteAction != null)
if (RunRouteAction != null && !_externalSourceChangeRequested)
{
RunRouteAction(eventReceived.Event.UserInterface.Presentation.ExternalSource.Selected.SourceIdentifier.Value, null);
}
_externalSourceChangeRequested = false;
}
}
else if (response.IndexOf("\"CommandResponse\":{") > -1 || response.IndexOf("\"CommandResponse\": {") > -1)
@@ -1633,12 +1665,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public void CameraAutoModeOn()
{
if (CameraIsOffFeedback.BoolValue)
{
CameraMuteOff();
}
SendText("xCommand Cameras SpeakerTrack Activate");
CameraMuteOff();
}
public void CameraAutoModeOff()
{
if (CameraIsOffFeedback.BoolValue)
{
CameraMuteOff();
}
SendText("xCommand Cameras SpeakerTrack Deactivate");
}
@@ -1957,6 +1998,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public void SetSelectedSource(string key)
{
SendText(string.Format("xCommand UserInterface Presentation ExternalSource Select SourceIdentifier: {0}", key));
_externalSourceChangeRequested = true;
}
/// <summary>
@@ -1994,7 +2036,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
/// </summary>
public void CameraMuteOn()
{
SendText("xCommand Video InputMainVideo Mute");
SendText("xCommand Video Input MainVideo Mute");
}
/// <summary>
@@ -2002,7 +2044,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
/// </summary>
public void CameraMuteOff()
{
SendText("xCommand Video InputMainVideo Unmute");
SendText("xCommand Video Input MainVideo Unmute");
}
/// <summary>

View File

@@ -8,6 +8,7 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Devices.Common.VideoCodec.CiscoCodec;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
@@ -1680,6 +1681,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public MainVideoSource MainVideoSource { get; set; }
public MainVideoMute MainVideoMute { get; set; }
public List<Source> Source { get; set; }
public Input2()
{
MainVideoMute = new MainVideoMute();
}
}
public class Local : ValueProperty
@@ -1875,6 +1881,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
Selfview = new Selfview();
Layout = new Layout();
Input = new Input2();
}
}