diff --git a/.gitignore b/.gitignore index 36d84cbc..c9469ffd 100644 --- a/.gitignore +++ b/.gitignore @@ -391,3 +391,4 @@ FodyWeavers.xsd essentials-framework/Essentials Interfaces/PepperDash_Essentials_Interfaces/PepperDash_Essentials_Interfaces.csproj .DS_Store /._PepperDash.Essentials.sln +.vscode/settings.json diff --git a/src/PepperDash.Essentials.Core/Bridges/BridgeBase.cs b/src/PepperDash.Essentials.Core/Bridges/BridgeBase.cs index b4bef5b8..c9784647 100644 --- a/src/PepperDash.Essentials.Core/Bridges/BridgeBase.cs +++ b/src/PepperDash.Essentials.Core/Bridges/BridgeBase.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; using Crestron.SimplSharp; -using Crestron.SimplSharp.Reflection; +using System.Reflection; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.EthernetCommunication; @@ -168,7 +168,7 @@ namespace PepperDash.Essentials.Core.Bridges Debug.LogMessage(LogEventLevel.Debug, this, "Linking Device: '{0}'", device.Key); - if (!typeof(IBridgeAdvanced).IsAssignableFrom(device.GetType().GetCType())) + if (!typeof(IBridgeAdvanced).IsAssignableFrom(device.GetType().GetType())) { Debug.LogMessage(LogEventLevel.Information, this, "{0} is not compatible with this bridge type. Please use 'eiscapi' instead, or updae the device.", diff --git a/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs b/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs index 679420d3..59e8c768 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs @@ -101,6 +101,7 @@ namespace PepperDash.Essentials.Core if (StreamDebugging.RxStreamDebuggingIsEnabled) Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", ComTextHelper.GetEscapedText(bytes)); bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); + return; } var textHandler = TextReceived; if (textHandler != null) @@ -108,7 +109,10 @@ namespace PepperDash.Essentials.Core if (StreamDebugging.RxStreamDebuggingIsEnabled) Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", s); textHandler(this, new GenericCommMethodReceiveTextArgs(s)); + return; } + + Debug.LogMessage(LogEventLevel.Warning, this, "Received data but no handler is registered"); } public override bool Deactivate() diff --git a/src/PepperDash.Essentials.Core/Comm and IR/GenericHttpClient.cs b/src/PepperDash.Essentials.Core/Comm and IR/GenericHttpClient.cs index 0347da80..47632c8d 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/GenericHttpClient.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/GenericHttpClient.cs @@ -1,14 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharp.Net.Http; +using Crestron.SimplSharp.Net.Http; using PepperDash.Core; +using System; namespace PepperDash.Essentials.Core { - [Obsolete("Please use the builtin HttpClient class instead: https://learn.microsoft.com/en-us/dotnet/fundamentals/networking/http/httpclient-guidelines")] + [Obsolete("Please use the builtin HttpClient class instead: https://learn.microsoft.com/en-us/dotnet/fundamentals/networking/http/httpclient-guidelines")] public class GenericHttpClient : Device, IBasicCommunication { public HttpClient Client; diff --git a/src/PepperDash.Essentials.Core/Config/AudioControlPointListItem.cs b/src/PepperDash.Essentials.Core/Config/AudioControlPointListItem.cs new file mode 100644 index 00000000..3552c2b2 --- /dev/null +++ b/src/PepperDash.Essentials.Core/Config/AudioControlPointListItem.cs @@ -0,0 +1,20 @@ +using Crestron.SimplSharpPro; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PepperDash.Essentials.Core.Config +{ + public class AudioControlPointListItem + { + [JsonProperty("levelControls")] + public Dictionary LevelControls { get; set; } = new Dictionary(); + + [JsonProperty("presets")] + public Dictionary Presets { get; set; } = new Dictionary(); + + } +} diff --git a/src/PepperDash.Essentials.Core/Config/BasicConfig.cs b/src/PepperDash.Essentials.Core/Config/BasicConfig.cs index 6e876de8..6df7b583 100644 --- a/src/PepperDash.Essentials.Core/Config/BasicConfig.cs +++ b/src/PepperDash.Essentials.Core/Config/BasicConfig.cs @@ -23,7 +23,10 @@ namespace PepperDash.Essentials.Core.Config public Dictionary> SourceLists { get; set; } [JsonProperty("destinationLists")] - public Dictionary> DestinationLists { get; set; } + public Dictionary> DestinationLists { get; set; } + + [JsonProperty("audioControlPointLists")] + public Dictionary AudioControlPointLists { get; set; } [JsonProperty("tieLines")] public List TieLines { get; set; } @@ -37,6 +40,7 @@ namespace PepperDash.Essentials.Core.Config Devices = new List(); SourceLists = new Dictionary>(); DestinationLists = new Dictionary>(); + AudioControlPointLists = new Dictionary(); TieLines = new List(); JoinMaps = new Dictionary(); } @@ -55,8 +59,8 @@ namespace PepperDash.Essentials.Core.Config /// /// Retrieves a DestinationListItem based on the key /// - /// key of the item to retrieve - /// DestinationListItem if the key exists, null otherwise + /// key of the list to retrieve + /// DestinationList if the key exists, null otherwise public Dictionary GetDestinationListForKey(string key) { if (string.IsNullOrEmpty(key) || !DestinationLists.ContainsKey(key)) @@ -65,7 +69,20 @@ namespace PepperDash.Essentials.Core.Config } return DestinationLists[key]; - } + } + + /// + /// Retrieves a AudioControlPointList based on the key + /// + /// key of the list to retrieve + /// AudioControlPointList if the key exists, null otherwise + public AudioControlPointListItem GetAudioControlPointListForKey(string key) + { + if (string.IsNullOrEmpty(key) || !AudioControlPointLists.ContainsKey(key)) + return null; + + return AudioControlPointLists[key]; + } /// /// Checks Devices for an item with a Key that matches and returns it if found. Otherwise, retunes null diff --git a/src/PepperDash.Essentials.Core/Config/InfoConfig.cs b/src/PepperDash.Essentials.Core/Config/InfoConfig.cs index 32a6f71e..12ca49f4 100644 --- a/src/PepperDash.Essentials.Core/Config/InfoConfig.cs +++ b/src/PepperDash.Essentials.Core/Config/InfoConfig.cs @@ -1,18 +1,16 @@  +using Crestron.SimplSharp; +using Newtonsoft.Json; using System; using System.Collections.Generic; -using Crestron.SimplSharp; -using Crestron.SimplSharp.Reflection; - -using Newtonsoft.Json; namespace PepperDash.Essentials.Core.Config { - /// - /// Represents the info section of a Config file - /// - public class InfoConfig + /// + /// Represents the info section of a Config file + /// + public class InfoConfig { [JsonProperty("name")] public string Name { get; set; } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs index ef806d9a..9fa0f222 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs @@ -15,10 +15,22 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces /// /// See MockDisplay for example implemntation /// - public interface IHasInputs: IKeyName + [Obsolete("Use IHasInputs instead. Will be removed for 2.0 release")] + public interface IHasInputs: IKeyName { - ISelectableItems Inputs { get; } + ISelectableItems Inputs { get; } + } - void SetInput(TSelector selector); + + /// + /// Describes a device that has selectable inputs + /// + /// the type to use as the key for each input item. Most likely an enum or string\ + /// + /// See MockDisplay for example implemntation + /// + public interface IHasInputs : IKeyName + { + ISelectableItems Inputs { get; } } } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMobileControl.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMobileControl.cs index b856a7c0..c30edebd 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMobileControl.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMobileControl.cs @@ -44,7 +44,10 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces void AddDeviceMessenger(IMobileControlMessenger messenger); bool CheckForDeviceMessenger(string key); - } + + IMobileControlRoomMessenger GetRoomMessenger(string key); + + } /// /// Describes a mobile control messenger diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IProjectorScreenLiftControl.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IProjectorScreenLiftControl.cs new file mode 100644 index 00000000..26895114 --- /dev/null +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IProjectorScreenLiftControl.cs @@ -0,0 +1,27 @@ +using Crestron.SimplSharpPro.DeviceSupport; +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +{ + /// + /// Defines a class that has warm up and cool down + /// + public interface IProjectorScreenLiftControl + { + void Raise(); + void Lower(); + BoolFeedback IsInUpPosition { get; } + bool InUpPosition { get; } + event EventHandler PositionChanged; + string DisplayDeviceKey { get; } + eScreenLiftControlType Type { get; } // screen/lift + } + + public enum eScreenLiftControlType + { + lift, + screen + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs index c1451afb..0d3968df 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs @@ -17,6 +17,6 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces Dictionary Items { get; set; } [JsonProperty("currentItem")] - string CurrentItem { get; set; } + TKey CurrentItem { get; set; } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/AudioControlListItemBase.cs b/src/PepperDash.Essentials.Core/Devices/AudioControlListItemBase.cs new file mode 100644 index 00000000..920c2d14 --- /dev/null +++ b/src/PepperDash.Essentials.Core/Devices/AudioControlListItemBase.cs @@ -0,0 +1,36 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PepperDash.Essentials.Core +{ + public abstract class AudioControlListItemBase + { + [JsonProperty("parentDeviceKey")] + public string ParentDeviceKey { get; set; } + + [JsonProperty("itemKey")] + public string ItemKey { get; set; } + + /// + /// A name that will override the items's name on the UI + /// + [JsonProperty("name")] + public string Name { get; set; } + + /// + /// Indicates if the item should be included in the user accessible list + /// + [JsonProperty("includeInUserList")] + public bool IncludeInUserList { get; set; } + + /// + /// Used to specify the order of the items in the source list when displayed + /// + [JsonProperty("order")] + public int Order { get; set; } + } +} diff --git a/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs b/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs index fcda0730..18559b40 100644 --- a/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs +++ b/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs @@ -7,7 +7,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Crestron.SimplSharp; -using Crestron.SimplSharp.Reflection; +using System.Reflection; using Newtonsoft.Json; using PepperDash.Core; @@ -64,7 +64,7 @@ namespace PepperDash.Essentials.Core action.Params = new object[0]; } - CType t = obj.GetType(); + Type t = obj.GetType(); try { var methods = t.GetMethods().Where(m => m.Name == action.MethodName).ToList(); @@ -84,7 +84,18 @@ namespace PepperDash.Essentials.Core .Select((p, i) => ConvertType(action.Params[i], p.ParameterType)) .ToArray(); - Task.Run(() => method.Invoke(obj, convertedParams)); + Task.Run(() => + { + try + { + Debug.LogMessage(LogEventLevel.Verbose, "Calling method {methodName} on device {deviceKey}", null, method.Name, action.DeviceKey); + method.Invoke(obj, convertedParams); + } + catch(Exception e) + { + Debug.LogMessage(e, "Error invoking method {methodName} on device {deviceKey}", null, method.Name, action.DeviceKey); + } + }); CrestronConsole.ConsoleCommandResponse("Method {0} successfully called on device {1}", method.Name, action.DeviceKey); @@ -123,7 +134,7 @@ namespace PepperDash.Essentials.Core if (obj == null) return "{ \"error\":\"No Device\"}"; - CType t = obj.GetType(); + Type t = obj.GetType(); // get the properties and set them into a new collection of NameType wrappers var props = t.GetProperties().Select(p => new PropertyNameType(p, obj)); return JsonConvert.SerializeObject(props, Formatting.Indented); @@ -141,7 +152,7 @@ namespace PepperDash.Essentials.Core if(dev == null) return "{ \"error\":\"No Device\"}"; - object prop = dev.GetType().GetCType().GetProperty(propertyName).GetValue(dev, null); + object prop = dev.GetType().GetType().GetProperty(propertyName).GetValue(dev, null); // var prop = t.GetProperty(propertyName); if (prop != null) @@ -167,7 +178,7 @@ namespace PepperDash.Essentials.Core return "{ \"error\":\"No Device\"}"; // Package up method names using helper objects - CType t = obj.GetType(); + Type t = obj.GetType(); var methods = t.GetMethods() .Where(m => !m.IsSpecialName) .Select(p => new MethodNameParams(p)); @@ -181,7 +192,7 @@ namespace PepperDash.Essentials.Core return "{ \"error\":\"No Device\"}"; // Package up method names using helper objects - CType t = obj.GetType(); + Type t = obj.GetType(); var methods = t.GetMethods() .Where(m => !m.IsSpecialName) .Where(m => m.GetCustomAttributes(typeof(ApiAttribute), true).Any()) @@ -228,7 +239,7 @@ namespace PepperDash.Essentials.Core Debug.LogMessage(LogEventLevel.Information, dev, " Checking for collection '{0}', index '{1}'", objName, indexStr); } - CType oType = obj.GetType(); + Type oType = obj.GetType(); var prop = oType.GetProperty(objName); if (prop == null) { @@ -258,7 +269,7 @@ namespace PepperDash.Essentials.Core obj = indexedPropInfo.GetValue(collection, new object[] { properParam }); } // if the index is bad, catch it here. - catch (Crestron.SimplSharp.Reflection.TargetInvocationException e) + catch (TargetInvocationException e) { if (e.InnerException is ArgumentOutOfRangeException) Debug.LogMessage(LogEventLevel.Information, " Index Out of range"); @@ -289,7 +300,7 @@ namespace PepperDash.Essentials.Core //if (obj == null) // return "{\"error\":\"No object found\"}"; - //CType t = obj.GetType(); + //Type t = obj.GetType(); //// get the properties and set them into a new collection of NameType wrappers @@ -367,7 +378,7 @@ namespace PepperDash.Essentials.Core } [AttributeUsage(AttributeTargets.All)] - public class ApiAttribute : CAttribute + public class ApiAttribute : Attribute { } diff --git a/src/PepperDash.Essentials.Core/Devices/DeviceManager.cs b/src/PepperDash.Essentials.Core/Devices/DeviceManager.cs index 916cc42f..e92d11c5 100644 --- a/src/PepperDash.Essentials.Core/Devices/DeviceManager.cs +++ b/src/PepperDash.Essentials.Core/Devices/DeviceManager.cs @@ -166,7 +166,7 @@ namespace PepperDash.Essentials.Core // var dev = GetDeviceForKey(devKey); // if(dev != null) // { - // var type = dev.GetType().GetCType(); + // var type = dev.GetType().GetType(); // var methods = type.GetMethods(BindingFlags.Public|BindingFlags.Instance); // var sb = new StringBuilder(); // sb.AppendLine(string.Format("{2} methods on [{0}] ({1}):", dev.Key, type.Name, methods.Length)); diff --git a/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs b/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs index e383627d..8b0fc9fe 100644 --- a/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs +++ b/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using Crestron.SimplSharp; -using Crestron.SimplSharp.Reflection; +using System.Reflection; using PepperDash.Core; using PepperDash.Essentials.Core.Config; diff --git a/src/PepperDash.Essentials.Core/Devices/IDspPreset.cs b/src/PepperDash.Essentials.Core/Devices/IDspPreset.cs deleted file mode 100644 index 645339bb..00000000 --- a/src/PepperDash.Essentials.Core/Devices/IDspPreset.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; - -namespace PepperDash.Essentials.Core -{ - public interface IHasDspPresets - { - List Presets { get; } - - void RecallPreset(IDspPreset preset); - - } - - public interface IDspPreset - { - string Name { get; } - } -} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/IDspPresets.cs b/src/PepperDash.Essentials.Core/Devices/IDspPresets.cs new file mode 100644 index 00000000..94bc3929 --- /dev/null +++ b/src/PepperDash.Essentials.Core/Devices/IDspPresets.cs @@ -0,0 +1,12 @@ +using PepperDash.Core; +using System.Collections.Generic; + +namespace PepperDash.Essentials.Core +{ + public interface IDspPresets + { + Dictionary Presets { get; } + + void RecallPreset(string key); + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/IHasFeedbacks.cs b/src/PepperDash.Essentials.Core/Devices/IHasFeedbacks.cs index 5241a147..9943c738 100644 --- a/src/PepperDash.Essentials.Core/Devices/IHasFeedbacks.cs +++ b/src/PepperDash.Essentials.Core/Devices/IHasFeedbacks.cs @@ -1,7 +1,5 @@ -using System.Collections.Generic; +using System; using System.Linq; -using Crestron.SimplSharpPro.DeviceSupport; -using Crestron.SimplSharp.Reflection; using PepperDash.Core; using Serilog.Events; @@ -23,7 +21,7 @@ namespace PepperDash.Essentials.Core { public static void DumpFeedbacksToConsole(this IHasFeedback source, bool getCurrentStates) { - CType t = source.GetType(); + Type t = source.GetType(); // get the properties and set them into a new collection of NameType wrappers var props = t.GetProperties().Select(p => new PropertyNameType(p, t)); diff --git a/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs new file mode 100644 index 00000000..d18dacc5 --- /dev/null +++ b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using PepperDash.Core; +using PepperDash.Essentials.Core.Devices; + +namespace PepperDash.Essentials.Core +{ + public class LevelControlListItem : AudioControlListItemBase + { + + + [JsonIgnore] + public IBasicVolumeWithFeedback LevelControl + { + get + { + if (_levelControl == null) + _levelControl = DeviceManager.GetDeviceForKey(ParentDeviceKey) as IBasicVolumeWithFeedback; + return _levelControl; + } + } + IBasicVolumeWithFeedback _levelControl; + + /// + /// Gets the name from the device if it implements IKeyName or else returns the Name property + /// + [JsonProperty("preferredName")] + public string PreferredName + { + get + { + if (!string.IsNullOrEmpty(Name)) return Name; + else + { + if (LevelControl is IKeyName namedLevelControl) + { + if (namedLevelControl == null) + return "---"; + return namedLevelControl.Name; + } + else return "---"; + } + } + } + + /// + /// The key of the device in the DeviceManager for control + /// + [JsonProperty("deviceKey")] + public string DeviceKey => DeviceManager.AllDevices. + Where(d => d.Key.Contains(ParentDeviceKey) && d.Key.Contains(ItemKey)).FirstOrDefault()?.Key ?? $"{ParentDeviceKey}--{ItemKey}"; + + /// + /// Indicates if the item is a level, mute , or both + /// + [JsonProperty("type")] + [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + public eLevelControlType Type { get; set; } + } + + [Flags] + public enum eLevelControlType + { + Level = 0, + Mute = 1, + LevelAndMute = Level | Mute, + } +} diff --git a/src/PepperDash.Essentials.Core/Devices/PresetListItem.cs b/src/PepperDash.Essentials.Core/Devices/PresetListItem.cs new file mode 100644 index 00000000..f539d718 --- /dev/null +++ b/src/PepperDash.Essentials.Core/Devices/PresetListItem.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using PepperDash.Core; + + +namespace PepperDash.Essentials.Core +{ + public class PresetListItem : AudioControlListItemBase + { + [JsonIgnore] + public IKeyName Preset + { + get + { + if (_preset == null) + { + var parent = DeviceManager.GetDeviceForKey(ParentDeviceKey) as IDspPresets; + if (parent == null || !parent.Presets.ContainsKey(ItemKey)) + return null; + _preset = parent.Presets[ItemKey]; + } + return _preset; + } + } + private IKeyName _preset; + + /// + /// Gets the name from the device if it implements IKeyName or else returns the Name property + /// + [JsonProperty("preferredName")] + public string PreferredName + { + get + { + if (!string.IsNullOrEmpty(Name)) return Name; + + else return Preset.Name; + } + } + } +} diff --git a/src/PepperDash.Essentials.Core/Display/DisplayBase.cs b/src/PepperDash.Essentials.Core/Display/DisplayBase.cs index 040e9d84..a41f936f 100644 --- a/src/PepperDash.Essentials.Core/Display/DisplayBase.cs +++ b/src/PepperDash.Essentials.Core/Display/DisplayBase.cs @@ -266,16 +266,16 @@ namespace PepperDash.Essentials.Core abstract protected Func PowerIsOnFeedbackFunc { get; } - public static MockDisplay DefaultDisplay - { - get - { - if (_DefaultDisplay == null) - _DefaultDisplay = new MockDisplay("default", "Default Display"); - return _DefaultDisplay; - } - } - static MockDisplay _DefaultDisplay; + // public static MockDisplay DefaultDisplay + // { + // get + // { + // if (_DefaultDisplay == null) + // _DefaultDisplay = new MockDisplay("default", "Default Display"); + // return _DefaultDisplay; + // } + //} + //static MockDisplay _DefaultDisplay; public TwoWayDisplayBase(string key, string name) : base(key, name) diff --git a/src/PepperDash.Essentials.Core/Display/MockDisplay.cs b/src/PepperDash.Essentials.Core/Display/MockDisplay.cs deleted file mode 100644 index 3f3fd2ac..00000000 --- a/src/PepperDash.Essentials.Core/Display/MockDisplay.cs +++ /dev/null @@ -1,237 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.DeviceSupport; -using Crestron.SimplSharpPro.DM; -using Crestron.SimplSharpPro.DM.Endpoints; -using Crestron.SimplSharpPro.DM.Endpoints.Transmitters; - -using PepperDash.Core; -using PepperDash.Essentials.Core.Bridges; -using PepperDash.Essentials.Core.Config; -using Serilog.Events; - -namespace PepperDash.Essentials.Core -{ - [Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")] - public class MockDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, IBridgeAdvanced - - { - public RoutingInputPort HdmiIn1 { get; private set; } - public RoutingInputPort HdmiIn2 { get; private set; } - public RoutingInputPort HdmiIn3 { get; private set; } - public RoutingInputPort ComponentIn1 { get; private set; } - public RoutingInputPort VgaIn1 { get; private set; } - - bool _PowerIsOn; - bool _IsWarmingUp; - bool _IsCoolingDown; - - protected override Func PowerIsOnFeedbackFunc - { - get - { - return () => - { - Debug.LogMessage(LogEventLevel.Verbose, this, "*************************************************** Display Power is {0}", _PowerIsOn ? "on" : "off"); - return _PowerIsOn; - }; - } } - protected override Func IsCoolingDownFeedbackFunc - { - get - { - return () => - { - Debug.LogMessage(LogEventLevel.Verbose, this, "*************************************************** {0}", _IsCoolingDown ? "Display is cooling down" : "Display has finished cooling down"); - return _IsCoolingDown; - }; - } - } - protected override Func IsWarmingUpFeedbackFunc - { - get - { - return () => - { - Debug.LogMessage(LogEventLevel.Verbose, this, "*************************************************** {0}", _IsWarmingUp ? "Display is warming up" : "Display has finished warming up"); - return _IsWarmingUp; - }; - } - } - protected override Func CurrentInputFeedbackFunc { get { return () => "Not Implemented"; } } - - int VolumeHeldRepeatInterval = 200; - ushort VolumeInterval = 655; - ushort _FakeVolumeLevel = 31768; - bool _IsMuted; - - public MockDisplay(string key, string name) - : base(key, name) - { - HdmiIn1 = new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null, this); - HdmiIn2 = new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null, this); - HdmiIn3 = new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null, this); - ComponentIn1 = new RoutingInputPort(RoutingPortNames.ComponentIn, eRoutingSignalType.Video, - eRoutingPortConnectionType.Component, null, this); - VgaIn1 = new RoutingInputPort(RoutingPortNames.VgaIn, eRoutingSignalType.Video, - eRoutingPortConnectionType.Composite, null, this); - InputPorts.AddRange(new[] { HdmiIn1, HdmiIn2, HdmiIn3, ComponentIn1, VgaIn1 }); - - VolumeLevelFeedback = new IntFeedback(() => { return _FakeVolumeLevel; }); - MuteFeedback = new BoolFeedback("MuteOn", () => _IsMuted); - - WarmupTime = 10000; - CooldownTime = 10000; - } - - public override void PowerOn() - { - if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown) - { - _IsWarmingUp = true; - IsWarmingUpFeedback.InvokeFireUpdate(); - // Fake power-up cycle - WarmupTimer = new CTimer(o => - { - _IsWarmingUp = false; - _PowerIsOn = true; - IsWarmingUpFeedback.InvokeFireUpdate(); - PowerIsOnFeedback.InvokeFireUpdate(); - }, WarmupTime); - } - } - - public override void PowerOff() - { - // If a display has unreliable-power off feedback, just override this and - // remove this check. - if (PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown) - { - _IsCoolingDown = true; - IsCoolingDownFeedback.InvokeFireUpdate(); - // Fake cool-down cycle - CooldownTimer = new CTimer(o => - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Cooldown timer ending"); - _IsCoolingDown = false; - IsCoolingDownFeedback.InvokeFireUpdate(); - _PowerIsOn = false; - PowerIsOnFeedback.InvokeFireUpdate(); - }, CooldownTime); - } - } - - public override void PowerToggle() - { - if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue) - PowerOff(); - else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue) - PowerOn(); - } - - public override void ExecuteSwitch(object selector) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "ExecuteSwitch: {0}", selector); - - if (!_PowerIsOn) - { - PowerOn(); - } - } - - - - #region IBasicVolumeWithFeedback Members - - public IntFeedback VolumeLevelFeedback { get; private set; } - - public void SetVolume(ushort level) - { - _FakeVolumeLevel = level; - VolumeLevelFeedback.InvokeFireUpdate(); - } - - public void MuteOn() - { - _IsMuted = true; - MuteFeedback.InvokeFireUpdate(); - } - - public void MuteOff() - { - _IsMuted = false; - MuteFeedback.InvokeFireUpdate(); - } - - public BoolFeedback MuteFeedback { get; private set; } - - #endregion - - #region IBasicVolumeControls Members - - public void VolumeUp(bool pressRelease) - { - //while (pressRelease) - //{ - Debug.LogMessage(LogEventLevel.Verbose, this, "Volume Down {0}", pressRelease); - if (pressRelease) - { - var newLevel = _FakeVolumeLevel + VolumeInterval; - SetVolume((ushort)newLevel); - CrestronEnvironment.Sleep(VolumeHeldRepeatInterval); - } - //} - } - - public void VolumeDown(bool pressRelease) - { - //while (pressRelease) - //{ - Debug.LogMessage(LogEventLevel.Verbose, this, "Volume Up {0}", pressRelease); - if (pressRelease) - { - var newLevel = _FakeVolumeLevel - VolumeInterval; - SetVolume((ushort)newLevel); - CrestronEnvironment.Sleep(VolumeHeldRepeatInterval); - } - //} - } - - public void MuteToggle() - { - _IsMuted = !_IsMuted; - MuteFeedback.InvokeFireUpdate(); - } - - #endregion - - public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge); - } - } - - - [Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")] - public class MockDisplayFactory : EssentialsDeviceFactory - { - public MockDisplayFactory() - { - TypeNames = new List() { "mockdisplay" }; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Mock Display Device"); - return new MockDisplay(dc.Key, dc.Name); - } - } - -} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Factory/DeviceFactory.cs b/src/PepperDash.Essentials.Core/Factory/DeviceFactory.cs index f4ce92a0..07bcc56a 100644 --- a/src/PepperDash.Essentials.Core/Factory/DeviceFactory.cs +++ b/src/PepperDash.Essentials.Core/Factory/DeviceFactory.cs @@ -14,13 +14,13 @@ namespace PepperDash.Essentials.Core { public class DeviceFactoryWrapper { - public Type CType { get; set; } + public Type Type { get; set; } public string Description { get; set; } public Func FactoryMethod { get; set; } public DeviceFactoryWrapper() { - CType = null; + Type = null; Description = "Not Available"; } } @@ -40,7 +40,7 @@ namespace PepperDash.Essentials.Core { try { - var factory = (IDeviceFactory)Crestron.SimplSharp.Reflection.Activator.CreateInstance(type); + var factory = (IDeviceFactory)Activator.CreateInstance(type); factory.LoadTypeFactories(); } catch (Exception e) @@ -69,7 +69,7 @@ namespace PepperDash.Essentials.Core DeviceFactory.FactoryMethods.Add(typeName, new DeviceFactoryWrapper() { FactoryMethod = method}); } - public static void AddFactoryForType(string typeName, string description, Type cType, Func method) + public static void AddFactoryForType(string typeName, string description, Type Type, Func method) { //Debug.LogMessage(LogEventLevel.Debug, "Adding factory method for type '{0}'", typeName); @@ -79,7 +79,7 @@ namespace PepperDash.Essentials.Core return; } - var wrapper = new DeviceFactoryWrapper() { CType = cType, Description = description, FactoryMethod = method }; + var wrapper = new DeviceFactoryWrapper() { Type = Type, Description = description, FactoryMethod = method }; DeviceFactory.FactoryMethods.Add(typeName, wrapper); } @@ -169,17 +169,17 @@ namespace PepperDash.Essentials.Core foreach (var type in types.OrderBy(t => t.Key)) { var description = type.Value.Description; - var cType = "Not Specified by Plugin"; + var Type = "Not Specified by Plugin"; - if (type.Value.CType != null) + if (type.Value.Type != null) { - cType = type.Value.CType.FullName; + Type = type.Value.Type.FullName; } CrestronConsole.ConsoleCommandResponse( @"Type: '{0}' - CType: '{1}' - Description: {2}{3}", type.Key, cType, description, CrestronEnvironment.NewLine); + Type: '{1}' + Description: {2}{3}", type.Key, Type, description, CrestronEnvironment.NewLine); } } diff --git a/src/PepperDash.Essentials.Core/Factory/IDeviceFactory.cs b/src/PepperDash.Essentials.Core/Factory/IDeviceFactory.cs index 91e073f2..9f7eec58 100644 --- a/src/PepperDash.Essentials.Core/Factory/IDeviceFactory.cs +++ b/src/PepperDash.Essentials.Core/Factory/IDeviceFactory.cs @@ -1,14 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharp.Reflection; - -using PepperDash.Core; -using PepperDash.Essentials.Core.Config; - -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core { /// /// Defines a class that is capable of loading device types diff --git a/src/PepperDash.Essentials.Core/Factory/ProcessorExtensionDeviceFactory.cs b/src/PepperDash.Essentials.Core/Factory/ProcessorExtensionDeviceFactory.cs index 95e0fb76..b67dcf5b 100644 --- a/src/PepperDash.Essentials.Core/Factory/ProcessorExtensionDeviceFactory.cs +++ b/src/PepperDash.Essentials.Core/Factory/ProcessorExtensionDeviceFactory.cs @@ -25,7 +25,7 @@ namespace PepperDash.Essentials.Core { try { - var factory = (IProcessorExtensionDeviceFactory)Crestron.SimplSharp.Reflection.Activator.CreateInstance(extension); + var factory = (IProcessorExtensionDeviceFactory)Activator.CreateInstance(extension); factory.LoadFactories(); } catch( Exception e ) @@ -55,7 +55,7 @@ namespace PepperDash.Essentials.Core ProcessorExtensionDeviceFactory.ProcessorExtensionFactoryMethods.Add(extensionName, new DeviceFactoryWrapper() { FactoryMethod = method }); } - public static void AddFactoryForType(string extensionName, string description, Type cType, Func method) + public static void AddFactoryForType(string extensionName, string description, Type Type, Func method) { //Debug.LogMessage(LogEventLevel.Debug, "Adding factory method for type '{0}'", typeName); @@ -65,7 +65,7 @@ namespace PepperDash.Essentials.Core return; } - var wrapper = new DeviceFactoryWrapper() { CType = cType, Description = description, FactoryMethod = method }; + var wrapper = new DeviceFactoryWrapper() { Type = Type, Description = description, FactoryMethod = method }; ProcessorExtensionDeviceFactory.ProcessorExtensionFactoryMethods.Add(extensionName, wrapper); } diff --git a/src/PepperDash.Essentials.Core/Global/Global.cs b/src/PepperDash.Essentials.Core/Global/Global.cs index b69143af..9e4b6462 100644 --- a/src/PepperDash.Essentials.Core/Global/Global.cs +++ b/src/PepperDash.Essentials.Core/Global/Global.cs @@ -137,6 +137,7 @@ namespace PepperDash.Essentials.Core public static void SetFilePathPrefix(string prefix) { FilePathPrefix = prefix; + Debug.LogMessage(LogEventLevel.Information, "File Path Prefix set to '{0}'", FilePathPrefix); } static string _AssemblyVersion; diff --git a/src/PepperDash.Essentials.Core/JoinMaps/JoinMapBase.cs b/src/PepperDash.Essentials.Core/JoinMaps/JoinMapBase.cs index f8a7e4d2..dda04445 100644 --- a/src/PepperDash.Essentials.Core/JoinMaps/JoinMapBase.cs +++ b/src/PepperDash.Essentials.Core/JoinMaps/JoinMapBase.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; -using Crestron.SimplSharp.Reflection; +using System.Reflection; using Crestron.SimplSharp.CrestronIO; using Crestron.SimplSharp; @@ -109,7 +109,7 @@ namespace PepperDash.Essentials.Core protected void AddJoins(Type type) { var fields = - type.GetCType() + type.GetType() .GetFields(BindingFlags.Public | BindingFlags.Instance) .Where(f => f.IsDefined(typeof (JoinNameAttribute), true)); @@ -501,7 +501,7 @@ namespace PepperDash.Essentials.Core public string GetNameAttribute(MemberInfo memberInfo) { var name = string.Empty; - var attribute = (JoinNameAttribute)CAttribute.GetCustomAttribute(memberInfo, typeof(JoinNameAttribute)); + var attribute = (JoinNameAttribute)Attribute.GetCustomAttribute(memberInfo, typeof(JoinNameAttribute)); if (attribute == null) return name; @@ -514,7 +514,7 @@ namespace PepperDash.Essentials.Core [AttributeUsage(AttributeTargets.All)] - public class JoinNameAttribute : CAttribute + public class JoinNameAttribute : Attribute { private string _Name; diff --git a/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs b/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs index 1ffb1b3c..06a4fbd9 100644 --- a/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs +++ b/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs @@ -110,7 +110,7 @@ namespace PepperDash.Essentials.Core.Monitoring _uptimePollTimer = null; } - private void PollUptime(object obj) + public void PollUptime(object obj) { var consoleResponse = string.Empty; @@ -142,19 +142,22 @@ namespace PepperDash.Essentials.Core.Monitoring _uptime = uptimeRaw.Substring(forIndex + 4); } - private static void ProcessorReboot() + public static void ProcessorReboot() { if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Server) return; + Debug.LogMessage(LogEventLevel.Information, "Rebooting..."); - var response = string.Empty; + + var response = string.Empty; CrestronConsole.SendControlSystemCommand("reboot", ref response); } - private static void ProgramReset(uint index) + public static void ProgramReset(uint index) { if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Server) return; + Debug.LogMessage(LogEventLevel.Information, "Resetting Program {0}...", index); - if (index <= 0 || index > 10) return; + if (index <= 0 || index > 10) return; var cmd = string.Format("progreset -p:{0}", index); diff --git a/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs b/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs index 7066be0e..225abb76 100644 --- a/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs +++ b/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using Crestron.SimplSharp; +using PepperDash.Core; namespace PepperDash.Essentials.Core { @@ -17,9 +18,31 @@ namespace PepperDash.Essentials.Core { private IPartitionStateProvider _partitionSensor; - private bool isInAutoMode; + public bool IsInAutoMode { get; private set; } - private bool partitionPresent; + private bool _partitionPresent; + + public bool PartitionPresent + { + get + { + return _partitionPresent; + } + set + { + if (_partitionPresent == value) + { + return; + } + + _partitionPresent = value; + + if (PartitionPresentFeedback != null) + { + PartitionPresentFeedback.FireUpdate(); + } + } + } public EssentialsPartitionController(string key, string name, IPartitionStateProvider sensor, bool defaultToManualMode, List adjacentRoomKeys) { @@ -52,7 +75,7 @@ namespace PepperDash.Essentials.Core void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e) { - if (isInAutoMode) + if (IsInAutoMode) { PartitionPresentFeedback.FireUpdate(); } @@ -64,7 +87,7 @@ namespace PepperDash.Essentials.Core public void SetAutoMode() { - isInAutoMode = true; + IsInAutoMode = true; if (PartitionPresentFeedback != null) { PartitionPresentFeedback.SetValueFunc(() => _partitionSensor.PartitionPresentFeedback.BoolValue); @@ -76,20 +99,21 @@ namespace PepperDash.Essentials.Core if (_partitionSensor != null) { + _partitionSensor.PartitionPresentFeedback.OutputChange -= PartitionPresentFeedback_OutputChange; _partitionSensor.PartitionPresentFeedback.OutputChange += PartitionPresentFeedback_OutputChange; } } public void SetManualMode() { - isInAutoMode = false; + IsInAutoMode = false; if (PartitionPresentFeedback != null) { - PartitionPresentFeedback.SetValueFunc(() => partitionPresent); + PartitionPresentFeedback.SetValueFunc(() => _partitionPresent); } else { - PartitionPresentFeedback = new BoolFeedback(() => partitionPresent); + PartitionPresentFeedback = new BoolFeedback(() => _partitionPresent); } if (_partitionSensor != null) @@ -101,27 +125,30 @@ namespace PepperDash.Essentials.Core public void SetPartitionStatePresent() { - if (!isInAutoMode) + if (!IsInAutoMode) { - partitionPresent = true; + PartitionPresent = true; PartitionPresentFeedback.FireUpdate(); } } public void SetPartitionStateNotPresent() { - if (!isInAutoMode) + if (!IsInAutoMode) { - partitionPresent = false; + PartitionPresent = false; PartitionPresentFeedback.FireUpdate(); } } public void ToggglePartitionState() { - if (!isInAutoMode) + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Toggling Partition State for {Key}", this); + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"IsInAutoMode: {IsInAutoMode}", this); + + if (!IsInAutoMode) { - partitionPresent = !partitionPresent; + PartitionPresent = !PartitionPresent; PartitionPresentFeedback.FireUpdate(); } } diff --git a/src/PepperDash.Essentials.Core/PartitionSensor/IPartitionStateProvider.cs b/src/PepperDash.Essentials.Core/PartitionSensor/IPartitionStateProvider.cs index adb420b7..418da80c 100644 --- a/src/PepperDash.Essentials.Core/PartitionSensor/IPartitionStateProvider.cs +++ b/src/PepperDash.Essentials.Core/PartitionSensor/IPartitionStateProvider.cs @@ -1,9 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - +using System.Collections.Generic; +using Newtonsoft.Json; using PepperDash.Core; namespace PepperDash.Essentials.Core @@ -13,7 +9,11 @@ namespace PepperDash.Essentials.Core /// public interface IPartitionStateProvider : IKeyName { + [JsonIgnore] BoolFeedback PartitionPresentFeedback { get; } + + [JsonProperty("partitionPresent")] + bool PartitionPresent { get; } } /// @@ -21,8 +21,12 @@ namespace PepperDash.Essentials.Core /// public interface IPartitionController : IPartitionStateProvider { + [JsonProperty("adjacentRoomKeys")] List AdjacentRoomKeys { get; } + [JsonProperty("isInAutoMode")] + bool IsInAutoMode { get; } + void SetPartitionStatePresent(); void SetPartitionStateNotPresent(); diff --git a/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj b/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj index 02d13f7d..c074651a 100644 --- a/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj +++ b/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj @@ -12,6 +12,8 @@ PepperDash Essentials Core PepperDash.Essentials.Core $(Version) + false + 2.0.0-local full @@ -22,13 +24,9 @@ pdbonly - - - - - + diff --git a/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs b/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs index aebd2d22..4759b2cd 100644 --- a/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs +++ b/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using Crestron.SimplSharp; using Crestron.SimplSharp.CrestronIO; using System.Reflection; @@ -9,6 +8,7 @@ using System.Reflection; using PepperDash.Core; using PepperDash.Essentials.Core; using Serilog.Events; +using Newtonsoft.Json; namespace PepperDash.Essentials { @@ -27,24 +27,31 @@ namespace PepperDash.Essentials /// static List LoadedPluginFolderAssemblies; + public static LoadedAssembly EssentialsAssembly { get; private set; } + + public static LoadedAssembly PepperDashCoreAssembly { get; private set; } + + public static List EssentialsPluginAssemblies { get; private set; } + /// /// The directory to look in for .cplz plugin packages /// - static string _pluginDirectory = Global.FilePathPrefix + "plugins"; + static string _pluginDirectory => Global.FilePathPrefix + "plugins"; /// /// The directory where plugins will be moved to and loaded from /// - static string _loadedPluginsDirectoryPath = _pluginDirectory + Global.DirectorySeparator + "loadedAssemblies"; + static string _loadedPluginsDirectoryPath => _pluginDirectory + Global.DirectorySeparator + "loadedAssemblies"; // The temp directory where .cplz archives will be unzipped to - static string _tempDirectory = _pluginDirectory + Global.DirectorySeparator + "temp"; + static string _tempDirectory => _pluginDirectory + Global.DirectorySeparator + "temp"; static PluginLoader() { LoadedAssemblies = new List(); LoadedPluginFolderAssemblies = new List(); + EssentialsPluginAssemblies = new List(); } /// @@ -69,6 +76,7 @@ namespace PepperDash.Essentials case ("PepperDashEssentials.dll"): { version = Global.AssemblyVersion; + EssentialsAssembly = new LoadedAssembly(fi.Name, version, assembly); break; } case ("PepperDash_Essentials_Core.dll"): @@ -81,9 +89,12 @@ namespace PepperDash.Essentials version = Global.AssemblyVersion; break; } - case ("PepperDash_Core.dll"): + case ("PepperDashCore.dll"): { - version = PepperDash.Core.Debug.PepperDashCoreVersion; + Debug.LogMessage(LogEventLevel.Verbose, "Found PepperDash_Core.dll"); + version = Debug.PepperDashCoreVersion; + Debug.LogMessage(LogEventLevel.Verbose, "PepperDash_Core Version: {0}", version); + PepperDashCoreAssembly = new LoadedAssembly(fi.Name, version, assembly); break; } } @@ -151,7 +162,7 @@ namespace PepperDash.Essentials /// /// /// - static string GetAssemblyVersion(Assembly assembly) + public static string GetAssemblyVersion(Assembly assembly) { var ver = assembly.GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false); if (ver != null && ver.Length > 0) @@ -197,12 +208,19 @@ namespace PepperDash.Essentials /// public static void ReportAssemblyVersions(string command) { - - CrestronConsole.ConsoleCommandResponse("Loaded Assemblies:" + CrestronEnvironment.NewLine); - foreach (var assembly in LoadedAssemblies) + CrestronConsole.ConsoleCommandResponse("Essentials Version: {0}" + CrestronEnvironment.NewLine, Global.AssemblyVersion); + CrestronConsole.ConsoleCommandResponse("PepperDash Core Version: {0}" + CrestronEnvironment.NewLine, PepperDashCoreAssembly.Version); + CrestronConsole.ConsoleCommandResponse("Essentials Plugin Versions:" + CrestronEnvironment.NewLine); + foreach (var assembly in EssentialsPluginAssemblies) { CrestronConsole.ConsoleCommandResponse("{0} Version: {1}" + CrestronEnvironment.NewLine, assembly.Name, assembly.Version); } + + //CrestronConsole.ConsoleCommandResponse("Loaded Assemblies:" + CrestronEnvironment.NewLine); + //foreach (var assembly in LoadedAssemblies) + //{ + // CrestronConsole.ConsoleCommandResponse("{0} Version: {1}" + CrestronEnvironment.NewLine, assembly.Name, assembly.Version); + //} } /// /// Moves any .dll assemblies not already loaded from the plugins folder to loadedPlugins folder @@ -382,7 +400,7 @@ namespace PepperDash.Essentials if (typeof (IPluginDeviceFactory).IsAssignableFrom(type) && !type.IsAbstract) { var plugin = - (IPluginDeviceFactory) Crestron.SimplSharp.Reflection.Activator.CreateInstance(type); + (IPluginDeviceFactory)Activator.CreateInstance(type); LoadCustomPlugin(plugin, loadedAssembly); } } @@ -439,6 +457,9 @@ namespace PepperDash.Essentials Debug.LogMessage(LogEventLevel.Information, "Loading plugin: {0}", loadedAssembly.Name); plugin.LoadTypeFactories(); + + if(!EssentialsPluginAssemblies.Contains(loadedAssembly)) + EssentialsPluginAssemblies.Add(loadedAssembly); } /// @@ -493,6 +514,8 @@ namespace PepperDash.Essentials /// public static void LoadPlugins() { + Debug.LogMessage(LogEventLevel.Information, "Attempting to Load Plugins from {_pluginDirectory}", _pluginDirectory); + if (Directory.Exists(_pluginDirectory)) { Debug.LogMessage(LogEventLevel.Information, "Plugins directory found, checking for plugins"); @@ -521,8 +544,11 @@ namespace PepperDash.Essentials /// public class LoadedAssembly { + [JsonProperty("name")] public string Name { get; private set; } + [JsonProperty("version")] public string Version { get; private set; } + [JsonIgnore] public Assembly Assembly { get; private set; } public LoadedAssembly(string name, string version, Assembly assembly) diff --git a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs index ac5df758..dfc1066a 100644 --- a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs +++ b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using Crestron.SimplSharp; using PepperDash.Core; using Serilog.Events; +using Newtonsoft.Json; namespace PepperDash.Essentials.Core { @@ -17,7 +17,33 @@ namespace PepperDash.Essentials.Core private List _rooms; - private bool isInAutoMode; + public List Rooms + { + get + { + return _rooms.Cast().ToList(); + } + } + + private bool _isInAutoMode; + + public bool IsInAutoMode + { + get + { + return _isInAutoMode; + } + set + { + if(value == _isInAutoMode) + { + return; + } + + _isInAutoMode = value; + IsInAutoModeFeedback.FireUpdate(); + } + } private CTimer _scenarioChangeDebounceTimer; @@ -36,14 +62,14 @@ namespace PepperDash.Essentials.Core _scenarioChangeDebounceTimeSeconds = _propertiesConfig.ScenarioChangeDebounceTimeSeconds; } - IsInAutoModeFeedback = new BoolFeedback(() => isInAutoMode); + IsInAutoModeFeedback = new BoolFeedback(() => _isInAutoMode); // default to auto mode - isInAutoMode = true; + IsInAutoMode = true; if (_propertiesConfig.defaultToManualMode) { - isInAutoMode = false; + IsInAutoMode = false; } IsInAutoModeFeedback.FireUpdate(); @@ -56,7 +82,7 @@ namespace PepperDash.Essentials.Core SetRooms(); - if (isInAutoMode) + if (IsInAutoMode) { DetermineRoomCombinationScenario(); } @@ -111,7 +137,11 @@ namespace PepperDash.Essentials.Core void StartDebounceTimer() { - var time = _scenarioChangeDebounceTimeSeconds * 1000; + // default to 500ms for manual mode + var time = 500; + + // if in auto mode, debounce the scenario change + if(IsInAutoMode) time = _scenarioChangeDebounceTimeSeconds * 1000; if (_scenarioChangeDebounceTimer == null) { @@ -185,7 +215,7 @@ namespace PepperDash.Essentials.Core { _currentScenario.Activate(); - Debug.LogMessage(LogEventLevel.Debug, this, "Current Scenario: {0}", _currentScenario.Name); + Debug.LogMessage(LogEventLevel.Debug, $"Current Scenario: {_currentScenario.Name}", this); } var handler = RoomCombinationScenarioChanged; @@ -201,20 +231,17 @@ namespace PepperDash.Essentials.Core public void SetAutoMode() { - isInAutoMode = true; - IsInAutoModeFeedback.FireUpdate(); + IsInAutoMode = true; } public void SetManualMode() { - isInAutoMode = false; - IsInAutoModeFeedback.FireUpdate(); + IsInAutoMode = false; } public void ToggleMode() { - isInAutoMode = !isInAutoMode; - IsInAutoModeFeedback.FireUpdate(); + IsInAutoMode = !IsInAutoMode; } public List RoomCombinationScenarios { get; private set; } @@ -223,7 +250,7 @@ namespace PepperDash.Essentials.Core public void TogglePartitionState(string partitionKey) { - var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionKey)) as IPartitionController; + var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionKey)); if (partition != null) { @@ -233,7 +260,7 @@ namespace PepperDash.Essentials.Core public void SetRoomCombinationScenario(string scenarioKey) { - if (isInAutoMode) + if (IsInAutoMode) { Debug.LogMessage(LogEventLevel.Information, this, "Cannot set room combination scenario when in auto mode. Set to auto mode first."); return; diff --git a/src/PepperDash.Essentials.Core/Room/Combining/IEssentialsRoomCombiner.cs b/src/PepperDash.Essentials.Core/Room/Combining/IEssentialsRoomCombiner.cs index e6bdd983..0d4a40cc 100644 --- a/src/PepperDash.Essentials.Core/Room/Combining/IEssentialsRoomCombiner.cs +++ b/src/PepperDash.Essentials.Core/Room/Combining/IEssentialsRoomCombiner.cs @@ -1,9 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - +using Newtonsoft.Json; using PepperDash.Core; namespace PepperDash.Essentials.Core @@ -21,13 +18,21 @@ namespace PepperDash.Essentials.Core /// /// The current room combination scenario /// + [JsonProperty("currentScenario")] IRoomCombinationScenario CurrentScenario { get; } /// /// When true, indicates the current mode is auto mode /// + [JsonIgnore] BoolFeedback IsInAutoModeFeedback {get;} + [JsonProperty("isInAutoMode")] + bool IsInAutoMode { get; } + + [JsonProperty("rooms")] + List Rooms { get; } + /// /// Sets auto mode /// @@ -46,11 +51,13 @@ namespace PepperDash.Essentials.Core /// /// The available room combinatino scenarios /// + [JsonProperty("roomCombinationScenarios")] List RoomCombinationScenarios { get; } /// /// The partition /// + [JsonProperty("partitions")] List Partitions { get; } /// @@ -71,8 +78,12 @@ namespace PepperDash.Essentials.Core /// /// When true, indicates that this room combination scenario is active /// + [JsonIgnore] BoolFeedback IsActiveFeedback { get; } + [JsonProperty("isActive")] + bool IsActive { get; } + /// /// Activates this room combination scenario /// @@ -86,11 +97,13 @@ namespace PepperDash.Essentials.Core /// /// The state of the partitions that would activate this scenario /// + [JsonProperty("partitionStates")] List PartitionStates { get; } /// /// The mapping of UIs by key to rooms by key /// + [JsonProperty("uiMap")] Dictionary UiMap { get; set; } } diff --git a/src/PepperDash.Essentials.Core/Room/Combining/RoomCombinationScenario.cs b/src/PepperDash.Essentials.Core/Room/Combining/RoomCombinationScenario.cs index 3a64efb7..9bc0d8ec 100644 --- a/src/PepperDash.Essentials.Core/Room/Combining/RoomCombinationScenario.cs +++ b/src/PepperDash.Essentials.Core/Room/Combining/RoomCombinationScenario.cs @@ -16,20 +16,41 @@ namespace PepperDash.Essentials.Core /// /// Represents a room combination scenario /// - public class RoomCombinationScenario: IRoomCombinationScenario + public class RoomCombinationScenario: IRoomCombinationScenario, IKeyName { private RoomCombinationScenarioConfig _config; + [JsonProperty("key")] public string Key { get; set; } + [JsonProperty("name")] public string Name { get; set; } + [JsonProperty("partitionStates")] public List PartitionStates { get; private set; } + [JsonProperty("uiMap")] public Dictionary UiMap { get; set; } private bool _isActive; + [JsonProperty("isActive")] + public bool IsActive + { + get { return _isActive; } + set + { + if(value == _isActive) + { + return; + } + + _isActive = value; + IsActiveFeedback.FireUpdate(); + } + } + + [JsonIgnore] public BoolFeedback IsActiveFeedback { get; private set; } private List activationActions; @@ -67,8 +88,7 @@ namespace PepperDash.Essentials.Core } } - _isActive = true; - IsActiveFeedback.FireUpdate(); + IsActive = true; } public void Deactivate() @@ -83,8 +103,7 @@ namespace PepperDash.Essentials.Core } } - _isActive = false; - IsActiveFeedback.FireUpdate(); + IsActive = false; } } diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs index f807ffe7..32e1feda 100644 --- a/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs +++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs @@ -198,6 +198,9 @@ namespace PepperDash.Essentials.Room.Config public string SourceListKey { get; set; } [JsonProperty("destinationListKey")] public string DestinationListKey { get; set; } + [JsonProperty("audioControlPointListKey")] + public string AudioControlPointListKey { get; set; } + [JsonProperty("defaultSourceItem")] public string DefaultSourceItem { get; set; } /// diff --git a/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs b/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs index 82693d4c..be86b70f 100644 --- a/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs +++ b/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs @@ -59,28 +59,81 @@ namespace PepperDash.Essentials.Core /// public IMobileControlRoomMessenger MobileControlRoomBridge { get; private set; } + protected const string _defaultListKey = "default"; + /// /// The config name of the source list /// /// - protected string _SourceListKey; + private string _sourceListKey; public string SourceListKey { get { - return _SourceListKey; - } - private set - { - if (value != _SourceListKey) + if(string.IsNullOrEmpty(_sourceListKey)) { - _SourceListKey = value; + return _defaultListKey; + } + else + { + return _sourceListKey; + } + } + protected set + { + if (value != _sourceListKey) + { + _sourceListKey = value; } } } - public string DestinationListKey { get; private set; } + private string _destinationListKey; + public string DestinationListKey + { + get + { + if (string.IsNullOrEmpty(_destinationListKey)) + { + return _defaultListKey; + } + else + { + return _destinationListKey; + } + } + protected set + { + if (value != _destinationListKey) + { + _destinationListKey = value; + } + } + } + + private string _audioControlPointListKey; + public string AudioControlPointListKey + { + get + { + if (string.IsNullOrEmpty(_audioControlPointListKey)) + { + return _defaultListKey; + } + else + { + return _destinationListKey; + } + } + protected set + { + if (value != _audioControlPointListKey) + { + _audioControlPointListKey = value; + } + } + } + - protected const string _defaultSourceListKey = "default"; /// /// Timer used for informing the UIs of a shutdown @@ -141,6 +194,7 @@ namespace PepperDash.Essentials.Core if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue) ShutdownType = eShutdownType.None; }; + ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered ShutdownPromptSeconds = 60; @@ -191,7 +245,7 @@ namespace PepperDash.Essentials.Core } else { - sourceListKey = _defaultSourceListKey; + sourceListKey = _defaultListKey; } } diff --git a/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs b/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs index 8bf999cc..4bf51376 100644 --- a/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs +++ b/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs @@ -29,6 +29,8 @@ namespace PepperDash.Essentials.Core string DestinationListKey { get; } + string AudioControlPointListKey { get; } + SecondsCountdownTimer ShutdownPromptTimer { get; } int ShutdownPromptSeconds { get; } int ShutdownVacancySeconds { get; } diff --git a/src/PepperDash.Essentials.Core/Room/Interfaces.cs b/src/PepperDash.Essentials.Core/Room/Interfaces.cs index c60581d2..c7635d7a 100644 --- a/src/PepperDash.Essentials.Core/Room/Interfaces.cs +++ b/src/PepperDash.Essentials.Core/Room/Interfaces.cs @@ -159,4 +159,13 @@ namespace PepperDash.Essentials.Core Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; } } + public interface IHasAccessoryDevices : IKeyName + { + List AccessoryDeviceKeys { get; } + } + + public interface IHasCiscoNavigatorTouchpanel + { + string CiscoNavigatorTouchpanelKey { get; } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/Extensions.cs b/src/PepperDash.Essentials.Core/Routing/Extensions.cs index 03c59bf0..a0eba868 100644 --- a/src/PepperDash.Essentials.Core/Routing/Extensions.cs +++ b/src/PepperDash.Essentials.Core/Routing/Extensions.cs @@ -1,5 +1,6 @@ using PepperDash.Core; using Serilog.Events; +using System; using System.Collections.Generic; using System.Linq; @@ -12,20 +13,37 @@ namespace PepperDash.Essentials.Core /// on those destinations. /// public static class Extensions - { + { private static readonly Dictionary RouteRequests = new Dictionary(); - /// - /// Gets any existing RouteDescriptor for a destination, clears it using ReleaseRoute - /// and then attempts a new Route and if sucessful, stores that RouteDescriptor - /// in RouteDescriptorCollection.DefaultCollection - /// - public static void ReleaseAndMakeRoute(this IRoutingSink destination, IRoutingOutputs source, eRoutingSignalType signalType) - { - var routeRequest = new RouteRequest { - Destination = destination, - Source = source, - SignalType = signalType - }; + + /// + /// Gets any existing RouteDescriptor for a destination, clears it using ReleaseRoute + /// and then attempts a new Route and if sucessful, stores that RouteDescriptor + /// in RouteDescriptorCollection.DefaultCollection + /// + public static void ReleaseAndMakeRoute(this IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, string destinationPortKey = "", string sourcePortKey = "") + { + var inputPort = string.IsNullOrEmpty(destinationPortKey) ? null : destination.InputPorts.FirstOrDefault(p => p.Key == destinationPortKey); + var outputPort = string.IsNullOrEmpty(sourcePortKey) ? null : source.OutputPorts.FirstOrDefault(p => p.Key == sourcePortKey); + + ReleaseAndMakeRoute(destination, source, signalType, inputPort, outputPort); + } + + private static void ReleaseAndMakeRoute(IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort = null, RoutingOutputPort sourcePort = null) + { + if (destination == null) throw new ArgumentNullException(nameof(destination)); + if (source == null) throw new ArgumentNullException(nameof(source)); + if (destinationPort == null) Debug.LogMessage(LogEventLevel.Verbose, "Destination port is null"); + if (sourcePort == null) Debug.LogMessage(LogEventLevel.Verbose, "Source port is null"); + + var routeRequest = new RouteRequest + { + Destination = destination, + DestinationPort = destinationPort, + Source = source, + SourcePort = sourcePort, + SignalType = signalType + }; var coolingDevice = destination as IWarmingCooling; @@ -65,33 +83,39 @@ namespace PepperDash.Essentials.Core destination.ReleaseRoute(); - RunRouteRequest(routeRequest); - } + RunRouteRequest(routeRequest); + } private static void RunRouteRequest(RouteRequest request) { if (request.Source == null) return; - - var newRoute = request.Destination.GetRouteToSource(request.Source, request.SignalType); - if (newRoute == null) + var (audioOrSingleRoute, videoRoute) = request.Destination.GetRouteToSource(request.Source, request.SignalType, request.DestinationPort, request.SourcePort); + + if (audioOrSingleRoute == null && videoRoute == null) return; - RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(newRoute); + RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(audioOrSingleRoute); + + if (videoRoute != null) + { + RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(videoRoute); + } Debug.LogMessage(LogEventLevel.Verbose, "Executing full route", request.Destination); - newRoute.ExecuteRoutes(); + audioOrSingleRoute.ExecuteRoutes(); + videoRoute?.ExecuteRoutes(); } - /// - /// Will release the existing route on the destination, if it is found in - /// RouteDescriptorCollection.DefaultCollection - /// - /// - public static void ReleaseRoute(this IRoutingSink destination) - { + /// + /// Will release the existing route on the destination, if it is found in + /// RouteDescriptorCollection.DefaultCollection + /// + /// + public static void ReleaseRoute(this IRoutingInputs destination) + { if (RouteRequests.TryGetValue(destination.Key, out RouteRequest existingRequest) && destination is IWarmingCooling) { @@ -102,138 +126,191 @@ namespace PepperDash.Essentials.Core RouteRequests.Remove(destination.Key); - var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination); - if (current != null) - { - Debug.LogMessage(LogEventLevel.Debug, "Releasing current route: {0}", destination, current.Source.Key); - current.ReleaseRoutes(); - } - } + var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination); + if (current != null) + { + Debug.LogMessage(LogEventLevel.Debug, "Releasing current route: {0}", destination, current.Source.Key); + current.ReleaseRoutes(); + } + } - /// - /// Builds a RouteDescriptor that contains the steps necessary to make a route between devices. - /// Routes of type AudioVideo will be built as two separate routes, audio and video. If - /// a route is discovered, a new RouteDescriptor is returned. If one or both parts - /// of an audio/video route are discovered a route descriptor is returned. If no route is - /// discovered, then null is returned - /// - public static RouteDescriptor GetRouteToSource(this IRoutingSink destination, IRoutingOutputs source, eRoutingSignalType signalType) - { - var routeDescriptor = new RouteDescriptor(source, destination, signalType); + /// + /// Builds a RouteDescriptor that contains the steps necessary to make a route between devices. + /// Routes of type AudioVideo will be built as two separate routes, audio and video. If + /// a route is discovered, a new RouteDescriptor is returned. If one or both parts + /// of an audio/video route are discovered a route descriptor is returned. If no route is + /// discovered, then null is returned + /// + public static (RouteDescriptor, RouteDescriptor) GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort, RoutingOutputPort sourcePort) + { + // if it's a single signal type, find the route + if (!signalType.HasFlag(eRoutingSignalType.AudioVideo)) + { + var singleTypeRouteDescriptor = new RouteDescriptor(source, destination, signalType); + Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {sourceKey} of type {type}", destination, source.Key, signalType); - // if it's a single signal type, find the route - if (!signalType.HasFlag(eRoutingSignalType.AudioVideo)) - { - Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {0}", null, source.Key); + if (!destination.GetRouteToSource(source, null, null, signalType, 0, singleTypeRouteDescriptor, destinationPort, sourcePort)) + singleTypeRouteDescriptor = null; - if (!destination.GetRouteToSource(source, null, null, signalType, 0, routeDescriptor)) - routeDescriptor = null; + foreach (var route in singleTypeRouteDescriptor.Routes) + { + Debug.LogMessage(LogEventLevel.Verbose, "Route for device: {route}", destination, route.ToString()); + } - return routeDescriptor; - } - // otherwise, audioVideo needs to be handled as two steps. - - Debug.LogMessage(LogEventLevel.Debug, "Attempting to build audio and video routes from {0}", destination, source.Key); + return (singleTypeRouteDescriptor, null); + } + // otherwise, audioVideo needs to be handled as two steps. - var audioSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Audio, 0, routeDescriptor); + Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {sourceKey} of type {type}", destination, source.Key); - if (!audioSuccess) - Debug.LogMessage(LogEventLevel.Debug, "Cannot find audio route to {0}", destination, source.Key); + var audioRouteDescriptor = new RouteDescriptor(source, destination, eRoutingSignalType.Audio); - var videoSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Video, 0, routeDescriptor); + var audioSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Audio, 0, audioRouteDescriptor, destinationPort, sourcePort); - if (!videoSuccess) - Debug.LogMessage(LogEventLevel.Debug, "Cannot find video route to {0}", destination, source.Key); + if (!audioSuccess) + Debug.LogMessage(LogEventLevel.Debug, "Cannot find audio route to {0}", destination, source.Key); - if (!audioSuccess && !videoSuccess) - routeDescriptor = null; - - - return routeDescriptor; - } + var videoRouteDescriptor = new RouteDescriptor(source, destination, eRoutingSignalType.Video); - /// - /// The recursive part of this. Will stop on each device, search its inputs for the - /// desired source and if not found, invoke this function for the each input port - /// hoping to find the source. - /// - /// - /// - /// The RoutingOutputPort whose link is being checked for a route - /// Prevents Devices from being twice-checked - /// This recursive function should not be called with AudioVideo - /// Just an informational counter - /// The RouteDescriptor being populated as the route is discovered - /// true if source is hit - static bool GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source, - RoutingOutputPort outputPortToUse, List alreadyCheckedDevices, - eRoutingSignalType signalType, int cycle, RouteDescriptor routeTable) - { - cycle++; + var videoSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Video, 0, videoRouteDescriptor, destinationPort, sourcePort); - Debug.LogMessage(LogEventLevel.Verbose, "GetRouteToSource: {0} {1}--> {2}", null, cycle, source.Key, destination.Key); + if (!videoSuccess) + Debug.LogMessage(LogEventLevel.Debug, "Cannot find video route to {0}", destination, source.Key); - RoutingInputPort goodInputPort = null; + foreach (var route in audioRouteDescriptor.Routes) + { + Debug.LogMessage(LogEventLevel.Verbose, "Audio route for device: {route}", destination, route.ToString()); + } - var destinationTieLines = TieLineCollection.Default.Where(t => - t.DestinationPort.ParentDevice == destination && (t.Type == signalType || t.Type.HasFlag(eRoutingSignalType.AudioVideo))); + foreach (var route in videoRouteDescriptor.Routes) + { + Debug.LogMessage(LogEventLevel.Verbose, "Video route for device: {route}", destination, route.ToString()); + } - // find a direct tie - var directTie = destinationTieLines.FirstOrDefault( - t => t.DestinationPort.ParentDevice == destination - && t.SourcePort.ParentDevice == source); - if (directTie != null) // Found a tie directly to the source - { - goodInputPort = directTie.DestinationPort; - } - else // no direct-connect. Walk back devices. - { - Debug.LogMessage(LogEventLevel.Verbose, "is not directly connected to {0}. Walking down tie lines", destination, source.Key); - // No direct tie? Run back out on the inputs' attached devices... - // Only the ones that are routing devices - var attachedMidpoints = destinationTieLines.Where(t => t.SourcePort.ParentDevice is IRoutingInputsOutputs); + if (!audioSuccess && !videoSuccess) + return (null, null); + + + return (audioRouteDescriptor, videoRouteDescriptor); + } + + /// + /// The recursive part of this. Will stop on each device, search its inputs for the + /// desired source and if not found, invoke this function for the each input port + /// hoping to find the source. + /// + /// + /// + /// The RoutingOutputPort whose link is being checked for a route + /// Prevents Devices from being twice-checked + /// This recursive function should not be called with AudioVideo + /// Just an informational counter + /// The RouteDescriptor being populated as the route is discovered + /// true if source is hit + private static bool GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source, + RoutingOutputPort outputPortToUse, List alreadyCheckedDevices, + eRoutingSignalType signalType, int cycle, RouteDescriptor routeTable, RoutingInputPort destinationPort, RoutingOutputPort sourcePort) + { + cycle++; + + Debug.LogMessage(LogEventLevel.Verbose, "GetRouteToSource: {cycle} {sourceKey}:{sourcePortKey}--> {destinationKey}:{destinationPortKey} {type}", null, cycle, source.Key, sourcePort?.Key ?? "auto", destination.Key, destinationPort?.Key ?? "auto", signalType.ToString()); + + RoutingInputPort goodInputPort = null; + + IEnumerable destinationTieLines; + TieLine directTie = null; + + if (destinationPort == null) + { + + destinationTieLines = TieLineCollection.Default.Where(t => + t.DestinationPort.ParentDevice.Key == destination.Key && (t.Type == signalType || t.Type.HasFlag(eRoutingSignalType.AudioVideo))); + } + else + { + destinationTieLines = TieLineCollection.Default.Where(t => t.DestinationPort.ParentDevice.Key == destination.Key && t.DestinationPort.Key == destinationPort.Key && (t.Type == signalType || t.Type.HasFlag(eRoutingSignalType.AudioVideo))); + } + + // find the TieLine without a port + if (destinationPort == null && sourcePort == null) + { + directTie = destinationTieLines.FirstOrDefault(t => t.DestinationPort.ParentDevice.Key == destination.Key && t.SourcePort.ParentDevice.Key == source.Key); + } + // find a tieLine to a specific destination port without a specific source port + else if (destinationPort != null && sourcePort == null) + { + directTie = destinationTieLines.FirstOrDefault(t => t.DestinationPort.ParentDevice.Key == destination.Key && t.DestinationPort.Key == destinationPort.Key && t.SourcePort.ParentDevice.Key == source.Key); + } + // find a tieline to a specific source port without a specific destination port + else if (destinationPort == null & sourcePort != null) + { + directTie = destinationTieLines.FirstOrDefault(t => t.DestinationPort.ParentDevice.Key == destination.Key && t.SourcePort.ParentDevice.Key == source.Key && t.SourcePort.Key == sourcePort.Key); + } + // find a tieline to a specific source port and destination port + else if (destinationPort != null && sourcePort != null) + { + directTie = destinationTieLines.FirstOrDefault(t => t.DestinationPort.ParentDevice.Key == destination.Key && t.DestinationPort.Key == destinationPort.Key && t.SourcePort.ParentDevice.Key == source.Key && t.SourcePort.Key == sourcePort.Key); + } + + if (directTie != null) // Found a tie directly to the source + { + goodInputPort = directTie.DestinationPort; + } + else // no direct-connect. Walk back devices. + { + Debug.LogMessage(LogEventLevel.Verbose, "is not directly connected to {sourceKey}. Walking down tie lines", destination, source.Key); + + // No direct tie? Run back out on the inputs' attached devices... + // Only the ones that are routing devices + var midpointTieLines = destinationTieLines.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(); alreadyCheckedDevices.Add(destination as IRoutingInputsOutputs); - foreach (var inputTieToTry in attachedMidpoints) - { - var upstreamDeviceOutputPort = inputTieToTry.SourcePort; - var upstreamRoutingDevice = upstreamDeviceOutputPort.ParentDevice as IRoutingInputsOutputs; - Debug.LogMessage(LogEventLevel.Verbose, "Trying to find route on {0}", destination, upstreamRoutingDevice.Key); + foreach (var tieLine in midpointTieLines) + { + var midpointDevice = tieLine.SourcePort.ParentDevice as IRoutingInputsOutputs; - // Check if this previous device has already been walked - if (alreadyCheckedDevices.Contains(upstreamRoutingDevice)) + // Check if this previous device has already been walked + if (alreadyCheckedDevices.Contains(midpointDevice)) { - Debug.LogMessage(LogEventLevel.Verbose, "Skipping input {0} on {1}, this was already checked", destination, upstreamRoutingDevice.Key, destination.Key); + Debug.LogMessage(LogEventLevel.Verbose, "Skipping input {midpointDeviceKey} on {destinationKey}, this was already checked", destination, midpointDevice.Key, destination.Key); continue; } + + var midpointOutputPort = tieLine.SourcePort; + + Debug.LogMessage(LogEventLevel.Verbose, "Trying to find route on {midpointDeviceKey}", destination, midpointDevice.Key); + // 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); + var upstreamRoutingSuccess = midpointDevice.GetRouteToSource(source, midpointOutputPort, + alreadyCheckedDevices, signalType, cycle, routeTable, null, sourcePort); + if (upstreamRoutingSuccess) { Debug.LogMessage(LogEventLevel.Verbose, "Upstream device route found", destination); - goodInputPort = inputTieToTry.DestinationPort; + Debug.LogMessage(LogEventLevel.Verbose, "Route found on {midpointDeviceKey}", destination, midpointDevice.Key); + Debug.LogMessage(LogEventLevel.Verbose, "TieLine: SourcePort: {SourcePort} DestinationPort: {DestinationPort}", destination, tieLine.SourcePort, tieLine.DestinationPort); + goodInputPort = tieLine.DestinationPort; break; // Stop looping the inputs in this cycle } - } - } + } + } - - if (goodInputPort == null) - { + + if (goodInputPort == null) + { Debug.LogMessage(LogEventLevel.Verbose, "No route found to {0}", destination, source.Key); return false; - } + } // we have a route on corresponding inputPort. *** Do the route *** - if (outputPortToUse == null) + if (destination is IRoutingSink) { // it's a sink device routeTable.Routes.Add(new RouteSwitchDescriptor(goodInputPort)); @@ -244,8 +321,8 @@ namespace PepperDash.Essentials.Core } else // device is merely IRoutingInputOutputs Debug.LogMessage(LogEventLevel.Verbose, "No routing. Passthrough device", destination); - + return true; } - } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/GenericExtensions.cs b/src/PepperDash.Essentials.Core/Routing/GenericExtensions.cs deleted file mode 100644 index 4406d14f..00000000 --- a/src/PepperDash.Essentials.Core/Routing/GenericExtensions.cs +++ /dev/null @@ -1,261 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.DM; - -using PepperDash.Core; -using Serilog.Events; - - -namespace PepperDash.Essentials.Core -{ - - /// - /// Extensions added to any IRoutingInputs classes to provide discovery-based routing - /// on those destinations. - /// - public static class GenericExtensions - { - //private static readonly Dictionary> RouteRequests = new(); - - /// - /// Gets any existing RouteDescriptor for a destination, clears it using ReleaseRoute - /// and then attempts a new Route and if sucessful, stores that RouteDescriptor - /// in RouteDescriptorCollection.DefaultCollection - /// - public static void ReleaseAndMakeRoute(this IRoutingSink destination, IRoutingOutputs source, eRoutingSignalType signalType) - { - var routeRequest = new RouteRequest { - Destination = destination, - Source = source, - SignalType = signalType - }; - - var coolingDevice = destination as IWarmingCooling; - var existingRouteRequest = destination.GetRouteRequest(); - - //We already have a route request for this device, and it's a cooling device and is cooling - if (existingRouteRequest != null && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) - { - coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown; - - coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; - - destination.UpdateRouteRequest(routeRequest); - - Debug.LogMessage(LogEventLevel.Verbose, "Device: {0} is cooling down and already has a routing request stored. Storing new route request to route to source key: {1}", null, destination.Key, routeRequest.Source.Key); - - return; - } - - //New Request - if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) - { - coolingDevice.IsCoolingDownFeedback.OutputChange -= routeRequest.HandleCooldown; - - coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; - - destination.UpdateRouteRequest(routeRequest); - - Debug.LogMessage(LogEventLevel.Verbose, "Device: {0} is cooling down. Storing route request to route to source key: {1}", null, destination.Key, routeRequest.Source.Key); - return; - } - - if (existingRouteRequest != null && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == false) - { - destination.UpdateRouteRequest(null); - - Debug.LogMessage(LogEventLevel.Verbose, "Device: {0} is NOT cooling down. Removing stored route request and routing to source key: {1}", null, destination.Key, routeRequest.Source.Key); - } - - destination.ReleaseRoute(); - - RunRouteRequest(routeRequest); - } - - public static void RunRouteRequest(RouteRequest request) - { - if (request.Source == null) - return; - - var newRoute = request.Destination.GetRouteToSource(request.Source, request.SignalType); - - if (newRoute == null) - return; - - RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(newRoute); - - Debug.LogMessage(LogEventLevel.Verbose, "Executing full route", request.Destination); - - newRoute.ExecuteRoutes(); - } - - /// - /// Will release the existing route on the destination, if it is found in - /// RouteDescriptorCollection.DefaultCollection - /// - /// - public static void ReleaseRoute(this IRoutingSink destination) - { - var existingRouteRequest = destination.GetRouteRequest(); - - if (existingRouteRequest != null && destination is IWarmingCooling) - { - var coolingDevice = destination as IWarmingCooling; - - coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown; - } - - destination.UpdateRouteRequest(null); - - var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination); - if (current != null) - { - Debug.LogMessage(LogEventLevel.Debug, "Releasing current route: {0}", destination, current.Source.Key); - current.ReleaseRoutes(); - } - } - - /// - /// Builds a RouteDescriptor that contains the steps necessary to make a route between devices. - /// Routes of type AudioVideo will be built as two separate routes, audio and video. If - /// a route is discovered, a new RouteDescriptor is returned. If one or both parts - /// of an audio/video route are discovered a route descriptor is returned. If no route is - /// discovered, then null is returned - /// - public static RouteDescriptor GetRouteToSource(this IRoutingSink destination, IRoutingOutputs source, eRoutingSignalType signalType) - { - var routeDescriptor = new RouteDescriptor(source, destination, signalType); - - // if it's a single signal type, find the route - if (!signalType.HasFlag(eRoutingSignalType.AudioVideo)) - { - Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {0}", null, source.Key); - - if (!destination.GetRouteToSource(source, null, null, signalType, 0, routeDescriptor)) - routeDescriptor = null; - - return routeDescriptor; - } - // otherwise, audioVideo needs to be handled as two steps. - - Debug.LogMessage(LogEventLevel.Debug, "Attempting to build audio and video routes from {0}", destination, source.Key); - - var audioSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Audio, 0, routeDescriptor); - - if (!audioSuccess) - Debug.LogMessage(LogEventLevel.Debug, "Cannot find audio route to {0}", destination, source.Key); - - var videoSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Video, 0, routeDescriptor); - - if (!videoSuccess) - Debug.LogMessage(LogEventLevel.Debug, "Cannot find video route to {0}", destination, source.Key); - - if (!audioSuccess && !videoSuccess) - routeDescriptor = null; - - - return routeDescriptor; - } - - /// - /// The recursive part of this. Will stop on each device, search its inputs for the - /// desired source and if not found, invoke this function for the each input port - /// hoping to find the source. - /// - /// - /// - /// The RoutingOutputPort whose link is being checked for a route - /// Prevents Devices from being twice-checked - /// This recursive function should not be called with AudioVideo - /// Just an informational counter - /// The RouteDescriptor being populated as the route is discovered - /// true if source is hit - static bool GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source, - RoutingOutputPort outputPortToUse, List> alreadyCheckedDevices, - eRoutingSignalType signalType, int cycle, RouteDescriptor routeTable) - { - - cycle++; - - Debug.LogMessage(LogEventLevel.Verbose, "GetRouteToSource: {0} {1}--> {2}", null, cycle, source.Key, destination.Key); - - RoutingInputPort goodInputPort = null; - - var destDevInputTies = TieLineCollection.Default.Where(t => - t.DestinationPort.ParentDevice == destination && (t.Type == signalType || t.Type.HasFlag(eRoutingSignalType.AudioVideo))); - - // find a direct tie - var directTie = destDevInputTies.FirstOrDefault( - t => t.DestinationPort.ParentDevice == destination - && t.SourcePort.ParentDevice == source); - if (directTie != null) // Found a tie directly to the source - { - goodInputPort = directTie.DestinationPort; - } - else // no direct-connect. Walk back devices. - { - Debug.LogMessage(LogEventLevel.Verbose, "is not directly connected to {0}. Walking down tie lines", destination, source.Key); - - // 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>(); - alreadyCheckedDevices.Add(destination as IRoutingInputsOutputs); - - foreach (var inputTieToTry in attachedMidpoints) - { - var upstreamDeviceOutputPort = inputTieToTry.SourcePort; - var upstreamRoutingDevice = upstreamDeviceOutputPort.ParentDevice as IRoutingInputsOutputs; - Debug.LogMessage(LogEventLevel.Verbose, "Trying to find route on {0}", destination, upstreamRoutingDevice.Key); - - // Check if this previous device has already been walked - if (alreadyCheckedDevices.Contains(upstreamRoutingDevice)) - { - Debug.LogMessage(LogEventLevel.Verbose, "Skipping input {0} on {1}, this was already checked", destination, 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.LogMessage(LogEventLevel.Verbose, "Upstream device route found", destination); - goodInputPort = inputTieToTry.DestinationPort; - break; // Stop looping the inputs in this cycle - } - } - } - - - if (goodInputPort == null) - { - Debug.LogMessage(LogEventLevel.Verbose, "No route found to {0}", destination, source.Key); - return false; - } - - // we have a route on corresponding inputPort. *** Do the route *** - - if (outputPortToUse == null) - { - // it's a sink device - routeTable.Routes.Add(new RouteSwitchDescriptor(goodInputPort)); - } - else if (destination is IRouting) - { - routeTable.Routes.Add(new RouteSwitchDescriptor(outputPortToUse, goodInputPort)); - } - else // device is merely IRoutingInputOutputs - Debug.LogMessage(LogEventLevel.Verbose, "No routing. Passthrough device", destination); - - return true; - } - } -} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingSource.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingSource.cs index f4705b8d..d50bcbb0 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingSource.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingSource.cs @@ -3,7 +3,7 @@ /// /// Defines an IRoutingOutputs devices as being a source - the start of the chain /// - public interface IRoutingSource - { - } + public interface IRoutingSource : IRoutingOutputs + { + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/RouteRequest.cs b/src/PepperDash.Essentials.Core/Routing/RouteRequest.cs index f4836c6d..35169474 100644 --- a/src/PepperDash.Essentials.Core/Routing/RouteRequest.cs +++ b/src/PepperDash.Essentials.Core/Routing/RouteRequest.cs @@ -2,19 +2,22 @@ { public class RouteRequest { - public IRoutingSink Destination {get; set;} - public IRoutingOutputs Source {get; set;} - public eRoutingSignalType SignalType {get; set;} + public RoutingInputPort DestinationPort { get; set; } + + public RoutingOutputPort SourcePort { get; set; } + public IRoutingInputs Destination { get; set; } + public IRoutingOutputs Source { get; set; } + public eRoutingSignalType SignalType { get; set; } public void HandleCooldown(object sender, FeedbackEventArgs args) { var coolingDevice = sender as IWarmingCooling; - - if(args.BoolValue == false) + + if (args.BoolValue == false) { Destination.ReleaseAndMakeRoute(Source, SignalType); - - if(sender == null) return; + + if (sender == null) return; coolingDevice.IsCoolingDownFeedback.OutputChange -= HandleCooldown; } diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingPortNames.cs b/src/PepperDash.Essentials.Core/Routing/RoutingPortNames.cs index 1605c631..160b4f16 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingPortNames.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingPortNames.cs @@ -239,5 +239,13 @@ namespace PepperDash.Essentials.Core /// HdBaseTOut /// public const string HdBaseTOut = "hdBaseTOut"; + /// + /// SdiIn + /// + public const string SdiIn = "sdiIn"; + /// + /// SdiOut + /// + public const string SdiOut = "sdiOut"; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/TieLine.cs b/src/PepperDash.Essentials.Core/Routing/TieLine.cs index 245194a9..0b271272 100644 --- a/src/PepperDash.Essentials.Core/Routing/TieLine.cs +++ b/src/PepperDash.Essentials.Core/Routing/TieLine.cs @@ -1,98 +1,91 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using Newtonsoft.Json; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.DM; - -using PepperDash.Core; namespace PepperDash.Essentials.Core { - public class TieLine - { - public RoutingOutputPort SourcePort { get; private set; } - public RoutingInputPort DestinationPort { get; private set; } - //public int InUseCount { get { return DestinationUsingThis.Count; } } + public class TieLine + { + public RoutingOutputPort SourcePort { get; private set; } + public RoutingInputPort DestinationPort { get; private set; } + //public int InUseCount { get { return DestinationUsingThis.Count; } } - /// - /// Gets the type of this tie line. Will either be the type of the desination port - /// or the type of OverrideType when it is set. - /// - public eRoutingSignalType Type - { - get - { - if (OverrideType.HasValue) return OverrideType.Value; - return DestinationPort.Type; - } - } + /// + /// Gets the type of this tie line. Will either be the type of the desination port + /// or the type of OverrideType when it is set. + /// + public eRoutingSignalType Type + { + get + { + if (OverrideType.HasValue) return OverrideType.Value; + return DestinationPort.Type; + } + } - /// - /// Use this to override the Type property for the destination port. For example, - /// when the tie line is type AudioVideo, and the signal flow should be limited to - /// Audio-only or Video only, changing this type will alter the signal paths - /// available to the routing algorithm without affecting the actual Type - /// of the destination port. - /// - public eRoutingSignalType? OverrideType { get; set; } + /// + /// Use this to override the Type property for the destination port. For example, + /// when the tie line is type AudioVideo, and the signal flow should be limited to + /// Audio-only or Video only, changing this type will alter the signal paths + /// available to the routing algorithm without affecting the actual Type + /// of the destination port. + /// + public eRoutingSignalType? OverrideType { get; set; } - //List DestinationUsingThis = new List(); + //List DestinationUsingThis = new List(); - /// - /// For tie lines that represent internal links, like from cards to the matrix in a DM. - /// This property is true if SourcePort and DestinationPort IsInternal - /// property are both true - /// - public bool IsInternal { get { return SourcePort.IsInternal && DestinationPort.IsInternal; } } - public bool TypeMismatch { get { return SourcePort.Type != DestinationPort.Type; } } - public bool ConnectionTypeMismatch { get { return SourcePort.ConnectionType != DestinationPort.ConnectionType; } } - public string TypeMismatchNote { get; set; } + /// + /// For tie lines that represent internal links, like from cards to the matrix in a DM. + /// This property is true if SourcePort and DestinationPort IsInternal + /// property are both true + /// + public bool IsInternal { get { return SourcePort.IsInternal && DestinationPort.IsInternal; } } + public bool TypeMismatch { get { return SourcePort.Type != DestinationPort.Type; } } + public bool ConnectionTypeMismatch { get { return SourcePort.ConnectionType != DestinationPort.ConnectionType; } } + public string TypeMismatchNote { get; set; } - /// - /// - /// - /// - /// - public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort) - { - if (sourcePort == null || destinationPort == null) - throw new ArgumentNullException("source or destination port"); - SourcePort = sourcePort; - DestinationPort = destinationPort; - } + /// + /// + /// + /// + /// + public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort) + { + if (sourcePort == null || destinationPort == null) + throw new ArgumentNullException("source or destination port"); + SourcePort = sourcePort; + DestinationPort = destinationPort; + } - /// - /// Creates a tie line with an overriding Type. See help for OverrideType property for info - /// - /// The signal type to limit the link to. Overrides DestinationPort.Type - public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType overrideType) : - this(sourcePort, destinationPort) - { - OverrideType = overrideType; - } + /// + /// Creates a tie line with an overriding Type. See help for OverrideType property for info + /// + /// The signal type to limit the link to. Overrides DestinationPort.Type + public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType overrideType) : + this(sourcePort, destinationPort) + { + OverrideType = overrideType; + } - /// - /// Will link up video status from supporting inputs to connected outputs - /// - public void Activate() - { - // Now does nothing - } + /// + /// Will link up video status from supporting inputs to connected outputs + /// + public void Activate() + { + // Now does nothing + } - public void Deactivate() - { - // Now does nothing - } + public void Deactivate() + { + // Now does nothing + } - public override string ToString() - { - return string.Format("Tie line: {0}:{1} --> {2}:{3}", SourcePort.ParentDevice.Key, SourcePort.Key, - DestinationPort.ParentDevice.Key, DestinationPort.Key); - } - } + public override string ToString() + { + return string.Format("Tie line: {0}:{1} --> {2}:{3} {4}", SourcePort.ParentDevice.Key, SourcePort.Key, + DestinationPort.ParentDevice.Key, DestinationPort.Key, Type.ToString()); + } + } //******************************************************************************** @@ -109,6 +102,6 @@ namespace PepperDash.Essentials.Core } [JsonIgnore] - static TieLineCollection _Default; - } + private static TieLineCollection _Default; + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Timers/CountdownTimer.cs b/src/PepperDash.Essentials.Core/Timers/CountdownTimer.cs index 1cac0a50..cbb470d6 100644 --- a/src/PepperDash.Essentials.Core/Timers/CountdownTimer.cs +++ b/src/PepperDash.Essentials.Core/Timers/CountdownTimer.cs @@ -52,8 +52,8 @@ namespace PepperDash.Essentials.Core var timeSpan = FinishTime - DateTime.Now; - Debug.LogMessage(LogEventLevel.Verbose, this, - "timeSpan.Minutes == {0}, timeSpan.Seconds == {1}, timeSpan.TotalSeconds == {2}", + Debug.LogMessage(LogEventLevel.Verbose, + "timeSpan.Minutes == {0}, timeSpan.Seconds == {1}, timeSpan.TotalSeconds == {2}", this, timeSpan.Minutes, timeSpan.Seconds, timeSpan.TotalSeconds); if (Math.Floor(timeSpan.TotalSeconds) < 60 && Math.Floor(timeSpan.TotalSeconds) >= 0) //ignore milliseconds @@ -103,6 +103,7 @@ namespace PepperDash.Essentials.Core public void Reset() { _isRunning = false; + IsRunningFeedback.FireUpdate(); Start(); } @@ -133,7 +134,11 @@ namespace PepperDash.Essentials.Core void StopHelper() { if (_secondTimer != null) + { _secondTimer.Stop(); + _secondTimer = null; + } + _isRunning = false; IsRunningFeedback.FireUpdate(); } diff --git a/src/PepperDash.Essentials.Core/Web/EssentialsWebApiHelpers.cs b/src/PepperDash.Essentials.Core/Web/EssentialsWebApiHelpers.cs index cc6d4cd6..d5f5af36 100644 --- a/src/PepperDash.Essentials.Core/Web/EssentialsWebApiHelpers.cs +++ b/src/PepperDash.Essentials.Core/Web/EssentialsWebApiHelpers.cs @@ -80,7 +80,7 @@ namespace PepperDash.Essentials.Core.Web { Type = device.Key, Description = device.Value.Description, - CType = device.Value.CType == null ? "---": device.Value.CType.ToString() + CType = device.Value.Type == null ? "---": device.Value.Type.ToString() }; } } diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTieLinesRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTieLinesRequestHandler.cs index d5de5ad0..fb1db4e7 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTieLinesRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTieLinesRequestHandler.cs @@ -1,25 +1,24 @@ using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; using PepperDash.Core.Web.RequestHandlers; -using System; -using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; namespace PepperDash.Essentials.Core.Web.RequestHandlers { - public class GetTieLinesRequestHandler:WebApiBaseRequestHandler + public class GetTieLinesRequestHandler : WebApiBaseRequestHandler { public GetTieLinesRequestHandler() : base(true) { } protected override void HandleGet(HttpCwsContext context) { - var tieLineString = JsonConvert.SerializeObject(TieLineCollection.Default.Select((tl) => new { + var tieLineString = JsonConvert.SerializeObject(TieLineCollection.Default.Select((tl) => new + { sourceKey = tl.SourcePort.ParentDevice.Key, sourcePort = tl.SourcePort.Key, destinationKey = tl.DestinationPort.ParentDevice.Key, - destinationPort = tl.DestinationPort.Key + destinationPort = tl.DestinationPort.Key, + type = tl.Type.ToString(), })); context.Response.StatusCode = 200; diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraBase.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraBase.cs index d606249f..4d59fe90 100644 --- a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraBase.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; using Crestron.SimplSharp; -using Crestron.SimplSharp.Reflection; +using System.Reflection; using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Core; using PepperDash.Essentials.Core; diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraVisca.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraVisca.cs index 302aa0f1..fa82ba1f 100644 --- a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraVisca.cs +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraVisca.cs @@ -12,7 +12,7 @@ using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Devices.Common.Codec; using System.Text.RegularExpressions; -using Crestron.SimplSharp.Reflection; +using System.Reflection; using Newtonsoft.Json; using Serilog.Events; diff --git a/src/PepperDash.Essentials.Devices.Common/DeviceFactory.cs b/src/PepperDash.Essentials.Devices.Common/DeviceFactory.cs index fdb583dc..0f1f973f 100644 --- a/src/PepperDash.Essentials.Devices.Common/DeviceFactory.cs +++ b/src/PepperDash.Essentials.Devices.Common/DeviceFactory.cs @@ -25,7 +25,7 @@ namespace PepperDash.Essentials.Devices.Common { try { - var factory = (IDeviceFactory)Crestron.SimplSharp.Reflection.Activator.CreateInstance(type); + var factory = (IDeviceFactory)Activator.CreateInstance(type); factory.LoadTypeFactories(); } catch (Exception e) diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs index ea7f3a5b..0fecadc5 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs @@ -120,7 +120,7 @@ namespace PepperDash.Essentials.Devices.Common.Displays // Fake cool-down cycle CooldownTimer = new CTimer(o => { - Debug.LogMessage(LogEventLevel.Verbose, this, "Cooldown timer ending"); + Debug.LogMessage(LogEventLevel.Verbose, "Cooldown timer ending", this); _IsCoolingDown = false; IsCoolingDownFeedback.InvokeFireUpdate(); _PowerIsOn = false; @@ -143,10 +143,10 @@ namespace PepperDash.Essentials.Devices.Common.Displays { Debug.LogMessage(LogEventLevel.Verbose, "ExecuteSwitch: {0}", this, selector); - if (!_PowerIsOn) - { - PowerOn(); - } + if (!_PowerIsOn) + { + PowerOn(); + } if (!Inputs.Items.TryGetValue(selector.ToString(), out var input)) return; @@ -200,7 +200,6 @@ namespace PepperDash.Essentials.Devices.Common.Displays } - #region IBasicVolumeWithFeedback Members public IntFeedback VolumeLevelFeedback { get; private set; } @@ -270,21 +269,19 @@ namespace PepperDash.Essentials.Devices.Common.Displays { LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge); } - - } - public class MockDisplayFactory : EssentialsDeviceFactory - { - public MockDisplayFactory() - { - TypeNames = new List() { "mockdisplay2" }; - } + public class MockDisplayFactory : EssentialsDeviceFactory + { + public MockDisplayFactory() + { + TypeNames = new List() { "mockdisplay" , "mockdisplay2" }; + } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Mock Display Device"); - return new MockDisplay(dc.Key, dc.Name); - } - } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Mock Display Device"); + return new MockDisplay(dc.Key, dc.Name); + } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs index f6fb7bc0..0380085f 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs @@ -54,8 +54,7 @@ namespace PepperDash.Essentials.Devices.Common.Displays public class MockDisplayInput : ISelectableItem { - private IHasInputs _parent; - + private MockDisplay _parent; private bool _isSelected; @@ -91,7 +90,12 @@ namespace PepperDash.Essentials.Devices.Common.Displays public void Select() { - _parent.SetInput(Key); + if (!_parent.PowerIsOnFeedback.BoolValue) _parent.PowerOn(); + + foreach(var input in _parent.Inputs.Items) + { + input.Value.IsSelected = input.Key == this.Key; + } } } } diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs b/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs new file mode 100644 index 00000000..1bb7f503 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs @@ -0,0 +1,266 @@ +using System; +using System.Collections.Generic; +using Crestron.SimplSharp; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Config; +using PepperDash.Essentials.Core.CrestronIO; +using PepperDash.Essentials.Core.DeviceTypeInterfaces; +using PepperDash.Essentials.Devices.Common; +using Serilog.Events; + +namespace PepperDash.Essentials.Devices.Common.Shades +{ + /// + /// Controls a single shade using three relays + /// + public class ScreenLiftController : EssentialsDevice, IProjectorScreenLiftControl + { + readonly ScreenLiftControllerConfigProperties Config; + readonly ScreenLiftRelaysConfig RaiseRelayConfig; + readonly ScreenLiftRelaysConfig LowerRelayConfig; + readonly ScreenLiftRelaysConfig LatchedRelayConfig; + + Displays.DisplayBase DisplayDevice; + ISwitchedOutput RaiseRelay; + ISwitchedOutput LowerRelay; + ISwitchedOutput LatchedRelay; + + public bool InUpPosition + { + get { return _isInUpPosition; } + set + { + if (value == _isInUpPosition) return; + _isInUpPosition = value; + IsInUpPosition.FireUpdate(); + PositionChanged?.Invoke(this, new EventArgs()); + } + } + + private bool _isInUpPosition { get; set; } + public eScreenLiftControlType Type { get; private set; } + public eScreenLiftControlMode Mode { get; private set; } + + public string DisplayDeviceKey { get; private set; } + public BoolFeedback IsInUpPosition { get; private set; } + + public event EventHandler PositionChanged; + + public ScreenLiftController(string key, string name, ScreenLiftControllerConfigProperties config) + : base(key, name) + { + Config = config; + DisplayDeviceKey = Config.DisplayDeviceKey; + Mode = Config.Mode; + Type = Config.Type; + + IsInUpPosition = new BoolFeedback(() => _isInUpPosition); + + switch (Mode) + { + case eScreenLiftControlMode.momentary: + { + RaiseRelayConfig = Config.Relays["raise"]; + LowerRelayConfig = Config.Relays["lower"]; + break; + } + case eScreenLiftControlMode.latched: + { + LatchedRelayConfig = Config.Relays["latched"]; + break; + } + } + } + + private void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + if (!DisplayDevice.IsCoolingDownFeedback.BoolValue && Type == eScreenLiftControlType.lift) + { + Raise(); + return; + } + if (DisplayDevice.IsCoolingDownFeedback.BoolValue && Type == eScreenLiftControlType.screen) + { + Raise(); + return; + } + } + + private void IsWarmingUpFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + if (DisplayDevice.IsWarmingUpFeedback.BoolValue) + { + Lower(); + } + } + + public override bool CustomActivate() + { + //Create ISwitchedOutput objects based on props + switch (Mode) + { + case eScreenLiftControlMode.momentary: + { + Debug.LogMessage(LogEventLevel.Debug, this, $"Getting relays for {Mode}"); + RaiseRelay = GetSwitchedOutputFromDevice(RaiseRelayConfig.DeviceKey); + LowerRelay = GetSwitchedOutputFromDevice(LowerRelayConfig.DeviceKey); + break; + } + case eScreenLiftControlMode.latched: + { + Debug.LogMessage(LogEventLevel.Debug, this, $"Getting relays for {Mode}"); + LatchedRelay = GetSwitchedOutputFromDevice(LatchedRelayConfig.DeviceKey); + break; + } + } + + Debug.LogMessage(LogEventLevel.Debug, this, $"Getting display with key {DisplayDeviceKey}"); + DisplayDevice = GetDisplayBaseFromDevice(DisplayDeviceKey); + + if (DisplayDevice != null) + { + Debug.LogMessage(LogEventLevel.Debug, this, $"Subscribing to {DisplayDeviceKey} feedbacks"); + + DisplayDevice.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange; + DisplayDevice.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange; + } + + return base.CustomActivate(); + } + + public void Raise() + { + if (RaiseRelay == null && LatchedRelay == null) return; + + Debug.LogMessage(LogEventLevel.Debug, this, $"Raising {Type}"); + + switch (Mode) + { + case eScreenLiftControlMode.momentary: + { + PulseOutput(RaiseRelay, RaiseRelayConfig.PulseTimeInMs); + break; + } + case eScreenLiftControlMode.latched: + { + LatchedRelay.Off(); + break; + } + } + InUpPosition = true; + } + + public void Lower() + { + if (LowerRelay == null && LatchedRelay == null) return; + + Debug.LogMessage(LogEventLevel.Debug, this, $"Lowering {Type}"); + + switch (Mode) + { + case eScreenLiftControlMode.momentary: + { + PulseOutput(LowerRelay, LowerRelayConfig.PulseTimeInMs); + break; + } + case eScreenLiftControlMode.latched: + { + LatchedRelay.On(); + break; + } + } + InUpPosition = false; + } + + void PulseOutput(ISwitchedOutput output, int pulseTime) + { + output.On(); + CTimer pulseTimer = new CTimer(new CTimerCallbackFunction((o) => output.Off()), pulseTime); + } + + /// + /// Attempts to get the port on teh specified device from config + /// + /// + /// + ISwitchedOutput GetSwitchedOutputFromDevice(string relayKey) + { + var portDevice = DeviceManager.GetDeviceForKey(relayKey); + if (portDevice != null) + { + return (portDevice as ISwitchedOutput); + } + else + { + Debug.LogMessage(LogEventLevel.Debug, this, "Error: Unable to get relay device with key '{0}'", relayKey); + return null; + } + } + + Displays.DisplayBase GetDisplayBaseFromDevice(string displayKey) + { + var displayDevice = DeviceManager.GetDeviceForKey(displayKey); + if (displayDevice != null) + { + return displayDevice as Displays.DisplayBase; + } + else + { + Debug.LogMessage(LogEventLevel.Debug, this, "Error: Unable to get display device with key '{0}'", displayKey); + return null; + } + } + + } + + public class ScreenLiftControllerConfigProperties + { + [JsonProperty("displayDeviceKey")] + public string DisplayDeviceKey { get; set; } + + [JsonProperty("type")] + [JsonConverter(typeof(StringEnumConverter))] + public eScreenLiftControlType Type { get; set; } + + [JsonProperty("mode")] + [JsonConverter(typeof(StringEnumConverter))] + public eScreenLiftControlMode Mode { get; set; } + + [JsonProperty("relays")] + public Dictionary Relays { get; set; } + + } + public class ScreenLiftRelaysConfig + { + [JsonProperty("deviceKey")] + public string DeviceKey { get; set; } + + [JsonProperty("pulseTimeInMs")] + public int PulseTimeInMs { get; set; } + } + + public class ScreenLiftControllerFactory : EssentialsDeviceFactory + { + public ScreenLiftControllerFactory() + { + TypeNames = new List() { "screenliftcontroller" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Comm Device"); + var props = Newtonsoft.Json.JsonConvert.DeserializeObject(dc.Properties.ToString()); + + return new ScreenLiftController(dc.Key, dc.Name, props); + } + } + + public enum eScreenLiftControlMode + { + momentary, + latched + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Generic/GenericSource.cs b/src/PepperDash.Essentials.Devices.Common/Generic/GenericSource.cs index 80823156..3c6e57d2 100644 --- a/src/PepperDash.Essentials.Devices.Common/Generic/GenericSource.cs +++ b/src/PepperDash.Essentials.Devices.Common/Generic/GenericSource.cs @@ -13,7 +13,7 @@ using Serilog.Events; namespace PepperDash.Essentials.Devices.Common { - public class GenericSource : EssentialsDevice, IUiDisplayInfo, IRoutingSource, IRoutingOutputs, IUsageTracking + public class GenericSource : EssentialsDevice, IUiDisplayInfo, IRoutingSource, IUsageTracking { public uint DisplayUiType { get { return DisplayUiConstants.TypeNoControls; } } diff --git a/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj b/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj index b1abcdb0..69f6d24e 100644 --- a/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj +++ b/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj @@ -12,7 +12,9 @@ True PepperDash Essentials Devices Common PepperDash.Essentials.Devices.Common + 2.0.0-local $(Version) + false full @@ -28,6 +30,6 @@ - + \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTV.cs b/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTV.cs index e19c5c81..7a0b57f1 100644 --- a/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTV.cs +++ b/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTV.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using Crestron.SimplSharp; -using Crestron.SimplSharp.Reflection; +using System.Reflection; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using Newtonsoft.Json; @@ -42,7 +42,7 @@ namespace PepperDash.Essentials.Devices.Common public void PrintExpectedIrCommands() { - var cmds = typeof (AppleTvIrCommands).GetCType().GetFields(BindingFlags.Public | BindingFlags.Static); + var cmds = typeof (AppleTvIrCommands).GetType().GetFields(BindingFlags.Public | BindingFlags.Static); foreach (var value in cmds.Select(cmd => cmd.GetValue(null)).OfType()) { diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs index daa9aa0b..374efedf 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs @@ -1214,7 +1214,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec var entryIndex = counterIndex; Debug.LogMessage(LogEventLevel.Verbose, this, "Entry{2:0000} Name: {0}, Folder ID: {1}, Type: {3}, ParentFolderId: {4}", - entry.Name, entry.FolderId, entryIndex, entry.GetType().GetCType().FullName, entry.ParentFolderId); + entry.Name, entry.FolderId, entryIndex, entry.GetType().GetType().FullName, entry.ParentFolderId); if (entry is DirectoryFolder) { diff --git a/src/PepperDash.Essentials/ControlSystem.cs b/src/PepperDash.Essentials/ControlSystem.cs index e16e7b6d..ddc60c09 100644 --- a/src/PepperDash.Essentials/ControlSystem.cs +++ b/src/PepperDash.Essentials/ControlSystem.cs @@ -1,7 +1,7 @@  using Crestron.SimplSharp; using Crestron.SimplSharp.CrestronIO; -using Crestron.SimplSharp.Reflection; +using System.Reflection; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.CrestronThread; using Crestron.SimplSharpPro.Diagnostics; @@ -177,11 +177,7 @@ namespace PepperDash.Essentials directoryPrefix = Directory.GetApplicationRootDirectory(); - var fullVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); - - Global.SetAssemblyVersion(fullVersion); - - //Global.SetAssemblyVersion(fullVersionAtt.InformationalVersion); + Global.SetAssemblyVersion(PluginLoader.GetAssemblyVersion(Assembly.GetExecutingAssembly())); if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server) // Handles 3-series running Windows CE OS { diff --git a/src/PepperDash.Essentials/Example Configuration/EssentialsHuddleSpaceRoom/configurationFile-HuddleSpace-2-Source.json b/src/PepperDash.Essentials/Example Configuration/EssentialsHuddleSpaceRoom/configurationFile-HuddleSpace-2-Source.json index d3ce3275..7be04854 100644 --- a/src/PepperDash.Essentials/Example Configuration/EssentialsHuddleSpaceRoom/configurationFile-HuddleSpace-2-Source.json +++ b/src/PepperDash.Essentials/Example Configuration/EssentialsHuddleSpaceRoom/configurationFile-HuddleSpace-2-Source.json @@ -61,7 +61,7 @@ "supportedSystemTypes": [ "hudType", "presType", - "vtcType", + "vtType", "custom" ], "type": "rmc3", diff --git a/src/PepperDash.Essentials/Factory/DeviceFactory.cs b/src/PepperDash.Essentials/Factory/DeviceFactory.cs index c68f0520..262130f1 100644 --- a/src/PepperDash.Essentials/Factory/DeviceFactory.cs +++ b/src/PepperDash.Essentials/Factory/DeviceFactory.cs @@ -35,7 +35,7 @@ namespace PepperDash.Essentials { try { - var factory = (IDeviceFactory)Crestron.SimplSharp.Reflection.Activator.CreateInstance(type); + var factory = (IDeviceFactory)Activator.CreateInstance(type); factory.LoadTypeFactories(); } catch (Exception e) diff --git a/src/PepperDash.Essentials/PepperDash.Essentials.csproj b/src/PepperDash.Essentials/PepperDash.Essentials.csproj index 0aada6d1..274b257f 100644 --- a/src/PepperDash.Essentials/PepperDash.Essentials.csproj +++ b/src/PepperDash.Essentials/PepperDash.Essentials.csproj @@ -11,7 +11,9 @@ bin\$(Configuration)\ PepperDash Essentials PepperDashEssentials + 2.0.0-local $(Version) + false full @@ -47,7 +49,7 @@ - +