mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-16 13:15:03 +00:00
Compare commits
8 Commits
3.0.0-beta
...
feature-2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
afc37f5426 | ||
|
|
4ed5bb7ada | ||
|
|
4360e7f992 | ||
|
|
f926db418d | ||
|
|
0944be2a70 | ||
|
|
bacc0a4f57 | ||
|
|
1d49ea67ad | ||
|
|
35018b3572 |
140
.github/workflows/docker.yml
vendored
Normal file
140
.github/workflows/docker.yml
vendored
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
name: Branch Build Using Docker
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- feature-2.0.0/*
|
||||||
|
- hotfix-2.0.0/*
|
||||||
|
- release-2.0.0/*
|
||||||
|
- development-2.0.0
|
||||||
|
|
||||||
|
env:
|
||||||
|
# solution path doesn't need slashes unless there it is multiple folders deep
|
||||||
|
# solution name does not include extension. .sln is assumed
|
||||||
|
SOLUTION_PATH: .
|
||||||
|
SOLUTION_FILE: PepperDash.Essentials
|
||||||
|
# Do not edit this, we're just creating it here
|
||||||
|
VERSION: 0.0.0-buildtype-buildnumber
|
||||||
|
# Defaults to debug for build type
|
||||||
|
BUILD_TYPE: Debug
|
||||||
|
# Defaults to main as the release branch. Change as necessary
|
||||||
|
RELEASE_BRANCH: main
|
||||||
|
jobs:
|
||||||
|
Build_Project_4-Series:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Set Version Number
|
||||||
|
id: setVersion
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
$latestVersion = [version]"2.0.0"
|
||||||
|
|
||||||
|
$newVersion = [version]$latestVersion
|
||||||
|
$phase = ""
|
||||||
|
$newVersionString = ""
|
||||||
|
|
||||||
|
switch -regex ($Env:GITHUB_REF) {
|
||||||
|
'^refs\/pull\/*.' {
|
||||||
|
$phase = 'beta';
|
||||||
|
$newVersionString = "{0}-{1}-{2}" -f $newVersion, $phase, $Env:GITHUB_RUN_NUMBER
|
||||||
|
}
|
||||||
|
'^refs\/heads\/hotfix-2.0.0\/*.' {
|
||||||
|
$phase = 'hotfix'
|
||||||
|
$newVersionString = "{0}-{1}-{2}" -f $newVersion, $phase, $Env:GITHUB_RUN_NUMBER
|
||||||
|
}
|
||||||
|
'^refs\/heads\/release-2.0.0\/*.' {
|
||||||
|
$splitRef = $Env:GITHUB_REF -split "/"
|
||||||
|
$version = [version]($splitRef[-1] -replace "v", "")
|
||||||
|
$phase = 'rc'
|
||||||
|
$newVersionString = "{0}-{1}-{2}" -f $version, $phase, $Env:GITHUB_RUN_NUMBER
|
||||||
|
}
|
||||||
|
'^refs\/heads\/feature-2.0.0\/*.' {
|
||||||
|
$phase = 'alpha'
|
||||||
|
$newVersionString = "{0}-{1}-{2}" -f $newVersion, $phase, $Env:GITHUB_RUN_NUMBER
|
||||||
|
}
|
||||||
|
'development-2.0.0' {
|
||||||
|
$phase = 'beta'
|
||||||
|
$newVersionString = "{0}-{1}-{2}" -f $newVersion, $phase, $Env:GITHUB_RUN_NUMBER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo "version=$newVersionString" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
|
||||||
|
- name: Setup MS Build
|
||||||
|
uses: microsoft/setup-msbuild@v1.1
|
||||||
|
- name: restore Nuget Packages
|
||||||
|
run: nuget restore .\$($Env:SOLUTION_FILE).sln
|
||||||
|
# Build the solutions in the docker image
|
||||||
|
- name: Build Solution
|
||||||
|
run: msbuild .\$($Env:SOLUTION_FILE).sln /p:Platform="Any CPU" /p:Configuration="Debug" /p:Version="${{ steps.setVersion.outputs.version }}" -m
|
||||||
|
- name: Debug CPZ Files
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
Write-Host "Checking for CPZ files..."
|
||||||
|
|
||||||
|
# First, let's find out the actual directory structure
|
||||||
|
Write-Host "Current directory: $(Get-Location)"
|
||||||
|
Write-Host "Directory structure:"
|
||||||
|
Get-ChildItem -Path . -Directory -Recurse -Depth 2 | ForEach-Object { Write-Host $_.FullName }
|
||||||
|
|
||||||
|
# Look for all CPZ files in the repository
|
||||||
|
Write-Host "Searching for all CPZ files in the repository:"
|
||||||
|
$cpzFiles = Get-ChildItem -Path . -Recurse -Filter "*.cpz"
|
||||||
|
if ($cpzFiles.Count -eq 0) {
|
||||||
|
Write-Host "No CPZ files found in the repository."
|
||||||
|
} else {
|
||||||
|
Write-Host "Found $($cpzFiles.Count) CPZ files:"
|
||||||
|
foreach ($file in $cpzFiles) {
|
||||||
|
Write-Host " $($file.FullName)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create output directory if it doesn't exist
|
||||||
|
$outputDir = ".\output\build"
|
||||||
|
if (-not (Test-Path $outputDir)) {
|
||||||
|
New-Item -ItemType Directory -Path $outputDir -Force
|
||||||
|
Write-Host "Created output directory: $outputDir"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy all CPZ files to the output directory
|
||||||
|
foreach ($file in $cpzFiles) {
|
||||||
|
$destPath = Join-Path $outputDir $file.Name
|
||||||
|
Write-Host "Copying $($file.FullName) to $destPath"
|
||||||
|
Copy-Item -Path $file.FullName -Destination $destPath -Force
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- name: Pack Solution
|
||||||
|
run: |
|
||||||
|
dotnet pack .\$($Env:SOLUTION_FILE).sln --configuration $env:BUILD_TYPE --output ./output /p:Version="${{ steps.setVersion.outputs.version }}"
|
||||||
|
|
||||||
|
# Ensure CPZ files are included in the package
|
||||||
|
$cpzFiles = Get-ChildItem -Path . -Recurse | Where-Object { $_.Extension -eq ".cpz" }
|
||||||
|
if ($cpzFiles.Count -eq 0) {
|
||||||
|
Write-Host "WARNING: No CPZ files found!"
|
||||||
|
} else {
|
||||||
|
Write-Host "Found $($cpzFiles.Count) CPZ files"
|
||||||
|
foreach ($file in $cpzFiles) {
|
||||||
|
Write-Host "CPZ file: $($file.FullName)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- name: Create tag for non-rc builds
|
||||||
|
if: contains(steps.setVersion.outputs.version, 'alpha')
|
||||||
|
run: |
|
||||||
|
git tag ${{ steps.setVersion.outputs.version }}
|
||||||
|
git push --tags origin
|
||||||
|
# Create the release on the source repo
|
||||||
|
- name: Create Release
|
||||||
|
id: create_release
|
||||||
|
uses: ncipollo/release-action@v1
|
||||||
|
with:
|
||||||
|
artifacts: 'output\**\*.*(cpz|cplz)'
|
||||||
|
generateReleaseNotes: true
|
||||||
|
prerelease: ${{contains('debug', env.BUILD_TYPE)}}
|
||||||
|
tag: ${{ steps.setVersion.outputs.version }}
|
||||||
|
- name: Setup Nuget
|
||||||
|
run: |
|
||||||
|
nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username pepperdash -password ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
nuget setApiKey ${{ secrets.GITHUB_TOKEN }} -Source github
|
||||||
|
nuget setApiKey ${{ secrets.NUGET_API_KEY }} -Source https://api.nuget.org/v3/index.json
|
||||||
|
- name: Publish to Nuget
|
||||||
|
run: nuget push .\output\*.nupkg -Source https://api.nuget.org/v3/index.json
|
||||||
|
- name: Publish to Github Nuget
|
||||||
|
run: nuget push .\output\*.nupkg -Source github
|
||||||
247
.github/workflows/essentials-3-dev-build.yml
vendored
247
.github/workflows/essentials-3-dev-build.yml
vendored
@@ -1,247 +0,0 @@
|
|||||||
name: Essentials v3 Development Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- feature-3.0.0/*
|
|
||||||
- hotfix-3.0.0/*
|
|
||||||
- release-3.0.0/*
|
|
||||||
- development-3.0.0
|
|
||||||
|
|
||||||
env:
|
|
||||||
SOLUTION_PATH: .
|
|
||||||
SOLUTION_FILE: PepperDash.Essentials
|
|
||||||
VERSION: 0.0.0-buildtype-buildnumber
|
|
||||||
BUILD_TYPE: Debug
|
|
||||||
RELEASE_BRANCH: main
|
|
||||||
jobs:
|
|
||||||
Build_Project_4-Series:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
# Detect environment (Act vs GitHub)
|
|
||||||
- name: Detect environment
|
|
||||||
id: detect_env
|
|
||||||
run: |
|
|
||||||
if [ -n "$ACT" ]; then
|
|
||||||
echo "is_local=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "is_local=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Install prerequisites
|
|
||||||
run: |
|
|
||||||
if [ "${{ steps.detect_env.outputs.is_local }}" == "true" ]; then
|
|
||||||
# For Act - no sudo needed
|
|
||||||
apt-get update
|
|
||||||
apt-get install -y curl wget libicu-dev git unzip
|
|
||||||
else
|
|
||||||
# For GitHub runners - sudo required
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y curl wget libicu-dev git unzip
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Set Version Number
|
|
||||||
id: setVersion
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
latestVersion="3.0.0"
|
|
||||||
newVersion=$latestVersion
|
|
||||||
phase=""
|
|
||||||
newVersionString=""
|
|
||||||
|
|
||||||
if [[ $GITHUB_REF =~ ^refs/pull/.* ]]; then
|
|
||||||
phase="beta"
|
|
||||||
newVersionString="${newVersion}-${phase}-${GITHUB_RUN_NUMBER}"
|
|
||||||
elif [[ $GITHUB_REF =~ ^refs/heads/hotfix-3.0.0/.* ]]; then
|
|
||||||
phase="hotfix"
|
|
||||||
newVersionString="${newVersion}-${phase}-${GITHUB_RUN_NUMBER}"
|
|
||||||
elif [[ $GITHUB_REF =~ ^refs/heads/feature-3.0.0/.* ]]; then
|
|
||||||
phase="alpha"
|
|
||||||
newVersionString="${newVersion}-${phase}-${GITHUB_RUN_NUMBER}"
|
|
||||||
elif [[ $GITHUB_REF == "refs/heads/development-3.0.0" ]]; then
|
|
||||||
phase="beta"
|
|
||||||
newVersionString="${newVersion}-${phase}-${GITHUB_RUN_NUMBER}"
|
|
||||||
elif [[ $GITHUB_REF =~ ^refs/heads/release-3.0.0/.* ]]; then
|
|
||||||
version=$(echo $GITHUB_REF | awk -F '/' '{print $NF}' | sed 's/v//')
|
|
||||||
phase="rc"
|
|
||||||
newVersionString="${version}-${phase}-${GITHUB_RUN_NUMBER}"
|
|
||||||
else
|
|
||||||
# For local builds or unrecognized branches
|
|
||||||
newVersionString="${newVersion}-local"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "version=$newVersionString" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
# Create Build Properties file
|
|
||||||
- name: Create Build Properties
|
|
||||||
run: |
|
|
||||||
cat > Directory.Build.props << EOF
|
|
||||||
<Project>
|
|
||||||
<PropertyGroup>
|
|
||||||
<Version>${{ steps.setVersion.outputs.version }}</Version>
|
|
||||||
<AssemblyVersion>${{ steps.setVersion.outputs.version }}</AssemblyVersion>
|
|
||||||
<FileVersion>${{ steps.setVersion.outputs.version }}</FileVersion>
|
|
||||||
<InformationalVersion>${{ steps.setVersion.outputs.version }}</InformationalVersion>
|
|
||||||
<PackageVersion>${{ steps.setVersion.outputs.version }}</PackageVersion>
|
|
||||||
<NuGetVersion>${{ steps.setVersion.outputs.version }}</NuGetVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
EOF
|
|
||||||
|
|
||||||
- name: Setup .NET
|
|
||||||
uses: actions/setup-dotnet@v3
|
|
||||||
with:
|
|
||||||
dotnet-version: '8.0.x'
|
|
||||||
|
|
||||||
- name: Restore NuGet Packages
|
|
||||||
run: dotnet restore ${SOLUTION_FILE}.sln
|
|
||||||
|
|
||||||
- name: Build Solution
|
|
||||||
run: dotnet build ${SOLUTION_FILE}.sln --configuration ${BUILD_TYPE} --no-restore
|
|
||||||
|
|
||||||
# Copy the CPZ file to the output directory with version in the filename
|
|
||||||
- name: Copy and Rename CPZ Files
|
|
||||||
run: |
|
|
||||||
mkdir -p ./output/cpz
|
|
||||||
|
|
||||||
# Find the main CPZ file in the build output
|
|
||||||
if [ -f "./src/PepperDash.Essentials/bin/${BUILD_TYPE}/net8/PepperDashEssentials.cpz" ]; then
|
|
||||||
cp "./src/PepperDash.Essentials/bin/${BUILD_TYPE}/net8/PepperDashEssentials.cpz" "./output/cpz/PepperDashEssentials.${{ steps.setVersion.outputs.version }}.cpz"
|
|
||||||
echo "Main CPZ file copied and renamed successfully."
|
|
||||||
else
|
|
||||||
echo "Warning: Main CPZ file not found at expected location."
|
|
||||||
find ./src -name "*.cpz" | xargs -I {} cp {} ./output/cpz/
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Pack Solution
|
|
||||||
run: dotnet pack ${SOLUTION_FILE}.sln --configuration ${BUILD_TYPE} --output ./output/nuget --no-build
|
|
||||||
|
|
||||||
# List build artifacts (runs in both environments)
|
|
||||||
- name: List Build Artifacts
|
|
||||||
run: |
|
|
||||||
echo "=== Build Artifacts ==="
|
|
||||||
echo "NuGet Packages:"
|
|
||||||
find ./output/nuget -type f | sort
|
|
||||||
echo ""
|
|
||||||
echo "CPZ/CPLZ Files:"
|
|
||||||
find ./output -name "*.cpz" -o -name "*.cplz" | sort
|
|
||||||
echo "======================="
|
|
||||||
|
|
||||||
# Enhanced package inspection for local runs
|
|
||||||
- name: Inspect NuGet Packages
|
|
||||||
if: steps.detect_env.outputs.is_local == 'true'
|
|
||||||
run: |
|
|
||||||
echo "=== NuGet Package Details ==="
|
|
||||||
for pkg in $(find ./output/nuget -name "*.nupkg"); do
|
|
||||||
echo "Package: $(basename "$pkg")"
|
|
||||||
echo "Size: $(du -h "$pkg" | cut -f1)"
|
|
||||||
|
|
||||||
# Extract and show package contents
|
|
||||||
echo "Contents:"
|
|
||||||
unzip -l "$pkg" | tail -n +4 | head -n -2
|
|
||||||
echo "--------------------------"
|
|
||||||
|
|
||||||
# Try to extract and show the nuspec file (contains metadata)
|
|
||||||
echo "Metadata:"
|
|
||||||
unzip -p "$pkg" "*.nuspec" 2>/dev/null | grep -E "(<id>|<version>|<description>|<authors>|<dependencies>)" || echo "Metadata extraction failed"
|
|
||||||
echo "--------------------------"
|
|
||||||
done
|
|
||||||
echo "==========================="
|
|
||||||
|
|
||||||
# Tag creation - GitHub version
|
|
||||||
- name: Create tag for non-rc builds (GitHub)
|
|
||||||
if: ${{ !contains(steps.setVersion.outputs.version, 'rc') && steps.detect_env.outputs.is_local == 'false' }}
|
|
||||||
run: |
|
|
||||||
git config --global user.name "GitHub Actions"
|
|
||||||
git config --global user.email "actions@github.com"
|
|
||||||
git tag ${{ steps.setVersion.outputs.version }}
|
|
||||||
git push --tags origin
|
|
||||||
|
|
||||||
# Tag creation - Act mock version
|
|
||||||
- name: Create tag for non-rc builds (Act Mock)
|
|
||||||
if: ${{ !contains(steps.setVersion.outputs.version, 'rc') && steps.detect_env.outputs.is_local == 'true' }}
|
|
||||||
run: |
|
|
||||||
echo "Would create git tag: ${{ steps.setVersion.outputs.version }}"
|
|
||||||
echo "Would push tag to: origin"
|
|
||||||
|
|
||||||
# Release creation - GitHub version
|
|
||||||
- name: Create Release (GitHub)
|
|
||||||
if: steps.detect_env.outputs.is_local == 'false'
|
|
||||||
id: create_release
|
|
||||||
uses: ncipollo/release-action@v1
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
artifacts: 'output/cpz/*,output/**/*.cplz'
|
|
||||||
generateReleaseNotes: true
|
|
||||||
prerelease: ${{contains('debug', env.BUILD_TYPE)}}
|
|
||||||
tag: ${{ steps.setVersion.outputs.version }}
|
|
||||||
|
|
||||||
# Release creation - Act mock version with enhanced output
|
|
||||||
- name: Create Release (Act Mock)
|
|
||||||
if: steps.detect_env.outputs.is_local == 'true'
|
|
||||||
run: |
|
|
||||||
echo "=== Mock Release Creation ==="
|
|
||||||
echo "Would create release with:"
|
|
||||||
echo "- Tag: ${{ steps.setVersion.outputs.version }}"
|
|
||||||
echo "- Prerelease: ${{contains('debug', env.BUILD_TYPE)}}"
|
|
||||||
echo "- Artifacts matching pattern: output/cpz/*,output/**/*.cplz"
|
|
||||||
echo ""
|
|
||||||
echo "Matching artifacts:"
|
|
||||||
find ./output/cpz -type f
|
|
||||||
find ./output -name "*.cplz"
|
|
||||||
|
|
||||||
# Detailed info about release artifacts
|
|
||||||
echo ""
|
|
||||||
echo "Artifact Details:"
|
|
||||||
for artifact in $(find ./output/cpz -type f; find ./output -name "*.cplz"); do
|
|
||||||
echo "File: $(basename "$artifact")"
|
|
||||||
echo "Size: $(du -h "$artifact" | cut -f1)"
|
|
||||||
echo "Created: $(stat -c %y "$artifact")"
|
|
||||||
echo "MD5: $(md5sum "$artifact" | cut -d' ' -f1)"
|
|
||||||
echo "--------------------------"
|
|
||||||
done
|
|
||||||
echo "============================"
|
|
||||||
|
|
||||||
# NuGet setup - GitHub version
|
|
||||||
- name: Setup NuGet (GitHub)
|
|
||||||
if: steps.detect_env.outputs.is_local == 'false'
|
|
||||||
run: |
|
|
||||||
dotnet nuget add source https://nuget.pkg.github.com/pepperdash/index.json -n github -u pepperdash -p ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text
|
|
||||||
|
|
||||||
# NuGet setup - Act mock version
|
|
||||||
- name: Setup NuGet (Act Mock)
|
|
||||||
if: steps.detect_env.outputs.is_local == 'true'
|
|
||||||
run: |
|
|
||||||
echo "=== Mock NuGet Setup ==="
|
|
||||||
echo "Would add GitHub NuGet source: https://nuget.pkg.github.com/pepperdash/index.json"
|
|
||||||
echo "======================="
|
|
||||||
|
|
||||||
# Publish to NuGet - GitHub version
|
|
||||||
- name: Publish to Nuget (GitHub)
|
|
||||||
if: steps.detect_env.outputs.is_local == 'false'
|
|
||||||
run: dotnet nuget push ./output/nuget/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }}
|
|
||||||
|
|
||||||
# Publish to NuGet - Act mock version
|
|
||||||
- name: Publish to Nuget (Act Mock)
|
|
||||||
if: steps.detect_env.outputs.is_local == 'true'
|
|
||||||
run: |
|
|
||||||
echo "=== Mock Publish to NuGet ==="
|
|
||||||
echo "Would publish the following packages to https://api.nuget.org/v3/index.json:"
|
|
||||||
find ./output/nuget -name "*.nupkg" | sort
|
|
||||||
echo "============================="
|
|
||||||
|
|
||||||
# Publish to GitHub NuGet - GitHub version
|
|
||||||
- name: Publish to Github Nuget (GitHub)
|
|
||||||
if: steps.detect_env.outputs.is_local == 'false'
|
|
||||||
run: dotnet nuget push ./output/nuget/*.nupkg --source github --api-key ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
# Publish to GitHub NuGet - Act mock version
|
|
||||||
- name: Publish to Github Nuget (Act Mock)
|
|
||||||
if: steps.detect_env.outputs.is_local == 'true'
|
|
||||||
run: |
|
|
||||||
echo "=== Mock Publish to GitHub NuGet ==="
|
|
||||||
echo "Would publish the following packages to the GitHub NuGet registry:"
|
|
||||||
find ./output/nuget -name "*.nupkg" | sort
|
|
||||||
echo "=================================="
|
|
||||||
57
.github/workflows/main.yml
vendored
Normal file
57
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
name: main Build using Docker
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
branches:
|
||||||
|
- main-2.0.0
|
||||||
|
env:
|
||||||
|
# solution path doesn't need slashes unless there it is multiple folders deep
|
||||||
|
# solution name does not include extension. .sln is assumed
|
||||||
|
SOLUTION_PATH: PepperDashEssentials
|
||||||
|
SOLUTION_FILE: PepperDashEssentials
|
||||||
|
# Do not edit this, we're just creating it here
|
||||||
|
VERSION: 0.0.0-buildtype-buildnumber
|
||||||
|
# Defaults to debug for build type
|
||||||
|
BUILD_TYPE: Release
|
||||||
|
# Defaults to main 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@v3
|
||||||
|
# Generate the appropriate version number
|
||||||
|
- name: Set Version Number
|
||||||
|
shell: powershell
|
||||||
|
id: setVersion
|
||||||
|
env:
|
||||||
|
TAG_NAME: ${{ github.event.release.tag_name }}
|
||||||
|
run: echo "VERSION=$($Env:TAG_NAME)" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
|
||||||
|
- name: Setup MS Build
|
||||||
|
uses: microsoft/setup-msbuild@v1.1
|
||||||
|
- name: restore Nuget Packages
|
||||||
|
run: nuget restore .\$($Env:SOLUTION_FILE).sln
|
||||||
|
- name: Build Solution
|
||||||
|
run: msbuild .\$($Env:SOLUTION_FILE).sln /p:Platform="Any CPU" /p:Configuration="Debug" /p:Version="${{ steps.setVersion.outputs.version }}" -m
|
||||||
|
- name: Pack Solution
|
||||||
|
run: dotnet pack .\$($Env:SOLUTION_FILE).sln --configuration $env:BUILD_TYPE --output ./output /p:Version="${{ steps.setVersion.outputs.version }}"
|
||||||
|
- name: Upload Release
|
||||||
|
id: create_release
|
||||||
|
uses: ncipollo/release-action@v1
|
||||||
|
with:
|
||||||
|
updateRelease: true
|
||||||
|
artifacts: 'output\**\*.*(cpz|cplz)'
|
||||||
|
tag: ${{ steps.setVersion.outputs.version }}
|
||||||
|
- name: Setup Nuget
|
||||||
|
run: |
|
||||||
|
nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username pepperdash -password ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
nuget setApiKey ${{ secrets.GITHUB_TOKEN }} -Source github
|
||||||
|
nuget setApiKey ${{ secrets.NUGET_API_KEY }} -Source https://api.nuget.org/v3/index.json
|
||||||
|
- name: Publish to Nuget
|
||||||
|
run: nuget push .\output\*.nupkg -Source https://api.nuget.org/v3/index.json
|
||||||
|
- name: Publish to Github Nuget
|
||||||
|
run: nuget push .\output\*.nupkg -Source github
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
Provided under MIT license
|
Provided under MIT license
|
||||||
|
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
PepperDash Essentials is an open source Crestron framework that can be configured as a standalone program capable of running a wide variety of system designs and can also be utilized as a plug-in architecture to augment other Simpl# Pro and Simpl Windows programs.
|
PepperDash Essentials is an open source Crestron framework that can be configured as a standalone program capable of running a wide variety of system designs and can also be utilized as a plug-in architecture to augment other Simpl# Pro and Simpl Windows programs.
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"runtimeOptions": {
|
|
||||||
"configProperties": {
|
|
||||||
"System.Globalization.Invariant": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,19 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="$(PackageOutputPath)\$(AssemblyName)\*.cpz" Condition="$(ProjectType) == 'Program'">
|
<!-- Include CPZ files from multiple possible locations -->
|
||||||
|
<None Include="$(TargetDir)*.cpz" Condition="$(ProjectType) == 'Program'">
|
||||||
|
<Pack>true</Pack>
|
||||||
|
<PackagePath>build;</PackagePath>
|
||||||
|
</None>
|
||||||
|
<None Include="$(OutputPath)*.cpz" Condition="$(ProjectType) == 'Program'">
|
||||||
|
<Pack>true</Pack>
|
||||||
|
<PackagePath>build;</PackagePath>
|
||||||
|
</None>
|
||||||
|
<None Include="$(MSBuildProjectDirectory)\bin\$(Configuration)\**\*.cpz" Condition="$(ProjectType) == 'Program'">
|
||||||
|
<Pack>true</Pack>
|
||||||
|
<PackagePath>build;</PackagePath>
|
||||||
|
</None>
|
||||||
|
<None Include="$(PackageOutputPath)\build\*.cpz" Condition="$(ProjectType) == 'Program'">
|
||||||
<Pack>true</Pack>
|
<Pack>true</Pack>
|
||||||
<PackagePath>build;</PackagePath>
|
<PackagePath>build;</PackagePath>
|
||||||
</None>
|
</None>
|
||||||
@@ -10,17 +23,94 @@
|
|||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Target Name="Create CPLZ" AfterTargets="Build; AfterRebuild" Condition="$(ProjectType) == 'ProgramLibrary' And $(TargetDir) != ''">
|
<Target Name="Create CPLZ" AfterTargets="Build; AfterRebuild" Condition="$(ProjectType) == 'ProgramLibrary' And $(TargetDir) != ''">
|
||||||
<Message Text="Creating CPLZ $(TargetDir)"></Message>
|
<Message Text="Creating CPLZ $(TargetDir)" Importance="high" />
|
||||||
|
<Message Text="PackageOutputPath: $(PackageOutputPath)" Importance="high" />
|
||||||
|
<Message Text="AssemblyName: $(AssemblyName)" Importance="high" />
|
||||||
|
<Message Text="TargetName: $(TargetName)" Importance="high" />
|
||||||
|
<Message Text="Version: $(Version)" Importance="high" />
|
||||||
|
<Message Text="TargetFramework: $(TargetFramework)" Importance="high" />
|
||||||
<MakeDir Directories="$(PackageOutputPath)" Condition="!Exists($(PackageOutputPath))" />
|
<MakeDir Directories="$(PackageOutputPath)" Condition="!Exists($(PackageOutputPath))" />
|
||||||
<MakeDir Directories="$(PackageOutputPath)\$(AssemblyName)" Condition="!Exists('$(PackageOutputPath)\$(AssemblyName)')" />
|
<MakeDir Directories="$(PackageOutputPath)\$(AssemblyName)" Condition="!Exists('$(PackageOutputPath)\$(AssemblyName)')" />
|
||||||
<ZipDirectory SourceDirectory="$(TargetDir)" DestinationFile="$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cplz" Overwrite="true"/>
|
<ZipDirectory SourceDirectory="$(TargetDir)" DestinationFile="$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cplz" Overwrite="true"/>
|
||||||
</Target>
|
</Target>
|
||||||
<Target Name="Copy CPZ NET6" AfterTargets="SimplSharpPostProcess" Condition="$(ProjectType) == 'Program' And ( ('$(TargetFramework)' == 'net6.0') Or ('$(TargetFramework)' == 'net8.0') )">
|
<Target Name="Debug Variables" BeforeTargets="Build">
|
||||||
<Message Text="Copying CPZ"></Message>
|
<Message Text="================ Debug Variables ================" Importance="high" />
|
||||||
<Move SourceFiles="$(TargetDir)$(TargetName).cpz" DestinationFiles="$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cpz" />
|
<Message Text="ProjectType: '$(ProjectType)'" Importance="high" />
|
||||||
|
<Message Text="TargetFramework: '$(TargetFramework)'" Importance="high" />
|
||||||
|
<Message Text="TargetDir: '$(TargetDir)'" Importance="high" />
|
||||||
|
<Message Text="===============================================" Importance="high" />
|
||||||
</Target>
|
</Target>
|
||||||
<Target Name="Copy CPZ NET47" AfterTargets="SimplSharpPostProcess47" Condition="($(ProjectType) == 'Program' And ( '$(TargetFramework)' != 'net6.0' ) And ( '$(TargetFramework)' != 'net8.0' ))">
|
<Target Name="Copy CPZ NET472"
|
||||||
<Message Text="Copying CPZ"></Message>
|
AfterTargets="Build"
|
||||||
<Move SourceFiles="$(TargetDir)$(TargetName).cpz" DestinationFiles="$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cpz" />
|
DependsOnTargets="BuildDependencies"
|
||||||
|
Condition="'$(ProjectType)' == 'Program' And '$(TargetFramework)' == 'net472'">
|
||||||
|
<Message Text="========================================" Importance="high" />
|
||||||
|
<Message Text="Starting CPZ Build Process for NET472" Importance="high" />
|
||||||
|
<Message Text="ProjectType: '$(ProjectType)'" Importance="high" />
|
||||||
|
<Message Text="TargetFramework: '$(TargetFramework)'" Importance="high" />
|
||||||
|
<Message Text="========================================" Importance="high" />
|
||||||
|
|
||||||
|
<!-- Create output directory -->
|
||||||
|
<MakeDir Directories="$(PackageOutputPath)\$(AssemblyName)"
|
||||||
|
Condition="!Exists('$(PackageOutputPath)\$(AssemblyName)')" />
|
||||||
|
|
||||||
|
<!-- Copy the CPZ file -->
|
||||||
|
<Copy SourceFiles="$(TargetDir)$(TargetName).cpz"
|
||||||
|
DestinationFiles="$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cpz"
|
||||||
|
Condition="Exists('$(TargetDir)$(TargetName).cpz')" />
|
||||||
|
|
||||||
|
<Message Text="CPZ Build completed for NET472"
|
||||||
|
Condition="Exists('$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cpz')"
|
||||||
|
Importance="high" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="Copy CPZ NET6"
|
||||||
|
AfterTargets="Build"
|
||||||
|
DependsOnTargets="BuildDependencies"
|
||||||
|
Condition="'$(ProjectType)' == 'Program' And ('$(TargetFramework)' == 'net6.0' Or '$(TargetFramework)' == 'net8.0')">
|
||||||
|
<Message Text="========================================" Importance="high" />
|
||||||
|
<Message Text="Starting CPZ Build Process" Importance="high" />
|
||||||
|
<Message Text="ProjectType: '$(ProjectType)'" Importance="high" />
|
||||||
|
<Message Text="TargetFramework: '$(TargetFramework)'" Importance="high" />
|
||||||
|
<Message Text="MSBuildProjectDirectory: '$(MSBuildProjectDirectory)'" Importance="high" />
|
||||||
|
<Message Text="PATH: '$(PATH)'" Importance="high" />
|
||||||
|
<Message Text="========================================" Importance="high" />
|
||||||
|
|
||||||
|
<!-- Check for SimplSharp compiler -->
|
||||||
|
<PropertyGroup>
|
||||||
|
<SimplSharpCompilerPath>$(HOME)/.crestron/SimplSharpPro/SimplSharpCompiler</SimplSharpCompilerPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Warning Text="SimplSharpCompiler not found at: $(SimplSharpCompilerPath)"
|
||||||
|
Condition="!Exists('$(SimplSharpCompilerPath)')" />
|
||||||
|
|
||||||
|
<!-- Run the SimplSharp compiler to create CPZ -->
|
||||||
|
<Exec Command=""$(SimplSharpCompilerPath)" "$(MSBuildProjectDirectory)" "$(TargetDir)""
|
||||||
|
IgnoreExitCode="false"
|
||||||
|
WorkingDirectory="$(MSBuildProjectDirectory)"
|
||||||
|
ConsoleToMSBuild="true"
|
||||||
|
Condition="Exists('$(SimplSharpCompilerPath)')">
|
||||||
|
<Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" />
|
||||||
|
</Exec>
|
||||||
|
|
||||||
|
<Message Text="SimplSharp Output: $(OutputOfExec)" Importance="high" />
|
||||||
|
|
||||||
|
<!-- Create output directory -->
|
||||||
|
<MakeDir Directories="$(PackageOutputPath)\$(AssemblyName)"
|
||||||
|
Condition="!Exists('$(PackageOutputPath)\$(AssemblyName)')" />
|
||||||
|
|
||||||
|
<!-- Copy the CPZ file -->
|
||||||
|
<Copy SourceFiles="$(TargetDir)$(TargetName).cpz"
|
||||||
|
DestinationFiles="$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cpz"
|
||||||
|
Condition="Exists('$(TargetDir)$(TargetName).cpz')" />
|
||||||
|
|
||||||
|
<Message Text="CPZ Build completed"
|
||||||
|
Condition="Exists('$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cpz')"
|
||||||
|
Importance="high" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="BuildDependencies">
|
||||||
|
<MSBuild Projects="@(ProjectReference)"
|
||||||
|
Targets="Build"
|
||||||
|
BuildInParallel="true" />
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@@ -33,8 +35,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
public static eCrestronSeries ProcessorSeries { get { return CrestronEnvironment.ProgramCompatibility; } }
|
public static eCrestronSeries ProcessorSeries { get { return CrestronEnvironment.ProgramCompatibility; } }
|
||||||
|
|
||||||
// TODO: consider making this configurable later
|
// TODO: consider making this configurable later
|
||||||
public static IFormatProvider Culture = CultureInfo.InvariantCulture;
|
public static IFormatProvider Culture = CultureInfo.CreateSpecificCulture("en-US");
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True when the processor type is a DMPS variant
|
/// True when the processor type is a DMPS variant
|
||||||
@@ -278,18 +279,6 @@ namespace PepperDash.Essentials.Core
|
|||||||
CrestronConsole.PrintLine("Error starting CrestronDataStoreStatic: {0}", err);
|
CrestronConsole.PrintLine("Error starting CrestronDataStoreStatic: {0}", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture("en");
|
|
||||||
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CreateSpecificCulture("en");
|
|
||||||
}
|
|
||||||
catch (CultureNotFoundException)
|
|
||||||
{
|
|
||||||
// If specific culture fails, fall back to invariant
|
|
||||||
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
|
|
||||||
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
|
using Crestron.SimplSharp.Reflection;
|
||||||
using Crestron.SimplSharp.Scheduler;
|
using Crestron.SimplSharp.Scheduler;
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<Configurations>Debug;Release;Debug 4.7.2</Configurations>
|
<Configurations>Debug;Release;Debug 4.7.2</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8</TargetFramework>
|
<TargetFrameworks>net472;net6</TargetFrameworks>
|
||||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||||
<AssemblyName>PepperDash_Essentials_Core</AssemblyName>
|
<AssemblyName>PepperDash_Essentials_Core</AssemblyName>
|
||||||
@@ -25,8 +25,8 @@
|
|||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.21.90" />
|
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.20.66" />
|
||||||
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-462" />
|
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-451" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Crestron\CrestronGenericBaseDevice.cs.orig" />
|
<None Include="Crestron\CrestronGenericBaseDevice.cs.orig" />
|
||||||
|
|||||||
@@ -1,18 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.IO;
|
|
||||||
using System.Reflection.PortableExecutable;
|
|
||||||
using System.Reflection.Metadata;
|
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using CrestronIO = Crestron.SimplSharp.CrestronIO;
|
|
||||||
using SystemIO = System.IO;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials
|
namespace PepperDash.Essentials
|
||||||
{
|
{
|
||||||
@@ -31,11 +27,6 @@ namespace PepperDash.Essentials
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
static List<LoadedAssembly> LoadedPluginFolderAssemblies;
|
static List<LoadedAssembly> LoadedPluginFolderAssemblies;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// List of plugins that were found to be incompatible with .NET 8
|
|
||||||
/// </summary>
|
|
||||||
public static List<IncompatiblePlugin> IncompatiblePlugins { get; private set; }
|
|
||||||
|
|
||||||
public static LoadedAssembly EssentialsAssembly { get; private set; }
|
public static LoadedAssembly EssentialsAssembly { get; private set; }
|
||||||
|
|
||||||
public static LoadedAssembly PepperDashCoreAssembly { get; private set; }
|
public static LoadedAssembly PepperDashCoreAssembly { get; private set; }
|
||||||
@@ -55,28 +46,12 @@ namespace PepperDash.Essentials
|
|||||||
// The temp directory where .cplz archives will be unzipped to
|
// The temp directory where .cplz archives will be unzipped to
|
||||||
static string _tempDirectory => _pluginDirectory + Global.DirectorySeparator + "temp";
|
static string _tempDirectory => _pluginDirectory + Global.DirectorySeparator + "temp";
|
||||||
|
|
||||||
// Known incompatible types in .NET 8
|
|
||||||
private static readonly HashSet<string> KnownIncompatibleTypes = new HashSet<string>
|
|
||||||
{
|
|
||||||
"System.Net.ICertificatePolicy",
|
|
||||||
"System.Security.Cryptography.SHA1CryptoServiceProvider",
|
|
||||||
"System.Web.HttpUtility",
|
|
||||||
"System.Configuration.ConfigurationManager",
|
|
||||||
"System.Web.Services.Protocols.SoapHttpClientProtocol",
|
|
||||||
"System.Runtime.Remoting",
|
|
||||||
"System.EnterpriseServices",
|
|
||||||
"System.Runtime.Serialization.Formatters.Binary.BinaryFormatter",
|
|
||||||
"System.Security.SecurityManager",
|
|
||||||
"System.Security.Permissions.FileIOPermission",
|
|
||||||
"System.AppDomain.CreateDomain"
|
|
||||||
};
|
|
||||||
|
|
||||||
static PluginLoader()
|
static PluginLoader()
|
||||||
{
|
{
|
||||||
LoadedAssemblies = new List<LoadedAssembly>();
|
LoadedAssemblies = new List<LoadedAssembly>();
|
||||||
LoadedPluginFolderAssemblies = new List<LoadedAssembly>();
|
LoadedPluginFolderAssemblies = new List<LoadedAssembly>();
|
||||||
EssentialsPluginAssemblies = new List<LoadedAssembly>();
|
EssentialsPluginAssemblies = new List<LoadedAssembly>();
|
||||||
IncompatiblePlugins = new List<IncompatiblePlugin>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -86,7 +61,7 @@ namespace PepperDash.Essentials
|
|||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "Getting Assemblies loaded with Essentials");
|
Debug.LogMessage(LogEventLevel.Verbose, "Getting Assemblies loaded with Essentials");
|
||||||
// Get the loaded assembly filenames
|
// Get the loaded assembly filenames
|
||||||
var appDi = new SystemIO.DirectoryInfo(Global.ApplicationDirectoryPathPrefix);
|
var appDi = new DirectoryInfo(Global.ApplicationDirectoryPathPrefix);
|
||||||
var assemblyFiles = appDi.GetFiles("*.dll");
|
var assemblyFiles = appDi.GetFiles("*.dll");
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "Found {0} Assemblies", assemblyFiles.Length);
|
Debug.LogMessage(LogEventLevel.Verbose, "Found {0} Assemblies", assemblyFiles.Length);
|
||||||
@@ -138,6 +113,7 @@ namespace PepperDash.Essentials
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void SetEssentialsAssembly(string name, Assembly assembly)
|
public static void SetEssentialsAssembly(string name, Assembly assembly)
|
||||||
{
|
{
|
||||||
var loadedAssembly = LoadedAssemblies.FirstOrDefault(la => la.Name.Equals(name));
|
var loadedAssembly = LoadedAssemblies.FirstOrDefault(la => la.Name.Equals(name));
|
||||||
@@ -148,109 +124,20 @@ namespace PepperDash.Essentials
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if a plugin is compatible with .NET 8 by examining its metadata
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="filePath">Path to the plugin assembly</param>
|
|
||||||
/// <returns>Tuple with compatibility result, reason if incompatible, and referenced assemblies</returns>
|
|
||||||
public static (bool IsCompatible, string Reason, List<string> References) IsPluginCompatibleWithNet8(string filePath)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
List<string> referencedAssemblies = new List<string>();
|
|
||||||
|
|
||||||
using (SystemIO.FileStream fs = new SystemIO.FileStream(filePath, SystemIO.FileMode.Open,
|
|
||||||
SystemIO.FileAccess.Read, SystemIO.FileShare.ReadWrite))
|
|
||||||
using (PEReader peReader = new PEReader(fs))
|
|
||||||
{
|
|
||||||
if (!peReader.HasMetadata)
|
|
||||||
return (false, "Not a valid .NET assembly", referencedAssemblies);
|
|
||||||
|
|
||||||
MetadataReader metadataReader = peReader.GetMetadataReader();
|
|
||||||
|
|
||||||
// Collect assembly references
|
|
||||||
foreach (var assemblyRefHandle in metadataReader.AssemblyReferences)
|
|
||||||
{
|
|
||||||
var assemblyRef = metadataReader.GetAssemblyReference(assemblyRefHandle);
|
|
||||||
string assemblyName = metadataReader.GetString(assemblyRef.Name);
|
|
||||||
referencedAssemblies.Add(assemblyName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for references to known incompatible types
|
|
||||||
foreach (var typeRefHandle in metadataReader.TypeReferences)
|
|
||||||
{
|
|
||||||
var typeRef = metadataReader.GetTypeReference(typeRefHandle);
|
|
||||||
string typeNamespace = metadataReader.GetString(typeRef.Namespace);
|
|
||||||
string typeName = metadataReader.GetString(typeRef.Name);
|
|
||||||
|
|
||||||
string fullTypeName = $"{typeNamespace}.{typeName}";
|
|
||||||
if (KnownIncompatibleTypes.Contains(fullTypeName))
|
|
||||||
{
|
|
||||||
return (false, $"Uses incompatible type: {fullTypeName}", referencedAssemblies);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for explicit .NET 8 compatibility attribute
|
|
||||||
bool hasNet8Attribute = false;
|
|
||||||
foreach (var customAttributeHandle in metadataReader.GetAssemblyDefinition().GetCustomAttributes())
|
|
||||||
{
|
|
||||||
var customAttribute = metadataReader.GetCustomAttribute(customAttributeHandle);
|
|
||||||
var ctorHandle = customAttribute.Constructor;
|
|
||||||
|
|
||||||
if (ctorHandle.Kind == HandleKind.MemberReference)
|
|
||||||
{
|
|
||||||
var memberRef = metadataReader.GetMemberReference((MemberReferenceHandle)ctorHandle);
|
|
||||||
var typeRef = metadataReader.GetTypeReference((TypeReferenceHandle)memberRef.Parent);
|
|
||||||
|
|
||||||
string typeName = metadataReader.GetString(typeRef.Name);
|
|
||||||
if (typeName == "Net8CompatibleAttribute" || typeName == "TargetFrameworkAttribute")
|
|
||||||
{
|
|
||||||
hasNet8Attribute = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasNet8Attribute)
|
|
||||||
{
|
|
||||||
return (true, null, referencedAssemblies);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we can't determine incompatibility, assume it's compatible
|
|
||||||
return (true, null, referencedAssemblies);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return (false, $"Error analyzing assembly: {ex.Message}", new List<string>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads an assembly via Reflection and adds it to the list of loaded assemblies
|
/// Loads an assembly via Reflection and adds it to the list of loaded assemblies
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filePath">Path to the assembly file</param>
|
/// <param name="fileName"></param>
|
||||||
/// <param name="requestedBy">Name of the plugin requesting this assembly (null for direct loads)</param>
|
static LoadedAssembly LoadAssembly(string filePath)
|
||||||
static LoadedAssembly LoadAssembly(string filePath, string requestedBy = null)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Check .NET 8 compatibility before loading
|
//Debug.LogMessage(LogEventLevel.Verbose, "Attempting to load {0}", filePath);
|
||||||
var (isCompatible, reason, references) = IsPluginCompatibleWithNet8(filePath);
|
|
||||||
if (!isCompatible)
|
|
||||||
{
|
|
||||||
string fileName = CrestronIO.Path.GetFileName(filePath);
|
|
||||||
Debug.LogMessage(LogEventLevel.Warning, "Assembly '{0}' is not compatible with .NET 8: {1}", fileName, reason);
|
|
||||||
|
|
||||||
var incompatiblePlugin = new IncompatiblePlugin(fileName, reason, requestedBy);
|
|
||||||
IncompatiblePlugins.Add(incompatiblePlugin);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var assembly = Assembly.LoadFrom(filePath);
|
var assembly = Assembly.LoadFrom(filePath);
|
||||||
if (assembly != null)
|
if (assembly != null)
|
||||||
{
|
{
|
||||||
var assyVersion = GetAssemblyVersion(assembly);
|
var assyVersion = GetAssemblyVersion(assembly);
|
||||||
|
|
||||||
var loadedAssembly = new LoadedAssembly(assembly.GetName().Name, assyVersion, assembly);
|
var loadedAssembly = new LoadedAssembly(assembly.GetName().Name, assyVersion, assembly);
|
||||||
LoadedAssemblies.Add(loadedAssembly);
|
LoadedAssemblies.Add(loadedAssembly);
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Loaded assembly '{0}', version {1}", loadedAssembly.Name, loadedAssembly.Version);
|
Debug.LogMessage(LogEventLevel.Information, "Loaded assembly '{0}', version {1}", loadedAssembly.Name, loadedAssembly.Version);
|
||||||
@@ -260,47 +147,14 @@ namespace PepperDash.Essentials
|
|||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Unable to load assembly: '{0}'", filePath);
|
Debug.LogMessage(LogEventLevel.Information, "Unable to load assembly: '{0}'", filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
} catch(Exception ex)
|
||||||
catch(SystemIO.FileLoadException ex) when (ex.Message.Contains("Assembly with same name is already loaded"))
|
|
||||||
{
|
|
||||||
// Get the assembly name from the file path
|
|
||||||
string assemblyName = CrestronIO.Path.GetFileNameWithoutExtension(filePath);
|
|
||||||
|
|
||||||
// Try to find the already loaded assembly
|
|
||||||
var existingAssembly = AppDomain.CurrentDomain.GetAssemblies()
|
|
||||||
.FirstOrDefault(a => a.GetName().Name.Equals(assemblyName, StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
if (existingAssembly != null)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Assembly '{0}' is already loaded, using existing instance", assemblyName);
|
|
||||||
var assyVersion = GetAssemblyVersion(existingAssembly);
|
|
||||||
var loadedAssembly = new LoadedAssembly(existingAssembly.GetName().Name, assyVersion, existingAssembly);
|
|
||||||
LoadedAssemblies.Add(loadedAssembly);
|
|
||||||
return loadedAssembly;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Warning, "Assembly with same name already loaded but couldn't find it: {0}", filePath);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch(Exception ex)
|
|
||||||
{
|
|
||||||
string fileName = CrestronIO.Path.GetFileName(filePath);
|
|
||||||
|
|
||||||
// Check if this might be a .NET Framework compatibility issue
|
|
||||||
if (ex.Message.Contains("Could not load type") ||
|
|
||||||
ex.Message.Contains("Unable to load one or more of the requested types"))
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Error, "Error loading assembly {0}: Likely .NET 8 compatibility issue: {1}",
|
|
||||||
fileName, ex.Message);
|
|
||||||
IncompatiblePlugins.Add(new IncompatiblePlugin(fileName, ex.Message, requestedBy));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
Debug.LogMessage(ex, "Error loading assembly from {path}", null, filePath);
|
Debug.LogMessage(ex, "Error loading assembly from {path}", null, filePath);
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -362,25 +216,12 @@ namespace PepperDash.Essentials
|
|||||||
CrestronConsole.ConsoleCommandResponse("{0} Version: {1}" + CrestronEnvironment.NewLine, assembly.Name, assembly.Version);
|
CrestronConsole.ConsoleCommandResponse("{0} Version: {1}" + CrestronEnvironment.NewLine, assembly.Name, assembly.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IncompatiblePlugins.Count > 0)
|
//CrestronConsole.ConsoleCommandResponse("Loaded Assemblies:" + CrestronEnvironment.NewLine);
|
||||||
{
|
//foreach (var assembly in LoadedAssemblies)
|
||||||
CrestronConsole.ConsoleCommandResponse("Incompatible Plugins:" + CrestronEnvironment.NewLine);
|
//{
|
||||||
foreach (var plugin in IncompatiblePlugins)
|
// CrestronConsole.ConsoleCommandResponse("{0} Version: {1}" + CrestronEnvironment.NewLine, assembly.Name, assembly.Version);
|
||||||
{
|
//}
|
||||||
if (plugin.TriggeredBy != "Direct load")
|
|
||||||
{
|
|
||||||
CrestronConsole.ConsoleCommandResponse("{0}: {1} (Required by: {2})" + CrestronEnvironment.NewLine,
|
|
||||||
plugin.Name, plugin.Reason, plugin.TriggeredBy);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
CrestronConsole.ConsoleCommandResponse("{0}: {1}" + CrestronEnvironment.NewLine,
|
|
||||||
plugin.Name, plugin.Reason);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Moves any .dll assemblies not already loaded from the plugins folder to loadedPlugins folder
|
/// Moves any .dll assemblies not already loaded from the plugins folder to loadedPlugins folder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -388,14 +229,14 @@ namespace PepperDash.Essentials
|
|||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Looking for .dll assemblies from plugins folder...");
|
Debug.LogMessage(LogEventLevel.Information, "Looking for .dll assemblies from plugins folder...");
|
||||||
|
|
||||||
var pluginDi = new SystemIO.DirectoryInfo(_pluginDirectory);
|
var pluginDi = new DirectoryInfo(_pluginDirectory);
|
||||||
var pluginFiles = pluginDi.GetFiles("*.dll");
|
var pluginFiles = pluginDi.GetFiles("*.dll");
|
||||||
|
|
||||||
if (pluginFiles.Length > 0)
|
if (pluginFiles.Length > 0)
|
||||||
{
|
{
|
||||||
if (!SystemIO.Directory.Exists(_loadedPluginsDirectoryPath))
|
if (!Directory.Exists(_loadedPluginsDirectoryPath))
|
||||||
{
|
{
|
||||||
SystemIO.Directory.CreateDirectory(_loadedPluginsDirectoryPath);
|
Directory.CreateDirectory(_loadedPluginsDirectoryPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,14 +253,14 @@ namespace PepperDash.Essentials
|
|||||||
filePath = _loadedPluginsDirectoryPath + Global.DirectorySeparator + pluginFile.Name;
|
filePath = _loadedPluginsDirectoryPath + Global.DirectorySeparator + pluginFile.Name;
|
||||||
|
|
||||||
// Check if there is a previous file in the loadedPlugins directory and delete
|
// Check if there is a previous file in the loadedPlugins directory and delete
|
||||||
if (SystemIO.File.Exists(filePath))
|
if (File.Exists(filePath))
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Found existing file in loadedPlugins: {0} Deleting and moving new file to replace it", filePath);
|
Debug.LogMessage(LogEventLevel.Information, "Found existing file in loadedPlugins: {0} Deleting and moving new file to replace it", filePath);
|
||||||
SystemIO.File.Delete(filePath);
|
File.Delete(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the file
|
// Move the file
|
||||||
SystemIO.File.Move(pluginFile.FullName, filePath);
|
File.Move(pluginFile.FullName, filePath);
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "Moved {0} to {1}", pluginFile.FullName, filePath);
|
Debug.LogMessage(LogEventLevel.Verbose, "Moved {0} to {1}", pluginFile.FullName, filePath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -443,21 +284,21 @@ namespace PepperDash.Essentials
|
|||||||
static void UnzipAndMoveCplzArchives()
|
static void UnzipAndMoveCplzArchives()
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Looking for .cplz archives from plugins folder...");
|
Debug.LogMessage(LogEventLevel.Information, "Looking for .cplz archives from plugins folder...");
|
||||||
var di = new SystemIO.DirectoryInfo(_pluginDirectory);
|
var di = new DirectoryInfo(_pluginDirectory);
|
||||||
var zFiles = di.GetFiles("*.cplz");
|
var zFiles = di.GetFiles("*.cplz");
|
||||||
|
|
||||||
if (zFiles.Length > 0)
|
if (zFiles.Length > 0)
|
||||||
{
|
{
|
||||||
if (!SystemIO.Directory.Exists(_loadedPluginsDirectoryPath))
|
if (!Directory.Exists(_loadedPluginsDirectoryPath))
|
||||||
{
|
{
|
||||||
SystemIO.Directory.CreateDirectory(_loadedPluginsDirectoryPath);
|
Directory.CreateDirectory(_loadedPluginsDirectoryPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var zfi in zFiles)
|
foreach (var zfi in zFiles)
|
||||||
{
|
{
|
||||||
SystemIO.Directory.CreateDirectory(_tempDirectory);
|
Directory.CreateDirectory(_tempDirectory);
|
||||||
var tempDi = new SystemIO.DirectoryInfo(_tempDirectory);
|
var tempDi = new DirectoryInfo(_tempDirectory);
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Found cplz: {0}. Unzipping into temp plugins directory", zfi.Name);
|
Debug.LogMessage(LogEventLevel.Information, "Found cplz: {0}. Unzipping into temp plugins directory", zfi.Name);
|
||||||
var result = CrestronZIP.Unzip(zfi.FullName, tempDi.FullName);
|
var result = CrestronZIP.Unzip(zfi.FullName, tempDi.FullName);
|
||||||
@@ -475,14 +316,14 @@ namespace PepperDash.Essentials
|
|||||||
filePath = _loadedPluginsDirectoryPath + Global.DirectorySeparator + tempFile.Name;
|
filePath = _loadedPluginsDirectoryPath + Global.DirectorySeparator + tempFile.Name;
|
||||||
|
|
||||||
// Check if there is a previous file in the loadedPlugins directory and delete
|
// Check if there is a previous file in the loadedPlugins directory and delete
|
||||||
if (SystemIO.File.Exists(filePath))
|
if (File.Exists(filePath))
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Found existing file in loadedPlugins: {0} Deleting and moving new file to replace it", filePath);
|
Debug.LogMessage(LogEventLevel.Information, "Found existing file in loadedPlugins: {0} Deleting and moving new file to replace it", filePath);
|
||||||
SystemIO.File.Delete(filePath);
|
File.Delete(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the file
|
// Move the file
|
||||||
SystemIO.File.Move(tempFile.FullName, filePath);
|
File.Move(tempFile.FullName, filePath);
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "Moved {0} to {1}", tempFile.FullName, filePath);
|
Debug.LogMessage(LogEventLevel.Verbose, "Moved {0} to {1}", tempFile.FullName, filePath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -498,7 +339,7 @@ namespace PepperDash.Essentials
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete the .cplz and the temp directory
|
// Delete the .cplz and the temp directory
|
||||||
SystemIO.Directory.Delete(_tempDirectory, true);
|
Directory.Delete(_tempDirectory, true);
|
||||||
zfi.Delete();
|
zfi.Delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,41 +352,17 @@ namespace PepperDash.Essentials
|
|||||||
static void LoadPluginAssemblies()
|
static void LoadPluginAssemblies()
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Loading assemblies from loadedPlugins folder...");
|
Debug.LogMessage(LogEventLevel.Information, "Loading assemblies from loadedPlugins folder...");
|
||||||
var pluginDi = new CrestronIO.DirectoryInfo(_loadedPluginsDirectoryPath);
|
var pluginDi = new DirectoryInfo(_loadedPluginsDirectoryPath);
|
||||||
var pluginFiles = pluginDi.GetFiles("*.dll");
|
var pluginFiles = pluginDi.GetFiles("*.dll");
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "Found {0} plugin assemblies to load", pluginFiles.Length);
|
Debug.LogMessage(LogEventLevel.Verbose, "Found {0} plugin assemblies to load", pluginFiles.Length);
|
||||||
|
|
||||||
// First, check compatibility of all assemblies before loading any
|
|
||||||
var assemblyCompatibility = new Dictionary<string, (bool IsCompatible, string Reason, List<string> References)>();
|
|
||||||
|
|
||||||
foreach (var pluginFile in pluginFiles)
|
foreach (var pluginFile in pluginFiles)
|
||||||
{
|
{
|
||||||
string fileName = pluginFile.Name;
|
var loadedAssembly = LoadAssembly(pluginFile.FullName);
|
||||||
assemblyCompatibility[fileName] = IsPluginCompatibleWithNet8(pluginFile.FullName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now load compatible assemblies and track incompatible ones
|
|
||||||
foreach (var pluginFile in pluginFiles)
|
|
||||||
{
|
|
||||||
string fileName = pluginFile.Name;
|
|
||||||
var (isCompatible, reason, references) = assemblyCompatibility[fileName];
|
|
||||||
|
|
||||||
if (!isCompatible)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Warning, "Assembly '{0}' is not compatible with .NET 8: {1}", fileName, reason);
|
|
||||||
IncompatiblePlugins.Add(new IncompatiblePlugin(fileName, reason, null));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to load the assembly
|
|
||||||
var loadedAssembly = LoadAssembly(pluginFile.FullName, null);
|
|
||||||
|
|
||||||
if (loadedAssembly != null)
|
|
||||||
{
|
|
||||||
LoadedPluginFolderAssemblies.Add(loadedAssembly);
|
LoadedPluginFolderAssemblies.Add(loadedAssembly);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "All Plugins Loaded.");
|
Debug.LogMessage(LogEventLevel.Information, "All Plugins Loaded.");
|
||||||
}
|
}
|
||||||
@@ -556,13 +373,8 @@ namespace PepperDash.Essentials
|
|||||||
static void LoadCustomPluginTypes()
|
static void LoadCustomPluginTypes()
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Loading Custom Plugin Types...");
|
Debug.LogMessage(LogEventLevel.Information, "Loading Custom Plugin Types...");
|
||||||
|
|
||||||
foreach (var loadedAssembly in LoadedPluginFolderAssemblies)
|
foreach (var loadedAssembly in LoadedPluginFolderAssemblies)
|
||||||
{
|
{
|
||||||
// Skip if assembly is null (can happen if we had loading issues)
|
|
||||||
if (loadedAssembly == null || loadedAssembly.Assembly == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// iteratate this assembly's classes, looking for "LoadPlugin()" methods
|
// iteratate this assembly's classes, looking for "LoadPlugin()" methods
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -573,49 +385,11 @@ namespace PepperDash.Essentials
|
|||||||
types = assy.GetTypes();
|
types = assy.GetTypes();
|
||||||
Debug.LogMessage(LogEventLevel.Debug, $"Got types for assembly {assy.GetName().Name}");
|
Debug.LogMessage(LogEventLevel.Debug, $"Got types for assembly {assy.GetName().Name}");
|
||||||
}
|
}
|
||||||
catch (ReflectionTypeLoadException e)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Error, "Unable to get types for assembly {0}: {1}",
|
|
||||||
loadedAssembly.Name, e.Message);
|
|
||||||
|
|
||||||
// Check if any of the loader exceptions are due to missing assemblies
|
|
||||||
foreach (var loaderEx in e.LoaderExceptions)
|
|
||||||
{
|
|
||||||
if (loaderEx is SystemIO.FileNotFoundException fileNotFoundEx)
|
|
||||||
{
|
|
||||||
string missingAssembly = fileNotFoundEx.FileName;
|
|
||||||
if (!string.IsNullOrEmpty(missingAssembly))
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Warning, "Assembly {0} requires missing dependency: {1}",
|
|
||||||
loadedAssembly.Name, missingAssembly);
|
|
||||||
|
|
||||||
// Add to incompatible plugins with dependency information
|
|
||||||
IncompatiblePlugins.Add(new IncompatiblePlugin(
|
|
||||||
CrestronIO.Path.GetFileName(missingAssembly),
|
|
||||||
$"Missing dependency required by {loadedAssembly.Name}",
|
|
||||||
loadedAssembly.Name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, e.StackTrace);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
catch (TypeLoadException e)
|
catch (TypeLoadException e)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Error, "Unable to get types for assembly {0}: {1}",
|
Debug.LogMessage(LogEventLevel.Error, "Unable to get types for assembly {0}: {1}",
|
||||||
loadedAssembly.Name, e.Message);
|
loadedAssembly.Name, e.Message);
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, e.StackTrace);
|
Debug.LogMessage(LogEventLevel.Verbose, e.StackTrace);
|
||||||
|
|
||||||
// Add to incompatible plugins if this is likely a .NET 8 compatibility issue
|
|
||||||
if (e.Message.Contains("Could not load type") ||
|
|
||||||
e.Message.Contains("Unable to load one or more of the requested types"))
|
|
||||||
{
|
|
||||||
IncompatiblePlugins.Add(new IncompatiblePlugin(loadedAssembly.Name,
|
|
||||||
$"Type loading error: {e.Message}",
|
|
||||||
null));
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,6 +414,7 @@ namespace PepperDash.Essentials
|
|||||||
loadedAssembly.Name, e.Message, type.Name);
|
loadedAssembly.Name, e.Message, type.Name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -647,59 +422,14 @@ namespace PepperDash.Essentials
|
|||||||
Debug.LogMessage(LogEventLevel.Information, "Error Loading assembly {0}: {1}",
|
Debug.LogMessage(LogEventLevel.Information, "Error Loading assembly {0}: {1}",
|
||||||
loadedAssembly.Name, e.Message);
|
loadedAssembly.Name, e.Message);
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "{0}", e.StackTrace);
|
Debug.LogMessage(LogEventLevel.Verbose, "{0}", e.StackTrace);
|
||||||
|
|
||||||
// Add to incompatible plugins if this is likely a .NET 8 compatibility issue
|
|
||||||
if (e.Message.Contains("Could not load type") ||
|
|
||||||
e.Message.Contains("Unable to load one or more of the requested types"))
|
|
||||||
{
|
|
||||||
IncompatiblePlugins.Add(new IncompatiblePlugin(loadedAssembly.Name,
|
|
||||||
$"Assembly loading error: {e.Message}",
|
|
||||||
null));
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update incompatible plugins with dependency information
|
|
||||||
var pluginDependencies = new Dictionary<string, List<string>>();
|
|
||||||
// Populate pluginDependencies with relevant data
|
|
||||||
// Example: pluginDependencies["PluginA"] = new List<string> { "Dependency1", "Dependency2" };
|
|
||||||
UpdateIncompatiblePluginDependencies(pluginDependencies);
|
|
||||||
|
|
||||||
// plugin dll will be loaded. Any classes in plugin should have a static constructor
|
// plugin dll will be loaded. Any classes in plugin should have a static constructor
|
||||||
// that registers that class with the Core.DeviceFactory
|
// that registers that class with the Core.DeviceFactory
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Done Loading Custom Plugin Types.");
|
Debug.LogMessage(LogEventLevel.Information, "Done Loading Custom Plugin Types.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Updates incompatible plugins with information about which plugins depend on them
|
|
||||||
/// </summary>
|
|
||||||
private static void UpdateIncompatiblePluginDependencies(Dictionary<string, List<string>> pluginDependencies)
|
|
||||||
{
|
|
||||||
// For each incompatible plugin
|
|
||||||
foreach (var incompatiblePlugin in IncompatiblePlugins)
|
|
||||||
{
|
|
||||||
// If it already has a requestedBy, skip it
|
|
||||||
if (incompatiblePlugin.TriggeredBy != "Direct load")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Find plugins that depend on this incompatible plugin
|
|
||||||
foreach (var plugin in pluginDependencies)
|
|
||||||
{
|
|
||||||
string pluginName = plugin.Key;
|
|
||||||
List<string> dependencies = plugin.Value;
|
|
||||||
|
|
||||||
// If this plugin depends on the incompatible plugin
|
|
||||||
if (dependencies.Contains(incompatiblePlugin.Name) ||
|
|
||||||
dependencies.Any(d => d.StartsWith(incompatiblePlugin.Name + ",")))
|
|
||||||
{
|
|
||||||
incompatiblePlugin.UpdateTriggeringPlugin(pluginName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads a
|
/// Loads a
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -776,6 +506,7 @@ namespace PepperDash.Essentials
|
|||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Loading legacy plugin: {0}", loadedAssembly.Name);
|
Debug.LogMessage(LogEventLevel.Information, "Loading legacy plugin: {0}", loadedAssembly.Name);
|
||||||
loadPlugin.Invoke(null, null);
|
loadPlugin.Invoke(null, null);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -785,7 +516,7 @@ namespace PepperDash.Essentials
|
|||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Attempting to Load Plugins from {_pluginDirectory}", _pluginDirectory);
|
Debug.LogMessage(LogEventLevel.Information, "Attempting to Load Plugins from {_pluginDirectory}", _pluginDirectory);
|
||||||
|
|
||||||
if (SystemIO.Directory.Exists(_pluginDirectory))
|
if (Directory.Exists(_pluginDirectory))
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Plugins directory found, checking for plugins");
|
Debug.LogMessage(LogEventLevel.Information, "Plugins directory found, checking for plugins");
|
||||||
|
|
||||||
@@ -795,7 +526,7 @@ namespace PepperDash.Essentials
|
|||||||
// Deal with any .cplz files
|
// Deal with any .cplz files
|
||||||
UnzipAndMoveCplzArchives();
|
UnzipAndMoveCplzArchives();
|
||||||
|
|
||||||
if (SystemIO.Directory.Exists(_loadedPluginsDirectoryPath))
|
if (Directory.Exists(_loadedPluginsDirectoryPath))
|
||||||
{
|
{
|
||||||
// Load the assemblies from the loadedPlugins folder into the AppDomain
|
// Load the assemblies from the loadedPlugins folder into the AppDomain
|
||||||
LoadPluginAssemblies();
|
LoadPluginAssemblies();
|
||||||
@@ -803,27 +534,9 @@ namespace PepperDash.Essentials
|
|||||||
// Load the types from any custom plugin assemblies
|
// Load the types from any custom plugin assemblies
|
||||||
LoadCustomPluginTypes();
|
LoadCustomPluginTypes();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Report on incompatible plugins
|
|
||||||
if (IncompatiblePlugins.Count > 0)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Warning, "Found {0} incompatible plugins:", IncompatiblePlugins.Count);
|
|
||||||
foreach (var plugin in IncompatiblePlugins)
|
|
||||||
{
|
|
||||||
if (plugin.TriggeredBy != "Direct load")
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Warning, " - {0}: {1} (Required by: {2})",
|
|
||||||
plugin.Name, plugin.Reason, plugin.TriggeredBy);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Warning, " - {0}: {1}",
|
|
||||||
plugin.Name, plugin.Reason);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -850,52 +563,4 @@ namespace PepperDash.Essentials
|
|||||||
Assembly = assembly;
|
Assembly = assembly;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a plugin that was found to be incompatible with .NET 8
|
|
||||||
/// </summary>
|
|
||||||
public class IncompatiblePlugin
|
|
||||||
{
|
|
||||||
[JsonProperty("name")]
|
|
||||||
public string Name { get; private set; }
|
|
||||||
|
|
||||||
[JsonProperty("reason")]
|
|
||||||
public string Reason { get; private set; }
|
|
||||||
|
|
||||||
[JsonProperty("triggeredBy")]
|
|
||||||
public string TriggeredBy { get; private set; }
|
|
||||||
|
|
||||||
public IncompatiblePlugin(string name, string reason, string triggeredBy = null)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
Reason = reason;
|
|
||||||
TriggeredBy = triggeredBy ?? "Direct load";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Updates the plugin that triggered this incompatibility
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="triggeringPlugin">Name of the plugin that requires this incompatible plugin</param>
|
|
||||||
public void UpdateTriggeringPlugin(string triggeringPlugin)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(triggeringPlugin))
|
|
||||||
{
|
|
||||||
TriggeredBy = triggeringPlugin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attribute to explicitly mark a plugin as .NET 8 compatible
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Assembly)]
|
|
||||||
public class Net8CompatibleAttribute : Attribute
|
|
||||||
{
|
|
||||||
public bool IsCompatible { get; }
|
|
||||||
|
|
||||||
public Net8CompatibleAttribute(bool isCompatible = true)
|
|
||||||
{
|
|
||||||
IsCompatible = isCompatible;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Net.WebSockets;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
public class SomeWebSocketClass
|
|
||||||
{
|
|
||||||
private ClientWebSocket _webSocket;
|
|
||||||
|
|
||||||
public SomeWebSocketClass()
|
|
||||||
{
|
|
||||||
_webSocket = new ClientWebSocket();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ConnectAsync(Uri uri)
|
|
||||||
{
|
|
||||||
await _webSocket.ConnectAsync(uri, CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SendAsync(string message)
|
|
||||||
{
|
|
||||||
var buffer = System.Text.Encoding.UTF8.GetBytes(message);
|
|
||||||
await _webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> ReceiveAsync()
|
|
||||||
{
|
|
||||||
var buffer = new byte[1024];
|
|
||||||
var result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
|
||||||
return System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task CloseAsync()
|
|
||||||
{
|
|
||||||
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,14 +10,11 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using PepperDash.Essentials.Core.Web.RequestHandlers;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core.Web.RequestHandlers
|
namespace PepperDash.Essentials.Core.Web.RequestHandlers
|
||||||
{
|
{
|
||||||
public class DebugSessionRequestHandler : WebApiBaseRequestHandler
|
public class DebugSessionRequestHandler : WebApiBaseRequestHandler
|
||||||
{
|
{
|
||||||
private readonly DebugWebsocketSink _sink = new DebugWebsocketSink();
|
|
||||||
|
|
||||||
public DebugSessionRequestHandler()
|
public DebugSessionRequestHandler()
|
||||||
: base(true)
|
: base(true)
|
||||||
{
|
{
|
||||||
@@ -46,21 +43,21 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers
|
|||||||
|
|
||||||
var port = 0;
|
var port = 0;
|
||||||
|
|
||||||
if (!_sink.IsRunning)
|
if (!Debug.WebsocketSink.IsRunning)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Starting WS Server");
|
Debug.LogMessage(LogEventLevel.Information, "Starting WS Server");
|
||||||
// Generate a random port within a specified range
|
// Generate a random port within a specified range
|
||||||
port = new Random().Next(65435, 65535);
|
port = new Random().Next(65435, 65535);
|
||||||
// Start the WS Server
|
// Start the WS Server
|
||||||
_sink.StartServerAndSetPort(port);
|
Debug.WebsocketSink.StartServerAndSetPort(port);
|
||||||
Debug.SetWebSocketMinimumDebugLevel(Serilog.Events.LogEventLevel.Verbose);
|
Debug.SetWebSocketMinimumDebugLevel(Serilog.Events.LogEventLevel.Verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = _sink.Url;
|
var url = Debug.WebsocketSink.Url;
|
||||||
|
|
||||||
object data = new
|
object data = new
|
||||||
{
|
{
|
||||||
url = _sink.Url
|
url = Debug.WebsocketSink.Url
|
||||||
};
|
};
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Debug Session URL: {0}", url);
|
Debug.LogMessage(LogEventLevel.Information, "Debug Session URL: {0}", url);
|
||||||
@@ -87,7 +84,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers
|
|||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
protected override void HandlePost(HttpCwsContext context)
|
protected override void HandlePost(HttpCwsContext context)
|
||||||
{
|
{
|
||||||
_sink.StopServer();
|
Debug.WebsocketSink.StopServer();
|
||||||
|
|
||||||
context.Response.StatusCode = 200;
|
context.Response.StatusCode = 200;
|
||||||
context.Response.StatusDescription = "OK";
|
context.Response.StatusDescription = "OK";
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core.Web.RequestHandlers
|
|
||||||
{
|
|
||||||
public class DebugWebsocketSink
|
|
||||||
{
|
|
||||||
private bool _isRunning;
|
|
||||||
private string _url;
|
|
||||||
|
|
||||||
public bool IsRunning => _isRunning;
|
|
||||||
public string Url => _url;
|
|
||||||
|
|
||||||
public void StartServerAndSetPort(int port)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_url = $"ws://localhost:{port}";
|
|
||||||
_isRunning = true;
|
|
||||||
// Implement actual server startup logic here
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_isRunning = false;
|
|
||||||
throw new Exception($"Failed to start debug websocket server: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void StopServer()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Implement actual server shutdown logic here
|
|
||||||
_isRunning = false;
|
|
||||||
_url = null;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"Failed to stop debug websocket server: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<Configurations>Debug;Release;Debug 4.7.2</Configurations>
|
<Configurations>Debug;Release;Debug 4.7.2</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8</TargetFramework>
|
<TargetFrameworks>net472;net6</TargetFrameworks>
|
||||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||||
<AssemblyName>Essentials Devices Common</AssemblyName>
|
<AssemblyName>Essentials Devices Common</AssemblyName>
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
<ProjectReference Include="..\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj" />
|
<ProjectReference Include="..\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.21.90" />
|
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.20.66" />
|
||||||
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-462" />
|
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-451" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Net.WebSockets;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
public class SomeOtherWebSocketClass
|
|
||||||
{
|
|
||||||
private ClientWebSocket _webSocket;
|
|
||||||
|
|
||||||
public SomeOtherWebSocketClass()
|
|
||||||
{
|
|
||||||
_webSocket = new ClientWebSocket();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ConnectAsync(Uri uri)
|
|
||||||
{
|
|
||||||
await _webSocket.ConnectAsync(uri, CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SendAsync(string message)
|
|
||||||
{
|
|
||||||
var buffer = System.Text.Encoding.UTF8.GetBytes(message);
|
|
||||||
await _webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> ReceiveAsync()
|
|
||||||
{
|
|
||||||
var buffer = new byte[1024];
|
|
||||||
var result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
|
||||||
return System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task CloseAsync()
|
|
||||||
{
|
|
||||||
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Crestron.SimplSharp.CrestronIO;
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
using System.Reflection;
|
using Crestron.SimplSharp.Reflection;
|
||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Crestron.SimplSharp;
|
|
||||||
|
using Crestron.SimplSharp;
|
||||||
using Crestron.SimplSharp.CrestronIO;
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Crestron.SimplSharpPro;
|
using Crestron.SimplSharpPro;
|
||||||
@@ -27,9 +28,7 @@ namespace PepperDash.Essentials
|
|||||||
|
|
||||||
public ControlSystem()
|
public ControlSystem()
|
||||||
: base()
|
: base()
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
Thread.MaxNumberOfUserThreads = 400;
|
Thread.MaxNumberOfUserThreads = 400;
|
||||||
Global.ControlSystem = this;
|
Global.ControlSystem = this;
|
||||||
DeviceManager.Initialize(this);
|
DeviceManager.Initialize(this);
|
||||||
@@ -97,9 +96,6 @@ namespace PepperDash.Essentials
|
|||||||
|
|
||||||
DeterminePlatform();
|
DeterminePlatform();
|
||||||
|
|
||||||
// Print .NET runtime version
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Running on .NET runtime version: {0}", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription);
|
|
||||||
|
|
||||||
if (Debug.DoNotLoadConfigOnNextBoot)
|
if (Debug.DoNotLoadConfigOnNextBoot)
|
||||||
{
|
{
|
||||||
CrestronConsole.AddNewConsoleCommand(s => CrestronInvoke.BeginInvoke((o) => GoWithLoad()), "go", "Loads configuration file",
|
CrestronConsole.AddNewConsoleCommand(s => CrestronInvoke.BeginInvoke((o) => GoWithLoad()), "go", "Loads configuration file",
|
||||||
@@ -148,7 +144,7 @@ namespace PepperDash.Essentials
|
|||||||
CrestronConsole.AddNewConsoleCommand(DeviceManager.GetRoutingPorts,
|
CrestronConsole.AddNewConsoleCommand(DeviceManager.GetRoutingPorts,
|
||||||
"getroutingports", "Reports all routing ports, if any. Requires a device key", ConsoleAccessLevelEnum.AccessOperator);
|
"getroutingports", "Reports all routing ports, if any. Requires a device key", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
|
|
||||||
//DeviceManager.AddDevice(new EssentialsWebApi("essentialsWebApi", "Essentials Web API"));
|
DeviceManager.AddDevice(new EssentialsWebApi("essentialsWebApi", "Essentials Web API"));
|
||||||
|
|
||||||
if (!Debug.DoNotLoadConfigOnNextBoot)
|
if (!Debug.DoNotLoadConfigOnNextBoot)
|
||||||
{
|
{
|
||||||
@@ -185,10 +181,24 @@ namespace PepperDash.Essentials
|
|||||||
|
|
||||||
if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server) // Handles 3-series running Windows CE OS
|
if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server) // Handles 3-series running Windows CE OS
|
||||||
{
|
{
|
||||||
string userFolder = "user";
|
string userFolder;
|
||||||
string nvramFolder = "nvram";
|
string nvramFolder;
|
||||||
|
bool is4series = false;
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Starting Essentials v{version:l} on {processorSeries:l} Appliance", Global.AssemblyVersion, "4-series");
|
if (eCrestronSeries.Series4 == (Global.ProcessorSeries & eCrestronSeries.Series4)) // Handle 4-series
|
||||||
|
{
|
||||||
|
is4series = true;
|
||||||
|
// Set path to user/
|
||||||
|
userFolder = "user";
|
||||||
|
nvramFolder = "nvram";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
userFolder = "User";
|
||||||
|
nvramFolder = "Nvram";
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.LogMessage(LogEventLevel.Information, "Starting Essentials v{version:l} on {processorSeries:l} Appliance", Global.AssemblyVersion, is4series ? "4-series" : "3-series");
|
||||||
//Debug.LogMessage(LogEventLevel.Information, "Starting Essentials v{0} on {1} Appliance", Global.AssemblyVersion, is4series ? "4-series" : "3-series");
|
//Debug.LogMessage(LogEventLevel.Information, "Starting Essentials v{0} on {1} Appliance", Global.AssemblyVersion, is4series ? "4-series" : "3-series");
|
||||||
|
|
||||||
// Check if User/ProgramX exists
|
// Check if User/ProgramX exists
|
||||||
@@ -350,7 +360,6 @@ namespace PepperDash.Essentials
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
||||||
void Load()
|
void Load()
|
||||||
{
|
{
|
||||||
LoadDevices();
|
LoadDevices();
|
||||||
@@ -471,16 +480,7 @@ namespace PepperDash.Essentials
|
|||||||
{
|
{
|
||||||
var room = Core.DeviceFactory.GetDevice(roomConfig);
|
var room = Core.DeviceFactory.GetDevice(roomConfig);
|
||||||
|
|
||||||
if(room == null)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "ERROR: Cannot load unknown room type '{roomType:l}', key '{roomKey:l}'.", roomConfig.Type, roomConfig.Key);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DeviceManager.AddDevice(room);
|
DeviceManager.AddDevice(room);
|
||||||
}
|
|
||||||
|
|
||||||
if (room is ICustomMobileControl)
|
if (room is ICustomMobileControl)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Net.WebSockets;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Fusion
|
|
||||||
{
|
|
||||||
public class EssentialsHuddleSpaceFusionSystemControllerBase
|
|
||||||
{
|
|
||||||
private ClientWebSocket _webSocket;
|
|
||||||
|
|
||||||
public EssentialsHuddleSpaceFusionSystemControllerBase()
|
|
||||||
{
|
|
||||||
_webSocket = new ClientWebSocket();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ConnectAsync(Uri uri)
|
|
||||||
{
|
|
||||||
await _webSocket.ConnectAsync(uri, CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SendAsync(string message)
|
|
||||||
{
|
|
||||||
var buffer = System.Text.Encoding.UTF8.GetBytes(message);
|
|
||||||
await _webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> ReceiveAsync()
|
|
||||||
{
|
|
||||||
var buffer = new byte[1024];
|
|
||||||
var result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
|
||||||
return System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task CloseAsync()
|
|
||||||
{
|
|
||||||
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,18 +6,15 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<RootNamespace>PepperDash.Essentials</RootNamespace>
|
<RootNamespace>PepperDash.Essentials</RootNamespace>
|
||||||
<AssemblyName>PepperDashEssentials</AssemblyName>
|
<AssemblyName>PepperDashEssentials</AssemblyName>
|
||||||
<TargetFramework>net8</TargetFramework>
|
<TargetFrameworks>net472</TargetFrameworks>
|
||||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||||
<OutputPath>$(ProjectDir)bin\$(Configuration)\</OutputPath>
|
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||||
<Title>PepperDash Essentials</Title>
|
<Title>PepperDash Essentials</Title>
|
||||||
<PackageId>PepperDashEssentials</PackageId>
|
<PackageId>PepperDashEssentials</PackageId>
|
||||||
<Version>2.0.0-local</Version>
|
<Version>2.0.0-local</Version>
|
||||||
<InformationalVersion>$(Version)</InformationalVersion>
|
<InformationalVersion>$(Version)</InformationalVersion>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
|
||||||
<ProjectType>Program</ProjectType>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -51,8 +48,8 @@
|
|||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Crestron.SimplSharp.SDK.Program" Version="2.21.90" />
|
<PackageReference Include="Crestron.SimplSharp.SDK.Program" Version="2.20.66" />
|
||||||
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-462" />
|
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-451" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj" />
|
<ProjectReference Include="..\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj" />
|
||||||
|
|||||||
Reference in New Issue
Block a user