From d8e2f8cd51efc432e684a5801922a3d151a03d8c Mon Sep 17 00:00:00 2001 From: Joshua_Gutenplan <18546589+jgutenplan@users.noreply.github.com> Date: Thu, 25 Apr 2024 10:03:38 -0700 Subject: [PATCH 01/48] feat: IVideoCodecUiExtensions --- .../Interfaces/IVideoCodecUiExtensions.cs | 12 +++++++ .../IVideoCodecUiExtensionsClickedAction.cs | 35 +++++++++++++++++++ .../IVideoCodecUiExtensionsClickedEvent.cs | 25 +++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensions.cs create mode 100644 src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedAction.cs create mode 100644 src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedEvent.cs diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensions.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensions.cs new file mode 100644 index 00000000..32e7f0c8 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensions.cs @@ -0,0 +1,12 @@ +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +{ + public interface IVideoCodecUiExtensionsHandler : IVideoCodecUiExtensionsWebViewDisplayAction, IVideoCodecUiExtensionsClickedEvent + { + } + + public interface IVideoCodecUiExtensions + { + IVideoCodecUiExtensionsHandler VideoCodecUiExtensionsHandler { get; set; } + } + +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedAction.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedAction.cs new file mode 100644 index 00000000..aba77e13 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedAction.cs @@ -0,0 +1,35 @@ +using System; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +{ + public interface IVideoCodecUiExtensionsWebViewDisplayAction + { + Action UiWebViewDisplayAction { get; set; } + } + + public class UiWebViewDisplayActionArgs + { + + /// + /// Required <0 - 2000> The URL of the web page. + /// + public string Url { get; set; } + + /// + /// Fullscreen, Modal Full screen: Display the web page on the entire screen.Modal: Display the web page in a window. + /// + + public string Mode { get; set; } + + /// + /// <0 - 255> The title of the web page. + /// + public string Title { get; set; } + + /// + /// <0 - 8192> An HTTP header field.You can add up 15 Header parameters in one command, each holding one HTTP header field. + /// + public string Header { get; set; } + } + +} diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedEvent.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedEvent.cs new file mode 100644 index 00000000..9e9bb63d --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedEvent.cs @@ -0,0 +1,25 @@ +using System; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +{ + public interface IVideoCodecUiExtensionsClickedEvent + { + event EventHandler UiExtensionsClickedEvent; + } + + public class UiExtensionsClickedEventArgs : EventArgs + { + public bool Clicked { get; set; } + public string Id { get; set; } + + public UiExtensionsClickedEventArgs(bool clicked, string id) + { + Clicked = clicked; + Id = id; + } + + public UiExtensionsClickedEventArgs() + { + } + } +} From 06d806687d60fb10118663c19d421f7096f577df Mon Sep 17 00:00:00 2001 From: Joshua_Gutenplan <18546589+jgutenplan@users.noreply.github.com> Date: Thu, 25 Apr 2024 15:29:44 -0700 Subject: [PATCH 02/48] feat: IMobileControlTouchpanelController --- .../DeviceTypeInterfaces/IMobileControl.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMobileControl.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMobileControl.cs index 7f1d1621..84e31595 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMobileControl.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMobileControl.cs @@ -106,4 +106,11 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces Action Action { get; } } + public interface IMobileControlTouchpanelController + { + StringFeedback AppUrlFeedback { get; } + string DefaultRoomKey { get; } + string DeviceKey { get; } + } + } \ No newline at end of file From e1b50649fd92f7b9ebb1810c5070fb40ff65f0e5 Mon Sep 17 00:00:00 2001 From: Joshua_Gutenplan <18546589+jgutenplan@users.noreply.github.com> Date: Tue, 30 Apr 2024 21:41:53 -0700 Subject: [PATCH 03/48] fix: UiWebViewDisplayActionArgs add target --- .../Interfaces/IVideoCodecUiExtensionsClickedAction.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedAction.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedAction.cs index aba77e13..1c9cafa0 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedAction.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedAction.cs @@ -30,6 +30,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces /// <0 - 8192> An HTTP header field.You can add up 15 Header parameters in one command, each holding one HTTP header field. /// public string Header { get; set; } + + /// + /// OSD, Controller, PersistentWebApp Controller: Only for Cisco internal use. + /// OSD: Close the web view that is displayed on the screen of the device.PersistentWebApp: Only for Cisco internal use. + /// + public string Target { get; set; } } } From e9954b30812d389b1b93d1c1dcefd61aee93e909 Mon Sep 17 00:00:00 2001 From: Joshua_Gutenplan <18546589+jgutenplan@users.noreply.github.com> Date: Thu, 2 May 2024 12:07:00 -0700 Subject: [PATCH 04/48] fix: add GetRoomMessenger to IMobileControl --- .../DeviceTypeInterfaces/IMobileControl.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 From 65369606a460ac71b60ace7eee91877a548c109b Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 2 May 2024 15:00:17 -0600 Subject: [PATCH 05/48] feat: updates to room combiner interfaces --- .../Room/Combining/EssentialsRoomCombiner.cs | 47 ++++++++++++++----- .../Room/Combining/IEssentialsRoomCombiner.cs | 18 +++++-- .../Room/Combining/RoomCombinationScenario.cs | 29 ++++++++++-- 3 files changed, 73 insertions(+), 21 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs index ac5df758..882b0a13 100644 --- a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs +++ b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs @@ -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(); } @@ -201,20 +227,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; } @@ -233,7 +256,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..a035b650 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,20 @@ 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; } + + List Rooms { get; } + /// /// Sets auto mode /// @@ -46,11 +50,13 @@ namespace PepperDash.Essentials.Core /// /// The available room combinatino scenarios /// + [JsonProperty("roomCombinationScenarios")] List RoomCombinationScenarios { get; } /// /// The partition /// + [JsonProperty("partitions")] List Partitions { get; } /// @@ -73,6 +79,9 @@ namespace PepperDash.Essentials.Core /// BoolFeedback IsActiveFeedback { get; } + [JsonProperty("isActive")] + bool IsActive { get; } + /// /// Activates this room combination scenario /// @@ -86,6 +95,7 @@ namespace PepperDash.Essentials.Core /// /// The state of the partitions that would activate this scenario /// + [JsonProperty("partitionStates")] List PartitionStates { get; } /// 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; } } From 2b6f79b68f47cf1e39541e155d6299944dc2ad21 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 2 May 2024 17:27:34 -0600 Subject: [PATCH 06/48] feat: updates to Room combiner for use with mobile control --- .../EssentialsPartitionController.cs | 34 +++++++++++++++---- .../IPartitionStateProvider.cs | 13 +++---- .../Room/Combining/EssentialsRoomCombiner.cs | 2 +- .../Room/Combining/IEssentialsRoomCombiner.cs | 3 ++ 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs b/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs index 7066be0e..52d93162 100644 --- a/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs +++ b/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs @@ -19,7 +19,29 @@ namespace PepperDash.Essentials.Core private bool isInAutoMode; - 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) { @@ -85,11 +107,11 @@ namespace PepperDash.Essentials.Core isInAutoMode = false; if (PartitionPresentFeedback != null) { - PartitionPresentFeedback.SetValueFunc(() => partitionPresent); + PartitionPresentFeedback.SetValueFunc(() => _partitionPresent); } else { - PartitionPresentFeedback = new BoolFeedback(() => partitionPresent); + PartitionPresentFeedback = new BoolFeedback(() => _partitionPresent); } if (_partitionSensor != null) @@ -103,7 +125,7 @@ namespace PepperDash.Essentials.Core { if (!isInAutoMode) { - partitionPresent = true; + PartitionPresent = true; PartitionPresentFeedback.FireUpdate(); } } @@ -112,7 +134,7 @@ namespace PepperDash.Essentials.Core { if (!isInAutoMode) { - partitionPresent = false; + PartitionPresent = false; PartitionPresentFeedback.FireUpdate(); } } @@ -121,7 +143,7 @@ namespace PepperDash.Essentials.Core { 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..60bd080e 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,6 +21,7 @@ namespace PepperDash.Essentials.Core /// public interface IPartitionController : IPartitionStateProvider { + [JsonProperty("adjacentRoomKeys")] List AdjacentRoomKeys { get; } void SetPartitionStatePresent(); diff --git a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs index 882b0a13..11b0a3ec 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 { diff --git a/src/PepperDash.Essentials.Core/Room/Combining/IEssentialsRoomCombiner.cs b/src/PepperDash.Essentials.Core/Room/Combining/IEssentialsRoomCombiner.cs index a035b650..0d4a40cc 100644 --- a/src/PepperDash.Essentials.Core/Room/Combining/IEssentialsRoomCombiner.cs +++ b/src/PepperDash.Essentials.Core/Room/Combining/IEssentialsRoomCombiner.cs @@ -30,6 +30,7 @@ namespace PepperDash.Essentials.Core [JsonProperty("isInAutoMode")] bool IsInAutoMode { get; } + [JsonProperty("rooms")] List Rooms { get; } /// @@ -77,6 +78,7 @@ namespace PepperDash.Essentials.Core /// /// When true, indicates that this room combination scenario is active /// + [JsonIgnore] BoolFeedback IsActiveFeedback { get; } [JsonProperty("isActive")] @@ -101,6 +103,7 @@ namespace PepperDash.Essentials.Core /// /// The mapping of UIs by key to rooms by key /// + [JsonProperty("uiMap")] Dictionary UiMap { get; set; } } From 3ee8cb7ea3f18d82da4f793e8ae55577beee5dbd Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 3 May 2024 13:34:22 -0600 Subject: [PATCH 07/48] feat: updates IHasInput to remove requirement for SetInputs method (unnecessary) --- .../DeviceTypeInterfaces/IHasInputs.cs | 6 ++---- .../DeviceTypeInterfaces/ISelectableItems.cs | 2 +- .../PartitionSensor/EssentialsPartitionController.cs | 2 +- .../Displays/MockDisplayInputs.cs | 3 +-- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs index ef806d9a..3a9ac617 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs @@ -15,10 +15,8 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces /// /// See MockDisplay for example implemntation /// - public interface IHasInputs: IKeyName + public interface IHasInputs: IKeyName { - ISelectableItems Inputs { get; } - - void SetInput(TSelector selector); + ISelectableItems Inputs { get; } } } 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/PartitionSensor/EssentialsPartitionController.cs b/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs index 52d93162..213cb835 100644 --- a/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs +++ b/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs @@ -64,7 +64,7 @@ namespace PepperDash.Essentials.Core SetManualMode(); } } - else + else { SetManualMode(); } diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs index f6fb7bc0..5013913c 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; From 8ec6fa785e01f551f37edcdc52b406779c6a08a5 Mon Sep 17 00:00:00 2001 From: Andrew Knous Date: Thu, 9 May 2024 13:47:46 -0400 Subject: [PATCH 08/48] feat: adds IProjectorScreenLiftControl and ScreenLiftController --- .../IProjectorScreenLiftControl.cs | 27 ++ .../Displays/ScreenLiftController.cs | 266 ++++++++++++++++++ 2 files changed, 293 insertions(+) create mode 100644 src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IProjectorScreenLiftControl.cs create mode 100644 src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs 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.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 From 01862ab9aa712ddf418d2e9a058399b81a1dbedd Mon Sep 17 00:00:00 2001 From: Andrew Knous Date: Thu, 9 May 2024 13:48:59 -0400 Subject: [PATCH 09/48] feat: moves mockdisplay factory from PepperDash.Essentials.Core to PepperDash.Essential.Devices.Common --- .../Display/MockDisplay.cs | 14 -------------- .../Displays/MockDisplay.cs | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Display/MockDisplay.cs b/src/PepperDash.Essentials.Core/Display/MockDisplay.cs index 7c9f0446..dcd9e949 100644 --- a/src/PepperDash.Essentials.Core/Display/MockDisplay.cs +++ b/src/PepperDash.Essentials.Core/Display/MockDisplay.cs @@ -220,19 +220,5 @@ namespace PepperDash.Essentials.Core } - [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.Devices.Common/Displays/MockDisplay.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs index a1241821..3f90c457 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs @@ -6,6 +6,7 @@ using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.DeviceTypeInterfaces; using PepperDash.Essentials.Core.Routing; using Serilog.Events; @@ -251,4 +252,17 @@ namespace PepperDash.Essentials.Devices.Common.Displays } + 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 From 5a55a701d638d5933651e7a83c76dc60cd1e757c Mon Sep 17 00:00:00 2001 From: Joshua_Gutenplan <18546589+jgutenplan@users.noreply.github.com> Date: Thu, 9 May 2024 12:10:42 -0700 Subject: [PATCH 10/48] fix: remove codec interfaces that are only needed in cisco epi now --- .gitignore | 1 + .../Interfaces/IVideoCodecUiExtensions.cs | 12 ------ .../IVideoCodecUiExtensionsClickedAction.cs | 41 ------------------- .../IVideoCodecUiExtensionsClickedEvent.cs | 25 ----------- 4 files changed, 1 insertion(+), 78 deletions(-) delete mode 100644 src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensions.cs delete mode 100644 src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedAction.cs delete mode 100644 src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedEvent.cs 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.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensions.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensions.cs deleted file mode 100644 index 32e7f0c8..00000000 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensions.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces -{ - public interface IVideoCodecUiExtensionsHandler : IVideoCodecUiExtensionsWebViewDisplayAction, IVideoCodecUiExtensionsClickedEvent - { - } - - public interface IVideoCodecUiExtensions - { - IVideoCodecUiExtensionsHandler VideoCodecUiExtensionsHandler { get; set; } - } - -} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedAction.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedAction.cs deleted file mode 100644 index 1c9cafa0..00000000 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedAction.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; - -namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces -{ - public interface IVideoCodecUiExtensionsWebViewDisplayAction - { - Action UiWebViewDisplayAction { get; set; } - } - - public class UiWebViewDisplayActionArgs - { - - /// - /// Required <0 - 2000> The URL of the web page. - /// - public string Url { get; set; } - - /// - /// Fullscreen, Modal Full screen: Display the web page on the entire screen.Modal: Display the web page in a window. - /// - - public string Mode { get; set; } - - /// - /// <0 - 255> The title of the web page. - /// - public string Title { get; set; } - - /// - /// <0 - 8192> An HTTP header field.You can add up 15 Header parameters in one command, each holding one HTTP header field. - /// - public string Header { get; set; } - - /// - /// OSD, Controller, PersistentWebApp Controller: Only for Cisco internal use. - /// OSD: Close the web view that is displayed on the screen of the device.PersistentWebApp: Only for Cisco internal use. - /// - public string Target { get; set; } - } - -} diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedEvent.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedEvent.cs deleted file mode 100644 index 9e9bb63d..00000000 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IVideoCodecUiExtensionsClickedEvent.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; - -namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces -{ - public interface IVideoCodecUiExtensionsClickedEvent - { - event EventHandler UiExtensionsClickedEvent; - } - - public class UiExtensionsClickedEventArgs : EventArgs - { - public bool Clicked { get; set; } - public string Id { get; set; } - - public UiExtensionsClickedEventArgs(bool clicked, string id) - { - Clicked = clicked; - Id = id; - } - - public UiExtensionsClickedEventArgs() - { - } - } -} From 64ab315142c43770b4cab11989d91393d4ddc60e Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 9 May 2024 15:16:35 -0600 Subject: [PATCH 11/48] fix: various updates for room combining from testing --- .../EssentialsPartitionController.cs | 21 ++++++++++++------- .../IPartitionStateProvider.cs | 3 +++ .../Room/Combining/EssentialsRoomCombiner.cs | 10 ++++++--- .../Room/EssentialsRoomBase.cs | 1 + .../Timers/CountdownTimer.cs | 9 ++++++-- 5 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs b/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs index 213cb835..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,7 +18,7 @@ namespace PepperDash.Essentials.Core { private IPartitionStateProvider _partitionSensor; - private bool isInAutoMode; + public bool IsInAutoMode { get; private set; } private bool _partitionPresent; @@ -64,7 +65,7 @@ namespace PepperDash.Essentials.Core SetManualMode(); } } - else + else { SetManualMode(); } @@ -74,7 +75,7 @@ namespace PepperDash.Essentials.Core void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e) { - if (isInAutoMode) + if (IsInAutoMode) { PartitionPresentFeedback.FireUpdate(); } @@ -86,7 +87,7 @@ namespace PepperDash.Essentials.Core public void SetAutoMode() { - isInAutoMode = true; + IsInAutoMode = true; if (PartitionPresentFeedback != null) { PartitionPresentFeedback.SetValueFunc(() => _partitionSensor.PartitionPresentFeedback.BoolValue); @@ -98,13 +99,14 @@ 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); @@ -123,7 +125,7 @@ namespace PepperDash.Essentials.Core public void SetPartitionStatePresent() { - if (!isInAutoMode) + if (!IsInAutoMode) { PartitionPresent = true; PartitionPresentFeedback.FireUpdate(); @@ -132,7 +134,7 @@ namespace PepperDash.Essentials.Core public void SetPartitionStateNotPresent() { - if (!isInAutoMode) + if (!IsInAutoMode) { PartitionPresent = false; PartitionPresentFeedback.FireUpdate(); @@ -141,7 +143,10 @@ namespace PepperDash.Essentials.Core 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; PartitionPresentFeedback.FireUpdate(); diff --git a/src/PepperDash.Essentials.Core/PartitionSensor/IPartitionStateProvider.cs b/src/PepperDash.Essentials.Core/PartitionSensor/IPartitionStateProvider.cs index 60bd080e..418da80c 100644 --- a/src/PepperDash.Essentials.Core/PartitionSensor/IPartitionStateProvider.cs +++ b/src/PepperDash.Essentials.Core/PartitionSensor/IPartitionStateProvider.cs @@ -24,6 +24,9 @@ namespace PepperDash.Essentials.Core [JsonProperty("adjacentRoomKeys")] List AdjacentRoomKeys { get; } + [JsonProperty("isInAutoMode")] + bool IsInAutoMode { get; } + void SetPartitionStatePresent(); void SetPartitionStateNotPresent(); diff --git a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs index 11b0a3ec..dfc1066a 100644 --- a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs +++ b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs @@ -137,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) { @@ -211,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; @@ -246,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) { diff --git a/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs b/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs index 82693d4c..413e0ffc 100644 --- a/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs +++ b/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs @@ -141,6 +141,7 @@ namespace PepperDash.Essentials.Core if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue) ShutdownType = eShutdownType.None; }; + ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered ShutdownPromptSeconds = 60; 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(); } From 7e4b5f984f7883b102045f0ac35a0b8f48d55c47 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 9 May 2024 16:07:52 -0600 Subject: [PATCH 12/48] feat: Adds IHasAccessoryDevices --- src/PepperDash.Essentials.Core/Room/Interfaces.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/PepperDash.Essentials.Core/Room/Interfaces.cs b/src/PepperDash.Essentials.Core/Room/Interfaces.cs index 640dc91f..0835738b 100644 --- a/src/PepperDash.Essentials.Core/Room/Interfaces.cs +++ b/src/PepperDash.Essentials.Core/Room/Interfaces.cs @@ -159,4 +159,9 @@ namespace PepperDash.Essentials.Core Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; } } + public interface IHasAccessoryDevices : IKeyName + { + List AccessoryDevices { get; } + } + } \ No newline at end of file From 8878ff7ddd1409b8db5b60371994bf121e32cb6e Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 9 May 2024 16:09:16 -0600 Subject: [PATCH 13/48] chore: renames property to Keys --- src/PepperDash.Essentials.Core/Room/Interfaces.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PepperDash.Essentials.Core/Room/Interfaces.cs b/src/PepperDash.Essentials.Core/Room/Interfaces.cs index 0835738b..49436684 100644 --- a/src/PepperDash.Essentials.Core/Room/Interfaces.cs +++ b/src/PepperDash.Essentials.Core/Room/Interfaces.cs @@ -161,7 +161,7 @@ namespace PepperDash.Essentials.Core public interface IHasAccessoryDevices : IKeyName { - List AccessoryDevices { get; } + List AccessoryDeviceKeys { get; } } } \ No newline at end of file From a11ad421f0296797c493e3e7a49924834054aa46 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 10 May 2024 13:16:59 -0600 Subject: [PATCH 14/48] fix: better implmentation of input select --- .../Displays/MockDisplay.cs | 36 +++---------------- .../Displays/MockDisplayInputs.cs | 7 +++- 2 files changed, 11 insertions(+), 32 deletions(-) diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs index 3f90c457..ff4c451b 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs @@ -121,7 +121,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; @@ -142,10 +142,10 @@ namespace PepperDash.Essentials.Devices.Common.Displays { Debug.LogMessage(LogEventLevel.Verbose, this, "ExecuteSwitch: {0}", selector); - if (!_PowerIsOn) - { - PowerOn(); - } + if (!_PowerIsOn) + { + PowerOn(); + } if (!Inputs.Items.TryGetValue(selector.ToString(), out var input)) return; @@ -153,32 +153,6 @@ namespace PepperDash.Essentials.Devices.Common.Displays input.Select(); } - public void SetInput(string selector) - { - ISelectableItem currentInput = null; - - try - { - currentInput = Inputs.Items.SingleOrDefault(Inputs => Inputs.Value.IsSelected).Value; - } - catch { } - - - if (currentInput != null) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "SetInput: {0}", selector); - currentInput.IsSelected = false; - } - - if (!Inputs.Items.TryGetValue(selector, out var input)) - return; - - input.IsSelected = true; - - Inputs.CurrentItem = selector; - } - - #region IBasicVolumeWithFeedback Members diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs index 5013913c..0380085f 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs @@ -90,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; + } } } } From 98f1a09c25b40155bfca0dc9362852a2da8596c7 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 10 May 2024 14:49:37 -0600 Subject: [PATCH 15/48] feat: Adds IHasCiscoNavigatorTouchpanel interface --- src/PepperDash.Essentials.Core/Room/Interfaces.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/PepperDash.Essentials.Core/Room/Interfaces.cs b/src/PepperDash.Essentials.Core/Room/Interfaces.cs index 49436684..36e785cd 100644 --- a/src/PepperDash.Essentials.Core/Room/Interfaces.cs +++ b/src/PepperDash.Essentials.Core/Room/Interfaces.cs @@ -164,4 +164,8 @@ namespace PepperDash.Essentials.Core List AccessoryDeviceKeys { get; } } + public interface IHasCiscoNavigatorTouchpanel + { + string CiscoNavigatorTouchpanelKey { get; } + } } \ No newline at end of file From eb955aa0144ee4e047cd992eef19d7a4c90aa1ff Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 14 May 2024 15:32:23 -0600 Subject: [PATCH 16/48] build: updates version of PD.Core --force-patch --- .../Comm and IR/GenericHttpClient.cs | 11 +++-------- .../PepperDash.Essentials.Core.csproj | 2 +- .../PepperDash.Essentials.Devices.Common.csproj | 2 +- .../PepperDash.Essentials.csproj | 2 +- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Comm and IR/GenericHttpClient.cs b/src/PepperDash.Essentials.Core/Comm and IR/GenericHttpClient.cs index fa6c298a..47632c8d 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/GenericHttpClient.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/GenericHttpClient.cs @@ -1,15 +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 PepperDash.Core.DebugThings; +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/PepperDash.Essentials.Core.csproj b/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj index da717cb4..375d15b9 100644 --- a/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj +++ b/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj @@ -23,7 +23,7 @@ - + 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 abfcd9c2..ce96b6ec 100644 --- a/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj +++ b/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj @@ -27,6 +27,6 @@ - + \ No newline at end of file diff --git a/src/PepperDash.Essentials/PepperDash.Essentials.csproj b/src/PepperDash.Essentials/PepperDash.Essentials.csproj index e10707c2..53d5a2d1 100644 --- a/src/PepperDash.Essentials/PepperDash.Essentials.csproj +++ b/src/PepperDash.Essentials/PepperDash.Essentials.csproj @@ -47,7 +47,7 @@ - + From cb16f2a505f6c65337ad81913734a82a0033dca0 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 16 May 2024 17:17:59 -0600 Subject: [PATCH 17/48] feat: Adds LevelControlLists to BasicConfig and LevelControlListItem class --- .../Config/BasicConfig.cs | 5 +- .../Devices/LevelControlListItem.cs | 81 +++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs diff --git a/src/PepperDash.Essentials.Core/Config/BasicConfig.cs b/src/PepperDash.Essentials.Core/Config/BasicConfig.cs index 6e876de8..ca15680c 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("levelControlLists")] + public Dictionary> LevelControlLists { get; set; } [JsonProperty("tieLines")] public List TieLines { get; set; } diff --git a/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs new file mode 100644 index 00000000..2bdd1dcc --- /dev/null +++ b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs @@ -0,0 +1,81 @@ +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 LevelControlListItem + { + [JsonProperty("deviceKey")] + public string DeviceKey { get; set; } + + [JsonIgnore] + public IBasicVolumeWithFeedback LevelControl + { + get + { + if (_levelControl == null) + _levelControl = DeviceManager.GetDeviceForKey(DeviceKey) 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 "---"; + } + } + } + + /// + /// 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; } + + /// + /// Indicates if the item is a level, mute , or both + /// + [JsonProperty("type")] + public eLevelControlType Type { get; set; } + } + + public enum eLevelControlType + { + Level = 0, + Mute = 1, + LevelAndMute = 2, + } +} From 734149960b02ac2a7ad2f2886a50081df72596c2 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 16 May 2024 17:23:38 -0600 Subject: [PATCH 18/48] fix: Adds missing StringEnumConverter --- src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs index 2bdd1dcc..686474eb 100644 --- a/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs +++ b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs @@ -69,6 +69,7 @@ namespace PepperDash.Essentials.Core /// Indicates if the item is a level, mute , or both /// [JsonProperty("type")] + [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public eLevelControlType Type { get; set; } } From 735433f6602941a2e4423bd91680cb085e6bbe4a Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 16 May 2024 17:26:35 -0600 Subject: [PATCH 19/48] fix: adds missing flags decorator to enum --- src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs index 686474eb..68c9c58a 100644 --- a/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs +++ b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs @@ -73,6 +73,7 @@ namespace PepperDash.Essentials.Core public eLevelControlType Type { get; set; } } + [Flags] public enum eLevelControlType { Level = 0, From dde85f39a2476fd7864cd2285e0dbf0857e6f94a Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 16 May 2024 20:20:11 -0600 Subject: [PATCH 20/48] fix: combine enum values --- src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs index 68c9c58a..fb18eb69 100644 --- a/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs +++ b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs @@ -78,6 +78,6 @@ namespace PepperDash.Essentials.Core { Level = 0, Mute = 1, - LevelAndMute = 2, + LevelAndMute = Level | Mute, } } From 356640037938d12b12a9cfff412edb3fa25b8550 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 16 May 2024 20:24:45 -0600 Subject: [PATCH 21/48] fix: Adds LevelControlListKey to EssentialsRoomPropertiesConfig --- .../Room/Config/EssentialsRoomConfig.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs index f807ffe7..18fd9528 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("levelControlListKey")] + public string LevelControlListKey { get; set; } + [JsonProperty("defaultSourceItem")] public string DefaultSourceItem { get; set; } /// From e1638762a13a771b17cfc59a62882c4edf5dea58 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 16 May 2024 20:30:22 -0600 Subject: [PATCH 22/48] feat: Adds helper method for getting LevelControlList by key --- .../Config/BasicConfig.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Config/BasicConfig.cs b/src/PepperDash.Essentials.Core/Config/BasicConfig.cs index ca15680c..623aacc1 100644 --- a/src/PepperDash.Essentials.Core/Config/BasicConfig.cs +++ b/src/PepperDash.Essentials.Core/Config/BasicConfig.cs @@ -58,8 +58,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)) @@ -70,6 +70,19 @@ namespace PepperDash.Essentials.Core.Config return DestinationLists[key]; } + /// + /// Retrieves a LevelControlList based on the key + /// + /// key of the list to retrieve + /// LevelControlList if the key exists, null otherwise + public Dictionary GetLevelControlListForKey(string key) + { + if (string.IsNullOrEmpty(key) || !LevelControlLists.ContainsKey(key)) + return null; + + return LevelControlLists[key]; + } + /// /// Checks Devices for an item with a Key that matches and returns it if found. Otherwise, retunes null /// From 7942c91f731115c486a7dd928b1f58fdfed02ed2 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 16 May 2024 20:49:11 -0600 Subject: [PATCH 23/48] feat: Adds LevelControlListKey to IEssentialsRoom --- src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs b/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs index 8bf999cc..d3bf9873 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 LevelControlListKey { get; } + SecondsCountdownTimer ShutdownPromptTimer { get; } int ShutdownPromptSeconds { get; } int ShutdownVacancySeconds { get; } From 0067e11d3dd5f6046b6b4788974c39d7297081ea Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 16 May 2024 20:57:38 -0600 Subject: [PATCH 24/48] fix: Adds new property to EssentialsRoomBase and implements consistent default key if no key set --- .../Room/EssentialsRoomBase.cs | 73 ++++++++++++++++--- 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs b/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs index 413e0ffc..7359c0fa 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 _levelControlListKey; + public string LevelControlListKey + { + get + { + if (string.IsNullOrEmpty(_levelControlListKey)) + { + return _defaultListKey; + } + else + { + return _destinationListKey; + } + } + protected set + { + if (value != _levelControlListKey) + { + _levelControlListKey = value; + } + } + } + - protected const string _defaultSourceListKey = "default"; /// /// Timer used for informing the UIs of a shutdown @@ -192,7 +245,7 @@ namespace PepperDash.Essentials.Core } else { - sourceListKey = _defaultSourceListKey; + sourceListKey = _defaultListKey; } } From 7e736ae5196f263543863bf2ee49ea6fb7694d40 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 16 May 2024 22:44:57 -0600 Subject: [PATCH 25/48] fix: initializes LevelControlLists in config --- src/PepperDash.Essentials.Core/Config/BasicConfig.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PepperDash.Essentials.Core/Config/BasicConfig.cs b/src/PepperDash.Essentials.Core/Config/BasicConfig.cs index 623aacc1..32ee4ce7 100644 --- a/src/PepperDash.Essentials.Core/Config/BasicConfig.cs +++ b/src/PepperDash.Essentials.Core/Config/BasicConfig.cs @@ -40,6 +40,7 @@ namespace PepperDash.Essentials.Core.Config Devices = new List(); SourceLists = new Dictionary>(); DestinationLists = new Dictionary>(); + LevelControlLists = new Dictionary>(); TieLines = new List(); JoinMaps = new Dictionary(); } From d8d2c5b34026c8e6ea7a1f808025b909a3b75152 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 16 May 2024 23:07:13 -0600 Subject: [PATCH 26/48] build(force-patch): Updates PD.Core version to support LevelControlList property merge in config --- .../PepperDash.Essentials.Core.csproj | 2 +- .../PepperDash.Essentials.Devices.Common.csproj | 2 +- src/PepperDash.Essentials/PepperDash.Essentials.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj b/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj index 375d15b9..4646a0cc 100644 --- a/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj +++ b/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj @@ -23,7 +23,7 @@ - + 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 ce96b6ec..6e179d3a 100644 --- a/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj +++ b/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj @@ -27,6 +27,6 @@ - + \ No newline at end of file diff --git a/src/PepperDash.Essentials/PepperDash.Essentials.csproj b/src/PepperDash.Essentials/PepperDash.Essentials.csproj index 53d5a2d1..5aa6d143 100644 --- a/src/PepperDash.Essentials/PepperDash.Essentials.csproj +++ b/src/PepperDash.Essentials/PepperDash.Essentials.csproj @@ -47,7 +47,7 @@ - + From 2e61d8d7096aeec6fe882c10c0c9e8a42bf06bde Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 21 May 2024 16:49:13 -0600 Subject: [PATCH 27/48] fix: Changes LevelControlLists to AudioControlPointLists and modified IHasDspPresets --- .../Config/AudioControlPointListItem.cs | 19 ++++++++ .../Config/BasicConfig.cs | 18 ++++---- .../Devices/AudioControlListItemBase.cs | 36 +++++++++++++++ .../Devices/IDspPreset.cs | 17 ------- .../Devices/IDspPresets.cs | 12 +++++ .../Devices/LevelControlListItem.cs | 30 +++---------- .../Devices/PresetListItem.cs | 45 +++++++++++++++++++ .../PepperDash.Essentials.Core.csproj | 2 +- ...epperDash.Essentials.Devices.Common.csproj | 2 +- .../PepperDash.Essentials.csproj | 2 +- 10 files changed, 130 insertions(+), 53 deletions(-) create mode 100644 src/PepperDash.Essentials.Core/Config/AudioControlPointListItem.cs create mode 100644 src/PepperDash.Essentials.Core/Devices/AudioControlListItemBase.cs delete mode 100644 src/PepperDash.Essentials.Core/Devices/IDspPreset.cs create mode 100644 src/PepperDash.Essentials.Core/Devices/IDspPresets.cs create mode 100644 src/PepperDash.Essentials.Core/Devices/PresetListItem.cs diff --git a/src/PepperDash.Essentials.Core/Config/AudioControlPointListItem.cs b/src/PepperDash.Essentials.Core/Config/AudioControlPointListItem.cs new file mode 100644 index 00000000..e58b9ee7 --- /dev/null +++ b/src/PepperDash.Essentials.Core/Config/AudioControlPointListItem.cs @@ -0,0 +1,19 @@ +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; } + + [JsonProperty("presets")] + public Dictionary Presets { get; set; } + } +} diff --git a/src/PepperDash.Essentials.Core/Config/BasicConfig.cs b/src/PepperDash.Essentials.Core/Config/BasicConfig.cs index 32ee4ce7..4917e250 100644 --- a/src/PepperDash.Essentials.Core/Config/BasicConfig.cs +++ b/src/PepperDash.Essentials.Core/Config/BasicConfig.cs @@ -25,8 +25,8 @@ namespace PepperDash.Essentials.Core.Config [JsonProperty("destinationLists")] public Dictionary> DestinationLists { get; set; } - [JsonProperty("levelControlLists")] - public Dictionary> LevelControlLists { get; set; } + [JsonProperty("audioControlPointLists")] + public Dictionary> AudioControlPointLists { get; set; } [JsonProperty("tieLines")] public List TieLines { get; set; } @@ -40,7 +40,7 @@ namespace PepperDash.Essentials.Core.Config Devices = new List(); SourceLists = new Dictionary>(); DestinationLists = new Dictionary>(); - LevelControlLists = new Dictionary>(); + AudioControlPointLists = new Dictionary>(); TieLines = new List(); JoinMaps = new Dictionary(); } @@ -69,19 +69,19 @@ namespace PepperDash.Essentials.Core.Config } return DestinationLists[key]; - } + } /// - /// Retrieves a LevelControlList based on the key + /// Retrieves a AudioControlPointList based on the key /// /// key of the list to retrieve - /// LevelControlList if the key exists, null otherwise - public Dictionary GetLevelControlListForKey(string key) + /// AudioControlPointList if the key exists, null otherwise + public Dictionary GetAudioControlPointListForKey(string key) { - if (string.IsNullOrEmpty(key) || !LevelControlLists.ContainsKey(key)) + if (string.IsNullOrEmpty(key) || !AudioControlPointLists.ContainsKey(key)) return null; - return LevelControlLists[key]; + return AudioControlPointLists[key]; } /// 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/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/LevelControlListItem.cs b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs index fb18eb69..bb23e632 100644 --- a/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs +++ b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs @@ -5,13 +5,13 @@ 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 + public class LevelControlListItem : AudioControlListItemBase { - [JsonProperty("deviceKey")] - public string DeviceKey { get; set; } + [JsonIgnore] public IBasicVolumeWithFeedback LevelControl @@ -19,7 +19,7 @@ namespace PepperDash.Essentials.Core get { if (_levelControl == null) - _levelControl = DeviceManager.GetDeviceForKey(DeviceKey) as IBasicVolumeWithFeedback; + _levelControl = DeviceManager.GetDeviceForKey(ParentDeviceKey) as IBasicVolumeWithFeedback; return _levelControl; } } @@ -34,8 +34,8 @@ namespace PepperDash.Essentials.Core get { if (!string.IsNullOrEmpty(Name)) return Name; - else - { + else + { if (LevelControl is IKeyName namedLevelControl) { if (namedLevelControl == null) @@ -47,24 +47,6 @@ namespace PepperDash.Essentials.Core } } - /// - /// 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; } - /// /// Indicates if the item is a level, mute , or both /// 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/PepperDash.Essentials.Core.csproj b/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj index 4646a0cc..6c1a058e 100644 --- a/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj +++ b/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj @@ -23,7 +23,7 @@ - + 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 6e179d3a..c34ec280 100644 --- a/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj +++ b/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj @@ -27,6 +27,6 @@ - + \ No newline at end of file diff --git a/src/PepperDash.Essentials/PepperDash.Essentials.csproj b/src/PepperDash.Essentials/PepperDash.Essentials.csproj index 5aa6d143..3d85afd5 100644 --- a/src/PepperDash.Essentials/PepperDash.Essentials.csproj +++ b/src/PepperDash.Essentials/PepperDash.Essentials.csproj @@ -47,7 +47,7 @@ - + From e7e448f02c40c0a5271fbb39a3aadb4ecb1ef715 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 21 May 2024 17:04:15 -0600 Subject: [PATCH 28/48] fix: Switches from LevelControlListKey to AudioControlPointListKey --- .../Room/Config/EssentialsRoomConfig.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs index 18fd9528..32e1feda 100644 --- a/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs +++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs @@ -198,8 +198,8 @@ namespace PepperDash.Essentials.Room.Config public string SourceListKey { get; set; } [JsonProperty("destinationListKey")] public string DestinationListKey { get; set; } - [JsonProperty("levelControlListKey")] - public string LevelControlListKey { get; set; } + [JsonProperty("audioControlPointListKey")] + public string AudioControlPointListKey { get; set; } [JsonProperty("defaultSourceItem")] public string DefaultSourceItem { get; set; } From 048004d4418dbff6316218d1e3196b45262ae912 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 21 May 2024 17:14:13 -0600 Subject: [PATCH 29/48] fix: updates IEssentialsRoom and EssentialsRoomBase for missed changes --- .../Room/EssentialsRoomBase.cs | 10 +++++----- src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs b/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs index 7359c0fa..be86b70f 100644 --- a/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs +++ b/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs @@ -110,12 +110,12 @@ namespace PepperDash.Essentials.Core } } - private string _levelControlListKey; - public string LevelControlListKey + private string _audioControlPointListKey; + public string AudioControlPointListKey { get { - if (string.IsNullOrEmpty(_levelControlListKey)) + if (string.IsNullOrEmpty(_audioControlPointListKey)) { return _defaultListKey; } @@ -126,9 +126,9 @@ namespace PepperDash.Essentials.Core } protected set { - if (value != _levelControlListKey) + if (value != _audioControlPointListKey) { - _levelControlListKey = value; + _audioControlPointListKey = value; } } } diff --git a/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs b/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs index d3bf9873..4bf51376 100644 --- a/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs +++ b/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs @@ -29,7 +29,7 @@ namespace PepperDash.Essentials.Core string DestinationListKey { get; } - string LevelControlListKey { get; } + string AudioControlPointListKey { get; } SecondsCountdownTimer ShutdownPromptTimer { get; } int ShutdownPromptSeconds { get; } From 983b18d25a9409dcd590c53e472610f62e578399 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 21 May 2024 17:28:05 -0600 Subject: [PATCH 30/48] fix: fixes type of AudioControlPointLists --- src/PepperDash.Essentials.Core/Config/BasicConfig.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Config/BasicConfig.cs b/src/PepperDash.Essentials.Core/Config/BasicConfig.cs index 4917e250..6df7b583 100644 --- a/src/PepperDash.Essentials.Core/Config/BasicConfig.cs +++ b/src/PepperDash.Essentials.Core/Config/BasicConfig.cs @@ -26,7 +26,7 @@ namespace PepperDash.Essentials.Core.Config public Dictionary> DestinationLists { get; set; } [JsonProperty("audioControlPointLists")] - public Dictionary> AudioControlPointLists { get; set; } + public Dictionary AudioControlPointLists { get; set; } [JsonProperty("tieLines")] public List TieLines { get; set; } @@ -40,7 +40,7 @@ namespace PepperDash.Essentials.Core.Config Devices = new List(); SourceLists = new Dictionary>(); DestinationLists = new Dictionary>(); - AudioControlPointLists = new Dictionary>(); + AudioControlPointLists = new Dictionary(); TieLines = new List(); JoinMaps = new Dictionary(); } @@ -76,7 +76,7 @@ namespace PepperDash.Essentials.Core.Config /// /// key of the list to retrieve /// AudioControlPointList if the key exists, null otherwise - public Dictionary GetAudioControlPointListForKey(string key) + public AudioControlPointListItem GetAudioControlPointListForKey(string key) { if (string.IsNullOrEmpty(key) || !AudioControlPointLists.ContainsKey(key)) return null; From 2f9038a50171b1aa70a6c6bd5a1307c58e1d53a3 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 21 May 2024 22:15:50 -0600 Subject: [PATCH 31/48] fix: adds initializer for dictionaries --- .../Config/AudioControlPointListItem.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Config/AudioControlPointListItem.cs b/src/PepperDash.Essentials.Core/Config/AudioControlPointListItem.cs index e58b9ee7..3552c2b2 100644 --- a/src/PepperDash.Essentials.Core/Config/AudioControlPointListItem.cs +++ b/src/PepperDash.Essentials.Core/Config/AudioControlPointListItem.cs @@ -11,9 +11,10 @@ namespace PepperDash.Essentials.Core.Config public class AudioControlPointListItem { [JsonProperty("levelControls")] - public Dictionary LevelControls { get; set; } + public Dictionary LevelControls { get; set; } = new Dictionary(); [JsonProperty("presets")] - public Dictionary Presets { get; set; } + public Dictionary Presets { get; set; } = new Dictionary(); + } } From 621d8484185e14bc1d9794b48d50e2b89efe557f Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 22 May 2024 14:53:01 -0600 Subject: [PATCH 32/48] feat: adds deviceKey property to LevelControlListItem to synthesize device key --- .../Devices/LevelControlListItem.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs index bb23e632..d18dacc5 100644 --- a/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs +++ b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs @@ -47,6 +47,13 @@ namespace PepperDash.Essentials.Core } } + /// + /// 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 /// From 0a2aaa693f42b3409d5aa085908ca8d7e1f6f51c Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 23 May 2024 14:11:42 -0600 Subject: [PATCH 33/48] feat: Replaces Crestron.SimplSharp.Reflection with System.Reflextion and updates the way essentials plugin versions are stored and retrieved --- .../Bridges/BridgeBase.cs | 4 +- .../Config/InfoConfig.cs | 14 +++--- .../Devices/DeviceJsonApi.cs | 20 ++++----- .../Devices/DeviceManager.cs | 2 +- .../Devices/EssentialsDevice.cs | 2 +- .../Devices/IHasFeedbacks.cs | 6 +-- .../Factory/DeviceFactory.cs | 22 +++++----- .../Factory/IDeviceFactory.cs | 12 +---- .../ProcessorExtensionDeviceFactory.cs | 8 ++-- .../Global/Global.cs | 1 + .../JoinMaps/JoinMapBase.cs | 8 ++-- .../PepperDash.Essentials.Core.csproj | 5 ++- .../Plugins/PluginLoader.cs | 44 ++++++++++++++----- .../Web/EssentialsWebApiHelpers.cs | 2 +- .../Cameras/CameraBase.cs | 2 +- .../Cameras/CameraVisca.cs | 2 +- .../DeviceFactory.cs | 4 +- ...epperDash.Essentials.Devices.Common.csproj | 5 ++- .../Streaming/AppleTV.cs | 4 +- .../VideoCodec/VideoCodecBase.cs | 2 +- src/PepperDash.Essentials/ControlSystem.cs | 8 +--- ...onfigurationFile-HuddleSpace-2-Source.json | 2 +- .../Factory/DeviceFactory.cs | 4 +- .../PepperDash.Essentials.csproj | 6 ++- 24 files changed, 100 insertions(+), 89 deletions(-) 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/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/Devices/DeviceJsonApi.cs b/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs index 691aea55..9d0b9616 100644 --- a/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs +++ b/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using Crestron.SimplSharp; -using Crestron.SimplSharp.Reflection; +using System.Reflection; using Newtonsoft.Json; using PepperDash.Core; @@ -63,7 +63,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(); @@ -121,7 +121,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); @@ -139,7 +139,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) @@ -165,7 +165,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)); @@ -179,7 +179,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()) @@ -226,7 +226,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) { @@ -256,7 +256,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"); @@ -287,7 +287,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 @@ -365,7 +365,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/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/Factory/DeviceFactory.cs b/src/PepperDash.Essentials.Core/Factory/DeviceFactory.cs index 65b410e6..63c6b224 100644 --- a/src/PepperDash.Essentials.Core/Factory/DeviceFactory.cs +++ b/src/PepperDash.Essentials.Core/Factory/DeviceFactory.cs @@ -1,7 +1,7 @@  using Crestron.SimplSharp; -using Crestron.SimplSharp.Reflection; +using System.Reflection; using Newtonsoft.Json.Linq; using PepperDash.Core; using PepperDash.Essentials.Core.Config; @@ -14,13 +14,13 @@ namespace PepperDash.Essentials.Core { public class DeviceFactoryWrapper { - public CType 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, CType 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); } @@ -180,17 +180,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 68f5dc1f..b67dcf5b 100644 --- a/src/PepperDash.Essentials.Core/Factory/ProcessorExtensionDeviceFactory.cs +++ b/src/PepperDash.Essentials.Core/Factory/ProcessorExtensionDeviceFactory.cs @@ -1,5 +1,5 @@  -using Crestron.SimplSharp.Reflection; +using System.Reflection; using PepperDash.Core; using PepperDash.Essentials.Core.Config; using Serilog.Events; @@ -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, CType 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/PepperDash.Essentials.Core.csproj b/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj index 6c1a058e..72dbb279 100644 --- a/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj +++ b/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj @@ -11,6 +11,9 @@ PepperDash.Essentials.Core PepperDash Essentials Core PepperDash.Essentials.Core + $(Version) + false + 2.0.0-local full @@ -23,7 +26,7 @@ - + diff --git a/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs b/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs index 3e658ea1..3b70b112 100644 --- a/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs +++ b/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs @@ -1,14 +1,14 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using Crestron.SimplSharp; using Crestron.SimplSharp.CrestronIO; -using Crestron.SimplSharp.Reflection; +using System.Reflection; using PepperDash.Core; using PepperDash.Essentials.Core; using Serilog.Events; +using Newtonsoft.Json; namespace PepperDash.Essentials { @@ -27,24 +27,29 @@ namespace PepperDash.Essentials /// static List LoadedPluginFolderAssemblies; + public static LoadedAssembly EssentialsAssembly { 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 +74,7 @@ namespace PepperDash.Essentials case ("PepperDashEssentials.dll"): { version = Global.AssemblyVersion; + EssentialsAssembly = new LoadedAssembly(fi.Name, version, assembly); break; } case ("PepperDash_Essentials_Core.dll"): @@ -144,7 +150,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) @@ -190,12 +196,18 @@ 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("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 @@ -354,7 +366,7 @@ namespace PepperDash.Essentials try { var assy = loadedAssembly.Assembly; - CType[] types = {}; + Type[] types = {}; try { types = assy.GetTypes(); @@ -375,7 +387,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); } } @@ -432,6 +444,9 @@ namespace PepperDash.Essentials Debug.LogMessage(LogEventLevel.Information, "Loading plugin: {0}", loadedAssembly.Name); plugin.LoadTypeFactories(); + + if(!EssentialsPluginAssemblies.Contains(loadedAssembly)) + EssentialsPluginAssemblies.Add(loadedAssembly); } /// @@ -439,7 +454,7 @@ namespace PepperDash.Essentials /// /// /// - static void LoadCustomLegacyPlugin(CType type, MethodInfo loadPlugin, LoadedAssembly loadedAssembly) + static void LoadCustomLegacyPlugin(Type type, MethodInfo loadPlugin, LoadedAssembly loadedAssembly) { Debug.LogMessage(LogEventLevel.Verbose, "LoadPlugin method found in {0}", type.Name); @@ -486,6 +501,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"); @@ -514,8 +531,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/Web/EssentialsWebApiHelpers.cs b/src/PepperDash.Essentials.Core/Web/EssentialsWebApiHelpers.cs index 89718fcf..3a3dd756 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.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 bd8cf92f..0f1f973f 100644 --- a/src/PepperDash.Essentials.Devices.Common/DeviceFactory.cs +++ b/src/PepperDash.Essentials.Devices.Common/DeviceFactory.cs @@ -2,7 +2,7 @@ using System; using System.Linq; -using Crestron.SimplSharp.Reflection; +using System.Reflection; using PepperDash.Core; using PepperDash.Essentials.Core; using Serilog.Events; @@ -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/PepperDash.Essentials.Devices.Common.csproj b/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj index c34ec280..ac5d9790 100644 --- a/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj +++ b/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj @@ -12,6 +12,9 @@ True PepperDash Essentials Devices Common PepperDash.Essentials.Devices.Common + 2.0.0-local + $(Version) + false full @@ -27,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 5c8f9163..643db30d 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 b4b2efad..f2a98a8d 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 84bf12ec..f084e6a5 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; @@ -172,11 +172,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 73063e30..262130f1 100644 --- a/src/PepperDash.Essentials/Factory/DeviceFactory.cs +++ b/src/PepperDash.Essentials/Factory/DeviceFactory.cs @@ -6,7 +6,7 @@ using System.Linq; using Crestron.SimplSharp; using Crestron.SimplSharp.CrestronIO; using Crestron.SimplSharpPro; -using Crestron.SimplSharp.Reflection; +using System.Reflection; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -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 3d85afd5..4600ef2c 100644 --- a/src/PepperDash.Essentials/PepperDash.Essentials.csproj +++ b/src/PepperDash.Essentials/PepperDash.Essentials.csproj @@ -11,7 +11,9 @@ bin\$(Configuration)\ PepperDash Essentials PepperDashEssentials - $(Version) + 2.0.0-local + $(Version) + false full @@ -47,7 +49,7 @@ - + From 448cc273ec45f8883f76e4953730345865105d12 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 23 May 2024 14:42:31 -0600 Subject: [PATCH 34/48] feat: Adds PepperDashCoreAssembly --- src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs b/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs index 3b70b112..b8db5452 100644 --- a/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs +++ b/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs @@ -29,6 +29,8 @@ namespace PepperDash.Essentials public static LoadedAssembly EssentialsAssembly { get; private set; } + public static LoadedAssembly PepperDashCoreAssembly { get; private set; } + public static List EssentialsPluginAssemblies { get; private set; } /// @@ -89,7 +91,8 @@ namespace PepperDash.Essentials } case ("PepperDash_Core.dll"): { - version = PepperDash.Core.Debug.PepperDashCoreVersion; + version = GetAssemblyVersion(assembly); + PepperDashCoreAssembly = new LoadedAssembly(fi.Name, version, assembly); break; } } @@ -197,6 +200,7 @@ namespace PepperDash.Essentials public static void ReportAssemblyVersions(string command) { 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) { From 6e05653c6cf4c8523f063ff2e1ec6b8147000c86 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 28 May 2024 14:25:05 -0600 Subject: [PATCH 35/48] fix: fixes name for PDCore dll --- src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs b/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs index b8db5452..96c96e58 100644 --- a/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs +++ b/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs @@ -89,9 +89,11 @@ namespace PepperDash.Essentials version = Global.AssemblyVersion; break; } - case ("PepperDash_Core.dll"): + case ("PepperDashCore.dll"): { - version = GetAssemblyVersion(assembly); + 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; } @@ -200,7 +202,7 @@ namespace PepperDash.Essentials public static void ReportAssemblyVersions(string command) { CrestronConsole.ConsoleCommandResponse("Essentials Version: {0}" + CrestronEnvironment.NewLine, Global.AssemblyVersion); - CrestronConsole.ConsoleCommandResponse("PepperDash_Core Version: {0}" + CrestronEnvironment.NewLine, PepperDashCoreAssembly.Version); + CrestronConsole.ConsoleCommandResponse("PepperDash Core Version: {0}" + CrestronEnvironment.NewLine, PepperDashCoreAssembly.Version); CrestronConsole.ConsoleCommandResponse("Essentials Plugin Versions:" + CrestronEnvironment.NewLine); foreach (var assembly in EssentialsPluginAssemblies) { From b876b8123d7358e587e76f18b1ef81f2fa43e517 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 28 May 2024 14:25:34 -0600 Subject: [PATCH 36/48] feat: changes access modifiers to public on SystemMonitorController methods --- .../Monitoring/SystemMonitorController.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs b/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs index 1ffb1b3c..1494e136 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,7 +142,7 @@ namespace PepperDash.Essentials.Core.Monitoring _uptime = uptimeRaw.Substring(forIndex + 4); } - private static void ProcessorReboot() + public static void ProcessorReboot() { if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Server) return; @@ -150,7 +150,7 @@ namespace PepperDash.Essentials.Core.Monitoring CrestronConsole.SendControlSystemCommand("reboot", ref response); } - private static void ProgramReset(uint index) + public static void ProgramReset(uint index) { if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Server) return; From e61fd7777a31ef5e51f6672aa2e3a415e4ed5324 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 6 Jun 2024 12:09:35 -0600 Subject: [PATCH 37/48] fix: fixed typenames for mockDisplay --- .../Display/MockDisplay.cs | 223 ------------------ .../Monitoring/SystemMonitorController.cs | 7 +- .../Displays/MockDisplay.cs | 5 +- 3 files changed, 7 insertions(+), 228 deletions(-) delete mode 100644 src/PepperDash.Essentials.Core/Display/MockDisplay.cs diff --git a/src/PepperDash.Essentials.Core/Display/MockDisplay.cs b/src/PepperDash.Essentials.Core/Display/MockDisplay.cs deleted file mode 100644 index 973e550b..00000000 --- a/src/PepperDash.Essentials.Core/Display/MockDisplay.cs +++ /dev/null @@ -1,223 +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); - } - } - - - -} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs b/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs index 1494e136..06a4fbd9 100644 --- a/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs +++ b/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs @@ -145,16 +145,19 @@ namespace PepperDash.Essentials.Core.Monitoring 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); } 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.Devices.Common/Displays/MockDisplay.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs index 0a2a11b5..0fecadc5 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs @@ -269,14 +269,13 @@ namespace PepperDash.Essentials.Devices.Common.Displays { LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge); } - - } + public class MockDisplayFactory : EssentialsDeviceFactory { public MockDisplayFactory() { - TypeNames = new List() { "mockdisplay, mockdisplay2" }; + TypeNames = new List() { "mockdisplay" , "mockdisplay2" }; } public override EssentialsDevice BuildDevice(DeviceConfig dc) From 171bd6b1ecef633c6cb55140b5b7442152a88947 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 6 Jun 2024 12:15:30 -0600 Subject: [PATCH 38/48] fix: removed DefaultDisplay from TwoWayDisplayBase --- .../Display/DisplayBase.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) 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) From 3a56e47c4831a22f541992c96193613242cf5495 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 13 Jun 2024 10:59:05 -0600 Subject: [PATCH 39/48] fix: updates IHasInputs to remove second generic that is unnecessary. --- .../DeviceTypeInterfaces/IHasInputs.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs index 3a9ac617..9fa0f222 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs @@ -15,8 +15,22 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces /// /// See MockDisplay for example implemntation /// + [Obsolete("Use IHasInputs instead. Will be removed for 2.0 release")] public interface IHasInputs: IKeyName { ISelectableItems Inputs { get; } } + + + /// + /// 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; } + } } From 25ebcdfb5d0b8e170ab837c5f3f75c5fb102f80b Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 19 Jun 2024 14:09:59 -0500 Subject: [PATCH 40/48] feat: update routing methods Routing methods will now take a source port and destination port. This should solve the issue where a device could have multiple input ports defined in tielines and allow Essentials routing to find a path correctly. --- .../Routing/Extensions.cs | 284 ++++++++++-------- .../Routing/IRoutingSource.cs | 6 +- .../Routing/RouteRequest.cs | 17 +- 3 files changed, 177 insertions(+), 130 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Routing/Extensions.cs b/src/PepperDash.Essentials.Core/Routing/Extensions.cs index 03c59bf0..bf476531 100644 --- a/src/PepperDash.Essentials.Core/Routing/Extensions.cs +++ b/src/PepperDash.Essentials.Core/Routing/Extensions.cs @@ -12,20 +12,32 @@ 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) + { + var routeRequest = new RouteRequest + { + Destination = destination, + DestinationPort = destinationPort, + Source = source, + SourcePort = sourcePort, + SignalType = signalType + }; var coolingDevice = destination as IWarmingCooling; @@ -65,15 +77,15 @@ 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); + + var newRoute = request.Destination.GetRouteToSource(request.Source, request.SignalType, request.DestinationPort, request.SourcePort); if (newRoute == null) return; @@ -85,13 +97,13 @@ namespace PepperDash.Essentials.Core newRoute.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,150 +114,182 @@ 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 GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort, RoutingOutputPort sourcePort) + { + 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 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; + if (!destination.GetRouteToSource(source, sourcePort, null, signalType, 0, routeDescriptor, destinationPort)) + 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); + } + // 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 audio and video routes from {0}", destination, source.Key); - if (!audioSuccess) - Debug.LogMessage(LogEventLevel.Debug, "Cannot find audio route to {0}", destination, source.Key); + var audioSuccess = destination.GetRouteToSource(source, sourcePort, null, eRoutingSignalType.Audio, 0, routeDescriptor, destinationPort); - var videoSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Video, 0, routeDescriptor); + if (!audioSuccess) + Debug.LogMessage(LogEventLevel.Debug, "Cannot find audio route to {0}", destination, source.Key); - if (!videoSuccess) - Debug.LogMessage(LogEventLevel.Debug, "Cannot find video route to {0}", destination, source.Key); + var videoSuccess = destination.GetRouteToSource(source, sourcePort, null, eRoutingSignalType.Video, 0, routeDescriptor, destinationPort); - if (!audioSuccess && !videoSuccess) - routeDescriptor = null; - - - return routeDescriptor; - } + if (!videoSuccess) + Debug.LogMessage(LogEventLevel.Debug, "Cannot find video route to {0}", destination, source.Key); - /// - /// 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++; + if (!audioSuccess && !videoSuccess) + routeDescriptor = null; - Debug.LogMessage(LogEventLevel.Verbose, "GetRouteToSource: {0} {1}--> {2}", null, cycle, source.Key, destination.Key); - RoutingInputPort goodInputPort = null; + return routeDescriptor; + } - var destinationTieLines = TieLineCollection.Default.Where(t => - t.DestinationPort.ParentDevice == destination && (t.Type == signalType || t.Type.HasFlag(eRoutingSignalType.AudioVideo))); + /// + /// 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 sourcePort, List alreadyCheckedDevices, + eRoutingSignalType signalType, int cycle, RouteDescriptor routeTable, RoutingInputPort destinationPort) + { + cycle++; - // 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); + Debug.LogMessage(LogEventLevel.Verbose, "GetRouteToSource: {0} {1}--> {2}", null, cycle, source.Key, destination.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); + 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.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.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.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.Key == destinationPort.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 {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 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 {0} on {1}, this was already checked", destination, midpointDevice.Key, destination.Key); continue; } + + var midpointOutputPort = sourcePort ?? tieLine.SourcePort; + + Debug.LogMessage(LogEventLevel.Verbose, "Trying to find route on {0}", 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); + if (upstreamRoutingSuccess) { Debug.LogMessage(LogEventLevel.Verbose, "Upstream device route found", destination); - goodInputPort = inputTieToTry.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 (sourcePort == null) { // it's a sink device routeTable.Routes.Add(new RouteSwitchDescriptor(goodInputPort)); } else if (destination is IRouting) { - routeTable.Routes.Add(new RouteSwitchDescriptor(outputPortToUse, goodInputPort)); + routeTable.Routes.Add(new RouteSwitchDescriptor(sourcePort, 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; } From ed0141a53679b60e8f68fe6dafb8b73c08bd0fa6 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 19 Jun 2024 14:37:04 -0500 Subject: [PATCH 41/48] fix: change ports and what's used where --- src/PepperDash.Essentials.Core/Routing/Extensions.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Routing/Extensions.cs b/src/PepperDash.Essentials.Core/Routing/Extensions.cs index bf476531..b48d6a03 100644 --- a/src/PepperDash.Essentials.Core/Routing/Extensions.cs +++ b/src/PepperDash.Essentials.Core/Routing/Extensions.cs @@ -178,8 +178,8 @@ namespace PepperDash.Essentials.Core /// The RouteDescriptor being populated as the route is discovered /// true if source is hit private static bool GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source, - RoutingOutputPort sourcePort, List alreadyCheckedDevices, - eRoutingSignalType signalType, int cycle, RouteDescriptor routeTable, RoutingInputPort destinationPort) + RoutingOutputPort outputPortToUse, List alreadyCheckedDevices, + eRoutingSignalType signalType, int cycle, RouteDescriptor routeTable, RoutingInputPort destinationPort, RoutingOutputPort sourcePort) { cycle++; @@ -250,14 +250,14 @@ namespace PepperDash.Essentials.Core continue; } - var midpointOutputPort = sourcePort ?? tieLine.SourcePort; + var midpointOutputPort = tieLine.SourcePort; Debug.LogMessage(LogEventLevel.Verbose, "Trying to find route on {0}", 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 = midpointDevice.GetRouteToSource(source, midpointOutputPort, - alreadyCheckedDevices, signalType, cycle, routeTable, null); + alreadyCheckedDevices, signalType, cycle, routeTable, null, sourcePort); if (upstreamRoutingSuccess) { @@ -277,14 +277,14 @@ namespace PepperDash.Essentials.Core // we have a route on corresponding inputPort. *** Do the route *** - if (sourcePort == null) + if (destination is IRoutingSink) { // it's a sink device routeTable.Routes.Add(new RouteSwitchDescriptor(goodInputPort)); } else if (destination is IRouting) { - routeTable.Routes.Add(new RouteSwitchDescriptor(sourcePort, goodInputPort)); + routeTable.Routes.Add(new RouteSwitchDescriptor(outputPortToUse, goodInputPort)); } else // device is merely IRoutingInputOutputs Debug.LogMessage(LogEventLevel.Verbose, "No routing. Passthrough device", destination); From 7bac65002d353e8b5a2f3311bcf7a83ba09e0d45 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 19 Jun 2024 15:01:25 -0500 Subject: [PATCH 42/48] fix: correct issues with method calls --- src/PepperDash.Essentials.Core/Routing/Extensions.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Routing/Extensions.cs b/src/PepperDash.Essentials.Core/Routing/Extensions.cs index b48d6a03..9090f034 100644 --- a/src/PepperDash.Essentials.Core/Routing/Extensions.cs +++ b/src/PepperDash.Essentials.Core/Routing/Extensions.cs @@ -138,7 +138,7 @@ namespace PepperDash.Essentials.Core { Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {0}", null, source.Key); - if (!destination.GetRouteToSource(source, sourcePort, null, signalType, 0, routeDescriptor, destinationPort)) + if (!destination.GetRouteToSource(source, null, null, signalType, 0, routeDescriptor, destinationPort, sourcePort)) routeDescriptor = null; return routeDescriptor; @@ -147,12 +147,12 @@ namespace PepperDash.Essentials.Core Debug.LogMessage(LogEventLevel.Debug, "Attempting to build audio and video routes from {0}", destination, source.Key); - var audioSuccess = destination.GetRouteToSource(source, sourcePort, null, eRoutingSignalType.Audio, 0, routeDescriptor, destinationPort); + var audioSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Audio, 0, routeDescriptor, destinationPort, sourcePort); if (!audioSuccess) Debug.LogMessage(LogEventLevel.Debug, "Cannot find audio route to {0}", destination, source.Key); - var videoSuccess = destination.GetRouteToSource(source, sourcePort, null, eRoutingSignalType.Video, 0, routeDescriptor, destinationPort); + var videoSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Video, 0, routeDescriptor, destinationPort, sourcePort); if (!videoSuccess) Debug.LogMessage(LogEventLevel.Debug, "Cannot find video route to {0}", destination, source.Key); From 5aa1f85df51bff056ef19e9f3c9dee8492d3a9bc Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 20 Jun 2024 11:57:32 -0600 Subject: [PATCH 43/48] feat: adds try catch to devjson execution thread and adds port names for sdi in/out --- .../Devices/DeviceJsonApi.cs | 13 ++++++++++++- .../Routing/RoutingPortNames.cs | 8 ++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs b/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs index 7c16021a..18559b40 100644 --- a/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs +++ b/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs @@ -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); 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 From e5e79316a63ef8480362a9b3e82b85ec0fadfd4e Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 21 Jun 2024 14:53:03 -0600 Subject: [PATCH 44/48] fix: fixes conditions for specific port and device matches --- .../Routing/Extensions.cs | 43 +++++++++++++++++-- .../Generic/GenericSource.cs | 2 +- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Routing/Extensions.cs b/src/PepperDash.Essentials.Core/Routing/Extensions.cs index 9090f034..fa685c7b 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; @@ -30,6 +31,11 @@ namespace PepperDash.Essentials.Core 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, @@ -141,6 +147,18 @@ namespace PepperDash.Essentials.Core if (!destination.GetRouteToSource(source, null, null, signalType, 0, routeDescriptor, destinationPort, sourcePort)) routeDescriptor = null; + foreach (var route in routeDescriptor.Routes) + { + Debug.LogMessage(LogEventLevel.Verbose, + @"Route for device: {route} +InputPort: {InputPort} +OutputPort: {OutputPort}", + destination, + route.SwitchingDevice.Key, + route.InputPort, + route.OutputPort); + } + return routeDescriptor; } // otherwise, audioVideo needs to be handled as two steps. @@ -157,6 +175,19 @@ namespace PepperDash.Essentials.Core if (!videoSuccess) Debug.LogMessage(LogEventLevel.Debug, "Cannot find video route to {0}", destination, source.Key); + foreach (var route in routeDescriptor.Routes) + { + Debug.LogMessage(LogEventLevel.Verbose, +@"Route for device: {route} +InputPort: {InputPort} +OutputPort: {OutputPort}", +destination, +route.SwitchingDevice.Key, +route.InputPort, +route.OutputPort); + } + + if (!audioSuccess && !videoSuccess) routeDescriptor = null; @@ -209,17 +240,17 @@ namespace PepperDash.Essentials.Core // 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.Key == destinationPort.Key && t.SourcePort.ParentDevice.Key == source.Key); + 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.Key == sourcePort.Key); + 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.Key == destinationPort.Key && t.SourcePort.Key == sourcePort.Key); + 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 @@ -262,6 +293,12 @@ namespace PepperDash.Essentials.Core if (upstreamRoutingSuccess) { Debug.LogMessage(LogEventLevel.Verbose, "Upstream device route found", destination); + Debug.LogMessage(LogEventLevel.Verbose, "Route found on {0}", destination, midpointDevice.Key); + Debug.LogMessage(LogEventLevel.Verbose, +@"TieLine:\n +SourcePort: {SourcePort}\n +DestinationPort: {DestinationPort}\n" +, destination, tieLine.SourcePort, tieLine.DestinationPort); goodInputPort = tieLine.DestinationPort; break; // Stop looping the inputs in this cycle } 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; } } From 71005940ac84335def890058fe04b29cd63dbfc8 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 21 Jun 2024 15:00:17 -0600 Subject: [PATCH 45/48] fix: catches last condition for destinationPort match --- src/PepperDash.Essentials.Core/Routing/Extensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PepperDash.Essentials.Core/Routing/Extensions.cs b/src/PepperDash.Essentials.Core/Routing/Extensions.cs index fa685c7b..435b4130 100644 --- a/src/PepperDash.Essentials.Core/Routing/Extensions.cs +++ b/src/PepperDash.Essentials.Core/Routing/Extensions.cs @@ -229,7 +229,7 @@ route.OutputPort); } else { - destinationTieLines = TieLineCollection.Default.Where(t => t.DestinationPort.ParentDevice.Key == destination.Key && (t.Type == signalType || t.Type.HasFlag(eRoutingSignalType.AudioVideo))); + 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 From 0aafe8a62e5a2a85e3e69192a6d6b3f07b809c33 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 24 Jun 2024 13:45:07 -0600 Subject: [PATCH 46/48] fix: add message to indicate no handler registered when debugging stream data --- .../Comm and IR/ComPortController.cs | 4 ++++ 1 file changed, 4 insertions(+) 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() From c50726f813205d7cd395c55bbb3dfa0b762ae435 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 24 Jun 2024 14:54:37 -0500 Subject: [PATCH 47/48] feat: separate audio & video route descriptors Also cleaned up logging some --- .../Routing/Extensions.cs | 92 +++++++++---------- 1 file changed, 44 insertions(+), 48 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Routing/Extensions.cs b/src/PepperDash.Essentials.Core/Routing/Extensions.cs index 435b4130..a0eba868 100644 --- a/src/PepperDash.Essentials.Core/Routing/Extensions.cs +++ b/src/PepperDash.Essentials.Core/Routing/Extensions.cs @@ -31,10 +31,10 @@ namespace PepperDash.Essentials.Core 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"); + 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 { @@ -91,16 +91,22 @@ namespace PepperDash.Essentials.Core if (request.Source == null) return; - var newRoute = request.Destination.GetRouteToSource(request.Source, request.SignalType, request.DestinationPort, request.SourcePort); + var (audioOrSingleRoute, videoRoute) = request.Destination.GetRouteToSource(request.Source, request.SignalType, request.DestinationPort, request.SourcePort); - if (newRoute == null) + 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(); } /// @@ -135,64 +141,58 @@ namespace PepperDash.Essentials.Core /// 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 IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort, RoutingOutputPort sourcePort) + public static (RouteDescriptor, RouteDescriptor) GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort, RoutingOutputPort sourcePort) { - 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); + 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 (!destination.GetRouteToSource(source, null, null, signalType, 0, routeDescriptor, destinationPort, sourcePort)) - routeDescriptor = null; + if (!destination.GetRouteToSource(source, null, null, signalType, 0, singleTypeRouteDescriptor, destinationPort, sourcePort)) + singleTypeRouteDescriptor = null; - foreach (var route in routeDescriptor.Routes) + foreach (var route in singleTypeRouteDescriptor.Routes) { - Debug.LogMessage(LogEventLevel.Verbose, - @"Route for device: {route} -InputPort: {InputPort} -OutputPort: {OutputPort}", - destination, - route.SwitchingDevice.Key, - route.InputPort, - route.OutputPort); + Debug.LogMessage(LogEventLevel.Verbose, "Route for device: {route}", destination, route.ToString()); } - return routeDescriptor; + return (singleTypeRouteDescriptor, null); } // 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); + Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {sourceKey} of type {type}", destination, source.Key); - var audioSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Audio, 0, routeDescriptor, destinationPort, sourcePort); + var audioRouteDescriptor = new RouteDescriptor(source, destination, eRoutingSignalType.Audio); + + var audioSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Audio, 0, audioRouteDescriptor, destinationPort, sourcePort); 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, destinationPort, sourcePort); + var videoRouteDescriptor = new RouteDescriptor(source, destination, eRoutingSignalType.Video); + + var videoSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Video, 0, videoRouteDescriptor, destinationPort, sourcePort); if (!videoSuccess) Debug.LogMessage(LogEventLevel.Debug, "Cannot find video route to {0}", destination, source.Key); - foreach (var route in routeDescriptor.Routes) + foreach (var route in audioRouteDescriptor.Routes) { - Debug.LogMessage(LogEventLevel.Verbose, -@"Route for device: {route} -InputPort: {InputPort} -OutputPort: {OutputPort}", -destination, -route.SwitchingDevice.Key, -route.InputPort, -route.OutputPort); + Debug.LogMessage(LogEventLevel.Verbose, "Audio route for device: {route}", destination, route.ToString()); + } + + foreach (var route in videoRouteDescriptor.Routes) + { + Debug.LogMessage(LogEventLevel.Verbose, "Video route for device: {route}", destination, route.ToString()); } if (!audioSuccess && !videoSuccess) - routeDescriptor = null; + return (null, null); - return routeDescriptor; + return (audioRouteDescriptor, videoRouteDescriptor); } /// @@ -214,7 +214,7 @@ route.OutputPort); { cycle++; - Debug.LogMessage(LogEventLevel.Verbose, "GetRouteToSource: {0} {1}--> {2}", null, cycle, source.Key, destination.Key); + 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; @@ -259,7 +259,7 @@ route.OutputPort); } else // no direct-connect. Walk back devices. { - Debug.LogMessage(LogEventLevel.Verbose, "is not directly connected to {0}. Walking down tie lines", destination, source.Key); + 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 @@ -277,13 +277,13 @@ route.OutputPort); // 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, midpointDevice.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 {0}", destination, midpointDevice.Key); + 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 @@ -293,12 +293,8 @@ route.OutputPort); if (upstreamRoutingSuccess) { Debug.LogMessage(LogEventLevel.Verbose, "Upstream device route found", destination); - Debug.LogMessage(LogEventLevel.Verbose, "Route found on {0}", destination, midpointDevice.Key); - Debug.LogMessage(LogEventLevel.Verbose, -@"TieLine:\n -SourcePort: {SourcePort}\n -DestinationPort: {DestinationPort}\n" -, destination, tieLine.SourcePort, tieLine.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 } From ba4ca2093650e15f5ef6d68a2e54f20e734bca69 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 24 Jun 2024 14:57:07 -0500 Subject: [PATCH 48/48] fix: add tieline type to output for console & CWS --- .../Routing/TieLine.cs | 161 +++++++++--------- .../GetTieLinesRequestHandler.cs | 11 +- 2 files changed, 82 insertions(+), 90 deletions(-) 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/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;