Skip to content

Commit d2684f3

Browse files
authored
Merge pull request #1407 from PepperDash/update-routing-documentation
Update routing docs & tieline creation
2 parents 305a466 + 29d5804 commit d2684f3

3 files changed

Lines changed: 185 additions & 21 deletions

File tree

docs/docs/technical-docs/Connection-Based-Routing.md

Lines changed: 144 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,35 @@
22

33
## TL;DR
44

5-
Routing is defined by a connection graph or a wiring diagram. Routeable devices are sources, midpoints, or destinations. Devices are connected by tie lines. Tie lines represent the cables connecting devices, and are of type audio, video or both. Routes are made by telling a destination to get an audio/video/combined route from a source.
5+
Routing is defined by a connection graph or a wiring diagram. Routable devices are sources, midpoints, or destinations. Devices are connected by tie lines. Tie lines represent the cables connecting devices, and have specific signal types (audio, video, audioVideo, secondaryAudio, usbInput, usbOutput). Routes are made by telling a destination to get a route from a source for a specific signal type. Combined signal types (e.g., audioVideo) are automatically split into separate routing operations.
66

77
## Summary
88

99
Essentials routing is described by defining a graph of connections between devices in a system, typically in configuration. The audio, video and combination connections are like a wiring diagram. This graph is a collection of devices and tie lines, each tie line connecting a source device, source output port, destination device and destination input port. Tie lines are logically represented as a collection.
1010

11-
When routes are to be executed, Essentials will use this connection graph to decide on routes from source to destination. A method call is made on a destination, which says “destination, find a way for source xyz to get to you.” An algorithm analyzes the tie lines, instantly walking backwards from the destination, down every connection until it finds a complete path from the source. If a connected path is found, the algorithm then walks forward through all midpoints to the destination, executing switches as required until the full route is complete. The developer or configurer only needs to say “destination, get source xyz” and Essentials figures out how, regardless of what devices lie in between.
11+
When routes are to be executed, Essentials will use this connection graph to decide on routes from source to destination. A method call is made on a destination, which says "destination, find a way for source xyz to get to you." An algorithm analyzes the tie lines, instantly walking backwards from the destination, down every connection until it finds a complete path from the source. If a connected path is found, the algorithm then walks forward through all midpoints to the destination, executing switches as required until the full route is complete. The developer or configurer only needs to say "destination, get source xyz" and Essentials figures out how, regardless of what devices lie in between.
12+
13+
### Signal Type Handling
14+
15+
When a combined signal type like `audioVideo` is requested, Essentials automatically splits it into two separate routing operations—one for audio and one for video. Each signal type is routed independently through the system, ensuring that:
16+
- Audio-only tie lines can be used for the audio portion
17+
- Video-only tie lines can be used for the video portion
18+
- AudioVideo tie lines can be used for both portions
19+
20+
During path discovery, **only tie lines that support the requested signal type are considered**. For example, if a video route is requested, only tie lines with the video flag will be evaluated. This ensures signal compatibility throughout the entire routing chain.
21+
22+
### Port-Specific Routing
23+
24+
The routing system supports routing to and from specific ports on devices. You can specify:
25+
- A specific input port on the destination device
26+
- A specific output port on the source device
27+
- Both specific ports for precise routing control
28+
29+
When no specific ports are specified, the algorithm will automatically discover the appropriate ports based on available tie lines.
30+
31+
### Request Queuing
32+
33+
All routing requests are processed sequentially through a queue. For devices that implement warming/cooling behavior (e.g., projectors), route requests are automatically held when a device is cooling down and executed once the device is ready. This prevents routing errors and ensures proper device state management.
1234

1335
### Classes Referenced
1436

@@ -23,15 +45,15 @@ When routes are to be executed, Essentials will use this connection graph to dec
2345

2446
The diagram below shows the connections in a simple presentation system, with a few variations in connection paths. Example routes will be described following the diagram.
2547

26-
Each visible line between ports on devices represents a tie line. A tie line connects an output port on one device to an input port on another device, for example: an HDMI port on a document camera to an HDMI input on a matrix switcher. A tie line may be audio, video or both. It is essentially a logical representation of a physical cable in a system. This diagram has 12 tie lines, and those tie lines are defined in the tieLines array in configuration.
48+
Each visible line between ports on devices represents a tie line. A tie line connects an output port on one device to an input port on another device, for example: an HDMI port on a document camera to an HDMI input on a matrix switcher. A tie line has a signal type (audio, video, audioVideo, secondaryAudio, usbInput, or usbOutput) that determines what signals can travel through it. It is essentially a logical representation of a physical cable in a system. This diagram has 12 tie lines, and those tie lines are defined in the tieLines array in configuration.
2749

