Compare commits

..

1 Commits

Author SHA1 Message Date
Neil Dorin
a364269c2b Merge 7640b95701 into b3617d04c8 2021-04-08 20:34:12 +00:00
20 changed files with 1623 additions and 2234 deletions

View File

@@ -1,27 +0,0 @@
---
name: Request for Information
about: Request specific information about capabilities of the framework
title: "[RFI]-"
labels: RFI
assignees: ''
---
**What is your request?**
Please provide as much detail as possible.
**What is the intended use case**
- [ ] Essentials Standalone Application
- [ ] Essentials + SIMPL Windows Hybrid
**User Interface Requirements**
- [ ] Not Applicable (logic only)
- [ ] Crestron Smart Graphics Touchpanel
- [ ] Cisco Touch10
- [ ] Mobile Control
- [ ] Crestron CH5 Touchpanel interface
**Additional context**
Add any other context or screenshots about the request here.

View File

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

View File

@@ -19,8 +19,7 @@ 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;
@@ -179,12 +178,10 @@ namespace PepperDash.Essentials
handler(_CurrentSourceInfo, ChangeType.DidChange);
var vc = VideoCodec as IHasExternalSourceSwitching;
if (vc != null && !_codecExternalSourceChange)
if (vc != null)
{
vc.SetSelectedSource(CurrentSourceInfoKey);
}
_codecExternalSourceChange = false;
}
}
SourceListItem _CurrentSourceInfo;
@@ -424,12 +421,6 @@ namespace PepperDash.Essentials
return true;
}
public void RunRouteActionCodec(string routeKey, string sourceListKey)
{
_codecExternalSourceChange = true;
RunRouteAction(routeKey, sourceListKey);
}
/// <summary>
///
/// </summary>
@@ -759,7 +750,7 @@ namespace PepperDash.Essentials
x => x.DestinationKey == VideoCodec.Key && x.DestinationPort == videoCodecWithExternalSwitching.ExternalSourceInputPort).DestinationPort;
videoCodecWithExternalSwitching.ClearExternalSources();
videoCodecWithExternalSwitching.RunRouteAction = RunRouteActionCodec;
videoCodecWithExternalSwitching.RunRouteAction = RunRouteAction;
var srcList = ConfigReader.ConfigObject.SourceLists.SingleOrDefault(x => x.Key == SourceListKey).Value.OrderBy(kv => kv.Value.Order); ;
foreach (var kvp in srcList)

View File

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

View File

@@ -30,19 +30,7 @@ namespace PepperDash.Essentials.Core.Config
[JsonProperty("properties")]
[JsonConverter(typeof(DevicePropertiesConverter))]
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() {}
public JToken Properties { get; set; }
}
/// <summary>

View File

