Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
root=true

[*.cs]
indent_style=space
indent_size=2

# .editorconfig

# Define a naming style for camelCase without an underscore prefix
dotnet_naming_style.private_field_camel_case.capitalization = camel_case
dotnet_naming_style.private_field_camel_case.required_prefix =

# Define a naming rule for private fields to use the defined style
dotnet_naming_rule.private_field_no_underscore.symbols = private_fields
dotnet_naming_rule.private_field_no_underscore.style = private_field_camel_case
dotnet_naming_rule.private_field_no_underscore.severity = warning

# Define the symbol kind for private fields
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
9 changes: 9 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"recommendations": [
"ms-dotnettools.vscode-dotnet-runtime",
"ms-dotnettools.csharp",
"ms-dotnettools.csdevkit",
"vivaxy.vscode-conventional-commits",
"mhutchie.git-graph"
]
}
32 changes: 32 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"workbench.colorCustomizations": {
"activityBar.activeBackground": "#8c57e5",
"activityBar.background": "#8c57e5",
"activityBar.foreground": "#e7e7e7",
"activityBar.inactiveForeground": "#e7e7e799",
"activityBarBadge.background": "#6e3411",
"activityBarBadge.foreground": "#e7e7e7",
"commandCenter.border": "#e7e7e799",
"sash.hoverBorder": "#8c57e5",
"statusBar.background": "#6e2bde",
"statusBar.foreground": "#e7e7e7",
"statusBarItem.hoverBackground": "#8c57e5",
"statusBarItem.remoteBackground": "#6e2bde",
"statusBarItem.remoteForeground": "#e7e7e7",
"titleBar.activeBackground": "#6e2bde",
"titleBar.activeForeground": "#e7e7e7",
"titleBar.inactiveBackground": "#6e2bde99",
"titleBar.inactiveForeground": "#e7e7e799"
},
"peacock.color": "#6e2bde",
"[csharp]": {
"editor.defaultFormatter": "ms-dotnettools.csharp",
"editor.formatOnSave": true,
"editor.formatOnSaveMode": "file"
},
"csharp.inlayHints.enableInlayHintsForImplicitObjectCreation": true,
"csharp.inlayHints.enableInlayHintsForImplicitVariableTypes": true,
"csharp.inlayHints.enableInlayHintsForLambdaParameterTypes": true,
"csharp.inlayHints.enableInlayHintsForTypes": true,
"dotnet.formatting.organizeImportsOnFormat": true
}
36 changes: 12 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
![PepperDash Essentials Pluign Logo](/images/essentials-plugin-blue.png)

# Essentials Plugin Template (c) 2023
# Essentials Plugin Template (c) 2025

## License

Provided under MIT license

## Overview

