From 3b7ddac3696b818e3065d55545ffec7501ea4d09 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Fri, 15 Jul 2022 11:48:33 -0500 Subject: [PATCH 01/36] fix: improper CSProj name in solution --- .../NvxUrlRoutingClientEpi.projectinfo | Bin 1888 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 PDT.EssentialsPluginTemplate.EPI/NvxUrlRoutingClientEpi.projectinfo diff --git a/PDT.EssentialsPluginTemplate.EPI/NvxUrlRoutingClientEpi.projectinfo b/PDT.EssentialsPluginTemplate.EPI/NvxUrlRoutingClientEpi.projectinfo deleted file mode 100644 index 96ee18796b996094386490683295705ec32ad495..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1888 zcmV-m2cP&KiwFP!000040PVd8U>r%7B_=Oz%6orG^-9;^bfE}=m|e(^`YTQU3S(MP)$b561U)?(aUhkIx?M z>`=QowL5wA`~JRPHF@3qzQ6Bx-W>nFzwgs(x?T_*`ula8HS_dYRnGGI_x*jJ)!8Dy zs_M7&&C926#-~j~%?d*KWx2j6mT&UKs?6GaeERb2HZ3N_l6uQ0>x-LPkEg5h2ZV58 zY4ozLembAFXUp^ISyARo!tLjBF!5O$uLR42uq5oynx{qGUYpr{eciPA;)P&7IL$QB z3qtm6_9nX+p7E1vu_7|ezFgjN>dg!PZy?^+;e^x0B%i&m*7Y<$uBY?jGPkU8QmwAv zRDx{t(IX>cdmsIh(MMkt%VM!!JS*zORaWOeNiB*BG}|5T>^!9Z?>!{oU#{ELx_z0o zKZgQBXnc_^i}So`-5BoCr^+z5CDa#Lu{@@Bi%EIy0PWK^-qha+Y*v=^MnEq5Z}-!C zyL%t?sM;mxw~0zXe(&Mr;eMX&&StZR_dnggmp!SOfA9XoEIa>n_uZ*`TcBqo*nE=r}rk4 zg9qn(yR&?9@Njo`?_jb!yUlzWkijJ00`NC7iKg@a56|3#Tg}{QJJ0K7-jW?&te3?! zYe}&-;cVXfH2?I|d;1R`>^{7|yT6m?pPuhd_VdZ~{=M`2dG_EIv$?UGV1{qe**7u6 z8xi{d@T?!)YSy2vVL!uJ-kau=PxtRsolkf3gXuy3ASWI8Am1YwCELCKX})vs!TE!o$t|Wb02^xAn}L556B!`z|K(}C zcdKdq%EYls<(-3v_sEj%OeZ^&{rmSG>^#_;k*m3PZ$E#qoA2bem_iFOn7&&8{wAi+ zcK-k6sq3VGTpy`~(oG5FnX;Aba@mQ-t$-lluqf(>==V_)~Wi z$WVpe4EVjK?xxQFzdUuFywA&gwaV+KgsAH+oVD{={$T%LXLm3E^x=rQJYr;14`~T&+>Lha9D1ZNxs?Nh{`gA%yIDbgCC!bL2 z^ug?2zIRS;;dFNY{`t-{3qrv-pkRh>0q$$gkl*G1mnWx_tMLZtx{J)yW-w*9fc$l*EZ+P7muIh&bBT|&n)?+wsvQG(;bSU_lIOG1~HhqTfqGWX72wF3DVt8mc{v2FY>FFvVqlk zXPJWHsE5=0vwJ(UET_ez^Mi-?r}sY1rjzq*n(xf+`*XGdS}3MwOX_i85~n){(>+Q@ zksonRp8EX-Ef+nId2JKd-BRJJ!IVjS!}q!d*?BMo@(!Gozki?<^6d(KRU?r!)*=swyW z<90F){l;UOA2-g)`N5}q6#h?lcFynRpXRgzc|WHl`3?=3?DhY<#>uGvlJEbLUo!gW aC-b^E*A-2g>vh@6)c-%ZRwX3mCjbCXc1X7X From 91ff0d8c83b627e3724fd6dd73d947a7ecd412f5 Mon Sep 17 00:00:00 2001 From: Jason Alborough Date: Fri, 15 Jul 2022 14:06:00 -0400 Subject: [PATCH 02/36] nuspec-TEMPLATE fix: #17 changes nuspec to nuspec-TEMPALTE feature: adds brief configuration instructions for nuspec file to readme --- ... => PDT.EssentialsPluginTemplate.nuspec-TEMPLATE} | 0 README.md | 12 ++++++++++++ 2 files changed, 12 insertions(+) rename PDT.EssentialsPluginTemplate.EPI/{PDT.EssentialsPluginTemplate.nuspec => PDT.EssentialsPluginTemplate.nuspec-TEMPLATE} (100%) diff --git a/PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.nuspec b/PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.nuspec-TEMPLATE similarity index 100% rename from PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.nuspec rename to PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.nuspec-TEMPLATE diff --git a/README.md b/README.md index 67a4614..8dfb905 100644 --- a/README.md +++ b/README.md @@ -40,3 +40,15 @@ If you need a different version of PepperDash Core, use the command `nuget insta 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 + +## Build Instructions (PepperDash Internal) + +## Generating Nuget Package + +In the solution folder is a file named "PDT.EssentialsPluginTemplate.nuspec-TEMPLATE" + +1. Remove the -TEMPLATE so that the extention is .nuspec. +2. Rename the file to match your plugin solution name +3. Edit the file to include your project specifics including + 1. PepperDash.Essentials.Plugin.MakeModel Convention is to use the prefix "PepperDash.Essentials.Plugin" and include the MakeModel of the device. + 2. https://github.com/PepperDash/EssentialsPluginTemplate Change to your url to the project repo \ No newline at end of file From 0cf654ce2dbd7132ac85c94d4a2deaf651e0e393 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 20 Jul 2022 16:42:25 -0500 Subject: [PATCH 03/36] Selective Nuget Package publish --- .../essentialsplugins-betabuilds.yml | 14 +- .../essentialsplugins-releasebuilds.yml | 19 +- GetPackages.BAT | 2 + ...T.EssentialsPluginTemplate.EPI.csproj.user | 5 - .../SIMPLSharpLogs/(2019-08-30 15-01-01).log | 63 --- .../EssentialsPluginTemplateBridgeJoinMap.cs | 6 +- .../EssentialsPluginTemplateConfigObject.cs | 388 +++++++++--------- .../EssentialsPluginTemplateCrestronDevice.cs | 2 +- .../EssentialsPluginTemplateDevice.cs | 6 +- .../EssentialsPluginTemplateFactory.cs | 16 +- .../EssentialsPluginTemplateLogicDevice.cs | 6 +- .../PDT.EssentialsPluginTemplate.EPI.csproj | 228 +++++----- .../PDT.EssentialsPluginTemplate.EPI.sln | 40 +- .../PDT.EssentialsPluginTemplate.nuspec | 4 +- .../Properties/AssemblyInfo.cs | 16 +- .../Properties/ControlSystem.cfg | 0 16 files changed, 382 insertions(+), 433 deletions(-) create mode 100644 GetPackages.BAT delete mode 100644 PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.EPI.csproj.user delete mode 100644 PDT.EssentialsPluginTemplate.EPI/SIMPLSharpLogs/(2019-08-30 15-01-01).log rename {PDT.EssentialsPluginTemplate.EPI => src}/EssentialsPluginTemplateBridgeJoinMap.cs (91%) rename {PDT.EssentialsPluginTemplate.EPI => src}/EssentialsPluginTemplateConfigObject.cs (94%) rename {PDT.EssentialsPluginTemplate.EPI => src}/EssentialsPluginTemplateCrestronDevice.cs (98%) rename {PDT.EssentialsPluginTemplate.EPI => src}/EssentialsPluginTemplateDevice.cs (97%) rename {PDT.EssentialsPluginTemplate.EPI => src}/EssentialsPluginTemplateFactory.cs (95%) rename {PDT.EssentialsPluginTemplate.EPI => src}/EssentialsPluginTemplateLogicDevice.cs (92%) rename {PDT.EssentialsPluginTemplate.EPI => src}/PDT.EssentialsPluginTemplate.EPI.csproj (98%) rename {PDT.EssentialsPluginTemplate.EPI => src}/PDT.EssentialsPluginTemplate.EPI.sln (97%) rename PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.nuspec-TEMPLATE => src/PDT.EssentialsPluginTemplate.nuspec (81%) rename {PDT.EssentialsPluginTemplate.EPI => src}/Properties/AssemblyInfo.cs (97%) rename {PDT.EssentialsPluginTemplate.EPI => src}/Properties/ControlSystem.cfg (100%) diff --git a/.github/workflows/essentialsplugins-betabuilds.yml b/.github/workflows/essentialsplugins-betabuilds.yml index ad34045..8fcbbf8 100644 --- a/.github/workflows/essentialsplugins-betabuilds.yml +++ b/.github/workflows/essentialsplugins-betabuilds.yml @@ -222,6 +222,7 @@ jobs: Push_Nuget_Package: needs: Build_Project runs-on: windows-2019 + env: NUSPECNAME steps: - name: Download Build Version Info uses: actions/download-artifact@v1 @@ -250,22 +251,27 @@ jobs: Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz") Get-ChildItem -Path .\output\* | Copy-Item -Destination .\ Remove-Item -Path .\output -Recurse + #Pushes to github nuget store - name: Get nuget File shell: powershell run: | - $nuspec_file = Get-ChildItem *.nuspec -recurse - echo "NUSPEC_FILE=$($nuspec_file.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + $NUSPECNAME = Get-ChildItem *.nuspec -recurse + echo "NUSPEC_FILE=$($NUSPECNAME.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Add nuget.exe uses: nuget/setup-nuget@v1 - name: Add Github Packages source + if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} - # Pushes to nuget, not needed unless publishing publicly + # Pushes to nuget gallery, not needed unless publishing publicly - name: Add nuget.org API Key + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - name: Create nuget package + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - name: Publish nuget package to Github registry + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' run: nuget push **/*.nupkg -source github - # Pushes to nuget, not needed unless publishing publicly >> this pushes package to nuget.org - name: Publish nuget package to nuget.org + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json diff --git a/.github/workflows/essentialsplugins-releasebuilds.yml b/.github/workflows/essentialsplugins-releasebuilds.yml index 3e169ce..ff951dd 100644 --- a/.github/workflows/essentialsplugins-releasebuilds.yml +++ b/.github/workflows/essentialsplugins-releasebuilds.yml @@ -111,7 +111,7 @@ jobs: $exclusions = "packages" # Trying to get any .json schema files (not currently working) # Gets any files with the listed extensions. - Get-ChildItem -recurse -Path "$($Env:GITHUB_WORKSPACE)" -include "*.clz", "*.cpz", "*.cplz", "*.nuspec" | ForEach-Object { + Get-ChildItem -recurse -Path "$($Env:GITHUB_WORKSPACE)" -include "*.clz", "*.cpz", "*.cplz", "*.nuspec", "*.md" | ForEach-Object { $allowed = $true; # Exclude any files in submodules foreach ($exclude in $exclusions) { @@ -170,6 +170,7 @@ jobs: Push_Nuget_Package: needs: Build_Project runs-on: windows-2019 + env: NUSPECNAME steps: - name: Download Build Version Info uses: actions/download-artifact@v1 @@ -195,25 +196,31 @@ jobs: Remove-Item -Path .\*.zip - name: Copy Files to root & delete output directory run: | - Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz") + Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz","*.md") Get-ChildItem -Path .\output\* | Copy-Item -Destination .\ Remove-Item -Path .\output -Recurse + # Pushes to github nuget store - name: Get nuget File shell: powershell run: | - $nuspec_file = Get-ChildItem *.nuspec -recurse - echo "NUSPEC_FILE=$($nuspec_file.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + $NUSPECNAME = Get-ChildItem *.nuspec -recurse + echo "NUSPEC_FILE=$($NUSPECNAME.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Add nuget.exe uses: nuget/setup-nuget@v1 - name: Add Github Packages source + if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} - # Pushes to nuget, not needed unless publishing publicly + # Pushes to nuget gallery, not needed unless publishing publicly - name: Add nuget.org API Key + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - name: Create nuget package + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - name: Publish nuget package to Github registry + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' run: nuget push **/*.nupkg -source github - # Pushes to nuget, not needed unless publishing publicly >> this pushes package to nuget.org - name: Publish nuget package to nuget.org + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json + \ No newline at end of file diff --git a/GetPackages.BAT b/GetPackages.BAT new file mode 100644 index 0000000..9b6def3 --- /dev/null +++ b/GetPackages.BAT @@ -0,0 +1,2 @@ +@Echo ON +nuget install .\packages.config -OutputDirectory .\packages -excludeVersion diff --git a/PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.EPI.csproj.user b/PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.EPI.csproj.user deleted file mode 100644 index 9c6c209..0000000 --- a/PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.EPI.csproj.user +++ /dev/null @@ -1,5 +0,0 @@ - - - E282E6BE-C7C3-4ece-916A-88FB1CF8AF3C - - \ No newline at end of file diff --git a/PDT.EssentialsPluginTemplate.EPI/SIMPLSharpLogs/(2019-08-30 15-01-01).log b/PDT.EssentialsPluginTemplate.EPI/SIMPLSharpLogs/(2019-08-30 15-01-01).log deleted file mode 100644 index b86200d..0000000 --- a/PDT.EssentialsPluginTemplate.EPI/SIMPLSharpLogs/(2019-08-30 15-01-01).log +++ /dev/null @@ -1,63 +0,0 @@ -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 diff --git a/PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateBridgeJoinMap.cs b/src/EssentialsPluginTemplateBridgeJoinMap.cs similarity index 91% rename from PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateBridgeJoinMap.cs rename to src/EssentialsPluginTemplateBridgeJoinMap.cs index 1f1f9d0..140d021 100644 --- a/PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateBridgeJoinMap.cs +++ b/src/EssentialsPluginTemplateBridgeJoinMap.cs @@ -12,7 +12,7 @@ namespace EssentialsPluginTemplate /// /// "EssentialsPluginBridgeJoinMapTemplate" renamed to "SamsungMdcBridgeJoinMap" /// - public class EssentialsPluginBridgeJoinMapTemplate : JoinMapBaseAdvanced + public class EssentialsPluginTemplateBridgeJoinMap : JoinMapBaseAdvanced { #region Digital @@ -93,8 +93,8 @@ namespace EssentialsPluginTemplate /// Plugin device BridgeJoinMap constructor /// /// This will be the join it starts on the EISC bridge - public EssentialsPluginBridgeJoinMapTemplate(uint joinStart) - : base(joinStart, typeof(EssentialsPluginBridgeJoinMapTemplate)) + public EssentialsPluginTemplateBridgeJoinMap(uint joinStart) + : base(joinStart, typeof(EssentialsPluginTemplateBridgeJoinMap)) { } } diff --git a/PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateConfigObject.cs b/src/EssentialsPluginTemplateConfigObject.cs similarity index 94% rename from PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateConfigObject.cs rename to src/EssentialsPluginTemplateConfigObject.cs index 027cefe..5894d67 100644 --- a/PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateConfigObject.cs +++ b/src/EssentialsPluginTemplateConfigObject.cs @@ -1,195 +1,195 @@ -using System.Collections.Generic; -using Newtonsoft.Json; -using PepperDash.Essentials.Core; - -namespace EssentialsPluginTemplate -{ - /// - /// Plugin device configuration object - /// - /// - /// Rename the class to match the device plugin being created - /// - /// - /// "EssentialsPluginConfigObjectTemplate" renamed to "SamsungMdcConfig" - /// - [ConfigSnippet("\"properties\":{\"control\":{}")] - public class EssentialsPluginConfigObjectTemplate - { - /// - /// JSON control object - /// - /// - /// 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. - /// In order to do so, you will need the username and password in the "tcpSshProperties" object. - /// - /// - /// - /// "control": { - /// "method": "tcpIp", - /// "controlPortDevKey": "processor", - /// "controlPortNumber": 1, - /// "comParams": { - /// "baudRate": 9600, - /// "dataBits": 8, - /// "stopBits": 1, - /// "parity": "None", - /// "protocol": "RS232", - /// "hardwareHandshake": "None", - /// "softwareHandshake": "None" - /// }, - /// "tcpSshProperties": { - /// "address": "172.22.0.101", - /// "port": 23, - /// "username": "admin", - /// "password": "password", - /// "autoReconnect": true, - /// "autoReconnectIntervalMs": 10000 - /// } - /// } - /// - /// - [JsonProperty("control")] - public EssentialsControlPropertiesConfig Control { get; set; } - - /// - /// Serializes the poll time value - /// - /// - /// This is an exmaple device plugin property. This should be modified or deleted as needed for the plugin being built. - /// - /// - /// PollTimeMs property gets/sets the value as a long - /// - /// - /// - /// "properties": { - /// "polltimeMs": 30000 - /// } - /// - /// - [JsonProperty("pollTimeMs")] - public long PollTimeMs { get; set; } - - /// - /// Serializes the warning timeout value - /// - /// - /// This is an exmaple device plugin property. This should be modified or deleted as needed for the plugin being built. - /// - /// - /// WarningTimeoutMs property gets/sets the value as a long - /// - /// - /// - /// "properties": { - /// "warningTimeoutMs": 180000 - /// } - /// - /// - [JsonProperty("warningTimeoutMs")] - public long WarningTimeoutMs { get; set; } - - /// - /// Serializes the error timeout value - /// - /// /// - /// This is an exmaple device plugin property. This should be modified or deleted as needed for the plugin being built. - /// - /// - /// ErrorTimeoutMs property gets/sets the value as a long - /// - /// - /// - /// "properties": { - /// "errorTimeoutMs": 300000 - /// } - /// - /// - [JsonProperty("errorTimeoutMs")] - public long ErrorTimeoutMs { get; set; } - - /// - /// Example dictionary of objects - /// - /// - /// This is an example collection configuration object. This should be modified or deleted as needed for the plugin being built. - /// - /// - /// - /// "properties": { - /// "presets": { - /// "preset1": { - /// "enabled": true, - /// "name": "Preset 1" - /// } - /// } - /// } - /// - /// - /// - /// - /// "properties": { - /// "inputNames": { - /// "input1": "Input 1", - /// "input2": "Input 2" - /// } - /// } - /// - /// - [JsonProperty("DeviceDictionary")] - public Dictionary DeviceDictionary { get; set; } - - /// - /// Constuctor - /// - /// - /// If using a collection you must instantiate the collection in the constructor - /// to avoid exceptions when reading the configuration file - /// - public EssentialsPluginConfigObjectTemplate() - { - DeviceDictionary = new Dictionary(); - } - } - - /// - /// Example plugin configuration dictionary object - /// - /// - /// This is an example collection of configuration objects. This can be modified or deleted as needed for the plugin being built. - /// - /// - /// - /// "properties": { - /// "dictionary": { - /// "item1": { - /// "name": "Item 1 Name", - /// "value": "Item 1 Value" - /// } - /// } - /// } - /// - /// - public class EssentialsPluginConfigObjectDictionaryTemplate - { - /// - /// Serializes collection name property - /// - /// - /// This is an example collection of configuration objects. This can be modified or deleted as needed for the plugin being built. - /// - [JsonProperty("name")] - public string Name { get; set; } - - /// - /// Serializes collection value property - /// - /// - /// This is an example collection of configuration objects. This can be modified or deleted as needed for the plugin being built. - /// - [JsonProperty("value")] - public uint Value { get; set; } - } +using System.Collections.Generic; +using Newtonsoft.Json; +using PepperDash.Essentials.Core; + +namespace EssentialsPluginTemplate +{ + /// + /// Plugin device configuration object + /// + /// + /// Rename the class to match the device plugin being created + /// + /// + /// "EssentialsPluginConfigObjectTemplate" renamed to "SamsungMdcConfig" + /// + [ConfigSnippet("\"properties\":{\"control\":{}")] + public class EssentialsPluginTemplateConfigObject + { + /// + /// JSON control object + /// + /// + /// 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. + /// In order to do so, you will need the username and password in the "tcpSshProperties" object. + /// + /// + /// + /// "control": { + /// "method": "tcpIp", + /// "controlPortDevKey": "processor", + /// "controlPortNumber": 1, + /// "comParams": { + /// "baudRate": 9600, + /// "dataBits": 8, + /// "stopBits": 1, + /// "parity": "None", + /// "protocol": "RS232", + /// "hardwareHandshake": "None", + /// "softwareHandshake": "None" + /// }, + /// "tcpSshProperties": { + /// "address": "172.22.0.101", + /// "port": 23, + /// "username": "admin", + /// "password": "password", + /// "autoReconnect": true, + /// "autoReconnectIntervalMs": 10000 + /// } + /// } + /// + /// + [JsonProperty("control")] + public EssentialsControlPropertiesConfig Control { get; set; } + + /// + /// Serializes the poll time value + /// + /// + /// This is an exmaple device plugin property. This should be modified or deleted as needed for the plugin being built. + /// + /// + /// PollTimeMs property gets/sets the value as a long + /// + /// + /// + /// "properties": { + /// "polltimeMs": 30000 + /// } + /// + /// + [JsonProperty("pollTimeMs")] + public long PollTimeMs { get; set; } + + /// + /// Serializes the warning timeout value + /// + /// + /// This is an exmaple device plugin property. This should be modified or deleted as needed for the plugin being built. + /// + /// + /// WarningTimeoutMs property gets/sets the value as a long + /// + /// + /// + /// "properties": { + /// "warningTimeoutMs": 180000 + /// } + /// + /// + [JsonProperty("warningTimeoutMs")] + public long WarningTimeoutMs { get; set; } + + /// + /// Serializes the error timeout value + /// + /// /// + /// This is an exmaple device plugin property. This should be modified or deleted as needed for the plugin being built. + /// + /// + /// ErrorTimeoutMs property gets/sets the value as a long + /// + /// + /// + /// "properties": { + /// "errorTimeoutMs": 300000 + /// } + /// + /// + [JsonProperty("errorTimeoutMs")] + public long ErrorTimeoutMs { get; set; } + + /// + /// Example dictionary of objects + /// + /// + /// This is an example collection configuration object. This should be modified or deleted as needed for the plugin being built. + /// + /// + /// + /// "properties": { + /// "presets": { + /// "preset1": { + /// "enabled": true, + /// "name": "Preset 1" + /// } + /// } + /// } + /// + /// + /// + /// + /// "properties": { + /// "inputNames": { + /// "input1": "Input 1", + /// "input2": "Input 2" + /// } + /// } + /// + /// + [JsonProperty("DeviceDictionary")] + public Dictionary DeviceDictionary { get; set; } + + /// + /// Constuctor + /// + /// + /// If using a collection you must instantiate the collection in the constructor + /// to avoid exceptions when reading the configuration file + /// + public EssentialsPluginConfigObjectTemplate() + { + DeviceDictionary = new Dictionary(); + } + } + + /// + /// Example plugin configuration dictionary object + /// + /// + /// This is an example collection of configuration objects. This can be modified or deleted as needed for the plugin being built. + /// + /// + /// + /// "properties": { + /// "dictionary": { + /// "item1": { + /// "name": "Item 1 Name", + /// "value": "Item 1 Value" + /// } + /// } + /// } + /// + /// + public class EssentialsPluginTemplateConfigObjectDictionary + { + /// + /// Serializes collection name property + /// + /// + /// This is an example collection of configuration objects. This can be modified or deleted as needed for the plugin being built. + /// + [JsonProperty("name")] + public string Name { get; set; } + + /// + /// Serializes collection value property + /// + /// + /// This is an example collection of configuration objects. This can be modified or deleted as needed for the plugin being built. + /// + [JsonProperty("value")] + public uint Value { get; set; } + } } \ No newline at end of file diff --git a/PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateCrestronDevice.cs b/src/EssentialsPluginTemplateCrestronDevice.cs similarity index 98% rename from PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateCrestronDevice.cs rename to src/EssentialsPluginTemplateCrestronDevice.cs index 2377387..7da4ddf 100644 --- a/PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateCrestronDevice.cs +++ b/src/EssentialsPluginTemplateCrestronDevice.cs @@ -23,7 +23,7 @@ namespace EssentialsPluginTemplate /// /// It is often desirable to store the config /// - private EssentialsPluginConfigObjectTemplate _config; + private EssentialsPluginTemplateConfigObject _config; #region Constructor for Devices without IBasicCommunication. Remove if not needed diff --git a/PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateDevice.cs b/src/EssentialsPluginTemplateDevice.cs similarity index 97% rename from PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateDevice.cs rename to src/EssentialsPluginTemplateDevice.cs index 20c99da..d08418c 100644 --- a/PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateDevice.cs +++ b/src/EssentialsPluginTemplateDevice.cs @@ -24,7 +24,7 @@ namespace EssentialsPluginTemplate /// /// It is often desirable to store the config /// - private EssentialsPluginConfigObjectTemplate _config; + private EssentialsPluginTemplateConfigObject _config; /// /// Provides a queue and dedicated worker thread for processing feedback messages from a device. @@ -98,7 +98,7 @@ namespace EssentialsPluginTemplate /// /// /// - public EssentialsPluginTemplateDevice(string key, string name, EssentialsPluginConfigObjectTemplate config, IBasicCommunication comms) + public EssentialsPluginTemplateDevice(string key, string name, EssentialsPluginTemplateConfigObject config, IBasicCommunication comms) : base(key, name) { Debug.Console(0, this, "Constructing new {0} instance", name); @@ -244,7 +244,7 @@ namespace EssentialsPluginTemplate /// public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { - var joinMap = new EssentialsPluginBridgeJoinMapTemplate(joinStart); + var joinMap = new EssentialsPluginTemplateBridgeJoinMap(joinStart); // This adds the join map to the collection on the bridge if (bridge != null) diff --git a/PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateFactory.cs b/src/EssentialsPluginTemplateFactory.cs similarity index 95% rename from PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateFactory.cs rename to src/EssentialsPluginTemplateFactory.cs index 1798d19..d2eddce 100644 --- a/PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateFactory.cs +++ b/src/EssentialsPluginTemplateFactory.cs @@ -14,7 +14,7 @@ namespace EssentialsPluginTemplate /// /// "EssentialsPluginFactoryTemplate" renamed to "MyDeviceFactory" /// - public class EssentialsPluginFactoryTemplate : EssentialsPluginDeviceFactory + public class EssentialsPluginTemplateFactory : EssentialsPluginDeviceFactory { /// /// Plugin device factory constructor @@ -32,7 +32,7 @@ namespace EssentialsPluginTemplate /// TypeNames = new List() { "SamsungMdc", "SamsungMdcDisplay" }; /// /// - public EssentialsPluginFactoryTemplate() + public EssentialsPluginTemplateFactory() { // Set the minimum Essentials Framework Version // TODO [ ] Update the Essentials minimum framework version which this plugin has been tested against @@ -58,7 +58,7 @@ namespace EssentialsPluginTemplate 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(); + var propertiesConfig = dc.Properties.ToObject(); if (propertiesConfig == null) { Debug.Console(0, "[{0}] Factory: failed to read properties config for {1}", dc.Key, dc.Name); @@ -91,7 +91,7 @@ namespace EssentialsPluginTemplate /// /// "EssentialsPluginFactoryTemplate" renamed to "MyLogicDeviceFactory" /// - public class EssentialsPluginFactoryLogicDeviceTemplate : EssentialsPluginDeviceFactory + public class EssentialsPluginTemplateFactoryLogicDevice : EssentialsPluginDeviceFactory { /// /// Plugin device factory constructor @@ -109,7 +109,7 @@ namespace EssentialsPluginTemplate /// TypeNames = new List() { "SamsungMdc", "SamsungMdcDisplay" }; /// /// - public EssentialsPluginFactoryLogicDeviceTemplate() + public EssentialsPluginTemplateFactoryLogicDevice() { // Set the minimum Essentials Framework Version // TODO [ ] Update the Essentials minimum framework version which this plugin has been tested against @@ -136,7 +136,7 @@ namespace EssentialsPluginTemplate 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(); + var propertiesConfig = dc.Properties.ToObject(); if (propertiesConfig == null) { Debug.Console(0, "[{0}] Factory: failed to read properties config for {1}", dc.Key, dc.Name); @@ -166,7 +166,7 @@ namespace EssentialsPluginTemplate /// /// "EssentialsPluginFactoryTemplate" renamed to "MyCrestronDeviceFactory" /// - public class EssentialsPluginFactoryCrestronDeviceTemplate : EssentialsPluginDeviceFactory + public class EssentialsPluginTemplateFactoryCrestronDevice : EssentialsPluginDeviceFactory { /// /// Plugin device factory constructor @@ -184,7 +184,7 @@ namespace EssentialsPluginTemplate /// TypeNames = new List() { "SamsungMdc", "SamsungMdcDisplay" }; /// /// - public EssentialsPluginFactoryCrestronDeviceTemplate() + public EssentialsPluginTemplateFactoryCrestronDevice() { // Set the minimum Essentials Framework Version // TODO [ ] Update the Essentials minimum framework version which this plugin has been tested against diff --git a/PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateLogicDevice.cs b/src/EssentialsPluginTemplateLogicDevice.cs similarity index 92% rename from PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateLogicDevice.cs rename to src/EssentialsPluginTemplateLogicDevice.cs index eda5ad0..0685a43 100644 --- a/PDT.EssentialsPluginTemplate.EPI/EssentialsPluginTemplateLogicDevice.cs +++ b/src/EssentialsPluginTemplateLogicDevice.cs @@ -19,7 +19,7 @@ namespace EssentialsPluginTemplate /// /// It is often desirable to store the config /// - private EssentialsPluginConfigObjectTemplate _config; + private EssentialsPluginTemplateConfigObject _config; /// /// Plugin device constructor @@ -27,7 +27,7 @@ namespace EssentialsPluginTemplate /// /// /// - public EssentialsPluginTemplateLogicDevice(string key, string name, EssentialsPluginConfigObjectTemplate config) + public EssentialsPluginTemplateLogicDevice(string key, string name, EssentialsPluginTemplateConfigObject config) : base(key, name) { Debug.Console(0, this, "Constructing new {0} instance", name); @@ -48,7 +48,7 @@ namespace EssentialsPluginTemplate /// public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { - var joinMap = new EssentialsPluginBridgeJoinMapTemplate(joinStart); + var joinMap = new EssentialsPluginTemplateBridgeJoinMap(joinStart); // This adds the join map to the collection on the bridge if (bridge != null) diff --git a/PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.EPI.csproj b/src/PDT.EssentialsPluginTemplate.EPI.csproj similarity index 98% rename from PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.EPI.csproj rename to src/PDT.EssentialsPluginTemplate.EPI.csproj index 6dd00f2..edda00c 100644 --- a/PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.EPI.csproj +++ b/src/PDT.EssentialsPluginTemplate.EPI.csproj @@ -1,115 +1,115 @@ - - - Release - AnyCPU - 9.0.30729 - 2.0 - {9D249E47-8F95-4437-A6BB-563510287AD1} - Library - Properties - PDT.EssentialsPluginTemplate.EPI - PDT.EssentialsPluginTemplate.EPI - {0B4745B0-194B-4BB6-8E21-E9057CA92300};{4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - WindowsCE - E2BECB1F-8C8C-41ba-B736-9BE7D946A398 - 5.0 - SmartDeviceProject1 - v3.5 - Windows CE - - - - - .allowedReferenceRelatedFileExtensions - true - full - false - bin\Debug\ - DEBUG;TRACE; - prompt - 4 - 512 - true - true - off - - - .allowedReferenceRelatedFileExtensions - none - true - bin\Release\ - prompt - 4 - 512 - true - true - off - - - - False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll - - - False - ..\packages\PepperDashEssentials\lib\net35\Essentials Devices Common.dll - - - - False - ..\packages\PepperDashEssentials\lib\net35\PepperDashEssentials.dll - - - False - ..\packages\PepperDashEssentials\lib\net35\PepperDash_Core.dll - - - False - ..\packages\PepperDashEssentials\lib\net35\PepperDash_Essentials_Core.dll - - - False - ..\packages\PepperDashEssentials\lib\net35\PepperDash_Essentials_DM.dll - - - False - ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll - False - - - False - ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll - False - - - False - ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll - - - False - ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe - False - - - False - ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll - - - - - - - - - - - - - - - - - - rem S# Pro preparation will execute after these operations - + + + Release + AnyCPU + 9.0.30729 + 2.0 + {9D249E47-8F95-4437-A6BB-563510287AD1} + Library + Properties + PDT.EssentialsPluginTemplate.EPI + PDT.EssentialsPluginTemplate.EPI + {0B4745B0-194B-4BB6-8E21-E9057CA92300};{4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + WindowsCE + E2BECB1F-8C8C-41ba-B736-9BE7D946A398 + 5.0 + SmartDeviceProject1 + v3.5 + Windows CE + + + + + .allowedReferenceRelatedFileExtensions + true + full + false + bin\Debug\ + DEBUG;TRACE; + prompt + 4 + 512 + true + true + off + + + .allowedReferenceRelatedFileExtensions + none + true + bin\Release\ + prompt + 4 + 512 + true + true + off + + + + False + ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll + + + False + ..\packages\PepperDashEssentials\lib\net35\Essentials Devices Common.dll + + + + False + ..\packages\PepperDashEssentials\lib\net35\PepperDashEssentials.dll + + + False + ..\packages\PepperDashEssentials\lib\net35\PepperDash_Core.dll + + + False + ..\packages\PepperDashEssentials\lib\net35\PepperDash_Essentials_Core.dll + + + False + ..\packages\PepperDashEssentials\lib\net35\PepperDash_Essentials_DM.dll + + + False + ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll + False + + + False + ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll + False + + + False + ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll + + + False + ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe + False + + + False + ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll + + + + + + + + + + + + + + + + + + rem S# Pro preparation will execute after these operations + \ No newline at end of file diff --git a/PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.EPI.sln b/src/PDT.EssentialsPluginTemplate.EPI.sln similarity index 97% rename from PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.EPI.sln rename to src/PDT.EssentialsPluginTemplate.EPI.sln index 08ca093..f453fd6 100644 --- a/PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.EPI.sln +++ b/src/PDT.EssentialsPluginTemplate.EPI.sln @@ -1,20 +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 + +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 diff --git a/PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.nuspec-TEMPLATE b/src/PDT.EssentialsPluginTemplate.nuspec similarity index 81% rename from PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.nuspec-TEMPLATE rename to src/PDT.EssentialsPluginTemplate.nuspec index 7b99bed..e72f807 100644 --- a/PDT.EssentialsPluginTemplate.EPI/PDT.EssentialsPluginTemplate.nuspec-TEMPLATE +++ b/src/PDT.EssentialsPluginTemplate.nuspec @@ -2,6 +2,7 @@ PDT.EssentialsPluginTemplate + docs\README.md 2.0.2 Essentials Plugin Template PepperDash Technologies @@ -11,11 +12,12 @@ https://github.com/PepperDash/EssentialsPluginTemplate Copyright 2022 This software iserves as a template for generating new Essentials-Compliant plugins - crestron 3series 4series samsung + crestron 3series 4series essentials pepperdash pepperdashessentials epi essentials plugin + \ No newline at end of file diff --git a/PDT.EssentialsPluginTemplate.EPI/Properties/AssemblyInfo.cs b/src/Properties/AssemblyInfo.cs similarity index 97% rename from PDT.EssentialsPluginTemplate.EPI/Properties/AssemblyInfo.cs rename to src/Properties/AssemblyInfo.cs index e8f1480..275e917 100644 --- a/PDT.EssentialsPluginTemplate.EPI/Properties/AssemblyInfo.cs +++ b/src/Properties/AssemblyInfo.cs @@ -1,8 +1,8 @@ -using System.Reflection; - -[assembly: AssemblyTitle("EssentialsPluginTemplateEpi")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("EssentialsPluginTemplateEpi")] -[assembly: AssemblyCopyright("Copyright © 2022")] -[assembly: AssemblyVersion("1.0.0.*")] - +using System.Reflection; + +[assembly: AssemblyTitle("EssentialsPluginTemplateEpi")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("EssentialsPluginTemplateEpi")] +[assembly: AssemblyCopyright("Copyright © 2022")] +[assembly: AssemblyVersion("1.0.0.*")] + diff --git a/PDT.EssentialsPluginTemplate.EPI/Properties/ControlSystem.cfg b/src/Properties/ControlSystem.cfg similarity index 100% rename from PDT.EssentialsPluginTemplate.EPI/Properties/ControlSystem.cfg rename to src/Properties/ControlSystem.cfg From 57a265d27f27018d988863ba529bf58dd060da49 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 20 Jul 2022 16:48:50 -0500 Subject: [PATCH 04/36] Made names of classes more consistent internally Removed obsolete references --- src/EssentialsPluginTemplateConfigObject.cs | 6 +++--- src/EssentialsPluginTemplateCrestronDevice.cs | 4 ++-- src/EssentialsPluginTemplateDevice.cs | 2 +- src/EssentialsPluginTemplateFactory.cs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/EssentialsPluginTemplateConfigObject.cs b/src/EssentialsPluginTemplateConfigObject.cs index 5894d67..e216796 100644 --- a/src/EssentialsPluginTemplateConfigObject.cs +++ b/src/EssentialsPluginTemplateConfigObject.cs @@ -139,7 +139,7 @@ namespace EssentialsPluginTemplate /// /// [JsonProperty("DeviceDictionary")] - public Dictionary DeviceDictionary { get; set; } + public Dictionary DeviceDictionary { get; set; } /// /// Constuctor @@ -148,9 +148,9 @@ namespace EssentialsPluginTemplate /// If using a collection you must instantiate the collection in the constructor /// to avoid exceptions when reading the configuration file /// - public EssentialsPluginConfigObjectTemplate() + public EssentialsPluginTemplateConfigObject() { - DeviceDictionary = new Dictionary(); + DeviceDictionary = new Dictionary(); } } diff --git a/src/EssentialsPluginTemplateCrestronDevice.cs b/src/EssentialsPluginTemplateCrestronDevice.cs index 7da4ddf..8836cc5 100644 --- a/src/EssentialsPluginTemplateCrestronDevice.cs +++ b/src/EssentialsPluginTemplateCrestronDevice.cs @@ -34,7 +34,7 @@ namespace EssentialsPluginTemplate /// /// /// - public EssentialsPluginTemplateCrestronDevice(string key, string name, EssentialsPluginConfigObjectTemplate config, GenericBase hardware) + public EssentialsPluginTemplateCrestronDevice(string key, string name, EssentialsPluginTemplateConfigObject config, GenericBase hardware) : base(key, name, hardware) { Debug.Console(0, this, "Constructing new {0} instance", name); @@ -60,7 +60,7 @@ namespace EssentialsPluginTemplate /// public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { - var joinMap = new EssentialsPluginBridgeJoinMapTemplate(joinStart); + var joinMap = new EssentialsPluginTemplateBridgeJoinMap(joinStart); // This adds the join map to the collection on the bridge if (bridge != null) diff --git a/src/EssentialsPluginTemplateDevice.cs b/src/EssentialsPluginTemplateDevice.cs index d08418c..b6d2031 100644 --- a/src/EssentialsPluginTemplateDevice.cs +++ b/src/EssentialsPluginTemplateDevice.cs @@ -5,7 +5,7 @@ using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; -using PepperDash_Essentials_Core.Queues; +using PepperDash.Essentials.Core.Queues; namespace EssentialsPluginTemplate diff --git a/src/EssentialsPluginTemplateFactory.cs b/src/EssentialsPluginTemplateFactory.cs index d2eddce..0b58f52 100644 --- a/src/EssentialsPluginTemplateFactory.cs +++ b/src/EssentialsPluginTemplateFactory.cs @@ -211,7 +211,7 @@ namespace EssentialsPluginTemplate 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(); + var propertiesConfig = dc.Properties.ToObject(); if (propertiesConfig == null) { Debug.Console(0, "[{0}] Factory: failed to read properties config for {1}", dc.Key, dc.Name); From baaf7c4a28bb4d43dc0db1592b0119c52746d008 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 20 Jul 2022 17:11:15 -0500 Subject: [PATCH 05/36] fix: Workflow Syntax --- .../essentialsplugins-betabuilds.yml | 21 ++++++++++----- .../essentialsplugins-releasebuilds.yml | 26 ++++++++++++------- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/.github/workflows/essentialsplugins-betabuilds.yml b/.github/workflows/essentialsplugins-betabuilds.yml index 8fcbbf8..5219292 100644 --- a/.github/workflows/essentialsplugins-betabuilds.yml +++ b/.github/workflows/essentialsplugins-betabuilds.yml @@ -222,13 +222,23 @@ jobs: Push_Nuget_Package: needs: Build_Project runs-on: windows-2019 - env: NUSPECNAME + env: + NUSPECNAME: default steps: + - name: Get nuget File + shell: powershell + run: | + $nuspec = Get-ChildItem *.nuspec -recurse + $NUSPECNAME = nuspec.BaseName + echo "NUSPEC_FILE=$($NUSPECNAME)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + - name: Download Build Version Info + if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' uses: actions/download-artifact@v1 with: name: Version - name: Set Version Number + if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' shell: powershell run: | Get-ChildItem "./Version" @@ -238,26 +248,25 @@ jobs: Remove-Item -Path ./Version/version.txt Remove-Item -Path ./Version - name: Download Build output + :if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' uses: actions/download-artifact@v1 with: name: Build path: ./ - name: Unzip Build file + if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' run: | Get-ChildItem .\*.zip | Expand-Archive -DestinationPath .\ Remove-Item -Path .\*.zip - name: Copy Files to root & delete output directory + if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' run: | Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz") Get-ChildItem -Path .\output\* | Copy-Item -Destination .\ Remove-Item -Path .\output -Recurse #Pushes to github nuget store - - name: Get nuget File - shell: powershell - run: | - $NUSPECNAME = Get-ChildItem *.nuspec -recurse - echo "NUSPEC_FILE=$($NUSPECNAME.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Add nuget.exe + if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' uses: nuget/setup-nuget@v1 - name: Add Github Packages source if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' diff --git a/.github/workflows/essentialsplugins-releasebuilds.yml b/.github/workflows/essentialsplugins-releasebuilds.yml index ff951dd..7537af9 100644 --- a/.github/workflows/essentialsplugins-releasebuilds.yml +++ b/.github/workflows/essentialsplugins-releasebuilds.yml @@ -170,13 +170,23 @@ jobs: Push_Nuget_Package: needs: Build_Project runs-on: windows-2019 - env: NUSPECNAME + env: + NUSPECNAME: default steps: + - name: Get nuget File + shell: powershell + run: | + $nuspec = Get-ChildItem *.nuspec -recurse + $NUSPECNAME = nuspec.BaseName + echo "NUSPEC_FILE=$($NUSPECNAME)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + - name: Download Build Version Info + if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' uses: actions/download-artifact@v1 with: name: Version - name: Set Version Number + if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' shell: powershell run: | Get-ChildItem "./Version" @@ -186,26 +196,25 @@ jobs: Remove-Item -Path ./Version/version.txt Remove-Item -Path ./Version - name: Download Build output + :if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' uses: actions/download-artifact@v1 with: name: Build path: ./ - name: Unzip Build file + if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' run: | Get-ChildItem .\*.zip | Expand-Archive -DestinationPath .\ Remove-Item -Path .\*.zip - name: Copy Files to root & delete output directory + if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' run: | - Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz","*.md") + Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz") Get-ChildItem -Path .\output\* | Copy-Item -Destination .\ Remove-Item -Path .\output -Recurse - # Pushes to github nuget store - - name: Get nuget File - shell: powershell - run: | - $NUSPECNAME = Get-ChildItem *.nuspec -recurse - echo "NUSPEC_FILE=$($NUSPECNAME.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + #Pushes to github nuget store - name: Add nuget.exe + if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' uses: nuget/setup-nuget@v1 - name: Add Github Packages source if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' @@ -223,4 +232,3 @@ jobs: - name: Publish nuget package to nuget.org if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json - \ No newline at end of file From 592400cc90033735029e271801fbc53d2b4e6535 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 20 Jul 2022 17:12:21 -0500 Subject: [PATCH 06/36] fix: Workflow Syntax --- .github/workflows/essentialsplugins-betabuilds.yml | 2 +- .github/workflows/essentialsplugins-releasebuilds.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/essentialsplugins-betabuilds.yml b/.github/workflows/essentialsplugins-betabuilds.yml index 5219292..94c9423 100644 --- a/.github/workflows/essentialsplugins-betabuilds.yml +++ b/.github/workflows/essentialsplugins-betabuilds.yml @@ -248,7 +248,7 @@ jobs: Remove-Item -Path ./Version/version.txt Remove-Item -Path ./Version - name: Download Build output - :if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' uses: actions/download-artifact@v1 with: name: Build diff --git a/.github/workflows/essentialsplugins-releasebuilds.yml b/.github/workflows/essentialsplugins-releasebuilds.yml index 7537af9..9d656db 100644 --- a/.github/workflows/essentialsplugins-releasebuilds.yml +++ b/.github/workflows/essentialsplugins-releasebuilds.yml @@ -196,7 +196,7 @@ jobs: Remove-Item -Path ./Version/version.txt Remove-Item -Path ./Version - name: Download Build output - :if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' uses: actions/download-artifact@v1 with: name: Build From 266bf187d955d6c6148df68c721ac11bd628db91 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 20 Jul 2022 17:15:39 -0500 Subject: [PATCH 07/36] fix: Workflow Syntax --- .../essentialsplugins-betabuilds.yml | 22 +++++++++---------- .../essentialsplugins-releasebuilds.yml | 22 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/essentialsplugins-betabuilds.yml b/.github/workflows/essentialsplugins-betabuilds.yml index 94c9423..4dcf064 100644 --- a/.github/workflows/essentialsplugins-betabuilds.yml +++ b/.github/workflows/essentialsplugins-betabuilds.yml @@ -233,12 +233,12 @@ jobs: echo "NUSPEC_FILE=$($NUSPECNAME)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Download Build Version Info - if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} uses: actions/download-artifact@v1 with: name: Version - name: Set Version Number - if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} shell: powershell run: | Get-ChildItem "./Version" @@ -248,39 +248,39 @@ jobs: Remove-Item -Path ./Version/version.txt Remove-Item -Path ./Version - name: Download Build output - if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} uses: actions/download-artifact@v1 with: name: Build path: ./ - name: Unzip Build file - if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} run: | Get-ChildItem .\*.zip | Expand-Archive -DestinationPath .\ Remove-Item -Path .\*.zip - name: Copy Files to root & delete output directory - if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} run: | Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz") Get-ChildItem -Path .\output\* | Copy-Item -Destination .\ Remove-Item -Path .\output -Recurse #Pushes to github nuget store - name: Add nuget.exe - if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} uses: nuget/setup-nuget@v1 - name: Add Github Packages source - if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} # Pushes to nuget gallery, not needed unless publishing publicly - name: Add nuget.org API Key - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - name: Create nuget package - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - name: Publish nuget package to Github registry - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} run: nuget push **/*.nupkg -source github - name: Publish nuget package to nuget.org - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json diff --git a/.github/workflows/essentialsplugins-releasebuilds.yml b/.github/workflows/essentialsplugins-releasebuilds.yml index 9d656db..c5bd360 100644 --- a/.github/workflows/essentialsplugins-releasebuilds.yml +++ b/.github/workflows/essentialsplugins-releasebuilds.yml @@ -181,12 +181,12 @@ jobs: echo "NUSPEC_FILE=$($NUSPECNAME)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Download Build Version Info - if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} uses: actions/download-artifact@v1 with: name: Version - name: Set Version Number - if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} shell: powershell run: | Get-ChildItem "./Version" @@ -196,39 +196,39 @@ jobs: Remove-Item -Path ./Version/version.txt Remove-Item -Path ./Version - name: Download Build output - if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} uses: actions/download-artifact@v1 with: name: Build path: ./ - name: Unzip Build file - if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} run: | Get-ChildItem .\*.zip | Expand-Archive -DestinationPath .\ Remove-Item -Path .\*.zip - name: Copy Files to root & delete output directory - if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} run: | Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz") Get-ChildItem -Path .\output\* | Copy-Item -Destination .\ Remove-Item -Path .\output -Recurse #Pushes to github nuget store - name: Add nuget.exe - if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} uses: nuget/setup-nuget@v1 - name: Add Github Packages source - if: $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} # Pushes to nuget gallery, not needed unless publishing publicly - name: Add nuget.org API Key - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - name: Create nuget package - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - name: Publish nuget package to Github registry - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} run: nuget push **/*.nupkg -source github - name: Publish nuget package to nuget.org - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && $NUSPECNAME != 'PDT.EssentialsPluginTemplate' + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json From 87872b78e28ac5a037a6e195fff618e4a420401e Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 20 Jul 2022 17:29:57 -0500 Subject: [PATCH 08/36] fix: Workflow Syntax --- .github/workflows/essentialsplugins-betabuilds.yml | 2 +- .github/workflows/essentialsplugins-releasebuilds.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/essentialsplugins-betabuilds.yml b/.github/workflows/essentialsplugins-betabuilds.yml index 4dcf064..4a52ae5 100644 --- a/.github/workflows/essentialsplugins-betabuilds.yml +++ b/.github/workflows/essentialsplugins-betabuilds.yml @@ -229,7 +229,7 @@ jobs: shell: powershell run: | $nuspec = Get-ChildItem *.nuspec -recurse - $NUSPECNAME = nuspec.BaseName + $NUSPECNAME = $nuspec.BaseName echo "NUSPEC_FILE=$($NUSPECNAME)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Download Build Version Info diff --git a/.github/workflows/essentialsplugins-releasebuilds.yml b/.github/workflows/essentialsplugins-releasebuilds.yml index c5bd360..45ee9db 100644 --- a/.github/workflows/essentialsplugins-releasebuilds.yml +++ b/.github/workflows/essentialsplugins-releasebuilds.yml @@ -177,7 +177,7 @@ jobs: shell: powershell run: | $nuspec = Get-ChildItem *.nuspec -recurse - $NUSPECNAME = nuspec.BaseName + $NUSPECNAME = $nuspec.BaseName echo "NUSPEC_FILE=$($NUSPECNAME)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Download Build Version Info From 856178d920e5dff018ed6c484214aa78bece3a3d Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 20 Jul 2022 17:53:48 -0500 Subject: [PATCH 09/36] fix: Workflow Syntax --- .github/workflows/essentialsplugins-betabuilds.yml | 6 +++--- .github/workflows/essentialsplugins-releasebuilds.yml | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/essentialsplugins-betabuilds.yml b/.github/workflows/essentialsplugins-betabuilds.yml index 4a52ae5..3dd9b81 100644 --- a/.github/workflows/essentialsplugins-betabuilds.yml +++ b/.github/workflows/essentialsplugins-betabuilds.yml @@ -228,9 +228,9 @@ jobs: - name: Get nuget File shell: powershell run: | - $nuspec = Get-ChildItem *.nuspec -recurse - $NUSPECNAME = $nuspec.BaseName - echo "NUSPEC_FILE=$($NUSPECNAME)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + $nuspec_file = Get-ChildItem *.nuspec -recurse + env.NUSPECNAME = $($nuspec_file.BaseName) + echo "NUSPEC_FILE=$($nuspec_file.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Download Build Version Info if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} diff --git a/.github/workflows/essentialsplugins-releasebuilds.yml b/.github/workflows/essentialsplugins-releasebuilds.yml index 45ee9db..3cf0c26 100644 --- a/.github/workflows/essentialsplugins-releasebuilds.yml +++ b/.github/workflows/essentialsplugins-releasebuilds.yml @@ -176,10 +176,9 @@ jobs: - name: Get nuget File shell: powershell run: | - $nuspec = Get-ChildItem *.nuspec -recurse - $NUSPECNAME = $nuspec.BaseName - echo "NUSPEC_FILE=$($NUSPECNAME)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - + $nuspec_file = Get-ChildItem *.nuspec -recurse + env.NUSPECNAME = $($nuspec_file.BaseName) + echo "NUSPEC_FILE=$($nuspec_file.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Download Build Version Info if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} uses: actions/download-artifact@v1 From 3d57ac3560ffa242c097ba194df73be96e0d78b3 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 20 Jul 2022 18:18:07 -0500 Subject: [PATCH 10/36] fix: Workflow Syntax --- .../essentialsplugins-betabuilds.yml | 25 +++++++++---------- .../essentialsplugins-releasebuilds.yml | 24 +++++++++--------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/.github/workflows/essentialsplugins-betabuilds.yml b/.github/workflows/essentialsplugins-betabuilds.yml index 3dd9b81..cfcea42 100644 --- a/.github/workflows/essentialsplugins-betabuilds.yml +++ b/.github/workflows/essentialsplugins-betabuilds.yml @@ -229,16 +229,15 @@ jobs: shell: powershell run: | $nuspec_file = Get-ChildItem *.nuspec -recurse - env.NUSPECNAME = $($nuspec_file.BaseName) + ${{ env.NUSPECNAME }} = $($nuspec_file.BaseName) echo "NUSPEC_FILE=$($nuspec_file.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - - name: Download Build Version Info - if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate '}} uses: actions/download-artifact@v1 with: name: Version - name: Set Version Number - if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} shell: powershell run: | Get-ChildItem "./Version" @@ -248,39 +247,39 @@ jobs: Remove-Item -Path ./Version/version.txt Remove-Item -Path ./Version - name: Download Build output - if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} uses: actions/download-artifact@v1 with: name: Build path: ./ - name: Unzip Build file - if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} run: | Get-ChildItem .\*.zip | Expand-Archive -DestinationPath .\ Remove-Item -Path .\*.zip - name: Copy Files to root & delete output directory - if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} run: | Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz") Get-ChildItem -Path .\output\* | Copy-Item -Destination .\ Remove-Item -Path .\output -Recurse #Pushes to github nuget store - name: Add nuget.exe - if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} uses: nuget/setup-nuget@v1 - name: Add Github Packages source - if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} # Pushes to nuget gallery, not needed unless publishing publicly - name: Add nuget.org API Key - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - name: Create nuget package - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - name: Publish nuget package to Github registry - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} run: nuget push **/*.nupkg -source github - name: Publish nuget package to nuget.org - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json diff --git a/.github/workflows/essentialsplugins-releasebuilds.yml b/.github/workflows/essentialsplugins-releasebuilds.yml index 3cf0c26..c6837a4 100644 --- a/.github/workflows/essentialsplugins-releasebuilds.yml +++ b/.github/workflows/essentialsplugins-releasebuilds.yml @@ -177,15 +177,15 @@ jobs: shell: powershell run: | $nuspec_file = Get-ChildItem *.nuspec -recurse - env.NUSPECNAME = $($nuspec_file.BaseName) + ${{ env.NUSPECNAME }} = $($nuspec_file.BaseName) echo "NUSPEC_FILE=$($nuspec_file.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Download Build Version Info - if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate '}} uses: actions/download-artifact@v1 with: name: Version - name: Set Version Number - if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} shell: powershell run: | Get-ChildItem "./Version" @@ -195,39 +195,39 @@ jobs: Remove-Item -Path ./Version/version.txt Remove-Item -Path ./Version - name: Download Build output - if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} uses: actions/download-artifact@v1 with: name: Build path: ./ - name: Unzip Build file - if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} run: | Get-ChildItem .\*.zip | Expand-Archive -DestinationPath .\ Remove-Item -Path .\*.zip - name: Copy Files to root & delete output directory - if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} run: | Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz") Get-ChildItem -Path .\output\* | Copy-Item -Destination .\ Remove-Item -Path .\output -Recurse #Pushes to github nuget store - name: Add nuget.exe - if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} uses: nuget/setup-nuget@v1 - name: Add Github Packages source - if: ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} # Pushes to nuget gallery, not needed unless publishing publicly - name: Add nuget.org API Key - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - name: Create nuget package - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - name: Publish nuget package to Github registry - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} run: nuget push **/*.nupkg -source github - name: Publish nuget package to nuget.org - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{env.NUSPECNAME != 'PDT.EssentialsPluginTemplate'}} + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json From 1add0c193ce57acb9e147534398b5fad75c8d765 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 20 Jul 2022 18:34:20 -0500 Subject: [PATCH 11/36] fix: Workflow Syntax --- .github/workflows/essentialsplugins-betabuilds.yml | 2 +- .github/workflows/essentialsplugins-releasebuilds.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/essentialsplugins-betabuilds.yml b/.github/workflows/essentialsplugins-betabuilds.yml index cfcea42..56515c2 100644 --- a/.github/workflows/essentialsplugins-betabuilds.yml +++ b/.github/workflows/essentialsplugins-betabuilds.yml @@ -229,7 +229,7 @@ jobs: shell: powershell run: | $nuspec_file = Get-ChildItem *.nuspec -recurse - ${{ env.NUSPECNAME }} = $($nuspec_file.BaseName) + echo "NUSPECNAME=$($nuspec_file.BaseName)" >> $GITHUB_ENV echo "NUSPEC_FILE=$($nuspec_file.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Download Build Version Info if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate '}} diff --git a/.github/workflows/essentialsplugins-releasebuilds.yml b/.github/workflows/essentialsplugins-releasebuilds.yml index c6837a4..eab1043 100644 --- a/.github/workflows/essentialsplugins-releasebuilds.yml +++ b/.github/workflows/essentialsplugins-releasebuilds.yml @@ -177,7 +177,7 @@ jobs: shell: powershell run: | $nuspec_file = Get-ChildItem *.nuspec -recurse - ${{ env.NUSPECNAME }} = $($nuspec_file.BaseName) + echo "NUSPECNAME=$($nuspec_file.BaseName)" >> $GITHUB_ENV echo "NUSPEC_FILE=$($nuspec_file.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Download Build Version Info if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate '}} From f08741efd6ae61486bfd16419c9fc92d15c3382f Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 20 Jul 2022 20:32:42 -0500 Subject: [PATCH 12/36] fix: Workflow Syntax --- .../essentialsplugins-releasebuilds.yml | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/essentialsplugins-releasebuilds.yml b/.github/workflows/essentialsplugins-releasebuilds.yml index eab1043..4be26b4 100644 --- a/.github/workflows/essentialsplugins-releasebuilds.yml +++ b/.github/workflows/essentialsplugins-releasebuilds.yml @@ -180,12 +180,12 @@ jobs: echo "NUSPECNAME=$($nuspec_file.BaseName)" >> $GITHUB_ENV echo "NUSPEC_FILE=$($nuspec_file.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Download Build Version Info - if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate '}} + if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" uses: actions/download-artifact@v1 with: name: Version - name: Set Version Number - if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" shell: powershell run: | Get-ChildItem "./Version" @@ -195,39 +195,39 @@ jobs: Remove-Item -Path ./Version/version.txt Remove-Item -Path ./Version - name: Download Build output - if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" uses: actions/download-artifact@v1 with: name: Build path: ./ - name: Unzip Build file - if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: | Get-ChildItem .\*.zip | Expand-Archive -DestinationPath .\ Remove-Item -Path .\*.zip - name: Copy Files to root & delete output directory - if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: | Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz") Get-ChildItem -Path .\output\* | Copy-Item -Destination .\ Remove-Item -Path .\output -Recurse #Pushes to github nuget store - name: Add nuget.exe - if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" uses: nuget/setup-nuget@v1 - name: Add Github Packages source - if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} # Pushes to nuget gallery, not needed unless publishing publicly - name: Add nuget.org API Key - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - name: Create nuget package - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - name: Publish nuget package to Github registry - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: nuget push **/*.nupkg -source github - name: Publish nuget package to nuget.org - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json From af7e9ae659a367e05498a4f265dc7c94194a03aa Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 20 Jul 2022 21:03:26 -0500 Subject: [PATCH 13/36] fix: Workflow Syntax --- .../essentialsplugins-betabuilds.yml | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/essentialsplugins-betabuilds.yml b/.github/workflows/essentialsplugins-betabuilds.yml index 56515c2..90374b7 100644 --- a/.github/workflows/essentialsplugins-betabuilds.yml +++ b/.github/workflows/essentialsplugins-betabuilds.yml @@ -232,12 +232,12 @@ jobs: echo "NUSPECNAME=$($nuspec_file.BaseName)" >> $GITHUB_ENV echo "NUSPEC_FILE=$($nuspec_file.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Download Build Version Info - if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate '}} + if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" uses: actions/download-artifact@v1 with: name: Version - name: Set Version Number - if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" shell: powershell run: | Get-ChildItem "./Version" @@ -247,39 +247,39 @@ jobs: Remove-Item -Path ./Version/version.txt Remove-Item -Path ./Version - name: Download Build output - if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" uses: actions/download-artifact@v1 with: name: Build path: ./ - name: Unzip Build file - if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: | Get-ChildItem .\*.zip | Expand-Archive -DestinationPath .\ Remove-Item -Path .\*.zip - name: Copy Files to root & delete output directory - if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: | Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz") Get-ChildItem -Path .\output\* | Copy-Item -Destination .\ Remove-Item -Path .\output -Recurse #Pushes to github nuget store - name: Add nuget.exe - if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" uses: nuget/setup-nuget@v1 - name: Add Github Packages source - if: ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} # Pushes to nuget gallery, not needed unless publishing publicly - name: Add nuget.org API Key - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - name: Create nuget package - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - name: Publish nuget package to Github registry - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: nuget push **/*.nupkg -source github - name: Publish nuget package to nuget.org - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && ${{ env.NUSPECNAME != 'PDT.EssentialsPluginTemplate' }} + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json From ee057ad3618faf378e6db98fdb24fc14b6fdebd1 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 20 Jul 2022 21:47:09 -0500 Subject: [PATCH 14/36] fix: Workflow Syntax --- .github/workflows/essentialsplugins-betabuilds.yml | 8 ++++---- .github/workflows/essentialsplugins-releasebuilds.yml | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/essentialsplugins-betabuilds.yml b/.github/workflows/essentialsplugins-betabuilds.yml index 90374b7..f3f4657 100644 --- a/.github/workflows/essentialsplugins-betabuilds.yml +++ b/.github/workflows/essentialsplugins-betabuilds.yml @@ -272,14 +272,14 @@ jobs: run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} # Pushes to nuget gallery, not needed unless publishing publicly - name: Add nuget.org API Key - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - name: Create nuget package - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - name: Publish nuget package to Github registry - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') run: nuget push **/*.nupkg -source github - name: Publish nuget package to nuget.org - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json diff --git a/.github/workflows/essentialsplugins-releasebuilds.yml b/.github/workflows/essentialsplugins-releasebuilds.yml index 4be26b4..869ddf9 100644 --- a/.github/workflows/essentialsplugins-releasebuilds.yml +++ b/.github/workflows/essentialsplugins-releasebuilds.yml @@ -220,14 +220,14 @@ jobs: run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} # Pushes to nuget gallery, not needed unless publishing publicly - name: Add nuget.org API Key - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - name: Create nuget package - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - name: Publish nuget package to Github registry - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') run: nuget push **/*.nupkg -source github - name: Publish nuget package to nuget.org - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json From 62912451e8757568180f937c4c67c5979fa0ceb3 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 20 Jul 2022 22:15:48 -0500 Subject: [PATCH 15/36] fix: Workflow Syntax --- .github/workflows/essentialsplugins-betabuilds.yml | 4 ++-- .github/workflows/essentialsplugins-releasebuilds.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/essentialsplugins-betabuilds.yml b/.github/workflows/essentialsplugins-betabuilds.yml index f3f4657..c2df4dc 100644 --- a/.github/workflows/essentialsplugins-betabuilds.yml +++ b/.github/workflows/essentialsplugins-betabuilds.yml @@ -229,8 +229,8 @@ jobs: shell: powershell run: | $nuspec_file = Get-ChildItem *.nuspec -recurse - echo "NUSPECNAME=$($nuspec_file.BaseName)" >> $GITHUB_ENV - echo "NUSPEC_FILE=$($nuspec_file.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + echo "NUSPECNAME=$($nuspec_file.BaseName)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + echo "NUSPEC_FILE=$($nuspec_file.BaseName)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Download Build Version Info if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" uses: actions/download-artifact@v1 diff --git a/.github/workflows/essentialsplugins-releasebuilds.yml b/.github/workflows/essentialsplugins-releasebuilds.yml index 869ddf9..be6aed4 100644 --- a/.github/workflows/essentialsplugins-releasebuilds.yml +++ b/.github/workflows/essentialsplugins-releasebuilds.yml @@ -177,8 +177,8 @@ jobs: shell: powershell run: | $nuspec_file = Get-ChildItem *.nuspec -recurse - echo "NUSPECNAME=$($nuspec_file.BaseName)" >> $GITHUB_ENV - echo "NUSPEC_FILE=$($nuspec_file.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + echo "NUSPECNAME=$($nuspec_file.BaseName)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + echo "NUSPEC_FILE=$($nuspec_file.BaseName)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Download Build Version Info if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" uses: actions/download-artifact@v1 From 62f959bb259cd8159d60c4b0bfed97d303ae3bec Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Thu, 21 Jul 2022 10:17:56 -0500 Subject: [PATCH 16/36] test workflow syntax --- .../essentialsplugins-betabuilds.yml | 20 +++--- .../essentialsplugins-releasebuilds.yml | 61 ++++++++++++++++++- 2 files changed, 68 insertions(+), 13 deletions(-) diff --git a/.github/workflows/essentialsplugins-betabuilds.yml b/.github/workflows/essentialsplugins-betabuilds.yml index c2df4dc..fa3e21c 100644 --- a/.github/workflows/essentialsplugins-betabuilds.yml +++ b/.github/workflows/essentialsplugins-betabuilds.yml @@ -225,19 +225,11 @@ jobs: env: NUSPECNAME: default steps: - - name: Get nuget File - shell: powershell - run: | - $nuspec_file = Get-ChildItem *.nuspec -recurse - echo "NUSPECNAME=$($nuspec_file.BaseName)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - echo "NUSPEC_FILE=$($nuspec_file.BaseName)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Download Build Version Info - if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" uses: actions/download-artifact@v1 with: name: Version - name: Set Version Number - if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" shell: powershell run: | Get-ChildItem "./Version" @@ -247,22 +239,26 @@ jobs: Remove-Item -Path ./Version/version.txt Remove-Item -Path ./Version - name: Download Build output - if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" uses: actions/download-artifact@v1 with: name: Build path: ./ - name: Unzip Build file - if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: | Get-ChildItem .\*.zip | Expand-Archive -DestinationPath .\ Remove-Item -Path .\*.zip - name: Copy Files to root & delete output directory - if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: | Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz") Get-ChildItem -Path .\output\* | Copy-Item -Destination .\ Remove-Item -Path .\output -Recurse + - name: Get nuget File + shell: powershell + run: | + $nuspec_file = (Get-ChildItem *.nuspec -recurse).BaseName + echo "NUSPECNAME=$($nuspec_file)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + echo "NUSPEC_FILE=$($nuspec_file)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + #Pushes to github nuget store - name: Add nuget.exe if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" @@ -270,7 +266,7 @@ jobs: - name: Add Github Packages source if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} - # Pushes to nuget gallery, not needed unless publishing publicly + # Pushes to nuget gallery - name: Add nuget.org API Key if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} diff --git a/.github/workflows/essentialsplugins-releasebuilds.yml b/.github/workflows/essentialsplugins-releasebuilds.yml index be6aed4..18b3771 100644 --- a/.github/workflows/essentialsplugins-releasebuilds.yml +++ b/.github/workflows/essentialsplugins-releasebuilds.yml @@ -167,7 +167,6 @@ jobs: asset_content_type: application/zip env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - Push_Nuget_Package: needs: Build_Project runs-on: windows-2019 env: @@ -231,3 +230,63 @@ jobs: - name: Publish nuget package to nuget.org if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json + Push_Nuget_Package: + needs: Build_Project + runs-on: windows-2019 + env: + NUSPECNAME: default + steps: + - name: Download Build Version Info + uses: actions/download-artifact@v1 + with: + name: Version + - name: Set Version Number + shell: powershell + run: | + Get-ChildItem "./Version" + $version = Get-Content -Path ./Version/version.txt + Write-Host "Version: $version" + echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + Remove-Item -Path ./Version/version.txt + Remove-Item -Path ./Version + - name: Download Build output + uses: actions/download-artifact@v1 + with: + name: Build + path: ./ + - name: Unzip Build file + run: | + Get-ChildItem .\*.zip | Expand-Archive -DestinationPath .\ + Remove-Item -Path .\*.zip + - name: Copy Files to root & delete output directory + run: | + Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz") + Get-ChildItem -Path .\output\* | Copy-Item -Destination .\ + Remove-Item -Path .\output -Recurse + - name: Get nuget File + shell: powershell + run: | + $nuspec_file = (Get-ChildItem *.nuspec -recurse).BaseName + echo "NUSPECNAME=$($nuspec_file)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + echo "NUSPEC_FILE=$($nuspec_file)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + + #Pushes to github nuget store + - name: Add nuget.exe + if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" + uses: nuget/setup-nuget@v1 + - name: Add Github Packages source + if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" + run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} + # Pushes to nuget gallery + - name: Add nuget.org API Key + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') + run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} + - name: Create nuget package + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') + run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} + - name: Publish nuget package to Github registry + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') + run: nuget push **/*.nupkg -source github + - name: Publish nuget package to nuget.org + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') + run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json From 259a71c562f1e0c939548e71ae2313de314985c3 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Thu, 21 Jul 2022 12:07:27 -0500 Subject: [PATCH 17/36] style: renamed classes for consistency build: updated essentials version ci: updated workflows docs: documentation updated ci: updated nuspec --- .../essentialsplugins-betabuilds.yml | 30 +++--- .../essentialsplugins-releasebuilds.yml | 91 +++---------------- README.md | 16 ++-- 3 files changed, 37 insertions(+), 100 deletions(-) diff --git a/.github/workflows/essentialsplugins-betabuilds.yml b/.github/workflows/essentialsplugins-betabuilds.yml index fa3e21c..3b42815 100644 --- a/.github/workflows/essentialsplugins-betabuilds.yml +++ b/.github/workflows/essentialsplugins-betabuilds.yml @@ -153,7 +153,7 @@ jobs: $exclusions = "packages" # Trying to get any .json schema files (not currently working) # Gets any files with the listed extensions. - Get-ChildItem -recurse -Path "$($Env:GITHUB_WORKSPACE)" -include "*.clz", "*.cpz", "*.cplz", "*.nuspec" | ForEach-Object { + Get-ChildItem -recurse -Path "$($Env:GITHUB_WORKSPACE)" -include "*.clz", "*.cpz", "*.cplz", "*.nuspec", "*.md" | ForEach-Object { $allowed = $true; # Exclude any files in submodules foreach ($exclude in $exclusions) { @@ -222,8 +222,6 @@ jobs: Push_Nuget_Package: needs: Build_Project runs-on: windows-2019 - env: - NUSPECNAME: default steps: - name: Download Build Version Info uses: actions/download-artifact@v1 @@ -256,26 +254,26 @@ jobs: shell: powershell run: | $nuspec_file = (Get-ChildItem *.nuspec -recurse).BaseName - echo "NUSPECNAME=$($nuspec_file)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append echo "NUSPEC_FILE=$($nuspec_file)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - - #Pushes to github nuget store + # Pulls the nuget builder packages - name: Add nuget.exe - if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" + if: "!contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate')" uses: nuget/setup-nuget@v1 + # Creating nuget Packages - name: Add Github Packages source - if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" + if: "!contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate')" run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} + - name: Create nuget package + if: "!contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate')" + run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} + # Pushes to internal github registry + - name: Publish nuget package to Github registry + if: "!contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate')" + run: nuget push **/*.nupkg -source github # Pushes to nuget gallery - name: Add nuget.org API Key - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate') run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - - name: Create nuget package - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') - run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - - name: Publish nuget package to Github registry - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') - run: nuget push **/*.nupkg -source github - name: Publish nuget package to nuget.org - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate') run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json diff --git a/.github/workflows/essentialsplugins-releasebuilds.yml b/.github/workflows/essentialsplugins-releasebuilds.yml index 18b3771..2ae1117 100644 --- a/.github/workflows/essentialsplugins-releasebuilds.yml +++ b/.github/workflows/essentialsplugins-releasebuilds.yml @@ -167,74 +167,9 @@ jobs: asset_content_type: application/zip env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - needs: Build_Project - runs-on: windows-2019 - env: - NUSPECNAME: default - steps: - - name: Get nuget File - shell: powershell - run: | - $nuspec_file = Get-ChildItem *.nuspec -recurse - echo "NUSPECNAME=$($nuspec_file.BaseName)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - echo "NUSPEC_FILE=$($nuspec_file.BaseName)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - - name: Download Build Version Info - if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" - uses: actions/download-artifact@v1 - with: - name: Version - - name: Set Version Number - if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" - shell: powershell - run: | - Get-ChildItem "./Version" - $version = Get-Content -Path ./Version/version.txt - Write-Host "Version: $version" - echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - Remove-Item -Path ./Version/version.txt - Remove-Item -Path ./Version - - name: Download Build output - if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" - uses: actions/download-artifact@v1 - with: - name: Build - path: ./ - - name: Unzip Build file - if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" - run: | - Get-ChildItem .\*.zip | Expand-Archive -DestinationPath .\ - Remove-Item -Path .\*.zip - - name: Copy Files to root & delete output directory - if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" - run: | - Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz") - Get-ChildItem -Path .\output\* | Copy-Item -Destination .\ - Remove-Item -Path .\output -Recurse - #Pushes to github nuget store - - name: Add nuget.exe - if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" - uses: nuget/setup-nuget@v1 - - name: Add Github Packages source - if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" - run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} - # Pushes to nuget gallery, not needed unless publishing publicly - - name: Add nuget.org API Key - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') - run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - - name: Create nuget package - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') - run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - - name: Publish nuget package to Github registry - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') - run: nuget push **/*.nupkg -source github - - name: Publish nuget package to nuget.org - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') - run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json Push_Nuget_Package: needs: Build_Project runs-on: windows-2019 - env: - NUSPECNAME: default steps: - name: Download Build Version Info uses: actions/download-artifact@v1 @@ -267,26 +202,26 @@ jobs: shell: powershell run: | $nuspec_file = (Get-ChildItem *.nuspec -recurse).BaseName - echo "NUSPECNAME=$($nuspec_file)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append echo "NUSPEC_FILE=$($nuspec_file)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - - #Pushes to github nuget store + # Pulls the nuget builder packages - name: Add nuget.exe - if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" + if: "!contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate')" uses: nuget/setup-nuget@v1 + # Creating nuget Packages - name: Add Github Packages source - if: "!contains(env.NUSPECNAME, 'EssentialsPluginTemplate')" + if: "!contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate')" run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} + - name: Create nuget package + if: "!contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate')" + run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} + # Pushes to internal github registry + - name: Publish nuget package to Github registry + if: "!contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate')" + run: nuget push **/*.nupkg -source github # Pushes to nuget gallery - name: Add nuget.org API Key - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate') run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - - name: Create nuget package - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') - run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - - name: Publish nuget package to Github registry - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') - run: nuget push **/*.nupkg -source github - name: Publish nuget package to nuget.org - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPECNAME, 'EssentialsPluginTemplate') + if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate') run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json diff --git a/README.md b/README.md index 8dfb905..d115b04 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ 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: `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 @@ -37,7 +38,7 @@ If you need a different version of PepperDash Core, use the command `nuget insta ### Instructions for Renaming Solution and Files -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. +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. For renaming instructions in particular, see the XML `remarks` tags on class definitions @@ -45,10 +46,13 @@ For renaming instructions in particular, see the XML `remarks` tags on class def ## Generating Nuget Package -In the solution folder is a file named "PDT.EssentialsPluginTemplate.nuspec-TEMPLATE" +In the solution folder is a file named "PDT.EssentialsPluginTemplate.nuspec" -1. Remove the -TEMPLATE so that the extention is .nuspec. -2. Rename the file to match your plugin solution name -3. Edit the file to include your project specifics including +1. Rename the file to match your plugin solution name +2. Edit the file to include your project specifics including 1. PepperDash.Essentials.Plugin.MakeModel Convention is to use the prefix "PepperDash.Essentials.Plugin" and include the MakeModel of the device. - 2. https://github.com/PepperDash/EssentialsPluginTemplate Change to your url to the project repo \ No newline at end of file + 2. https://github.com/PepperDash/EssentialsPluginTemplate 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__ \ No newline at end of file From 7ba409d64c1ca3515024e6ac1d209b55d5f3ad11 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 29 Aug 2023 16:27:59 -0500 Subject: [PATCH 18/36] feature: adds logo file and updates readme to reference logo --- README.md | 4 +++- images/essentials-plugin-blue.png | Bin 0 -> 42276 bytes images/essentials-plugin-white.png | Bin 0 -> 38390 bytes 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 images/essentials-plugin-blue.png create mode 100644 images/essentials-plugin-white.png diff --git a/README.md b/README.md index d115b04..458eca2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# Essentials Plugin Template (c) 2020 +![PepperDash Essentials Pluign Logo](/images/essentials-plugin-blue.png) + +# Essentials Plugin Template (c) 2023 ## License diff --git a/images/essentials-plugin-blue.png b/images/essentials-plugin-blue.png new file mode 100644 index 0000000000000000000000000000000000000000..c94b32059eb1d3a0421107d162bf79df2cdfdc8c GIT binary patch literal 42276 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 Ux?vyaZv-(hK4Fw+aQe#s0ValIXaE2J literal 0 HcmV?d00001 diff --git a/images/essentials-plugin-white.png b/images/essentials-plugin-white.png new file mode 100644 index 0000000000000000000000000000000000000000..73d6b3f6c105bc989d8abedda5b74a26389d5a1a GIT binary patch literal 38390 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%0DirF_A$;T0Gc1o=hq8k{SO#4 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 H`kenSj7h+Q literal 0 HcmV?d00001 From 2586e9502dd77d578b14b0ad221a8cfb765ca824 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 26 Sep 2023 08:57:39 -0500 Subject: [PATCH 19/36] Create essentialsplugins-betabuilds-caller.yml --- .../essentialsplugins-betabuilds-caller.yml | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/essentialsplugins-betabuilds-caller.yml diff --git a/.github/workflows/essentialsplugins-betabuilds-caller.yml b/.github/workflows/essentialsplugins-betabuilds-caller.yml new file mode 100644 index 0000000..8ca618c --- /dev/null +++ b/.github/workflows/essentialsplugins-betabuilds-caller.yml @@ -0,0 +1,22 @@ +name: Beta Build + +on: + push: + branches-ignore: + - "main" + + workflow_dispatch: + inputs: + branch: + description: 'Branch to build' + required: true + type: string + +jobs: + call-workflow: + uses: PepperDash/workflow-templates/.github/workflows/essentialsplugins-builds.yml@main + secrets: inherit + with: + branch: ${{ github.ref_name }} + default-branch: "main" + From 1b3c28da0cd81aa35e997e0ea6eb7d2dcdba31ed Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 26 Sep 2023 08:58:37 -0500 Subject: [PATCH 20/36] Create essentialsplugins-releasebuilds-caller.yml --- ...essentialsplugins-releasebuilds-caller.yml | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/essentialsplugins-releasebuilds-caller.yml diff --git a/.github/workflows/essentialsplugins-releasebuilds-caller.yml b/.github/workflows/essentialsplugins-releasebuilds-caller.yml new file mode 100644 index 0000000..d17c1d5 --- /dev/null +++ b/.github/workflows/essentialsplugins-releasebuilds-caller.yml @@ -0,0 +1,26 @@ + +name: Release Build + +on: + release: + types: + - released + branches: + - "main" + + workflow_dispatch: + inputs: + branch: + description: 'Branch to build' + required: true + type: string + +jobs: + call-workflow: + uses: PepperDash/workflow-templates/.github/workflows/essentialsplugins-builds.yml@main + secrets: inherit + with: + branch: "main" + default-branch: "main" + + From 4244b394e7d949b9a4ba8c7fc6f836ef5807da06 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 26 Sep 2023 09:03:37 -0500 Subject: [PATCH 21/36] fix: removes old betabuild action --- .../essentialsplugins-betabuilds.yml | 279 ------------------ 1 file changed, 279 deletions(-) delete mode 100644 .github/workflows/essentialsplugins-betabuilds.yml diff --git a/.github/workflows/essentialsplugins-betabuilds.yml b/.github/workflows/essentialsplugins-betabuilds.yml deleted file mode 100644 index 3b42815..0000000 --- a/.github/workflows/essentialsplugins-betabuilds.yml +++ /dev/null @@ -1,279 +0,0 @@ -name: Branch Build Using Docker - -on: - push: - branches: - - feature/* - - hotfix/* - - release/* - - dev* - -env: - # 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 master as the release branch. Change as necessary - RELEASE_BRANCH: main -jobs: - Build_Project: - runs-on: windows-2019 - steps: - # First we checkout the source repo - - name: Checkout repo - uses: actions/checkout@v2 - with: - fetch-depth: 0 - # Fetch all tags - - name: Fetch tags - run: git fetch --tags - # Generate the appropriate version number - - name: Set Version Number - shell: powershell - run: | - $latestVersions = $(git tag --merged origin/main) - $latestVersion = [version]"0.0.0" - Foreach ($version in $latestVersions) { - Write-Host $version - try { - if (([version]$version) -ge $latestVersion) { - $latestVersion = $version - Write-Host "Setting latest version to: $latestVersion" - } - } - catch { - Write-Host "Unable to convert $($version). Skipping" - continue; - } - } - - $newVersion = [version]$latestVersion - $phase = "" - $newVersionString = "" - switch -regex ($Env:GITHUB_REF) { - '^refs\/heads\/main*.' { - $newVersionString = "{0}.{1}.{2}" -f $newVersion.Major, $newVersion.Minor, $newVersion.Build - } - '^refs\/heads\/feature\/*.' { - $phase = 'alpha' - $newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER - } - '^refs\/heads\/release\/*.' { - $splitRef = $Env:GITHUB_REF -split "/" - $version = [version]($splitRef[-1] -replace "v", "") - $phase = 'rc' - $newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $version.Major, $version.Minor, $version.Build, $phase, $Env:GITHUB_RUN_NUMBER - } - '^refs\/heads\/dev*.' { - $phase = 'beta' - $newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER - } - '^refs\/heads\/hotfix\/*.' { - $phase = 'hotfix' - $newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER - } - } - echo "VERSION=$newVersionString" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - # Use the version number to set the version of the assemblies - - name: Update AssemblyInfo.cs - shell: powershell - run: | - function Update-SourceVersion { - Param ([string]$Version) - #$fullVersion = $Version - $baseVersion = [regex]::Match($Version, "(\d+.\d+.\d+).*").captures.groups[1].value - $NewAssemblyVersion = 'AssemblyVersion("' + $baseVersion + '.*")' - Write-Output "AssemblyVersion = $NewAssemblyVersion" - $NewAssemblyInformationalVersion = 'AssemblyInformationalVersion("' + $Version + '")' - Write-Output "AssemblyInformationalVersion = $NewAssemblyInformationalVersion" - foreach ($o in $input) { - Write-output $o.FullName - $TmpFile = $o.FullName + ".tmp" - get-content $o.FullName | - ForEach-Object { - $_ -replace 'AssemblyVersion\(".*"\)', $NewAssemblyVersion } | - ForEach-Object { - $_ -replace 'AssemblyInformationalVersion\(".*"\)', $NewAssemblyInformationalVersion - } > $TmpFile - move-item $TmpFile $o.FullName -force - } - } - function Update-AllAssemblyInfoFiles ( $version ) { - foreach ($file in "AssemblyInfo.cs", "AssemblyInfo.vb" ) { - get-childitem -Path $Env:GITHUB_WORKSPACE -recurse | Where-Object { $_.Name -eq $file } | Update-SourceVersion $version ; - } - } - # validate arguments - $r = [System.Text.RegularExpressions.Regex]::Match($Env:VERSION, "\d+\.\d+\.\d+.*"); - if ($r.Success) { - Write-Output "Updating Assembly Version to $Env:VERSION ..."; - Update-AllAssemblyInfoFiles $Env:VERSION; - } - else { - Write-Output " "; - Write-Output "Error: Input version $Env:VERSION does not match x.y.z format!" - Write-Output " "; - Write-Output "Unable to apply version to AssemblyInfo.cs files"; - } - - name: restore Nuget Packages - run: nuget install .\packages.config -OutputDirectory .\packages -ExcludeVersion - # Set the SOLUTION_PATH - - name: Get SLN Path - shell: powershell - run: | - $solution_path = Get-ChildItem *.sln -recurse - $solution_path = $solution_path.FullName - $solution_path = $solution_path -replace "(?:[^\\]*\\){4}", "" - Write-Output $solution_path - echo "SOLUTION_PATH=$($solution_path)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - # Set the SOLUTION_FILE - - name: Get SLN File - shell: powershell - run: | - $solution_file = Get-ChildItem .\*.sln -recurse -Path "$($Env:GITHUB_WORKSPACE)" - echo "SOLUTION_FILE=$($solution_file.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - # Login to Docker - - 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)"" -BuildSolutionConfiguration $($ENV:BUILD_TYPE)" - # Zip up the output files as needed - - name: Zip Build Output - shell: powershell - run: | - $destination = "$($Env:GITHUB_HOME)\output" - New-Item -ItemType Directory -Force -Path ($destination) - Get-ChildItem ($destination) - $exclusions = "packages" - # Trying to get any .json schema files (not currently working) - # Gets any files with the listed extensions. - Get-ChildItem -recurse -Path "$($Env:GITHUB_WORKSPACE)" -include "*.clz", "*.cpz", "*.cplz", "*.nuspec", "*.md" | ForEach-Object { - $allowed = $true; - # Exclude any files in submodules - foreach ($exclude in $exclusions) { - if ((Split-Path $_.FullName -Parent).contains("$($exclude)")) { - $allowed = $false; - break; - } - } - if ($allowed) { - Write-Host "allowing $($_)" - $_; - } - } | Copy-Item -Destination ($destination) -Force - Write-Host "Getting matching files..." - # Get any files from the output folder that match the following extensions - Get-ChildItem -Path $destination | Where-Object {($_.Extension -eq ".clz") -or ($_.Extension -eq ".cpz" -or ($_.Extension -eq ".cplz"))} | ForEach-Object { - # Replace the extensions with dll and xml and create an array - $filenames = @($($_ -replace "cpz|clz|cplz", "dll"), $($_ -replace "cpz|clz|cplz", "xml")) - Write-Host "Filenames:" - Write-Host $filenames - if ($filenames.length -gt 0) { - # Attempt to get the files and return them to the output directory - 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 - Write-Host "Output Contents post Zip" - Get-ChildItem -Path $destination - # Write the version to a file to be consumed by the push jobs - - name: Write Version - run: Write-Output "$($Env:VERSION)" | Out-File -FilePath "$($Env:GITHUB_HOME)\output\version.txt" - # Upload output files - - name: Upload Build Output - uses: actions/upload-artifact@v1 - with: - name: Build - path: ./${{ env.SOLUTION_FILE}}-${{ env.VERSION}}.zip - # Upload the Version file as an artifact - - name: Upload version.txt - uses: actions/upload-artifact@v1 - with: - name: Version - path: ${{env.GITHUB_HOME}}\output\version.txt - # Create the release on the source repo - - name: Create Release - id: create_release - uses: fleskesvor/create-release@feature/support-target-commitish - 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 }} - Push_Nuget_Package: - needs: Build_Project - runs-on: windows-2019 - steps: - - name: Download Build Version Info - uses: actions/download-artifact@v1 - with: - name: Version - - name: Set Version Number - shell: powershell - run: | - Get-ChildItem "./Version" - $version = Get-Content -Path ./Version/version.txt - Write-Host "Version: $version" - echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - Remove-Item -Path ./Version/version.txt - Remove-Item -Path ./Version - - name: Download Build output - uses: actions/download-artifact@v1 - with: - name: Build - path: ./ - - name: Unzip Build file - run: | - Get-ChildItem .\*.zip | Expand-Archive -DestinationPath .\ - Remove-Item -Path .\*.zip - - name: Copy Files to root & delete output directory - run: | - Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz") - Get-ChildItem -Path .\output\* | Copy-Item -Destination .\ - Remove-Item -Path .\output -Recurse - - name: Get nuget File - shell: powershell - run: | - $nuspec_file = (Get-ChildItem *.nuspec -recurse).BaseName - echo "NUSPEC_FILE=$($nuspec_file)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - # Pulls the nuget builder packages - - name: Add nuget.exe - if: "!contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate')" - uses: nuget/setup-nuget@v1 - # Creating nuget Packages - - name: Add Github Packages source - if: "!contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate')" - run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} - - name: Create nuget package - if: "!contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate')" - run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - # Pushes to internal github registry - - name: Publish nuget package to Github registry - if: "!contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate')" - run: nuget push **/*.nupkg -source github - # Pushes to nuget gallery - - name: Add nuget.org API Key - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate') - run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - - name: Publish nuget package to nuget.org - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate') - run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json From d327f2def8558cc5d667280cb100f7f74298bbb8 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 26 Sep 2023 09:04:31 -0500 Subject: [PATCH 22/36] fix: removes old release build action --- .../essentialsplugins-releasebuilds.yml | 227 ------------------ 1 file changed, 227 deletions(-) delete mode 100644 .github/workflows/essentialsplugins-releasebuilds.yml diff --git a/.github/workflows/essentialsplugins-releasebuilds.yml b/.github/workflows/essentialsplugins-releasebuilds.yml deleted file mode 100644 index 2ae1117..0000000 --- a/.github/workflows/essentialsplugins-releasebuilds.yml +++ /dev/null @@ -1,227 +0,0 @@ -name: Main Build using Docker - -on: - release: - types: - - released - branches: - - main - -env: - # 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 master as the release branch. Change as necessary - RELEASE_BRANCH: main -jobs: - Build_Project: - runs-on: windows-2019 - steps: - # First we checkout the source repo - - name: Checkout repo - uses: actions/checkout@v2 - with: - fetch-depth: 0 - # Fetch all tags - - name: Fetch tags - run: git fetch --tags - # Generate the appropriate version number - - name: Set Version Number - shell: powershell - env: - TAG_NAME: ${{ github.event.release.tag_name }} - run: echo "VERSION=$($Env:TAG_NAME)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - # Use the version number to set the version of the assemblies - - name: Update AssemblyInfo.cs - shell: powershell - run: | - function Update-SourceVersion { - Param ([string]$Version) - #$fullVersion = $Version - $baseVersion = [regex]::Match($Version, "(\d+.\d+.\d+).*").captures.groups[1].value - $NewAssemblyVersion = 'AssemblyVersion("' + $baseVersion + '.*")' - Write-Output "AssemblyVersion = $NewAssemblyVersion" - $NewAssemblyInformationalVersion = 'AssemblyInformationalVersion("' + $Version + '")' - Write-Output "AssemblyInformationalVersion = $NewAssemblyInformationalVersion" - foreach ($o in $input) { - Write-output $o.FullName - $TmpFile = $o.FullName + ".tmp" - get-content $o.FullName | - ForEach-Object { - $_ -replace 'AssemblyVersion\(".*"\)', $NewAssemblyVersion } | - ForEach-Object { - $_ -replace 'AssemblyInformationalVersion\(".*"\)', $NewAssemblyInformationalVersion - } > $TmpFile - move-item $TmpFile $o.FullName -force - } - } - function Update-AllAssemblyInfoFiles ( $version ) { - foreach ($file in "AssemblyInfo.cs", "AssemblyInfo.vb" ) { - get-childitem -Path $Env:GITHUB_WORKSPACE -recurse | Where-Object { $_.Name -eq $file } | Update-SourceVersion $version ; - } - } - # validate arguments - $r = [System.Text.RegularExpressions.Regex]::Match($Env:VERSION, "\d+\.\d+\.\d+.*"); - if ($r.Success) { - Write-Output "Updating Assembly Version to $Env:VERSION ..."; - Update-AllAssemblyInfoFiles $Env:VERSION; - } - else { - Write-Output " "; - Write-Output "Error: Input version $Env:VERSION does not match x.y.z format!" - Write-Output " "; - Write-Output "Unable to apply version to AssemblyInfo.cs files"; - } - - name: restore Nuget Packages - run: nuget install .\packages.config -OutputDirectory .\packages -ExcludeVersion - # Set the SOLUTION_PATH - - name: Get SLN Path - shell: powershell - run: | - $solution_path = Get-ChildItem *.sln -recurse - $solution_path = $solution_path.FullName - $solution_path = $solution_path -replace "(?:[^\\]*\\){4}", "" - Write-Output $solution_path - echo "SOLUTION_PATH=$($solution_path)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - # Set the SOLUTION_FILE - - name: Get SLN File - shell: powershell - run: | - $solution_file = Get-ChildItem .\*.sln -recurse -Path "$($Env:GITHUB_WORKSPACE)" - echo "SOLUTION_FILE=$($solution_file.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - # Login to Docker - - 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)"" -BuildSolutionConfiguration $($ENV:BUILD_TYPE)" - # Zip up the output files as needed - - name: Zip Build Output - shell: powershell - run: | - $destination = "$($Env:GITHUB_HOME)\output" - New-Item -ItemType Directory -Force -Path ($destination) - Get-ChildItem ($destination) - $exclusions = "packages" - # Trying to get any .json schema files (not currently working) - # Gets any files with the listed extensions. - Get-ChildItem -recurse -Path "$($Env:GITHUB_WORKSPACE)" -include "*.clz", "*.cpz", "*.cplz", "*.nuspec", "*.md" | ForEach-Object { - $allowed = $true; - # Exclude any files in submodules - foreach ($exclude in $exclusions) { - if ((Split-Path $_.FullName -Parent).contains("$($exclude)")) { - $allowed = $false; - break; - } - } - if ($allowed) { - Write-Host "allowing $($_)" - $_; - } - } | Copy-Item -Destination ($destination) -Force - Write-Host "Getting matching files..." - # Get any files from the output folder that match the following extensions - Get-ChildItem -Path $destination | Where-Object {($_.Extension -eq ".clz") -or ($_.Extension -eq ".cpz" -or ($_.Extension -eq ".cplz"))} | ForEach-Object { - # Replace the extensions with dll and xml and create an array - $filenames = @($($_ -replace "cpz|clz|cplz", "dll"), $($_ -replace "cpz|clz|cplz", "xml")) - Write-Host "Filenames:" - Write-Host $filenames - if ($filenames.length -gt 0) { - # Attempt to get the files and return them to the output directory - 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 - Write-Host "Output Contents post Zip" - Get-ChildItem -Path $destination - # Write the version to a file to be consumed by the push jobs - - name: Write Version - run: Write-Output "$($Env:VERSION)" | Out-File -FilePath "$($Env:GITHUB_HOME)\output\version.txt" - # Upload output files - - name: Upload Build Output - uses: actions/upload-artifact@v1 - with: - name: Build - path: ./${{ env.SOLUTION_FILE}}-${{ env.VERSION}}.zip - # Upload the Version file as an artifact - - name: Upload version.txt - uses: actions/upload-artifact@v1 - with: - name: Version - path: ${{env.GITHUB_HOME}}\output\version.txt - # Upload the build package to the release - - name: Upload Release Package - id: upload_release - uses: actions/upload-release-asset@v1 - with: - upload_url: ${{ github.event.release.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 }} - Push_Nuget_Package: - needs: Build_Project - runs-on: windows-2019 - steps: - - name: Download Build Version Info - uses: actions/download-artifact@v1 - with: - name: Version - - name: Set Version Number - shell: powershell - run: | - Get-ChildItem "./Version" - $version = Get-Content -Path ./Version/version.txt - Write-Host "Version: $version" - echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - Remove-Item -Path ./Version/version.txt - Remove-Item -Path ./Version - - name: Download Build output - uses: actions/download-artifact@v1 - with: - name: Build - path: ./ - - name: Unzip Build file - run: | - Get-ChildItem .\*.zip | Expand-Archive -DestinationPath .\ - Remove-Item -Path .\*.zip - - name: Copy Files to root & delete output directory - run: | - Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz") - Get-ChildItem -Path .\output\* | Copy-Item -Destination .\ - Remove-Item -Path .\output -Recurse - - name: Get nuget File - shell: powershell - run: | - $nuspec_file = (Get-ChildItem *.nuspec -recurse).BaseName - echo "NUSPEC_FILE=$($nuspec_file)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - # Pulls the nuget builder packages - - name: Add nuget.exe - if: "!contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate')" - uses: nuget/setup-nuget@v1 - # Creating nuget Packages - - name: Add Github Packages source - if: "!contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate')" - run: nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username Pepperdash -password ${{ secrets.GITHUB_TOKEN }} - - name: Create nuget package - if: "!contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate')" - run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - # Pushes to internal github registry - - name: Publish nuget package to Github registry - if: "!contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate')" - run: nuget push **/*.nupkg -source github - # Pushes to nuget gallery - - name: Add nuget.org API Key - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate') - run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - - name: Publish nuget package to nuget.org - if: github.repository_owner == 'PepperDash' && github.repository_visibility == 'public' && !contains(env.NUSPEC_FILE, 'EssentialsPluginTemplate') - run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json From 2264d903722f7ad1b54d7a75dca50b4bed7c525e Mon Sep 17 00:00:00 2001 From: Aviv Cohn Date: Thu, 10 Oct 2024 13:04:15 -0400 Subject: [PATCH 23/36] feat: Add 4Series csproj and update info --- PDT.EssentialsPluginTemplate.EPI.4Series.sln | 25 +++++++++++++ ....EssentialsPluginTemplate.EPI.3Series.sln} | 0 ...sentialsPluginTemplate.EPI.4Series..csproj | 36 +++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 PDT.EssentialsPluginTemplate.EPI.4Series.sln rename src/{PDT.EssentialsPluginTemplate.EPI.sln => PDT.EssentialsPluginTemplate.EPI.3Series.sln} (100%) create mode 100644 src/PDT.EssentialsPluginTemplate.EPI.4Series..csproj diff --git a/PDT.EssentialsPluginTemplate.EPI.4Series.sln b/PDT.EssentialsPluginTemplate.EPI.4Series.sln new file mode 100644 index 0000000..af0013f --- /dev/null +++ b/PDT.EssentialsPluginTemplate.EPI.4Series.sln @@ -0,0 +1,25 @@ + +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}") = "PDT.EssentialsPluginTemplate.EPI.4Series.", "src\PDT.EssentialsPluginTemplate.EPI.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 diff --git a/src/PDT.EssentialsPluginTemplate.EPI.sln b/src/PDT.EssentialsPluginTemplate.EPI.3Series.sln similarity index 100% rename from src/PDT.EssentialsPluginTemplate.EPI.sln rename to src/PDT.EssentialsPluginTemplate.EPI.3Series.sln diff --git a/src/PDT.EssentialsPluginTemplate.EPI.4Series..csproj b/src/PDT.EssentialsPluginTemplate.EPI.4Series..csproj new file mode 100644 index 0000000..0036b83 --- /dev/null +++ b/src/PDT.EssentialsPluginTemplate.EPI.4Series..csproj @@ -0,0 +1,36 @@ + + + ProgramLibrary + + + net472 + PDT.EssentialsPluginTemplate.EPI + false + PDT.EssentialsPluginTemplate.EPI + PepperDash Technologies + This software is a template for a PepperDash Essentials Plugin. + Copyright 2024 + 1.0.0-local + true + $(Version) + 4Series\bin\$(Configuration)\ + PepperDash Technologies + Pepperdash.Essentials.Plugins.Template + https://github.com/PepperDash/EssentialsPluginTemplate.git + crestron 4series essentials plugin template + + + + $(DefineConstants);SERIES4 + + + + + + + + + + + + \ No newline at end of file From a427afaf3c98553d1ef5e2c668c73f93481084f4 Mon Sep 17 00:00:00 2001 From: Aviv Cohn Date: Thu, 10 Oct 2024 14:04:26 -0400 Subject: [PATCH 24/36] feat: Add Directory.Build.x files --- src/Directory.Build.props | 21 +++++++++++++++++++++ src/Directory.Build.targets | 20 ++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 src/Directory.Build.props create mode 100644 src/Directory.Build.targets diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 0000000..ef365ad --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,21 @@ + + + 1.0.0-local + $(Version) + PepperDash Technologies + PepperDash Technologies + PepperDash Essentials Plugin Template + Copyright © 2024 + https://github.com/PepperDash/EssentialsPluginTemplate.git + git + Crestron; 4series + ../output + True + LICENSE.md + README.md + + + + + + diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets new file mode 100644 index 0000000..3af6067 --- /dev/null +++ b/src/Directory.Build.targets @@ -0,0 +1,20 @@ + + + + true + content; + + + true + content; + + + + + + + + + + + From 7c3c0bea71d7966bd492a888bbcc79add3c8aed0 Mon Sep 17 00:00:00 2001 From: Aviv Cohn Date: Thu, 10 Oct 2024 14:27:29 -0400 Subject: [PATCH 25/36] feat: add files --- .../EssentialsPlugins-builds-caller.yml | 31 +++++++++++++++++ .../essentialsplugins-betabuilds-caller.yml | 22 ------------ ...essentialsplugins-releasebuilds-caller.yml | 26 -------------- releaserc.json | 34 +++++++++++++++++++ ...T.EssentialsPluginTemplate.EPI.3Series.sln | 20 ----------- ...sentialsPluginTemplate.EPI.4Series..csproj | 4 +++ 6 files changed, 69 insertions(+), 68 deletions(-) create mode 100644 .github/workflows/EssentialsPlugins-builds-caller.yml delete mode 100644 .github/workflows/essentialsplugins-betabuilds-caller.yml delete mode 100644 .github/workflows/essentialsplugins-releasebuilds-caller.yml create mode 100644 releaserc.json delete mode 100644 src/PDT.EssentialsPluginTemplate.EPI.3Series.sln diff --git a/.github/workflows/EssentialsPlugins-builds-caller.yml b/.github/workflows/EssentialsPlugins-builds-caller.yml new file mode 100644 index 0000000..6d9f244 --- /dev/null +++ b/.github/workflows/EssentialsPlugins-builds-caller.yml @@ -0,0 +1,31 @@ +name: Build Essentials Plugin + +on: + push: + branches: + - '**' + +jobs: + getVersion: + uses: PepperDash/workflow-templates/.github/workflows/essentialsplugins-getversion.yml@main + secrets: inherit + build-3Series: + uses: PepperDash/workflow-templates/.github/workflows/essentialsplugins-3Series-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 }} + 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 }} \ No newline at end of file diff --git a/.github/workflows/essentialsplugins-betabuilds-caller.yml b/.github/workflows/essentialsplugins-betabuilds-caller.yml deleted file mode 100644 index 8ca618c..0000000 --- a/.github/workflows/essentialsplugins-betabuilds-caller.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Beta Build - -on: - push: - branches-ignore: - - "main" - - workflow_dispatch: - inputs: - branch: - description: 'Branch to build' - required: true - type: string - -jobs: - call-workflow: - uses: PepperDash/workflow-templates/.github/workflows/essentialsplugins-builds.yml@main - secrets: inherit - with: - branch: ${{ github.ref_name }} - default-branch: "main" - diff --git a/.github/workflows/essentialsplugins-releasebuilds-caller.yml b/.github/workflows/essentialsplugins-releasebuilds-caller.yml deleted file mode 100644 index d17c1d5..0000000 --- a/.github/workflows/essentialsplugins-releasebuilds-caller.yml +++ /dev/null @@ -1,26 +0,0 @@ - -name: Release Build - -on: - release: - types: - - released - branches: - - "main" - - workflow_dispatch: - inputs: - branch: - description: 'Branch to build' - required: true - type: string - -jobs: - call-workflow: - uses: PepperDash/workflow-templates/.github/workflows/essentialsplugins-builds.yml@main - secrets: inherit - with: - branch: "main" - default-branch: "main" - - diff --git a/releaserc.json b/releaserc.json new file mode 100644 index 0000000..c4bd268 --- /dev/null +++ b/releaserc.json @@ -0,0 +1,34 @@ +{ + "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" + } + ] +} \ No newline at end of file diff --git a/src/PDT.EssentialsPluginTemplate.EPI.3Series.sln b/src/PDT.EssentialsPluginTemplate.EPI.3Series.sln deleted file mode 100644 index f453fd6..0000000 --- a/src/PDT.EssentialsPluginTemplate.EPI.3Series.sln +++ /dev/null @@ -1,20 +0,0 @@ - -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 diff --git a/src/PDT.EssentialsPluginTemplate.EPI.4Series..csproj b/src/PDT.EssentialsPluginTemplate.EPI.4Series..csproj index 0036b83..1f930c1 100644 --- a/src/PDT.EssentialsPluginTemplate.EPI.4Series..csproj +++ b/src/PDT.EssentialsPluginTemplate.EPI.4Series..csproj @@ -33,4 +33,8 @@ + + + + \ No newline at end of file From 85d2e4e1dc461c038d60113e4fc5ffe63c957b00 Mon Sep 17 00:00:00 2001 From: jdevito Date: Thu, 30 Jan 2025 16:39:56 -0600 Subject: [PATCH 26/36] fix: update template repo 1. update workflow files 2. Add 3-series SLN and csproj files - Remove from project when using the template if not needed 3. Update 4-series SLN and csproj files 4. Moved SLN's to root of project 5. Rename *.cs files to identify naming convention of 'MakeModel' 6. Upate packages.config to reference latest Essentials v1 release --- .../EssentialsPlugins-builds-caller.yml | 2 + epi-make-model.3Series.sln | 20 + ....4Series.sln => epi-make-model.4Series.sln | 2 +- packages.config | 2 +- src/Directory.Build.props | 2 +- ...geJoinMap.cs => MakeModelBridgeJoinMap.cs} | 200 +++--- ...nfigObject.cs => MakeModelConfigObject.cs} | 10 +- ...onDevice.cs => MakeModelCrestronDevice.cs} | 18 +- ...inTemplateDevice.cs => MakeModelDevice.cs} | 597 +++++++++--------- ...TemplateFactory.cs => MakeModelFactory.cs} | 12 +- ...LogicDevice.cs => MakeModelLogicDevice.cs} | 12 +- src/PDT.EssentialsPluginTemplate.nuspec | 23 - ...I.csproj => epi-make-model.3Series.csproj} | 228 +++---- .....csproj => epi-make-model.4Series.csproj} | 24 +- 14 files changed, 579 insertions(+), 573 deletions(-) create mode 100644 epi-make-model.3Series.sln rename PDT.EssentialsPluginTemplate.EPI.4Series.sln => epi-make-model.4Series.sln (83%) rename src/{EssentialsPluginTemplateBridgeJoinMap.cs => MakeModelBridgeJoinMap.cs} (94%) rename src/{EssentialsPluginTemplateConfigObject.cs => MakeModelConfigObject.cs} (99%) rename src/{EssentialsPluginTemplateCrestronDevice.cs => MakeModelCrestronDevice.cs} (98%) rename src/{EssentialsPluginTemplateDevice.cs => MakeModelDevice.cs} (96%) rename src/{EssentialsPluginTemplateFactory.cs => MakeModelFactory.cs} (99%) rename src/{EssentialsPluginTemplateLogicDevice.cs => MakeModelLogicDevice.cs} (98%) delete mode 100644 src/PDT.EssentialsPluginTemplate.nuspec rename src/{PDT.EssentialsPluginTemplate.EPI.csproj => epi-make-model.3Series.csproj} (82%) rename src/{PDT.EssentialsPluginTemplate.EPI.4Series..csproj => epi-make-model.4Series.csproj} (67%) diff --git a/.github/workflows/EssentialsPlugins-builds-caller.yml b/.github/workflows/EssentialsPlugins-builds-caller.yml index 6d9f244..63a2fcd 100644 --- a/.github/workflows/EssentialsPlugins-builds-caller.yml +++ b/.github/workflows/EssentialsPlugins-builds-caller.yml @@ -9,6 +9,7 @@ jobs: getVersion: uses: PepperDash/workflow-templates/.github/workflows/essentialsplugins-getversion.yml@main secrets: inherit + build-3Series: uses: PepperDash/workflow-templates/.github/workflows/essentialsplugins-3Series-builds.yml@main secrets: inherit @@ -19,6 +20,7 @@ jobs: version: ${{ needs.getVersion.outputs.version }} tag: ${{ needs.getVersion.outputs.tag }} channel: ${{ needs.getVersion.outputs.channel }} + build-4Series: uses: PepperDash/workflow-templates/.github/workflows/essentialsplugins-4Series-builds.yml@main secrets: inherit diff --git a/epi-make-model.3Series.sln b/epi-make-model.3Series.sln new file mode 100644 index 0000000..b106642 --- /dev/null +++ b/epi-make-model.3Series.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "epi-make-model.3Series", "src\epi-make-model.3Series.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 diff --git a/PDT.EssentialsPluginTemplate.EPI.4Series.sln b/epi-make-model.4Series.sln similarity index 83% rename from PDT.EssentialsPluginTemplate.EPI.4Series.sln rename to epi-make-model.4Series.sln index af0013f..e073161 100644 --- a/PDT.EssentialsPluginTemplate.EPI.4Series.sln +++ b/epi-make-model.4Series.sln @@ -3,7 +3,7 @@ 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}") = "PDT.EssentialsPluginTemplate.EPI.4Series.", "src\PDT.EssentialsPluginTemplate.EPI.4Series..csproj", "{52E6E0A0-A710-4B5F-AF52-08816F5C99BB}" +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 diff --git a/packages.config b/packages.config index 2a12f4c..c0df495 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index ef365ad..db59da5 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -5,7 +5,7 @@ PepperDash Technologies PepperDash Technologies PepperDash Essentials Plugin Template - Copyright © 2024 + Copyright © 2025 https://github.com/PepperDash/EssentialsPluginTemplate.git git Crestron; 4series diff --git a/src/EssentialsPluginTemplateBridgeJoinMap.cs b/src/MakeModelBridgeJoinMap.cs similarity index 94% rename from src/EssentialsPluginTemplateBridgeJoinMap.cs rename to src/MakeModelBridgeJoinMap.cs index 140d021..0d20a8f 100644 --- a/src/EssentialsPluginTemplateBridgeJoinMap.cs +++ b/src/MakeModelBridgeJoinMap.cs @@ -1,101 +1,101 @@ -using PepperDash.Essentials.Core; - -namespace EssentialsPluginTemplate -{ - ///

