diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index be78aaf9..53ea9e13 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -490,21 +490,17 @@ namespace PepperDash.Essentials } } + AddRoomAndBuildMC(room); + if (room is IEssentialsHuddleSpaceRoom) { - DeviceManager.AddDevice(room); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId); DeviceManager.AddDevice(new Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase(room, fusionIpId, fusionJoinMapKey)); - - Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge..."); - - CreateMobileControlBridge(room); } else if (room is IEssentialsHuddleVtc1Room) { - DeviceManager.AddDevice(room); if (!(room is EssentialsCombinedHuddleVtc1Room)) { @@ -512,28 +508,15 @@ namespace PepperDash.Essentials DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((IEssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey)); } - Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge..."); - - CreateMobileControlBridge(room); } else if (room is EssentialsTechRoom) { - DeviceManager.AddDevice(room); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsTechRoom, Attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId); DeviceManager.AddDevice(new EssentialsTechRoomFusionSystemController((EssentialsTechRoom)room, fusionIpId, fusionJoinMapKey)); - Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge"); - - CreateMobileControlBridge(room); } - else - { - Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is NOT EssentialsRoom, attempting to add to DeviceManager w/o Fusion"); - DeviceManager.AddDevice(room); - } - fusionIpId += 1; } else @@ -547,6 +530,15 @@ namespace PepperDash.Essentials } + private static void AddRoomAndBuildMC(IEssentialsRoom room) + { + DeviceManager.AddDevice(room); + + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge"); + + CreateMobileControlBridge(room); + } + private static void CreateMobileControlBridge(object room) { var mobileControl = GetMobileControlDevice(); diff --git a/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs b/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs index 5a2bd34f..20d1ce75 100644 --- a/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs +++ b/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs @@ -19,32 +19,41 @@ namespace PepperDash.Essentials.Room.Config /// Returns a room object from this config data /// /// - public static Device GetRoomObject(DeviceConfig roomConfig) + public static IKeyed GetRoomObject(DeviceConfig roomConfig) { var typeName = roomConfig.Type.ToLower(); - if (typeName == "huddle") - { - return new EssentialsHuddleSpaceRoom(roomConfig); - } - if (typeName == "huddlevtc1") + switch (typeName) { - return new EssentialsHuddleVtc1Room(roomConfig); + case "huddle" : + { + return new EssentialsHuddleSpaceRoom(roomConfig); + } + case "huddlevtc1" : + { + return new EssentialsHuddleVtc1Room(roomConfig); + } + case "ddvc01bridge" : + { + return new Device(roomConfig.Key, roomConfig.Name); // placeholder device that does nothing. + } + case "dualdisplay" : + { + return new EssentialsDualDisplayRoom(roomConfig); + } + case "combinedhuddlevtc1" : + { + return new EssentialsCombinedHuddleVtc1Room(roomConfig); + } + case "techroom" : + { + return new EssentialsTechRoom(roomConfig); + } + default : + { + return Core.DeviceFactory.GetDevice(roomConfig); + } } - if (typeName == "ddvc01bridge") - { - return new Device(roomConfig.Key, roomConfig.Name); // placeholder device that does nothing. - } - if (typeName == "dualdisplay") - { - return new EssentialsDualDisplayRoom(roomConfig); - } - if (typeName == "combinedhuddlevtc1") - { - return new EssentialsCombinedHuddleVtc1Room(roomConfig); - } - - return typeName != "techroom" ? null : new EssentialsTechRoom(roomConfig); } /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/PduJoinMapBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/PduJoinMapBase.cs new file mode 100644 index 00000000..2ac56ff1 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/PduJoinMapBase.cs @@ -0,0 +1,60 @@ +using System; + +namespace PepperDash.Essentials.Core.Bridges +{ + public class PduJoinMapBase : JoinMapBaseAdvanced + { + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "PDU Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("Online")] + public JoinDataComplete Online = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "PDU Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutletCount")] + public JoinDataComplete OutletCount = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Number of COntrolled Outlets", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("OutletName")] + public JoinDataComplete OutletName = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "Outlet Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("OutletEnabled")] + public JoinDataComplete OutletEnabled = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "Outlet Enabled", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutletPowerCycle")] + public JoinDataComplete OutletPowerCycle = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata { Description = "Outlet Power Cycle", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutletPowerOn")] + public JoinDataComplete OutletPowerOn = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, + new JoinMetadata { Description = "Outlet Power On", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutletPowerOff")] + public JoinDataComplete OutletPowerOff = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, + new JoinMetadata { Description = "Outlet Power Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public PduJoinMapBase(uint joinStart) + :base(joinStart, typeof(PduJoinMapBase)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + public PduJoinMapBase(uint joinStart, Type type) + : base(joinStart, type) + { + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index d1b383b0..9e982700 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -1,4 +1,4 @@ -using System; +using System; using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Core.Bridges.JoinMaps { @@ -1576,6 +1576,36 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); + [JoinName("AvailableLayoutsFb")] + public JoinDataComplete AvailableLayoutsFb = new JoinDataComplete( + new JoinData + { + JoinNumber = 142, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "xSig of all available layouts", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SelectLayout")] + public JoinDataComplete SelectLayout = new JoinDataComplete( + new JoinData + { + JoinNumber = 142, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Select Layout by string", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + + [JoinName("CurrentParticipants")] public JoinDataComplete CurrentParticipants = new JoinDataComplete( new JoinData @@ -3014,6 +3044,35 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); + [JoinName("AvailableLayoutsFb")] + public JoinDataComplete AvailableLayoutsFb = new JoinDataComplete( + new JoinData + { + JoinNumber = 142, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "xSig of all available layouts", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SelectLayout")] + public JoinDataComplete SelectLayout = new JoinDataComplete( + new JoinData + { + JoinNumber = 142, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Select Layout by string", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentParticipants")] public JoinDataComplete CurrentParticipants = new JoinDataComplete( new JoinData @@ -3111,4 +3170,4 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps { } } -} +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/DeviceConfig.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/DeviceConfig.cs index 1d9ed1c2..5c1ee54c 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/DeviceConfig.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/DeviceConfig.cs @@ -1,35 +1,35 @@ -using System; -using System.Collections.Generic; -using Crestron.SimplSharp; -using Crestron.SimplSharp.CrestronIO; -using Crestron.SimplSharpPro; - -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using PepperDash.Core; -using PepperDash.Essentials.Core; - -namespace PepperDash.Essentials.Core.Config -{ - public class DeviceConfig - { - [JsonProperty("key")] - public string Key { get; set; } - - [JsonProperty("uid")] - public int Uid { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("group")] - public string Group { get; set; } - - [JsonProperty("type")] - public string Type { get; set; } - - [JsonProperty("properties")] - [JsonConverter(typeof(DevicePropertiesConverter))] +using System; +using System.Collections.Generic; +using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronIO; +using Crestron.SimplSharpPro; + +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Core.Config +{ + public class DeviceConfig + { + [JsonProperty("key")] + public string Key { get; set; } + + [JsonProperty("uid")] + public int Uid { get; set; } + + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("group")] + public string Group { get; set; } + + [JsonProperty("type")] + public string Type { get; set; } + + [JsonProperty("properties")] + [JsonConverter(typeof(DevicePropertiesConverter))] public JToken Properties { get; set; } public DeviceConfig(DeviceConfig dc) @@ -39,39 +39,42 @@ namespace PepperDash.Essentials.Core.Config Name = dc.Name; Group = dc.Group; Type = dc.Type; - Properties = JToken.FromObject(dc.Properties); + + Properties = JToken.Parse(dc.Properties.ToString()); + + //Properties = JToken.FromObject(dc.Properties); } public DeviceConfig() {} - } - - /// - /// - /// - public class DevicePropertiesConverter : JsonConverter - { - - public override bool CanConvert(Type objectType) - { - return objectType == typeof(JToken); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - return JToken.ReadFrom(reader); - } - - public override bool CanWrite - { - get - { - return false; - } - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - throw new NotImplementedException("SOD OFF HOSER"); - } - } + } + + /// + /// + /// + public class DevicePropertiesConverter : JsonConverter + { + + public override bool CanConvert(Type objectType) + { + return objectType == typeof(JToken); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + return JToken.ReadFrom(reader); + } + + public override bool CanWrite + { + get + { + return false; + } + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException("SOD OFF HOSER"); + } + } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IVolumeAndAudioInterfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IVolumeAndAudioInterfaces.cs index 1cff62fc..c8a5df39 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IVolumeAndAudioInterfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IVolumeAndAudioInterfaces.cs @@ -7,25 +7,61 @@ using Crestron.SimplSharp; namespace PepperDash.Essentials.Core { /// - /// Defines minimal volume control methods + /// Defines minimal volume and mute control methods /// - public interface IBasicVolumeControls + public interface IBasicVolumeControls { void VolumeUp(bool pressRelease); void VolumeDown(bool pressRelease); void MuteToggle(); } + /// + /// Defines basic volume control methods + /// + public interface IHasVolumeControl + { + void VolumeUp(bool pressRelease); + void VolumeDown(bool pressRelease); + } + + /// + /// Defines volume control methods and properties with feedback + /// + public interface IHasVolumeControlWithFeedback : IHasVolumeControl + { + void SetVolume(ushort level); + IntFeedback VolumeLevelFeedback { get; } + } + + /// + /// Defines basic mute control methods + /// + public interface IHasMuteControl + { + void MuteToggle(); + } + + /// + /// Defines mute control methods and properties with feedback + /// + public interface IHasMuteControlWithFeedback : IHasMuteControl + { + BoolFeedback MuteFeedback { get; } + void MuteOn(); + void MuteOff(); + } + /// /// Adds feedback and direct volume level set to IBasicVolumeControls /// - public interface IBasicVolumeWithFeedback : IBasicVolumeControls + public interface IBasicVolumeWithFeedback : IBasicVolumeControls { - void SetVolume(ushort level); - void MuteOn(); - void MuteOff(); - IntFeedback VolumeLevelFeedback { get; } BoolFeedback MuteFeedback { get; } + void MuteOn(); + void MuteOff(); + void SetVolume(ushort level); + IntFeedback VolumeLevelFeedback { get; } } /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/PduInterfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/PduInterfaces.cs new file mode 100644 index 00000000..0f3b3fbf --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/PduInterfaces.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using Crestron.SimplSharp; +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace PepperDash_Essentials_Core.Devices +{ + /// + /// Interface for any device that is able to control it'spower and has a configurable reboot time + /// + public interface IHasPowerCycle : IKeyName, IHasPowerControlWithFeedback + { + /// + /// Delay between power off and power on for reboot + /// + int PowerCycleTimeMs { get;} + + /// + /// Reboot outlet + /// + void PowerCycle(); + } + + /// + /// Interface for any device that contains a collection of IHasPowerReboot Devices + /// + public interface IHasControlledPowerOutlets : IKeyName + { + /// + /// Collection of IPduOutlets + /// + ReadOnlyDictionary PduOutlets { get; } + + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs index 3239e192..a54f728d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs @@ -59,7 +59,7 @@ namespace PepperDash.Essentials.Core.Devices /// /// Used by the extending class to allow for any custom actions to be taken (tell the ConfigWriter to write config, etc) /// - /// + /// protected virtual void CustomSetConfig(DeviceConfig config) { ConfigWriter.UpdateDeviceConfig(config); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/File/FileIO.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/File/FileIO.cs new file mode 100644 index 00000000..51d64230 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/File/FileIO.cs @@ -0,0 +1,278 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronIO; +using PepperDash.Core; +using Crestron.SimplSharpPro.CrestronThread; + +namespace PepperDash.Essentials.Core +{ + public static class FileIO + { + + static CCriticalSection fileLock = new CCriticalSection(); + public delegate void GotFileEventHandler(object sender, FileEventArgs e); + public static event GotFileEventHandler GotFileEvent; + + /// + /// Get the full file info from a path/filename, can include wildcards. + /// + /// + /// + public static FileInfo[] GetFiles(string fileName) + { + DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(fileName)); + var files = dirInfo.GetFiles(Path.GetFileName(fileName)); + Debug.Console(0, "FileIO found: {0}, {1}", files.Count(), fileName); + if (files.Count() > 0) + { + return files; + } + else + { + return null; + } + } + + public static FileInfo GetFile(string fileName) + { + DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(fileName)); + var files = dirInfo.GetFiles(Path.GetFileName(fileName)); + Debug.Console(0, "FileIO found: {0}, {1}", files.Count(), fileName); + if (files.Count() > 0) + { + return files.FirstOrDefault(); + } + else + { + return null; + } + } + + + /// + /// Get the data from string path/filename + /// + /// + /// + public static string ReadDataFromFile(string fileName) + { + try + { + return ReadDataFromFile(GetFile(fileName)); + } + catch (Exception e) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "Error: FileIO read failed: \r{0}", e); + return ""; + } + } + + /// + /// Get the data with fileInfo object + /// + /// + /// + public static string ReadDataFromFile(FileInfo file) + { + try + { + if (fileLock.TryEnter()) + { + DirectoryInfo dirInfo = new DirectoryInfo(file.Name); + Debug.Console(2, "FileIO Getting Data {0}", file.FullName); + + if (File.Exists(file.FullName)) + { + using (StreamReader r = new StreamReader(file.FullName)) + { + return r.ReadToEnd(); + } + } + else + { + Debug.Console(2, "File {0} does not exsist", file.FullName); + return ""; + } + } + else + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "FileIO Unable to enter FileLock"); + return ""; + } + + } + catch (Exception e) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "Error: FileIO read failed: \r{0}", e); + return ""; + } + finally + { + if (fileLock != null && !fileLock.Disposed) + fileLock.Leave(); + + } + } + + + public static void ReadDataFromFileASync(string fileName) + { + try + { + ReadDataFromFileASync(GetFile(fileName)); + } + catch (Exception e) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "Error: FileIO read failed: \r{0}", e); + } + } + + public static void ReadDataFromFileASync(FileInfo file) + { + try + { + CrestronInvoke.BeginInvoke(o => _ReadDataFromFileASync(file)); + } + catch (Exception e) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "Error: FileIO read failed: \r{0}", e); + } + } + + private static void _ReadDataFromFileASync(FileInfo file) + { + string data; + try + { + if (fileLock.TryEnter()) + { + DirectoryInfo dirInfo = new DirectoryInfo(file.Name); + Debug.Console(2, "FileIO Getting Data {0}", file.FullName); + + + if (File.Exists(file.FullName)) + { + using (StreamReader r = new StreamReader(file.FullName)) + { + data = r.ReadToEnd(); + } + } + else + { + Debug.Console(2, "File {0} Does not exsist", file.FullName); + data = ""; + } + GotFileEvent.Invoke(null, new FileEventArgs(data)); + } + else + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "FileIO Unable to enter FileLock"); + } + + } + catch (Exception e) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "Error: FileIO read failed: \r{0}", e); + data = ""; + } + finally + { + if (fileLock != null && !fileLock.Disposed) + fileLock.Leave(); + + } + + + + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void WriteDataToFile(string data, string filePath) + { + Thread _WriteFileThread; + _WriteFileThread = new Thread((O) => _WriteFileMethod(data, filePath), null, Thread.eThreadStartOptions.CreateSuspended); + _WriteFileThread.Priority = Thread.eThreadPriority.LowestPriority; + _WriteFileThread.Start(); + Debug.Console(0, Debug.ErrorLogLevel.Notice, "New WriteFile Thread"); + + } + + static object _WriteFileMethod(string data, string filePath) + { + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to write file: '{0}'", filePath); + + try + { + if (fileLock.TryEnter()) + { + using (StreamWriter sw = new StreamWriter(filePath)) + { + sw.Write(data); + sw.Flush(); + } + + } + else + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "FileIO Unable to enter FileLock"); + } + + } + catch (Exception e) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "Error: FileIO write failed: \r{0}", e); + } + finally + { + if (fileLock != null && !fileLock.Disposed) + fileLock.Leave(); + + } + return null; + + } + + /// + /// + /// + /// + public static bool FileIoUnitTest() + { + var testData = "Testing FileIO"; + FileIO.WriteDataToFile(testData, "\\user\\FileIOTest.pdt"); + + var file = FileIO.GetFile("\\user\\*FileIOTest*"); + + var readData = FileIO.ReadDataFromFile(file); + Debug.Console(0, "Returned {0}", readData); + File.Delete(file.FullName); + if (testData == readData) + { + return true; + } + else + { + return false; + } + } + + } + public class FileEventArgs + { + public FileEventArgs(string data) { Data = data; } + public string Data { get; private set; } // readonly + + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Lighting/LightingBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Lighting/LightingBase.cs index 604965af..48a4aa76 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Lighting/LightingBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Lighting/LightingBase.cs @@ -92,50 +92,47 @@ namespace PepperDash.Essentials.Core.Lighting return LinkLightingToApi(lightingDevice, trilist, joinMap); } - protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, GenericLightingJoinMap joinMap) - { + protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, GenericLightingJoinMap joinMap) + { + Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + Debug.Console(0, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString()); - Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + // GenericLighitng Actions & FeedBack + trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u])); - Debug.Console(0, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString()); + var sceneIndex = 0; + foreach (var scene in lightingDevice.LightingScenes) + { + var index = sceneIndex; - // GenericLighitng Actions & FeedBack - trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u])); + trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + index), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[index])); + scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)]); + trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name; + trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true; - var sceneIndex = 0; - foreach (var scene in lightingDevice.LightingScenes) - { - var index = sceneIndex; + sceneIndex++; + } - trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + index), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[index])); - scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)]); - trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name; - trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true; + trilist.OnlineStatusChange += (sender, args) => + { + if (!args.DeviceOnLine) return; - sceneIndex++; - } + sceneIndex = 0; + foreach (var scene in lightingDevice.LightingScenes) + { + var index = sceneIndex; - trilist.OnlineStatusChange += (sender, args) => - { - if (!args.DeviceOnLine) return; + trilist.StringInput[(uint) (joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name; + trilist.BooleanInput[(uint) (joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true; + scene.IsActiveFeedback.FireUpdate(); - sceneIndex = 0; - foreach (var scene in lightingDevice.LightingScenes) - { - var index = sceneIndex; - - trilist.StringInput[(uint) (joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name; - trilist.BooleanInput[(uint) (joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true; - scene.IsActiveFeedback.FireUpdate(); - - sceneIndex++; - } - }; - - return joinMap; - } + sceneIndex++; + } + }; + return joinMap; + } } public class LightingScene diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index cdf6406c..252a881e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -123,6 +123,7 @@ + @@ -203,6 +204,7 @@ + @@ -224,6 +226,7 @@ + @@ -335,7 +338,9 @@ - + + + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronGlobalSecretsProvider.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronGlobalSecretsProvider.cs new file mode 100644 index 00000000..5adefd9e --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronGlobalSecretsProvider.cs @@ -0,0 +1,102 @@ +using System; +using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronDataStore; +using PepperDash.Core; + + +namespace PepperDash.Essentials.Core +{ + public class CrestronGlobalSecretsProvider : ISecretProvider + { + public string Key { get; set; } + //Added for reference + public string Description { get; private set; } + + public CrestronGlobalSecretsProvider(string key) + { + Key = key; + Description = String.Format("Default secret provider serving all local applications"); + + } + + static CrestronGlobalSecretsProvider() + { + //Added for future encrypted reference + var secureSupported = CrestronSecureStorage.Supported; + + CrestronDataStoreStatic.InitCrestronDataStore(); + if (secureSupported) + { + //doThingsFuture + } + } + + /// + /// Set secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// Secret Value + public bool SetSecret(string key, object value) + { + var secret = value as string; + CrestronDataStore.CDS_ERROR returnCode; + + if (String.IsNullOrEmpty(secret)) + { + returnCode = CrestronDataStoreStatic.clearGlobal(key); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + { + Debug.Console(0, this, "Successfully removed secret \"{0}\"", secret); + return true; + } + } + + else + { + returnCode = CrestronDataStoreStatic.SetGlobalStringValue(key, secret); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + { + Debug.Console(0, this, "Successfully set secret \"{0}\"", secret); + return true; + } + } + + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to set secret for {0}:{1} - {2}", Key, key, returnCode.ToString()); + return false; + } + + /// + /// Retrieve secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// ISecret Object containing key, provider, and value + public ISecret GetSecret(string key) + { + string mySecret; + var getErrorCode = CrestronDataStoreStatic.GetGlobalStringValue(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; + } + } + + /// + /// Determine if a secret is present within the provider without retrieving it + /// + /// Secret Key + /// bool if present + public bool TestSecret(string key) + { + string mySecret; + return CrestronDataStoreStatic.GetGlobalStringValue(key, out mySecret) == CrestronDataStore.CDS_ERROR.CDS_SUCCESS; + } + } + +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronLocalSecretsProvider.cs similarity index 52% rename from essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs rename to essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronLocalSecretsProvider.cs index 3e0a5964..955c875c 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronLocalSecretsProvider.cs @@ -1,97 +1,103 @@ -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 - } - } - - /// - /// Set secret for item in the CrestronSecretsProvider - /// - /// Secret Key - /// Secret Value - 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; - } - } - - /// - /// Retrieve secret for item in the CrestronSecretsProvider - /// - /// Secret Key - /// ISecret Object containing key, provider, and value - 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; - } - } - } - - /// - /// Special container class for CrestronSecret provider - /// - 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; - } - - } +using System; +using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronDataStore; +using PepperDash.Core; +using Crestron.SimplSharpPro; + + +namespace PepperDash.Essentials.Core +{ + public class CrestronLocalSecretsProvider : ISecretProvider + { + public string Key { get; set; } + //Added for reference + public string Description { get; private set; } + + + public CrestronLocalSecretsProvider(string key) + { + Key = key; + Description = String.Format("Default secret provider serving Essentials Application {0}", InitialParametersClass.ApplicationNumber); + } + + static CrestronLocalSecretsProvider() + { + //Added for future encrypted reference + var secureSupported = CrestronSecureStorage.Supported; + + CrestronDataStoreStatic.InitCrestronDataStore(); + if (secureSupported) + { + //doThingsFuture + } + } + + /// + /// Set secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// Secret Value + public bool SetSecret(string key, object value) + { + var secret = value as string; + CrestronDataStore.CDS_ERROR returnCode; + + if (String.IsNullOrEmpty(secret)) + { + returnCode = CrestronDataStoreStatic.clearLocal(key); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + { + Debug.Console(0, this, "Successfully removed secret \"{0}\"", secret); + return true; + } + } + + else + { + returnCode = CrestronDataStoreStatic.SetLocalStringValue(key, secret); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + { + Debug.Console(0, this, "Successfully set secret \"{0}\"", secret); + return true; + } + } + + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to set secret for {0}:{1} - {2}", Key, key, returnCode.ToString()); + return false; + } + + /// + /// Retrieve secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// ISecret Object containing key, provider, and value + 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; + } + } + + /// + /// Determine if a secret is present within the provider without retrieving it + /// + /// Secret Key + /// bool if present + public bool TestSecret(string key) + { + string mySecret; + return CrestronDataStoreStatic.GetLocalStringValue(key, out mySecret) == CrestronDataStore.CDS_ERROR.CDS_SUCCESS; + } + } + } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecret.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecret.cs new file mode 100644 index 00000000..27fbcdad --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecret.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Essentials.Core +{ + /// + /// Special container class for CrestronSecret provider + /// + 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; + } + + } + +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs index 43c6a230..e61ac208 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs @@ -7,9 +7,32 @@ namespace PepperDash.Essentials.Core /// public interface ISecretProvider : IKeyed { + /// + /// Set secret value for provider by key + /// + /// key of secret to set + /// value to set secret to + /// bool SetSecret(string key, object value); + /// + /// Return object containing secret from provider + /// + /// key of secret to retrieve + /// ISecret GetSecret(string key); + + /// + /// Verifies presence of secret + /// + /// key of secret to chek + /// + bool TestSecret(string key); + + /// + /// Description of the secrets provider + /// + string Description { get; } } /// @@ -17,8 +40,19 @@ namespace PepperDash.Essentials.Core /// public interface ISecret { + /// + /// Instance of ISecretProvider that the secret belongs to + /// ISecretProvider Provider { get; } + + /// + /// Key of the secret in the provider + /// string Key { get; } + + /// + /// Value of the secret + /// object Value { get; } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs index bcb46ff5..95a94a24 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; +using System.Linq; using Crestron.SimplSharp; using PepperDash.Core; - namespace PepperDash.Essentials.Core { public static class SecretsManager @@ -16,18 +16,28 @@ namespace PepperDash.Essentials.Core public static void Initialize() { - AddSecretProvider("default", new CrestronSecretsProvider("default")); + AddSecretProvider("default", new CrestronLocalSecretsProvider("default")); + + AddSecretProvider("CrestronGlobalSecrets", new CrestronGlobalSecretsProvider("CrestronGlobalSecrets")); CrestronConsole.AddNewConsoleCommand(SetSecretProcess, "setsecret", - "Adds secrets to secret provider", + "Adds secret to secrets provider", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(UpdateSecretProcess, "updatesecret", - "Updates secrets in secret provider", + "Updates secret in secrets provider", ConsoleAccessLevelEnum.AccessAdministrator); CrestronConsole.AddNewConsoleCommand(DeleteSecretProcess, "deletesecret", - "Deletes secrets in secret provider", + "Deletes secret from secrest provider", + ConsoleAccessLevelEnum.AccessAdministrator); + + CrestronConsole.AddNewConsoleCommand(ListProviders, "secretproviderlist", + "Return list of all valid secrets providers", + ConsoleAccessLevelEnum.AccessAdministrator); + + CrestronConsole.AddNewConsoleCommand(GetProviderInfo, "secretproviderinfo", + "Return data about secrets provider", ConsoleAccessLevelEnum.AccessAdministrator); } @@ -54,6 +64,79 @@ namespace PepperDash.Essentials.Core return secret; } + public static void GetProviderInfo(string cmd) + { + string response; + var args = cmd.Split(' '); + + if (cmd.Length == 0 || (args.Length == 1 && args[0] == "?")) + { + response = "Returns data about secrets provider. Format 'secretproviderinfo '"; + CrestronConsole.ConsoleCommandResponse(response); + return; + + } + + if (args.Length == 1) + { + var provider = GetSecretProviderByKey(args[0]); + + if (provider == null) + { + response = "Invalid secrets provider key"; + CrestronConsole.ConsoleCommandResponse(response); + return; + } + + response = String.Format("{0} : {1}", provider.Key, provider.Description); + CrestronConsole.ConsoleCommandResponse(response); + return; + } + + response = "Improper number of arguments"; + CrestronConsole.ConsoleCommandResponse(response); + + } + + + /// + /// Console Command that returns all valid secrets in the essentials program. + /// + /// + public static void ListProviders(string cmd) + { + var response = String.Empty; + var args = cmd.Split(' '); + + if (cmd.Length == 0) + { + if (Secrets != null && Secrets.Count > 0) + { + response = Secrets.Aggregate(response, + (current, secretProvider) => current + (secretProvider.Key + "\n\r")); + } + else + { + response = "No Secrets Providers Available"; + } + CrestronConsole.ConsoleCommandResponse(response); + return; + + } + + if (args.Length == 1 && args[0] == "?") + { + response = "Reports all valid and preset Secret providers"; + CrestronConsole.ConsoleCommandResponse(response); + return; + } + + + response = "Improper number of arguments"; + CrestronConsole.ConsoleCommandResponse(response); + + } + /// /// Add secret provider to secrets dictionary /// @@ -100,14 +183,14 @@ namespace PepperDash.Essentials.Core if (args.Length == 0) { //some Instructional Text - response = "Adds secrets to secret provider. Format 'setsecret "; + response = "Adds secrets to secret provider. Format 'setsecret '"; CrestronConsole.ConsoleCommandResponse(response); return; } if (args.Length == 1 && args[0] == "?") { - response = "Adds secrets to secret provider. Format 'setsecret "; + response = "Adds secrets to secret provider. Format 'setsecret '"; CrestronConsole.ConsoleCommandResponse(response); return; } @@ -134,23 +217,7 @@ namespace PepperDash.Essentials.Core 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); + CrestronConsole.ConsoleCommandResponse(SetSecret(provider, key, secret)); } private static void UpdateSecretProcess(string cmd) @@ -161,7 +228,7 @@ namespace PepperDash.Essentials.Core if (args.Length == 0) { //some Instructional Text - response = "Updates secrets in secret provider. Format 'updatesecret "; + response = "Updates secrets in secret provider. Format 'updatesecret '"; CrestronConsole.ConsoleCommandResponse(response); return; @@ -169,7 +236,7 @@ namespace PepperDash.Essentials.Core if (args.Length == 1 && args[0] == "?") { - response = "Updates secrets in secret provider. Format 'updatesecret "; + response = "Updates secrets in secret provider. Format 'updatesecret '"; CrestronConsole.ConsoleCommandResponse(response); return; } @@ -198,23 +265,49 @@ namespace PepperDash.Essentials.Core 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; - } + CrestronConsole.ConsoleCommandResponse(UpdateSecret(provider, key, secret)); + + } + + private static string UpdateSecret(ISecretProvider provider, string key, string secret) + { + var secretPresent = provider.TestSecret(key); + + Debug.Console(2, provider, "SecretsProvider {0} {1} contain a secret entry for {2}", provider.Key, secretPresent ? "does" : "does not", key); + + if (!secretPresent) + return + String.Format( + "Unable to update secret for {0}:{1} - Please use the 'SetSecret' command to modify it"); + var 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); + return response; + } + + private static string SetSecret(ISecretProvider provider, string key, string secret) + { + var secretPresent = provider.TestSecret(key); + + Debug.Console(2, provider, "SecretsProvider {0} {1} contain a secret entry for {2}", provider.Key, secretPresent ? "does" : "does not", key); + + if (secretPresent) + return + String.Format( + "Unable to set secret for {0}:{1} - Please use the 'UpdateSecret' command to modify it"); + var 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); + return response; - 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) @@ -225,14 +318,14 @@ namespace PepperDash.Essentials.Core if (args.Length == 0) { //some Instructional Text - response = "Deletes secrets in secret provider. Format 'deletesecret "; + response = "Deletes secrets in secret provider. Format 'deletesecret '"; CrestronConsole.ConsoleCommandResponse(response); return; } if (args.Length == 1 && args[0] == "?") { - response = "Deletes secrets in secret provider. Format 'deletesecret "; + response = "Deletes secrets in secret provider. Format 'deletesecret '"; CrestronConsole.ConsoleCommandResponse(response); return; } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/SmartObjects/SubpageReferencList/SubpageReferenceList.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/SmartObjects/SubpageReferencList/SubpageReferenceList.cs index fe69e4ca..711a3cde 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/SmartObjects/SubpageReferencList/SubpageReferenceList.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/SmartObjects/SubpageReferencList/SubpageReferenceList.cs @@ -144,7 +144,7 @@ namespace PepperDash.Essentials.Core public UShortOutputSig GetUShortOutputSig(uint index, uint sigNum) { if (sigNum > UShortIncrement) return null; - return SRL.UShortOutput.FirstOrDefault(s => s.Name.Equals(GetBoolFeedbackSigName(index, sigNum))); + return SRL.UShortOutput.FirstOrDefault(s => s.Name.Equals(GetUShortOutputSigName(index, sigNum))); } /// @@ -159,7 +159,7 @@ namespace PepperDash.Essentials.Core public StringOutputSig GetStringOutputSig(uint index, uint sigNum) { if (sigNum > StringIncrement) return null; - return SRL.StringOutput.FirstOrDefault(s => s.Name.Equals(GetBoolFeedbackSigName(index, sigNum))); + return SRL.StringOutput.FirstOrDefault(s => s.Name.Equals(GetStringOutputSigName(index, sigNum))); } /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/NECPSXMDisplay.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/NECPSXMDisplay.cs index 176f28ac..a674b11a 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/NECPSXMDisplay.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/NECPSXMDisplay.cs @@ -308,7 +308,7 @@ namespace PepperDash.Essentials.Devices.Displays //Send((string)selector); } - void SetVolume(ushort level) + public void SetVolume(ushort level) { var levelString = string.Format("{0}{1:X4}\x03", VolumeLevelPartialCmd, level); AppendChecksumAndSend(levelString); @@ -333,10 +333,13 @@ namespace PepperDash.Essentials.Devices.Displays Send(MuteOnCmd); } - void IBasicVolumeWithFeedback.SetVolume(ushort level) + + /* + public void IBasicVolumeWithFeedback.SetVolume(ushort level) { SetVolume(level); } + */ #endregion diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/PanasonicThDisplay.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/PanasonicThDisplay.cs index b8d33bd1..9acc395e 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/PanasonicThDisplay.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/PanasonicThDisplay.cs @@ -290,7 +290,7 @@ namespace PepperDash.Essentials.Devices.Displays //Send((string)selector); } - void SetVolume(ushort level) + public void SetVolume(ushort level) { var levelString = string.Format("{0}{1:X3}\x03", VolumeLevelPartialCmd, level); @@ -315,11 +315,12 @@ namespace PepperDash.Essentials.Devices.Displays Send(MuteOnCmd); } + /* void IBasicVolumeWithFeedback.SetVolume(ushort level) { SetVolume(level); } - + */ #endregion #region IBasicVolumeControls Members diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index fe4d5f61..547e8711 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -108,6 +108,7 @@ + diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index c9e584d3..0bca7181 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -1023,20 +1023,25 @@ ConnectorID: {2}" if (tempPresets.Count > 0) { // Create temporary list to store the existing items from the CiscoCodecStatus.RoomPreset collection - List existingRoomPresets = new List(); + var existingRoomPresets = new List(); // Add the existing items to the temporary list existingRoomPresets.AddRange(CodecStatus.Status.RoomPreset); // Populate the CodecStatus object (this will append new values to the RoomPreset collection JsonConvert.PopulateObject(response, CodecStatus); - JObject jResponse = JObject.Parse(response); + var jResponse = JObject.Parse(response); + + List convertedRoomPresets = + existingRoomPresets.Select(a => (CiscoCodecStatus.RoomPreset) a).ToList(); IList roomPresets = jResponse["Status"]["RoomPreset"].Children().ToList(); // Iterate the new items in this response agains the temporary list. Overwrite any existing items and add new ones. - foreach (var preset in tempPresets) + foreach (var camPreset in tempPresets) { + var preset = camPreset as CiscoCodecStatus.RoomPreset; + if (preset == null) continue; // First fine the existing preset that matches the id - var existingPreset = existingRoomPresets.FirstOrDefault(p => p.id.Equals(preset.id)); + var existingPreset = convertedRoomPresets.FirstOrDefault(p => p.id.Equals(preset.id)); if (existingPreset != null) { Debug.Console(1, this, "Existing Room Preset with ID: {0} found. Updating.", existingPreset.id); @@ -1068,7 +1073,7 @@ ConnectorID: {2}" CodecStatus.Status.RoomPreset = existingRoomPresets; // Generecise the list - NearEndPresets = RoomPresets.GetGenericPresets(CodecStatus.Status.RoomPreset); + NearEndPresets = existingRoomPresets.GetGenericPresets(); var handler = CodecRoomPresetsListHasChanged; if (handler != null) @@ -2465,20 +2470,6 @@ ConnectorID: {2}" } - /// - /// Represents a codec command that might need to have a friendly label applied for UI feedback purposes - /// - public class CodecCommandWithLabel - { - public string Command { get; set; } - public string Label { get; set; } - - public CodecCommandWithLabel(string command, string label) - { - Command = command; - Label = label; - } - } /// /// Tracks the initial sycnronization state of the codec when making a connection diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs index b6327d52..4fec0d89 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs @@ -1,14 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Essentials.Core.Presets; -using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco; namespace PepperDash.Essentials.Devices.Common.VideoCodec { @@ -33,39 +28,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public static class RoomPresets { /// - /// Converts Cisco RoomPresets to generic CameraPresets + /// Converts non-generic RoomPresets to generic CameraPresets /// /// /// - public static List GetGenericPresets(List presets) + public static List GetGenericPresets(this List presets) { - var cameraPresets = new List(); - - if (Debug.Level > 0) - { - Debug.Console(1, "Presets List:"); - } - - foreach (CiscoCodecStatus.RoomPreset preset in presets) - { - try - { - var cameraPreset = new CodecRoomPreset(UInt16.Parse(preset.id), preset.Description.Value, preset.Defined.BoolValue, true); - - cameraPresets.Add(cameraPreset); - - if (Debug.Level > 0) - { - Debug.Console(1, "Added Preset ID: {0}, Description: {1}, IsDefined: {2}, isDefinable: {3}", cameraPreset.ID, cameraPreset.Description, cameraPreset.Defined, cameraPreset.IsDefinable); - } - } - catch (Exception e) - { - Debug.Console(2, "Unable to convert preset: {0}. Error: {1}", preset.id, e); - } - } - - return cameraPresets; + return + presets.Select(preset => preset.ConvertCodecPreset()) + .Where(newPreset => newPreset != null) + .Cast() + .ToList(); } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index 5bde30ff..23e8c6ab 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -9,6 +9,7 @@ using Newtonsoft.Json.Linq; using PepperDash.Core; using PepperDash.Essentials.Devices.Common.VideoCodec.CiscoCodec; +using PepperDash.Essentials.Core.Presets; namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { @@ -2185,7 +2186,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } } - public class RoomPreset + public class RoomPreset : IConvertiblePreset { public string id { get; set; } public Defined Defined { get; set; } @@ -2198,7 +2199,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco Description = new Description2(); Type = new Type5(); } - } + + public PresetBase ConvertCodecPreset() + { + try + { + var preset = new CodecRoomPreset(UInt16.Parse(id), Description.Value, Defined.BoolValue, true); + + Debug.Console(2, "Preset ID {0} Converted from Cisco Codec Preset to Essentials Preset"); + + return preset; + } + catch (Exception e) + { + Debug.Console(2, "Unable to convert preset: {0}. Error: {1}", id, e); + return null; + } + } +} @@ -2222,7 +2240,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public Proximity Proximity { get; set; } public RoomAnalytics RoomAnalytics { get; set; } - public List RoomPreset { get; set; } + public List RoomPreset { get; set; } public SIP SIP { get; set; } public Security Security { get; set; } @@ -2239,7 +2257,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco Standby = new Standby(); Cameras = new Cameras(); RoomAnalytics = new RoomAnalytics(); - RoomPreset = new List(); + RoomPreset = new List(); Conference = new Conference2(); SystemUnit = new SystemUnit(); Video = new Video(); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/IConvertiblePreset.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/IConvertiblePreset.cs new file mode 100644 index 00000000..f6f3f74f --- /dev/null +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/IConvertiblePreset.cs @@ -0,0 +1,9 @@ +using PepperDash.Essentials.Core.Presets; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec +{ + public interface IConvertiblePreset + { + PresetBase ConvertCodecPreset(); + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs index ef0bf2bd..bfc43db6 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs @@ -22,6 +22,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec void MinMaxLayoutToggle(); } + /// + /// Defines the required elements for layout control with direct layout selection + /// + public interface IHasCodecLayoutsAvailable : IHasCodecLayouts + { + + event EventHandler AvailableLayoutsChanged; + + StringFeedback AvailableLocalLayoutsFeedback { get; } + List AvailableLocalLayouts { get; } + void LocalLayoutSet(string layout); + void LocalLayoutSet(CodecCommandWithLabel layout); + + } + + public class AvailableLayoutChangedEventArgs : EventArgs + { + public List AvailableLayouts { get; set; } + } + /// /// Defines the requirements for Zoom Room layout control /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs index 5360b80a..d0ba25fd 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs @@ -1,5 +1,5 @@ using PepperDash.Essentials.Core; -using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco; +using PepperDash.Essentials.Devices.Common.VideoCodec; namespace PepperDash.Essentials.Core.DeviceTypeInterfaces { diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewSize.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewSize.cs index 91ac3ec8..4103fa0e 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewSize.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewSize.cs @@ -1,4 +1,4 @@ -using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco; +using PepperDash.Essentials.Devices.Common.VideoCodec; namespace PepperDash.Essentials.Core.DeviceTypeInterfaces { diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 593472e9..c7579f0b 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -370,6 +370,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec LinkVideoCodecCameraLayoutsToApi(codec as IHasCodecLayouts, trilist, joinMap); } + if (codec is IHasCodecLayoutsAvailable) + { + LinkVideoCodecAvailableLayoutsToApi(codec as IHasCodecLayoutsAvailable, trilist, joinMap); + } + if (codec is IHasSelfviewPosition) { LinkVideoCodecSelfviewPositionToApi(codec as IHasSelfviewPosition, trilist, joinMap); @@ -1471,6 +1476,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec codec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentLayoutStringFb.JoinNumber]); } + private void LinkVideoCodecAvailableLayoutsToApi(IHasCodecLayoutsAvailable codec, BasicTriList trilist, + VideoCodecControllerJoinMap joinMap) + { + codec.AvailableLocalLayoutsFeedback.LinkInputSig(trilist.StringInput[joinMap.AvailableLayoutsFb.JoinNumber]); + + trilist.SetStringSigAction(joinMap.SelectLayout.JoinNumber, codec.LocalLayoutSet); + } + private void LinkVideoCodecCameraModeToApi(IHasCameraAutoMode codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { trilist.SetSigFalseAction(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeOn); @@ -1982,4 +1995,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } } } + /// + /// Represents a codec command that might need to have a friendly label applied for UI feedback purposes + /// + public class CodecCommandWithLabel + { + public string Command { get; private set; } + public string Label { get; private set; } + + public CodecCommandWithLabel(string command, string label) + { + Command = command; + Label = label; + } + } + } \ No newline at end of file