2850
![Routing system diagram](~/docs/images/routing-system-diagram.png)
2951

3052
Let’s go through some examples of routing, using pseudo-code:
3153

3254
1. Method call: “Projector 1, show Doc cam.” Routing will walk backwards through DM-RMC-3 and DM-8x8 iterating through all “wired up” ports until it finds a path back to the Doc cam. Routing will then step back through all devices in the discovered chain, switching routes on those that are switchable: Doc cam: no switching; DM 8x8: route input 3 to output 3; DM-RMC-3: no switching; Projector 1: Select input HDMI In. Route is complete.
33-
2. Method call: Projector 2, show Laptop, video-only. Routing will walk backwards through DM-RMC-4, DM 8x8, DM-TX-1, iterating through all connected ports until it finds a connection to the laptop. Routing then steps back through all devices, switching video where it can: Laptop: No switching; DM-TX-1: Select HDMI in; DM 8x8: Route input 5 to output 4; DM-RMC-4: No switching; Projector 2: Select HDMI input. Route is complete.
34-
3. Method call: Amplifier, connect Laptop audio. Again walking backwards to Laptop, as in #2 above. Switching will take place on DM-TX-1, DM 8x8, audio-only.
55+
2. Method call: "Projector 2, show Laptop, video-only." Routing will walk backwards through DM-RMC-4, DM 8x8, DM-TX-1, iterating through all connected ports until it finds a connection to the laptop. During this search, only tie lines that support video signals are considered. Routing then steps back through all devices, switching video where it can: Laptop: No switching; DM-TX-1: Select HDMI in; DM 8x8: Route input 5 to output 4; DM-RMC-4: No switching; Projector 2: Select HDMI input. Route is complete.
56+
3. Method call: "Amplifier, connect Laptop audio." Again walking backwards to Laptop, as in #2 above, but this time only tie lines supporting audio signals are evaluated. Switching will take place on DM-TX-1, DM 8x8, audio-only.
3557
4. Very simple call: “Lobby display, show signage controller.” Routing will walk back on HDMI input 1 and immediately find the signage controller. It then does a switch to HDMI 1 on the display.
3658

3759
All four of the above could be logically combined in a series of calls to define a possible “scene” in a room: Put Document camera on Projector 1, put Laptop on Projector 2 and the audio, put Signage on the Lobby display. They key takeaway is that the developer doesn’t need to define what is involved in making a certain route. The person configuring the system defines how it’s wired up, and the code only needs to tell a given destination to get a source, likely through configuration as well.
@@ -40,6 +62,37 @@ All of the above routes can be defined in source list routing tables, covered el
4062

4163
---
4264

65+
## Routing Algorithm Details
66+
67+
### Combined Signal Type Splitting
68+
69+
When an `audioVideo` route is requested, the routing system automatically splits it into two independent routing operations:
70+
71+
1. **Audio Route**: Finds the best path for audio signals from source to destination
72+
2. **Video Route**: Finds the best path for video signals from source to destination
73+
74+
Each route can take a different physical path through the system. For example:
75+
- Video might travel: Laptop → DM-TX-1 → DM Matrix → Display
76+
- Audio might travel: Laptop → DM-TX-1 → DM Matrix → Audio Processor → Amplifier
77+
78+
Both routes are discovered, stored, and executed independently. This allows for flexible system designs where audio and video follow different paths.
79+
80+
The same splitting behavior occurs for `Video + SecondaryAudio` requests, where video and secondary audio are routed as separate operations.
81+
82+
### Signal Type Filtering
83+
84+
At each step of the route discovery process, the algorithm filters tie lines based on the requested signal type:
85+
86+
- **Video request**: Only considers tie lines with the `video` flag set
87+
- **Audio request**: Only considers tie lines with the `audio` flag set
88+
- **AudioVideo request**: Routes audio and video separately, each following their respective filtering rules
89+
90+
If no tie line exists with the required signal type at any point in the chain, that path is rejected and the algorithm continues searching for an alternative route. If no valid path is found, the route request fails and no switching occurs.
91+
92+
This filtering ensures that incompatible signal types never interfere with routing decisions. For example, an audio-only cable will never be selected when routing video, preventing misconfiguration errors.
93+
94+
---
95+
4396
### Definitions
4497

4598
#### Ports
@@ -64,17 +117,100 @@ A sink is a device at the end of a full signal path. For example, a display, amp
64117

65118
#### Tie-line
66119

