Compare commits

..

No commits in common. "v2.0.0-remove-3series.2" and "1.0.3-alpha-20" have entirely different histories.

35 changed files with 852 additions and 1352 deletions

View file

@ -1,20 +0,0 @@
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

View file

@ -1,17 +0,0 @@
---
name: Essentials Plugin Request
about: Request an Essentials Plugin
title: "[REQUEST] - "
labels: plugin request
assignees: ''
---
** Describe the Plugin **
What do you want the plugin to do? Is it for a specific device? If it's for a specific device, include the manufacturer and model, along with links to API documentation if available.
** Does it need to be available in SIMPL Windows? **
If it does, describe the functionality that should be exposed to SIMPL Windows via EISC. This may include an example join map, or other way of documenting the layout of the EISC.
** Additional Features or functionality **
Describe additional features or functionality that this plugin should have.

View file

@ -7,8 +7,7 @@ Foreach ($version in $latestVersions) {
$latestVersion = $version $latestVersion = $version
Write-Host "Setting latest version to: $latestVersion" Write-Host "Setting latest version to: $latestVersion"
} }
} } catch {
catch {
Write-Host "Unable to convert $($version). Skipping" Write-Host "Unable to convert $($version). Skipping"
continue; continue;
} }
@ -19,19 +18,17 @@ $phase = ""
$newVersionString = "" $newVersionString = ""
switch -regex ($Env:GITHUB_REF) { switch -regex ($Env:GITHUB_REF) {
'^refs\/heads\/main*.' { '^refs\/heads\/main*.' {
$newVersionString = "{0}.{1}.{2}" -f $newVersion.Major, $newVersion.Minor, $newVersion.Build $newVersionString = "{0}.{1}.{2}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1)
} }
'^refs\/heads\/feature\/*.' { '^refs\/heads\/feature\/*.' {
$phase = 'alpha' $phase = 'alpha'
$newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER $newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER
} }
'^refs\/heads\/release\/*.' { '^refs\/heads\/release\/*.' {
$splitRef = $Env:GITHUB_REF -split "/"
$version = [version]($splitRef[-1] -replace "v", "")
$phase = 'rc' $phase = 'rc'
$newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $version.Major, $version.Minor, $version.Build, $phase, $Env:GITHUB_RUN_NUMBER $newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER
} }
'^refs\/heads\/dev*.' { '^refs\/heads\/development*.' {
$phase = 'beta' $phase = 'beta'
$newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER $newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER
} }

View file

@ -10,7 +10,7 @@ Get-ChildItem ($destination)
$exclusions = @(git submodule foreach --quiet 'echo $name') $exclusions = @(git submodule foreach --quiet 'echo $name')
# Trying to get any .json schema files (not currently working) # Trying to get any .json schema files (not currently working)
# Gets any files with the listed extensions. # Gets any files with the listed extensions.
Get-ChildItem -recurse -Path "$($Env:GITHUB_WORKSPACE)" -include "*.cplz" | ForEach-Object { Get-ChildItem -recurse -Path "$($Env:GITHUB_WORKSPACE)" -include "*.clz", "*.cpz", "*.cplz" | ForEach-Object {
$allowed = $true; $allowed = $true;
# Exclude any files in submodules # Exclude any files in submodules
foreach ($exclude in $exclusions) { foreach ($exclude in $exclusions) {
@ -36,7 +36,6 @@ Get-ChildItem -Path $destination | Where-Object {($_.Extension -eq ".clz") -or (
Get-ChildItem -Recurse -Path "$($Env:GITHUB_WORKSPACE)" -include $filenames | Copy-Item -Destination ($destination) -Force Get-ChildItem -Recurse -Path "$($Env:GITHUB_WORKSPACE)" -include $filenames | Copy-Item -Destination ($destination) -Force
} }
} }
Get-ChildItem -Path $destination\*.cplz | Rename-Item -NewName { "$($_.BaseName)-$($Env:VERSION)$($_.Extension)" }
Compress-Archive -Path $destination -DestinationPath "$($Env:GITHUB_WORKSPACE)\$($Env:SOLUTION_FILE)-$($Env:VERSION).zip" -Force Compress-Archive -Path $destination -DestinationPath "$($Env:GITHUB_WORKSPACE)\$($Env:SOLUTION_FILE)-$($Env:VERSION).zip" -Force
Write-Host "Output Contents post Zip" Write-Host "Output Contents post Zip"
Get-ChildItem -Path $destination Get-ChildItem -Path $destination

View file

@ -1,22 +0,0 @@
name: Build Essentials Plugin
on:
push:
branches:
- '**'
jobs:
getVersion:
uses: PepperDash/workflow-templates/.github/workflows/essentialsplugins-getversion.yml@main
secrets: inherit
build-4Series:
uses: PepperDash/workflow-templates/.github/workflows/essentialsplugins-4Series-builds.yml@main
secrets: inherit
needs: getVersion
if: needs.getVersion.outputs.newVersion == 'true'
with:
newVersion: ${{ needs.getVersion.outputs.newVersion }}
version: ${{ needs.getVersion.outputs.version }}
tag: ${{ needs.getVersion.outputs.tag }}
channel: ${{ needs.getVersion.outputs.channel }}

103
.github/workflows/docker.yml vendored Normal file
View file

@ -0,0 +1,103 @@
name: Branch Build Using Docker
on:
push:
branches:
- feature/*
- hotfix/*
- release/*
- main
- development
env:
# solution path doesn't need slashes unless there it is multiple folders deep
# solution name does not include extension. .sln is assumed
SOLUTION_PATH: PDT.EssentialsPluginTemplate.EPI
SOLUTION_FILE: PDT.EssentialsPluginTemplate.EPI
# Do not edit this, we're just creating it here
VERSION: 0.0.0-buildtype-buildnumber
# Defaults to debug for build type
BUILD_TYPE: Debug
# Defaults to main as the release branch. Change as necessary
RELEASE_BRANCH: main
jobs:
Build_Project:
runs-on: windows-latest
steps:
# First we checkout the source repo
- name: Checkout repo
uses: actions/checkout@v2
with:
fetch-depth: 0
# And any submodules
- name: Checkout submodules
shell: bash
run: |
git config --global url."https://github.com/".insteadOf "git@github.com:"
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
git submodule sync --recursive
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
# Set the BUILD_TYPE environment variable
- name: Set Build to Release if triggered from main
run: |
if("$($Env:GITHUB_REF)".contains("$($Env:RELEASE_BRANCH)")) {
Write-Host "Setting build type to Release"
Write-Output "::set-env name=BUILD_TYPE::Release"
}
# Fetch all tags
- name: Fetch tags
run: git fetch --tags
# Generate the appropriate version number
- name: Set Version Number
shell: powershell
run: |
$version = ./.github/scripts/GenerateVersionNumber.ps1
Write-Output "::set-env name=VERSION::$version"
# Use the version number to set the version of the assemblies
- name: Update AssemblyInfo.cs
shell: powershell
run: |
Write-Output ${{ env.VERSION }}
./.github/scripts/UpdateAssemblyVersion.ps1 ${{ env.VERSION }}
- name: restore Nuget Packages
run: nuget install .\packages.config -OutputDirectory .\packages -ExcludeVersion
- name: Login to Docker
uses: azure/docker-login@v1
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
# Build the solutions in the docker image
- name: Build Solution
shell: powershell
run: |
Invoke-Expression "docker run --rm --mount type=bind,source=""$($Env:GITHUB_WORKSPACE)"",target=""c:/project"" pepperdash/sspbuilder c:\cihelpers\vsidebuild.exe -Solution ""c:\project\$($Env:SOLUTION_PATH)\$($Env:SOLUTION_FILE).sln"" -BuildSolutionConfiguration $($ENV:BUILD_TYPE)"
# Zip up the output files as needed
- name: Zip Build Output
shell: powershell
run: ./.github/scripts/ZipBuildOutput.ps1
- name: Upload Build Output
uses: actions/upload-artifact@v1
with:
name: Build
path: ./${{ env.SOLUTION_FILE}}-${{ env.VERSION}}.zip
# Create the release on the source repo
- name: Create Release
id: create_release
uses: actions/create-release@v1
with:
tag_name: ${{ env.VERSION }}
release_name: ${{ env.VERSION }}
prerelease: ${{contains('debug', env.BUILD_TYPE)}}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Upload the build package to the release
- name: Upload Release Package
id: upload_release
uses: actions/upload-release-asset@v1
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./${{ env.SOLUTION_FILE}}-${{ env.VERSION}}.zip
asset_name: ${{ env.SOLUTION_FILE}}-${{ env.VERSION}}.zip
asset_content_type: application/zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -1,14 +0,0 @@
name: Generate README
on:
push:
branches-ignore:
- 'robot-docs'
jobs:
call-update-readme:
uses: PepperDash/workflow-templates/.github/workflows/update-readme.yml@main
with:
target-branch: ${{ github.ref_name }}

View file

@ -1,34 +0,0 @@
{
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"releaseRules": [
{ "scope": "force-patch", "release": "patch" },
{ "scope": "no-release", "release": false }
]
}
],
"@semantic-release/release-notes-generator",
["@semantic-release/changelog",
{
"changelogFile": "CHANGELOG.md"
}
],
[
"@semantic-release/exec",
{
"verifyReleaseCmd": "echo \"newVersion=true\" >> $GITHUB_OUTPUT",
"publishCmd": "echo \"version=${nextRelease.version}\" >> $GITHUB_OUTPUT && echo \"tag=${nextRelease.gitTag}\" >> $GITHUB_OUTPUT && echo \"type=${nextRelease.type}\" >> $GITHUB_OUTPUT && echo \"channel=${nextRelease.channel}\" >> $GITHUB_OUTPUT"
}
]
],
"branches": [
"main",
{
"name": "replace-me-feature-branch",
"prerelease": "replace-me-prerelease",
"channel": "replace-me-prerelease"
}
]
}

View file

@ -1,9 +0,0 @@
{
"recommendations": [
"ms-dotnettools.vscode-dotnet-runtime",
"ms-dotnettools.csharp",
"ms-dotnettools.csdevkit",
"vivaxy.vscode-conventional-commits",
"mhutchie.git-graph"
]
}

32
.vscode/settings.json vendored
View file

@ -1,32 +0,0 @@
{
"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
}

View file

@ -1,2 +0,0 @@
@Echo ON
nuget install .\packages.config -OutputDirectory .\packages -excludeVersion

View file

@ -1,101 +1,101 @@
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Plugin namespace EssentialsPluginTemplate
{ {
/// <summary> /// <summary>
/// Plugin device Bridge Join Map /// Plugin device Bridge Join Map
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Rename the class to match the device plugin being developed. Reference Essentials JoinMaps, if one exists for the device plugin being developed /// Rename the class to match the device plugin being developed. Reference Essentials JoinMaps, if one exists for the device plugin being developed
/// </remarks> /// </remarks>
/// <see cref="PepperDash.Essentials.Core.Bridges"/> /// <see cref="PepperDash.Essentials.Core.Bridges"/>
/// <example> /// <example>
/// "EssentialsPluginBridgeJoinMapTemplate" renamed to "SamsungMdcBridgeJoinMap" /// "EssentialsPluginBridgeJoinMapTemplate" renamed to "SamsungMdcBridgeJoinMap"
/// </example> /// </example>
public class EssentialsPluginTemplateBridgeJoinMap : JoinMapBaseAdvanced public class EssentialsPluginBridgeJoinMapTemplate : JoinMapBaseAdvanced
{ {
#region Digital #region Digital
// TODO [ ] Add digital joins below plugin being developed // TODO [ ] Add digital joins below plugin being developed
[JoinName("IsOnline")] [JoinName("IsOnline")]
public JoinDataComplete IsOnline = new JoinDataComplete( public JoinDataComplete IsOnline = new JoinDataComplete(
new JoinData new JoinData
{ {
JoinNumber = 1, JoinNumber = 1,
JoinSpan = 1 JoinSpan = 1
}, },
new JoinMetadata new JoinMetadata
{ {
Description = "Is Online", Description = "Is Online",
JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("Connect")] [JoinName("Connect")]
public JoinDataComplete Connect = new JoinDataComplete( public JoinDataComplete Connect = new JoinDataComplete(
new JoinData new JoinData
{ {
JoinNumber = 2, JoinNumber = 2,
JoinSpan = 1 JoinSpan = 1
}, },
new JoinMetadata new JoinMetadata
{ {
Description = "Connect (Held)/Disconnect (Release) & corresponding feedback", Description = "Connect (Held)/Disconnect (Release) & corresponding feedback",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
#endregion #endregion
#region Analog #region Analog
// TODO [ ] Add analog joins below plugin being developed // TODO [ ] Add analog joins below plugin being developed
[JoinName("Status")] [JoinName("Status")]
public JoinDataComplete Status = new JoinDataComplete( public JoinDataComplete Status = new JoinDataComplete(
new JoinData new JoinData
{ {
JoinNumber = 1, JoinNumber = 1,
JoinSpan = 1 JoinSpan = 1
}, },
new JoinMetadata new JoinMetadata
{ {
Description = "Socket Status", Description = "Socket Status",
JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Analog JoinType = eJoinType.Analog
}); });
#endregion #endregion
#region Serial #region Serial
// TODO [ ] Add serial joins below plugin being developed // TODO [ ] Add serial joins below plugin being developed
public JoinDataComplete DeviceName = new JoinDataComplete( public JoinDataComplete DeviceName = new JoinDataComplete(
new JoinData new JoinData
{ {
JoinNumber = 1, JoinNumber = 1,
JoinSpan = 1 JoinSpan = 1
}, },
new JoinMetadata new JoinMetadata
{ {
Description = "Device Name", Description = "Device Name",
JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial JoinType = eJoinType.Serial
}); });
#endregion #endregion
/// <summary> /// <summary>
/// Plugin device BridgeJoinMap constructor /// Plugin device BridgeJoinMap constructor
/// </summary> /// </summary>
/// <param name="joinStart">This will be the join it starts on the EISC bridge</param> /// <param name="joinStart">This will be the join it starts on the EISC bridge</param>
public EssentialsPluginTemplateBridgeJoinMap(uint joinStart) public EssentialsPluginBridgeJoinMapTemplate(uint joinStart)
: base(joinStart, typeof(EssentialsPluginTemplateBridgeJoinMap)) : base(joinStart, typeof(EssentialsPluginBridgeJoinMapTemplate))
{ {
} }
} }
} }

View file

@ -1,195 +1,195 @@
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json; using Newtonsoft.Json;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Plugin namespace EssentialsPluginTemplate
{ {
/// <summary> /// <summary>
/// Plugin device configuration object /// Plugin device configuration object
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Rename the class to match the device plugin being created /// Rename the class to match the device plugin being created
/// </remarks> /// </remarks>
/// <example> /// <example>
/// "EssentialsPluginConfigObjectTemplate" renamed to "SamsungMdcConfig" /// "EssentialsPluginConfigObjectTemplate" renamed to "SamsungMdcConfig"
/// </example> /// </example>
[ConfigSnippet("\"properties\":{\"control\":{}")] [ConfigSnippet("\"properties\":{\"control\":{}")]
public class MakeModelConfig public class EssentialsPluginConfigObjectTemplate
{ {
/// <summary> /// <summary>
/// JSON control object /// JSON control object
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Typically this object is not required, but in some instances it may be needed. For example, when building a /// Typically this object is not required, but in some instances it may be needed. For example, when building a
/// plugin that is using Telnet (TCP/IP) communications and requires login, the device will need to handle the login. /// plugin that is using Telnet (TCP/IP) communications and requires login, the device will need to handle the login.
/// In order to do so, you will need the username and password in the "tcpSshProperties" object. /// In order to do so, you will need the username and password in the "tcpSshProperties" object.
/// </remarks> /// </remarks>
/// <example> /// <example>
/// <code> /// <code>
/// "control": { /// "control": {
/// "method": "tcpIp", /// "method": "tcpIp",
/// "controlPortDevKey": "processor", /// "controlPortDevKey": "processor",
/// "controlPortNumber": 1, /// "controlPortNumber": 1,
/// "comParams": { /// "comParams": {
/// "baudRate": 9600, /// "baudRate": 9600,
/// "dataBits": 8, /// "dataBits": 8,
/// "stopBits": 1, /// "stopBits": 1,
/// "parity": "None", /// "parity": "None",
/// "protocol": "RS232", /// "protocol": "RS232",
/// "hardwareHandshake": "None", /// "hardwareHandshake": "None",
/// "softwareHandshake": "None" /// "softwareHandshake": "None"
/// }, /// },
/// "tcpSshProperties": { /// "tcpSshProperties": {
/// "address": "172.22.0.101", /// "address": "172.22.0.101",
/// "port": 23, /// "port": 23,
/// "username": "admin", /// "username": "admin",
/// "password": "password", /// "password": "password",
/// "autoReconnect": true, /// "autoReconnect": true,
/// "autoReconnectIntervalMs": 10000 /// "autoReconnectIntervalMs": 10000
/// } /// }
/// } /// }
/// </code> /// </code>
/// </example> /// </example>
[JsonProperty("control")] [JsonProperty("control")]
public EssentialsControlPropertiesConfig Control { get; set; } public EssentialsControlPropertiesConfig Control { get; set; }
/// <summary> /// <summary>
/// Serializes the poll time value /// Serializes the poll time value
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This is an exmaple device plugin property. This should be modified or deleted as needed for the plugin being built. /// This is an exmaple device plugin property. This should be modified or deleted as needed for the plugin being built.
/// </remarks> /// </remarks>
/// <value> /// <value>
/// PollTimeMs property gets/sets the value as a long /// PollTimeMs property gets/sets the value as a long
/// </value> /// </value>
/// <example> /// <example>
/// <code> /// <code>
/// "properties": { /// "properties": {
/// "polltimeMs": 30000 /// "polltimeMs": 30000
/// } /// }
/// </code> /// </code>
/// </example> /// </example>
[JsonProperty("pollTimeMs")] [JsonProperty("pollTimeMs")]
public long PollTimeMs { get; set; } public long PollTimeMs { get; set; }
/// <summary> /// <summary>
/// Serializes the warning timeout value /// Serializes the warning timeout value
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This is an exmaple device plugin property. This should be modified or deleted as needed for the plugin being built. /// This is an exmaple device plugin property. This should be modified or deleted as needed for the plugin being built.
/// </remarks> /// </remarks>
/// <value> /// <value>
/// WarningTimeoutMs property gets/sets the value as a long /// WarningTimeoutMs property gets/sets the value as a long
/// </value> /// </value>
/// <example> /// <example>
/// <code> /// <code>
/// "properties": { /// "properties": {
/// "warningTimeoutMs": 180000 /// "warningTimeoutMs": 180000
/// } /// }
/// </code> /// </code>
/// </example> /// </example>
[JsonProperty("warningTimeoutMs")] [JsonProperty("warningTimeoutMs")]
public long WarningTimeoutMs { get; set; } public long WarningTimeoutMs { get; set; }
/// <summary> /// <summary>
/// Serializes the error timeout value /// Serializes the error timeout value
/// </summary> /// </summary>
/// /// <remarks> /// /// <remarks>
/// This is an exmaple device plugin property. This should be modified or deleted as needed for the plugin being built. /// This is an exmaple device plugin property. This should be modified or deleted as needed for the plugin being built.
/// </remarks> /// </remarks>
/// <value> /// <value>
/// ErrorTimeoutMs property gets/sets the value as a long /// ErrorTimeoutMs property gets/sets the value as a long
/// </value> /// </value>
/// <example> /// <example>
/// <code> /// <code>
/// "properties": { /// "properties": {
/// "errorTimeoutMs": 300000 /// "errorTimeoutMs": 300000
/// } /// }
/// </code> /// </code>
/// </example> /// </example>
[JsonProperty("errorTimeoutMs")] [JsonProperty("errorTimeoutMs")]
public long ErrorTimeoutMs { get; set; } public long ErrorTimeoutMs { get; set; }
/// <summary> /// <summary>
/// Example dictionary of objects /// Example dictionary of objects
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This is an example collection configuration object. This should be modified or deleted as needed for the plugin being built. /// This is an example collection configuration object. This should be modified or deleted as needed for the plugin being built.
/// </remarks> /// </remarks>
/// <example> /// <example>
/// <code> /// <code>
/// "properties": { /// "properties": {
/// "presets": { /// "presets": {
/// "preset1": { /// "preset1": {
/// "enabled": true, /// "enabled": true,
/// "name": "Preset 1" /// "name": "Preset 1"
/// } /// }
/// } /// }
/// } /// }
/// </code> /// </code>
/// </example> /// </example>
/// <example> /// <example>
/// <code> /// <code>
/// "properties": { /// "properties": {
/// "inputNames": { /// "inputNames": {
/// "input1": "Input 1", /// "input1": "Input 1",
/// "input2": "Input 2" /// "input2": "Input 2"
/// } /// }
/// } /// }
/// </code> /// </code>
/// </example> /// </example>
[JsonProperty("DeviceDictionary")] [JsonProperty("DeviceDictionary")]
public Dictionary<string, MakeModelConfigDictionary> DeviceDictionary { get; set; } public Dictionary<string, EssentialsPluginConfigObjectDictionaryTemplate> DeviceDictionary { get; set; }
/// <summary> /// <summary>
/// Constuctor /// Constuctor
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// If using a collection you must instantiate the collection in the constructor /// If using a collection you must instantiate the collection in the constructor
/// to avoid exceptions when reading the configuration file /// to avoid exceptions when reading the configuration file
/// </remarks> /// </remarks>
public MakeModelConfig() public EssentialsPluginConfigObjectTemplate()
{ {
DeviceDictionary = new Dictionary<string, MakeModelConfigDictionary>(); DeviceDictionary = new Dictionary<string, EssentialsPluginConfigObjectDictionaryTemplate>();
} }
} }
/// <summary> /// <summary>
/// Example plugin configuration dictionary object /// Example plugin configuration dictionary object
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This is an example collection of configuration objects. This can be modified or deleted as needed for the plugin being built. /// This is an example collection of configuration objects. This can be modified or deleted as needed for the plugin being built.
/// </remarks> /// </remarks>
/// <example> /// <example>
/// <code> /// <code>
/// "properties": { /// "properties": {
/// "dictionary": { /// "dictionary": {
/// "item1": { /// "item1": {
/// "name": "Item 1 Name", /// "name": "Item 1 Name",
/// "value": "Item 1 Value" /// "value": "Item 1 Value"
/// } /// }
/// } /// }
/// } /// }
/// </code> /// </code>
/// </example> /// </example>
public class MakeModelConfigDictionary public class EssentialsPluginConfigObjectDictionaryTemplate
{ {
/// <summary> /// <summary>
/// Serializes collection name property /// Serializes collection name property
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This is an example collection of configuration objects. This can be modified or deleted as needed for the plugin being built. /// This is an example collection of configuration objects. This can be modified or deleted as needed for the plugin being built.
/// </remarks> /// </remarks>
[JsonProperty("name")] [JsonProperty("name")]
public string Name { get; set; } public string Name { get; set; }
/// <summary> /// <summary>
/// Serializes collection value property /// Serializes collection value property
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This is an example collection of configuration objects. This can be modified or deleted as needed for the plugin being built. /// This is an example collection of configuration objects. This can be modified or deleted as needed for the plugin being built.
/// </remarks> /// </remarks>
[JsonProperty("value")] [JsonProperty("value")]
public uint Value { get; set; } public uint Value { get; set; }
} }
} }

View file

@ -1,294 +1,246 @@
// For Basic SIMPL# Classes // For Basic SIMPL# Classes
// For Basic SIMPL#Pro classes // For Basic SIMPL#Pro classes
using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Core.Logging; using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Queues; namespace EssentialsPluginTemplate
{
namespace PepperDash.Essentials.Plugin /// <summary>
{ /// Plugin device
/// <summary> /// </summary>
/// Plugin device template for third party devices that use IBasicCommunication /// <remarks>
/// </summary> /// Rename the class to match the device plugin being developed.
/// <remarks> /// </remarks>
/// Rename the class to match the device plugin being developed. /// <example>
/// </remarks> /// "EssentialsPluginDeviceTemplate" renamed to "SamsungMdcDevice"
/// <example> /// </example>
/// "EssentialsPluginDeviceTemplate" renamed to "SamsungMdcDevice" public class EssentialsPluginDeviceTemplate : EssentialsBridgeableDevice
/// </example> {
public class MakeModelDevice : EssentialsBridgeableDevice // TODO [ ] Add, modify, remove properties and fields as needed for the plugin being developed
{ private readonly IBasicCommunication _comms;
/// <summary> private readonly GenericCommunicationMonitor _commsMonitor;
/// It is often desirable to store the config
/// </summary> // _comms gather for ASCII based API's
private readonly MakeModelConfig config; // TODO [ ] If not using an ASCII based API, delete the properties below
private readonly CommunicationGather _commsGather;
/// <summary> private const string CommsDelimiter = "\r";
/// Provides a queue and dedicated worker thread for processing feedback messages from a device.
/// </summary> // _comms byte buffer for HEX/byte based API's
private readonly GenericQueue receiveQueue; // TODO [ ] If not using an HEX/byte based API, delete the properties below
private byte[] _commsByteBuffer = { };
#region IBasicCommunication Properties and Constructor. Remove if not needed.
// TODO [ ] Add, modify, remove properties and fields as needed for the plugin being developed private EssentialsPluginConfigObjectTemplate _config;
private readonly IBasicCommunication comms;
private readonly GenericCommunicationMonitor commsMonitor; /// <summary>
/// Connects/disconnects the comms of the plugin device
// comms gather for ASCII based API's /// </summary>
// TODO [ ] If not using an ASCII based API, delete the properties below /// <remarks>
private readonly CommunicationGather commsGather; /// triggers the _comms.Connect/Disconnect as well as thee comms monitor start/stop
/// </remarks>
/// <summary> public bool Connect
/// Set this value to that of the delimiter used by the API (if applicable) {
/// </summary> get { return _comms.IsConnected; }
private const string commsDelimiter = "\r"; set
{
// comms byte buffer for HEX/byte based API's if (value)
// TODO [ ] If not using an HEX/byte based API, delete the properties below {
private readonly byte[] commsByteBuffer = { }; _comms.Connect();
_commsMonitor.Start();
}
else
/// <summary> {
/// Connects/disconnects the comms of the plugin device _comms.Disconnect();
/// </summary> _commsMonitor.Stop();
/// <remarks> }
/// triggers the comms.Connect/Disconnect as well as thee comms monitor start/stop }
/// </remarks> }
public bool Connect
{ /// <summary>
get { return comms.IsConnected; } /// Reports connect feedback through the bridge
set /// </summary>
{ public BoolFeedback ConnectFeedback { get; private set; }
if (value)
{ /// <summary>
comms.Connect(); /// Reports online feedback through the bridge
commsMonitor.Start(); /// </summary>
} public BoolFeedback OnlineFeedback { get; private set; }
else
{ /// <summary>
comms.Disconnect(); /// Reports socket status feedback through the bridge
commsMonitor.Stop(); /// </summary>
} public IntFeedback StatusFeedback { get; private set; }
}
} /// <summary>
/// Plugin device constructor
/// <summary> /// </summary>
/// Reports connect feedback through the bridge /// <param name="key"></param>
/// </summary> /// <param name="name"></param>
public BoolFeedback ConnectFeedback { get; private set; } /// <param name="config"></param>
/// <param name="comms"></param>
/// <summary> public EssentialsPluginDeviceTemplate(string key, string name, EssentialsPluginConfigObjectTemplate config, IBasicCommunication comms)
/// Reports online feedback through the bridge : base(key, name)
/// </summary> {
public BoolFeedback OnlineFeedback { get; private set; } Debug.Console(0, this, "Constructing new {0} instance", name);
/// <summary> // TODO [ ] Update the constructor as needed for the plugin device being developed
/// Reports socket status feedback through the bridge
/// </summary> _config = config;
public IntFeedback StatusFeedback { get; private set; }
ConnectFeedback = new BoolFeedback(() => Connect);
/// <summary> OnlineFeedback = new BoolFeedback(() => _commsMonitor.IsOnline);
/// Plugin device constructor for devices that need IBasicCommunication StatusFeedback = new IntFeedback(() => (int)_commsMonitor.Status);
/// </summary>
/// <param name="key"></param> _comms = comms;
/// <param name="name"></param> _commsMonitor = new GenericCommunicationMonitor(this, _comms, _config.PollTimeMs, _config.WarningTimeoutMs, _config.ErrorTimeoutMs, Poll);
/// <param name="config"></param>
/// <param name="comms"></param> var socket = _comms as ISocketStatus;
public MakeModelDevice(string key, string name, MakeModelConfig config, IBasicCommunication comms) if (socket != null)
: base(key, name) {
{ // device comms is IP **ELSE** device comms is RS232
this.LogInformation("Constructing new {0} instance", name); socket.ConnectionChange += socket_ConnectionChange;
Connect = true;
// TODO [ ] Update the constructor as needed for the plugin device being developed }
this.config = config; // _comms gather for ASCII based API's
// TODO [ ] If not using an ASCII based API, delete the properties below
receiveQueue = new GenericQueue(key + "-rxqueue"); // If you need to set the thread priority, use one of the available overloaded constructors. _commsGather = new CommunicationGather(_comms, CommsDelimiter);
AddPostActivationAction(() => _commsGather.LineReceived += Handle_LineRecieved);
ConnectFeedback = new BoolFeedback("connect", () => Connect);
OnlineFeedback = new BoolFeedback("online", () => commsMonitor.IsOnline); // _comms byte buffer for HEX/byte based API's
StatusFeedback = new IntFeedback("status", () => (int)commsMonitor.Status); // TODO [ ] If not using an HEX/byte based API, delete the properties below
_comms.BytesReceived += Handle_BytesReceived;
this.comms = comms; AddPostActivationAction(() => _comms.BytesReceived += Handle_BytesReceived);
commsMonitor = new GenericCommunicationMonitor(this, this.comms, this.config.PollTimeMs, this.config.WarningTimeoutMs, this.config.ErrorTimeoutMs, Poll); }
var socket = this.comms as ISocketStatus; #region Overrides of EssentialsBridgeableDevice
if (socket != null)
{ /// <summary>
// device comms is IP **ELSE** device comms is RS232 /// Links the plugin device to the EISC bridge
socket.ConnectionChange += socket_ConnectionChange; /// </summary>
Connect = true; /// <param name="trilist"></param>
} /// <param name="joinStart"></param>
/// <param name="joinMapKey"></param>
#region Communication data event handlers. Comment out any that don't apply to the API type /// <param name="bridge"></param>
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
// Only one of the below handlers should be necessary. {
var joinMap = new EssentialsPluginBridgeJoinMapTemplate(joinStart);
// comms gather for any API that has a defined delimiter
// TODO [ ] If not using an ASCII based API, remove the line below // This adds the join map to the collection on the bridge
commsGather = new CommunicationGather(this.comms, commsDelimiter); if (bridge != null)
commsGather.LineReceived += Handle_LineRecieved; {
bridge.AddJoinMap(Key, joinMap);
// comms byte buffer for HEX/byte based API's with no delimiter }
// TODO [ ] If not using an HEX/byte based API, remove the line below
this.comms.BytesReceived += Handle_BytesReceived; var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey);
// comms byte buffer for HEX/byte based API's with no delimiter if (customJoins != null)
// TODO [ ] If not using an HEX/byte based API, remove the line below {
this.comms.TextReceived += Handle_TextReceived; joinMap.SetCustomJoinData(customJoins);
}
#endregion
} Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, "Linking to Bridge Type {0}", GetType().Name);
private void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs args) // TODO [ ] Implement bridge links as needed
{
ConnectFeedback?.FireUpdate(); // links to bridge
trilist.SetString(joinMap.DeviceName.JoinNumber, Name);
StatusFeedback?.FireUpdate();
} trilist.SetBoolSigAction(joinMap.Connect.JoinNumber, sig => Connect = sig);
ConnectFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Connect.JoinNumber]);
// TODO [ ] If not using an API with a delimeter, delete the method below
private void Handle_LineRecieved(object sender, GenericCommMethodReceiveTextArgs args) StatusFeedback.LinkInputSig(trilist.UShortInput[joinMap.Status.JoinNumber]);
{ OnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
// TODO [ ] Implement method
UpdateFeedbacks();
// Enqueues the message to be processed in a dedicated thread, but the specified method
receiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessFeedbackMessage)); trilist.OnlineStatusChange += (o, a) =>
} {
if (!a.DeviceOnLine) return;
// TODO [ ] If not using an HEX/byte based API with no delimeter, delete the method below
private void Handle_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs args) trilist.SetString(joinMap.DeviceName.JoinNumber, Name);
{ UpdateFeedbacks();
// TODO [ ] Implement method };
throw new System.NotImplementedException(); }
}
private void UpdateFeedbacks()
// TODO [ ] If not using an ASCII based API with no delimeter, delete the method below {
void Handle_TextReceived(object sender, GenericCommMethodReceiveTextArgs e) // TODO [ ] Update as needed for the plugin being developed
{ ConnectFeedback.FireUpdate();
// TODO [ ] Implement method OnlineFeedback.FireUpdate();
throw new System.NotImplementedException(); StatusFeedback.FireUpdate();
} }
/// <summary> #endregion
/// This method should perform any necessary parsing of feedback messages from the device
/// </summary> private void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs args)
/// <param name="message"></param> {
void ProcessFeedbackMessage(string message) if (ConnectFeedback != null)
{ ConnectFeedback.FireUpdate();
} if (StatusFeedback != null)
StatusFeedback.FireUpdate();
}
// TODO [ ] If not using an ACII based API, delete the properties below
/// <summary> // TODO [ ] If not using an ASCII based API, delete the properties below
/// Sends text to the device plugin comms private void Handle_LineRecieved(object sender, GenericCommMethodReceiveTextArgs args)
/// </summary> {
/// <remarks> // TODO [ ] Implement method
/// Can be used to test commands with the device plugin using the DEVPROPS and DEVJSON console commands throw new System.NotImplementedException();
/// </remarks> }
/// <param name="text">Command to be sent</param>
public void SendText(string text) // TODO [ ] If not using an HEX/byte based API, delete the properties below
{ private void Handle_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs args)
if (string.IsNullOrEmpty(text)) return; {
// TODO [ ] Implement method
comms.SendText(string.Format("{0}{1}", text, commsDelimiter)); throw new System.NotImplementedException();
} }
// TODO [ ] If not using an HEX/byte based API, delete the properties below // TODO [ ] If not using an ACII based API, delete the properties below
/// <summary> /// <summary>
/// Sends bytes to the device plugin comms /// Sends text to the device plugin comms
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Can be used to test commands with the device plugin using the DEVPROPS and DEVJSON console commands /// Can be used to test commands with the device plugin using the DEVPROPS and DEVJSON console commands
/// </remarks> /// </remarks>
/// <param name="bytes">Bytes to be sent</param> /// <param name="text">Command to be sent</param>
public void SendBytes(byte[] bytes) public void SendText(string text)
{ {
if (bytes == null) return; if (string.IsNullOrEmpty(text)) return;
comms.SendBytes(bytes); _comms.SendText(string.Format("{0}{1}", text, CommsDelimiter));
} }
/// <summary> // TODO [ ] If not using an HEX/byte based API, delete the properties below
/// Polls the device /// <summary>
/// </summary> /// Sends bytes to the device plugin comms
/// <remarks> /// </summary>
/// Poll method is used by the communication monitor. Update the poll method as needed for the plugin being developed /// <remarks>
/// </remarks> /// Can be used to test commands with the device plugin using the DEVPROPS and DEVJSON console commands
public void Poll() /// </remarks>
{ /// <param name="bytes">Bytes to be sent</param>
// TODO [ ] Update Poll method as needed for the plugin being developed public void SendBytes(byte[] bytes)
// Example: SendText("getstatus"); {
throw new System.NotImplementedException(); if (bytes == null) return;
}
_comms.SendBytes(bytes);
#endregion }
/// <summary>
#region Overrides of EssentialsBridgeableDevice /// Polls the device
/// </summary>
/// <summary> /// <remarks>
/// Links the plugin device to the EISC bridge /// Poll method is used by the communication monitor. Update the poll method as needed for the plugin being developed
/// </summary> /// </remarks>
/// <param name="trilist"></param> public void Poll()
/// <param name="joinStart"></param> {
/// <param name="joinMapKey"></param> // TODO [ ] Update Poll method as needed for the plugin being developed
/// <param name="bridge"></param> throw new System.NotImplementedException();
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) }
{ }
var joinMap = new EssentialsPluginTemplateBridgeJoinMap(joinStart); }
// This adds the join map to the collection on the bridge
bridge?.AddJoinMap(Key, joinMap);
var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey);
if (customJoins != null)
{
joinMap.SetCustomJoinData(customJoins);
}
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
// links to bridge
trilist.SetString(joinMap.DeviceName.JoinNumber, Name);
trilist.SetBoolSigAction(joinMap.Connect.JoinNumber, sig => Connect = sig);
ConnectFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Connect.JoinNumber]);
StatusFeedback.LinkInputSig(trilist.UShortInput[joinMap.Status.JoinNumber]);
OnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
UpdateFeedbacks();
trilist.OnlineStatusChange += (o, a) =>
{
if (!a.DeviceOnLine) return;
trilist.SetString(joinMap.DeviceName.JoinNumber, Name);
UpdateFeedbacks();
};
}
private void UpdateFeedbacks()
{
// TODO [ ] Update as needed for the plugin being developed
ConnectFeedback.FireUpdate();
OnlineFeedback.FireUpdate();
StatusFeedback.FireUpdate();
}
#endregion
}
}

View file

@ -0,0 +1,92 @@
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace EssentialsPluginTemplate
{
/// <summary>
/// Plugin device factory
/// </summary>
/// <remarks>
/// Rename the class to match the device plugin being developed
/// </remarks>
/// <example>
/// "EssentialsPluginFactoryTemplate" renamed to "SamsungMdcFactory"
/// </example>
public class EssentialsPluginFactoryTemplate : EssentialsPluginDeviceFactory<EssentialsPluginDeviceTemplate>
{
/// <summary>
/// Plugin device factory constructor
/// </summary>
/// <remarks>
/// Update the MinimumEssentialsFrameworkVersion & TypeNames as needed when creating a plugin
/// </remarks>
/// <example>
/// <code>
/// // Set the minimum Essentials Framework Version
/// MinimumEssentialsFrameworkVersion = "1.5.5";
/// // In the constructor we initialize the list with the typenames that will build an instance of this device
#pragma warning disable 1570
/// TypeNames = new List<string>() { "SamsungMdc", "SamsungMdcDisplay" };
#pragma warning restore 1570
/// </code>
/// </example>
public EssentialsPluginFactoryTemplate()
{
// Set the minimum Essentials Framework Version
// TODO [ ] Update the Essentials minimum framework version which this plugin has been tested against
MinimumEssentialsFrameworkVersion = "1.6.4";
// 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>() { "examplePluginDevice" };
}
/// <summary>
/// Builds and returns an instance of EssentialsPluginDeviceTemplate
/// </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.Console(1, "[{0}] Factory Attempting to create new device from type: {1}", dc.Key, dc.Type);
// get the plugin device properties configuration object & check for null
var propertiesConfig = dc.Properties.ToObject<EssentialsPluginConfigObjectTemplate>();
if (propertiesConfig == null)
{
Debug.Console(0, "[{0}] Factory: failed to read properties config for {1}", dc.Key, dc.Name);
return null;
}
// TODO [ ] Discuss with Andrew/Neil on recommended best practice
// Method 1
//var username = dc.Properties["control"].Value<TcpSshPropertiesConfig>("tcpSshProperties").Username;
//var password = dc.Properties["control"].Value<TcpSshPropertiesConfig>("tcpSshProperties").Password;
//var method = dc.Properties["control"].Value<string>("method");
// Method 2 - Returns a JValue, has to be casted to string
var username = (string)dc.Properties["control"]["tcpSshProperties"]["username"];
var password = (string)dc.Properties["control"]["tcpSshProperties"]["password"];
var method = (string)dc.Properties["control"]["method"];
// build the plugin device comms & check for null
// TODO { ] As of PepperDash Core 1.0.41, HTTP and HTTPS are not valid eControlMethods and will throw an exception.
var comms = CommFactory.CreateCommForDevice(dc);
if (comms == null)
{
Debug.Console(0, "[{0}] Factory: failed to create comm for {1}", dc.Key, dc.Name);
return null;
}
return new EssentialsPluginDeviceTemplate(dc.Key, dc.Name, propertiesConfig, comms);
}
}
}

View file

@ -7,8 +7,8 @@
<ProjectGuid>{9D249E47-8F95-4437-A6BB-563510287AD1}</ProjectGuid> <ProjectGuid>{9D249E47-8F95-4437-A6BB-563510287AD1}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>PepperDash.Essentials.Plugin</RootNamespace> <RootNamespace>PDT.EssentialsPluginTemplate.EPI</RootNamespace>
<AssemblyName>MakeModelPlugin</AssemblyName> <AssemblyName>PDT.EssentialsPluginTemplate.EPI</AssemblyName>
<ProjectTypeGuids>{0B4745B0-194B-4BB6-8E21-E9057CA92300};{4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProjectTypeGuids>{0B4745B0-194B-4BB6-8E21-E9057CA92300};{4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<PlatformFamilyName>WindowsCE</PlatformFamilyName> <PlatformFamilyName>WindowsCE</PlatformFamilyName>
<PlatformID>E2BECB1F-8C8C-41ba-B736-9BE7D946A398</PlatformID> <PlatformID>E2BECB1F-8C8C-41ba-B736-9BE7D946A398</PlatformID>
@ -46,10 +46,6 @@
<GenerateSerializationAssemblies>off</GenerateSerializationAssemblies> <GenerateSerializationAssemblies>off</GenerateSerializationAssemblies>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Crestron.SimplSharpPro.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll</HintPath>
</Reference>
<Reference Include="Essentials Devices Common, Version=1.6.2.33892, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Essentials Devices Common, Version=1.6.2.33892, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\PepperDashEssentials\lib\net35\Essentials Devices Common.dll</HintPath> <HintPath>..\packages\PepperDashEssentials\lib\net35\Essentials Devices Common.dll</HintPath>
@ -73,39 +69,37 @@
</Reference> </Reference>
<Reference Include="SimplSharpCustomAttributesInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL"> <Reference Include="SimplSharpCustomAttributesInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>C:\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll</HintPath> <HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="SimplSharpHelperInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL"> <Reference Include="SimplSharpHelperInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>C:\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll</HintPath> <HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="SimplSharpNewtonsoft, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL"> <Reference Include="SimplSharpNewtonsoft, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>C:\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll</HintPath> <HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll</HintPath>
</Reference> </Reference>
<Reference Include="SimplSharpPro, Version=1.5.3.17, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL"> <Reference Include="SimplSharpPro, Version=1.5.3.17, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>C:\ProgramData\Crestron\SDK\SimplSharpPro.exe</HintPath> <HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="SimplSharpReflectionInterface, Version=1.0.5583.25238, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL"> <Reference Include="SimplSharpReflectionInterface, Version=1.0.5583.25238, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>C:\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath> <HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="MakeModelCrestronDevice.cs" /> <Compile Include="EssentialsPluginTemplateBridgeJoinMap.cs" />
<Compile Include="MakeModelBridgeJoinMap.cs" /> <Compile Include="EssentialsPluginTemplateConfigObject.cs" />
<Compile Include="MakeModelConfigObject.cs" /> <Compile Include="EssentialsPluginTemplateFactory.cs" />
<Compile Include="MakeModelDevice.cs" />
<Compile Include="MakeModelFactory.cs" />
<Compile Include="MakeModelLogicDevice.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="EssentialsPluginTemplateDevice.cs" />
<None Include="Properties\ControlSystem.cfg" /> <None Include="Properties\ControlSystem.cfg" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CompactFramework.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CompactFramework.CSharp.targets" />

View file

@ -0,0 +1,5 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<DeployDeviceID>E282E6BE-C7C3-4ece-916A-88FB1CF8AF3C</DeployDeviceID>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PDT.EssentialsPluginTemplate.EPI", "PDT.EssentialsPluginTemplate.EPI.csproj", "{9D249E47-8F95-4437-A6BB-563510287AD1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9D249E47-8F95-4437-A6BB-563510287AD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9D249E47-8F95-4437-A6BB-563510287AD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D249E47-8F95-4437-A6BB-563510287AD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9D249E47-8F95-4437-A6BB-563510287AD1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -1,8 +1,8 @@
using System.Reflection; using System.Reflection;
[assembly: AssemblyTitle("EssentialsPluginTemplateEpi")] [assembly: AssemblyTitle("EssentialsPluginTemplateEpi")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("EssentialsPluginTemplateEpi")] [assembly: AssemblyProduct("EssentialsPluginTemplateEpi")]
[assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyVersion("1.0.0.*")] [assembly: AssemblyVersion("1.0.0.*")]

View file

@ -0,0 +1,63 @@
8/30/2019 3:01:01 PM, Info: Initializing SIMPLSharp Services...
8/30/2019 3:01:01 PM, Info: ProjectInfo successfully initialized.
8/30/2019 3:01:02 PM, Info: Saving project information...
8/30/2019 3:01:02 PM, Info: Saving project information...
8/30/2019 3:01:02 PM, Info: Saving project information...
8/30/2019 3:01:02 PM, Info: Saving project information...
8/30/2019 3:01:02 PM, Info: Saving project information...
8/30/2019 3:01:02 PM, Info: Saving project information...
8/30/2019 3:04:48 PM, Info: Validating assembly C:\Users\JTA\Documents\Stash Folder\KPMG\SLN103-AVNoc\SLN103-AVNoc.Plugins\NvxUrlRoutingClient.Epi\essentials-builds\PepperDashEssentials.dll...
8/30/2019 3:05:10 PM, Info: Saving project information...
8/30/2019 3:05:10 PM, Info: Saving project information...
8/30/2019 3:05:10 PM, Info: Saving project information...
8/30/2019 3:05:39 PM, Info: Validating assembly C:\Users\JTA\Documents\Stash Folder\KPMG\SLN103-AVNoc\SLN103-AVNoc.Plugins\NvxUrlRoutingClient.Epi\essentials-builds\PepperDash_Core.dll...
8/30/2019 3:05:39 PM, Info: Validating assembly C:\Users\JTA\Documents\Stash Folder\KPMG\SLN103-AVNoc\SLN103-AVNoc.Plugins\NvxUrlRoutingClient.Epi\essentials-builds\PepperDash_Essentials_Core.dll...
8/30/2019 3:05:40 PM, Info: Validating assembly C:\Users\JTA\Documents\Stash Folder\KPMG\SLN103-AVNoc\SLN103-AVNoc.Plugins\NvxUrlRoutingClient.Epi\essentials-builds\PepperDash_Essentials_DM.dll...
8/30/2019 3:06:24 PM, Info: Saving project information...
8/30/2019 3:06:24 PM, Info: Saving project information...
8/30/2019 3:06:24 PM, Info: Saving project information...
8/30/2019 3:06:24 PM, Info: Saving project information...
8/30/2019 3:06:24 PM, Info: Saving project information...
8/30/2019 3:06:24 PM, Info: Saving project information...
8/30/2019 3:06:36 PM, Info: Saving project information...
8/30/2019 3:06:36 PM, Info: Saving project information...
8/30/2019 3:06:36 PM, Info: Saving project information...
8/30/2019 3:06:36 PM, Info: Saving project information...
8/30/2019 3:06:36 PM, Info: Saving project information...
8/30/2019 3:06:36 PM, Info: Saving project information...
8/30/2019 3:08:54 PM, Info: Saving project information...
8/30/2019 3:08:54 PM, Info: Saving project information...
8/30/2019 3:08:54 PM, Info: Saving project information...
8/30/2019 3:08:54 PM, Info: Saving project information...
8/30/2019 3:08:54 PM, Info: Saving project information...
8/30/2019 3:08:54 PM, Info: Saving project information...
8/30/2019 3:09:39 PM, Info: Validating assembly C:\Users\JTA\Documents\Stash Folder\KPMG\SLN103-AVNoc\SLN103-AVNoc.Plugins\NvxUrlRoutingClient.Epi\essentials-builds\PepperDash_Essentials_Core.dll...
8/30/2019 3:10:10 PM, Info: Saving project information...
8/30/2019 3:10:10 PM, Info: Saving project information...
8/30/2019 3:10:10 PM, Info: Saving project information...
8/30/2019 3:15:10 PM, Info: Saving project information...
8/30/2019 3:15:10 PM, Info: Saving project information...
8/30/2019 3:15:10 PM, Info: Saving project information...
8/30/2019 3:20:10 PM, Info: Saving project information...
8/30/2019 3:20:10 PM, Info: Saving project information...
8/30/2019 3:20:10 PM, Info: Saving project information...
8/30/2019 3:25:10 PM, Info: Saving project information...
8/30/2019 3:25:10 PM, Info: Saving project information...
8/30/2019 3:25:10 PM, Info: Saving project information...
8/30/2019 3:30:10 PM, Info: Saving project information...
8/30/2019 3:30:10 PM, Info: Saving project information...
8/30/2019 3:30:10 PM, Info: Saving project information...
8/30/2019 3:35:10 PM, Info: Saving project information...
8/30/2019 3:35:10 PM, Info: Saving project information...
8/30/2019 3:35:10 PM, Info: Saving project information...
8/30/2019 3:35:38 PM, Info: Saving project information...
8/30/2019 3:35:38 PM, Info: Saving project information...
8/30/2019 3:35:38 PM, Info: Saving project information...
8/30/2019 3:35:38 PM, Info: Saving project information...
8/30/2019 3:35:38 PM, Info: Saving project information...
8/30/2019 3:35:38 PM, Info: Saving project information...
8/30/2019 3:36:52 PM, Info: Validating assembly C:\Users\JTA\Documents\Stash Folder\KPMG\SLN103-AVNoc\SLN103-AVNoc.Plugins\NvxUrlRoutingClient.Epi\NvxUrlRoutingClientEpi\bin\Debug\NvxUrlRoutingClientEpi.dll...
8/30/2019 3:36:52 PM, Info: Verifying assembly C:\Users\JTA\Documents\Stash Folder\KPMG\SLN103-AVNoc\SLN103-AVNoc.Plugins\NvxUrlRoutingClient.Epi\NvxUrlRoutingClientEpi\bin\Debug\NvxUrlRoutingClientEpi.dll
8/30/2019 3:36:52 PM, Info: Creating Archive C:\Users\JTA\Documents\Stash Folder\KPMG\SLN103-AVNoc\SLN103-AVNoc.Plugins\NvxUrlRoutingClient.Epi\NvxUrlRoutingClientEpi\bin\Debug\NvxUrlRoutingClientEpi.cplz...
8/30/2019 3:36:53 PM, Info: Saving project information...
9/2/2019 8:34:46 AM, Info: Terminating SIMPLSharp Services

View file

@ -1,6 +1,4 @@
![PepperDash Essentials Pluign Logo](/images/essentials-plugin-blue.png) # Essentials Plugin Template (c) 2020
# Essentials Plugin Template (c) 2023
## License ## License
@ -10,15 +8,6 @@ Provided under MIT license
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://github.com/PepperDash/Essentials/wiki/Plugins) 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
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`.
This also illustrates how a plugin can contain multiple devices.
## Cloning Instructions ## Cloning Instructions
After forking this repository into your own GitHub space, you can create a new repository using this one as the template. Then you must install the necessary dependencies as indicated below. After forking this repository into your own GitHub space, you can create a new repository using this one as the template. Then you must install the necessary dependencies as indicated below.
@ -31,7 +20,6 @@ The [Essentials](https://github.com/PepperDash/Essentials) libraries are require
To install dependencies once nuget.exe is installed, run the following command from the root directory of your repository: 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`. `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. 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 ### Installing Different versions of PepperDash Core
@ -40,21 +28,6 @@ If you need a different version of PepperDash Core, use the command `nuget insta
### Instructions for Renaming Solution and Files ### Instructions for Renaming Solution and Files
See the Task List in Visual Studio for a guide on how to start using the template. There is extensive inline documentation and examples as well. See the Task List in Visual Studio for a guide on how to start using the templage. There is extensive inline documentation and examples as well.
For renaming instructions in particular, see the XML `remarks` tags on class definitions For renaming instructions in particular, see the XML `remarks` tags on class definitions
## 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
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.
__If you do not make these changes to the nuspec file, the project will not generate a nuget package__

View file

@ -1,25 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.11.35327.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "epi-make-model.4Series", "src\epi-make-model.4Series.csproj", "{52E6E0A0-A710-4B5F-AF52-08816F5C99BB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{52E6E0A0-A710-4B5F-AF52-08816F5C99BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{52E6E0A0-A710-4B5F-AF52-08816F5C99BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{52E6E0A0-A710-4B5F-AF52-08816F5C99BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{52E6E0A0-A710-4B5F-AF52-08816F5C99BB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {45BE70E2-A4DC-4851-92ED-CE67B99F5D86}
EndGlobalSection
EndGlobal

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

3
packages.config Normal file
View file

@ -0,0 +1,3 @@
<packages>
<package id="PepperDashEssentials" version="1.6.4" targetFramework="net35" allowedVersions="[1.0,2.0)"/>
</packages>

View file

@ -1,21 +0,0 @@
<Project>
<PropertyGroup>
<Version>1.0.0-local</Version>
<InformationalVersion>$(Version)</InformationalVersion>
<Authors>PepperDash Technology</Authors>
<Company>PepperDash Technology</Company>
<Product>PepperDash Essentials Plugin Template</Product>
<Copyright>Copyright © 2025</Copyright>
<RepositoryUrl>https://github.com/PepperDash/EssentialsPluginTemplate.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>Crestron; 4series</PackageTags>
<PackageOutputPath>..\output</PackageOutputPath>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<ItemGroup>
<None Include="..\LICENSE.md" Pack="true" PackagePath=""/>
<None Include="..\README.md" Pack="true" PackagePath=""/>
</ItemGroup>
</Project>

View file

@ -1,20 +0,0 @@
<Project>
<ItemGroup>
<None Include="$(TargetDir)\$(TargetName).$(Version).cpz" Condition="$(ProjectType) == 'Program'">
<Pack>true</Pack>
<PackagePath>content;</PackagePath>
</None>
<None Include="$(PackageOutputPath)\$(TargetName).$(Version).cplz" Condition="$(ProjectType) == 'ProgramLibrary'">
<Pack>true</Pack>
<PackagePath>content;</PackagePath>
</None>
</ItemGroup>
<Target Name="Create CPLZ" AfterTargets="Build; Rebuild" Condition="$(ProjectType) == 'ProgramLibrary'">
<Message Text="Creating CPLZ"></Message>
<MakeDir Directories="$(PackageOutputPath)" Condition="!Exists($(PackageOutputPath))"></MakeDir>
<ZipDirectory SourceDirectory="$(TargetDir)" DestinationFile="$(PackageOutputPath)\$(TargetName).$(Version).cplz" Overwrite="true"/>
</Target>
<Target Name="Clean CPLZ" AfterTargets="AfterClean" Condition="$(ProjectType) == 'ProgramLibrary'">
<Delete Files="$(PackageOutputPath)\$(TargetName).$(Version).cplz"/>
</Target>
</Project>

View file

@ -1,96 +0,0 @@
// For Basic SIMPL# Classes
// 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 MakeModelCrestronDevice : CrestronGenericBridgeableBaseDevice
{
/// <summary>
/// It is often desirable to store the config
/// </summary>
private readonly MakeModelConfig config;
#region Constructor for Devices without IBasicCommunication. Remove if not needed
/// <summary>
/// Plugin device constructor for Crestron devices
/// </summary>
/// <param name="key"></param>
/// <param name="name"></param>
/// <param name="config"></param>
/// <param name="hardware"></param>
public MakeModelCrestronDevice(string key, string name, MakeModelConfig config, GenericBase hardware)
: base(key, name, hardware)
{
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
this.config = config;
}
#endregion
#region Overrides of EssentialsBridgeableDevice
/// <summary>
/// Links the plugin device to the EISC bridge
/// </summary>
/// <param name="trilist"></param>
/// <param name="joinStart"></param>
/// <param name="joinMapKey"></param>
/// <param name="bridge"></param>
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new EssentialsPluginTemplateBridgeJoinMap(joinStart);
// This adds the join map to the collection on the bridge
bridge?.AddJoinMap(Key, joinMap);
var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey);
if (customJoins != null)
{
joinMap.SetCustomJoinData(customJoins);
}
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
// links to bridge
trilist.SetString(joinMap.DeviceName.JoinNumber, Name);
trilist.OnlineStatusChange += (o, a) =>
{
if (!a.DeviceOnLine) return;
trilist.SetString(joinMap.DeviceName.JoinNumber, Name);
};
}
#endregion
}
}

View file

@ -1,87 +0,0 @@
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;
}
}
}
}

View file

@ -1,85 +0,0 @@
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Plugin
{
/// <summary>
/// Plugin device factory for devices that use IBasicCommunication
/// </summary>
/// <remarks>
/// Rename the class to match the device plugin being developed
/// </remarks>
/// <example>
/// "EssentialsPluginFactoryTemplate" renamed to "MyDeviceFactory"
/// </example>
public class MakeModelDeviceFactory : EssentialsPluginDeviceFactory<MakeModelDevice>
{
/// <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 = "2.12.1;
/// </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 MakeModelDeviceFactory()
{
// 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>() { "examplePluginDevice" };
}
/// <summary>
/// Builds and returns an instance of EssentialsPluginDeviceTemplate
/// </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.LogVerbose("[{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.LogError("[{key}] Factory: failed to read properties config for {name}", dc.Key, dc.Name);
return null;
}
// attempt build the plugin device comms device & check for null
// TODO { ] As of PepperDash Core 1.0.41, HTTP and HTTPS are not valid eControlMethods and will throw an exception.
var comms = CommFactory.CreateCommForDevice(dc);
if (comms == null)
{
Debug.LogError("[{key}] Factory Notice: No control object present for device {name}", dc.Key, dc.Name);
return null;
}
else
{
return new MakeModelDevice(dc.Key, dc.Name, propertiesConfig, comms);
}
}
}
}

View file

@ -1,84 +0,0 @@
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.Plugin
{
/// <summary>
/// Plugin device template for logic devices that don't communicate outside the program
/// </summary>
/// <remarks>
/// Rename the class to match the device plugin being developed.
/// </remarks>
/// <example>
/// "EssentialsPluginTemplateLogicDevice" renamed to "SamsungMdcDevice"
/// </example>
public class MakeModelLogicDevice : EssentialsBridgeableDevice
{
/// <summary>
/// It is often desirable to store the config
/// </summary>
private readonly MakeModelConfig config;
/// <summary>
/// Plugin device constructor
/// </summary>
/// <param name="key"></param>
/// <param name="name"></param>
/// <param name="config"></param>
public MakeModelLogicDevice(string key, string name, MakeModelConfig config)
: base(key, name)
{
this.LogInformation("Constructing new {0} instance", name);
// TODO [ ] Update the constructor as needed for the plugin device being developed
this.config = config;
}
#region Overrides of EssentialsBridgeableDevice
/// <summary>
/// Links the plugin device to the EISC bridge
/// </summary>
/// <param name="trilist"></param>
/// <param name="joinStart"></param>
/// <param name="joinMapKey"></param>
/// <param name="bridge"></param>
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new EssentialsPluginTemplateBridgeJoinMap(joinStart);
// This adds the join map to the collection on the bridge
bridge?.AddJoinMap(Key, joinMap);
var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey);
if (customJoins != null)
{
joinMap.SetCustomJoinData(customJoins);
}
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
// links to bridge
trilist.SetString(joinMap.DeviceName.JoinNumber, Name);
trilist.OnlineStatusChange += (o, a) =>
{
if (!a.DeviceOnLine) return;
trilist.SetString(joinMap.DeviceName.JoinNumber, Name);
};
}
#endregion
}
}

View file

@ -1,83 +0,0 @@
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Plugin
{
/// <summary>
/// Plugin device factory for logic devices that don't communicate
/// </summary>
/// <remarks>
/// Rename the class to match the device plugin being developed
/// </remarks>
/// <example>
/// "EssentialsPluginFactoryTemplate" renamed to "MyLogicDeviceFactory"
/// </example>
public class MakeModelLogicDeviceFactory : EssentialsPluginDeviceFactory<MakeModelLogicDevice>
{
/// <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 MakeModelLogicDeviceFactory()
{
// 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>() { "examplePluginLogicDevice" };
}
/// <summary>
/// Builds and returns an instance of EssentialsPluginTemplateLogicDevice
/// </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.LogError("[{key}] Factory: failed to read properties config for {name}", dc.Key, dc.Name);
return null;
}
var controlConfig = CommFactory.GetControlPropertiesConfig(dc);
if (controlConfig == null)
{
return new MakeModelLogicDevice(dc.Key, dc.Name, propertiesConfig);
}
else
{
Debug.LogError("[{key}] Factory: Unable to get control properties from device config for {name}", dc.Key, dc.Name);
return null;
}
}
}
}

View file

@ -1,50 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectType>ProgramLibrary</ProjectType>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<RootNamespace>PepperDash.Essentials.Plugin</RootNamespace>
<Deterministic>false</Deterministic>
<AssemblyTitle>PepperDash.Essentials.Plugin.Make.Model</AssemblyTitle>
<Company>PepperDash Technology</Company>
<Description>This software is a template for a PepperDash Essentials Plugin.</Description>
<Copyright>Copyright 2025</Copyright>
<Version>1.0.0-local</Version>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<InformationalVersion>$(Version)</InformationalVersion>
<OutputPath>bin\$(Configuration)\</OutputPath>
<Authors>PepperDash Technology</Authors>
<PackageId>Pepperdash.Essentials.Plugins.Template</PackageId>
<PackageProjectUrl>https://github.com/PepperDash/EssentialsPluginTemplate.git</PackageProjectUrl>
<PackageTags>crestron 4series essentials plugin template</PackageTags>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>$(DefineConstants);SERIES4</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Properties\**" />
<EmbeddedResource Remove="Properties\**" />
<None Remove="Properties\**" />
</ItemGroup>
<ItemGroup>
<None Remove="epi-make-model.projectinfo" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="PepperDashEssentials" Version="2.12.1" >
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Remove="../output\epi-make-model.4Series.1.0.0-local.cplz" />
</ItemGroup>
<ItemGroup>
<None Remove="../output\epi-make-model.4Series.1.0.0-local.cplz" />
</ItemGroup>
</Project>