Fork this repo when creating a new plugin for Essentials. For more information about plugins, refer to the Essentials Wiki [Plugins](https://github.com/PepperDash/Essentials/wiki/Plugins) article.
Fork this repo when creating a new plugin for Essentials. For more information about plugins, refer to the Essentials Wiki [Plugins](https://pepperdash.github.io/Essentials/docs/Plugins.html) article.

This repo contains example classes for the three main categories of devices:
* `EssentialsPluginTemplateDevice`: Used for most third party devices which require communication over a streaming mechanism such as a Com port, TCP/SSh/UDP socket, CEC, etc
* `EssentialsPluginTemplateLogicDevice`: Used for devices that contain logic, but don't require any communication with third parties outside the program
* `EssentialsPluginTemplateCrestronDevice`: Used for devices that represent a piece of Crestron hardware
* `MakeModelDevice`: Used for most third party devices which require communication over a streaming mechanism such as a Com port, TCP/SSh/UDP socket, CEC, etc
* `MakeModelLogicDevice`: Used for devices that contain logic, but don't require any communication with third parties outside the program
* `MakeModelCrestronDevice`: Used for devices that represent a piece of Crestron hardware

There are matching factory classes for each of the three categories of devices. The `EssentialsPluginTemplateConfigObject` should be used as a template and modified for any of the categories of device. Same goes for the `EssentialsPluginTemplateBridgeJoinMap`.
There are matching factory classes for each of the three categories of devices. The `MakeModelConfigObject` should be used as a template and modified for any of the categories of device. Same goes for the `MakeModeleBridgeJoinMap`.

This also illustrates how a plugin can contain multiple devices.

Expand All @@ -29,14 +29,7 @@ The [Essentials](https://github.com/PepperDash/Essentials) libraries are require

### Installing Dependencies

To install dependencies once nuget.exe is installed, run the following command from the root directory of your repository:
`nuget install .\packages.config -OutputDirectory .\packages -excludeVersion`.
Alternatively, you can simply run the `GetPackages.bat` file.
To verify that the packages installed correctly, open the plugin solution in your repo and make sure that all references are found, then try and build it.

### Installing Different versions of PepperDash Core

If you need a different version of PepperDash Core, use the command `nuget install .\packages.config -OutputDirectory .\packages -excludeVersion -Version {versionToGet}`. Omitting the `-Version` option will pull the version indicated in the packages.config file.
Dependencies will be automatically installed when

### Instructions for Renaming Solution and Files

Expand All @@ -46,15 +39,10 @@ For renaming instructions in particular, see the XML `remarks` tags on class def

## Build Instructions (PepperDash Internal)

## Generating Nuget Package

In the solution folder is a file named "PDT.EssentialsPluginTemplate.nuspec"

1. Rename the file to match your plugin solution name
2. Edit the file to include your project specifics including
1. <id>PepperDash.Essentials.Plugin.MakeModel</id> Convention is to use the prefix "PepperDash.Essentials.Plugin" and include the MakeModel of the device.
2. <projectUrl>https://github.com/PepperDash/EssentialsPluginTemplate</projectUrl> Change to your url to the project repo
## Generating Nuget Package

There is no longer a requirement to adjust workflow files for nuget generation for private and public repositories. This is now handled automatically in the workflow.
A nuget package is automatically generated when the plugin is build. To modify the name and other details of the package, edit the following properties in the .csproj file:

__If you do not make these changes to the nuspec file, the project will not generate a nuget package__
1. `PackageId` - This is the name that will be used to pull the package from Nuget once it's published
2. `PackgeProjectUrl` - This should match the URL for the plugin repo
3. `AssemblyTitle` - This is the dll file name that is will show on a processor when the plugin is loaded
20 changes: 0 additions & 20 deletions epi-make-model.3Series.sln

This file was deleted.

3 changes: 0 additions & 3 deletions packages.config

This file was deleted.

20 changes: 10 additions & 10 deletions src/MakeModelConfigObject.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using Newtonsoft.Json;
using PepperDash.Essentials.Core;
using System.Collections.Generic;
using Newtonsoft.Json;
using PepperDash.Essentials.Core;

namespace PepperDash.Essentials.Plugin
{
/// <summary>
Expand All @@ -14,7 +14,7 @@ namespace PepperDash.Essentials.Plugin
/// "EssentialsPluginConfigObjectTemplate" renamed to "SamsungMdcConfig"
/// </example>
[ConfigSnippet("\"properties\":{\"control\":{}")]
public class EssentialsPluginTemplateConfigObject
public class MakeModelConfig
{
/// <summary>
/// JSON control object
Expand All @@ -27,7 +27,7 @@ public class EssentialsPluginTemplateConfigObject
/// <example>
/// <code>
/// "control": {
/// "method": "tcpIp",
/// "method": "tcpIp",
/// "controlPortDevKey": "processor",
/// "controlPortNumber": 1,
/// "comParams": {
Expand Down Expand Up @@ -139,7 +139,7 @@ public class EssentialsPluginTemplateConfigObject
/// </code>
/// </example>
[JsonProperty("DeviceDictionary")]
public Dictionary<string, EssentialsPluginTemplateConfigObjectDictionary> DeviceDictionary { get; set; }
public Dictionary<string, MakeModelConfigDictionary> DeviceDictionary { get; set; }

/// <summary>
/// Constuctor
Expand All @@ -148,9 +148,9 @@ public class EssentialsPluginTemplateConfigObject
/// If using a collection you must instantiate the collection in the constructor
/// to avoid exceptions when reading the configuration file
/// </remarks>
public EssentialsPluginTemplateConfigObject()
public MakeModelConfig()
{
DeviceDictionary = new Dictionary<string, EssentialsPluginTemplateConfigObjectDictionary>();
DeviceDictionary = new Dictionary<string, MakeModelConfigDictionary>();
}
}

Expand All @@ -172,7 +172,7 @@ public EssentialsPluginTemplateConfigObject()
/// }
/// </code>
/// </example>
public class EssentialsPluginTemplateConfigObjectDictionary
public class MakeModelConfigDictionary
{
/// <summary>
/// Serializes collection name property
Expand Down
53 changes: 25 additions & 28 deletions src/MakeModelCrestronDevice.cs
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
// For Basic SIMPL# Classes
// For Basic SIMPL#Pro classes
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
// For Basic SIMPL#Pro classes

using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;

namespace PepperDash.Essentials.Plugin
{
/// <summary>
/// Plugin device
/// </summary>
/// <remarks>
/// Rename the class to match the device plugin being developed.
/// </remarks>
/// <example>
/// "EssentialsPluginDeviceTemplate" renamed to "SamsungMdcDevice"
/// </example>
public class EssentialsPluginTemplateCrestronDevice : CrestronGenericBridgeableBaseDevice
/// <summary>
/// Plugin device
/// </summary>
/// <remarks>
/// Rename the class to match the device plugin being developed.
/// </remarks>
/// <example>
/// "EssentialsPluginDeviceTemplate" renamed to "SamsungMdcDevice"
/// </example>
public class MakeModelCrestronDevice : CrestronGenericBridgeableBaseDevice
{
/// <summary>
/// It is often desirable to store the config
/// </summary>
private EssentialsPluginTemplateConfigObject _config;
private readonly MakeModelConfig config;


#region Constructor for Devices without IBasicCommunication. Remove if not needed
Expand All @@ -34,16 +34,16 @@ public class EssentialsPluginTemplateCrestronDevice : CrestronGenericBridgeableB
/// <param name="name"></param>
/// <param name="config"></param>
/// <param name="hardware"></param>
public EssentialsPluginTemplateCrestronDevice(string key, string name, EssentialsPluginTemplateConfigObject config, GenericBase hardware)
public MakeModelCrestronDevice(string key, string name, MakeModelConfig config, GenericBase hardware)
: base(key, name, hardware)
{
Debug.Console(0, this, "Constructing new {0} instance", name);
this.LogInformation("Constructing new {0} instance", name);

// The base class takes care of registering the hardware device for you

// TODO [ ] Update the constructor as needed for the plugin device being developed

_config = config;
this.config = config;
}

#endregion
Expand All @@ -63,10 +63,7 @@ public override void LinkToApi(BasicTriList trilist, uint joinStart, string join
var joinMap = new EssentialsPluginTemplateBridgeJoinMap(joinStart);

// This adds the join map to the collection on the bridge
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
bridge?.AddJoinMap(Key, joinMap);

var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey);

Expand All @@ -75,8 +72,8 @@ public override void LinkToApi(BasicTriList trilist, uint joinStart, string join
joinMap.SetCustomJoinData(customJoins);
}

Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, "Linking to Bridge Type {0}", GetType().Name);
this.LogDebug("Linking to Trilist {id}", trilist.ID.ToString("X"));
this.LogInformation("Linking to Bridge Type {type}", GetType().Name);

// TODO [ ] Implement bridge links as needed

Expand Down
87 changes: 87 additions & 0 deletions src/MakeModelCrestronDeviceFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System.Collections.Generic;
using Crestron.SimplSharpPro.UI;
using PepperDash.Core;
using PepperDash.Essentials.Core;

namespace PepperDash.Essentials.Plugin
{

/// <summary>
/// Plugin device factory for Crestron wrapper devices
/// </summary>
/// <remarks>
/// Rename the class to match the device plugin being developed
/// </remarks>
/// <example>
/// "EssentialsPluginFactoryTemplate" renamed to "MyCrestronDeviceFactory"
/// </example>
public class MakeModelCrestronDeviceFactory : EssentialsPluginDeviceFactory<MakeModelCrestronDevice>
{
/// <summary>
/// Plugin device factory constructor
/// </summary>
/// <remarks>
/// Update the MinimumEssentialsFrameworkVersion & TypeNames as needed when creating a plugin
/// </remarks>
/// <example>
/// Set the minimum Essentials Framework Version
/// <code>
/// MinimumEssentialsFrameworkVersion = "1.6.4;
/// </code>
/// In the constructor we initialize the list with the typenames that will build an instance of this device
/// <code>
/// TypeNames = new List<string>() { "SamsungMdc", "SamsungMdcDisplay" };
/// </code>
/// </example>
public MakeModelCrestronDeviceFactory()
{
// Set the minimum Essentials Framework Version
// TODO [ ] Update the Essentials minimum framework version which this plugin has been tested against
MinimumEssentialsFrameworkVersion = "2.12.1";

// In the constructor we initialize the list with the typenames that will build an instance of this device
// TODO [ ] Update the TypeNames for the plugin being developed
TypeNames = new List<string>() { "examplePluginCrestronDevice" };
}

/// <summary>
/// Builds and returns an instance of EssentialsPluginTemplateCrestronDevice
/// </summary>
/// <param name="dc">device configuration</param>
/// <returns>plugin device or null</returns>
/// <remarks>
/// The example provided below takes the device key, name, properties config and the comms device created.
/// Modify the EssetnialsPlugingDeviceTemplate constructor as needed to meet the requirements of the plugin device.
/// </remarks>
/// <seealso cref="PepperDash.Core.eControlMethod"/>
public override EssentialsDevice BuildDevice(PepperDash.Essentials.Core.Config.DeviceConfig dc)
{

Debug.LogDebug("[{key}] Factory Attempting to create new device from type: {type}", dc.Key, dc.Type);

// get the plugin device properties configuration object & check for null
var propertiesConfig = dc.Properties.ToObject<MakeModelConfig>();
if (propertiesConfig == null)
{
Debug.LogWarning("[{key}] Factory: failed to read properties config for {name}", dc.Key, dc.Name);
return null;
}

var controlConfig = CommFactory.GetControlPropertiesConfig(dc);

if (controlConfig != null)
{
var myTouchpanel = new Tsw760(controlConfig.IpIdInt, Global.ControlSystem);

return new MakeModelCrestronDevice(dc.Key, dc.Name, propertiesConfig, myTouchpanel);
}
else
{
Debug.LogWarning("[{key}] Factory: Unable to get control properties from device config for {name}", dc.Key, dc.Name);
return null;
}
}
}

}

Loading