Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
53e7a30
fix: handle threading issues for concurrent clients joining
andrew-welker Dec 26, 2025
9d6aaa2
Initial plan
Copilot Dec 27, 2025
7ea1efb
Add raise/lower movement time configuration and banked command support
Copilot Dec 27, 2025
bd11c82
Split movement time into separate raise/lower times and remove timing…
Copilot Dec 27, 2025
ae0b2fe
Refactor timer disposal and improve code readability
Copilot Dec 27, 2025
a7ff2e8
fix: move isInUpPosition to momvement complete method, remove conditi…
erikdred Dec 27, 2025
78c9381
fix: add clientId as qp for websocket for MC
andrew-welker Dec 29, 2025
7d3f871
Merge branch 'copilot/featureadd-raise-lower-time' into mc-connection…
andrew-welker Dec 29, 2025
0c4aec1
fix: use .NET timers instead of CTimer
andrew-welker Dec 29, 2025
7ad8218
fix: fusion controller now sets only associated room custom values
andrew-welker Dec 29, 2025
3878c85
fix: use correct property name for isInUpPosition
andrew-welker Dec 29, 2025
7629921
fix: a few logging updates
ngenovese11 Dec 29, 2025
babb9a7
fix: a few logging updates
ngenovese11 Dec 29, 2025
a983e2c
fix: save config only when values change
andrew-welker Dec 30, 2025
316bb84
fix: update matrix routing inputs if endpoint online status changes
andrew-welker Dec 30, 2025
7f2bb07
fix: revert prop name to inUpPosition for screenlift messenger
andrew-welker Dec 31, 2025
57cd77f
fix: implement IKeyName for DspControlPoint
andrew-welker Dec 31, 2025
3fb30d5
Merge pull request #1373 from PepperDash/matrix-routing-isonline
ngenovese11 Dec 31, 2025
7910b79
feat: Add mute logic to ScreenLiftController
ngenovese11 Jan 1, 2026
f49901d
fix: Improve status messages in StatusMonitorCollection
ngenovese11 Jan 2, 2026
9bad3ae
fix: handle subsequent join calls and clientid/websocket client misma…
andrew-welker Jan 21, 2026
4fa7a42
Merge pull request #1376 from PepperDash/client-id-issues
ndorin Jan 21, 2026
8bc6d43
feat: add circuitType property to IOPortConfig and implement state in…
equinoy Jan 22, 2026
c0971a4
Merge remote-tracking branch 'origin/screen-lift-controller-mute-logi…
equinoy Jan 22, 2026
a7c4e2f
feat: complete XML documentation in PD Core
erikdred Jan 27, 2026
b1a5136
fix: remove buildFile.txt
erikdred Jan 27, 2026
a1029cd
fix: add param info, clean up trailing whitespace and minor formatting
erikdred Jan 27, 2026
a4759c3
fix case sensitivity issue for file searches
onryigit Feb 3, 2026
1404899
Merge pull request #1383 from onryigit/fix/case-insensitive-files
ndorin Feb 3, 2026
1fb5d3e
fix: make registering for push schedule updates optional
andrew-welker Feb 9, 2026
0764685
Merge pull request #1378 from PepperDash/xml-docs
andrew-welker Feb 9, 2026
4437074
fix: implement copilot suggestions
andrew-welker Feb 9, 2026
2924ce6
docs: complete XML documentation in Devices.Common
erikdred Jan 27, 2026
f88bb13
docs: update XML comments for Essentials Core
andrew-welker Feb 9, 2026
10579f1
Merge pull request #1380 from PepperDash/xml-docs-essentials-core
andrew-welker Feb 9, 2026
b35d2b4
Merge pull request #1379 from PepperDash/xml-docs-devices
andrew-welker Feb 9, 2026
8ff9de8
docs: reorganize and add article on working with docFx
andrew-welker Feb 9, 2026
afc5cf1
docs: update landing page and getting started
andrew-welker Feb 9, 2026
3ed0bd5
Merge branch 'main' into feature/circuittype-property-versiport
andrew-welker Feb 9, 2026
39ebf6f
Merge pull request #1377 from PepperDash/feature/circuittype-property…
ndorin Feb 9, 2026
f8a81de
Merge pull request #1385 from PepperDash/docfx-docs
ndorin Feb 9, 2026
633608c
docs: fix capitalization error in toc
andrew-welker Feb 9, 2026
9de14da
Merge pull request #1386 from PepperDash/docfx-docs
ndorin Feb 9, 2026
b40200e
feat: add IHasWebViewWithPwaMode interface with PWA navigation methods
ndorin Feb 24, 2026
a704e48
feat: add IsInPwaModeFeedback property to IHasWebViewWithPwaMode inte…
ndorin Feb 24, 2026
bd38475
Update src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasWebVie…
ndorin Feb 24, 2026
e162ed2
Update src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasWebVie…
ndorin Feb 24, 2026
963925f
Merge pull request #1388 from PepperDash/feature/add-IHasWebViewWithP…
ndorin Feb 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
13 changes: 13 additions & 0 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": 1,
"isRoot": true,
"tools": {
"csharpier": {
"version": "1.2.4",
"commands": [
"csharpier"
],
"rollForward": false
}
}
}
1 change: 1 addition & 0 deletions docs/docfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"_appLogoPath": "docs/images/favicon-32x32.png",
"_appFaviconPath": "docs/images/favicon.ico",
"_disableToc": false,
"_enableNewTab": true,
"pdf": false
}
}
Expand Down
49 changes: 35 additions & 14 deletions docs/docs/Get-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Once Essentials is running with a valid configuration, the following console commands can be used to see what's going on:

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.
* ```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/Standalone-Use.md)
Next: [Standalone use](~/docs/usage/Standalone-Use.md)
2 changes: 1 addition & 1 deletion docs/docs/Home.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/Plugins-Deprecated.md
Original file line number Diff line number Diff line change
@@ -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?

Expand Down
4 changes: 2 additions & 2 deletions docs/docs/SIMPL-Bridging-Deprecated.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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)
6 changes: 3 additions & 3 deletions docs/docs/SIMPL-Bridging.md
Original file line number Diff line number Diff line change
@@ -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#.

Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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 changes: 148 additions & 0 deletions docs/docs/how-to/how-to-add-docs.md
Original file line number Diff line number Diff line change
@@ -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: `![Alt text](../images/your-image.png)`
- 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/)
4 changes: 2 additions & 2 deletions docs/docs/Arch-1.md → docs/docs/technical-docs/Arch-1.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -38,4 +38,4 @@ This flat structure ensures that every device in a system exists in one place an

![Architecture overview](~/docs/images/arch-overview.png)

Next: [Configurable lifecycle](~/docs/Arch-lifecycle.md)
Next: [Configurable lifecycle](~/docs/technical-docs/Arch-lifecycle.md)
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)
Original file line number Diff line number Diff line change
Expand Up @@ -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))

![Lifecycle](~/docs/images/lifecycle.png)

Next: [Activation phases](~/docs/Arch-activate.md)
Next: [Activation phases](~/docs/technical-docs/Arch-activate.md)
Loading