67-
A tie-line is a logical representation of a physical cable connection between two devices. It has five properties that define how the tie-line connects two devices. A configuration snippet for a single tie line connecting HDMI output 1 on a Cisco RoomKit to HDMI input 1 on a display, carrying both audio and video, is shown below.
120+
A tie-line is a logical representation of a physical cable connection between two devices. It has five properties that define how the tie-line connects two devices.
121+
122+
##### How Tie Line Types Are Determined
123+
124+
The effective type of a tie line is determined by one of two methods:
125+
126+
1. **Automatic (Recommended)**: When no `type` property is specified in configuration, the tie line's type is automatically calculated as the **intersection** of signal types supported by both the source and destination ports. This ensures only compatible signals are considered for routing.
127+
128+
Example: If a source port supports `AudioVideo` and the destination port supports `Audio`, the tie line will have type `Audio` (the only common type).
129+
130+
2. **Manual Override**: When the `type` property is explicitly set, it overrides the automatic calculation. This is useful when the physical cable supports fewer signal types than both ports are capable of.
131+
132+
Example: Both ports support `AudioVideo`, but the cable only carries audio, so you set `"type": "audio"`.
133+
134+
##### Validation
135+
136+
At startup, tie line configurations are validated to ensure:
137+
- Both ports exist on their respective devices
138+
- The source and destination ports have at least one common signal type
139+
- If a `type` override is specified, both ports must support that signal type
140+
141+
Invalid tie lines will fail to build with descriptive error messages, preventing runtime routing issues.
142+
143+
##### Signal Types
144+
145+
Tie lines support the following signal types:
146+
147+
- `audio` - Audio-only signals
148+
- `video` - Video-only signals
149+
- `audioVideo` - Combined audio and video (automatically split during routing)
150+
- `secondaryAudio` - Secondary audio channel (e.g., program audio separate from microphone audio)
151+
- `usbInput` - USB input signals
152+
- `usbOutput` - USB output signals
153+
154+
The `type` property determines which signals can travel through the tie line. During route discovery, only tie lines matching the requested signal type will be considered as valid paths.
155+
156+
**Note**: In most cases, you should omit the `type` property and let the system automatically calculate it from the port capabilities. Only use it when you need to restrict the tie line to fewer signal types than the ports support or when needed for clarity.
157+
158+
##### Configuration Examples
159+
160+
**Example 1: Automatic type calculation (recommended)**
161+
162+
Connecting an HDMI cable between devices that both support audio and video. The `type` property is omitted, so the tie line will automatically support `AudioVideo`:
68163

69164
```json
70165
{
71166
"sourceKey": "ciscoSparkPlusCodec-1",
72167
"sourcePort": "HdmiOut1",
73168
"destinationKey": "display-1",
74-
"destinationPort": "HdmiIn1",
75-
"type": "audioVideo"
169+
"destinationPort": "HdmiIn1"
170+
}
171+
```
172+
173+
**Example 2: Type override for cable limitations**
174+
175+
Both devices support `AudioVideo`, but the physical cable only carries audio. The `type` property restricts routing to audio only:
176+
177+
```json
178+
{
179+
"sourceKey": "dmSwitcher-1",
180+
"sourcePort": "audioVideoOut1",
181+
"destinationKey": "amplifier-1",
182+
"destinationPort": "audioVideoIn1",
183+
"type": "audio"
184+
}
185+
```
186+
187+
**Example 3: Mismatched port types (automatically handled)**
188+
189+
Source only supports audio, destination supports both. No `type` needed—the tie line will automatically be `Audio`:
190+
191+
```json
192+
{
193+
"sourceKey": "audioProcessor-1",
194+
"sourcePort": "audioOut1",
195+
"destinationKey": "dmSwitcher-1",
196+
"destinationPort": "audioVideoIn1"
197+
}
198+
```
199+
200+
**Invalid Example: Incompatible types**
201+
202+
This configuration will **fail validation** at startup because the ports have no common signal types:
203+
204+
```json
205+
{
206+
"sourceKey": "audioProcessor-1",
207+
"sourcePort": "audioOut1",
208+
"destinationKey": "display-1",
209+
"destinationPort": "hdmiIn1",
210+
"type": "video"
76211
}
77212
```
213+
Error: `"Override type 'Video' is not supported by source port 'audioOut1' (type: Audio)"`
78214

79215
### Interfaces
80216

src/PepperDash.Essentials.Core/Routing/TieLine.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
using Newtonsoft.Json;
2-
using System;
1+
using System;
32
using System.Collections.Generic;
3+
using Newtonsoft.Json;
44

