From 90251d92df93db0ab0c75a8dec35fc42d57bf38a Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 26 Aug 2024 12:47:31 -0600 Subject: [PATCH 01/10] fix: adds condition to handle legacy and current portal URL structures and adds null check for getting list types in basic config helper methods --- .../Config/BasicConfig.cs | 8 ++--- .../Config/Essentials/EssentialsConfig.cs | 30 ++++++++++++++----- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Config/BasicConfig.cs b/src/PepperDash.Essentials.Core/Config/BasicConfig.cs index 59ea9bae..0e3e1e35 100644 --- a/src/PepperDash.Essentials.Core/Config/BasicConfig.cs +++ b/src/PepperDash.Essentials.Core/Config/BasicConfig.cs @@ -55,7 +55,7 @@ namespace PepperDash.Essentials.Core.Config /// public Dictionary GetSourceListForKey(string key) { - if (string.IsNullOrEmpty(key) || !SourceLists.ContainsKey(key)) + if (SourceLists == null || string.IsNullOrEmpty(key) || !SourceLists.ContainsKey(key)) return null; return SourceLists[key]; @@ -68,7 +68,7 @@ namespace PepperDash.Essentials.Core.Config /// DestinationList if the key exists, null otherwise public Dictionary GetDestinationListForKey(string key) { - if (string.IsNullOrEmpty(key) || !DestinationLists.ContainsKey(key)) + if (DestinationLists == null || string.IsNullOrEmpty(key) || !DestinationLists.ContainsKey(key)) { return null; } @@ -83,7 +83,7 @@ namespace PepperDash.Essentials.Core.Config /// AudioControlPointList if the key exists, null otherwise public AudioControlPointListItem GetAudioControlPointListForKey(string key) { - if (string.IsNullOrEmpty(key) || !AudioControlPointLists.ContainsKey(key)) + if (AudioControlPointLists == null || string.IsNullOrEmpty(key) || !AudioControlPointLists.ContainsKey(key)) return null; return AudioControlPointLists[key]; @@ -94,7 +94,7 @@ namespace PepperDash.Essentials.Core.Config /// public Dictionary GetCameraListForKey(string key) { - if (string.IsNullOrEmpty(key) || !CameraLists.ContainsKey(key)) + if (CameraLists == null || string.IsNullOrEmpty(key) || !CameraLists.ContainsKey(key)) return null; return CameraLists[key]; diff --git a/src/PepperDash.Essentials.Core/Config/Essentials/EssentialsConfig.cs b/src/PepperDash.Essentials.Core/Config/Essentials/EssentialsConfig.cs index dac5a35c..b42ec94c 100644 --- a/src/PepperDash.Essentials.Core/Config/Essentials/EssentialsConfig.cs +++ b/src/PepperDash.Essentials.Core/Config/Essentials/EssentialsConfig.cs @@ -31,9 +31,17 @@ namespace PepperDash.Essentials.Core.Config if (string.IsNullOrEmpty(SystemUrl)) return "missing url"; - var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/#.*"); - string uuid = result.Groups[1].Value; - return uuid; + if (SystemUrl.Contains("#")) + { + var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/#.*"); + string uuid = result.Groups[1].Value; + return uuid; + } else + { + var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/.*"); + string uuid = result.Groups[1].Value; + return uuid; + } } } @@ -44,10 +52,18 @@ namespace PepperDash.Essentials.Core.Config { if (string.IsNullOrEmpty(TemplateUrl)) return "missing template url"; - - var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/templates\/(.*)\/#.*"); - string uuid = result.Groups[1].Value; - return uuid; + + if (TemplateUrl.Contains("#")) + { + var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/templates\/(.*)\/#.*"); + string uuid = result.Groups[1].Value; + return uuid; + } else + { + var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/system-templates\/(.*)\/system-template-versions\/(.*)\/.*"); + string uuid = result.Groups[2].Value; + return uuid; + } } } From aa503f3b298ecb7210de0f7fac12905f790183d3 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 28 Aug 2024 13:16:27 -0600 Subject: [PATCH 02/10] feat: Allows for the ItemKey to be left undefined or empty and the ParentDeviceKey to be used on it's own instead. --- .../Devices/AudioControlListItemBase.cs | 6 ++++++ .../Devices/LevelControlListItem.cs | 14 ++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Devices/AudioControlListItemBase.cs b/src/PepperDash.Essentials.Core/Devices/AudioControlListItemBase.cs index 920c2d14..295fd25c 100644 --- a/src/PepperDash.Essentials.Core/Devices/AudioControlListItemBase.cs +++ b/src/PepperDash.Essentials.Core/Devices/AudioControlListItemBase.cs @@ -9,9 +9,15 @@ namespace PepperDash.Essentials.Core { public abstract class AudioControlListItemBase { + /// + /// Key of the parent device in the DeviceManager + /// [JsonProperty("parentDeviceKey")] public string ParentDeviceKey { get; set; } + /// + /// Optional key of the item in the parent device + /// [JsonProperty("itemKey")] public string ItemKey { get; set; } diff --git a/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs index 18da1130..4c2e83e4 100644 --- a/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs +++ b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs @@ -51,8 +51,18 @@ 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}"; + public string DeviceKey + { + get + { + if(string.IsNullOrEmpty(ItemKey)) return ParentDeviceKey; + else + { + return 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 d0dbe986f3ac447560d85fefbfea75c1bb0f8129 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 13 Sep 2024 13:17:51 -0600 Subject: [PATCH 03/10] feat: Adds ITemperatureSensor and IHumiditySensor interfaces --- .../DeviceTypeInterfaces/IHumiditySensor.cs | 18 +++++++++++++++ .../ITemperatureSensor.cs | 22 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHumiditySensor.cs create mode 100644 src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ITemperatureSensor.cs diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHumiditySensor.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHumiditySensor.cs new file mode 100644 index 00000000..8e9a369b --- /dev/null +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHumiditySensor.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +{ + public interface IHumiditySensor + { + /// + /// Reports the relative humidity level. Level ranging from 0 to 100 (for 0% to 100% + /// RH). EventIds: HumidityFeedbackFeedbackEventId will trigger to indicate change. + /// + IntFeedback HumidityFeedback { get; } + + } +} diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ITemperatureSensor.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ITemperatureSensor.cs new file mode 100644 index 00000000..fe1c560c --- /dev/null +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ITemperatureSensor.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +{ + public interface ITemperatureSensor + { + /// + /// The values will range from -400 to +1760 (for -40° to +176° F) or -400 to +800 + /// (for -40° to +80° C)in tenths of a degree. + /// + IntFeedback TemperatureFeedback { get; } + + + BoolFeedback TemperatureInCFeedback { get; } + + void SetTemperatureFormat(bool setToC); + } +} From 82ebf459210901a7f4c6968d0355a0b56b65798f Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 26 Sep 2024 08:44:27 -0500 Subject: [PATCH 04/10] fix: use correct class for generic sink factory --- .../Generic/GenericSink.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/PepperDash.Essentials.Devices.Common/Generic/GenericSink.cs b/src/PepperDash.Essentials.Devices.Common/Generic/GenericSink.cs index 13878321..cc9bc1e2 100644 --- a/src/PepperDash.Essentials.Devices.Common/Generic/GenericSink.cs +++ b/src/PepperDash.Essentials.Devices.Common/Generic/GenericSink.cs @@ -4,9 +4,6 @@ using PepperDash.Essentials.Core.Config; using Serilog.Events; using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace PepperDash.Essentials.Devices.Common.Generic { @@ -16,10 +13,9 @@ namespace PepperDash.Essentials.Devices.Common.Generic { InputPorts = new RoutingPortCollection(); - var inputPort = new RoutingInputPort($"{Key}-{RoutingPortNames.AnyVideoIn}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this); + var inputPort = new RoutingInputPort(RoutingPortNames.AnyVideoIn, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this); InputPorts.Add(inputPort); - } public RoutingPortCollection InputPorts { get; private set; } @@ -57,8 +53,8 @@ namespace PepperDash.Essentials.Devices.Common.Generic public override EssentialsDevice BuildDevice(DeviceConfig dc) { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Source Device"); - return new GenericSource(dc.Key, dc.Name); + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Sink Device"); + return new GenericSink(dc.Key, dc.Name); } } } From 0a7da79356f057b97da805442ffecc63cd540976 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 26 Sep 2024 15:03:31 -0600 Subject: [PATCH 05/10] fix: Allows both BytesReceived and TextReceived to both fire on the ComPortController --- .../Comm and IR/ComPortController.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs b/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs index 59e8c768..41420b7c 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs @@ -93,6 +93,7 @@ namespace PepperDash.Essentials.Core void OnDataReceived(string s) { + var eventSubscribed = false; var bytesHandler = BytesReceived; if (bytesHandler != null) @@ -101,7 +102,7 @@ namespace PepperDash.Essentials.Core if (StreamDebugging.RxStreamDebuggingIsEnabled) Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", ComTextHelper.GetEscapedText(bytes)); bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); - return; + eventSubscribed = true; } var textHandler = TextReceived; if (textHandler != null) @@ -109,10 +110,10 @@ namespace PepperDash.Essentials.Core if (StreamDebugging.RxStreamDebuggingIsEnabled) Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", s); textHandler(this, new GenericCommMethodReceiveTextArgs(s)); - return; + eventSubscribed = true; } - Debug.LogMessage(LogEventLevel.Warning, this, "Received data but no handler is registered"); + if(!eventSubscribed) Debug.LogMessage(LogEventLevel.Warning, this, "Received data but no handler is registered"); } public override bool Deactivate() From fa38e8a9a8862c1e8c3ffb5fe7497a6758812af8 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 4 Oct 2024 10:33:09 -0600 Subject: [PATCH 06/10] feat: Adds mechanism to track initialization status of EssentialsDevice as well as an event on DeviceManager to notify when all devices initialized. Room combiner now waits for all initialize before setting current scenario. --- .../Devices/DeviceManager.cs | 27 ++++++++++++++++++- .../Devices/EssentialsDevice.cs | 20 ++++++++++++++ .../Room/Combining/EssentialsRoomCombiner.cs | 10 ++++++- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Devices/DeviceManager.cs b/src/PepperDash.Essentials.Core/Devices/DeviceManager.cs index 0552faeb..ae8eba03 100644 --- a/src/PepperDash.Essentials.Core/Devices/DeviceManager.cs +++ b/src/PepperDash.Essentials.Core/Devices/DeviceManager.cs @@ -14,6 +14,7 @@ namespace PepperDash.Essentials.Core { public static event EventHandler AllDevicesActivated; public static event EventHandler AllDevicesRegistered; + public static event EventHandler AllDevicesInitialized; private static readonly CCriticalSection DeviceCriticalSection = new CCriticalSection(); private static readonly CEvent AllowAddDevicesCEvent = new CEvent(false, true); @@ -67,7 +68,7 @@ namespace PepperDash.Essentials.Core foreach (var d in Devices.Values) { try - { + { if (d is Device) (d as Device).PreActivate(); } @@ -123,6 +124,18 @@ namespace PepperDash.Essentials.Core } } + private static void DeviceManager_Initialized(object sender, EventArgs e) + { + var allInitialized = Devices.Values.OfType().All(d => d.IsInitialized); + + if (allInitialized) + { + Debug.LogMessage(LogEventLevel.Information, "****All Devices Initalized****"); + + OnAllDevicesInitialized(); + } + } + private static void OnAllDevicesActivated() { var handler = AllDevicesActivated; @@ -141,6 +154,15 @@ namespace PepperDash.Essentials.Core } } + private static void OnAllDevicesInitialized() + { + var handler = AllDevicesInitialized; + if (handler != null) + { + handler(null, new EventArgs()); + } + } + /// /// Calls activate on all Device class items /// @@ -264,6 +286,9 @@ namespace PepperDash.Essentials.Core Devices.Add(newDev.Key, newDev); //if (!(_Devices.Contains(newDev))) // _Devices.Add(newDev); + + if (newDev is EssentialsDevice essentialsDev) + essentialsDev.Initialized += DeviceManager_Initialized; } finally { diff --git a/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs b/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs index 8b0fc9fe..bdb8b45a 100644 --- a/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs +++ b/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs @@ -17,6 +17,24 @@ namespace PepperDash.Essentials.Core [Description("The base Essentials Device Class")] public abstract class EssentialsDevice : Device { + public event EventHandler Initialized; + + private bool _isInitialized; + public bool IsInitialized { + get { return _isInitialized; } + private set + { + if (_isInitialized == value) return; + + _isInitialized = value; + + if (_isInitialized) + { + Initialized?.Invoke(this, new EventArgs()); + } + } + } + protected EssentialsDevice(string key) : base(key) { @@ -41,6 +59,8 @@ namespace PepperDash.Essentials.Core try { Initialize(); + + IsInitialized = true; } catch (Exception ex) { diff --git a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs index 11086821..f0fb5e98 100644 --- a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs +++ b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs @@ -84,7 +84,15 @@ namespace PepperDash.Essentials.Core SetupPartitionStateProviders(); SetRooms(); + }); + + // Subscribe to the AllDevicesInitialized event + // We need to wait until all devices are initialized in case + // any actions are dependent on 3rd party devices already being + // connected and initialized + DeviceManager.AllDevicesInitialized += (o, a) => + { if (IsInAutoMode) { DetermineRoomCombinationScenario(); @@ -93,7 +101,7 @@ namespace PepperDash.Essentials.Core { SetRoomCombinationScenario(_propertiesConfig.defaultScenarioKey); } - }); + }; } private void CreateScenarios() From f04f70495f2f5efa222d1639420ecd48774373ab Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 18 Oct 2024 10:43:53 -0500 Subject: [PATCH 07/10] fix: check for nulls in route switch descriptors --- .../Routing/RouteSwitchDescriptor.cs | 4 ++-- .../Routing/RoutingFeedbackManager.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs b/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs index 080b932e..9e4aaca1 100644 --- a/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs +++ b/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs @@ -23,9 +23,9 @@ public override string ToString() { if (SwitchingDevice is IRouting) - return $"{SwitchingDevice?.Key} switches output {OutputPort.Key} to input {InputPort.Key}"; + return $"{SwitchingDevice?.Key} switches output {OutputPort?.Key} to input {InputPort?.Key}"; else - return $"{SwitchingDevice.Key} switches to input {InputPort.Key}"; + return $"{SwitchingDevice?.Key} switches to input {InputPort?.Key}"; } } diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs b/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs index 28fefa96..e8809191 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs @@ -217,7 +217,7 @@ namespace PepperDash.Essentials.Core.Routing var currentRoute = midpoint.CurrentRoutes.FirstOrDefault(route => { Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Checking {route} against {tieLine}", this, route, tieLine); - return route.OutputPort.Key == tieLine.SourcePort.Key && route.OutputPort.ParentDevice.Key == tieLine.SourcePort.ParentDevice.Key; + return route.OutputPort?.Key == tieLine.SourcePort.Key && route.OutputPort?.ParentDevice.Key == tieLine.SourcePort.ParentDevice.Key; }); if (currentRoute == null) From 631dd2b00dc89f03964747b88177b1dda0549e5c Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 18 Oct 2024 11:09:15 -0500 Subject: [PATCH 08/10] fix: check for nulls in SwitchingDevice property --- .../Routing/RouteSwitchDescriptor.cs | 6 +++--- .../Routing/RoutingFeedbackManager.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs b/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs index 9e4aaca1..c425d0a4 100644 --- a/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs +++ b/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs @@ -5,7 +5,7 @@ /// public class RouteSwitchDescriptor { - public IRoutingInputs SwitchingDevice { get { return InputPort.ParentDevice; } } + public IRoutingInputs SwitchingDevice { get { return InputPort?.ParentDevice; } } public RoutingOutputPort OutputPort { get; set; } public RoutingInputPort InputPort { get; set; } @@ -23,9 +23,9 @@ public override string ToString() { if (SwitchingDevice is IRouting) - return $"{SwitchingDevice?.Key} switches output {OutputPort?.Key} to input {InputPort?.Key}"; + return $"{(SwitchingDevice != null ? SwitchingDevice.Key : "No Device")} switches output {(OutputPort != null ? OutputPort.Key : "No output port")} to input {(InputPort != null ? InputPort.Key : "No input port")}"; else - return $"{SwitchingDevice?.Key} switches to input {InputPort?.Key}"; + return $"{(SwitchingDevice != null ? SwitchingDevice.Key : "No Device")} switches to input {(InputPort != null ? InputPort.Key : "No input port")}"; } } diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs b/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs index e8809191..802088df 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs @@ -217,7 +217,7 @@ namespace PepperDash.Essentials.Core.Routing var currentRoute = midpoint.CurrentRoutes.FirstOrDefault(route => { Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Checking {route} against {tieLine}", this, route, tieLine); - return route.OutputPort?.Key == tieLine.SourcePort.Key && route.OutputPort?.ParentDevice.Key == tieLine.SourcePort.ParentDevice.Key; + return route.OutputPort != null && route.InputPort != null && route.OutputPort?.Key == tieLine.SourcePort.Key && route.OutputPort?.ParentDevice.Key == tieLine.SourcePort.ParentDevice.Key; }); if (currentRoute == null) From d11827bc7bd264cd905de4e0abb443503cdc2ca2 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 18 Oct 2024 15:04:08 -0500 Subject: [PATCH 09/10] fix: remove verbose logging for feedback manager --- .../Routing/RoutingFeedbackManager.cs | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs b/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs index 802088df..0af3bfa5 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs @@ -65,7 +65,7 @@ namespace PepperDash.Essentials.Core.Routing private void UpdateDestination(IRoutingSinkWithSwitching destination, RoutingInputPort inputPort) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Updating destination {destination} with inputPort {inputPort}", this,destination?.Key, inputPort?.Key); + // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Updating destination {destination} with inputPort {inputPort}", this,destination?.Key, inputPort?.Key); if(inputPort == null) { @@ -101,7 +101,7 @@ namespace PepperDash.Essentials.Core.Routing return; } - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Getting source for first TieLine {tieLine}", this, firstTieLine); + // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Getting source for first TieLine {tieLine}", this, firstTieLine); TieLine sourceTieLine; try @@ -128,7 +128,7 @@ namespace PepperDash.Essentials.Core.Routing return; } - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root TieLine {tieLine}", this, sourceTieLine); + // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root TieLine {tieLine}", this, sourceTieLine); // Does not handle combinable scenarios or other scenarios where a display might be part of multiple rooms yet. var room = DeviceManager.AllDevices.OfType().FirstOrDefault((r) => { @@ -151,7 +151,7 @@ namespace PepperDash.Essentials.Core.Routing return; } - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found room {room} for destination {destination}", this, room.Key, destination.Key); + // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found room {room} for destination {destination}", this, room.Key, destination.Key); var sourceList = ConfigReader.ConfigObject.GetSourceListForKey(room.SourceListKey); @@ -161,15 +161,15 @@ namespace PepperDash.Essentials.Core.Routing return; } - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found sourceList for room {room}", this, room.Key); + // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found sourceList for room {room}", this, room.Key); var sourceListItem = sourceList.FirstOrDefault(sli => { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, - "SourceListItem {sourceListItem}:{sourceKey} tieLine sourceport device key {sourcePortDeviceKey}", - this, - sli.Key, - sli.Value.SourceKey, - sourceTieLine.SourcePort.ParentDevice.Key); + //// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, + // "SourceListItem {sourceListItem}:{sourceKey} tieLine sourceport device key {sourcePortDeviceKey}", + // this, + // sli.Key, + // sli.Value.SourceKey, + // sourceTieLine.SourcePort.ParentDevice.Key); return sli.Value.SourceKey.Equals(sourceTieLine.SourcePort.ParentDevice.Key,StringComparison.InvariantCultureIgnoreCase); }); @@ -191,7 +191,7 @@ namespace PepperDash.Essentials.Core.Routing return; } - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Got Source {source}", this, source); + // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Got Source {source}", this, source); destination.CurrentSourceInfo = source; destination.CurrentSourceInfoKey = source.SourceKey; @@ -202,11 +202,11 @@ namespace PepperDash.Essentials.Core.Routing TieLine nextTieLine = null; try { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "**Following tieLine {tieLine}**", this, tieLine); + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "**Following tieLine {tieLine}**", this, tieLine); if (tieLine.SourcePort.ParentDevice is IRoutingWithFeedback midpoint) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLine Source device {sourceDevice} is midpoint", this, midpoint); + // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLine Source device {sourceDevice} is midpoint", this, midpoint); if(midpoint.CurrentRoutes == null || midpoint.CurrentRoutes.Count == 0) { @@ -215,7 +215,7 @@ namespace PepperDash.Essentials.Core.Routing } var currentRoute = midpoint.CurrentRoutes.FirstOrDefault(route => { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Checking {route} against {tieLine}", this, route, tieLine); + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Checking {route} against {tieLine}", this, route, tieLine); return route.OutputPort != null && route.InputPort != null && route.OutputPort?.Key == tieLine.SourcePort.Key && route.OutputPort?.ParentDevice.Key == tieLine.SourcePort.ParentDevice.Key; }); @@ -226,28 +226,28 @@ namespace PepperDash.Essentials.Core.Routing return null; } - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found currentRoute {currentRoute} through {midpoint}", this, currentRoute, midpoint); + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found currentRoute {currentRoute} through {midpoint}", this, currentRoute, midpoint); nextTieLine = TieLineCollection.Default.FirstOrDefault(tl => { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Checking {route} against {tieLine}", tl.DestinationPort.Key, currentRoute.InputPort.Key); + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Checking {route} against {tieLine}", tl.DestinationPort.Key, currentRoute.InputPort.Key); return tl.DestinationPort.Key == currentRoute.InputPort.Key && tl.DestinationPort.ParentDevice.Key == currentRoute.InputPort.ParentDevice.Key; }); if (nextTieLine != null) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found next tieLine {tieLine}. Walking the chain", this, nextTieLine); + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found next tieLine {tieLine}. Walking the chain", this, nextTieLine); return GetRootTieLine(nextTieLine); } - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root tieLine {tieLine}", this,nextTieLine); + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root tieLine {tieLine}", this,nextTieLine); return nextTieLine; } - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLIne Source Device {sourceDeviceKey} is IRoutingSource: {isIRoutingSource}", this, tieLine.SourcePort.ParentDevice.Key, tieLine.SourcePort.ParentDevice is IRoutingSource); - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLine Source Device interfaces: {typeFullName}:{interfaces}", this, tieLine.SourcePort.ParentDevice.GetType().FullName, tieLine.SourcePort.ParentDevice.GetType().GetInterfaces().Select(i => i.Name)); + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLIne Source Device {sourceDeviceKey} is IRoutingSource: {isIRoutingSource}", this, tieLine.SourcePort.ParentDevice.Key, tieLine.SourcePort.ParentDevice is IRoutingSource); + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLine Source Device interfaces: {typeFullName}:{interfaces}", this, tieLine.SourcePort.ParentDevice.GetType().FullName, tieLine.SourcePort.ParentDevice.GetType().GetInterfaces().Select(i => i.Name)); if (tieLine.SourcePort.ParentDevice is IRoutingSource || tieLine.SourcePort.ParentDevice is IRoutingOutputs) //end of the chain { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root: {tieLine}", this, tieLine); + // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root: {tieLine}", this, tieLine); return tieLine; } From 0e16dff90c89a7b0b0c3f82bf0c81c29ffeb535b Mon Sep 17 00:00:00 2001 From: Nick Genovese Date: Thu, 24 Oct 2024 20:52:24 -0400 Subject: [PATCH 10/10] fix: checks the routing output port for null --- .../Routing/RouteDescriptor.cs | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Routing/RouteDescriptor.cs b/src/PepperDash.Essentials.Core/Routing/RouteDescriptor.cs index fa486c07..ee8b69ac 100644 --- a/src/PepperDash.Essentials.Core/Routing/RouteDescriptor.cs +++ b/src/PepperDash.Essentials.Core/Routing/RouteDescriptor.cs @@ -68,19 +68,29 @@ namespace PepperDash.Essentials.Core /// public void ReleaseRoutes() { - foreach (var route in Routes.Where(r => r.SwitchingDevice is IRouting)) - { - if (route.SwitchingDevice is IRouting switchingDevice) - { + foreach (var route in Routes.Where(r => r.SwitchingDevice is IRouting)) + { + if (route.SwitchingDevice is IRouting switchingDevice) + { + if (route.OutputPort == null) + { + continue; + } + switchingDevice.ExecuteSwitch(null, route.OutputPort.Selector, SignalType); - // Pull the route from the port. Whatever is watching the output's in use tracker is - // responsible for responding appropriately. - route.OutputPort.InUseTracker.RemoveUser(Destination, "destination-" + SignalType); - Debug.LogMessage(LogEventLevel.Verbose, "Port {0} releasing. Count={1}",null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue); - } - } - } + if (route.OutputPort.InUseTracker != null) + { + route.OutputPort.InUseTracker.RemoveUser(Destination, "destination-" + SignalType); + Debug.LogMessage(LogEventLevel.Verbose, "Port {0} releasing. Count={1}", null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue); + } + else + { + Debug.LogMessage(LogEventLevel.Error, "InUseTracker is null for OutputPort {0}", null, route.OutputPort.Key); + } + } + } + } public override string ToString() {