mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-01-11 19:44:52 +00:00
Compare commits
22 Commits
v2.24.4-fu
...
1.8.5-pr70
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac6b67e63e | ||
|
|
78be8ec5f2 | ||
|
|
5fc4ff6027 | ||
|
|
da179c01f5 | ||
|
|
0ded3e30f9 | ||
|
|
8d215930d9 | ||
|
|
03b076c8eb | ||
|
|
7c58221acc | ||
|
|
14f7c27b33 | ||
|
|
9ea65883b7 | ||
|
|
9d0020d999 | ||
|
|
fb44a3b93c | ||
|
|
6b7c5c01f8 | ||
|
|
1a3eb9a546 | ||
|
|
e6f5142fc3 | ||
|
|
3c9ca1e527 | ||
|
|
452d0a5a39 | ||
|
|
8643ed2caf | ||
|
|
2787c7fc52 | ||
|
|
babc3e4f1a | ||
|
|
0a4ff82af0 | ||
|
|
b455e1af21 |
@@ -36,6 +36,7 @@ namespace PepperDash.Essentials
|
||||
Thread.MaxNumberOfUserThreads = 400;
|
||||
Global.ControlSystem = this;
|
||||
DeviceManager.Initialize(this);
|
||||
SecretsManager.Initialize();
|
||||
SystemMonitor.ProgramInitialization.ProgramInitializationUnderUserControl = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace PepperDash.Essentials.Core
|
||||
public GenericComm(DeviceConfig config)
|
||||
: base(config)
|
||||
{
|
||||
|
||||
PropertiesConfig = CommFactory.GetControlPropertiesConfig(config);
|
||||
|
||||
var commPort = CommFactory.CreateCommForDevice(config);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 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();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
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();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ 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
|
||||
{
|
||||
@@ -52,6 +54,8 @@ 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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -123,25 +123,34 @@ 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 != 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
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,10 +172,6 @@ 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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,8 @@ 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;
|
||||
@@ -25,7 +27,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||
Focus = 8
|
||||
}
|
||||
|
||||
public abstract class CameraBase : EssentialsDevice, IRoutingOutputs
|
||||
public abstract class CameraBase : ReconfigurableDevice, IRoutingOutputs
|
||||
{
|
||||
public eCameraControlMode ControlMode { get; protected set; }
|
||||
|
||||
@@ -70,12 +72,18 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||
// A bitmasked value to indicate the movement capabilites of this camera
|
||||
protected eCameraCapabilities Capabilities { get; set; }
|
||||
|
||||
protected CameraBase(string key, string name) :
|
||||
base(key, name)
|
||||
{
|
||||
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
|
||||
protected CameraBase(DeviceConfig config) : base(config)
|
||||
{
|
||||
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
|
||||
|
||||
ControlMode = eCameraControlMode.Manual;
|
||||
ControlMode = eCameraControlMode.Manual;
|
||||
|
||||
}
|
||||
|
||||
protected CameraBase(string key, string name) :
|
||||
this (new DeviceConfig{Name = name, Key = key})
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected void LinkCameraToApi(CameraBase cameraDevice, BasicTriList trilist, uint joinStart, string joinMapKey,
|
||||
|
||||
Reference in New Issue
Block a user