diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..2a45fd9 Binary files /dev/null and b/.DS_Store differ diff --git a/._.DS_Store b/._.DS_Store new file mode 100644 index 0000000..6f0da76 Binary files /dev/null and b/._.DS_Store differ diff --git a/.github/.DS_Store b/.github/.DS_Store new file mode 100644 index 0000000..2ff9b28 Binary files /dev/null and b/.github/.DS_Store differ diff --git a/.github/._.DS_Store b/.github/._.DS_Store new file mode 100644 index 0000000..aaafa1f Binary files /dev/null and b/.github/._.DS_Store differ 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.yml b/.github/workflows/essentialsplugins-betabuilds.yml deleted file mode 100644 index ad34045..0000000 --- a/.github/workflows/essentialsplugins-betabuilds.yml +++ /dev/null @@ -1,271 +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" | 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 - echo "NUSPEC_FILE=$($nuspec_file.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - - name: Add nuget.exe - uses: nuget/setup-nuget@v1 - - name: Add Github Packages source - 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 - - name: Add nuget.org API Key - run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - - name: Create nuget package - run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - - name: Publish nuget package to Github registry - 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 - 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 deleted file mode 100644 index 3e169ce..0000000 --- a/.github/workflows/essentialsplugins-releasebuilds.yml +++ /dev/null @@ -1,219 +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" | 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 - echo "NUSPEC_FILE=$($nuspec_file.BaseName)"| Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - - name: Add nuget.exe - uses: nuget/setup-nuget@v1 - - name: Add Github Packages source - 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 - - name: Add nuget.org API Key - run: nuget setApiKey ${{ secrets.NUGET_API_KEY }} - - name: Create nuget package - run: nuget pack "./${{ env.NUSPEC_FILE}}.nuspec" -version ${{ env.VERSION }} - - name: Publish nuget package to Github registry - 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 - run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json diff --git a/.gitignore b/.gitignore index a94bae4..67fcf59 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,10 @@ *.sln.docstates *.projectinfo +[Oo]utput/ +*._ +*.cplz + # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs @@ -353,3 +357,5 @@ MigrationBackup/ .ionide/ *.projectinfo *.projectinfo~Stashed changes +/output/epi-sony-bravia.4Series.1.0.0-local.cplz +/._.gitignore 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/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..d67fed7 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,7 @@ +Copyright (c) <2020> PepperDash Technology Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/SonyBraviaEpi.sln b/SonyBraviaEpi.3Series.sln similarity index 100% rename from SonyBraviaEpi.sln rename to SonyBraviaEpi.3Series.sln diff --git a/epi-sony-bravia.4Series.sln b/epi-sony-bravia.4Series.sln new file mode 100644 index 0000000..94ed273 --- /dev/null +++ b/epi-sony-bravia.4Series.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34408.163 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "epi-sony-bravia.4Series", "src\epi-sony-bravia.4Series.csproj", "{A93F076E-84AA-49D9-81BF-5632599E7933}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A93F076E-84AA-49D9-81BF-5632599E7933}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A93F076E-84AA-49D9-81BF-5632599E7933}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A93F076E-84AA-49D9-81BF-5632599E7933}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A93F076E-84AA-49D9-81BF-5632599E7933}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2D8B4216-1F88-4B54-BB65-452F86F15482} + EndGlobalSection +EndGlobal diff --git a/packages.config b/packages.config index f8f712e..da29c1d 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 new file mode 100644 index 0000000..64af439 --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,21 @@ + + + 1.0.0-local + $(Version) + PepperDash Technologies + PepperDash Technologies + PepperDash Sony Bravia Display + Copyright © 2024 + https://github.com/PepperDash/epi-sony-bravia + 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; + + + + + + + + + + + diff --git a/src/Rs232Commands.cs b/src/Rs232Commands.cs index abdd7ba..788c372 100644 --- a/src/Rs232Commands.cs +++ b/src/Rs232Commands.cs @@ -8,8 +8,7 @@ namespace SonyBraviaEpi public static class Rs232Commands { public static readonly byte[] PowerOn = {0x8c, 0x00, 0x00, 0x02, 0x01}; - public static readonly byte[] PowerOff = {0x8c, 0x00, 0x00, 0x02, 0x00}; - public static readonly byte[] PowerQuery = {0x83, 0x00, 0x00, 0xFF, 0xFF}; + public static readonly byte[] PowerOff = {0x8c, 0x00, 0x00, 0x02, 0x00}; public static readonly byte[] InputVideo1 = {0x8C, 0x00, 0x02, 0x03, 0x02, 0x01}; public static readonly byte[] InputVideo2 = {0x8C, 0x00, 0x02, 0x03, 0x02, 0x02}; public static readonly byte[] InputVideo3 = {0x8C, 0x00, 0x02, 0x03, 0x02, 0x03}; @@ -22,7 +21,18 @@ public static class Rs232Commands public static readonly byte[] InputHdmi4 = {0x8C, 0x00, 0x02, 0x03, 0x04, 0x04}; public static readonly byte[] InputHdmi5 = {0x8C, 0x00, 0x02, 0x03, 0x04, 0x05}; public static readonly byte[] InputPc1 = {0x8C, 0x00, 0x02, 0x03, 0x05, 0x01}; - public static readonly byte[] InputQuery = {0x83, 0x00, 0x02, 0xFF, 0xFF}; + + public static readonly byte[] VolumeUp = { 0x8C, 0x00, 0x05, 0x03, 0x00, 0x00 }; + public static readonly byte[] VolumeDown = { 0x8C, 0x00, 0x05, 0x03, 0x00, 0x01 }; + public static readonly byte[] VolumeDirect = { 0x83, 0x00, 0x05, 0x03, 0x01, 0x00 }; //reset byte[5] to actual volume level + + public static readonly byte[] MuteOn = { 0x8C, 0x00, 0x06, 0x03, 0x01, 0x01}; + public static readonly byte[] MuteOff = { 0x8C, 0x00, 0x06, 0x03, 0x01, 0x00 }; + + public static readonly byte[] PowerQuery = { 0x83, 0x00, 0x00, 0xFF, 0xFF }; + public static readonly byte[] InputQuery = { 0x83, 0x00, 0x02, 0xFF, 0xFF }; + public static readonly byte[] VolumeQuery = { 0x83, 0x00, 0x05, 0xFF, 0xFF }; + public static readonly byte[] MuteQuery = { 0x83, 0x00, 0x06, 0xFF, 0xFF }; public static byte CalculateChecksum(this byte[] data) { @@ -41,84 +51,135 @@ public static byte[] WithChecksum(this byte[] data) return newArray.ToArray(); } - public static IQueueMessage GetPowerOn(IBasicCommunication coms) + public static IQueueMessage GetVolumeQuery(IBasicCommunication coms, Action action) + { + return new Rs232Command(coms, VolumeQuery.WithChecksum(), action, eCommandType.VolumeQuery); + } + + public static IQueueMessage GetVolumeUp(IBasicCommunication coms, Action action) + { + return new Rs232Command(coms, VolumeUp.WithChecksum(), action, eCommandType.Command); + } + + public static IQueueMessage GetVolumeDown(IBasicCommunication coms, Action action) + { + return new Rs232Command(coms, VolumeDown.WithChecksum(), action, eCommandType.Command); + } + + public static IQueueMessage GetVolumeDirect(IBasicCommunication coms, Action action, int volume) + { + if(volume < 0 ) + { + VolumeDirect[5] = 0x00; + + return new Rs232Command(coms, VolumeDirect.WithChecksum(), action, eCommandType.Command); + } + + if (volume > 255) + { + VolumeDirect[5] = 0xFF; + + return new Rs232Command(coms, VolumeDirect.WithChecksum(), action, eCommandType.Command); + } + + VolumeDirect[5] = (byte) volume; + + return new Rs232Command(coms, VolumeDirect.WithChecksum(), action, eCommandType.Command); + } + + public static IQueueMessage GetMuteQuery(IBasicCommunication coms, Action action) + { + return new Rs232Command(coms, MuteQuery.WithChecksum(), action, eCommandType.MuteQuery); + } + + public static IQueueMessage GetMuteOn(IBasicCommunication coms, Action action) + { + return new Rs232Command(coms, MuteOn.WithChecksum(), action, eCommandType.Command); + } + + public static IQueueMessage GetMuteOff(IBasicCommunication coms, Action action) { - return new ComsMessage(coms, PowerOn.WithChecksum()); + return new Rs232Command(coms, MuteOff.WithChecksum(), action, eCommandType.Command); } - public static IQueueMessage GetPowerOff(IBasicCommunication coms) + public static IQueueMessage GetPowerOn(IBasicCommunication coms, Action action) { - return new ComsMessage(coms, PowerOff.WithChecksum()); + return new Rs232Command(coms, PowerOn.WithChecksum(), action, eCommandType.Command); } - public static IQueueMessage GetPowerQuery(IBasicCommunication coms) + public static IQueueMessage GetPowerOff(IBasicCommunication coms, Action action) { - return new ComsMessage(coms, PowerQuery.WithChecksum()); + return new Rs232Command(coms, PowerOff.WithChecksum(), action, eCommandType.Command); } - public static IQueueMessage GetHdmi1(IBasicCommunication coms) + public static IQueueMessage GetPowerQuery(IBasicCommunication coms, Action action) { - return new ComsMessage(coms, InputHdmi1.WithChecksum()); + return new Rs232Command(coms, PowerQuery.WithChecksum(), action, eCommandType.PowerQuery); } - public static IQueueMessage GetHdmi2(IBasicCommunication coms) + public static IQueueMessage GetHdmi1(IBasicCommunication coms, Action action) { - return new ComsMessage(coms, InputHdmi2.WithChecksum()); + return new Rs232Command(coms, InputHdmi1.WithChecksum(), action, eCommandType.Command); } - public static IQueueMessage GetHdmi3(IBasicCommunication coms) + public static IQueueMessage GetHdmi2(IBasicCommunication coms, Action action) { - return new ComsMessage(coms, InputHdmi3.WithChecksum()); + return new Rs232Command(coms, InputHdmi2.WithChecksum(), action, eCommandType.Command); } - public static IQueueMessage GetHdmi4(IBasicCommunication coms) + public static IQueueMessage GetHdmi3(IBasicCommunication coms, Action action) { - return new ComsMessage(coms, InputHdmi4.WithChecksum()); + return new Rs232Command(coms, InputHdmi3.WithChecksum(), action, eCommandType.Command); } - public static IQueueMessage GetHdmi5(IBasicCommunication coms) + public static IQueueMessage GetHdmi4(IBasicCommunication coms, Action action) { - return new ComsMessage(coms, InputHdmi5.WithChecksum()); + return new Rs232Command(coms, InputHdmi4.WithChecksum(), action, eCommandType.Command); } - public static IQueueMessage GetVideo1(IBasicCommunication coms) + public static IQueueMessage GetHdmi5(IBasicCommunication coms, Action action) { - return new ComsMessage(coms, InputVideo1.WithChecksum()); + return new Rs232Command(coms, InputHdmi5.WithChecksum(), action, eCommandType.Command); } - public static IQueueMessage GetVideo2(IBasicCommunication coms) + public static IQueueMessage GetVideo1(IBasicCommunication coms, Action action) { - return new ComsMessage(coms, InputVideo2.WithChecksum()); + return new Rs232Command(coms, InputVideo1.WithChecksum(), action, eCommandType.Command); } - public static IQueueMessage GetVideo3(IBasicCommunication coms) + public static IQueueMessage GetVideo2(IBasicCommunication coms, Action action) { - return new ComsMessage(coms, InputVideo3.WithChecksum()); + return new Rs232Command(coms, InputVideo2.WithChecksum(), action, eCommandType.Command); } - public static IQueueMessage GetComponent1(IBasicCommunication coms) + public static IQueueMessage GetVideo3(IBasicCommunication coms, Action action) { - return new ComsMessage(coms, InputComponent1.WithChecksum()); + return new Rs232Command(coms, InputVideo3.WithChecksum(), action, eCommandType.Command); } - public static IQueueMessage GetComponent2(IBasicCommunication coms) + public static IQueueMessage GetComponent1(IBasicCommunication coms, Action action) { - return new ComsMessage(coms, InputComponent2.WithChecksum()); + return new Rs232Command(coms, InputComponent1.WithChecksum(), action, eCommandType.Command); } - public static IQueueMessage GetComponent3(IBasicCommunication coms) + public static IQueueMessage GetComponent2(IBasicCommunication coms, Action action) { - return new ComsMessage(coms, InputComponent3.WithChecksum()); + return new Rs232Command(coms, InputComponent2.WithChecksum(), action, eCommandType.Command); } - public static IQueueMessage GetPc(IBasicCommunication coms) + public static IQueueMessage GetComponent3(IBasicCommunication coms, Action action) { - return new ComsMessage(coms, InputPc1.WithChecksum()); + return new Rs232Command(coms, InputComponent3.WithChecksum(), action, eCommandType.Command); } - public static IQueueMessage GetInputQuery(IBasicCommunication coms) + public static IQueueMessage GetPc(IBasicCommunication coms, Action action) { - return new ComsMessage(coms, InputQuery.WithChecksum()); + return new Rs232Command(coms, InputPc1.WithChecksum(), action, eCommandType.Command); + } + + public static IQueueMessage GetInputQuery(IBasicCommunication coms, Action action) + { + return new Rs232Command(coms, InputQuery.WithChecksum(), action, eCommandType.InputQuery); } /*const commands = { "power_on": [0x8C, 0x00, 0x00, 0x02, 0x01], @@ -249,4 +310,71 @@ public static IQueueMessage GetInputQuery(IBasicCommunication coms) "signage_productinfo3": [0x83, 0x00, 0x6C, 0xFF, 0xFF] }*/ } + + public class Rs232Command:IQueueMessage + { + private readonly Action _action; + + private readonly byte[] _message; + + private readonly IBasicCommunication _comm; + + private readonly eCommandType _commandType; + + public Rs232Command(IBasicCommunication coms, byte[] message, Action updateCommandAction, eCommandType commandType) + { + if(coms == null) + { +#if SERIES4 + throw new ArgumentNullException(nameof(coms)); +#else + throw new ArgumentNullException("coms"); +#endif + } + + if (message == null) + { +#if SERIES4 + throw new ArgumentNullException(nameof(message)); +#else + throw new ArgumentNullException("message"); +#endif + } + + if (updateCommandAction == null) + { +#if SERIES4 + throw new ArgumentNullException(nameof(updateCommandAction)); +#else + throw new ArgumentNullException("updateCommandAction"); +#endif + } + + _action = updateCommandAction; + _message = message; + _comm = coms; + _commandType = commandType; + } + + public void Dispatch() + { + _action(_commandType); + + _comm.SendBytes(_message); + } + + public override string ToString() + { + return _message.ToString(); + } + } + + public enum eCommandType + { + Command, + PowerQuery, + InputQuery, + VolumeQuery, + MuteQuery + } } \ No newline at end of file diff --git a/src/Rs232ParsingUtils.cs b/src/Rs232ParsingUtils.cs index 7386c0f..5e3f106 100644 --- a/src/Rs232ParsingUtils.cs +++ b/src/Rs232ParsingUtils.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using PepperDash.Core; @@ -6,42 +7,81 @@ namespace SonyBraviaEpi { public static class Rs232ParsingUtils { + private static Dictionary _inputMap = new Dictionary + { + {0x0201,"video1" }, + {0x0202,"video2" }, + {0x0203,"video3" }, + {0x0301, "component1" }, + {0x0302,"component2" }, + {0x0303,"component3" }, + {0x0401,"hdmi1" }, + {0x0402,"hdmi2" }, + {0x0403,"hdmi3" }, + {0x0404,"hdmi4" }, + {0x0405,"hdmi5" }, + {0x0501,"vga1" } + }; private const byte Header = 0x70; - public static bool ParsePowerResponse(this byte[] response, out bool power) - { - // TODO [ ] actually add in parsing + public static bool ParsePowerResponse(this byte[] response) + { Debug.Console(DebugLevels.DebugLevel, "ParsePowerResponse response: {0}", response.ToReadableString()); if (response[2] == 0x00) { - power = response[3] == 0x01; - return true; + return response[3] == 0x01; } if (response[2] == 0x02) { - power = response[3] != 0x00; - return true; + return response[3] != 0x00; } - power = false; return false; } - public static bool ParseInputResponse(this byte[] response, out string input) + public static string ParseInputResponse(this byte[] response) { // TODO [ ] actually add in parsing Debug.Console(DebugLevels.DebugLevel, "ParseInputResponse response: {0}", response.ToReadableString()); - if (response[2] == 0x02) + //add together the input type byte & the input number byte + var inputNumber = response[3] << 8 | response[4]; + + string input; + + if(_inputMap.TryGetValue(inputNumber,out input)) { - input = ""; - //return true; + Debug.Console(DebugLevels.DebugLevel, "Got input {0}", input); + return input; } - input = ""; - return false; + return input; + } + + public static int ParseVolumeResponse(this byte[] response) + { + //not a direct volume response + if (response[3] != 0x01) + { + return 0; + } + + return response[4]; + } + + /// + /// True = isMuted + /// + /// + /// + public static bool ParseMuteResponse(this byte[] response) + { + //not a direct mute response + if (response[3] != 0x01) { return false; } + + return response[4] == 0x01; } public static bool IsComplete(this byte[] message) diff --git a/src/SimpleIpParsingUtils.cs b/src/SimpleIpParsingUtils.cs index 431b041..1293fbe 100644 --- a/src/SimpleIpParsingUtils.cs +++ b/src/SimpleIpParsingUtils.cs @@ -5,7 +5,7 @@ namespace SonyBraviaEpi { public static class SimpleIpParsingUtils { - public static IEnumerable SplitInParts(this String s, Int32 partLength) + public static IEnumerable SplitInParts(this string s, int partLength) { if ((s == null) || (partLength <= 0)) yield break; for (var i = 0; i < s.Length; i += partLength) diff --git a/src/SonyBraviaDevice.cs b/src/SonyBraviaDevice.cs index 015658a..0f88eca 100644 --- a/src/SonyBraviaDevice.cs +++ b/src/SonyBraviaDevice.cs @@ -10,6 +10,7 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; +using PepperDash.Essentials.Core.DeviceTypeInterfaces; using PepperDash.Essentials.Core.Queues; using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Devices.Displays; @@ -18,7 +19,11 @@ namespace SonyBraviaEpi { public class SonyBraviaDevice : TwoWayDisplayBase, ICommunicationMonitor, IBridgeAdvanced, IInputHdmi1, IInputHdmi2, IInputHdmi3, IInputHdmi4, IInputVga1, - IOnline + IOnline, + IBasicVolumeWithFeedback +#if SERIES4 + , IHasInputs +#endif { private readonly IBasicCommunication _coms; private readonly bool _comsIsRs232; @@ -44,12 +49,20 @@ public class SonyBraviaDevice : TwoWayDisplayBase, ICommunicationMonitor, IBridg private readonly long _coolingTimeMs; private readonly long _warmingtimeMs; - /// - /// Constructor - /// - /// - /// - public SonyBraviaDevice(DeviceConfig config, IBasicCommunication comms) + private Dictionary _ackStringFormats = new Dictionary { + {0x00, "Control complete ({0})"}, + {0x01, "Abnormal End: over maximum value ({0})" }, + {0x02, "Abnormal End: under minimum value ({0})" }, + {0x03, "Abnormal End: command cancelled ({0})"}, + {0x04, "Abnormal End: parse error/data format error ({0})" } + }; + + /// + /// Constructor + /// + /// + /// + public SonyBraviaDevice(DeviceConfig config, IBasicCommunication comms) : base(config.Key, config.Name) { DebugLevels.Key = Key; @@ -60,6 +73,8 @@ public SonyBraviaDevice(DeviceConfig config, IBasicCommunication comms) IQueueMessage powerQuery; IQueueMessage inputQuery; + IQueueMessage volumeQuery; + IQueueMessage muteQuery; _coms = comms; var socket = _coms as ISocketStatus; @@ -69,10 +84,12 @@ public SonyBraviaDevice(DeviceConfig config, IBasicCommunication comms) _queueRs232 = new CrestronQueue(50); _coms.BytesReceived += (sender, args) => _queueRs232.Enqueue(args.Bytes); - _powerOnCommand = Rs232Commands.GetPowerOn(_coms); - _powerOffCommand = Rs232Commands.GetPowerOff(_coms); - powerQuery = Rs232Commands.GetPowerQuery(_coms); - inputQuery = Rs232Commands.GetInputQuery(_coms); + _powerOnCommand = Rs232Commands.GetPowerOn(_coms, UpdateLastSentCommandType); + _powerOffCommand = Rs232Commands.GetPowerOff(_coms, UpdateLastSentCommandType); + powerQuery = Rs232Commands.GetPowerQuery(_coms, UpdateLastSentCommandType); + inputQuery = Rs232Commands.GetInputQuery(_coms, UpdateLastSentCommandType); + volumeQuery = Rs232Commands.GetVolumeQuery(_coms, UpdateLastSentCommandType); + muteQuery = Rs232Commands.GetMuteQuery(_coms, UpdateLastSentCommandType); } else { @@ -84,10 +101,12 @@ public SonyBraviaDevice(DeviceConfig config, IBasicCommunication comms) _powerOffCommand = SimpleIpCommands.GetControlCommand(_coms, "POWR", 0); powerQuery = SimpleIpCommands.GetQueryCommand(_coms, "POWR"); inputQuery = SimpleIpCommands.GetQueryCommand(_coms, "INPT"); + volumeQuery = SimpleIpCommands.GetQueryCommand(_coms, "VOLU"); + muteQuery = SimpleIpCommands.GetQueryCommand(_coms, "AMUT"); } if (CommandQueue == null) - CommandQueue = new GenericQueue(string.Format("{0}-commandQueue", config.Key), 50); + CommandQueue = new GenericQueue(string.Format("{0}-commandQueue", config.Key),100, 50); var monitorConfig = props.CommunicationMonitorProperties ?? DefaultMonitorConfig; CommunicationMonitor = new GenericCommunicationMonitor( @@ -96,11 +115,17 @@ public SonyBraviaDevice(DeviceConfig config, IBasicCommunication comms) BuildInputRoutingPorts(); + SetupInputs(); + + var worker = _comsIsRs232 ? new Thread(ProcessRs232Response, null) : new Thread(ProcessSimpleIpResponse, null); - _pollTimer = new CTimer(Poll, new[] { powerQuery, inputQuery }, Timeout.Infinite); + _pollTimer = new CTimer((o) => Poll(new List { powerQuery, inputQuery, muteQuery, volumeQuery }),Timeout.Infinite); + + MuteFeedback = new BoolFeedback(() => _muted); + VolumeLevelFeedback = new IntFeedback(() => CrestronEnvironment.ScaleWithLimits(_rawVolume, 255, 0, 65535, 0)); CrestronEnvironment.ProgramStatusEventHandler += type => { @@ -119,22 +144,29 @@ public SonyBraviaDevice(DeviceConfig config, IBasicCommunication comms) Debug.Console(DebugLevels.ErrorLevel, this, Debug.ErrorLogLevel.Notice, "Caught an exception at program stop: {0}{1}", ex.Message, ex.StackTrace); } - }; + }; + } - DeviceManager.AllDevicesActivated += (sender, args) => + public override void Initialize() + { + try { - try - { - _coms.Connect(); - CommunicationMonitor.Start(); - _pollTimer.Reset(5000, 15000); - } - catch (Exception ex) - { - Debug.Console(DebugLevels.ErrorLevel, this, Debug.ErrorLogLevel.Notice, "Caught an exception at AllDevicesActivated: {0}{1}", - ex.Message, ex.StackTrace); - } - }; + _coms.Connect(); + CommunicationMonitor.Start(); + _pollTimer.Reset(5000, 15000); + } + catch (Exception ex) + { + Debug.Console(DebugLevels.ErrorLevel, this, Debug.ErrorLogLevel.Notice, "Caught an exception at AllDevicesActivated: {0}{1}", + ex.Message, ex.StackTrace); + } + } + + private eCommandType _lastCommandType; + + private void UpdateLastSentCommandType(eCommandType commandType) + { + _lastCommandType = commandType; } /// @@ -229,23 +261,27 @@ public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, E public BoolFeedback IsOnline { get { return CommunicationMonitor.IsOnlineFeedback; } } +#if SERIES4 + public ISelectableItems Inputs { get; private set; } +#endif + private bool _muted; + + private int _rawVolume; + + public BoolFeedback MuteFeedback { get; private set; } + + public IntFeedback VolumeLevelFeedback { get; private set; } + /// /// Poll device /// /// - public static void Poll(object o) + public static void Poll(List commands) { - var commands = o as IEnumerable; - if (commands == null) - return; - - commands - .ToList() - .ForEach(command => - { - CommandQueue.Enqueue(command); - Thread.Sleep(100); - }); + foreach(var command in commands) + { + CommandQueue.Enqueue(command); + } } /// @@ -287,7 +323,7 @@ public override void PowerToggle() public void PowerPoll() { CommandQueue.Enqueue(_comsIsRs232 - ? Rs232Commands.GetPowerQuery(_coms) + ? Rs232Commands.GetPowerQuery(_coms, UpdateLastSentCommandType) : SimpleIpCommands.GetQueryCommand(_coms, "POWR")); } @@ -367,13 +403,85 @@ public void BuildInputRoutingPorts() new Action(InputComponent3), this), 12); } + private void SetupInputs() + { +#if SERIES4 + Inputs = new SonyBraviaInputs + { + Items = new Dictionary + { + { + "hdmi1", new SonyBraviaInput("Hdmi1", "HDMI 1", this, + _comsIsRs232 ? Rs232Commands.GetHdmi1(_coms, UpdateLastSentCommandType) + : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Hdmi, 1))}, + { + + "hdmi2", new SonyBraviaInput("hdmi2", "HDMI 2", this, + _comsIsRs232 ? Rs232Commands.GetHdmi2(_coms, UpdateLastSentCommandType) + : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Hdmi, 2)) + }, + { + "hdmi3", new SonyBraviaInput("hdmi3", "HDMI 3", this, + _comsIsRs232 ? Rs232Commands.GetHdmi3(_coms, UpdateLastSentCommandType) + : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Hdmi, 3)) + }, + { + "hdmi4", new SonyBraviaInput("hdmi4", "HDMI 4", this, + _comsIsRs232 ? Rs232Commands.GetHdmi4(_coms, UpdateLastSentCommandType) + : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Hdmi, 4)) + }, + { + "hdmi5", new SonyBraviaInput("hdmi5", "HDMI 5", this, + _comsIsRs232 ? Rs232Commands.GetHdmi5(_coms, UpdateLastSentCommandType) + : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Hdmi, 5)) + }, + { + "video1", new SonyBraviaInput("video1", "Video 1", this, + _comsIsRs232 ? Rs232Commands.GetVideo1(_coms, UpdateLastSentCommandType) + : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Composite, 1)) + }, + { + "video2", new SonyBraviaInput("video2", "Video 2", this, + _comsIsRs232 ? Rs232Commands.GetVideo2(_coms, UpdateLastSentCommandType) + : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Composite, 2)) + }, + { + "video3", new SonyBraviaInput("video3", "Video 3", this, + _comsIsRs232 ? Rs232Commands.GetVideo3(_coms, UpdateLastSentCommandType) + : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Composite, 3)) + }, + { + "component1", new SonyBraviaInput("component1", "Component 1", this, + _comsIsRs232 ? Rs232Commands.GetComponent1(_coms, UpdateLastSentCommandType) + : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Component, 1)) + }, + { + "component2", new SonyBraviaInput("component2", "Component 2", this, + _comsIsRs232 ? Rs232Commands.GetComponent2(_coms, UpdateLastSentCommandType) + : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Component, 2)) + }, + { + "component3", new SonyBraviaInput("component3", "Component 3", this, + _comsIsRs232 ? Rs232Commands.GetComponent3(_coms, UpdateLastSentCommandType) + : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Component, 3)) + }, + { + "vga1", new SonyBraviaInput("vga1", "VGA 1", this, + _comsIsRs232 ? Rs232Commands.GetComponent1(_coms, UpdateLastSentCommandType) + : null) + } + } + }; +#endif + } + /// /// Select HDMI 1 input /// public void InputHdmi1() { CommandQueue.Enqueue(_comsIsRs232 - ? Rs232Commands.GetHdmi1(_coms) + ? Rs232Commands.GetHdmi1(_coms, UpdateLastSentCommandType) : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Hdmi, 1)); } @@ -383,7 +491,7 @@ public void InputHdmi1() public void InputHdmi2() { CommandQueue.Enqueue(_comsIsRs232 - ? Rs232Commands.GetHdmi2(_coms) + ? Rs232Commands.GetHdmi2(_coms, UpdateLastSentCommandType) : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Hdmi, 2)); } @@ -393,7 +501,7 @@ public void InputHdmi2() public void InputHdmi3() { CommandQueue.Enqueue(_comsIsRs232 - ? Rs232Commands.GetHdmi3(_coms) + ? Rs232Commands.GetHdmi3(_coms, UpdateLastSentCommandType) : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Hdmi, 3)); } @@ -403,7 +511,7 @@ public void InputHdmi3() public void InputHdmi4() { CommandQueue.Enqueue(_comsIsRs232 - ? Rs232Commands.GetHdmi4(_coms) + ? Rs232Commands.GetHdmi4(_coms, UpdateLastSentCommandType) : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Hdmi, 4)); } @@ -413,7 +521,7 @@ public void InputHdmi4() public void InputHdmi5() { CommandQueue.Enqueue(_comsIsRs232 - ? Rs232Commands.GetHdmi5(_coms) + ? Rs232Commands.GetHdmi5(_coms, UpdateLastSentCommandType) : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Hdmi, 5)); } @@ -423,7 +531,7 @@ public void InputHdmi5() public void InputVideo1() { CommandQueue.Enqueue(_comsIsRs232 - ? Rs232Commands.GetVideo1(_coms) + ? Rs232Commands.GetVideo1(_coms, UpdateLastSentCommandType) : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Composite, 1)); } @@ -433,7 +541,7 @@ public void InputVideo1() public void InputVideo2() { CommandQueue.Enqueue(_comsIsRs232 - ? Rs232Commands.GetVideo2(_coms) + ? Rs232Commands.GetVideo2(_coms, UpdateLastSentCommandType) : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Composite, 2)); } @@ -443,7 +551,7 @@ public void InputVideo2() public void InputVideo3() { CommandQueue.Enqueue(_comsIsRs232 - ? Rs232Commands.GetVideo3(_coms) + ? Rs232Commands.GetVideo3(_coms, UpdateLastSentCommandType) : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Composite, 3)); } @@ -453,7 +561,7 @@ public void InputVideo3() public void InputComponent1() { CommandQueue.Enqueue(_comsIsRs232 - ? Rs232Commands.GetComponent1(_coms) + ? Rs232Commands.GetComponent1(_coms, UpdateLastSentCommandType) : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Component, 1)); } @@ -463,7 +571,7 @@ public void InputComponent1() public void InputComponent2() { CommandQueue.Enqueue(_comsIsRs232 - ? Rs232Commands.GetComponent2(_coms) + ? Rs232Commands.GetComponent2(_coms, UpdateLastSentCommandType) : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Component, 2)); } @@ -473,7 +581,7 @@ public void InputComponent2() public void InputComponent3() { CommandQueue.Enqueue(_comsIsRs232 - ? Rs232Commands.GetComponent3(_coms) + ? Rs232Commands.GetComponent3(_coms, UpdateLastSentCommandType) : SimpleIpCommands.GetInputCommand(_coms, SimpleIpCommands.InputTypes.Component, 3)); } @@ -483,7 +591,7 @@ public void InputComponent3() public void InputVga1() { CommandQueue.Enqueue(_comsIsRs232 - ? Rs232Commands.GetComponent1(_coms) + ? Rs232Commands.GetComponent1(_coms, UpdateLastSentCommandType) : null); } @@ -495,7 +603,7 @@ public void InputPoll() // byte[] poll = { 0x83, 0x00, 0x02, 0xFF, 0xFF, 0x83 }; //CommandQueue.Enqueue(Rs232Commands.GetInputQuery(_coms)); CommandQueue.Enqueue(_comsIsRs232 - ? Rs232Commands.GetInputQuery(_coms) + ? Rs232Commands.GetInputQuery(_coms, UpdateLastSentCommandType) : SimpleIpCommands.GetQueryCommand(_coms, "INPT")); } @@ -547,11 +655,9 @@ private object ProcessRs232Response(object _) { Debug.Console(DebugLevels.ErrorLevel, this, "ProcessRs232Response: _queueRs232.Dequeue failed, object was null"); return null; - } + } - Debug.Console(DebugLevels.ErrorLevel, this, seperator); - Debug.Console(DebugLevels.ErrorLevel, this, "ProcessRs232Response: bytes-'{0}' (len-'{1}')", - bytes.ToReadableString(), bytes.Length); + Debug.Console(DebugLevels.ErrorLevel, this, "ProcessRs232Response: bytes-'{0}' (len-'{1}')", bytes.ToReadableString(), bytes.Length); if (buffer == null) buffer = bytes; @@ -563,8 +669,7 @@ private object ProcessRs232Response(object _) buffer = newBuffer; } - Debug.Console(DebugLevels.ErrorLevel, this, "ProcessRs232Response: bytes-'{0}' (len-'{1}') | buffer-'{2}' (len-'{3}')", - bytes.ToReadableString(), bytes.Length, buffer.ToReadableString(), buffer.Length); + Debug.Console(DebugLevels.ErrorLevel, this, "ProcessRs232Response: bytes-'{0}' (len-'{1}') | buffer-'{2}' (len-'{3}')", bytes.ToReadableString(), bytes.Length, buffer.ToReadableString(), buffer.Length); if (!buffer.ContainsHeader()) { @@ -598,52 +703,16 @@ private object ProcessRs232Response(object _) bytes.ToReadableString(), bytes.Length, buffer.ToReadableString(), buffer.Length, message.ToReadableString(), message.Length); - - if (message.Length < 4) + switch (_lastCommandType) { - // we have an ACK in here, let's print it out and keep moving - switch (message.ToReadableString()) - { - // response to query request (abnormal end) - Command Cancelled - // package is recieved normally, but the request is not acceptable in the current display status - case "07-00-70": - { - Debug.Console(DebugLevels.DebugLevel, this, "Control complete ({0})", message.ToReadableString()); - break; - } - case "07-01-71": - { - Debug.Console(DebugLevels.DebugLevel, this, "Abnormal End: over maximum value ({0})", message.ToReadableString()); - break; - } - case "07-02-72": - { - Debug.Console(DebugLevels.DebugLevel, this, "Abnormal End: under minimum value ({0})", message.ToReadableString()); - break; - } - case "70-03-73": - { - Debug.Console(DebugLevels.DebugLevel, this, "Abnormal End: command cancelled ({0})", message.ToReadableString()); - break; - } - case "70-04-74": - { - Debug.Console(DebugLevels.DebugLevel, this, "Abnormal End: parse error/data format error ({0})", message.ToReadableString()); - break; - } - default: - { - Debug.Console(DebugLevels.DebugLevel, this, "Unknown Response: {0}", message.ToReadableString()); - break; - } - } - - buffer = buffer.CleanOutFirstMessage(); - Debug.Console(DebugLevels.ErrorLevel, this, "ProcessRs232Response: buffer-'{0}' (len-'{1}')", - buffer.ToReadableString(), buffer.Length); + case eCommandType.Command: + { + HandleAck(message); + buffer = buffer.CleanOutFirstMessage(); + continue; + } - continue; - } + } // we have a full message, lets check it out Debug.Console(DebugLevels.ErrorLevel, this, "ProcessRs232Response: message-'{0}' (len-'{1}')", @@ -662,23 +731,49 @@ private object ProcessRs232Response(object _) break; } - bool powerResult; - if (buffer.ParsePowerResponse(out powerResult)) + switch (_lastCommandType) { - PowerIsOn = powerResult; - PowerIsOnFeedback.FireUpdate(); - } + case eCommandType.PowerQuery: + { + PowerIsOn = buffer.ParsePowerResponse(); - string input; - if (buffer.ParseInputResponse(out input)) - { - _currentInput = input; - CurrentInputFeedback.FireUpdate(); - } + PowerIsOnFeedback.FireUpdate(); + break; + } + case eCommandType.InputQuery: + { + _currentInput = buffer.ParseInputResponse(); + CurrentInputFeedback.FireUpdate(); - buffer = buffer.NumberOfHeaders() > 1 ? buffer.CleanOutFirstMessage() : new byte[0]; +#if SERIES4 + if (Inputs.Items.ContainsKey(_currentInput)) + { + foreach (var item in Inputs.Items) + { + item.Value.IsSelected = item.Key.Equals(_currentInput); + } + } - Debug.Console(DebugLevels.DebugLevel, this, seperator); + Inputs.CurrentItem = _currentInput; +#endif + break; + } + case eCommandType.VolumeQuery: + { + _rawVolume = buffer.ParseVolumeResponse(); + + VolumeLevelFeedback.FireUpdate(); + break; + } + case eCommandType.MuteQuery: + { + _muted = buffer.ParseMuteResponse(); + MuteFeedback.FireUpdate(); + break; + } + } + + buffer = buffer.NumberOfHeaders() > 1 ? buffer.CleanOutFirstMessage() : new byte[0]; } } catch (Exception ex) @@ -693,6 +788,19 @@ private object ProcessRs232Response(object _) } } + private void HandleAck(byte[] message) + { + string consoleMessageFormat; + + if (!_ackStringFormats.TryGetValue(message[1], out consoleMessageFormat)) + { + Debug.Console(DebugLevels.DebugLevel, this, "Unknown Response: {0}", message.ToReadableString()); + return; + } + + Debug.Console(DebugLevels.DebugLevel, this, consoleMessageFormat, message.ToReadableString()); + } + private object ProcessSimpleIpResponse(object _) { var seperator = new string('-', 50); @@ -785,6 +893,19 @@ private object ProcessSimpleIpResponse(object _) } } + +#if SERIES4 + // No idea if this will work with _currentInput. It's not clear how the input is determined for IP communication + if (Inputs.Items.ContainsKey(_currentInput)) + { + foreach (var item in Inputs.Items) + { + item.Value.IsSelected = item.Key.Equals(_currentInput); + } + } + + Inputs.CurrentItem = _currentInput; +#endif Debug.Console(DebugLevels.ErrorLevel, this, "ProcessSimpleIpResponse: _currentInput == '{0}'", _currentInput); break; @@ -813,5 +934,70 @@ private object ProcessSimpleIpResponse(object _) } } } + + public void EnqueueCommand(IQueueMessage command) + { + CommandQueue.Enqueue(command); + } + +#if SERIES4 + public void SetInput(string selector) + { + var input = Inputs.Items[selector]; + + if (input != null) + { + input.Select(); + } + } +#endif + public void MuteOn() + { + CommandQueue.Enqueue(_comsIsRs232 + ? Rs232Commands.GetMuteOn(_coms, UpdateLastSentCommandType) + : null); + } + + public void MuteOff() + { + CommandQueue.Enqueue(_comsIsRs232 + ? Rs232Commands.GetMuteOff(_coms, UpdateLastSentCommandType) + : null); + } + public void MuteToggle() + { + if (_muted) + { + MuteOff(); + return; + } + + MuteOn(); + } + + public void SetVolume(ushort level) + { + var scaledVolume = CrestronEnvironment.ScaleWithLimits(level, 65535, 0, 255, 0); + + CommandQueue.Enqueue(_comsIsRs232 + ? Rs232Commands.GetVolumeDirect(_coms, UpdateLastSentCommandType, scaledVolume) + : null); + } + + public void VolumeUp(bool pressRelease) + { + CommandQueue.Enqueue(_comsIsRs232 + ? Rs232Commands.GetVolumeUp(_coms, UpdateLastSentCommandType) + : null); + } + + public void VolumeDown(bool pressRelease) + { + CommandQueue.Enqueue(_comsIsRs232 + ? Rs232Commands.GetVolumeDown(_coms, UpdateLastSentCommandType) + : null); + } + + } } \ No newline at end of file diff --git a/src/SonyBraviaEpi.csproj b/src/SonyBraviaEpi.csproj index 450d310..c1ff93a 100644 --- a/src/SonyBraviaEpi.csproj +++ b/src/SonyBraviaEpi.csproj @@ -61,26 +61,26 @@ False - ..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll + ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll False False - ..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll + ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll False False - ..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll + ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll False - ..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe + ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe False False - ..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll + ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll diff --git a/src/SonyBraviaInputs.cs b/src/SonyBraviaInputs.cs new file mode 100644 index 0000000..0c24c88 --- /dev/null +++ b/src/SonyBraviaInputs.cs @@ -0,0 +1,100 @@ + +using PepperDash.Essentials.Core.DeviceTypeInterfaces; +using PepperDash.Essentials.Core.Queues; +using SonyBraviaEpi; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SonyBraviaEpi +{ +#if SERIES4 + public class SonyBraviaInputs : ISelectableItems + { + private Dictionary _items = new Dictionary(); + + public Dictionary Items + { + get + { + return _items; + } + set + { + if (_items == value) + return; + + _items = value; + + ItemsUpdated?.Invoke(this, null); + } + } + + private string _currentItem; + + public string CurrentItem + { + get + { + return _currentItem; + } + set + { + if (_currentItem == value) + return; + + _currentItem = value; + + CurrentItemChanged?.Invoke(this, null); + } + } + + public event EventHandler ItemsUpdated; + public event EventHandler CurrentItemChanged; + + } + + public class SonyBraviaInput : ISelectableItem + { + private bool _isSelected; + + private readonly IQueueMessage _inputCommand; + private readonly SonyBraviaDevice _parent; + + public SonyBraviaInput(string key, string name, SonyBraviaDevice parent, IQueueMessage inputCommand) + { + Key = key; + Name = name; + _parent = parent; + _inputCommand = inputCommand; + } + + public string Key { get; private set; } + public string Name { get; private set; } + + public event EventHandler ItemUpdated; + + public bool IsSelected + { + get { return _isSelected; } + set + { + if (value == _isSelected) + return; + + _isSelected = value; + var handler = ItemUpdated; + if (handler != null) + handler(this, EventArgs.Empty); + } + } + + public void Select() + { + _parent.EnqueueCommand(_inputCommand); + } + } +#endif +} diff --git a/src/epi-sony-bravia.4Series.csproj b/src/epi-sony-bravia.4Series.csproj new file mode 100644 index 0000000..807931b --- /dev/null +++ b/src/epi-sony-bravia.4Series.csproj @@ -0,0 +1,48 @@ + + + ProgramLibrary + + + net472 + Pepperdash.Essentials.Plugins.Display.Sony.Bravia + false + EPI.Sony.Bravia + PepperDash Technologies + This software is a plugin designed to work as a part of PepperDash Essentials for Crestron control processors. This plugin allows for control of Sony Bravia Displays. + Copyright 2024 + 1.0.0-local + true + $(Version) + 4Series\bin\$(Configuration)\ + PepperDash Technologies + Pepperdash.Essentials.Plugins.Display.Sony.Bravia + https://github.com/PepperDash/epi-sony-bravia + crestron 4series sony bravia + + + + $(DefineConstants);SERIES4 + + + + + + + + + + + + + + + + + + + + + + + +