- /// Plugin device Bridge Join Map - /// - /// - /// Rename the class to match the device plugin being developed. Reference Essentials JoinMaps, if one exists for the device plugin being developed - /// - /// - /// - /// "EssentialsPluginBridgeJoinMapTemplate" renamed to "SamsungMdcBridgeJoinMap" - /// - public class EssentialsPluginTemplateBridgeJoinMap : JoinMapBaseAdvanced - { - #region Digital - - // TODO [ ] Add digital joins below plugin being developed - - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete( - new JoinData - { - JoinNumber = 1, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Is Online", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("Connect")] - public JoinDataComplete Connect = new JoinDataComplete( - new JoinData - { - JoinNumber = 2, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Connect (Held)/Disconnect (Release) & corresponding feedback", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - #endregion - - - #region Analog - - // TODO [ ] Add analog joins below plugin being developed - - [JoinName("Status")] - public JoinDataComplete Status = new JoinDataComplete( - new JoinData - { - JoinNumber = 1, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Socket Status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - #endregion - - - #region Serial - - // TODO [ ] Add serial joins below plugin being developed - - public JoinDataComplete DeviceName = new JoinDataComplete( - new JoinData - { - JoinNumber = 1, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Device Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - #endregion - - /// - /// Plugin device BridgeJoinMap constructor - /// - /// This will be the join it starts on the EISC bridge - public EssentialsPluginTemplateBridgeJoinMap(uint joinStart) - : base(joinStart, typeof(EssentialsPluginTemplateBridgeJoinMap)) - { - } - } +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Plugin +{ + /// + /// Plugin device Bridge Join Map + /// + /// + /// Rename the class to match the device plugin being developed. Reference Essentials JoinMaps, if one exists for the device plugin being developed + /// + /// + /// + /// "EssentialsPluginBridgeJoinMapTemplate" renamed to "SamsungMdcBridgeJoinMap" + /// + public class EssentialsPluginTemplateBridgeJoinMap : JoinMapBaseAdvanced + { + #region Digital + + // TODO [ ] Add digital joins below plugin being developed + + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Is Online", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Connect")] + public JoinDataComplete Connect = new JoinDataComplete( + new JoinData + { + JoinNumber = 2, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Connect (Held)/Disconnect (Release) & corresponding feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + #endregion + + + #region Analog + + // TODO [ ] Add analog joins below plugin being developed + + [JoinName("Status")] + public JoinDataComplete Status = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Socket Status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + #endregion + + + #region Serial + + // TODO [ ] Add serial joins below plugin being developed + + public JoinDataComplete DeviceName = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Device Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + #endregion + + /// + /// Plugin device BridgeJoinMap constructor + /// + /// This will be the join it starts on the EISC bridge + public EssentialsPluginTemplateBridgeJoinMap(uint joinStart) + : base(joinStart, typeof(EssentialsPluginTemplateBridgeJoinMap)) + { + } + } } \ No newline at end of file diff --git a/src/EssentialsPluginTemplateConfigObject.cs b/src/MakeModelConfigObject.cs similarity index 99% rename from src/EssentialsPluginTemplateConfigObject.cs rename to src/MakeModelConfigObject.cs index e216796..b247414 100644 --- a/src/EssentialsPluginTemplateConfigObject.cs +++ b/src/MakeModelConfigObject.cs @@ -1,8 +1,8 @@ -using System.Collections.Generic; -using Newtonsoft.Json; -using PepperDash.Essentials.Core; - -namespace EssentialsPluginTemplate +using System.Collections.Generic; +using Newtonsoft.Json; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Plugin { /// /// Plugin device configuration object diff --git a/src/EssentialsPluginTemplateCrestronDevice.cs b/src/MakeModelCrestronDevice.cs similarity index 98% rename from src/EssentialsPluginTemplateCrestronDevice.cs rename to src/MakeModelCrestronDevice.cs index 8836cc5..71c91c1 100644 --- a/src/EssentialsPluginTemplateCrestronDevice.cs +++ b/src/MakeModelCrestronDevice.cs @@ -1,13 +1,13 @@ // For Basic SIMPL# Classes -// For Basic SIMPL#Pro classes - -using Crestron.SimplSharpPro.DeviceSupport; -using Crestron.SimplSharpPro; -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Bridges; - -namespace EssentialsPluginTemplate +// For Basic SIMPL#Pro classes + +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges; + +namespace PepperDash.Essentials.Plugin { /// /// Plugin device diff --git a/src/EssentialsPluginTemplateDevice.cs b/src/MakeModelDevice.cs similarity index 96% rename from src/EssentialsPluginTemplateDevice.cs rename to src/MakeModelDevice.cs index b6d2031..da423a2 100644 --- a/src/EssentialsPluginTemplateDevice.cs +++ b/src/MakeModelDevice.cs @@ -1,299 +1,298 @@ -// For Basic SIMPL# Classes -// For Basic SIMPL#Pro classes - -using Crestron.SimplSharpPro.DeviceSupport; -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Bridges; -using PepperDash.Essentials.Core.Queues; - - -namespace EssentialsPluginTemplate -{ - /// - /// Plugin device template for third party devices that use IBasicCommunication - /// - /// - /// Rename the class to match the device plugin being developed. - /// - /// - /// "EssentialsPluginDeviceTemplate" renamed to "SamsungMdcDevice" - /// - public class EssentialsPluginTemplateDevice : EssentialsBridgeableDevice - { - /// - /// It is often desirable to store the config - /// - private EssentialsPluginTemplateConfigObject _config; - - /// - /// Provides a queue and dedicated worker thread for processing feedback messages from a device. - /// - private GenericQueue ReceiveQueue; - - #region IBasicCommunication Properties and Constructor. Remove if not needed. - - // TODO [ ] Add, modify, remove properties and fields as needed for the plugin being developed - private readonly IBasicCommunication _comms; - private readonly GenericCommunicationMonitor _commsMonitor; - - // _comms gather for ASCII based API's - // TODO [ ] If not using an ASCII based API, delete the properties below - private readonly CommunicationGather _commsGather; - - /// - /// Set this value to that of the delimiter used by the API (if applicable) - /// - private const string CommsDelimiter = "\r"; - - // _comms byte buffer for HEX/byte based API's - // TODO [ ] If not using an HEX/byte based API, delete the properties below - private byte[] _commsByteBuffer = { }; - - - - /// - /// Connects/disconnects the comms of the plugin device - /// - /// - /// triggers the _comms.Connect/Disconnect as well as thee comms monitor start/stop - /// - public bool Connect - { - get { return _comms.IsConnected; } - set - { - if (value) - { - _comms.Connect(); - _commsMonitor.Start(); - } - else - { - _comms.Disconnect(); - _commsMonitor.Stop(); - } - } - } - - /// - /// Reports connect feedback through the bridge - /// - public BoolFeedback ConnectFeedback { get; private set; } - - /// - /// Reports online feedback through the bridge - /// - public BoolFeedback OnlineFeedback { get; private set; } - - /// - /// Reports socket status feedback through the bridge - /// - public IntFeedback StatusFeedback { get; private set; } - - /// - /// Plugin device constructor for devices that need IBasicCommunication - /// - /// - /// - /// - /// - public EssentialsPluginTemplateDevice(string key, string name, EssentialsPluginTemplateConfigObject config, IBasicCommunication comms) - : base(key, name) - { - Debug.Console(0, this, "Constructing new {0} instance", name); - - // TODO [ ] Update the constructor as needed for the plugin device being developed - - _config = config; - - ReceiveQueue = new GenericQueue(key + "-rxqueue"); // If you need to set the thread priority, use one of the available overloaded constructors. - - ConnectFeedback = new BoolFeedback(() => Connect); - OnlineFeedback = new BoolFeedback(() => _commsMonitor.IsOnline); - StatusFeedback = new IntFeedback(() => (int)_commsMonitor.Status); - - _comms = comms; - _commsMonitor = new GenericCommunicationMonitor(this, _comms, _config.PollTimeMs, _config.WarningTimeoutMs, _config.ErrorTimeoutMs, Poll); - - var socket = _comms as ISocketStatus; - if (socket != null) - { - // device comms is IP **ELSE** device comms is RS232 - socket.ConnectionChange += socket_ConnectionChange; - Connect = true; - } - - #region Communication data event handlers. Comment out any that don't apply to the API type - - // Only one of the below handlers should be necessary. - - // _comms gather for any API that has a defined delimiter - // TODO [ ] If not using an ASCII based API, remove the line below - _commsGather = new CommunicationGather(_comms, CommsDelimiter); - _commsGather.LineReceived += Handle_LineRecieved; - - // _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 - _comms.BytesReceived += Handle_BytesReceived; - - // _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 - _comms.TextReceived += Handle_TextReceived; - - #endregion - } - - - private void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs args) - { - if (ConnectFeedback != null) - ConnectFeedback.FireUpdate(); - - if (StatusFeedback != null) - StatusFeedback.FireUpdate(); - } - - // TODO [ ] If not using an API with a delimeter, delete the method below - private void Handle_LineRecieved(object sender, GenericCommMethodReceiveTextArgs args) - { - // TODO [ ] Implement method - - // Enqueues the message to be processed in a dedicated thread, but the specified method - ReceiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessFeedbackMessage)); - } - - // TODO [ ] If not using an HEX/byte based API with no delimeter, delete the method below - private void Handle_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs args) - { - // TODO [ ] Implement method - throw new System.NotImplementedException(); - } - - // TODO [ ] If not using an ASCII based API with no delimeter, delete the method below - void Handle_TextReceived(object sender, GenericCommMethodReceiveTextArgs e) - { - // TODO [ ] Implement method - throw new System.NotImplementedException(); - } - - /// - /// This method should perform any necessary parsing of feedback messages from the device - /// - /// - void ProcessFeedbackMessage(string message) - { - - } - - - // TODO [ ] If not using an ACII based API, delete the properties below - /// - /// Sends text to the device plugin comms - /// - /// - /// Can be used to test commands with the device plugin using the DEVPROPS and DEVJSON console commands - /// - /// Command to be sent - public void SendText(string text) - { - if (string.IsNullOrEmpty(text)) return; - - _comms.SendText(string.Format("{0}{1}", text, CommsDelimiter)); - } - - // TODO [ ] If not using an HEX/byte based API, delete the properties below - /// - /// Sends bytes to the device plugin comms - /// - /// - /// Can be used to test commands with the device plugin using the DEVPROPS and DEVJSON console commands - /// - /// Bytes to be sent - public void SendBytes(byte[] bytes) - { - if (bytes == null) return; - - _comms.SendBytes(bytes); - } - - /// - /// Polls the device - /// - /// - /// Poll method is used by the communication monitor. Update the poll method as needed for the plugin being developed - /// - public void Poll() - { - // TODO [ ] Update Poll method as needed for the plugin being developed - // Example: SendText("getstatus"); - throw new System.NotImplementedException(); - } - - #endregion - - - #region Overrides of EssentialsBridgeableDevice - - /// - /// Links the plugin device to the EISC bridge - /// - /// - /// - /// - /// - 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 - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - - var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); - - if (customJoins != null) - { - joinMap.SetCustomJoinData(customJoins); - } - - Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - Debug.Console(0, "Linking to Bridge Type {0}", 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 - - } -} - +// For Basic SIMPL# Classes +// For Basic SIMPL#Pro classes + +using Crestron.SimplSharpPro.DeviceSupport; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core.Queues; + +namespace PepperDash.Essentials.Plugin +{ + /// + /// Plugin device template for third party devices that use IBasicCommunication + /// + /// + /// Rename the class to match the device plugin being developed. + /// + /// + /// "EssentialsPluginDeviceTemplate" renamed to "SamsungMdcDevice" + /// + public class EssentialsPluginTemplateDevice : EssentialsBridgeableDevice + { + /// + /// It is often desirable to store the config + /// + private EssentialsPluginTemplateConfigObject _config; + + /// + /// Provides a queue and dedicated worker thread for processing feedback messages from a device. + /// + private GenericQueue ReceiveQueue; + + #region IBasicCommunication Properties and Constructor. Remove if not needed. + + // TODO [ ] Add, modify, remove properties and fields as needed for the plugin being developed + private readonly IBasicCommunication _comms; + private readonly GenericCommunicationMonitor _commsMonitor; + + // _comms gather for ASCII based API's + // TODO [ ] If not using an ASCII based API, delete the properties below + private readonly CommunicationGather _commsGather; + + /// + /// Set this value to that of the delimiter used by the API (if applicable) + /// + private const string CommsDelimiter = "\r"; + + // _comms byte buffer for HEX/byte based API's + // TODO [ ] If not using an HEX/byte based API, delete the properties below + private byte[] _commsByteBuffer = { }; + + + + /// + /// Connects/disconnects the comms of the plugin device + /// + /// + /// triggers the _comms.Connect/Disconnect as well as thee comms monitor start/stop + /// + public bool Connect + { + get { return _comms.IsConnected; } + set + { + if (value) + { + _comms.Connect(); + _commsMonitor.Start(); + } + else + { + _comms.Disconnect(); + _commsMonitor.Stop(); + } + } + } + + /// + /// Reports connect feedback through the bridge + /// + public BoolFeedback ConnectFeedback { get; private set; } + + /// + /// Reports online feedback through the bridge + /// + public BoolFeedback OnlineFeedback { get; private set; } + + /// + /// Reports socket status feedback through the bridge + /// + public IntFeedback StatusFeedback { get; private set; } + + /// + /// Plugin device constructor for devices that need IBasicCommunication + /// + /// + /// + /// + /// + public EssentialsPluginTemplateDevice(string key, string name, EssentialsPluginTemplateConfigObject config, IBasicCommunication comms) + : base(key, name) + { + Debug.Console(0, this, "Constructing new {0} instance", name); + + // TODO [ ] Update the constructor as needed for the plugin device being developed + + _config = config; + + ReceiveQueue = new GenericQueue(key + "-rxqueue"); // If you need to set the thread priority, use one of the available overloaded constructors. + + ConnectFeedback = new BoolFeedback(() => Connect); + OnlineFeedback = new BoolFeedback(() => _commsMonitor.IsOnline); + StatusFeedback = new IntFeedback(() => (int)_commsMonitor.Status); + + _comms = comms; + _commsMonitor = new GenericCommunicationMonitor(this, _comms, _config.PollTimeMs, _config.WarningTimeoutMs, _config.ErrorTimeoutMs, Poll); + + var socket = _comms as ISocketStatus; + if (socket != null) + { + // device comms is IP **ELSE** device comms is RS232 + socket.ConnectionChange += socket_ConnectionChange; + Connect = true; + } + + #region Communication data event handlers. Comment out any that don't apply to the API type + + // Only one of the below handlers should be necessary. + + // _comms gather for any API that has a defined delimiter + // TODO [ ] If not using an ASCII based API, remove the line below + _commsGather = new CommunicationGather(_comms, CommsDelimiter); + _commsGather.LineReceived += Handle_LineRecieved; + + // _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 + _comms.BytesReceived += Handle_BytesReceived; + + // _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 + _comms.TextReceived += Handle_TextReceived; + + #endregion + } + + + private void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs args) + { + if (ConnectFeedback != null) + ConnectFeedback.FireUpdate(); + + if (StatusFeedback != null) + StatusFeedback.FireUpdate(); + } + + // TODO [ ] If not using an API with a delimeter, delete the method below + private void Handle_LineRecieved(object sender, GenericCommMethodReceiveTextArgs args) + { + // TODO [ ] Implement method + + // Enqueues the message to be processed in a dedicated thread, but the specified method + ReceiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessFeedbackMessage)); + } + + // TODO [ ] If not using an HEX/byte based API with no delimeter, delete the method below + private void Handle_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs args) + { + // TODO [ ] Implement method + throw new System.NotImplementedException(); + } + + // TODO [ ] If not using an ASCII based API with no delimeter, delete the method below + void Handle_TextReceived(object sender, GenericCommMethodReceiveTextArgs e) + { + // TODO [ ] Implement method + throw new System.NotImplementedException(); + } + + /// + /// This method should perform any necessary parsing of feedback messages from the device + /// + /// + void ProcessFeedbackMessage(string message) + { + + } + + + // TODO [ ] If not using an ACII based API, delete the properties below + /// + /// Sends text to the device plugin comms + /// + /// + /// Can be used to test commands with the device plugin using the DEVPROPS and DEVJSON console commands + /// + /// Command to be sent + public void SendText(string text) + { + if (string.IsNullOrEmpty(text)) return; + + _comms.SendText(string.Format("{0}{1}", text, CommsDelimiter)); + } + + // TODO [ ] If not using an HEX/byte based API, delete the properties below + /// + /// Sends bytes to the device plugin comms + /// + /// + /// Can be used to test commands with the device plugin using the DEVPROPS and DEVJSON console commands + /// + /// Bytes to be sent + public void SendBytes(byte[] bytes) + { + if (bytes == null) return; + + _comms.SendBytes(bytes); + } + + /// + /// Polls the device + /// + /// + /// Poll method is used by the communication monitor. Update the poll method as needed for the plugin being developed + /// + public void Poll() + { + // TODO [ ] Update Poll method as needed for the plugin being developed + // Example: SendText("getstatus"); + throw new System.NotImplementedException(); + } + + #endregion + + + #region Overrides of EssentialsBridgeableDevice + + /// + /// Links the plugin device to the EISC bridge + /// + /// + /// + /// + /// + 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 + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + + var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); + + if (customJoins != null) + { + joinMap.SetCustomJoinData(customJoins); + } + + Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + Debug.Console(0, "Linking to Bridge Type {0}", 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 + + } +} + diff --git a/src/EssentialsPluginTemplateFactory.cs b/src/MakeModelFactory.cs similarity index 99% rename from src/EssentialsPluginTemplateFactory.cs rename to src/MakeModelFactory.cs index 0b58f52..e94994a 100644 --- a/src/EssentialsPluginTemplateFactory.cs +++ b/src/MakeModelFactory.cs @@ -1,9 +1,9 @@ -using System.Collections.Generic; -using PepperDash.Core; -using PepperDash.Essentials.Core; -using Crestron.SimplSharpPro.UI; - -namespace EssentialsPluginTemplate +using System.Collections.Generic; +using Crestron.SimplSharpPro.UI; +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Plugin { /// /// Plugin device factory for devices that use IBasicCommunication diff --git a/src/EssentialsPluginTemplateLogicDevice.cs b/src/MakeModelLogicDevice.cs similarity index 98% rename from src/EssentialsPluginTemplateLogicDevice.cs rename to src/MakeModelLogicDevice.cs index 0685a43..44aeeec 100644 --- a/src/EssentialsPluginTemplateLogicDevice.cs +++ b/src/MakeModelLogicDevice.cs @@ -1,9 +1,9 @@ -using Crestron.SimplSharpPro.DeviceSupport; -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Bridges; - -namespace EssentialsPluginTemplate +using Crestron.SimplSharpPro.DeviceSupport; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges; + +namespace PepperDash.Essentials.Plugin { /// /// Plugin device template for logic devices that don't communicate outside the program diff --git a/src/PDT.EssentialsPluginTemplate.nuspec b/src/PDT.EssentialsPluginTemplate.nuspec deleted file mode 100644 index e72f807..0000000 --- a/src/PDT.EssentialsPluginTemplate.nuspec +++ /dev/null @@ -1,23 +0,0 @@ - - - - PDT.EssentialsPluginTemplate - docs\README.md - 2.0.2 - Essentials Plugin Template - PepperDash Technologies - pepperdash - false - MIT - https://github.com/PepperDash/EssentialsPluginTemplate - Copyright 2022 - This software iserves as a template for generating new Essentials-Compliant plugins - crestron 3series 4series essentials pepperdash pepperdashessentials epi essentials plugin - - - - - - - - \ No newline at end of file diff --git a/src/PDT.EssentialsPluginTemplate.EPI.csproj b/src/epi-make-model.3Series.csproj similarity index 82% rename from src/PDT.EssentialsPluginTemplate.EPI.csproj rename to src/epi-make-model.3Series.csproj index edda00c..03aa3ce 100644 --- a/src/PDT.EssentialsPluginTemplate.EPI.csproj +++ b/src/epi-make-model.3Series.csproj @@ -1,115 +1,115 @@ - - - Release - AnyCPU - 9.0.30729 - 2.0 - {9D249E47-8F95-4437-A6BB-563510287AD1} - Library - Properties - PDT.EssentialsPluginTemplate.EPI - PDT.EssentialsPluginTemplate.EPI - {0B4745B0-194B-4BB6-8E21-E9057CA92300};{4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - WindowsCE - E2BECB1F-8C8C-41ba-B736-9BE7D946A398 - 5.0 - SmartDeviceProject1 - v3.5 - Windows CE - - - - - .allowedReferenceRelatedFileExtensions - true - full - false - bin\Debug\ - DEBUG;TRACE; - prompt - 4 - 512 - true - true - off - - - .allowedReferenceRelatedFileExtensions - none - true - bin\Release\ - prompt - 4 - 512 - true - true - off - - - - False - ..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll - - - False - ..\packages\PepperDashEssentials\lib\net35\Essentials Devices Common.dll - - - - False - ..\packages\PepperDashEssentials\lib\net35\PepperDashEssentials.dll - - - False - ..\packages\PepperDashEssentials\lib\net35\PepperDash_Core.dll - - - False - ..\packages\PepperDashEssentials\lib\net35\PepperDash_Essentials_Core.dll - - - False - ..\packages\PepperDashEssentials\lib\net35\PepperDash_Essentials_DM.dll - - - False - ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll - False - - - False - ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll - False - - - False - ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll - - - False - ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe - False - - - False - ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll - - - - - - - - - - - - - - - - - - rem S# Pro preparation will execute after these operations - + + + Release + AnyCPU + 9.0.30729 + 2.0 + {9D249E47-8F95-4437-A6BB-563510287AD1} + Library + Properties + PepperDash.Essentials.Plugin + MakeModelPlugin + {0B4745B0-194B-4BB6-8E21-E9057CA92300};{4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + WindowsCE + E2BECB1F-8C8C-41ba-B736-9BE7D946A398 + 5.0 + SmartDeviceProject1 + v3.5 + Windows CE + + + + + .allowedReferenceRelatedFileExtensions + true + full + false + bin\Debug\ + DEBUG;TRACE; + prompt + 4 + 512 + true + true + off + + + .allowedReferenceRelatedFileExtensions + none + true + bin\Release\ + prompt + 4 + 512 + true + true + off + + + + False + C:\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll + + + False + ..\packages\PepperDashEssentials\lib\net35\Essentials Devices Common.dll + + + + False + ..\packages\PepperDashEssentials\lib\net35\PepperDashEssentials.dll + + + False + ..\packages\PepperDashEssentials\lib\net35\PepperDash_Core.dll + + + False + ..\packages\PepperDashEssentials\lib\net35\PepperDash_Essentials_Core.dll + + + False + ..\packages\PepperDashEssentials\lib\net35\PepperDash_Essentials_DM.dll + + + False + C:\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll + False + + + False + C:\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll + False + + + False + C:\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll + + + False + C:\ProgramData\Crestron\SDK\SimplSharpPro.exe + False + + + False + C:\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll + + + + + + + + + + + + + + + + + + rem S# Pro preparation will execute after these operations + \ No newline at end of file diff --git a/src/PDT.EssentialsPluginTemplate.EPI.4Series..csproj b/src/epi-make-model.4Series.csproj similarity index 67% rename from src/PDT.EssentialsPluginTemplate.EPI.4Series..csproj rename to src/epi-make-model.4Series.csproj index 1f930c1..59740a8 100644 --- a/src/PDT.EssentialsPluginTemplate.EPI.4Series..csproj +++ b/src/epi-make-model.4Series.csproj @@ -4,12 +4,12 @@ net472 - PDT.EssentialsPluginTemplate.EPI + PepperDash.Essentials.Plugin false - PDT.EssentialsPluginTemplate.EPI + PepperDash.Essentials.Plugin.Make.Model PepperDash Technologies This software is a template for a PepperDash Essentials Plugin. - Copyright 2024 + Copyright 2025 1.0.0-local true $(Version) @@ -31,10 +31,18 @@ - - + + - - - + + + + + + + + + + + \ No newline at end of file From eee7822de0d3cada3a0a534cf91cced3fda9b83b Mon Sep 17 00:00:00 2001 From: jdevito Date: Fri, 31 Jan 2025 08:23:32 -0600 Subject: [PATCH 27/36] feat: add updatedoc caller --- .../essentialsplugins-updatereadme-caller.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/workflows/essentialsplugins-updatereadme-caller.yml diff --git a/.github/workflows/essentialsplugins-updatereadme-caller.yml b/.github/workflows/essentialsplugins-updatereadme-caller.yml new file mode 100644 index 0000000..e3680bd --- /dev/null +++ b/.github/workflows/essentialsplugins-updatereadme-caller.yml @@ -0,0 +1,14 @@ + +name: Generate README + +on: + push: + branches-ignore: + - 'robot-docs' + +jobs: + call-update-readme: + uses: PepperDash/workflow-templates/.github/workflows/update-readme.yml@development + with: + target-branch: ${{ github.ref_name }} + From 61b8c51db2f64f81c00c1b860c910aee58dcc696 Mon Sep 17 00:00:00 2001 From: jdevito Date: Fri, 31 Jan 2025 08:23:54 -0600 Subject: [PATCH 28/36] chore: remove deleted file reference --- .github/workflows/EssentialsPlugins-builds-caller.yml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.github/workflows/EssentialsPlugins-builds-caller.yml b/.github/workflows/EssentialsPlugins-builds-caller.yml index 63a2fcd..606fcb9 100644 --- a/.github/workflows/EssentialsPlugins-builds-caller.yml +++ b/.github/workflows/EssentialsPlugins-builds-caller.yml @@ -10,17 +10,6 @@ jobs: uses: PepperDash/workflow-templates/.github/workflows/essentialsplugins-getversion.yml@main secrets: inherit - build-3Series: - uses: PepperDash/workflow-templates/.github/workflows/essentialsplugins-3Series-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 }} - build-4Series: uses: PepperDash/workflow-templates/.github/workflows/essentialsplugins-4Series-builds.yml@main secrets: inherit From 3f2ef8087761778d2372e1a711be640b40053b08 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 25 Mar 2025 10:53:56 -0500 Subject: [PATCH 29/36] Update epi-make-model.4Series.csproj Update 4Series.csproj to exlcude assets and change local bid output path. --- src/epi-make-model.4Series.csproj | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/epi-make-model.4Series.csproj b/src/epi-make-model.4Series.csproj index 59740a8..3f7a307 100644 --- a/src/epi-make-model.4Series.csproj +++ b/src/epi-make-model.4Series.csproj @@ -13,7 +13,7 @@ 1.0.0-local true $(Version) - 4Series\bin\$(Configuration)\ + bin\$(Configuration)\ PepperDash Technologies Pepperdash.Essentials.Plugins.Template https://github.com/PepperDash/EssentialsPluginTemplate.git @@ -35,7 +35,9 @@ - + + runtime + @@ -45,4 +47,4 @@ - \ No newline at end of file + From c225184021e621fd8c3b4cbd5d688f71c18ad256 Mon Sep 17 00:00:00 2001 From: Jason T Alborough Date: Tue, 25 Mar 2025 16:43:00 -0400 Subject: [PATCH 30/36] Rename releaserc.json to .releaserc.json --- releaserc.json => .releaserc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename releaserc.json => .releaserc.json (99%) diff --git a/releaserc.json b/.releaserc.json similarity index 99% rename from releaserc.json rename to .releaserc.json index c4bd268..e6ec36a 100644 --- a/releaserc.json +++ b/.releaserc.json @@ -31,4 +31,4 @@ "channel": "replace-me-prerelease" } ] -} \ No newline at end of file +} From 952d5b61a4b629b65a44cde876257b6457c09db6 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 25 Mar 2025 15:54:31 -0500 Subject: [PATCH 31/36] Update epi-make-model.4Series.csproj Update PepperDash Essentials version to 2.0.0 --- src/epi-make-model.4Series.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/epi-make-model.4Series.csproj b/src/epi-make-model.4Series.csproj index 3f7a307..929c2aa 100644 --- a/src/epi-make-model.4Series.csproj +++ b/src/epi-make-model.4Series.csproj @@ -35,7 +35,7 @@ - + runtime From 4283fb2abd9d34f26a9b29e035ed3f7a54f459f4 Mon Sep 17 00:00:00 2001 From: Jonathan Arndt Date: Wed, 21 May 2025 09:31:49 -0700 Subject: [PATCH 32/36] fix: Update README workflow to use main branch and correct author/company names in Directory.Build.props --- .github/workflows/essentialsplugins-updatereadme-caller.yml | 2 +- src/Directory.Build.props | 6 +++--- src/epi-make-model.4Series.csproj | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/essentialsplugins-updatereadme-caller.yml b/.github/workflows/essentialsplugins-updatereadme-caller.yml index e3680bd..8f4bbe3 100644 --- a/.github/workflows/essentialsplugins-updatereadme-caller.yml +++ b/.github/workflows/essentialsplugins-updatereadme-caller.yml @@ -8,7 +8,7 @@ on: jobs: call-update-readme: - uses: PepperDash/workflow-templates/.github/workflows/update-readme.yml@development + uses: PepperDash/workflow-templates/.github/workflows/update-readme.yml@main with: target-branch: ${{ github.ref_name }} diff --git a/src/Directory.Build.props b/src/Directory.Build.props index db59da5..206b6c0 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -2,14 +2,14 @@ 1.0.0-local $(Version) - PepperDash Technologies - PepperDash Technologies + PepperDash Technology + PepperDash Technology PepperDash Essentials Plugin Template Copyright © 2025 https://github.com/PepperDash/EssentialsPluginTemplate.git git Crestron; 4series - ../output + ..\output True LICENSE.md README.md diff --git a/src/epi-make-model.4Series.csproj b/src/epi-make-model.4Series.csproj index 929c2aa..7ac4bfa 100644 --- a/src/epi-make-model.4Series.csproj +++ b/src/epi-make-model.4Series.csproj @@ -7,14 +7,14 @@ PepperDash.Essentials.Plugin false PepperDash.Essentials.Plugin.Make.Model - PepperDash Technologies + PepperDash Technology This software is a template for a PepperDash Essentials Plugin. Copyright 2025 1.0.0-local true $(Version) bin\$(Configuration)\ - PepperDash Technologies + PepperDash Technology Pepperdash.Essentials.Plugins.Template https://github.com/PepperDash/EssentialsPluginTemplate.git crestron 4series essentials plugin template From cf3f35a53c1a5a4363e11893eda973688cc81aa1 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 29 Jul 2025 13:11:00 -0500 Subject: [PATCH 33/36] feat: update for Essentials 2 & remove deprecation warnings BREAKING CHANGE: Drop 3-series support --- .editorconfig | 20 +++ .vscode/extensions.json | 9 + .vscode/settings.json | 32 ++++ epi-make-model.3Series.sln | 20 --- packages.config | 3 - src/MakeModelConfigObject.cs | 20 +-- src/MakeModelCrestronDevice.cs | 53 +++--- src/MakeModelCrestronDeviceFactory.cs | 87 +++++++++ src/MakeModelDevice.cs | 248 +++++++++++++------------- src/MakeModelDeviceFactory.cs | 85 +++++++++ src/MakeModelFactory.cs | 239 ------------------------- src/MakeModelLogicDevice.cs | 46 +++-- src/MakeModelLogicDeviceFactory.cs | 83 +++++++++ src/epi-make-model.4Series.csproj | 2 +- 14 files changed, 496 insertions(+), 451 deletions(-) create mode 100644 .editorconfig create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json delete mode 100644 epi-make-model.3Series.sln delete mode 100644 packages.config create mode 100644 src/MakeModelCrestronDeviceFactory.cs create mode 100644 src/MakeModelDeviceFactory.cs delete mode 100644 src/MakeModelFactory.cs create mode 100644 src/MakeModelLogicDeviceFactory.cs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..466990d --- /dev/null +++ b/.editorconfig @@ -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 \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..48c5715 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "ms-dotnettools.vscode-dotnet-runtime", + "ms-dotnettools.csharp", + "ms-dotnettools.csdevkit", + "vivaxy.vscode-conventional-commits", + "mhutchie.git-graph" + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..1ac4b1c --- /dev/null +++ b/.vscode/settings.json @@ -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 +} \ No newline at end of file diff --git a/epi-make-model.3Series.sln b/epi-make-model.3Series.sln deleted file mode 100644 index b106642..0000000 --- a/epi-make-model.3Series.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "epi-make-model.3Series", "src\epi-make-model.3Series.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 diff --git a/packages.config b/packages.config deleted file mode 100644 index c0df495..0000000 --- a/packages.config +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/src/MakeModelConfigObject.cs b/src/MakeModelConfigObject.cs index b247414..0492f38 100644 --- a/src/MakeModelConfigObject.cs +++ b/src/MakeModelConfigObject.cs @@ -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 { /// @@ -14,7 +14,7 @@ namespace PepperDash.Essentials.Plugin /// "EssentialsPluginConfigObjectTemplate" renamed to "SamsungMdcConfig" /// [ConfigSnippet("\"properties\":{\"control\":{}")] - public class EssentialsPluginTemplateConfigObject + public class MakeModelConfig { /// /// JSON control object @@ -27,7 +27,7 @@ namespace PepperDash.Essentials.Plugin /// /// /// "control": { - /// "method": "tcpIp", + /// "method": "tcpIp", /// "controlPortDevKey": "processor", /// "controlPortNumber": 1, /// "comParams": { @@ -139,7 +139,7 @@ namespace PepperDash.Essentials.Plugin /// /// [JsonProperty("DeviceDictionary")] - public Dictionary DeviceDictionary { get; set; } + public Dictionary DeviceDictionary { get; set; } /// /// Constuctor @@ -148,9 +148,9 @@ namespace PepperDash.Essentials.Plugin /// If using a collection you must instantiate the collection in the constructor /// to avoid exceptions when reading the configuration file /// - public EssentialsPluginTemplateConfigObject() + public MakeModelConfig() { - DeviceDictionary = new Dictionary(); + DeviceDictionary = new Dictionary(); } } @@ -172,7 +172,7 @@ namespace PepperDash.Essentials.Plugin /// } /// /// - public class EssentialsPluginTemplateConfigObjectDictionary + public class MakeModelConfigDictionary { /// /// Serializes collection name property diff --git a/src/MakeModelCrestronDevice.cs b/src/MakeModelCrestronDevice.cs index 71c91c1..a60d7cb 100644 --- a/src/MakeModelCrestronDevice.cs +++ b/src/MakeModelCrestronDevice.cs @@ -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 { - /// - /// Plugin device - /// - /// - /// Rename the class to match the device plugin being developed. - /// - /// - /// "EssentialsPluginDeviceTemplate" renamed to "SamsungMdcDevice" - /// - public class EssentialsPluginTemplateCrestronDevice : CrestronGenericBridgeableBaseDevice + /// + /// Plugin device + /// + /// + /// Rename the class to match the device plugin being developed. + /// + /// + /// "EssentialsPluginDeviceTemplate" renamed to "SamsungMdcDevice" + /// + public class MakeModelCrestronDevice : CrestronGenericBridgeableBaseDevice { /// /// It is often desirable to store the config /// - private EssentialsPluginTemplateConfigObject _config; + private readonly MakeModelConfig config; #region Constructor for Devices without IBasicCommunication. Remove if not needed @@ -34,16 +34,16 @@ namespace PepperDash.Essentials.Plugin /// /// /// - 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 @@ -63,10 +63,7 @@ namespace PepperDash.Essentials.Plugin 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); @@ -75,8 +72,8 @@ namespace PepperDash.Essentials.Plugin 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 diff --git a/src/MakeModelCrestronDeviceFactory.cs b/src/MakeModelCrestronDeviceFactory.cs new file mode 100644 index 0000000..8e3a994 --- /dev/null +++ b/src/MakeModelCrestronDeviceFactory.cs @@ -0,0 +1,87 @@ +using System.Collections.Generic; +using Crestron.SimplSharpPro.UI; +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Plugin +{ + + /// + /// Plugin device factory for Crestron wrapper devices + /// + /// + /// Rename the class to match the device plugin being developed + /// + /// + /// "EssentialsPluginFactoryTemplate" renamed to "MyCrestronDeviceFactory" + /// + public class MakeModelCrestronDeviceFactory : EssentialsPluginDeviceFactory + { + /// + /// Plugin device factory constructor + /// + /// + /// Update the MinimumEssentialsFrameworkVersion & TypeNames as needed when creating a plugin + /// + /// + /// Set the minimum Essentials Framework Version + /// + /// MinimumEssentialsFrameworkVersion = "1.6.4; + /// + /// In the constructor we initialize the list with the typenames that will build an instance of this device + /// + /// TypeNames = new List() { "SamsungMdc", "SamsungMdcDisplay" }; + /// + /// + 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() { "examplePluginCrestronDevice" }; + } + + /// + /// Builds and returns an instance of EssentialsPluginTemplateCrestronDevice + /// + /// device configuration + /// plugin device or null + /// + /// 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. + /// + /// + 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(); + 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; + } + } + } + +} + diff --git a/src/MakeModelDevice.cs b/src/MakeModelDevice.cs index da423a2..ad89717 100644 --- a/src/MakeModelDevice.cs +++ b/src/MakeModelDevice.cs @@ -3,6 +3,7 @@ using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Core; +using PepperDash.Core.Logging; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Queues; @@ -18,36 +19,36 @@ namespace PepperDash.Essentials.Plugin /// /// "EssentialsPluginDeviceTemplate" renamed to "SamsungMdcDevice" /// - public class EssentialsPluginTemplateDevice : EssentialsBridgeableDevice - { - /// - /// It is often desirable to store the config - /// - private EssentialsPluginTemplateConfigObject _config; + public class MakeModelDevice : EssentialsBridgeableDevice + { + /// + /// It is often desirable to store the config + /// + private readonly MakeModelConfig config; - /// - /// Provides a queue and dedicated worker thread for processing feedback messages from a device. - /// - private GenericQueue ReceiveQueue; + /// + /// Provides a queue and dedicated worker thread for processing feedback messages from a device. + /// + private readonly GenericQueue receiveQueue; - #region IBasicCommunication Properties and Constructor. Remove if not needed. + #region IBasicCommunication Properties and Constructor. Remove if not needed. - // TODO [ ] Add, modify, remove properties and fields as needed for the plugin being developed - private readonly IBasicCommunication _comms; - private readonly GenericCommunicationMonitor _commsMonitor; + // TODO [ ] Add, modify, remove properties and fields as needed for the plugin being developed + private readonly IBasicCommunication comms; + private readonly GenericCommunicationMonitor commsMonitor; - // _comms gather for ASCII based API's + // comms gather for ASCII based API's // TODO [ ] If not using an ASCII based API, delete the properties below - private readonly CommunicationGather _commsGather; + private readonly CommunicationGather commsGather; - /// - /// Set this value to that of the delimiter used by the API (if applicable) - /// - private const string CommsDelimiter = "\r"; + /// + /// Set this value to that of the delimiter used by the API (if applicable) + /// + private const string commsDelimiter = "\r"; - // _comms byte buffer for HEX/byte based API's + // comms byte buffer for HEX/byte based API's // TODO [ ] If not using an HEX/byte based API, delete the properties below - private byte[] _commsByteBuffer = { }; + private readonly byte[] commsByteBuffer = { }; @@ -55,22 +56,22 @@ namespace PepperDash.Essentials.Plugin /// Connects/disconnects the comms of the plugin device /// /// - /// triggers the _comms.Connect/Disconnect as well as thee comms monitor start/stop + /// triggers the comms.Connect/Disconnect as well as thee comms monitor start/stop /// public bool Connect { - get { return _comms.IsConnected; } + get { return comms.IsConnected; } set { if (value) { - _comms.Connect(); - _commsMonitor.Start(); + comms.Connect(); + commsMonitor.Start(); } else { - _comms.Disconnect(); - _commsMonitor.Stop(); + comms.Disconnect(); + commsMonitor.Stop(); } } } @@ -97,93 +98,91 @@ namespace PepperDash.Essentials.Plugin /// /// /// - public EssentialsPluginTemplateDevice(string key, string name, EssentialsPluginTemplateConfigObject config, IBasicCommunication comms) - : base(key, name) + public MakeModelDevice(string key, string name, MakeModelConfig config, IBasicCommunication comms) + : base(key, name) { - Debug.Console(0, this, "Constructing new {0} instance", name); + this.LogInformation("Constructing new {0} instance", name); // TODO [ ] Update the constructor as needed for the plugin device being developed - _config = config; + this.config = config; - ReceiveQueue = new GenericQueue(key + "-rxqueue"); // If you need to set the thread priority, use one of the available overloaded constructors. + receiveQueue = new GenericQueue(key + "-rxqueue"); // If you need to set the thread priority, use one of the available overloaded constructors. - ConnectFeedback = new BoolFeedback(() => Connect); - OnlineFeedback = new BoolFeedback(() => _commsMonitor.IsOnline); - StatusFeedback = new IntFeedback(() => (int)_commsMonitor.Status); + ConnectFeedback = new BoolFeedback("connect", () => Connect); + OnlineFeedback = new BoolFeedback("online", () => commsMonitor.IsOnline); + StatusFeedback = new IntFeedback("status", () => (int)commsMonitor.Status); - _comms = comms; - _commsMonitor = new GenericCommunicationMonitor(this, _comms, _config.PollTimeMs, _config.WarningTimeoutMs, _config.ErrorTimeoutMs, Poll); + this.comms = comms; + commsMonitor = new GenericCommunicationMonitor(this, this.comms, this.config.PollTimeMs, this.config.WarningTimeoutMs, this.config.ErrorTimeoutMs, Poll); - var socket = _comms as ISocketStatus; + var socket = this.comms as ISocketStatus; if (socket != null) { // device comms is IP **ELSE** device comms is RS232 socket.ConnectionChange += socket_ConnectionChange; Connect = true; - } + } - #region Communication data event handlers. Comment out any that don't apply to the API type + #region Communication data event handlers. Comment out any that don't apply to the API type - // Only one of the below handlers should be necessary. + // Only one of the below handlers should be necessary. - // _comms gather for any API that has a defined delimiter + // comms gather for any API that has a defined delimiter // TODO [ ] If not using an ASCII based API, remove the line below - _commsGather = new CommunicationGather(_comms, CommsDelimiter); - _commsGather.LineReceived += Handle_LineRecieved; + commsGather = new CommunicationGather(this.comms, commsDelimiter); + commsGather.LineReceived += Handle_LineRecieved; - // _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 - _comms.BytesReceived += Handle_BytesReceived; + // 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; - // _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 - _comms.TextReceived += Handle_TextReceived; + // 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.TextReceived += Handle_TextReceived; - #endregion - } + #endregion + } private void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs args) { - if (ConnectFeedback != null) - ConnectFeedback.FireUpdate(); + ConnectFeedback?.FireUpdate(); - if (StatusFeedback != null) - StatusFeedback.FireUpdate(); + StatusFeedback?.FireUpdate(); } // TODO [ ] If not using an API with a delimeter, delete the method below private void Handle_LineRecieved(object sender, GenericCommMethodReceiveTextArgs args) { // TODO [ ] Implement method - - // Enqueues the message to be processed in a dedicated thread, but the specified method - ReceiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessFeedbackMessage)); + + // Enqueues the message to be processed in a dedicated thread, but the specified method + receiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessFeedbackMessage)); } - // TODO [ ] If not using an HEX/byte based API with no delimeter, delete the method below + // TODO [ ] If not using an HEX/byte based API with no delimeter, delete the method below private void Handle_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs args) { // TODO [ ] Implement method throw new System.NotImplementedException(); } - // TODO [ ] If not using an ASCII based API with no delimeter, delete the method below - void Handle_TextReceived(object sender, GenericCommMethodReceiveTextArgs e) - { - // TODO [ ] Implement method - throw new System.NotImplementedException(); - } + // TODO [ ] If not using an ASCII based API with no delimeter, delete the method below + void Handle_TextReceived(object sender, GenericCommMethodReceiveTextArgs e) + { + // TODO [ ] Implement method + throw new System.NotImplementedException(); + } - /// - /// This method should perform any necessary parsing of feedback messages from the device - /// - /// - void ProcessFeedbackMessage(string message) - { + /// + /// This method should perform any necessary parsing of feedback messages from the device + /// + /// + void ProcessFeedbackMessage(string message) + { - } + } // TODO [ ] If not using an ACII based API, delete the properties below @@ -198,7 +197,7 @@ namespace PepperDash.Essentials.Plugin { if (string.IsNullOrEmpty(text)) return; - _comms.SendText(string.Format("{0}{1}", text, CommsDelimiter)); + comms.SendText(string.Format("{0}{1}", text, commsDelimiter)); } // TODO [ ] If not using an HEX/byte based API, delete the properties below @@ -213,7 +212,7 @@ namespace PepperDash.Essentials.Plugin { if (bytes == null) return; - _comms.SendBytes(bytes); + comms.SendBytes(bytes); } /// @@ -225,74 +224,71 @@ namespace PepperDash.Essentials.Plugin public void Poll() { // TODO [ ] Update Poll method as needed for the plugin being developed - // Example: SendText("getstatus"); + // Example: SendText("getstatus"); throw new System.NotImplementedException(); - } + } - #endregion + #endregion - #region Overrides of EssentialsBridgeableDevice + #region Overrides of EssentialsBridgeableDevice - /// - /// Links the plugin device to the EISC bridge - /// - /// - /// - /// - /// - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = new EssentialsPluginTemplateBridgeJoinMap(joinStart); + /// + /// Links the plugin device to the EISC bridge + /// + /// + /// + /// + /// + 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 - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } + // This adds the join map to the collection on the bridge + bridge?.AddJoinMap(Key, joinMap); - var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); + var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); - if (customJoins != null) - { - joinMap.SetCustomJoinData(customJoins); - } + if (customJoins != null) + { + 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 + // TODO [ ] Implement bridge links as needed - // links to bridge - trilist.SetString(joinMap.DeviceName.JoinNumber, Name); + // links to bridge + trilist.SetString(joinMap.DeviceName.JoinNumber, Name); - trilist.SetBoolSigAction(joinMap.Connect.JoinNumber, sig => Connect = sig); - ConnectFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Connect.JoinNumber]); + 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]); + StatusFeedback.LinkInputSig(trilist.UShortInput[joinMap.Status.JoinNumber]); + OnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); - UpdateFeedbacks(); + UpdateFeedbacks(); - trilist.OnlineStatusChange += (o, a) => - { - if (!a.DeviceOnLine) return; + trilist.OnlineStatusChange += (o, a) => + { + if (!a.DeviceOnLine) return; - trilist.SetString(joinMap.DeviceName.JoinNumber, Name); - UpdateFeedbacks(); - }; - } + 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(); - } + private void UpdateFeedbacks() + { + // TODO [ ] Update as needed for the plugin being developed + ConnectFeedback.FireUpdate(); + OnlineFeedback.FireUpdate(); + StatusFeedback.FireUpdate(); + } - #endregion + #endregion - } + } } diff --git a/src/MakeModelDeviceFactory.cs b/src/MakeModelDeviceFactory.cs new file mode 100644 index 0000000..b767a29 --- /dev/null +++ b/src/MakeModelDeviceFactory.cs @@ -0,0 +1,85 @@ +using System.Collections.Generic; +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Plugin +{ + /// + /// Plugin device factory for devices that use IBasicCommunication + /// + /// + /// Rename the class to match the device plugin being developed + /// + /// + /// "EssentialsPluginFactoryTemplate" renamed to "MyDeviceFactory" + /// + public class MakeModelDeviceFactory : EssentialsPluginDeviceFactory + { + /// + /// Plugin device factory constructor + /// + /// + /// Update the MinimumEssentialsFrameworkVersion & TypeNames as needed when creating a plugin + /// + /// + /// Set the minimum Essentials Framework Version + /// + /// MinimumEssentialsFrameworkVersion = "2.12.1; + /// + /// In the constructor we initialize the list with the typenames that will build an instance of this device + /// + /// TypeNames = new List() { "SamsungMdc", "SamsungMdcDisplay" }; + /// + /// + 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() { "examplePluginDevice" }; + } + + /// + /// Builds and returns an instance of EssentialsPluginDeviceTemplate + /// + /// device configuration + /// plugin device or null + /// + /// 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. + /// + /// + 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(); + 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); + } + + } + + } + +} + diff --git a/src/MakeModelFactory.cs b/src/MakeModelFactory.cs deleted file mode 100644 index e94994a..0000000 --- a/src/MakeModelFactory.cs +++ /dev/null @@ -1,239 +0,0 @@ -using System.Collections.Generic; -using Crestron.SimplSharpPro.UI; -using PepperDash.Core; -using PepperDash.Essentials.Core; - -namespace PepperDash.Essentials.Plugin -{ - /// - /// Plugin device factory for devices that use IBasicCommunication - /// - /// - /// Rename the class to match the device plugin being developed - /// - /// - /// "EssentialsPluginFactoryTemplate" renamed to "MyDeviceFactory" - /// - public class EssentialsPluginTemplateFactory : EssentialsPluginDeviceFactory - { - /// - /// Plugin device factory constructor - /// - /// - /// Update the MinimumEssentialsFrameworkVersion & TypeNames as needed when creating a plugin - /// - /// - /// Set the minimum Essentials Framework Version - /// - /// MinimumEssentialsFrameworkVersion = "1.6.4; - /// - /// In the constructor we initialize the list with the typenames that will build an instance of this device - /// - /// TypeNames = new List() { "SamsungMdc", "SamsungMdcDisplay" }; - /// - /// - public EssentialsPluginTemplateFactory() - { - // 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() { "examplePluginDevice" }; - } - - /// - /// Builds and returns an instance of EssentialsPluginDeviceTemplate - /// - /// device configuration - /// plugin device or null - /// - /// 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. - /// - /// - 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(); - if (propertiesConfig == null) - { - Debug.Console(0, "[{0}] Factory: failed to read properties config for {1}", 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.Console(1, "[{0}] Factory Notice: No control object present for device {1}", dc.Key, dc.Name); - return null; - } - else - { - return new EssentialsPluginTemplateDevice(dc.Key, dc.Name, propertiesConfig, comms); - } - - } - - } - - /// - /// Plugin device factory for logic devices that don't communicate - /// - /// - /// Rename the class to match the device plugin being developed - /// - /// - /// "EssentialsPluginFactoryTemplate" renamed to "MyLogicDeviceFactory" - /// - public class EssentialsPluginTemplateFactoryLogicDevice : EssentialsPluginDeviceFactory - { - /// - /// Plugin device factory constructor - /// - /// - /// Update the MinimumEssentialsFrameworkVersion & TypeNames as needed when creating a plugin - /// - /// - /// Set the minimum Essentials Framework Version - /// - /// MinimumEssentialsFrameworkVersion = "1.6.4; - /// - /// In the constructor we initialize the list with the typenames that will build an instance of this device - /// - /// TypeNames = new List() { "SamsungMdc", "SamsungMdcDisplay" }; - /// - /// - public EssentialsPluginTemplateFactoryLogicDevice() - { - // 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() { "examplePluginLogicDevice" }; - } - - /// - /// Builds and returns an instance of EssentialsPluginTemplateLogicDevice - /// - /// device configuration - /// plugin device or null - /// - /// 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. - /// - /// - 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(); - if (propertiesConfig == null) - { - Debug.Console(0, "[{0}] Factory: failed to read properties config for {1}", dc.Key, dc.Name); - return null; - } - - var controlConfig = CommFactory.GetControlPropertiesConfig(dc); - - if (controlConfig == null) - { - return new EssentialsPluginTemplateLogicDevice(dc.Key, dc.Name, propertiesConfig); - } - else - { - Debug.Console(0, "[{0}] Factory: Unable to get control properties from device config for {1}", dc.Key, dc.Name); - return null; - } - } - } - - /// - /// Plugin device factory for Crestron wrapper devices - /// - /// - /// Rename the class to match the device plugin being developed - /// - /// - /// "EssentialsPluginFactoryTemplate" renamed to "MyCrestronDeviceFactory" - /// - public class EssentialsPluginTemplateFactoryCrestronDevice : EssentialsPluginDeviceFactory - { - /// - /// Plugin device factory constructor - /// - /// - /// Update the MinimumEssentialsFrameworkVersion & TypeNames as needed when creating a plugin - /// - /// - /// Set the minimum Essentials Framework Version - /// - /// MinimumEssentialsFrameworkVersion = "1.6.4; - /// - /// In the constructor we initialize the list with the typenames that will build an instance of this device - /// - /// TypeNames = new List() { "SamsungMdc", "SamsungMdcDisplay" }; - /// - /// - public EssentialsPluginTemplateFactoryCrestronDevice() - { - // Set the minimum Essentials Framework Version - // TODO [ ] Update the Essentials minimum framework version which this plugin has been tested against - MinimumEssentialsFrameworkVersion = "1.7.5"; - - // 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() { "examplePluginCrestronDevice" }; - } - - /// - /// Builds and returns an instance of EssentialsPluginTemplateCrestronDevice - /// - /// device configuration - /// plugin device or null - /// - /// 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. - /// - /// - 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(); - if (propertiesConfig == null) - { - Debug.Console(0, "[{0}] Factory: failed to read properties config for {1}", dc.Key, dc.Name); - return null; - } - - var controlConfig = CommFactory.GetControlPropertiesConfig(dc); - - if (controlConfig == null) - { - var myTouchpanel = new Tsw760(controlConfig.IpIdInt, Global.ControlSystem); - - return new EssentialsPluginTemplateCrestronDevice(dc.Key, dc.Name, propertiesConfig, myTouchpanel); - } - else - { - Debug.Console(0, "[{0}] Factory: Unable to get control properties from device config for {1}", dc.Key, dc.Name); - return null; - } - } - } - -} - - \ No newline at end of file diff --git a/src/MakeModelLogicDevice.cs b/src/MakeModelLogicDevice.cs index 44aeeec..02b3d35 100644 --- a/src/MakeModelLogicDevice.cs +++ b/src/MakeModelLogicDevice.cs @@ -1,25 +1,26 @@ -using Crestron.SimplSharpPro.DeviceSupport; -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Bridges; - +using Crestron.SimplSharpPro.DeviceSupport; +using PepperDash.Core; +using PepperDash.Core.Logging; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges; + namespace PepperDash.Essentials.Plugin { - /// - /// Plugin device template for logic devices that don't communicate outside the program - /// - /// - /// Rename the class to match the device plugin being developed. - /// - /// + /// + /// Plugin device template for logic devices that don't communicate outside the program + /// + /// + /// Rename the class to match the device plugin being developed. + /// + /// /// "EssentialsPluginTemplateLogicDevice" renamed to "SamsungMdcDevice" - /// - public class EssentialsPluginTemplateLogicDevice : EssentialsBridgeableDevice + /// + public class MakeModelLogicDevice : EssentialsBridgeableDevice { /// /// It is often desirable to store the config /// - private EssentialsPluginTemplateConfigObject _config; + private readonly MakeModelConfig config; /// /// Plugin device constructor @@ -27,14 +28,14 @@ namespace PepperDash.Essentials.Plugin /// /// /// - public EssentialsPluginTemplateLogicDevice(string key, string name, EssentialsPluginTemplateConfigObject config) + public MakeModelLogicDevice(string key, string name, MakeModelConfig config) : base(key, name) { - Debug.Console(0, this, "Constructing new {0} instance", name); + this.LogInformation("Constructing new {0} instance", name); // TODO [ ] Update the constructor as needed for the plugin device being developed - _config = config; + this.config = config; } #region Overrides of EssentialsBridgeableDevice @@ -51,10 +52,7 @@ namespace PepperDash.Essentials.Plugin 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); @@ -63,8 +61,8 @@ namespace PepperDash.Essentials.Plugin 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 diff --git a/src/MakeModelLogicDeviceFactory.cs b/src/MakeModelLogicDeviceFactory.cs new file mode 100644 index 0000000..1f8cfa2 --- /dev/null +++ b/src/MakeModelLogicDeviceFactory.cs @@ -0,0 +1,83 @@ +using System.Collections.Generic; +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Plugin +{ + /// + /// Plugin device factory for logic devices that don't communicate + /// + /// + /// Rename the class to match the device plugin being developed + /// + /// + /// "EssentialsPluginFactoryTemplate" renamed to "MyLogicDeviceFactory" + /// + public class MakeModelLogicDeviceFactory : EssentialsPluginDeviceFactory + { + /// + /// Plugin device factory constructor + /// + /// + /// Update the MinimumEssentialsFrameworkVersion & TypeNames as needed when creating a plugin + /// + /// + /// Set the minimum Essentials Framework Version + /// + /// MinimumEssentialsFrameworkVersion = "1.6.4; + /// + /// In the constructor we initialize the list with the typenames that will build an instance of this device + /// + /// TypeNames = new List() { "SamsungMdc", "SamsungMdcDisplay" }; + /// + /// + 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() { "examplePluginLogicDevice" }; + } + + /// + /// Builds and returns an instance of EssentialsPluginTemplateLogicDevice + /// + /// device configuration + /// plugin device or null + /// + /// 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. + /// + /// + 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(); + 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; + } + } + } + +} + diff --git a/src/epi-make-model.4Series.csproj b/src/epi-make-model.4Series.csproj index 7ac4bfa..081ac42 100644 --- a/src/epi-make-model.4Series.csproj +++ b/src/epi-make-model.4Series.csproj @@ -35,7 +35,7 @@ - + runtime From 22faf9ef109b4d49558f28a6ca6b445006a0f158 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 29 Jul 2025 13:52:27 -0500 Subject: [PATCH 34/36] fix: use correct null check --- src/MakeModelCrestronDeviceFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MakeModelCrestronDeviceFactory.cs b/src/MakeModelCrestronDeviceFactory.cs index 8e3a994..f014b95 100644 --- a/src/MakeModelCrestronDeviceFactory.cs +++ b/src/MakeModelCrestronDeviceFactory.cs @@ -69,7 +69,7 @@ namespace PepperDash.Essentials.Plugin var controlConfig = CommFactory.GetControlPropertiesConfig(dc); - if (controlConfig == null) + if (controlConfig != null) { var myTouchpanel = new Tsw760(controlConfig.IpIdInt, Global.ControlSystem); From a86f97c4f4c5f239f2cdd2fd8f74e84f209bbd3c Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 29 Jul 2025 14:00:20 -0500 Subject: [PATCH 35/36] docs: update readme --- README.md | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 458eca2..9d2df4d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![PepperDash Essentials Pluign Logo](/images/essentials-plugin-blue.png) -# Essentials Plugin Template (c) 2023 +# Essentials Plugin Template (c) 2025 ## License @@ -8,14 +8,14 @@ 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. @@ -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 @@ -46,15 +39,10 @@ For renaming instructions in particular, see the XML `remarks` tags on class def ## Build Instructions (PepperDash Internal) -## Generating Nuget Package +## Generating Nuget Package -In the solution folder is a file named "PDT.EssentialsPluginTemplate.nuspec" +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: -1. Rename the file to match your plugin solution name -2. Edit the file to include your project specifics including - 1. PepperDash.Essentials.Plugin.MakeModel Convention is to use the prefix "PepperDash.Essentials.Plugin" and include the MakeModel of the device. - 2. https://github.com/PepperDash/EssentialsPluginTemplate 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__ \ No newline at end of file +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 \ No newline at end of file From 09a6270da8b3396b8c2e74fe3363ea931e3ec3db Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Tue, 29 Jul 2025 19:05:42 +0000 Subject: [PATCH 36/36] Automated README update --- README.md | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9d2df4d..5f6993e 100644 --- a/README.md +++ b/README.md @@ -45,4 +45,77 @@ A nuget package is automatically generated when the plugin is build. To modify t 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 \ No newline at end of file +3. `AssemblyTitle` - This is the dll file name that is will show on a processor when the plugin is loaded + +### Minimum Essentials Framework Versions + +- 2.12.1 +- 2.12.1 +- 2.12.1 + + +### Config Example + +```json +{ + "key": "GeneratedKey", + "uid": 1, + "name": "GeneratedName", + "type": "examplePluginDevice", + "group": "Group", + "properties": { + "control": "SampleValue", + "pollTimeMs": 0, + "warningTimeoutMs": 0, + "errorTimeoutMs": 0, + "DeviceDictionary": { + "SampleString": { + "name": "SampleString", + "value": "SampleValue" + } + } + } +} +``` + + +### Supported Types + +- examplePluginDevice +- examplePluginCrestronDevice +- examplePluginLogicDevice + + + + + + + + +### Base Classes + +- CrestronGenericBridgeableBaseDevice +- EssentialsBridgeableDevice +- JoinMapBaseAdvanced + + +### Public Methods + +- public void SendText(string text) +- public void SendBytes(byte[] bytes) +- public void Poll() + + +### Bool Feedbacks + +- ConnectFeedback +- OnlineFeedback + + +### Int Feedbacks + +- StatusFeedback + + + +