mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-04-04 03:55:07 +00:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2684f364d | ||
|
|
29d5804cb0 | ||
|
|
c20d49f430 | ||
|
|
a82cf4f449 | ||
|
|
305a466b1b | ||
|
|
5a07e837ee | ||
|
|
b64f63ac6b | ||
|
|
b21be608f0 | ||
|
|
6ab3ed9911 | ||
|
|
a9fdf30880 | ||
|
|
963925ffef | ||
|
|
e162ed208b | ||
|
|
bd38475b10 | ||
|
|
a704e48ae6 | ||
|
|
b40200ecae | ||
|
|
9de14da201 | ||
|
|
633608c8c6 | ||
|
|
f8a81de177 | ||
|
|
afc5cf1a14 | ||
|
|
8ff9de817c |
@@ -52,6 +52,7 @@
|
||||
"_appLogoPath": "docs/images/favicon-32x32.png",
|
||||
"_appFaviconPath": "docs/images/favicon.ico",
|
||||
"_disableToc": false,
|
||||
"_enableNewTab": true,
|
||||
"pdf": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
# Essentials connection-based routing
|
||||
|
||||
## TL;DR
|
||||
|
||||
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.
|
||||
|
||||
## Summary
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
### Classes Referenced
|
||||
|
||||
* `PepperDash.Essentials.Core.Routing.IRoutingSource`
|
||||
* `PepperDash.Essentials.Core.Routing.IRoutingOutputs`
|
||||
* `PepperDash.Essentials.Core.Routing.IRoutingInputs`
|
||||
* `PepperDash.Essentials.Core.Routing.IRoutingInputsOutputs`
|
||||
* `PepperDash.Essentials.Core.Routing.IRoutingSinkNoSwitching`
|
||||
* `PepperDash.Essentials.Core.Routing.IRoutingSinkWithSwitching`
|
||||
|
||||
## Example system, a simple presentation system
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
Let’s go through some examples of routing, using pseudo-code:
|
||||
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
All of the above routes can be defined in source list routing tables, covered elsewhere (**make link)**.
|
||||
|
||||
---
|
||||
|
||||
### Definitions
|
||||
|
||||
#### Ports
|
||||
|
||||
Ports are logical representations of the input and output ports on a device.
|
||||
|
||||
#### Source
|
||||
|
||||
A source is a device at the beginning of a signal chain. For example, a set-top box, or a camera. Source devices typically have only output ports.
|
||||
|
||||
Source devices in Essentials must implement `IRoutingOutputs` or `IRoutingSource`
|
||||
|
||||
#### Midpoint
|
||||
|
||||
A midpoint is a device in the middle of the signal chain. Typically a switcher, matrix or otherwise. Examples: DM chassis; DM-TX; DM-RMC; A video codec. These devices will have input and output ports.
|
||||
|
||||
Midpoint devices must implement `IRoutingInputsOutputs`. Midpoints with switching must implement `IRouting`.
|
||||
|
||||
#### Sink
|
||||
|
||||
A sink is a device at the end of a full signal path. For example, a display, amplifier, encoder, etc. Sinks typically contain only input ports. They may or may not have switching, like a display with several inputs. Classes defining sink devices must implement `IRoutingSinkNoSwitching` or `IRoutingSinkWithSwitching`.
|
||||
|
||||
#### Tie-line
|
||||
|
||||
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.
|
||||
|
||||
```json
|
||||
{
|
||||
"sourceKey": "ciscoSparkPlusCodec-1",
|
||||
"sourcePort": "HdmiOut1",
|
||||
"destinationKey": "display-1",
|
||||
"destinationPort": "HdmiIn1",
|
||||
"type": "audioVideo"
|
||||
}
|
||||
```
|
||||
|
||||
### Interfaces
|
||||
|
||||
Todo: Define Interfaces IRouting, IRoutingOutputs, IRoutingInputs
|
||||
@@ -4,23 +4,44 @@
|
||||
[YouTube Video - Getting Started with PepperDash Essentials](https://youtu.be/FxEZtbpCwiQ)
|
||||
***
|
||||
|
||||
## Download or clone
|
||||
## Get a CPZ
|
||||
|
||||
You may clone Essentials at <https://github.com/PepperDash/Essentials.git>
|
||||
### Prerequisites
|
||||
|
||||
* [VS Code](https://code.visualstudio.com/)
|
||||
* [.NET 9 SDK](https://dotnet.microsoft.com/en-us/download)
|
||||
* [Git](https://git-scm.com/)
|
||||
|
||||
> Note: Essentials 2.x.x uses .NET Framework 4.7.2 currently. The .NET 9 SDK will build the project with the appropriate references
|
||||
|
||||
### Build From Source
|
||||
|
||||
1. Clone the repo: `git clone https://github.com/PepperDash/Essentials.git`
|
||||
2. Open the folder in VS Code
|
||||
3. Build using the dotnet CLI: `dotnet build`
|
||||
|
||||
### Download the latest release
|
||||
|
||||
The latest release can be found on [Github](https://github.com/PepperDash/Essentials/releases/latest)
|
||||
|
||||
## How to Get Started
|
||||
|
||||
This section assumes knowledge of loading programs to and working with the file system on a Crestron processor.
|
||||
2. Using an SFTP client or Crestron Toolbox, load the downloaded (or built) cpz to the processor in program slot 1
|
||||
1. If using SFTP, connect via SSH and start the program by sending console command `progload -p:1`
|
||||
3. On first boot, the Essentials Application will build the necessary configuration folder structure in the user/program1/ path.
|
||||
4. The application has some example configuration files included. Copy `/Program01/Example Configuration/EssentialsSpaceHuddleRoom/configurationFile-HuddleSpace-2-Source.json` to the `/User/Program1/` folder.
|
||||
6. Reset the program via console `progreset -p:1`. The program will load the example configuration file.
|
||||
|
||||
1. Using an SFTP client, load `PepperDashEssentials1.4.32.cpz` to the processor in program slot 1 and start the program by sending console command `progload -p:1`
|
||||
1. On first boot, the Essentials Application will build the necessary configuration folder structure in the User/Program1/ path.
|
||||
1. The application has some example configuration files included. Copy `/Program01/Example Configuration/EssentialsSpaceHuddleRoom/configurationFile-HuddleSpace-2-Source.json` to the `/User/Program1/` folder.
|
||||
1. Copy the SGD files from `/Program01/SGD` to `/User/Program1/sgd`
|
||||
1. Reset the program via console `progreset -p:1`. The program will load the example configuration file.
|
||||
1. Via console, you can run the `devlist:1` command to get some insight into what has been loaded from the configuration file into the system . This will print the basic device information in the form of ["key"] "Name". The "key" value is what we can use to interact with each device uniquely.
|
||||
1. Run the command `devprops:1 display-1`. This will print the real-time property values of the device with key "display-1".
|
||||
1. Run the command `devmethods:1 display-1`. This will print the public methods available for the device with key "display-1".
|
||||
1. Run the command `devjson:1 {"deviceKey":"display-1","methodName":"PowerOn", "params": []}`. This will call the method PowerOn() on the device with key "display-1".
|
||||
1. Run the provided example XPanel SmartGraphics project and connect to your processor at the appropriate IPID.
|
||||
Once Essentials is running with a valid configuration, the following console commands can be used to see what's going on:
|
||||
|
||||
Next: [Standalone use](~/docs/Standalone-Use.md)
|
||||
* ```devlist:1```
|
||||
* Print the list of devices in [{key}] {name} format
|
||||
* The key of a device can be used with the rest of the commands to get more information
|
||||
* `devprops:1 {deviceKey}`
|
||||
* Print the real-time property values of the device with key "display-1".
|
||||
* `devmethods:1 display-1`
|
||||
* Print the public methods available for the device with key "display-1".
|
||||
* `devjson:1 {"deviceKey":"display-1","methodName":"PowerOn", "params": []}`
|
||||
* Call the method `PowerOn()` on the device with key "display-1".
|
||||
|
||||
Next: [Standalone use](~/docs/usage/Standalone-Use.md)
|
||||
|
||||
@@ -39,7 +39,7 @@ Thanks!
|
||||
|
||||
## Collaboration
|
||||
|
||||
Essentials is an open-source project and we encourage collaboration on this community project. For features that may not be useful to the greater community, or for just-plain learning, we want to remind developers to try writing plugins for Essentials. More information can be found here: [Plugins](~/docs/Plugins.md)
|
||||
Essentials is an open-source project and we encourage collaboration on this community project. For features that may not be useful to the greater community, or for just-plain learning, we want to remind developers to try writing plugins for Essentials. More information can be found here: [Plugins](~/docs/technical-docs/Plugins.md)
|
||||
|
||||
### Open-source-collaborative workflow
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Deprecated
|
||||
|
||||
**Note : this entry is out of date - please see [Plugins](~/docs/Plugins.md)**
|
||||
**Note : this entry is out of date - please see [Plugins](~/docs/technical-docs/Plugins.md)**
|
||||
|
||||
## What are Essentials Plugins?
|
||||
|
||||
|
||||
@@ -358,7 +358,7 @@ Example device config: <https://github.com/PepperDash/Essentials/blob/main/Peppe
|
||||
|
||||
1. A bridge need not only bridge between applications on the same processor. A bridge may bridge to an application on a completely separate processor; simply define the ip address in the Bridge control properties accordingly.
|
||||
|
||||
1. For devices included in Essentials, you will be able to find defined join maps below. If you are building your own plugins, you will need to build the join map yourself. It would be beneficial to review the wiki entry on the [Feedback Class](~/docs/Feedback-Classes.md) for this.
|
||||
1. For devices included in Essentials, you will be able to find defined join maps below. If you are building your own plugins, you will need to build the join map yourself. It would be beneficial to review the wiki entry on the [Feedback Class](~/docs/technical-docs/Feedback-Classes.md) for this.
|
||||
|
||||
1. When building plugins, we highly recommend reusing JoinMaps, as this will make code more easily interchangeable. For example; if you were to build a display plugin, we'd recommend you use/extend the existing DisplayControllerJoinMap. This way, you can swap plugins without needing any change on the Simpl Windows side. This is extremely powerful when maintaining Simpl Windows code bases for large deployments that may utilize differing equipment per room. If you can build a Simpl Windows program that interacts with established join maps, you can swap out the device via config without any change needed to Simpl Windows.
|
||||
|
||||
@@ -474,4 +474,4 @@ Example device config: <https://github.com/PepperDash/Essentials/blob/main/Peppe
|
||||
|
||||
We've provided an [example program](https://github.com/PepperDash/EssentialsSIMPLWindowsBridgeExample) for SIMPL Windows that works with the provided example Essentials configuration file [SIMPLBridgeExample_configurationFile.json](https://github.com/PepperDash/Essentials/blob/main/PepperDashEssentials/Example%20Configuration/SIMPLBridging/SIMPLBridgeExample_configurationFile.json). Load Essentials and the example SIMPL program to two slots on the same processor and you can get a better idea of how to take advantage of SIMPL Windows bridging.
|
||||
|
||||
Next: [Essentials architecture](~/docs/Arch-summary.md)
|
||||
Next: [Essentials architecture](~/docs/technical-docs/Arch-summary.md)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# SIMPL Windows Bridging
|
||||
|
||||
**Note : this entry is out of date - please see [SIMPL Windows Bridging - Updated](~/docs/SIMPL-Bridging-Updated.md)**
|
||||
**Note : this entry is out of date - please see [SIMPL Windows Bridging - Updated](~/docs/usage/SIMPL-Bridging-Updated.md)**
|
||||
|
||||
Essentials allows for devices defined within the SIMPL# Pro application to be bridged to a SIMPL Windows application over Ethernet Intersystem Communication (EISC). This allows a SIMPL Windows program to take advantage of some of the features of the SIMPL# Pro environment, without requiring the entire application to be written in C#.
|
||||
|
||||
@@ -356,7 +356,7 @@ Example device config: <https://github.com/PepperDash/Essentials/blob/main/Peppe
|
||||
|
||||
1. A bridge need not only bridge between applications on the same processor. A bridge may bridge to an application on a completely separate processor; simply define the ip address in the Bridge control properties accordingly.
|
||||
|
||||
1. For devices included in Essentials, you will be able to find defined join maps below. If you are building your own plugins, you will need to build the join map yourself. It would be beneficial to review the wiki entry on the [Feedback Class](~/docs/Feedback-Classes.md) for this.
|
||||
1. For devices included in Essentials, you will be able to find defined join maps below. If you are building your own plugins, you will need to build the join map yourself. It would be beneficial to review the wiki entry on the [Feedback Class](~/docs/technical-docs/Feedback-Classes.md) for this.
|
||||
|
||||
1. When building plugins, we highly recommend reusing JoinMaps, as this will make code more easily interchangeable. For example; if you were to build a display plugin, we'd recommend you use/extend the existing DisplayControllerJoinMap. This way, you can swap plugins without needing any change on the Simpl Windows side. This is extremely powerful when maintaining Simpl Windows code bases for large deployments that may utilize differing equipment per room. If you can build a Simpl Windows program that interacts with established join maps, you can swap out the device via config without any change needed to Simpl Windows.
|
||||
|
||||
@@ -472,4 +472,4 @@ Example device config: <https://github.com/PepperDash/Essentials/blob/main/Peppe
|
||||
|
||||
We've provided an [example program](https://github.com/PepperDash/EssentialsSIMPLWindowsBridgeExample) for SIMPL Windows that works with the provided example Essentials configuration file [SIMPLBridgeExample_configurationFile.json](https://github.com/PepperDash/Essentials/blob/main/PepperDashEssentials/Example%20Configuration/SIMPLBridging/SIMPLBridgeExample_configurationFile.json). Load Essentials and the example SIMPL program to two slots on the same processor and you can get a better idea of how to take advantage of SIMPL Windows bridging.
|
||||
|
||||
Next: [Essentials architecture](~/docs/Arch-summary.md)
|
||||
Next: [Essentials architecture](~/docs/technical-docs/Arch-summary.md)
|
||||
|
||||
148
docs/docs/how-to/how-to-add-docs.md
Normal file
148
docs/docs/how-to/how-to-add-docs.md
Normal file
@@ -0,0 +1,148 @@
|
||||
# How to Add Documentation to Essentials
|
||||
|
||||
This guide explains how to add new documentation articles to the Essentials docFx site.
|
||||
|
||||
## Overview
|
||||
|
||||
The Essentials documentation uses [docFx](https://dotnet.github.io/docfx/) to generate a static documentation website. Documentation files are organized in a hierarchical structure with a table of contents (TOC) file that defines the site navigation. Documentation should be organized and written to fit into the [Diátaxis](https://diataxis.fr/start-here/) conceptual framework.
|
||||
|
||||
## Documentation Structure
|
||||
|
||||
Documentation files are located in `/docs/docs/` and organized into the following subdirectories:
|
||||
|
||||
- **how-to/** - Step-by-step guides and tutorials
|
||||
- **usage/** - Usage documentation for SIMPL bridging, standalone use, and hardware integration
|
||||
- **technical-docs/** - Technical documentation including architecture, plugins, and API references
|
||||
- **images/** - Image assets used in documentation
|
||||
|
||||
## Adding a New Document
|
||||
|
||||
### Step 1: Create Your Markdown File
|
||||
|
||||
1. Determine which category your document belongs to (how-to, usage, or technical-docs)
|
||||
2. Create a new `.md` file in the appropriate subdirectory
|
||||
3. Use a descriptive filename with hyphens (e.g., `my-new-feature.md`)
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
# For a how-to guide
|
||||
touch /docs/docs/how-to/configure-audio-settings.md
|
||||
|
||||
# For usage documentation
|
||||
touch /docs/docs/usage/video-switcher-control.md
|
||||
|
||||
# For technical documentation
|
||||
touch /docs/docs/technical-docs/custom-device-plugin.md
|
||||
```
|
||||
|
||||
### Step 2: Write Your Content
|
||||
|
||||
Start your markdown file with a level 1 heading (`#`) that serves as the page title:
|
||||
|
||||
```markdown
|
||||
# Your Document Title
|
||||
|
||||
Brief introduction to the topic.
|
||||
|
||||
## Section Heading
|
||||
|
||||
Content goes here...
|
||||
|
||||
### Subsection
|
||||
|
||||
More detailed content...
|
||||
```
|
||||
|
||||
**Markdown Features:**
|
||||
- Use standard markdown syntax
|
||||
- Include code blocks with language specifiers (```csharp, ```json, etc.)
|
||||
- Add images: ``
|
||||
- Link to other docs: `[Link text](../usage/related-doc.md)`
|
||||
|
||||
### Step 3: Add to Table of Contents
|
||||
|
||||
Edit `/docs/docs/toc.yml` to add your new document to the navigation:
|
||||
|
||||
```yaml
|
||||
- name: How-to's
|
||||
items:
|
||||
- href: how-to/how-to-add-docs.md
|
||||
- href: how-to/your-new-doc.md # Add your document here
|
||||
```
|
||||
|
||||
**TOC Structure:**
|
||||
- `name:` - Display name in the navigation menu
|
||||
- `href:` - Relative path to the markdown file
|
||||
- `items:` - Nested items for hierarchical navigation
|
||||
|
||||
**Example with nested items:**
|
||||
```yaml
|
||||
- name: Usage
|
||||
items:
|
||||
- name: SIMPL Bridging
|
||||
href: usage/SIMPL-Bridging-Updated.md
|
||||
items:
|
||||
- name: Your Sub-Topic
|
||||
href: usage/your-sub-topic.md
|
||||
```
|
||||
|
||||
### Step 4: Test Locally
|
||||
|
||||
Build and preview the docFx site locally to verify your changes:
|
||||
|
||||
```bash
|
||||
# Navigate to the docs directory
|
||||
cd docs
|
||||
|
||||
# Build the documentation
|
||||
docfx build
|
||||
|
||||
# Serve the site locally
|
||||
docfx serve _site
|
||||
```
|
||||
|
||||
Then open your browser to `http://localhost:8080` to view the site.
|
||||
|
||||
## Best Practices
|
||||
|
||||
### File Naming
|
||||
- Use lowercase with hyphens: `my-document-name.md`
|
||||
- Be descriptive but concise
|
||||
- Avoid special characters
|
||||
|
||||
### Content Guidelines
|
||||
- Start with a clear introduction
|
||||
- Use hierarchical headings (H1 → H2 → H3)
|
||||
- Include code examples where appropriate
|
||||
- Add images to illustrate complex concepts
|
||||
- Link to related documentation
|
||||
|
||||
### TOC Organization
|
||||
- Group related documents under the same parent
|
||||
- Order items logically (basic → advanced)
|
||||
- Keep the TOC hierarchy shallow (2-3 levels max)
|
||||
- Use clear, descriptive names for navigation items
|
||||
|
||||
## Common Issues
|
||||
|
||||
### Document Not Appearing
|
||||
- Verify the file path in `toc.yml` is correct and uses forward slashes
|
||||
- Ensure the markdown file exists in the specified location
|
||||
- Check for YAML syntax errors in `toc.yml`
|
||||
|
||||
### Images Not Loading
|
||||
- Verify image path is relative to the markdown file location
|
||||
- Use `../images/` for files in the images directory
|
||||
- Ensure image files are committed to the repository
|
||||
|
||||
### Broken Links
|
||||
- Use relative paths for internal links
|
||||
- Test all links after building the site
|
||||
- Use `.md` extension when linking to other documentation files
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [docFx Documentation](https://dotnet.github.io/docfx/)
|
||||
- [Markdown Guide](https://www.markdownguide.org/)
|
||||
- [YAML Syntax](https://yaml.org/spec/1.2/spec.html)
|
||||
- [Diátaxis](https://diataxis.fr/start-here/)
|
||||
@@ -26,7 +26,7 @@ Types of things in `DeviceManager`:
|
||||
|
||||
A Device doesn't always represent a physical piece of hardware, but rather a logical construct that "does something" and is used by one or more other devices in the running program. For example, we create a room device, and its corresponding Fusion device, and that room has a Cisco codec device, with an attached SSh client device. All of these lie in a flat collection in the `DeviceManager`.
|
||||
|
||||
> The `DeviceManager` is nothing more than a modified collection of things, and technically those things don't have to be Devices, but must at least implement the `IKeyed` (`PepperDash.Core.IKeyed`) interface (simply so items can be looked up by their key.) Items in the `DeviceManager` that are Devices are run through additional steps of [activation](~/docs/Arch-activate.md#2-pre-activation) at startup. This collection of devices is all interrelated by their string keys.
|
||||
> The `DeviceManager` is nothing more than a modified collection of things, and technically those things don't have to be Devices, but must at least implement the `IKeyed` (`PepperDash.Core.IKeyed`) interface (simply so items can be looked up by their key.) Items in the `DeviceManager` that are Devices are run through additional steps of [activation](~/docs/technical-docs/Arch-activate.md#2-pre-activation) at startup. This collection of devices is all interrelated by their string keys.
|
||||
|
||||
In this flat design, we spin up devices, and then introduce them to their "coworkers and bosses" - the other devices and logical units that they will interact with - and get them all operating together to form a running unit. For example: A room configuration will contain a "VideoCodecKey" property and a "DefaultDisplayKey" property. The `DeviceManager` provides the room with the codec or displays having the appropriate keys. What the room does with those is dependent on its coding.
|
||||
|
||||
@@ -38,4 +38,4 @@ This flat structure ensures that every device in a system exists in one place an
|
||||
|
||||

|
||||
|
||||
Next: [Configurable lifecycle](~/docs/Arch-lifecycle.md)
|
||||
Next: [Configurable lifecycle](~/docs/technical-docs/Arch-lifecycle.md)
|
||||
@@ -105,7 +105,7 @@ Each of the three activation phases operates in a try/catch block for each devic
|
||||
|
||||
In any real-world system, devices and business logic need to talk to each other, otherwise, what's the point of all this coding? When creating your classes and configuration, it is best practice to _try_ not to "plug" one device into another during construction or activation. For example your touchpanel controller class has a `Display1` property that holds the display-1 object. Rather, it may be better to refer to the device as it is stored in the `DeviceManager` when it's needed using the static `DeviceManager.GetDeviceForKey(key)` method to get a reference to the device, which can be cast using various interfaces/class types, and then interacted with. This prevents objects from being referenced in places where the developer may later forget to dereference them, causing memory leak. This will become more important as Essentials becomes more able to be reconfigured at runtime.
|
||||
|
||||
As an example, [connection-based routing](~/docs/Connection-based-routing.md#essentials-connection-based-routing) uses these methods. When a route is requested, the collection of tielines and devices is searched for the devices and paths necessary to complete a route, but there are no devices or tie lines that are object-referenced in running code. It can all be torn down and reconfigured without any memory-management dereferencing, setting things to null.
|
||||
As an example, [connection-based routing](~/docs/technical-docs/Connection-based-routing.md#essentials-connection-based-routing) uses these methods. When a route is requested, the collection of tielines and devices is searched for the devices and paths necessary to complete a route, but there are no devices or tie lines that are object-referenced in running code. It can all be torn down and reconfigured without any memory-management dereferencing, setting things to null.
|
||||
|
||||
## Device Initialization
|
||||
|
||||
@@ -155,4 +155,4 @@ Robust C#-based system code should not depend on "order" or "time" to get runnin
|
||||
|
||||
When designing new Device-based classes, be it rooms, devices, port controllers, bridges, make them as independent as possible. They could exist alone in a program with no required partner objects, and just quietly exist without failing. We want the system to be fast and flexible, and keeping the interdependence between objects at a minimum improves this flexibility into the future.
|
||||
|
||||
Next: [More architecture](~/docs/Arch-topics.md)
|
||||
Next: [More architecture](~/docs/technical-docs/Arch-topics.md)
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
The diagram below describes how Essentials gets a program up and running.
|
||||
|
||||
(The various activation phases are covered in more detail on the [next page](~/docs/Arch-activate.md))
|
||||
(The various activation phases are covered in more detail on the [next page](~/docs/technical-docs/Arch-activate.md))
|
||||
|
||||

|
||||
|
||||
Next: [Activation phases](~/docs/Arch-activate.md)
|
||||
Next: [Activation phases](~/docs/technical-docs/Arch-activate.md)
|
||||
@@ -16,4 +16,4 @@ The diagram below shows the reference dependencies that exist between the differ
|
||||
|
||||

|
||||
|
||||
Next: [Architecture](~/docs/Arch-1.md)
|
||||
Next: [Architecture](~/docs/technical-docs/Arch-1.md)
|
||||
217
docs/docs/technical-docs/Connection-Based-Routing.md
Normal file
217
docs/docs/technical-docs/Connection-Based-Routing.md
Normal file
@@ -0,0 +1,217 @@
|
||||
# Essentials connection-based routing
|
||||
|
||||
## TL;DR
|
||||
|
||||
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.
|
||||
|
||||
## Summary
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
### Signal Type Handling
|
||||
|
||||
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:
|
||||
- Audio-only tie lines can be used for the audio portion
|
||||
- Video-only tie lines can be used for the video portion
|
||||
- AudioVideo tie lines can be used for both portions
|
||||
|
||||
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.
|
||||
|
||||
### Port-Specific Routing
|
||||
|
||||
The routing system supports routing to and from specific ports on devices. You can specify:
|
||||
- A specific input port on the destination device
|
||||
- A specific output port on the source device
|
||||
- Both specific ports for precise routing control
|
||||
|
||||
When no specific ports are specified, the algorithm will automatically discover the appropriate ports based on available tie lines.
|
||||
|
||||
### Request Queuing
|
||||
|
||||
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.
|
||||
|
||||
### Classes Referenced
|
||||
|
||||
* `PepperDash.Essentials.Core.Routing.IRoutingSource`
|
||||
* `PepperDash.Essentials.Core.Routing.IRoutingOutputs`
|
||||
* `PepperDash.Essentials.Core.Routing.IRoutingInputs`
|
||||
* `PepperDash.Essentials.Core.Routing.IRoutingInputsOutputs`
|
||||
* `PepperDash.Essentials.Core.Routing.IRoutingSinkNoSwitching`
|
||||
* `PepperDash.Essentials.Core.Routing.IRoutingSinkWithSwitching`
|
||||
|
||||
## Example system, a simple presentation system
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
Let’s go through some examples of routing, using pseudo-code:
|
||||
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
All of the above routes can be defined in source list routing tables, covered elsewhere (**make link)**.
|
||||
|
||||
---
|
||||
|
||||
## Routing Algorithm Details
|
||||
|
||||
### Combined Signal Type Splitting
|
||||
|
||||
When an `audioVideo` route is requested, the routing system automatically splits it into two independent routing operations:
|
||||
|
||||
1. **Audio Route**: Finds the best path for audio signals from source to destination
|
||||
2. **Video Route**: Finds the best path for video signals from source to destination
|
||||
|
||||
Each route can take a different physical path through the system. For example:
|
||||
- Video might travel: Laptop → DM-TX-1 → DM Matrix → Display
|
||||
- Audio might travel: Laptop → DM-TX-1 → DM Matrix → Audio Processor → Amplifier
|
||||
|
||||
Both routes are discovered, stored, and executed independently. This allows for flexible system designs where audio and video follow different paths.
|
||||
|
||||
The same splitting behavior occurs for `Video + SecondaryAudio` requests, where video and secondary audio are routed as separate operations.
|
||||
|
||||
### Signal Type Filtering
|
||||
|
||||
At each step of the route discovery process, the algorithm filters tie lines based on the requested signal type:
|
||||
|
||||
- **Video request**: Only considers tie lines with the `video` flag set
|
||||
- **Audio request**: Only considers tie lines with the `audio` flag set
|
||||
- **AudioVideo request**: Routes audio and video separately, each following their respective filtering rules
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
### Definitions
|
||||
|
||||
#### Ports
|
||||
|
||||
Ports are logical representations of the input and output ports on a device.
|
||||
|
||||
#### Source
|
||||
|
||||
A source is a device at the beginning of a signal chain. For example, a set-top box, or a camera. Source devices typically have only output ports.
|
||||
|
||||
Source devices in Essentials must implement `IRoutingOutputs` or `IRoutingSource`
|
||||
|
||||
#### Midpoint
|
||||
|
||||
A midpoint is a device in the middle of the signal chain. Typically a switcher, matrix or otherwise. Examples: DM chassis; DM-TX; DM-RMC; A video codec. These devices will have input and output ports.
|
||||
|
||||
Midpoint devices must implement `IRoutingInputsOutputs`. Midpoints with switching must implement `IRouting`.
|
||||
|
||||
#### Sink
|
||||
|
||||
A sink is a device at the end of a full signal path. For example, a display, amplifier, encoder, etc. Sinks typically contain only input ports. They may or may not have switching, like a display with several inputs. Classes defining sink devices must implement `IRoutingSinkNoSwitching` or `IRoutingSinkWithSwitching`.
|
||||
|
||||
#### Tie-line
|
||||
|
||||
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.
|
||||
|
||||
##### How Tie Line Types Are Determined
|
||||
|
||||
The effective type of a tie line is determined by one of two methods:
|
||||
|
||||
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.
|
||||
|
||||
Example: If a source port supports `AudioVideo` and the destination port supports `Audio`, the tie line will have type `Audio` (the only common type).
|
||||
|
||||
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.
|
||||
|
||||
Example: Both ports support `AudioVideo`, but the cable only carries audio, so you set `"type": "audio"`.
|
||||
|
||||
##### Validation
|
||||
|
||||
At startup, tie line configurations are validated to ensure:
|
||||
- Both ports exist on their respective devices
|
||||
- The source and destination ports have at least one common signal type
|
||||
- If a `type` override is specified, both ports must support that signal type
|
||||
|
||||
Invalid tie lines will fail to build with descriptive error messages, preventing runtime routing issues.
|
||||
|
||||
##### Signal Types
|
||||
|
||||
Tie lines support the following signal types:
|
||||
|
||||
- `audio` - Audio-only signals
|
||||
- `video` - Video-only signals
|
||||
- `audioVideo` - Combined audio and video (automatically split during routing)
|
||||
- `secondaryAudio` - Secondary audio channel (e.g., program audio separate from microphone audio)
|
||||
- `usbInput` - USB input signals
|
||||
- `usbOutput` - USB output signals
|
||||
|
||||
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.
|
||||
|
||||
**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.
|
||||
|
||||
##### Configuration Examples
|
||||
|
||||
**Example 1: Automatic type calculation (recommended)**
|
||||
|
||||
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`:
|
||||
|
||||
```json
|
||||
{
|
||||
"sourceKey": "ciscoSparkPlusCodec-1",
|
||||
"sourcePort": "HdmiOut1",
|
||||
"destinationKey": "display-1",
|
||||
"destinationPort": "HdmiIn1"
|
||||
}
|
||||
```
|
||||
|
||||
**Example 2: Type override for cable limitations**
|
||||
|
||||
Both devices support `AudioVideo`, but the physical cable only carries audio. The `type` property restricts routing to audio only:
|
||||
|
||||
```json
|
||||
{
|
||||
"sourceKey": "dmSwitcher-1",
|
||||
"sourcePort": "audioVideoOut1",
|
||||
"destinationKey": "amplifier-1",
|
||||
"destinationPort": "audioVideoIn1",
|
||||
"type": "audio"
|
||||
}
|
||||
```
|
||||
|
||||
**Example 3: Mismatched port types (automatically handled)**
|
||||
|
||||
Source only supports audio, destination supports both. No `type` needed—the tie line will automatically be `Audio`:
|
||||
|
||||
```json
|
||||
{
|
||||
"sourceKey": "audioProcessor-1",
|
||||
"sourcePort": "audioOut1",
|
||||
"destinationKey": "dmSwitcher-1",
|
||||
"destinationPort": "audioVideoIn1"
|
||||
}
|
||||
```
|
||||
|
||||
**Invalid Example: Incompatible types**
|
||||
|
||||
This configuration will **fail validation** at startup because the ports have no common signal types:
|
||||
|
||||
```json
|
||||
{
|
||||
"sourceKey": "audioProcessor-1",
|
||||
"sourcePort": "audioOut1",
|
||||
"destinationKey": "display-1",
|
||||
"destinationPort": "hdmiIn1",
|
||||
"type": "video"
|
||||
}
|
||||
```
|
||||
Error: `"Override type 'Video' is not supported by source port 'audioOut1' (type: Audio)"`
|
||||
|
||||
### Interfaces
|
||||
|
||||
Todo: Define Interfaces IRouting, IRoutingOutputs, IRoutingInputs
|
||||
@@ -1,48 +1,52 @@
|
||||
- name: Get Started With Essentials
|
||||
- href: ../index.md
|
||||
- href: Get-started.md
|
||||
- href: Get-started.md
|
||||
- name: How-to's
|
||||
items:
|
||||
- name: How to add an article or doc page
|
||||
href: how-to/how-to-add-docs.md
|
||||
- name: Usage
|
||||
items:
|
||||
- href: Standalone-Use.md
|
||||
- href: SIMPL-Bridging-Updated.md
|
||||
- href: usage/Standalone-Use.md
|
||||
- href: usage/SIMPL-Bridging-Updated.md
|
||||
items:
|
||||
- name: Join Maps
|
||||
href: JoinMaps.md
|
||||
href: usage/JoinMaps.md
|
||||
- name: Bridging to Hardware Resources
|
||||
href: Bridging-To-Hardware-Resources.md
|
||||
href: usage/Bridging-To-Hardware-Resources.md
|
||||
items:
|
||||
- name: GenericComm Bridging
|
||||
href: GenericComm.md
|
||||
href: usage/GenericComm.md
|
||||
- name: RelayOutput Bridging
|
||||
href: RelayOutput.md
|
||||
href: usage/RelayOutput.md
|
||||
- name: Digital Input Bridging
|
||||
href: DigitalInput.md
|
||||
href: usage/DigitalInput.md
|
||||
- name: IR Driver Bridging
|
||||
href: IR-Driver-Bridging.md
|
||||
href: usage/IR-Driver-Bridging.md
|
||||
- name: Technical documentation
|
||||
items:
|
||||
- href: Arch-summary.md
|
||||
- href: technical-docs/Arch-summary.md
|
||||
- name: Devices and DeviceManager
|
||||
href: Arch-1.md
|
||||
href: technical-docs/Arch-1.md
|
||||
- name: Configurable lifecycle
|
||||
href: Arch-lifecycle.md
|
||||
href: technical-docs/Arch-lifecycle.md
|
||||
- name: Activation phases
|
||||
href: Arch-activate.md
|
||||
href: technical-docs/Arch-activate.md
|
||||
- name: More
|
||||
href: Arch-topics.md
|
||||
href: technical-docs/Arch-topics.md
|
||||
- name: Plugins
|
||||
href: Plugins.md
|
||||
href: technical-docs/Plugins.md
|
||||
- name: Communication Basics
|
||||
href: Communication-Basics.md
|
||||
href: technical-docs/Communication-Basics.md
|
||||
- name: Debugging
|
||||
href: Debugging.md
|
||||
href: technical-docs/Debugging.md
|
||||
- name: Feedback Classes
|
||||
href: Feedback-Classes.md
|
||||
href: technical-docs/Feedback-Classes.md
|
||||
- name: Connection Based Routing
|
||||
href: Connection-Based-Routing.md
|
||||
href: technical-docs/Connection-Based-Routing.md
|
||||
- name: Configuration Structure
|
||||
href: ConfigurationStructure.md
|
||||
href: technical-docs/ConfigurationStructure.md
|
||||
- name: Supported Devices
|
||||
href: Supported-Devices.md
|
||||
href: technical-docs/Supported-Devices.md
|
||||
- name: Glossary of Terms
|
||||
href: Glossary-of-Terms.md
|
||||
href: technical-docs/Glossary-of-Terms.md
|
||||
@@ -6,10 +6,10 @@ One of the most powerful features of Essentials is the ability to bridge SIMPL t
|
||||
|
||||
Follow the links below for examples of bridging to hardware and network resources.
|
||||
|
||||
**[GenericComm Bridging](~/docs/GenericComm.md)**
|
||||
**[GenericComm Bridging](~/docs/usage/GenericComm.md)**
|
||||
|
||||
**[RelayOutput Bridging](~/docs/RelayOutput.md)**
|
||||
**[RelayOutput Bridging](~/docs/usage/RelayOutput.md)**
|
||||
|
||||
**[Digital Input Bridging](~/docs/DigitalInput.md)**
|
||||
**[Digital Input Bridging](~/docs/usage/DigitalInput.md)**
|
||||
|
||||
**[Card Frame Bridging](~/docs/CardFrame.md)**
|
||||
@@ -286,7 +286,7 @@ Example device config: <https://github.com/PepperDash/Essentials/blob/main/Peppe
|
||||
|
||||
3. A bridge need not only bridge between applications on the same processor. A bridge may bridge to an application on a completely separate processor; simply define the ip address in the Bridge control properties accordingly.
|
||||
|
||||
4. For devices included in Essentials, you will be able to find defined join maps below. If you are building your own plugins, you will need to build the join map yourself. It would be beneficial to review the wiki entry on the [Feedback Class](~/docs/Feedback-Classes.md) for this.
|
||||
4. For devices included in Essentials, you will be able to find defined join maps below. If you are building your own plugins, you will need to build the join map yourself. It would be beneficial to review the wiki entry on the [Feedback Class](~/docs/technical-docs/Feedback-Classes.md) for this.
|
||||
|
||||
5. When building plugins, we highly recommend reusing JoinMaps, as this will make code more easily interchangeable. For example; if you were to build a display plugin, we'd recommend you use/extend the existing `DisplayControllerJoinMap`. This way, you can swap plugins without needing any change on the SIMPL Windows side. This is extremely powerful when maintaining SIMPL Windows code bases for large deployments that may utilize differing equipment per room. If you can build a SIMPL Windows program that interacts with established join maps, you can swap out the device via config without any change needed to SIMPL Windows.
|
||||
|
||||
@@ -302,7 +302,7 @@ Example device config: <https://github.com/PepperDash/Essentials/blob/main/Peppe
|
||||
|
||||
## Join Map Documentation
|
||||
|
||||
[Join Map Documentation](~/docs/JoinMaps.md)
|
||||
[Join Map Documentation](~/docs/usage/JoinMaps.md)
|
||||
|
||||
## Device Type Join Maps
|
||||
|
||||
@@ -408,4 +408,4 @@ Please note that these joinmaps _may_ be using a deprecated implementation. The
|
||||
|
||||
We've provided an [example program](https://github.com/PepperDash/EssentialsSIMPLWindowsBridgeExample) for SIMPL Windows that works with the provided example Essentials configuration file [SIMPLBridgeExample_configurationFile.json](https://github.com/PepperDash/Essentials/blob/main/PepperDashEssentials/Example%20Configuration/SIMPLBridging/SIMPLBridgeExample_configurationFile.json). Load Essentials and the example SIMPL program to two slots on the same processor and you can get a better idea of how to take advantage of SIMPL Windows bridging.
|
||||
|
||||
Next: [Essentials architecture](~/docs/Arch-summary.md)
|
||||
Next: [Essentials architecture](~/docs/technical-docs/Arch-summary.md)
|
||||
@@ -8,7 +8,7 @@ By defining devices and a room in a JSON configuration file, Essentials can cont
|
||||
|
||||
### Devices
|
||||
|
||||
Essentials supports device plugins for communicating with various devices using both standard Crestron CIP communications, Cresnet, SSH, or other TCP/IP-based communication methods. See [the Plugins section](~/docs/Plugins.md) for more details
|
||||
Essentials supports device plugins for communicating with various devices using both standard Crestron CIP communications, Cresnet, SSH, or other TCP/IP-based communication methods. See [the Plugins section](~/docs/technical-docs/Plugins.md) for more details
|
||||
|
||||
### Rooms
|
||||
|
||||
@@ -16,4 +16,4 @@ In order to tie together equipment into a unit that comprises what devices are u
|
||||
|
||||
See Also: [[Supported Devices|Supported-Devices]]
|
||||
|
||||
Next: [Simpl Windows bridging](~/docs/SIMPL-Bridging-Updated.md)
|
||||
Next: [Simpl Windows bridging](~/docs/usage/SIMPL-Bridging-Updated.md)
|
||||
@@ -8,12 +8,12 @@ Essentials is a collection of C# libraries that can be used in many ways. It is
|
||||
|
||||
## Get started
|
||||
|
||||
- [Download essentials build or clone repo](~/docs/Get-started.md)
|
||||
- [How to get started](~/docs/Get-started.md)
|
||||
- [Download an Essentials build or clone the repo](~/docs/Get-started.md)
|
||||
- [Get started](~/docs/Get-started.md)
|
||||
- [YouTube Video Series Playlist](https://youtube.com/playlist?list=PLKOoNNwgPFZdV5wDEBDZxTHu1KROspaBu)
|
||||
- [Discord Server](https://discord.gg/6Vh3ssDdPs)
|
||||
|
||||
Or use the links to the right to navigate our documentation.
|
||||
Or use the links to the left to navigate our documentation.
|
||||
|
||||
---
|
||||
|
||||
@@ -25,21 +25,12 @@ Or use the links to the right to navigate our documentation.
|
||||
- Shared resources made easily available
|
||||
- More flexibility with less code
|
||||
- Configurable using simple JSON files
|
||||
- Is awesome
|
||||
|
||||
---
|
||||
|
||||
## Comment
|
||||
|
||||
The Essentials wiki is clearly in-progress right now. Take a look at the links to the right. We are actively working on this documentation, so please be patient with us. If you have any comments on or suggestions for the documentation, please file an issue here, with as much detail as you can provide: <https://github.com/PepperDash/Essentials/issues>
|
||||
|
||||
Thanks!
|
||||
|
||||
---
|
||||
|
||||
## Collaboration
|
||||
|
||||
Essentials is an open-source project and we encourage collaboration on this community project. For features that may not be useful to the greater community, or for just-plain learning, we want to remind developers to try writing plugins for Essentials. More information can be found here: [Plugins](~/docs/Plugins.md)
|
||||
Essentials is an open-source project and we encourage collaboration on this community project. For features that may not be useful to the greater community, or for just-plain learning, we want to remind developers to try writing plugins for Essentials. More information can be found here: [Plugins](~/docs/technical-docs/Plugins.md)
|
||||
|
||||
### Open-source-collaborative workflow
|
||||
|
||||
@@ -52,7 +43,7 @@ The `main` branch always contain the latest stable version. The `development` br
|
||||
- Example: `feature/add-awesomeness` or `hotfix/really-big-oops`
|
||||
- When working on a new feature or bugfix, branch from the `development` branch. When working on a hotfix, branch from `main`.
|
||||
3. Make commits as necessary (often is better). And use concise, descriptive language, leveraging issue notation and/or [Closing Keywords](https://help.github.com/articles/closing-issues-using-keywords) to ensure any issues addressed by your work are referenced accordingly.
|
||||
4. When the scope of the work for your branch is complete, make sure to rebase your branch in case further progress has been made since the repo was forked
|
||||
4. When the scope of the work for your branch is complete, make sure to update your branch in case further progress has been made since the repo was forked
|
||||
5. Create a Pull Request to pull your branch into the appropriate branch in the main repository.
|
||||
6. Your Pull Request will be reviewed by our team and evaluated for inclusion into the main repository.
|
||||
|
||||
|
||||
@@ -30,6 +30,17 @@ namespace PepperDash.Essentials.Core.Bridges
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
protected BridgeApi(string key, string name) :
|
||||
base(key, name)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -58,7 +69,7 @@ namespace PepperDash.Essentials.Core.Bridges
|
||||
/// <param name="dc">Device configuration</param>
|
||||
/// <param name="eisc">EISC instance</param>
|
||||
public EiscApiAdvanced(DeviceConfig dc, BasicTriList eisc) :
|
||||
base(dc.Key)
|
||||
base(dc.Key, dc.Name)
|
||||
{
|
||||
JoinMaps = new Dictionary<string, JoinMapBaseAdvanced>();
|
||||
|
||||
|
||||
@@ -36,6 +36,35 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||
event EventHandler<WebViewStatusChangedEventArgs> WebViewStatusChanged;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Defines the contract for IHasWebViewWithPwaMode
|
||||
/// </summary>
|
||||
public interface IHasWebViewWithPwaMode : IHasWebView
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates whether the webview is currently in PWA mode
|
||||
/// </summary>
|
||||
bool IsInPwaMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the BoolFeedback indicating whether the webview is currently in PWA mode
|
||||
/// </summary>
|
||||
BoolFeedback IsInPwaModeFeedback { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Sends navigators to the specified PWA URL. Accepts an absolute URL or a relative URL for a mobile control app
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to navigate to</param>
|
||||
void SendNavigatorsToPwaUrl(string url);
|
||||
|
||||
/// <summary>
|
||||
/// Exits navigators from PWA mode
|
||||
/// </summary>
|
||||
void ExitNavigatorsPwaMode();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a WebViewStatusChangedEventArgs
|
||||
/// </summary>
|
||||
|
||||
@@ -36,8 +36,17 @@ namespace PepperDash.Essentials.Core
|
||||
{
|
||||
var programAssemblies = Directory.GetFiles(InitialParametersClass.ProgramDirectory.ToString(), "*.dll");
|
||||
|
||||
// Assemblies known to cause load errors that should be skipped
|
||||
var assembliesToSkip = new[] { "CrestronOnvif.dll" };
|
||||
|
||||
foreach (var assembly in programAssemblies)
|
||||
{
|
||||
if (assembliesToSkip.Any(a => Path.GetFileName(assembly).Equals(a, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
Debug.LogMessage(LogEventLevel.Verbose, "Skipping assembly: {assemblyName}", Path.GetFileName(assembly));
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Assembly.LoadFrom(assembly);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
@@ -21,24 +21,24 @@ namespace PepperDash.Essentials.Core
|
||||
//public int InUseCount { get { return DestinationUsingThis.Count; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of this tie line. Will either be the type of the destination port
|
||||
/// or the type of OverrideType when it is set.
|
||||
/// Gets the type of this tie line. Returns the intersection of signal types supported by both
|
||||
/// the source and destination ports (what signals can actually travel through this tie line),
|
||||
/// or the OverrideType when it is set.
|
||||
/// </summary>
|
||||
public eRoutingSignalType Type
|
||||
{
|
||||
get
|
||||
{
|
||||
if (OverrideType.HasValue) return OverrideType.Value;
|
||||
return DestinationPort.Type;
|
||||
return SourcePort.Type & DestinationPort.Type;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// Use this to override the Type property. For example, when both ports support AudioVideo
|
||||
/// but the physical cable only carries Audio or Video, setting this will limit the signal
|
||||
/// paths available to the routing algorithm without affecting the actual port types.
|
||||
/// When set, this value is used instead of the calculated intersection of source and destination types.
|
||||
/// </summary>
|
||||
public eRoutingSignalType? OverrideType { get; set; }
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace PepperDash.Essentials.Core
|
||||
/// </summary>
|
||||
/// <param name="sourcePort">The source output port.</param>
|
||||
/// <param name="destinationPort">The destination input port.</param>
|
||||
/// <param name="overrideType">The signal type to limit the link to. Overrides DestinationPort.Type for routing calculations.</param>
|
||||
/// <param name="overrideType">The signal type to limit the link to. Overrides the calculated intersection of port types for routing calculations.</param>
|
||||
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType? overrideType) :
|
||||
this(sourcePort, destinationPort)
|
||||
{
|
||||
@@ -91,7 +91,7 @@ namespace PepperDash.Essentials.Core
|
||||
/// </summary>
|
||||
/// <param name="sourcePort">The source output port.</param>
|
||||
/// <param name="destinationPort">The destination input port.</param>
|
||||
/// <param name="overrideType">The signal type to limit the link to. Overrides DestinationPort.Type for routing calculations.</param>
|
||||
/// <param name="overrideType">The signal type to limit the link to. Overrides the calculated intersection of port types for routing calculations.</param>
|
||||
public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType overrideType) :
|
||||
this(sourcePort, destinationPort)
|
||||
{
|
||||
|
||||
@@ -49,7 +49,9 @@ namespace PepperDash.Essentials.Core.Config
|
||||
public string DestinationPort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional override for the signal type of the tie line. If set, this overrides the destination port's type for routing calculations.
|
||||
/// Optional override for the signal type of the tie line. If set, this overrides the calculated
|
||||
/// intersection of source and destination port types for routing calculations. Useful when the
|
||||
/// physical cable supports fewer signal types than both ports are capable of.
|
||||
/// </summary>
|
||||
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
@@ -96,6 +98,32 @@ namespace PepperDash.Essentials.Core.Config
|
||||
return null;
|
||||
}
|
||||
|
||||
// Validate signal type compatibility
|
||||
if (OverrideType.HasValue)
|
||||
{
|
||||
// When override type is specified, both ports must support it
|
||||
if (!sourceOutputPort.Type.HasFlag(OverrideType.Value))
|
||||
{
|
||||
LogError($"Override type '{OverrideType.Value}' is not supported by source port '{SourcePort}' (type: {sourceOutputPort.Type})");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!destinationInputPort.Type.HasFlag(OverrideType.Value))
|
||||
{
|
||||
LogError($"Override type '{OverrideType.Value}' is not supported by destination port '{DestinationPort}' (type: {destinationInputPort.Type})");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Without override type, ports must have at least one common signal type flag
|
||||
if ((sourceOutputPort.Type & destinationInputPort.Type) == 0)
|
||||
{
|
||||
LogError($"Incompatible signal types: source port '{SourcePort}' (type: {sourceOutputPort.Type}) has no common signal types with destination port '{DestinationPort}' (type: {destinationInputPort.Type})");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return new TieLine(sourceOutputPort, destinationInputPort, OverrideType);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user