mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-15 20:54:55 +00:00
feat: add RoutingFeedbackManager
RoutingFeedbackManager keeps track of updates from IRoutingSinkWotjFeedbacl devoces & IRoutingWithFeedback devices to allow for walking tieLines and finding a source.
This commit is contained in:
@@ -5,6 +5,7 @@ using System.Collections;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
using Crestron.SimplSharp.Reflection;
|
using Crestron.SimplSharp.Reflection;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
@@ -82,7 +83,8 @@ namespace PepperDash.Essentials.Core
|
|||||||
var convertedParams = mParams
|
var convertedParams = mParams
|
||||||
.Select((p, i) => ConvertType(action.Params[i], p.ParameterType))
|
.Select((p, i) => ConvertType(action.Params[i], p.ParameterType))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
method.Invoke(obj, convertedParams);
|
|
||||||
|
Task.Run(() => method.Invoke(obj, convertedParams));
|
||||||
|
|
||||||
CrestronConsole.ConsoleCommandResponse("Method {0} successfully called on device {1}", method.Name,
|
CrestronConsole.ConsoleCommandResponse("Method {0} successfully called on device {1}", method.Name,
|
||||||
action.DeviceKey);
|
action.DeviceKey);
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ namespace PepperDash.Essentials.Core.Devices
|
|||||||
{
|
{
|
||||||
public LaptopFactory()
|
public LaptopFactory()
|
||||||
{
|
{
|
||||||
TypeNames = new List<string>() { "laptop" };
|
TypeNames = new List<string>() { "deprecated" };
|
||||||
}
|
}
|
||||||
|
|
||||||
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
||||||
|
|||||||
@@ -161,7 +161,10 @@ namespace PepperDash.Essentials.Core
|
|||||||
Icon = "Blank";
|
Icon = "Blank";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{SourceKey}:{Name}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SourceRouteListItem
|
public class SourceRouteListItem
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using PepperDash.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core.Routing
|
namespace PepperDash.Essentials.Core.Routing
|
||||||
{
|
{
|
||||||
public class DummyRoutingInputsDevice : Device, IRoutingSource
|
public class DummyRoutingInputsDevice : Device, IRoutingSource, IRoutingOutputs
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A single output port, backplane, audioVideo
|
/// A single output port, backplane, audioVideo
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines an IRoutingOutputs devices as being a source - the start of the chain
|
/// Defines an IRoutingOutputs devices as being a source - the start of the chain
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IRoutingSource : IRoutingOutputs
|
public interface IRoutingSource
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core.Routing
|
namespace PepperDash.Essentials.Core.Routing
|
||||||
{
|
{
|
||||||
@@ -47,9 +48,16 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void HandleSinkUpdate(IRoutingSinkWithSwitching sender, RoutingInputPort currentInputPort)
|
private void HandleSinkUpdate(IRoutingSinkWithSwitching sender, RoutingInputPort currentInputPort)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
UpdateDestination(sender, currentInputPort);
|
UpdateDestination(sender, currentInputPort);
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(ex, "Error handling Sink update from {senderKey}:{Exception}", this, sender.Key, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateDestination(IRoutingSinkWithSwitching destination, RoutingInputPort inputPort)
|
private void UpdateDestination(IRoutingSinkWithSwitching destination, RoutingInputPort inputPort)
|
||||||
{
|
{
|
||||||
@@ -66,6 +74,8 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Getting source for first TieLine {tieLine}", this, firstTieLine);
|
||||||
|
|
||||||
var sourceTieLine = GetRootTieLine(firstTieLine);
|
var sourceTieLine = GetRootTieLine(firstTieLine);
|
||||||
|
|
||||||
if (sourceTieLine == null)
|
if (sourceTieLine == null)
|
||||||
@@ -76,6 +86,7 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
destination.CurrentSourceInfoKey = string.Empty;
|
destination.CurrentSourceInfoKey = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.
|
// Does not handle combinable scenarios or other scenarios where a display might be part of multiple rooms yet.
|
||||||
var room = DeviceManager.AllDevices.OfType<IEssentialsRoom>().FirstOrDefault((r) => {
|
var room = DeviceManager.AllDevices.OfType<IEssentialsRoom>().FirstOrDefault((r) => {
|
||||||
@@ -98,6 +109,8 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found room {room} for destination {destination}", this, room.Key, destination.Key);
|
||||||
|
|
||||||
var sourceList = ConfigReader.ConfigObject.GetSourceListForKey(room.SourceListKey);
|
var sourceList = ConfigReader.ConfigObject.GetSourceListForKey(room.SourceListKey);
|
||||||
|
|
||||||
if (sourceList == null)
|
if (sourceList == null)
|
||||||
@@ -106,7 +119,18 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sourceListItem = sourceList.FirstOrDefault(sli => sli.Value.SourceKey == sourceTieLine.SourcePort.ParentDevice.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);
|
||||||
|
|
||||||
|
return sli.Value.SourceKey.Equals(sourceTieLine.SourcePort.ParentDevice.Key,StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
});
|
||||||
|
|
||||||
var source = sourceListItem.Value;
|
var source = sourceListItem.Value;
|
||||||
|
|
||||||
@@ -119,6 +143,8 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Got Source {source}", this, source);
|
||||||
|
|
||||||
destination.CurrentSourceInfo = source;
|
destination.CurrentSourceInfo = source;
|
||||||
destination.CurrentSourceInfoKey = source.SourceKey;
|
destination.CurrentSourceInfoKey = source.SourceKey;
|
||||||
}
|
}
|
||||||
@@ -129,6 +155,8 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
|
|
||||||
if(tieLine.SourcePort.ParentDevice is IRoutingWithFeedback midpoint)
|
if(tieLine.SourcePort.ParentDevice is IRoutingWithFeedback midpoint)
|
||||||
{
|
{
|
||||||
|
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLine Source device is midpoint", this);
|
||||||
|
|
||||||
var currentRoute = midpoint.CurrentRoutes.FirstOrDefault(route => route.OutputPort.Key == tieLine.SourcePort.Key);
|
var currentRoute = midpoint.CurrentRoutes.FirstOrDefault(route => route.OutputPort.Key == tieLine.SourcePort.Key);
|
||||||
|
|
||||||
if(currentRoute == null)
|
if(currentRoute == null)
|
||||||
@@ -147,8 +175,12 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
return tieLine;
|
return tieLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tieLine.SourcePort.ParentDevice is IRoutingSource) //end of the chain
|
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);
|
||||||
return tieLine;
|
return tieLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +191,7 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
return GetRootTieLine(nextTieLine);
|
return GetRootTieLine(nextTieLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nextTieLine;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace PepperDash.Essentials.Devices.Common.Displays
|
|||||||
return _currentInputPort;
|
return _currentInputPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
private set
|
protected set
|
||||||
{
|
{
|
||||||
_currentInputPort = value;
|
_currentInputPort = value;
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Crestron.SimplSharpPro.DeviceSupport;
|
|||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using PepperDash.Essentials.Core.Bridges;
|
using PepperDash.Essentials.Core.Bridges;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||||
using PepperDash.Essentials.Core.Routing;
|
using PepperDash.Essentials.Core.Routing;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
@@ -139,7 +140,9 @@ namespace PepperDash.Essentials.Devices.Common.Displays
|
|||||||
|
|
||||||
public override void ExecuteSwitch(object selector)
|
public override void ExecuteSwitch(object selector)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "ExecuteSwitch: {0}", selector);
|
try
|
||||||
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Verbose, "ExecuteSwitch: {0}", this, selector);
|
||||||
|
|
||||||
if (!_PowerIsOn)
|
if (!_PowerIsOn)
|
||||||
{
|
{
|
||||||
@@ -149,7 +152,27 @@ namespace PepperDash.Essentials.Devices.Common.Displays
|
|||||||
if (!Inputs.Items.TryGetValue(selector.ToString(), out var input))
|
if (!Inputs.Items.TryGetValue(selector.ToString(), out var input))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Debug.LogMessage(LogEventLevel.Verbose, "Selected input: {input}", this, input.Key);
|
||||||
input.Select();
|
input.Select();
|
||||||
|
|
||||||
|
var inputPort = InputPorts.FirstOrDefault(port =>
|
||||||
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Verbose, "Checking input port {inputPort} with selector {portSelector} against {selector}", this, port, port.Selector, selector);
|
||||||
|
return port.Selector.ToString() == selector.ToString();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (inputPort == null)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Verbose, "Unable to find input port for selector {selector}", this, selector);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.LogMessage(LogEventLevel.Verbose, "Setting current input port to {inputPort}", this, inputPort);
|
||||||
|
CurrentInputPort = inputPort;
|
||||||
|
} catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(ex, "Error making switch: {Exception}", this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetInput(string selector)
|
public void SetInput(string selector)
|
||||||
@@ -251,4 +274,18 @@ namespace PepperDash.Essentials.Devices.Common.Displays
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class MockDisplay2Factory : EssentialsDeviceFactory<MockDisplay>
|
||||||
|
{
|
||||||
|
public MockDisplay2Factory()
|
||||||
|
{
|
||||||
|
TypeNames = new List<string>() { "mockdisplay2" };
|
||||||
|
}
|
||||||
|
|
||||||
|
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Mock Display Device");
|
||||||
|
return new MockDisplay(dc.Key, dc.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ using Serilog.Events;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common
|
namespace PepperDash.Essentials.Devices.Common
|
||||||
{
|
{
|
||||||
public class GenericSource : EssentialsDevice, IUiDisplayInfo, IRoutingSource, IUsageTracking
|
public class GenericSource : EssentialsDevice, IUiDisplayInfo, IRoutingSource, IRoutingOutputs, IUsageTracking
|
||||||
{
|
{
|
||||||
|
|
||||||
public uint DisplayUiType { get { return DisplayUiConstants.TypeNoControls; } }
|
public uint DisplayUiType { get { return DisplayUiConstants.TypeNoControls; } }
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ using Serilog.Events;
|
|||||||
namespace PepperDash.Essentials.Devices.Common
|
namespace PepperDash.Essentials.Devices.Common
|
||||||
{
|
{
|
||||||
[Description("Wrapper class for an IR Set Top Box")]
|
[Description("Wrapper class for an IR Set Top Box")]
|
||||||
public class IRSetTopBoxBase : EssentialsBridgeableDevice, ISetTopBoxControls, IRoutingSource, IUsageTracking, IHasPowerControl, ITvPresetsProvider
|
public class IRSetTopBoxBase : EssentialsBridgeableDevice, ISetTopBoxControls, IRoutingSource, IRoutingOutputs, IUsageTracking, IHasPowerControl, ITvPresetsProvider
|
||||||
{
|
{
|
||||||
public IrOutputPortController IrPort { get; private set; }
|
public IrOutputPortController IrPort { get; private set; }
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.SoftCodec
|
namespace PepperDash.Essentials.Devices.Common.SoftCodec
|
||||||
{
|
{
|
||||||
public class GenericSoftCodec : EssentialsDevice, IRoutingSource, IRoutingSinkWithSwitching
|
public class GenericSoftCodec : EssentialsDevice, IRoutingSource, IRoutingOutputs, IRoutingSinkWithSwitching
|
||||||
{
|
{
|
||||||
private RoutingInputPort _currentInputPort;
|
private RoutingInputPort _currentInputPort;
|
||||||
public RoutingInputPort CurrentInputPort {
|
public RoutingInputPort CurrentInputPort {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using Serilog.Events;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.Sources
|
namespace PepperDash.Essentials.Devices.Common.Sources
|
||||||
{
|
{
|
||||||
public class InRoomPc : EssentialsDevice, IHasFeedback, IRoutingSource, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking
|
public class InRoomPc : EssentialsDevice, IHasFeedback, IRoutingSource, IRoutingOutputs, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking
|
||||||
{
|
{
|
||||||
public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } }
|
public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } }
|
||||||
public string IconName { get; set; }
|
public string IconName { get; set; }
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using Serilog.Events;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.Sources
|
namespace PepperDash.Essentials.Devices.Common.Sources
|
||||||
{
|
{
|
||||||
public class Laptop : EssentialsDevice, IHasFeedback, IRoutingSource, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking
|
public class Laptop : EssentialsDevice, IHasFeedback, IRoutingSource, IRoutingOutputs, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking
|
||||||
{
|
{
|
||||||
public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } }
|
public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } }
|
||||||
public string IconName { get; set; }
|
public string IconName { get; set; }
|
||||||
@@ -29,11 +29,15 @@ namespace PepperDash.Essentials.Devices.Common.Sources
|
|||||||
: base(key, name)
|
: base(key, name)
|
||||||
{
|
{
|
||||||
IconName = "Laptop";
|
IconName = "Laptop";
|
||||||
|
|
||||||
HasPowerOnFeedback = new BoolFeedback("HasPowerFeedback",
|
HasPowerOnFeedback = new BoolFeedback("HasPowerFeedback",
|
||||||
() => this.GetVideoStatuses() != VideoStatusOutputs.NoStatus);
|
() => this.GetVideoStatuses() != VideoStatusOutputs.NoStatus);
|
||||||
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
|
|
||||||
OutputPorts.Add(AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
|
OutputPorts = new RoutingPortCollection<RoutingOutputPort>
|
||||||
eRoutingPortConnectionType.None, 0, this));
|
{
|
||||||
|
(AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
|
||||||
|
eRoutingPortConnectionType.None, 0, this))
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IHasFeedback Members
|
#region IHasFeedback Members
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ using Serilog.Events;
|
|||||||
namespace PepperDash.Essentials.Devices.Common
|
namespace PepperDash.Essentials.Devices.Common
|
||||||
{
|
{
|
||||||
[Description("Wrapper class for an IR-Controlled AppleTV")]
|
[Description("Wrapper class for an IR-Controlled AppleTV")]
|
||||||
public class AppleTV : EssentialsBridgeableDevice, IDPad, ITransport, IUiDisplayInfo, IRoutingSource
|
public class AppleTV : EssentialsBridgeableDevice, IDPad, ITransport, IUiDisplayInfo, IRoutingSource, IRoutingOutputs
|
||||||
|
|
||||||
{
|
{
|
||||||
public IrOutputPortController IrPort { get; private set; }
|
public IrOutputPortController IrPort { get; private set; }
|
||||||
public const string StandardDriverName = "Apple_AppleTV_4th_Gen_Essentials.ir";
|
public const string StandardDriverName = "Apple_AppleTV_4th_Gen_Essentials.ir";
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ using Serilog.Events;
|
|||||||
namespace PepperDash.Essentials.Devices.Common
|
namespace PepperDash.Essentials.Devices.Common
|
||||||
{
|
{
|
||||||
[Description("Wrapper class for an IR-Controlled Roku")]
|
[Description("Wrapper class for an IR-Controlled Roku")]
|
||||||
public class Roku2 : EssentialsDevice, IDPad, ITransport, IUiDisplayInfo, IRoutingSource
|
public class Roku2 : EssentialsDevice, IDPad, ITransport, IUiDisplayInfo, IRoutingSource, IRoutingOutputs
|
||||||
{
|
{
|
||||||
[Api]
|
[Api]
|
||||||
public IrOutputPortController IrPort { get; private set; }
|
public IrOutputPortController IrPort { get; private set; }
|
||||||
|
|||||||
Reference in New Issue
Block a user