@@ -1,162 +1,162 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
namespace PepperDash.Essentials.Core.Config
{
/// <summary>
/// Responsible for updating config at runtime, and writing the updates out to a local file
/// </summary>
public class ConfigWriter
{
public const string LocalConfigFolder = "LocalConfig";
public const long WriteTimeout = 30000;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
namespace PepperDash.Essentials.Core.Config
{
/// <summary>
/// Responsible for updating config at runtime, and writing the updates out to a local file
/// </summary>
public class ConfigWriter
{
public const string LocalConfigFolder = "LocalConfig";
public const long WriteTimeout = 30000;
public static CTimer WriteTimer;
static CCriticalSection fileLock = new CCriticalSection();
/// <summary>
/// Updates the config properties of a device
/// </summary>
/// <param name="deviceKey"></param>
/// <param name="properties"></param>
/// <returns></returns>
public static bool UpdateDeviceProperties(string deviceKey, JToken properties)
{
bool success = false;
// Get the current device config
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(deviceKey));
if (deviceConfig != null)
{
// Replace the current properties JToken with the new one passed into this method
deviceConfig.Properties = properties;
Debug.Console(1, "Updated properties of device: '{0}'", deviceKey);
success = true;
}
ResetTimer();
return success;
}
public static bool UpdateDeviceConfig(DeviceConfig config)
{
bool success = false;
var deviceConfigIndex = ConfigReader.ConfigObject.Devices.FindIndex(d => d.Key.Equals(config.Key));
if (deviceConfigIndex >= 0)
{
ConfigReader.ConfigObject.Devices[deviceConfigIndex] = config;
Debug.Console(1, "Updated config of device: '{0}'", config.Key);
success = true;
}
ResetTimer();
return success;
}
public static bool UpdateRoomConfig(DeviceConfig config)
{
bool success = false;
var roomConfigIndex = ConfigReader.ConfigObject.Rooms.FindIndex(d => d.Key.Equals(config.Key));
if (roomConfigIndex >= 0)
{
ConfigReader.ConfigObject.Rooms[roomConfigIndex] = config;
Debug.Console(1, "Updated room of device: '{0}'", config.Key);
success = true;
}
ResetTimer();
return success;
}
/// <summary>
/// Resets (or starts) the write timer
/// </summary>
static void ResetTimer()
{
if (WriteTimer == null)
WriteTimer = new CTimer(WriteConfigFile, WriteTimeout);
WriteTimer.Reset(WriteTimeout);
Debug.Console(1, "Config File write timer has been reset.");
}
/// <summary>
/// Writes the current config to a file in the LocalConfig subfolder
/// </summary>
/// <returns></returns>
private static void WriteConfigFile(object o)
{
var filePath = Global.FilePathPrefix + LocalConfigFolder + Global.DirectorySeparator + "configurationFile.json";
var configData = JsonConvert.SerializeObject(ConfigReader.ConfigObject);
WriteFile(filePath, configData);
}
/// <summary>
/// Writes
/// </summary>
/// <param name="filepath"></param>
/// <param name="o"></param>
public static void WriteFile(string filePath, string configData)
{
if (WriteTimer != null)
WriteTimer.Stop();
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Writing Configuration to file");
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to write config file: '{0}'", filePath);
try
{
if (fileLock.TryEnter())
{
using (StreamWriter sw = new StreamWriter(filePath))
{
sw.Write(configData);
sw.Flush();
}
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to enter FileLock");
}
}
catch (Exception e)
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "Error: Config write failed: \r{0}", e);
}
finally
{
if (fileLock != null && !fileLock.Disposed)
fileLock.Leave();
}
}
}
static CCriticalSection fileLock = new CCriticalSection();
/// <summary>
/// Updates the config properties of a device
/// </summary>
/// <param name="deviceKey"></param>
/// <param name="properties"></param>
/// <returns></returns>
public static bool UpdateDeviceProperties(string deviceKey, JToken properties)
{
bool success = false;
// Get the current device config
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(deviceKey));
if (deviceConfig != null)
{
// Replace the current properties JToken with the new one passed into this method
deviceConfig.Properties = properties;
Debug.Console(1, "Updated properties of device: '{0}'", deviceKey);
success = true;
}
ResetTimer();
return success;
}
public static bool UpdateDeviceConfig(DeviceConfig config)
{
bool success = false;
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(config.Key));
if (deviceConfig != null)
{
deviceConfig = config;
Debug.Console(1, "Updated config of device: '{0}'", config.Key);
success = true;
}
ResetTimer();
return success;
}
public static bool UpdateRoomConfig(DeviceConfig config)
{
bool success = false;
var deviceConfig = ConfigReader.ConfigObject.Rooms.FirstOrDefault(d => d.Key.Equals(config.Key));
if (deviceConfig != null)
{
deviceConfig = config;
Debug.Console(1, "Updated config of device: '{0}'", config.Key);
success = true;
}
ResetTimer();
return success;
}
/// <summary>
/// Resets (or starts) the write timer
/// </summary>
static void ResetTimer()
{
if (WriteTimer == null)
WriteTimer = new CTimer(WriteConfigFile, WriteTimeout);
WriteTimer.Reset(WriteTimeout);
Debug.Console(1, "Config File write timer has been reset.");
}
/// <summary>
/// Writes the current config to a file in the LocalConfig subfolder
/// </summary>
/// <returns></returns>
private static void WriteConfigFile(object o)
{
var filePath = Global.FilePathPrefix + LocalConfigFolder + Global.DirectorySeparator + "configurationFile.json";
var configData = JsonConvert.SerializeObject(ConfigReader.ConfigObject);
WriteFile(filePath, configData);
}
/// <summary>
/// Writes
/// </summary>
/// <param name="filepath"></param>
/// <param name="o"></param>
public static void WriteFile(string filePath, string configData)
{
if (WriteTimer != null)
WriteTimer.Stop();
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Writing Configuration to file");
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to write config file: '{0}'", filePath);
try
{
if (fileLock.TryEnter())
{
using (StreamWriter sw = new StreamWriter(filePath))
{
sw.Write(configData);
sw.Flush();
}
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to enter FileLock");
}
}
catch (Exception e)
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "Error: Config write failed: \r{0}", e);
}
finally
{
if (fileLock != null && !fileLock.Disposed)
fileLock.Leave();
}
}
}
}

View File

@@ -7,8 +7,6 @@ using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace PepperDash.Essentials.Core.Devices
{
@@ -54,8 +52,6 @@ namespace PepperDash.Essentials.Core.Devices
Name = config.Name;
}
/// <summary>
/// Used by the extending class to allow for any custom actions to be taken (tell the ConfigWriter to write config, etc)
/// </summary>

View File

@@ -1,42 +0,0 @@
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,8 +7,6 @@ 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;
@@ -85,81 +83,33 @@ namespace PepperDash.Essentials.Core
var wrapper = new DeviceFactoryWrapper() { CType = cType, Description = description, FactoryMethod = method };
DeviceFactory.FactoryMethods.Add(typeName, wrapper);
}
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>
/// 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;
}
/// <summary>
/// Prints the type names and associated metadata from the FactoryMethods collection.
/// </summary>

View File