55
namespace PepperDash.Essentials.Core
66
{
@@ -21,24 +21,24 @@ public class TieLine
2121
//public int InUseCount { get { return DestinationUsingThis.Count; } }
2222

2323
/// <summary>
24-
/// Gets the type of this tie line. Will either be the type of the destination port
25-
/// or the type of OverrideType when it is set.
24+
/// Gets the type of this tie line. Returns the intersection of signal types supported by both
25+
/// the source and destination ports (what signals can actually travel through this tie line),
26+
/// or the OverrideType when it is set.
2627
/// </summary>
2728
public eRoutingSignalType Type
2829
{
2930
get
3031
{
3132
if (OverrideType.HasValue) return OverrideType.Value;
32-
return DestinationPort.Type;
33+
return SourcePort.Type & DestinationPort.Type;
3334
}
3435
}
3536

3637
/// <summary>
37-
/// Use this to override the Type property for the destination port. For example,
38-
/// when the tie line is type AudioVideo, and the signal flow should be limited to
39-
/// Audio-only or Video only, changing this type will alter the signal paths
40-
/// available to the routing algorithm without affecting the actual Type
41-
/// of the destination port.
38+
/// Use this to override the Type property. For example, when both ports support AudioVideo
39+
/// but the physical cable only carries Audio or Video, setting this will limit the signal
40+
/// paths available to the routing algorithm without affecting the actual port types.
41+
/// When set, this value is used instead of the calculated intersection of source and destination types.
4242
/// </summary>
4343
public eRoutingSignalType? OverrideType { get; set; }
4444

@@ -79,7 +79,7 @@ public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort)
7979
/// </summary>
8080
/// <param name="sourcePort">The source output port.</param>
8181
/// <param name="destinationPort">The destination input port.</param>
82-
/// <param name="overrideType">The signal type to limit the link to. Overrides DestinationPort.Type for routing calculations.</param>
82+
/// <param name="overrideType">The signal type to limit the link to. Overrides the calculated intersection of port types for routing calculations.</param>
8383
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType? overrideType) :
8484
this(sourcePort, destinationPort)
8585
{
@@ -91,7 +91,7 @@ public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, e
9191
/// </summary>
9292
/// <param name="sourcePort">The source output port.</param>
9393
/// <param name="destinationPort">The destination input port.</param>
94-
/// <param name="overrideType">The signal type to limit the link to. Overrides DestinationPort.Type for routing calculations.</param>
94+
/// <param name="overrideType">The signal type to limit the link to. Overrides the calculated intersection of port types for routing calculations.</param>
9595
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType overrideType) :
9696
this(sourcePort, destinationPort)
9797
{

src/PepperDash.Essentials.Core/Routing/TieLineConfig.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ public class TieLineConfig
4949
public string DestinationPort { get; set; }
5050

5151
/// <summary>
52-
/// Optional override for the signal type of the tie line. If set, this overrides the destination port's type for routing calculations.
52+
/// Optional override for the signal type of the tie line. If set, this overrides the calculated
53+
/// intersection of source and destination port types for routing calculations. Useful when the
54+
/// physical cable supports fewer signal types than both ports are capable of.
5355
/// </summary>
5456
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
5557
[JsonConverter(typeof(StringEnumConverter))]
@@ -96,6 +98,32 @@ public TieLine GetTieLine()
9698
return null;
9799
}
98100

101+
// Validate signal type compatibility
102+
if (OverrideType.HasValue)
103+
{
104+
// When override type is specified, both ports must support it
105+
if (!sourceOutputPort.Type.HasFlag(OverrideType.Value))
106+
{
107+
LogError($"Override type '{OverrideType.Value}' is not supported by source port '{SourcePort}' (type: {sourceOutputPort.Type})");
108+
return null;
109+
}
110+
111+
if (!destinationInputPort.Type.HasFlag(OverrideType.Value))
112+
{
113+
LogError($"Override type '{OverrideType.Value}' is not supported by destination port '{DestinationPort}' (type: {destinationInputPort.Type})");
114+
return null;
115+
}
116+
}
117+
else
118+
{
119+
// Without override type, ports must have at least one common signal type flag
120+
if ((sourceOutputPort.Type & destinationInputPort.Type) == 0)
121+
{
122+
LogError($"Incompatible signal types: source port '{SourcePort}' (type: {sourceOutputPort.Type}) has no common signal types with destination port '{DestinationPort}' (type: {destinationInputPort.Type})");
123+
return null;
124+
}
125+
}
126+
99127
return new TieLine(sourceOutputPort, destinationInputPort, OverrideType);
100128
}
101129

0 commit comments

Comments
 (0)