@@ -209,7 +209,6 @@
<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" />
@@ -321,10 +320,6 @@
<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,27 +358,14 @@ namespace PepperDash.Essentials
try
{
var assy = loadedAssembly.Assembly;
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;
}
var types = assy.GetTypes();
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
@@ -391,11 +378,6 @@ 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}",
@@ -407,9 +389,7 @@ namespace PepperDash.Essentials
}
catch (Exception e)
{
Debug.Console(0, Debug.ErrorLogLevel.Warning, "Error Loading assembly {0}: {1}",
loadedAssembly.Name, e.Message);
Debug.Console(2, "{0}", e.StackTrace);
Debug.Console(2, "Error Loading Assembly: {0} Exception: {1} ", loadedAssembly.Name, e);
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;
@@ -158,7 +158,7 @@ namespace PepperDash.Essentials.Core.Queues
Dispose(true);
};
}
/// <summary>
/// Thread callback
/// </summary>

View File

@@ -123,34 +123,25 @@ namespace PepperDash.Essentials.Core
// No direct tie? Run back out on the inputs' attached devices...
// Only the ones that are routing devices
var attachedMidpoints = destDevInputTies.Where(t => t.SourcePort.ParentDevice is IRoutingInputsOutputs);
//Create a list for tracking already checked devices to avoid loops, if it doesn't already exist from previous iteration
if (alreadyCheckedDevices == null)
alreadyCheckedDevices = new List<IRoutingInputsOutputs>();
alreadyCheckedDevices.Add(destination as IRoutingInputsOutputs);
foreach (var inputTieToTry in attachedMidpoints)
{
Debug.Console(2, destination, "Trying to find route on {0}", inputTieToTry.SourcePort.ParentDevice.Key);
var upstreamDeviceOutputPort = inputTieToTry.SourcePort;
var upstreamRoutingDevice = upstreamDeviceOutputPort.ParentDevice as IRoutingInputsOutputs;
Debug.Console(2, destination, "Trying to find route on {0}", upstreamRoutingDevice.Key);
// Check if this previous device has already been walked
if (alreadyCheckedDevices.Contains(upstreamRoutingDevice))
{
Debug.Console(2, destination, "Skipping input {0} on {1}, this was already checked", upstreamRoutingDevice.Key, destination.Key);
continue;
}
// haven't seen this device yet. Do it. Pass the output port to the next
// level to enable switching on success
var upstreamRoutingSuccess = upstreamRoutingDevice.GetRouteToSource(source, upstreamDeviceOutputPort,
alreadyCheckedDevices, signalType, cycle, routeTable);
if (upstreamRoutingSuccess)
{
Debug.Console(2, destination, "Upstream device route found");
goodInputPort = inputTieToTry.DestinationPort;
break; // Stop looping the inputs in this cycle
}
if (!(alreadyCheckedDevices != null && alreadyCheckedDevices.Contains(upstreamRoutingDevice)))
{
// haven't seen this device yet. Do it. Pass the output port to the next
// level to enable switching on success
var upstreamRoutingSuccess = upstreamRoutingDevice.GetRouteToSource(source, upstreamDeviceOutputPort,
alreadyCheckedDevices, signalType, cycle, routeTable);
if (upstreamRoutingSuccess)
{
Debug.Console(2, destination, "Upstream device route found");
goodInputPort = inputTieToTry.DestinationPort;
break; // Stop looping the inputs in this cycle
}
}
}
}
@@ -172,6 +163,10 @@ namespace PepperDash.Essentials.Core
//Debug.Console(2, destination, "Exiting cycle {0}", cycle);
return true;
}
if(alreadyCheckedDevices == null)
alreadyCheckedDevices = new List<IRoutingInputsOutputs>();
alreadyCheckedDevices.Add(destination as IRoutingInputsOutputs);
Debug.Console(2, destination, "No route found to {0}", source.Key);
return false;

View File

@@ -1,97 +0,0 @@
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

@@ -1,24 +0,0 @@
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

@@ -1,281 +0,0 @@
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

@@ -1,20 +0,0 @@
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

@@ -8,8 +8,6 @@ using Crestron.SimplSharp.Reflection;
using Crestron.SimplSharpPro.DeviceSupport;
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.Presets;
using PepperDash.Essentials.Devices.Common.Codec;
@@ -27,7 +25,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
Focus = 8
}
public abstract class CameraBase : ReconfigurableDevice, IRoutingOutputs
public abstract class CameraBase : EssentialsDevice, IRoutingOutputs
{
public eCameraControlMode ControlMode { get; protected set; }
@@ -72,18 +70,12 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
// A bitmasked value to indicate the movement capabilites of this camera
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})
protected CameraBase(string key, string name) :
base(key, name)
{
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
ControlMode = eCameraControlMode.Manual;
}
protected void LinkCameraToApi(CameraBase cameraDevice, BasicTriList trilist, uint joinStart, string joinMapKey,

View File

@@ -30,8 +30,6 @@ 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;
@@ -963,12 +961,10 @@ 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 && !_externalSourceChangeRequested)
if (RunRouteAction != null)
{
RunRouteAction(eventReceived.Event.UserInterface.Presentation.ExternalSource.Selected.SourceIdentifier.Value, null);
}
_externalSourceChangeRequested = false;
}
}
else if (response.IndexOf("\"CommandResponse\":{") > -1 || response.IndexOf("\"CommandResponse\": {") > -1)
@@ -1998,7 +1994,6 @@ 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>