Compare commits

..

66 Commits
1.6.0 ... 1.6.2

Author SHA1 Message Date
Neil Dorin
9af95e017a Merge pull request #384 from PepperDash/release/1.6.2
Release/1.6.2
2020-08-25 12:26:18 -06:00
Andrew Welker
5e74eaf3f2 Merge branch 'main' into release/1.6.2 2020-08-25 12:05:41 -06:00
Trevor Payne
74268d6a9b Merge pull request #383 from PepperDash/feature/Modify-LoadRoom-Errors
Change some console messages
2020-08-20 09:04:40 -05:00
Trevor Payne
4d53e6b33e Resolves #16
Changed some error messages to notices in LoadRooms() to make them a little less spooky
2020-08-19 17:07:11 -05:00
Trevor Payne
9f70031cc1 Merge pull request #356 from PepperDash/feature/Descriptive-CEC-genericComm-failure-message
Add descriptive CEC generic comm failure message
2020-08-19 16:42:01 -05:00
Trevor Payne
c74a92d220 Merge branch 'development' into feature/Descriptive-CEC-genericComm-failure-message 2020-08-19 16:28:02 -05:00
Andrew Welker
a4c24fc197 Merge pull request #379 from PepperDash/bugfix/ScreenSaver-Never-Starts
Fixed improperly set up device extender
2020-08-19 17:27:19 -04:00
Andrew Welker
25fccbd095 Merge branch 'development' into bugfix/ScreenSaver-Never-Starts 2020-08-19 17:11:54 -04:00
Neil Dorin
c9fce06bd7 Updates necessary to make screen saver disappear on incoming call 2020-08-19 14:53:47 -06:00
Trevor Payne
b1040b56d5 Fix Build Process 2020-08-19 13:30:28 -05:00
Neil Dorin
5359427981 Merge pull request #382 from PepperDash/feature/push-to-nuget.org
Put nuget publishing and consumption back where it's supposed to be
2020-08-19 11:23:16 -06:00
Andrew Welker
764f61a500 Merge branch 'development' into feature/push-to-nuget.org 2020-08-18 20:56:39 -04:00
Andrew Welker
e292790cea adding nuspec 2020-08-18 18:42:24 -06:00
Andrew Welker
1fb329f1c1 now it'll ACTUALLY use nuget 2020-08-18 17:05:46 -06:00
Andrew Welker
a2fc1b9f40 make essentials use nuget instead of submodule 2020-08-18 17:01:51 -06:00
Andrew Welker
419e7c5b31 fix readme.md 2020-08-18 16:59:15 -06:00
Andrew Welker
efbd78fb7c fixing everything to use nuget 2020-08-18 16:57:03 -06:00
Trevor Payne
486c951982 Fix some merge conflicts 2020-08-18 17:35:03 -05:00
Andrew Welker
fc67c53f4c Merge pull request #381 from PepperDash/feature/push-to-nuget.org
Re-add nuget stuff
2020-08-18 18:28:37 -04:00
Trevor Payne
f0a887981d Resolved Tracking Packages 2020-08-18 17:13:41 -05:00
Andrew Welker
7628b0ffff Merge branch 'development' into feature/push-to-nuget.org 2020-08-18 18:11:45 -04:00
Trevor Payne
63d8cf27fd gMerge branch 'bugfix/ScreenSaver-Never-Starts' of https://github.com/PepperDash/Essentials into bugfix/ScreenSaver-Never-Starts 2020-08-18 16:37:36 -05:00
Trevor Payne
eb9149b96a More gitignore changes 2020-08-18 16:37:28 -05:00
Trevor Payne
f5410c0786 Merge branch 'development' into bugfix/ScreenSaver-Never-Starts 2020-08-18 16:27:09 -05:00
Trevor Payne
7624445b4b Merge pull request #369 from PepperDash/bugfix/SystemMonitor-IndexOutOfRange
Fix system monitor index out of range exception
2020-08-18 16:26:45 -05:00
Trevor Payne
ece05caa28 Merge branch 'bugfix/ScreenSaver-Never-Starts' of https://github.com/PepperDash/Essentials into bugfix/ScreenSaver-Never-Starts 2020-08-18 16:25:25 -05:00
Trevor Payne
702c186c2c Fixed Gitignore 2020-08-18 16:24:32 -05:00
Andrew Welker
22ce57e628 add packages folder to .gitignore 2020-08-18 15:04:35 -06:00
Andrew Welker
10f1f5b1d6 update version for PepperDashCore to match the correct version 2020-08-18 14:57:05 -06:00
Trevor Payne
182499a79b Merge branch 'development' into bugfix/ScreenSaver-Never-Starts 2020-08-18 15:35:18 -05:00
Trevor Payne
6e148e7d62 Resolves #378
Fixed improperly set up device extender
2020-08-18 15:30:58 -05:00
Andrew Welker
6a31504cf8 Merge branch 'development' into bugfix/SystemMonitor-IndexOutOfRange 2020-08-18 15:42:56 -04:00
Andrew Welker
a6bb35a20d Merge pull request #375 from PepperDash/feature/test-build-image-revert-373
Revert "Update docker build image to use Crestron DB 200.00.004.00 & …
2020-08-18 15:42:43 -04:00
Andrew Welker
b53282e3e0 Merge pull request #376 from PepperDash/feature/test-build-image
Update docker build image to use Crestron DB 200.00.004.00 & Device DB 200.00.015.00
2020-08-18 15:42:28 -04:00
Andrew Welker
d6fd9517f0 Revert "Update docker build image to use Crestron DB 200.00.004.00 & Device DB 200.00.015.00" 2020-08-18 13:06:18 -06:00
Trevor Payne
bbcd3598b2 Merge pull request #373 from PepperDash/feature/test-build-image
Update docker build image to use Crestron DB 200.00.004.00 & Device DB 200.00.015.00
2020-08-18 14:04:33 -05:00
Andrew Welker
4ad966d909 back to main image 2020-08-18 12:20:31 -06:00
Andrew Welker
f61db7f7bf testing dev image 2020-08-18 11:05:48 -06:00
Trevor Payne
95fb6cc204 Merge branch 'development' into bugfix/SystemMonitor-IndexOutOfRange 2020-08-18 11:38:27 -05:00
Andrew Welker
5668653785 Merge pull request #370 from PepperDash/feature/cisco-external-sources
Feature/cisco external sources
2020-08-18 12:34:38 -04:00
Trevor Payne
3325d81cab Merge branch 'development' into bugfix/SystemMonitor-IndexOutOfRange 2020-08-18 10:55:07 -05:00
Trevor Payne
78f9142b35 Resolves #368
Changed parsing routine to no longer use absolute indicies for 'ParseUptime'
2020-08-18 10:40:20 -05:00
Trevor Payne
f18ed56909 Merge branch 'bugfix/SystemMonitor-IndexOutOfRange' of https://github.com/PepperDash/Essentials into bugfix/SystemMonitor-IndexOutOfRange 2020-08-18 10:19:29 -05:00
Trevor Payne
951da716a6 Added try/catch to ParseUptime with a way to view what was being parsed
Testing for #368
2020-08-18 10:18:49 -05:00
Trevor Payne
7ac11952eb Added try/catch to ParseUptime with a way to view what was being parsed 2020-08-18 10:17:13 -05:00
Andrew Welker
a99b6e37e4 Merge pull request #366 from PepperDash/feature/cisco-external-sources
Add External Source API to VideoCodec
2020-08-18 10:55:06 -04:00
Andrew Welker
9b567b7ead Merge branch 'development' into feature/Descriptive-CEC-genericComm-failure-message 2020-08-18 10:04:59 -04:00
Jason Alborough
67f0ae92ef Adds null check before running RunRouteAction event in Cisco Spark class.
Fixes spelling error and other minor cleanup.
2020-08-18 10:00:53 -04:00
Jason Alborough
4e2683f8fc Removes ToDo's 2020-08-17 14:57:33 -04:00
Jason Alborough
f0d10fb1f9 Finalized IHasExternalSourceSwitching adding method for setting the ExternalSource State
Adds arguments for External Source type it the AddExternalSource()
Adds subscription and parsing for External Source events
2020-08-17 14:52:49 -04:00
Jason Alborough
aea6942a1f Update to support Cisco Codec External Sources using Essentials Room logic.
Adds new interface for Codecs IHasExternalSourceSwitching
Adds ability to set and clear External Sources in Cisco Spark device class
Adds ability to send sources from the source list to the Cisco Spark in the "EssentialsHuddleVtc1Room" room
[ ] still needs parsing when source is selected on the Cisco touch 10
2020-08-14 15:51:37 -04:00
Neil Dorin
22ff61d7f3 Merge pull request #361 from PepperDash/feature/add-qr-code-on-tsw-panels
Add Mobile Control QR code to TSW Panels for Essentials Standalone
2020-08-07 09:56:55 -06:00
Neil Dorin
f066321f3a Merge branch 'main' into feature/add-qr-code-on-tsw-panels 2020-08-07 09:41:47 -06:00
Neil Dorin
302603aa54 Updates to phone and video address logic 2020-08-07 09:29:55 -06:00
Neil Dorin
dea858e187 Updates to phone and video address logic 2020-08-07 09:11:31 -06:00
Neil Dorin
ddbee2ed04 Fixed incorrect join for dark background logo. Updates CodecInfo class to correclty poppulate values 2020-08-07 08:56:29 -06:00
Neil Dorin
b7c9677c7a Updates to finesse screen saver and get phone/video number display working correclty 2020-08-06 22:04:07 -06:00
Neil Dorin
d6581cab2e Updates to work out kinks 2020-08-06 21:16:03 -06:00
Neil Dorin
66c481e3dc Seems to work except dynamic graphics for logos and QR code 2020-08-06 19:46:12 -06:00
Neil Dorin
edd01785d5 Adds ability to get URL for both light and dark logo options 2020-08-06 18:07:23 -06:00
Neil Dorin
192aa4255c Adds ability for dark logo option 2020-08-06 15:20:24 -06:00
Neil Dorin
637ca2f312 removes parent from interfaces 2020-08-06 15:04:02 -06:00
Neil Dorin
bf7a0600f3 specified previous docker build version 2020-08-06 14:42:45 -06:00
Neil Dorin
f59654d75e working on #109 to add QR support for TSW panels 2020-08-06 13:56:42 -06:00
Andrew Welker
211665c0c4 Merge pull request #358 from PepperDash/release/1.6.0
Release/1.6.0
2020-08-06 09:21:00 -04:00
Trevor Payne
c77fe5c454 Add more desciptive error messages when creating a CEC genericComm device
Resolves #355
2020-08-05 13:59:48 -05:00
38 changed files with 2755 additions and 1480 deletions

View File

@@ -10,7 +10,7 @@ Get-ChildItem ($destination)
$exclusions = @(git submodule foreach --quiet 'echo $name')
# 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", "*.dll" | ForEach-Object {
Get-ChildItem -recurse -Path "$($Env:GITHUB_WORKSPACE)" -include "*.clz", "*.cpz", "*.cplz", "*.dll", "*.nuspec" | ForEach-Object {
$allowed = $true;
# Exclude any files in submodules
foreach ($exclude in $exclusions) {

View File

@@ -48,6 +48,8 @@ jobs:
run: |
Write-Output ${{ env.VERSION }}
./.github/scripts/UpdateAssemblyVersion.ps1 ${{ env.VERSION }}
- name: restore Nuget Packages
run: nuget install .\packages.config -OutputDirectory .\packages -ExcludeVersion
# Login to Docker
- name: Login to Docker
uses: azure/docker-login@v1
@@ -58,7 +60,7 @@ jobs:
- 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_FILE).sln"" -BuildSolutionConfiguration $($ENV:BUILD_TYPE)"
Invoke-Expression "docker run --rm --mount type=bind,source=""$($Env:GITHUB_WORKSPACE)"",target=""c:/project"" pepperdash/sspbuilder:v1.4.1 c:\cihelpers\vsidebuild.exe -Solution ""c:\project\$($Env:SOLUTION_FILE).sln"" -BuildSolutionConfiguration $($ENV:BUILD_TYPE)"
# Zip up the output files as needed
- name: Zip Build Output
shell: powershell
@@ -107,6 +109,49 @@ jobs:
asset_content_type: application/zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Push_Nuget_Package:
needs: Build_Project
runs-on: windows-latest
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"
Write-Output "::set-env name=VERSION::$version"
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: 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 }}
- name: Add nuget.org API Key
run: nuget setApiKey ${{ secrets.NUGET_API_KEY }}
- name: Create nuget package
run: nuget pack "./PepperDash_Essentials_Core.nuspec" -version ${{ env.VERSION }}
- name: Publish nuget package to Github registry
run: nuget push **/*.nupkg -source github
- name: Publish nuget package to nuget.org
run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json
# This step always runs and pushes the build to the internal build rep
Internal_Push_Output:
needs: Build_Project

View File

@@ -44,6 +44,8 @@ jobs:
run: |
Write-Output ${{ env.VERSION }}
./.github/scripts/UpdateAssemblyVersion.ps1 ${{ env.VERSION }}
- name: restore Nuget Packages
run: nuget install .\packages.config -OutputDirectory .\packages -ExcludeVersion
# Login to Docker
- name: Login to Docker
uses: azure/docker-login@v1
@@ -85,6 +87,49 @@ jobs:
asset_content_type: application/zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Push_Nuget_Package:
needs: Build_Project
runs-on: windows-latest
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"
Write-Output "::set-env name=VERSION::$version"
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: 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 }}
- name: Add nuget.org API Key
run: nuget setApiKey ${{ secrets.NUGET_API_KEY }}
- name: Create nuget package
run: nuget pack "./PepperDash_Essentials_Core.nuspec" -version ${{ env.VERSION }}
- name: Publish nuget package to Github registry
run: nuget push **/*.nupkg -source github
- name: Publish nuget package to nuget.org
run: nuget push **/*.nupkg -Source https://api.nuget.org/v3/index.json
Internal_Push_Output:
needs: Build_Project
runs-on: windows-latest

363
.gitignore vendored
View File

@@ -23,5 +23,368 @@ SIMPLSharpLogs/
*.projectinfo
essentials-framework/EssentialDMTestConfig/
output/
packages/
PepperDashEssentials-0.0.0-buildType-test.zip
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd

View File

@@ -91,6 +91,9 @@ namespace PepperDash.Essentials
}, "portalinfo", "Shows portal URLS from configuration", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(DeviceManager.GetRoutingPorts,
"getroutingports", "Reports all routing ports, if any. Requires a device key", ConsoleAccessLevelEnum.AccessOperator);
if (!Debug.DoNotLoadOnNextBoot)
{
GoWithLoad();
@@ -440,7 +443,7 @@ namespace PepperDash.Essentials
{
if (ConfigReader.ConfigObject.Rooms == null)
{
Debug.Console(0, Debug.ErrorLogLevel.Warning, "WARNING: Configuration contains no rooms");
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Notice: Configuration contains no rooms - Is this intentional? This may be a valid configuration.");
return;
}
@@ -488,7 +491,7 @@ namespace PepperDash.Essentials
}
else
Debug.Console(0, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create room from config, key '{0}'", roomConfig.Key);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Notice: Cannot create room from config, key '{0}' - Is this intentional? This may be a valid configuration.", roomConfig.Key);
}
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Rooms Loaded.");

View File

@@ -2,340 +2,340 @@
using System.Linq;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.Fusion;
using Crestron.SimplSharpPro.Fusion;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Fusion;
namespace PepperDash.Essentials.Fusion
{
public class EssentialsHuddleVtc1FusionController : EssentialsHuddleSpaceFusionSystemControllerBase
{
BooleanSigData CodecIsInCall;
public EssentialsHuddleVtc1FusionController(EssentialsHuddleVtc1Room room, uint ipId)
: base(room, ipId)
{
}
/// <summary>
/// Called in base class constructor before RVI and GUID files are built
/// </summary>
protected override void ExecuteCustomSteps()
{
SetUpCodec();
}
/// <summary>
/// Creates a static asset for the codec and maps the joins to the main room symbol
/// </summary>
void SetUpCodec()
{
try
{
var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec;
if (codec == null)
{
Debug.Console(1, this, "Cannot link codec to Fusion because codec is null");
return;
}
codec.UsageTracker = new UsageTracking(codec);
codec.UsageTracker.UsageIsTracked = true;
codec.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
var codecPowerOnAction = new Action<bool>(b => { if (!b) codec.StandbyDeactivate(); });
var codecPowerOffAction = new Action<bool>(b => { if (!b) codec.StandbyActivate(); });
// Map FusionRoom Attributes:
// Codec volume
var codecVolume = FusionRoom.CreateOffsetUshortSig(50, "Volume - Fader01", eSigIoMask.InputOutputSig);
codecVolume.OutputSig.UserObject = new Action<ushort>(b => (codec as IBasicVolumeWithFeedback).SetVolume(b));
(codec as IBasicVolumeWithFeedback).VolumeLevelFeedback.LinkInputSig(codecVolume.InputSig);
// In Call Status
CodecIsInCall = FusionRoom.CreateOffsetBoolSig(69, "Conf - VC 1 In Call", eSigIoMask.InputSigOnly);
codec.CallStatusChange += new EventHandler<PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
// Online status
if (codec is ICommunicationMonitor)
{
var c = codec as ICommunicationMonitor;
var codecOnline = FusionRoom.CreateOffsetBoolSig(122, "Online - VC 1", eSigIoMask.InputSigOnly);
codecOnline.InputSig.BoolValue = c.CommunicationMonitor.Status == MonitorStatus.IsOk;
c.CommunicationMonitor.StatusChange += (o, a) =>
{
codecOnline.InputSig.BoolValue = a.Status == MonitorStatus.IsOk;
};
Debug.Console(0, this, "Linking '{0}' communication monitor to Fusion '{1}'", codec.Key, "Online - VC 1");
}
// Codec IP Address
bool codecHasIpInfo = false;
var codecComm = codec.Communication;
string codecIpAddress = string.Empty;
int codecIpPort = 0;
StringSigData codecIpAddressSig;
StringSigData codecIpPortSig;
if(codecComm is GenericSshClient)
{
codecIpAddress = (codecComm as GenericSshClient).Hostname;
codecIpPort = (codecComm as GenericSshClient).Port;
codecHasIpInfo = true;
}
else if (codecComm is GenericTcpIpClient)
{
codecIpAddress = (codecComm as GenericTcpIpClient).Hostname;
codecIpPort = (codecComm as GenericTcpIpClient).Port;
codecHasIpInfo = true;
}
if (codecHasIpInfo)
{
codecIpAddressSig = FusionRoom.CreateOffsetStringSig(121, "IP Address - VC", eSigIoMask.InputSigOnly);
codecIpAddressSig.InputSig.StringValue = codecIpAddress;
codecIpPortSig = FusionRoom.CreateOffsetStringSig(150, "IP Port - VC", eSigIoMask.InputSigOnly);
codecIpPortSig.InputSig.StringValue = codecIpPort.ToString();
}
var tempAsset = new FusionAsset();
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(c => c.Key.Equals(codec.Key));
if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
{
tempAsset = FusionStaticAssets[deviceConfig.Uid];
}
else
{
// Create a new asset
tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), codec.Name, "Codec", "");
FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
}
var codecAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
codecAsset.PowerOn.OutputSig.UserObject = codecPowerOnAction;
codecAsset.PowerOff.OutputSig.UserObject = codecPowerOffAction;
codec.StandbyIsOnFeedback.LinkComplementInputSig(codecAsset.PowerOn.InputSig);
// TODO: Map relevant attributes on asset symbol
codecAsset.TrySetMakeModel(codec);
codecAsset.TryLinkAssetErrorToCommunication(codec);
}
catch (Exception e)
{
Debug.Console(1, this, "Error setting up codec in Fusion: {0}", e);
}
}
void codec_CallStatusChange(object sender, PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs e)
{
var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec;
CodecIsInCall.InputSig.BoolValue = codec.IsInCall;
}
// These methods are overridden because they access the room class which is of a different type
protected override void CreateSymbolAndBasicSigs(uint ipId)
{
Debug.Console(1, this, "Creating Fusion Room symbol with GUID: {0}", RoomGuid);
FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();
FusionRoom.ExtenderFusionRoomDataReservedSigs.Use();
FusionRoom.Register();
FusionRoom.FusionStateChange += FusionRoom_FusionStateChange;
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.DeviceExtenderSigChange += FusionRoomSchedule_DeviceExtenderSigChange;
FusionRoom.ExtenderFusionRoomDataReservedSigs.DeviceExtenderSigChange += ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange;
FusionRoom.OnlineStatusChange += FusionRoom_OnlineStatusChange;
CrestronConsole.AddNewConsoleCommand(RequestFullRoomSchedule, "FusReqRoomSchedule", "Requests schedule of the room for the next 24 hours", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(ModifyMeetingEndTimeConsoleHelper, "FusReqRoomSchMod", "Ends or extends a meeting by the specified time", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(CreateAsHocMeeting, "FusCreateMeeting", "Creates and Ad Hoc meeting for on hour or until the next meeting", ConsoleAccessLevelEnum.AccessOperator);
// Room to fusion room
Room.OnFeedback.LinkInputSig(FusionRoom.SystemPowerOn.InputSig);
// Moved to
CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(84, "Display 1 - Current Source", eSigIoMask.InputSigOnly);
// Don't think we need to get current status of this as nothing should be alive yet.
(Room as EssentialsHuddleVtc1Room).CurrentSourceChange += Room_CurrentSourceInfoChange;
FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction((Room as EssentialsHuddleVtc1Room).PowerOnToDefaultOrLastSource);
FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff", Room.SourceListKey));
// NO!! room.RoomIsOn.LinkComplementInputSig(FusionRoom.SystemPowerOff.InputSig);
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
}
protected override void SetUpSources()
{
// Sources
var dict = ConfigReader.ConfigObject.GetSourceListForKey((Room as EssentialsHuddleVtc1Room).SourceListKey);
if (dict != null)
{
// NEW PROCESS:
// Make these lists and insert the fusion attributes by iterating these
var setTopBoxes = dict.Where(d => d.Value.SourceDevice is ISetTopBoxControls);
uint i = 1;
foreach (var kvp in setTopBoxes)
{
TryAddRouteActionSigs("Display 1 - Source TV " + i, 188 + i, kvp.Key, kvp.Value.SourceDevice);
i++;
if (i > 5) // We only have five spots
break;
}
var discPlayers = dict.Where(d => d.Value.SourceDevice is IDiscPlayerControls);
i = 1;
foreach (var kvp in discPlayers)
{
TryAddRouteActionSigs("Display 1 - Source DVD " + i, 181 + i, kvp.Key, kvp.Value.SourceDevice);
i++;
if (i > 5) // We only have five spots
break;
}
var laptops = dict.Where(d => d.Value.SourceDevice is Core.Devices.Laptop);
i = 1;
foreach (var kvp in laptops)
{
TryAddRouteActionSigs("Display 1 - Source Laptop " + i, 166 + i, kvp.Key, kvp.Value.SourceDevice);
i++;
if (i > 10) // We only have ten spots???
break;
}
foreach (var kvp in dict)
{
var usageDevice = kvp.Value.SourceDevice as IUsageTracking;
if (usageDevice != null)
{
usageDevice.UsageTracker = new UsageTracking(usageDevice as Device);
usageDevice.UsageTracker.UsageIsTracked = true;
usageDevice.UsageTracker.DeviceUsageEnded += new EventHandler<DeviceUsageEventArgs>(UsageTracker_DeviceUsageEnded);
}
}
}
else
{
Debug.Console(1, this, "WARNING: Config source list '{0}' not found for room '{1}'",
(Room as EssentialsHuddleVtc1Room).SourceListKey, Room.Key);
}
}
protected override void SetUpDisplay()
{
try
{
//Setup Display Usage Monitoring
var displays = DeviceManager.AllDevices.Where(d => d is DisplayBase);
// Consider updating this in multiple display systems
foreach (DisplayBase display in displays)
{
display.UsageTracker = new UsageTracking(display);
display.UsageTracker.UsageIsTracked = true;
display.UsageTracker.DeviceUsageEnded += new EventHandler<DeviceUsageEventArgs>(UsageTracker_DeviceUsageEnded);
}
var defaultDisplay = (Room as EssentialsHuddleVtc1Room).DefaultDisplay as DisplayBase;
if (defaultDisplay == null)
{
Debug.Console(1, this, "Cannot link null display to Fusion because default display is null");
return;
}
var dispPowerOnAction = new Action<bool>(b => { if (!b) defaultDisplay.PowerOn(); });
var dispPowerOffAction = new Action<bool>(b => { if (!b) defaultDisplay.PowerOff(); });
// Display to fusion room sigs
FusionRoom.DisplayPowerOn.OutputSig.UserObject = dispPowerOnAction;
FusionRoom.DisplayPowerOff.OutputSig.UserObject = dispPowerOffAction;
defaultDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
if (defaultDisplay is IDisplayUsage)
(defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
MapDisplayToRoomJoins(1, 158, defaultDisplay);
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key));
//Check for existing asset in GUIDs collection
var tempAsset = new FusionAsset();
if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
{
tempAsset = FusionStaticAssets[deviceConfig.Uid];
}
else
{
// Create a new asset
tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), defaultDisplay.Name, "Display", "");
FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
}
var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
defaultDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
// NO!! display.PowerIsOn.LinkComplementInputSig(dispAsset.PowerOff.InputSig);
// Use extension methods
dispAsset.TrySetMakeModel(defaultDisplay);
dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay);
}
catch (Exception e)
{
Debug.Console(1, this, "Error setting up display in Fusion: {0}", e);
}
}
protected override void MapDisplayToRoomJoins(int displayIndex, int joinOffset, DisplayBase display)
{
string displayName = string.Format("Display {0} - ", displayIndex);
if (display == (Room as EssentialsHuddleVtc1Room).DefaultDisplay)
{
// Power on
var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig);
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b => { if (!b) display.PowerOn(); });
display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
// Power Off
var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off", eSigIoMask.InputOutputSig);
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b => { if (!b) display.PowerOff(); }); ;
display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
// Current Source
var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig);
defaultDisplaySourceNone.OutputSig.UserObject = new Action<bool>(b => { if (!b) (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff", Room.SourceListKey); }); ;
}
}
}
namespace PepperDash.Essentials.Fusion
{
public class EssentialsHuddleVtc1FusionController : EssentialsHuddleSpaceFusionSystemControllerBase
{
BooleanSigData CodecIsInCall;
public EssentialsHuddleVtc1FusionController(EssentialsHuddleVtc1Room room, uint ipId)
: base(room, ipId)
{
}
/// <summary>
/// Called in base class constructor before RVI and GUID files are built
/// </summary>
protected override void ExecuteCustomSteps()
{
SetUpCodec();
}
/// <summary>
/// Creates a static asset for the codec and maps the joins to the main room symbol
/// </summary>
void SetUpCodec()
{
try
{
var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec;
if (codec == null)
{
Debug.Console(1, this, "Cannot link codec to Fusion because codec is null");
return;
}
codec.UsageTracker = new UsageTracking(codec);
codec.UsageTracker.UsageIsTracked = true;
codec.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
var codecPowerOnAction = new Action<bool>(b => { if (!b) codec.StandbyDeactivate(); });
var codecPowerOffAction = new Action<bool>(b => { if (!b) codec.StandbyActivate(); });
// Map FusionRoom Attributes:
// Codec volume
var codecVolume = FusionRoom.CreateOffsetUshortSig(50, "Volume - Fader01", eSigIoMask.InputOutputSig);
codecVolume.OutputSig.UserObject = new Action<ushort>(b => (codec as IBasicVolumeWithFeedback).SetVolume(b));
(codec as IBasicVolumeWithFeedback).VolumeLevelFeedback.LinkInputSig(codecVolume.InputSig);
// In Call Status
CodecIsInCall = FusionRoom.CreateOffsetBoolSig(69, "Conf - VC 1 In Call", eSigIoMask.InputSigOnly);
codec.CallStatusChange += new EventHandler<PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
// Online status
if (codec is ICommunicationMonitor)
{
var c = codec as ICommunicationMonitor;
var codecOnline = FusionRoom.CreateOffsetBoolSig(122, "Online - VC 1", eSigIoMask.InputSigOnly);
codecOnline.InputSig.BoolValue = c.CommunicationMonitor.Status == MonitorStatus.IsOk;
c.CommunicationMonitor.StatusChange += (o, a) =>
{
codecOnline.InputSig.BoolValue = a.Status == MonitorStatus.IsOk;
};
Debug.Console(0, this, "Linking '{0}' communication monitor to Fusion '{1}'", codec.Key, "Online - VC 1");
}
// Codec IP Address
bool codecHasIpInfo = false;
var codecComm = codec.Communication;
string codecIpAddress = string.Empty;
int codecIpPort = 0;
StringSigData codecIpAddressSig;
StringSigData codecIpPortSig;
if(codecComm is GenericSshClient)
{
codecIpAddress = (codecComm as GenericSshClient).Hostname;
codecIpPort = (codecComm as GenericSshClient).Port;
codecHasIpInfo = true;
}
else if (codecComm is GenericTcpIpClient)
{
codecIpAddress = (codecComm as GenericTcpIpClient).Hostname;
codecIpPort = (codecComm as GenericTcpIpClient).Port;
codecHasIpInfo = true;
}
if (codecHasIpInfo)
{
codecIpAddressSig = FusionRoom.CreateOffsetStringSig(121, "IP Address - VC", eSigIoMask.InputSigOnly);
codecIpAddressSig.InputSig.StringValue = codecIpAddress;
codecIpPortSig = FusionRoom.CreateOffsetStringSig(150, "IP Port - VC", eSigIoMask.InputSigOnly);
codecIpPortSig.InputSig.StringValue = codecIpPort.ToString();
}
var tempAsset = new FusionAsset();
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(c => c.Key.Equals(codec.Key));
if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
{
tempAsset = FusionStaticAssets[deviceConfig.Uid];
}
else
{
// Create a new asset
tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), codec.Name, "Codec", "");
FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
}
var codecAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
codecAsset.PowerOn.OutputSig.UserObject = codecPowerOnAction;
codecAsset.PowerOff.OutputSig.UserObject = codecPowerOffAction;
codec.StandbyIsOnFeedback.LinkComplementInputSig(codecAsset.PowerOn.InputSig);
// TODO: Map relevant attributes on asset symbol
codecAsset.TrySetMakeModel(codec);
codecAsset.TryLinkAssetErrorToCommunication(codec);
}
catch (Exception e)
{
Debug.Console(1, this, "Error setting up codec in Fusion: {0}", e);
}
}
void codec_CallStatusChange(object sender, PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs e)
{
var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec;
CodecIsInCall.InputSig.BoolValue = codec.IsInCall;
}
// These methods are overridden because they access the room class which is of a different type
protected override void CreateSymbolAndBasicSigs(uint ipId)
{
Debug.Console(1, this, "Creating Fusion Room symbol with GUID: {0}", RoomGuid);
FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();
FusionRoom.ExtenderFusionRoomDataReservedSigs.Use();
FusionRoom.Register();
FusionRoom.FusionStateChange += FusionRoom_FusionStateChange;
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.DeviceExtenderSigChange += FusionRoomSchedule_DeviceExtenderSigChange;
FusionRoom.ExtenderFusionRoomDataReservedSigs.DeviceExtenderSigChange += ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange;
FusionRoom.OnlineStatusChange += FusionRoom_OnlineStatusChange;
CrestronConsole.AddNewConsoleCommand(RequestFullRoomSchedule, "FusReqRoomSchedule", "Requests schedule of the room for the next 24 hours", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(ModifyMeetingEndTimeConsoleHelper, "FusReqRoomSchMod", "Ends or extends a meeting by the specified time", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(CreateAsHocMeeting, "FusCreateMeeting", "Creates and Ad Hoc meeting for on hour or until the next meeting", ConsoleAccessLevelEnum.AccessOperator);
// Room to fusion room
Room.OnFeedback.LinkInputSig(FusionRoom.SystemPowerOn.InputSig);
// Moved to
CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(84, "Display 1 - Current Source", eSigIoMask.InputSigOnly);
// Don't think we need to get current status of this as nothing should be alive yet.
(Room as EssentialsHuddleVtc1Room).CurrentSourceChange += Room_CurrentSourceInfoChange;
FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction((Room as EssentialsHuddleVtc1Room).PowerOnToDefaultOrLastSource);
FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff", Room.SourceListKey));
// NO!! room.RoomIsOn.LinkComplementInputSig(FusionRoom.SystemPowerOff.InputSig);
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
}
protected override void SetUpSources()
{
// Sources
var dict = ConfigReader.ConfigObject.GetSourceListForKey((Room as EssentialsHuddleVtc1Room).SourceListKey);
if (dict != null)
{
// NEW PROCESS:
// Make these lists and insert the fusion attributes by iterating these
var setTopBoxes = dict.Where(d => d.Value.SourceDevice is ISetTopBoxControls);
uint i = 1;
foreach (var kvp in setTopBoxes)
{
TryAddRouteActionSigs("Display 1 - Source TV " + i, 188 + i, kvp.Key, kvp.Value.SourceDevice);
i++;
if (i > 5) // We only have five spots
break;
}
var discPlayers = dict.Where(d => d.Value.SourceDevice is IDiscPlayerControls);
i = 1;
foreach (var kvp in discPlayers)
{
TryAddRouteActionSigs("Display 1 - Source DVD " + i, 181 + i, kvp.Key, kvp.Value.SourceDevice);
i++;
if (i > 5) // We only have five spots
break;
}
var laptops = dict.Where(d => d.Value.SourceDevice is Core.Devices.Laptop);
i = 1;
foreach (var kvp in laptops)
{
TryAddRouteActionSigs("Display 1 - Source Laptop " + i, 166 + i, kvp.Key, kvp.Value.SourceDevice);
i++;
if (i > 10) // We only have ten spots???
break;
}
foreach (var kvp in dict)
{
var usageDevice = kvp.Value.SourceDevice as IUsageTracking;
if (usageDevice != null)
{
usageDevice.UsageTracker = new UsageTracking(usageDevice as Device);
usageDevice.UsageTracker.UsageIsTracked = true;
usageDevice.UsageTracker.DeviceUsageEnded += new EventHandler<DeviceUsageEventArgs>(UsageTracker_DeviceUsageEnded);
}
}
}
else
{
Debug.Console(1, this, "WARNING: Config source list '{0}' not found for room '{1}'",
(Room as EssentialsHuddleVtc1Room).SourceListKey, Room.Key);
}
}
protected override void SetUpDisplay()
{
try
{
//Setup Display Usage Monitoring
var displays = DeviceManager.AllDevices.Where(d => d is DisplayBase);
// Consider updating this in multiple display systems
foreach (DisplayBase display in displays)
{
display.UsageTracker = new UsageTracking(display);
display.UsageTracker.UsageIsTracked = true;
display.UsageTracker.DeviceUsageEnded += new EventHandler<DeviceUsageEventArgs>(UsageTracker_DeviceUsageEnded);
}
var defaultDisplay = (Room as EssentialsHuddleVtc1Room).DefaultDisplay as DisplayBase;
if (defaultDisplay == null)
{
Debug.Console(1, this, "Cannot link null display to Fusion because default display is null");
return;
}
var dispPowerOnAction = new Action<bool>(b => { if (!b) defaultDisplay.PowerOn(); });
var dispPowerOffAction = new Action<bool>(b => { if (!b) defaultDisplay.PowerOff(); });
// Display to fusion room sigs
FusionRoom.DisplayPowerOn.OutputSig.UserObject = dispPowerOnAction;
FusionRoom.DisplayPowerOff.OutputSig.UserObject = dispPowerOffAction;
defaultDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
if (defaultDisplay is IDisplayUsage)
(defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
MapDisplayToRoomJoins(1, 158, defaultDisplay);
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key));
//Check for existing asset in GUIDs collection
var tempAsset = new FusionAsset();
if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
{
tempAsset = FusionStaticAssets[deviceConfig.Uid];
}
else
{
// Create a new asset
tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), defaultDisplay.Name, "Display", "");
FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
}
var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
defaultDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
// NO!! display.PowerIsOn.LinkComplementInputSig(dispAsset.PowerOff.InputSig);
// Use extension methods
dispAsset.TrySetMakeModel(defaultDisplay);
dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay);
}
catch (Exception e)
{
Debug.Console(1, this, "Error setting up display in Fusion: {0}", e);
}
}
protected override void MapDisplayToRoomJoins(int displayIndex, int joinOffset, DisplayBase display)
{
string displayName = string.Format("Display {0} - ", displayIndex);
if (display == (Room as EssentialsHuddleVtc1Room).DefaultDisplay)
{
// Power on
var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig);
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b => { if (!b) display.PowerOn(); });
display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
// Power Off
var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off", eSigIoMask.InputOutputSig);
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b => { if (!b) display.PowerOff(); }); ;
display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
// Current Source
var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig);
defaultDisplaySourceNone.OutputSig.UserObject = new Action<bool>(b => { if (!b) (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff", Room.SourceListKey); }); ;
}
}
}
}

View File

@@ -71,9 +71,9 @@
<HintPath>..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="PepperDash_Core, Version=1.0.26.30384, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="PepperDash_Core, Version=1.0.41.31808, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\essentials-framework\pepperdashcore-builds\PepperDash_Core.dll</HintPath>
<HintPath>..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll</HintPath>
</Reference>
<Reference Include="PepperDash_Essentials_DM, Version=1.0.0.19343, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -155,6 +155,7 @@
<Compile Include="UIDrivers\Environment Drivers\EssentialsShadeDriver.cs" />
<Compile Include="UIDrivers\Essentials\EssentialsHeaderDriver.cs" />
<Compile Include="UIDrivers\JoinedSigInterlock.cs" />
<Compile Include="UIDrivers\ScreenSaverController.cs" />
<Compile Include="UIDrivers\SigInterlock.cs" />
<Compile Include="UIDrivers\EssentialsHuddleVTC\EssentialsHuddlePresentationUiDriver.cs" />
<Compile Include="UIDrivers\EssentialsHuddle\EssentialsHuddleTechPageDriver.cs" />

View File

@@ -156,7 +156,10 @@ namespace PepperDash.Essentials.Room.Config
public EssentialsEnvironmentPropertiesConfig Environment { get; set; }
[JsonProperty("logo")]
public EssentialsLogoPropertiesConfig Logo { get; set; }
public EssentialsLogoPropertiesConfig LogoLight { get; set; }
[JsonProperty("logoDark")]
public EssentialsLogoPropertiesConfig LogoDark { get; set; }
[JsonProperty("microphonePrivacy")]
public EssentialsRoomMicrophonePrivacyConfig MicrophonePrivacy { get; set; }
@@ -181,6 +184,12 @@ namespace PepperDash.Essentials.Room.Config
[JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")]
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; }
public EssentialsRoomPropertiesConfig()
{
LogoLight = new EssentialsLogoPropertiesConfig();
LogoDark = new EssentialsLogoPropertiesConfig();
}
}
public class EssentialsAvRoomPropertiesConfig : EssentialsRoomPropertiesConfig
@@ -280,7 +289,7 @@ namespace PepperDash.Essentials.Room.Config
/// <summary>
/// Gets either the custom URL, a local-to-processor URL, or null if it's a default logo
/// </summary>
public string GetUrl()
public string GetLogoUrlLight()
{
if (Type == "url")
return Url;
@@ -289,6 +298,16 @@ namespace PepperDash.Essentials.Room.Config
CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0));
return null;
}
public string GetLogoUrlDark()
{
if (Type == "url")
return Url;
if (Type == "system")
return string.Format("http://{0}:8080/logo-dark.png",
CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0));
return null;
}
}
/// <summary>

View File

@@ -327,7 +327,8 @@ namespace PepperDash.Essentials
this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes);
this.LogoUrl = PropertiesConfig.Logo.GetUrl();
this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight();
this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark();
this.SourceListKey = PropertiesConfig.SourceListKey;
this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);

View File

@@ -250,7 +250,8 @@ namespace PepperDash.Essentials
this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes);
this.LogoUrl = PropertiesConfig.Logo.GetUrl();
this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight();
this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark();
this.SourceListKey = PropertiesConfig.SourceListKey;
this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);

View File

@@ -50,6 +50,19 @@ namespace PepperDash.Essentials
//************************
public override string SourceListKey
{
get
{
return _SourceListKey;
}
set
{
_SourceListKey = value;
SetCodecExternalSources();
}
}
protected override Func<bool> OnFeedbackFunc
{
@@ -206,9 +219,11 @@ namespace PepperDash.Essentials
VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as
PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;
if (VideoCodec == null)
throw new ArgumentNullException("codec cannot be null");
AudioCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.AudioCodecKey) as
PepperDash.Essentials.Devices.Common.AudioCodec.AudioCodecBase;
if (AudioCodec == null)
@@ -298,6 +313,7 @@ namespace PepperDash.Essentials
VideoCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate();
VideoCodec.IsReadyChange += (o, a) => this.SetCodecExternalSources();
if (AudioCodec != null)
AudioCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate();
@@ -340,15 +356,16 @@ namespace PepperDash.Essentials
IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes);
}
this.LogoUrl = PropertiesConfig.Logo.GetUrl();
this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight();
this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark();
this.SourceListKey = PropertiesConfig.SourceListKey;
this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);
return base.CustomActivate();
}
/// <summary>
///
/// </summary>
@@ -670,6 +687,42 @@ namespace PepperDash.Essentials
(room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
}
/// <summary>
/// Setup the external sources for the Cisco Touch 10 devices that support IHasExternalSourceSwitch
/// </summary>
private void SetCodecExternalSources()
{
var videoCodecWithExternalSwitching = VideoCodec as IHasExternalSourceSwitching;
if (videoCodecWithExternalSwitching == null)
{
return;
}
else
{
string codecTieLine = "";
codecTieLine = ConfigReader.ConfigObject.TieLines.SingleOrDefault(x => x.DestinationKey == VideoCodec.Key).DestinationPort;
videoCodecWithExternalSwitching.ClearExternalSources();
videoCodecWithExternalSwitching.RunRouteAction = RunRouteAction;
var srcList = ConfigReader.ConfigObject.SourceLists.SingleOrDefault(x => x.Key == SourceListKey).Value.OrderBy(kv => kv.Value.Order); ;
foreach (var kvp in srcList)
{
var srcConfig = kvp.Value;
if (kvp.Key != DefaultCodecRouteString && kvp.Key != "roomOff")
{
videoCodecWithExternalSwitching.AddExternalSource(codecTieLine, kvp.Key, srcConfig.PreferredName, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceType.desktop);
videoCodecWithExternalSwitching.SetExternalSourceState(kvp.Key, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceMode.Ready);
}
}
}
}
#region IPrivacy Members

View File

@@ -224,6 +224,8 @@ namespace PepperDash.Essentials
var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey);
if (room is EssentialsHuddleSpaceRoom)
{
// Screen Saver Driver
mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, props);
// Header Driver
Debug.Console(0, panelController, "Adding header driver");
@@ -272,6 +274,9 @@ namespace PepperDash.Essentials
{
Debug.Console(0, panelController, "Adding huddle space VTC AV driver");
// Screen Saver Driver
mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, props);
// Header Driver
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, props);

File diff suppressed because it is too large Load Diff

View File

@@ -146,6 +146,10 @@ namespace PepperDash.Essentials
/// </summary>
public const uint RoomPhoneText = 3904;
/// <summary>
/// 3905 - Video address/number for room header
/// </summary>
public const uint RoomVideoAddressText = 3905;
/// <summary>
/// 3906 - The separator for verbose-header text on addresses
/// </summary>
public const uint RoomAddressPipeText = 3906;
@@ -154,6 +158,14 @@ namespace PepperDash.Essentials
/// </summary>
public const uint RoomUserCode = 3907;
/// <summary>
/// 3908 - The url for the mobile control server
/// </summary>
public const uint RoomMcUrl = 3908;
/// <summary>
/// 3909 - The url for the mobile control QR Code image
/// </summary>
public const uint RoomMcQrCodeUrl = 3909;
/// <summary>
/// 3911
/// </summary>
public const uint PowerOffMessage = 3911;
@@ -189,12 +201,19 @@ namespace PepperDash.Essentials
/// <summary>
/// 3923
/// </summary>
public const uint LogoUrl = 3923;
public const uint LogoUrlLightBkgnd = 3923;
/// <summary>
/// 3924 - the text on the "call help desk" button
/// </summary>
public const uint HelpPageCallButtonText = 3924;
/// <summary>
/// 3925
/// </summary>
public const uint LogoUrlDarkBkgnd = 3925;
/// <summary>
/// 3951
/// </summary>

View File

@@ -1,4 +1,5 @@
using System;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.UI;
using PepperDash.Essentials.Core;
@@ -11,6 +12,8 @@ namespace PepperDash.Essentials
/// </summary>
public class EssentialsPanelMainInterfaceDriver : PanelDriverBase
{
CTimer InactivityTimer;
/// <summary>
/// Assign the appropriate A/V driver.
/// Want to keep the AvDriver alive, because it may hold states
@@ -23,6 +26,10 @@ namespace PepperDash.Essentials
public PanelDriverBase CurrentChildDriver { get; private set; }
public ScreenSaverController ScreenSaverController { get; set; }
private readonly long _timeoutMs;
CrestronTouchpanelPropertiesConfig Config;
/// <summary>
@@ -35,18 +42,72 @@ namespace PepperDash.Essentials
: base(trilist)
{
Config = config;
_timeoutMs = Config.ScreenSaverTimeoutMin * 60 * 1000;
var tsx52or60 = trilist as Tswx52ButtonVoiceControl;
if (tsx52or60 != null)
{
tsx52or60.ExtenderTouchDetectionReservedSigs.Use();
tsx52or60.ExtenderTouchDetectionReservedSigs.DeviceExtenderSigChange += ExtenderTouchDetectionReservedSigs_DeviceExtenderSigChange;
tsx52or60.ExtenderTouchDetectionReservedSigs.Time.UShortValue = 1;
ManageInactivityTimer();
}
else
{
var tswx70 = trilist as TswX70Base;
if (tswx70 != null)
{
tswx70.ExtenderTouchDetectionReservedSigs.Use();
tswx70.ExtenderTouchDetectionReservedSigs.DeviceExtenderSigChange += ExtenderTouchDetectionReservedSigs_DeviceExtenderSigChange;
tswx70.ExtenderTouchDetectionReservedSigs.Time.UShortValue = 1;
ManageInactivityTimer();
}
}
}
void ExtenderTouchDetectionReservedSigs_DeviceExtenderSigChange(Crestron.SimplSharpPro.DeviceExtender currentDeviceExtender, Crestron.SimplSharpPro.SigEventArgs args)
{
if (args.Sig.BoolValue)
{
ManageInactivityTimer();
}
}
private void ManageInactivityTimer()
{
if (InactivityTimer != null)
{
InactivityTimer.Reset(_timeoutMs);
}
else
{
InactivityTimer = new CTimer((o) => InactivityTimerExpired(), _timeoutMs);
}
}
void InactivityTimerExpired()
{
InactivityTimer.Stop();
InactivityTimer.Dispose();
InactivityTimer = null;
ScreenSaverController.Show();
}
public override void Show()
{
CurrentChildDriver = null;
ShowSubDriver(AvDriver as PanelDriverBase);
base.Show();
base.Show();
}
public override void Hide()
{
TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = false;
TriList.BooleanInput[AvDriver.StartPageVisibleJoin].BoolValue = false;
base.Hide();
}

View File

@@ -267,7 +267,7 @@
// HideAndClearCurrentDisplayModeSigsInUse();
// tl[UIBoolJoin.TopBarHabaneroVisible].BoolValue = false;
// tl[UIBoolJoin.ActivityFooterVisible].BoolValue = false;
// tl[UIBoolJoin.StartPageVisible].BoolValue = false;
// tl[StartPageVisibleJoin].BoolValue = false;
// tl[UIBoolJoin.TapToBeginVisible].BoolValue = false;
// tl[UIBoolJoin.ToggleSharingModeVisible].BoolValue = false;
// tl[UIBoolJoin.SourceStagingBarVisible].BoolValue = false;
@@ -335,7 +335,7 @@
// }
// else
// {
// TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = true;
// TriList.BooleanInput[StartPageVisibleJoin].BoolValue = true;
// TriList.BooleanInput[UIBoolJoin.TapToBeginVisible].BoolValue = true;
// TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
// }
@@ -525,7 +525,7 @@
// if (!_CurrentRoom.OnFeedback.BoolValue)
// {
// ShareButtonSig.BoolValue = true;
// TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = false;
// TriList.BooleanInput[StartPageVisibleJoin].BoolValue = false;
// ShowCurrentSharingMode();
// }
// }
@@ -953,13 +953,13 @@
// if (value)
// {
// SetupActivityFooterWhenRoomOn();
// TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = false;
// TriList.BooleanInput[StartPageVisibleJoin].BoolValue = false;
// }
// else
// {
// HideCurrentSharingMode();
// SetupActivityFooterWhenRoomOff();
// TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = true;
// TriList.BooleanInput[StartPageVisibleJoin].BoolValue = true;
// if (LastSelectedSourceSig != null)
// {
// LastSelectedSourceSig.BoolValue = false;

View File

@@ -24,6 +24,9 @@ namespace PepperDash.Essentials
PresentationMode, AudioSetup
}
public uint StartPageVisibleJoin { get; private set; }
/// <summary>
/// Whether volume ramping from this panel will show the volume
/// gauge popup.
@@ -209,6 +212,7 @@ namespace PepperDash.Essentials
"Tap Share to begin";
}
/// <summary>
///
/// </summary>
@@ -225,20 +229,34 @@ namespace PepperDash.Essentials
if (Config.HeaderStyle.ToLower() == CrestronTouchpanelPropertiesConfig.Habanero)
{
TriList.SetSigFalseAction(UIBoolJoin.HeaderRoomButtonPress, () =>
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderPageVisible));
{
if (CurrentRoom.IsMobileControlEnabled)
{
Debug.Console(1, "Showing Mobile Control Header Info");
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderInfoMCPageVisible);
}
else
{
Debug.Console(1, "Showing Non Mobile Control Header Info");
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderInfoPageVisible);
}
});
}
else if (Config.HeaderStyle.ToLower() == CrestronTouchpanelPropertiesConfig.Verbose)
{
// room name on join 1, concat phone and sip on join 2, no button method
//var addr = roomConf.Addresses;
//if (addr == null) // protect from missing values by using default empties
// addr = new EssentialsRoomAddressPropertiesConfig();
//// empty string when either missing, pipe when both showing
//TriList.SetString(UIStringJoin.RoomAddressPipeText,
// (string.IsNullOrEmpty(addr.PhoneNumber.Trim())
// || string.IsNullOrEmpty(addr.SipAddress.Trim())) ? "" : " | ");
//TriList.SetString(UIStringJoin.RoomPhoneText, addr.PhoneNumber);
//TriList.SetString(UIStringJoin.RoomSipText, addr.SipAddress);
TriList.SetSigFalseAction(UIBoolJoin.HeaderRoomButtonPress, () =>
{
if (CurrentRoom.IsMobileControlEnabled)
{
Debug.Console(1, "Showing Mobile Control Header Info");
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderInfoMCPageVisible);
}
else
{
Debug.Console(1, "Showing Non Mobile Control Header Info");
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderInfoPageVisible);
}
});
}
TriList.SetBool(UIBoolJoin.DateAndTimeVisible, Config.ShowDate && Config.ShowTime);
@@ -256,7 +274,7 @@ namespace PepperDash.Essentials
}
else
{
TriList.SetBool(UIBoolJoin.StartPageVisible, true);
TriList.SetBool(StartPageVisibleJoin, true);
TriList.SetBool(UIBoolJoin.TapToBeginVisible, true);
SetupActivityFooterWhenRoomOff();
}
@@ -321,7 +339,7 @@ namespace PepperDash.Essentials
/// </summary>
void ShowLogo()
{
if (CurrentRoom.LogoUrl == null)
if (CurrentRoom.LogoUrlLightBkgnd == null)
{
TriList.SetBool(UIBoolJoin.LogoDefaultVisible, true);
TriList.SetBool(UIBoolJoin.LogoUrlVisible, false);
@@ -330,7 +348,8 @@ namespace PepperDash.Essentials
{
TriList.SetBool(UIBoolJoin.LogoDefaultVisible, false);
TriList.SetBool(UIBoolJoin.LogoUrlVisible, true);
TriList.SetString(UIStringJoin.LogoUrl, _CurrentRoom.LogoUrl);
TriList.SetString(UIStringJoin.LogoUrlLightBkgnd, _CurrentRoom.LogoUrlLightBkgnd);
TriList.SetString(UIStringJoin.LogoUrlDarkBkgnd, _CurrentRoom.LogoUrlDarkBkgnd);
}
}
@@ -351,7 +370,7 @@ namespace PepperDash.Essentials
HideAndClearCurrentDisplayModeSigsInUse();
TriList.BooleanInput[UIBoolJoin.TopBarHabaneroDynamicVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.ActivityFooterVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = false;
TriList.BooleanInput[StartPageVisibleJoin].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.TapToBeginVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
//TriList.BooleanInput[UIBoolJoin.StagingPageVisible].BoolValue = false;
@@ -416,7 +435,7 @@ namespace PepperDash.Essentials
}
else
{
TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = true;
TriList.BooleanInput[StartPageVisibleJoin].BoolValue = true;
TriList.BooleanInput[UIBoolJoin.TapToBeginVisible].BoolValue = true;
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
}
@@ -474,7 +493,7 @@ namespace PepperDash.Essentials
void ShareButtonPressed()
{
ShareButtonSig.BoolValue = true;
TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = false;
TriList.BooleanInput[StartPageVisibleJoin].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue = true;
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = true;
// Run default source when room is off and share is pressed
@@ -778,7 +797,7 @@ namespace PepperDash.Essentials
}
// Name and logo
TriList.StringInput[UIStringJoin.CurrentRoomName].StringValue = _CurrentRoom.Name;
if (_CurrentRoom.LogoUrl == null)
if (_CurrentRoom.LogoUrlLightBkgnd == null)
{
TriList.BooleanInput[UIBoolJoin.LogoDefaultVisible].BoolValue = true;
TriList.BooleanInput[UIBoolJoin.LogoUrlVisible].BoolValue = false;
@@ -787,7 +806,9 @@ namespace PepperDash.Essentials
{
TriList.BooleanInput[UIBoolJoin.LogoDefaultVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.LogoUrlVisible].BoolValue = true;
TriList.StringInput[UIStringJoin.LogoUrl].StringValue = _CurrentRoom.LogoUrl;
TriList.StringInput[UIStringJoin.LogoUrlLightBkgnd].StringValue = _CurrentRoom.LogoUrlLightBkgnd;
TriList.StringInput[UIStringJoin.LogoUrlLightBkgnd].StringValue = _CurrentRoom.LogoUrlDarkBkgnd;
}
// Shutdown timer
@@ -820,12 +841,43 @@ namespace PepperDash.Essentials
if (_CurrentRoom == room) return;
// Disconnect current (probably never called)
if (_CurrentRoom != null)
_CurrentRoom.ConfigChanged -= room_ConfigChanged;
room.ConfigChanged -= room_ConfigChanged;
room.ConfigChanged += room_ConfigChanged;
if (room.IsMobileControlEnabled)
{
StartPageVisibleJoin = UIBoolJoin.StartMCPageVisible;
UpdateMCJoins(room);
if (_CurrentRoom != null)
_CurrentRoom.MobileControlRoomBridge.UserCodeChanged -= MobileControlRoomBridge_UserCodeChanged;
room.MobileControlRoomBridge.UserCodeChanged -= MobileControlRoomBridge_UserCodeChanged;
room.MobileControlRoomBridge.UserCodeChanged += MobileControlRoomBridge_UserCodeChanged;
}
else
{
StartPageVisibleJoin = UIBoolJoin.StartPageVisible;
}
RefreshCurrentRoom(room);
}
void MobileControlRoomBridge_UserCodeChanged(object sender, EventArgs e)
{
UpdateMCJoins(_CurrentRoom);
}
void UpdateMCJoins(EssentialsHuddleSpaceRoom room)
{
TriList.SetString(UIStringJoin.RoomMcUrl, room.MobileControlRoomBridge.McServerUrl);
TriList.SetString(UIStringJoin.RoomMcQrCodeUrl, room.MobileControlRoomBridge.QrCodeUrl);
TriList.SetString(UIStringJoin.RoomUserCode, room.MobileControlRoomBridge.UserCode);
}
/// <summary>
/// Fires when room config of current room has changed. Meant to refresh room values to propegate any updates to UI
/// </summary>
@@ -855,7 +907,7 @@ namespace PepperDash.Essentials
SetupActivityFooterWhenRoomOn();
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue = true;
TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = false;
TriList.BooleanInput[StartPageVisibleJoin].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.VolumeSingleMute1Visible].BoolValue = true;
}
@@ -863,7 +915,7 @@ namespace PepperDash.Essentials
{
SetupActivityFooterWhenRoomOff();
ShowLogo();
TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = true;
TriList.BooleanInput[StartPageVisibleJoin].BoolValue = true;
TriList.BooleanInput[UIBoolJoin.VolumeSingleMute1Visible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue = false;
}

View File

@@ -28,6 +28,8 @@ namespace PepperDash.Essentials
Presentation, AudioSetup, Call, Start
}
public uint StartPageVisibleJoin { get; private set; }
/// <summary>
/// Whether volume ramping from this panel will show the volume
/// gauge popup.
@@ -240,20 +242,34 @@ namespace PepperDash.Essentials
if (Config.HeaderStyle.ToLower() == CrestronTouchpanelPropertiesConfig.Habanero)
{
TriList.SetSigFalseAction(UIBoolJoin.HeaderRoomButtonPress, () =>
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderPageVisible));
{
if (CurrentRoom.IsMobileControlEnabled)
{
Debug.Console(1, "Showing Mobile Control Header Info");
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderInfoMCPageVisible);
}
else
{
Debug.Console(1, "Showing Non Mobile Control Header Info");
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderInfoPageVisible);
}
});
}
else if (Config.HeaderStyle.ToLower() == CrestronTouchpanelPropertiesConfig.Verbose)
{
// room name on join 1, concat phone and sip on join 2, no button method
//var addr = roomConf.Addresses;
//if (addr == null) // protect from missing values by using default empties
// addr = new EssentialsRoomAddressPropertiesConfig();
//// empty string when either missing, pipe when both showing
//TriList.SetString(UIStringJoin.RoomAddressPipeText,
// (string.IsNullOrEmpty(addr.PhoneNumber.Trim())
// || string.IsNullOrEmpty(addr.SipAddress.Trim())) ? "" : " | ");
//TriList.SetString(UIStringJoin.RoomPhoneText, addr.PhoneNumber);
//TriList.SetString(UIStringJoin.RoomSipText, addr.SipAddress);
TriList.SetSigFalseAction(UIBoolJoin.HeaderRoomButtonPress, () =>
{
if (CurrentRoom.IsMobileControlEnabled)
{
Debug.Console(1, "Showing Mobile Control Header Info");
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderInfoMCPageVisible);
}
else
{
Debug.Console(1, "Showing Non Mobile Control Header Info");
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderInfoPageVisible);
}
});
}
TriList.SetBool(UIBoolJoin.DateAndTimeVisible, Config.ShowDate && Config.ShowTime);
@@ -276,7 +292,7 @@ namespace PepperDash.Essentials
}
else
{
TriList.SetBool(UIBoolJoin.StartPageVisible, true);
TriList.SetBool(StartPageVisibleJoin, true);
TriList.SetBool(UIBoolJoin.TapToBeginVisible, true);
SetupActivityFooterWhenRoomOff();
}
@@ -332,7 +348,7 @@ namespace PepperDash.Essentials
/// </summary>
void ShowLogo()
{
if (CurrentRoom.LogoUrl == null)
if (CurrentRoom.LogoUrlLightBkgnd == null)
{
TriList.SetBool(UIBoolJoin.LogoDefaultVisible, true);
TriList.SetBool(UIBoolJoin.LogoUrlVisible, false);
@@ -341,7 +357,8 @@ namespace PepperDash.Essentials
{
TriList.SetBool(UIBoolJoin.LogoDefaultVisible, false);
TriList.SetBool(UIBoolJoin.LogoUrlVisible, true);
TriList.SetString(UIStringJoin.LogoUrl, _CurrentRoom.LogoUrl);
TriList.SetString(UIStringJoin.LogoUrlLightBkgnd, _CurrentRoom.LogoUrlLightBkgnd);
TriList.SetString(UIStringJoin.LogoUrlDarkBkgnd, _CurrentRoom.LogoUrlDarkBkgnd);
}
}
@@ -362,7 +379,7 @@ namespace PepperDash.Essentials
HideAndClearCurrentDisplayModeSigsInUse();
TriList.SetBool(UIBoolJoin.TopBarHabaneroDynamicVisible, false);
TriList.BooleanInput[UIBoolJoin.ActivityFooterVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = false;
TriList.BooleanInput[StartPageVisibleJoin].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.TapToBeginVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
if (NextMeetingTimer != null)
@@ -606,7 +623,7 @@ namespace PepperDash.Essentials
return;
HideLogo();
HideNextMeetingPopup();
TriList.SetBool(UIBoolJoin.StartPageVisible, false);
TriList.SetBool(StartPageVisibleJoin, false);
TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, false);
TriList.SetBool(UIBoolJoin.SelectASourceVisible, false);
if (CurrentSourcePageManager != null)
@@ -626,7 +643,7 @@ namespace PepperDash.Essentials
if (VCDriver.IsVisible)
VCDriver.Hide();
HideNextMeetingPopup();
TriList.SetBool(UIBoolJoin.StartPageVisible, false);
TriList.SetBool(StartPageVisibleJoin, false);
TriList.SetBool(UIBoolJoin.CallStagingBarVisible, false);
TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, true);
// Run default source when room is off and share is pressed
@@ -957,12 +974,43 @@ namespace PepperDash.Essentials
if (_CurrentRoom == room) return;
// Disconnect current (probably never called)
if(_CurrentRoom != null)
_CurrentRoom.ConfigChanged -= room_ConfigChanged;
room.ConfigChanged -= room_ConfigChanged;
room.ConfigChanged += room_ConfigChanged;
if (room.IsMobileControlEnabled)
{
StartPageVisibleJoin = UIBoolJoin.StartMCPageVisible;
UpdateMCJoins(room);
if (_CurrentRoom != null)
_CurrentRoom.MobileControlRoomBridge.UserCodeChanged -= MobileControlRoomBridge_UserCodeChanged;
room.MobileControlRoomBridge.UserCodeChanged -= MobileControlRoomBridge_UserCodeChanged;
room.MobileControlRoomBridge.UserCodeChanged += MobileControlRoomBridge_UserCodeChanged;
}
else
{
StartPageVisibleJoin = UIBoolJoin.StartPageVisible;
}
RefreshCurrentRoom(room);
}
void MobileControlRoomBridge_UserCodeChanged(object sender, EventArgs e)
{
UpdateMCJoins(_CurrentRoom);
}
void UpdateMCJoins(EssentialsHuddleVtc1Room room)
{
TriList.SetString(UIStringJoin.RoomMcUrl, room.MobileControlRoomBridge.McServerUrl);
TriList.SetString(UIStringJoin.RoomMcQrCodeUrl, room.MobileControlRoomBridge.QrCodeUrl);
TriList.SetString(UIStringJoin.RoomUserCode, room.MobileControlRoomBridge.UserCode);
}
/// <summary>
/// Fires when room config of current room has changed. Meant to refresh room values to propegate any updates to UI
/// </summary>
@@ -999,12 +1047,15 @@ namespace PepperDash.Essentials
/// </summary>
void SetupSourceList()
{
var inCall = CurrentRoom.InCallFeedback.BoolValue;
var config = ConfigReader.ConfigObject.SourceLists;
if (config.ContainsKey(_CurrentRoom.SourceListKey))
{
var srcList = config[_CurrentRoom.SourceListKey].OrderBy(kv => kv.Value.Order);
// Setup sources list
SourceStagingSrl.Clear();
@@ -1028,6 +1079,8 @@ namespace PepperDash.Essentials
b => { if (!b) UiSelectSource(routeKey); });
SourceStagingSrl.AddItem(item); // add to the SRL
item.RegisterForSourceChange(_CurrentRoom);
Debug.Console(1, "**** KEY {0}", kvp.Key);
}
SourceStagingSrl.Count = (ushort)(i - 1);
}
@@ -1149,7 +1202,7 @@ namespace PepperDash.Essentials
var value = _CurrentRoom.OnFeedback.BoolValue;
TriList.BooleanInput[UIBoolJoin.RoomIsOn].BoolValue = value;
TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = !value;
TriList.BooleanInput[StartPageVisibleJoin].BoolValue = !value;
if (value) //ON
{
@@ -1381,6 +1434,7 @@ namespace PepperDash.Essentials
void ShowNotificationRibbon(string message, int timeout);
void HideNotificationRibbon();
void ShowTech();
uint StartPageVisibleJoin { get; }
}
/// <summary>

View File

@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials
{
/// <summary>
/// Driver responsible for controlling the screenshaver showing the client logo, MC connection information and QR Code. Moves the elements around to prevent screen burn in
/// </summary>
public class ScreenSaverController : PanelDriverBase
{
/// <summary>
/// The parent driver for this
/// </summary>
EssentialsPanelMainInterfaceDriver Parent;
CTimer PositionTimer;
uint PositionTimeoutMs;
List<uint> PositionJoins;
int CurrentPositionIndex = 0;
public ScreenSaverController(EssentialsPanelMainInterfaceDriver parent, CrestronTouchpanelPropertiesConfig config)
: base(parent.TriList)
{
Parent = parent;
PositionTimeoutMs = config.ScreenSaverMovePositionIntervalMs;
TriList.SetSigFalseAction(UIBoolJoin.MCScreenSaverClosePress, () => this.Hide());
}
public override void Show()
{
TriList.SetBool(UIBoolJoin.MCScreenSaverVisible, true);
Parent.AvDriver.PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.MCScreenSaverVisible);
//TriList.SetBool(UIBoolJoin.MCScreenSaverVisible, true);
CurrentPositionIndex = 0;
SetCurrentPosition();
ClearAllPositions();
TriList.SetBool(UIBoolJoin.MCScreenSaverVisible, false);
Parent.AvDriver.PopupInterlock.HideAndClear();
//TriList.SetBool(UIBoolJoin.MCScreenSaverVisible, false);
base.Hide();
}
void StartPositionTimer()
{
if (PositionTimer == null)
{
PositionTimer = new CTimer((o) => PositionTimerExpired(), PositionTimeoutMs);
}
else
{
PositionTimer.Reset(PositionTimeoutMs);
}
}
void PositionTimerExpired()
{
IncrementPositionIndex();
SetCurrentPosition();
StartPositionTimer();
}
void IncrementPositionIndex()
{
if (CurrentPositionIndex < PositionJoins.Count - 1)
{
CurrentPositionIndex++;
}
else
{
CurrentPositionIndex = 0;
}
Debug.Console(1, "ScreenSaver Position Timer Expired: Setting new position: {0}", CurrentPositionIndex);
}
//
void SetCurrentPosition()
{
ClearAllPositions();
// Set based on current index
TriList.SetBool(PositionJoins[CurrentPositionIndex], true);
}
void ClearAllPositions()
{
foreach (var join in PositionJoins)
{
TriList.SetBool(join, false);
}
}
}
}

View File

@@ -192,22 +192,76 @@ namespace PepperDash.Essentials.UIDrivers.VC
/// <param name="e"></param>
void Codec_IsReady()
{
string roomNumberSipUri = "";
if (!string.IsNullOrEmpty(Codec.CodecInfo.SipUri)) // If both values are present, format the string with a pipe divider
roomNumberSipUri = string.Format("{0} | {1}", GetFormattedPhoneNumber(Codec.CodecInfo.SipPhoneNumber), Codec.CodecInfo.SipUri);
else // If only one value present, just show the phone number
roomNumberSipUri = Codec.CodecInfo.SipPhoneNumber;
if(string.IsNullOrEmpty(roomNumberSipUri))
roomNumberSipUri = string.Format("{0} | {1}", Codec.CodecInfo.E164Alias, Codec.CodecInfo.H323Id);
TriList.SetString(UIStringJoin.RoomPhoneText, roomNumberSipUri);
SetupAddresses();
if(HeaderDriver.HeaderButtonsAreSetUp)
HeaderDriver.ComputeHeaderCallStatus(Codec);
}
void SetupAddresses()
{
string roomContactNumbers = "";
string roomPhoneNumber = "";
string roomVideoAddress = "";
Debug.Console(1,
@"
Codec.CodecInfo.IpAddress: {0}
Codec.CodecInfo.SipUri: {1}
Codec.CodecInfo.SipPhoneNumber: {2}
Codec.CodecInfo.E164Alias: {3}
Codec.CodecInfo.H323Id: {4}
", Codec.CodecInfo.IpAddress, Codec.CodecInfo.SipUri, Codec.CodecInfo.SipPhoneNumber, Codec.CodecInfo.E164Alias, Codec.CodecInfo.H323Id);
// Populate phone number
if (!string.IsNullOrEmpty(Codec.CodecInfo.SipUri)) // If both values are present, format the string with a pipe divider
{
roomPhoneNumber = Codec.CodecInfo.SipUri;
}
else if (!string.IsNullOrEmpty(Codec.CodecInfo.SipPhoneNumber)) // If only one value present, just show the phone number
{
roomPhoneNumber = GetFormattedPhoneNumber(Codec.CodecInfo.SipPhoneNumber);
}
// Populate video number
if (!string.IsNullOrEmpty(Codec.CodecInfo.IpAddress))
{
roomVideoAddress = Codec.CodecInfo.IpAddress;
}
else if (!string.IsNullOrEmpty(Codec.CodecInfo.E164Alias))
{
roomVideoAddress = Codec.CodecInfo.E164Alias;
}
else if (!string.IsNullOrEmpty(Codec.CodecInfo.H323Id))
{
roomVideoAddress = Codec.CodecInfo.H323Id;
}
Debug.Console(1,
@" Room Contact Numbers:
Phone Number: {0}
Video Number: {1}
", roomPhoneNumber, roomVideoAddress);
if (!string.IsNullOrEmpty(roomPhoneNumber) && !string.IsNullOrEmpty(roomVideoAddress))
{
roomContactNumbers = string.Format("{0} | {1}", roomPhoneNumber, roomVideoAddress);
}
else if (!string.IsNullOrEmpty(roomPhoneNumber))
{
roomContactNumbers = roomPhoneNumber;
}
else if (!string.IsNullOrEmpty(roomVideoAddress))
{
roomContactNumbers = roomVideoAddress;
}
TriList.SetString(UIStringJoin.RoomAddressPipeText, roomContactNumbers);
TriList.SetString(UIStringJoin.RoomPhoneText, roomPhoneNumber);
TriList.SetString(UIStringJoin.RoomVideoAddressText, roomVideoAddress);
}
/// <summary>
/// Handles status changes for calls
/// </summary>
@@ -337,6 +391,15 @@ namespace PepperDash.Essentials.UIDrivers.VC
icon = "Camera";
msg = string.Format("Incoming video call from: {0}", call.Name);
}
if (Parent.PopupInterlock.IsShown)
{
if (Parent.PopupInterlock.CurrentJoin == UIBoolJoin.MCScreenSaverVisible)
{
Parent.PopupInterlock.HideAndClear();
}
}
IncomingCallModal.PresentModalDialog(2, "Incoming Call", icon, msg,
"Ignore", "Accept", false, false, b =>
{

View File

@@ -1,26 +1,39 @@
# PepperDash Essentials Framework (c) 2020
## [Latest Release](https://github.com/PepperDash/Essentials/releases/latest)
## License
Provided under MIT license
## 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.
Essentials Framework is a collection of C# / Simpl# Pro libraries that can be utilized in several different manners. It is currently operating as a 100% configuration-driven system, and can be extended to add different workflows and behaviors, either through the addition of further device "types" or via the plug-in mechanism. The framework is a collection of "things" that are all related and interconnected, but in general do not have dependencies on each other.
## Minimum Requirements
- Essentials Framework runs on any Crestron 3-series processor, **4-series** processor or Crestron's VC-4 platform.
- To edit and compile the source, Microsoft Visual Studio 2008 Professional with SP1 is required.
- Crestron's Simpl# Plugin is also required (must be obtained from Crestron).
## Dependencies
The [PepperDash.Core](https://github.com/PepperDash/PepperDashCore) SIMPL# library is required. It is referenced as a submodule and will be automatically checked out when cloning this repo if set to recurse submodules. This allows different builds of the PepperDash.Core library to be referenced by checking out the desired submodule commit.
The [PepperDash.Core](https://github.com/PepperDash/PepperDashCore) SIMPL# library is required. It is referenced via nuget. You must have nuget.exe installed and in the `PATH` environment variable to use the following command. Nuget.exe is available at [nuget.org](https://dist.nuget.org/win-x86-commandline/latest/nuget.exe).
### Installing Dependencies
To install dependencies once nuget.exe is installed, run the following command:
`nuget install .\packages.config -OutputDirectory .\packages -excludeVersion`.
To verify that the packages installed correctly, open Essentials and make sure that all references are found, then try and build it.
### Installing Different versions of PepperDash Core
If you need a different version of PepperDash Core, use the command `nuget install .\packages.config -OutputDirectory .\packages -excludeVersion -Version {versionToGet}`. Omitting the `-Version` option will pull the version indicated in the packages.config file.
## Utilization
Essentials was originally conceptualized as a standalone application for running control system logic entirely in Simpl# Pro. It is primarily designed around accomplishing this goal, but during development, it became obvious that it could easily be leveraged to also serve as a partner application to one or more SIMPL Windows programs.
Utilization of Essentials Framework falls into the following categories:
@@ -34,13 +47,13 @@ Utilization of Essentials Framework falls into the following categories:
- Advanced logic. Some logic operations that cannot be affectively accomplished in SIMPL Windows (ex. JSON/XML serialization/deserialization, database operations, etc.) can be done in the Simpl# Pro environment and the necessary input and output bridged to a SIMPL Windows program via EISC.
3. Hybrid Application that may contain elements of both standalone control and SIMPL partner application integration.
- There may be a use case where a device can only be defined in a single application, but that device may need to be interacted with from multiple applications. The device can be defined in an Essentials application, interacted with in that application and also bridged to one or more SIMPL Windows applications.
## Documentation
For detailed documentation, see the [Wiki](https://github.com/PepperDash/EssentialsFramework/wiki).
- There may be a use case where a device can only be defined in a single application, but that device may need to be interacted with from multiple applications. The device can be defined in an Essentials application, interacted with in that application and also bridged to one or more SIMPL Windows applications.
## Documentation
For detailed documentation, see the [Wiki](https://github.com/PepperDash/EssentialsFramework/wiki).
## How-To (Getting Started)
See [Getting Started](https://github.com/PepperDash/Essentials/wiki/Get-started#how-to-get-started)

View File

@@ -115,23 +115,40 @@ namespace PepperDash.Essentials.Core
/// <returns></returns>
public static ICec GetCecPort(ControlPropertiesConfig config)
{
var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey);
var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey);
if (dev != null)
{
if (!String.IsNullOrEmpty(config.ControlPortName))
{
var inputPort = (dev as IRoutingInputsOutputs).InputPorts[config.ControlPortName];
if (inputPort != null)
{
if (inputPort.Port is ICec)
return inputPort.Port as ICec;
}
var outputPort = (dev as IRoutingInputsOutputs).OutputPorts[config.ControlPortName];
if (outputPort != null)
{
if (outputPort.Port is ICec)
return outputPort.Port as ICec;
}
else
Debug.Console(0, "GetCecPort: Device '{0}' does not have a CEC port called: '{1}'",
config.ControlPortDevKey, config.ControlPortName);
}
else
{
Debug.Console(0, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey);
}
}
Debug.Console(0, "GetCecPort: Device '{0}' is not a valid device.", config.ControlPortDevKey);
if (dev != null)
{
var inputPort = (dev as IRoutingInputsOutputs).InputPorts[config.ControlPortName];
if (inputPort != null)
if (inputPort.Port is ICec)
return inputPort.Port as ICec;
var outputPort = (dev as IRoutingInputsOutputs).OutputPorts[config.ControlPortName];
if (outputPort != null)
if (outputPort.Port is ICec)
return outputPort.Port as ICec;
}
Debug.Console(0, "GetCecPort: Device '{0}' does not have a CEC port called: '{1}'", config.ControlPortDevKey, config.ControlPortName);
return null;
}

View File

@@ -1,11 +1,33 @@
using PepperDash.Core;
using System;
using PepperDash.Core;
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
{
public interface IMobileControl:IKeyed
/// <summary>
/// Describes a MobileControlSystemController
/// </summary>
public interface IMobileControl : IKeyed
{
void CreateMobileControlRoomBridge(EssentialsRoomBase room);
void LinkSystemMonitorToAppServer();
}
/// <summary>
/// Describes a MobileControl Room Bridge
/// </summary>
public interface IMobileControlRoomBridge : IKeyed
{
event EventHandler<EventArgs> UserCodeChanged;
string UserCode { get; }
string QrCodeUrl { get; }
string McServerUrl { get; }
string RoomName { get; }
}
}

View File

@@ -337,7 +337,36 @@ namespace PepperDash.Essentials.Core
return;
}
com.SimulateReceive(match.Groups[2].Value);
}
}
/// <summary>
/// Prints a list of routing inputs and outputs by device key.
/// </summary>
/// <param name="s">Device key from which to report data</param>
public static void GetRoutingPorts(string s)
{
var device = GetDeviceForKey(s);
if (device == null) return;
var inputPorts = (device as IRoutingInputsOutputs).InputPorts;
var outputPorts = (device as IRoutingInputsOutputs).OutputPorts;
if (inputPorts != null)
{
Debug.Console(0, "Device {0} has {1} Input Ports:", s, inputPorts.Count);
foreach (var routingInputPort in inputPorts)
{
Debug.Console(0, "{0}", routingInputPort.Key);
}
}
if (outputPorts != null)
{
Debug.Console(0, "Device {0} has {1} Output Ports:", s, outputPorts.Count);
foreach (var routingOutputPort in outputPorts)
{
Debug.Console(0, "{0}", routingOutputPort.Key);
}
}
}
/// <summary>
/// Attempts to set the debug level of a device

View File

@@ -1,45 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using System;
using System.Collections.Generic;
using System.Linq;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core.Config;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// IR port wrapper. May act standalone
/// </summary>
public class IrOutputPortController : Device
{
uint IrPortUid;
IROutputPort IrPort;
public ushort StandardIrPulseTime { get; set; }
public string DriverFilepath { get; private set; }
public bool DriverIsLoaded { get; private set; }
/// <summary>
/// Constructor for IrDevice base class. If a null port is provided, this class will
/// still function without trying to talk to a port.
/// </summary>
public IrOutputPortController(string key, IROutputPort port, string irDriverFilepath)
: base(key)
{
//if (port == null) throw new ArgumentNullException("port");
IrPort = port;
if (port == null)
{
Debug.Console(0, this, "WARNING No valid IR Port assigned to controller. IR will not function");
return;
}
LoadDriver(irDriverFilepath);
using PepperDash.Essentials.Core.Config;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// IR port wrapper. May act standalone
/// </summary>
public class IrOutputPortController : Device
{
uint IrPortUid;
IROutputPort IrPort;
public ushort StandardIrPulseTime { get; set; }
public string DriverFilepath { get; private set; }
public bool DriverIsLoaded { get; private set; }
/// <summary>
/// Constructor for IrDevice base class. If a null port is provided, this class will
/// still function without trying to talk to a port.
/// </summary>
public IrOutputPortController(string key, IROutputPort port, string irDriverFilepath)
: base(key)
{
//if (port == null) throw new ArgumentNullException("port");
IrPort = port;
if (port == null)
{
Debug.Console(0, this, "WARNING No valid IR Port assigned to controller. IR will not function");
return;
}
LoadDriver(irDriverFilepath);
}
public IrOutputPortController(string key, Func<DeviceConfig, IROutputPort> postActivationFunc,
@@ -54,85 +54,85 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// Loads the IR driver at path
/// </summary>
/// <param name="path"></param>
public void LoadDriver(string path)
{
if (string.IsNullOrEmpty(path)) path = DriverFilepath;
try
{
IrPortUid = IrPort.LoadIRDriver(path);
DriverFilepath = path;
StandardIrPulseTime = 200;
DriverIsLoaded = true;
}
catch
{
DriverIsLoaded = false;
var message = string.Format("WARNING IR Driver '{0}' failed to load", path);
Debug.Console(0, this, message);
ErrorLog.Error(message);
}
}
/// <summary>
/// Starts and stops IR command on driver. Safe for missing commands
/// </summary>
public virtual void PressRelease(string command, bool state)
{
Debug.Console(2, this, "IR:'{0}'={1}", command, state);
if (IrPort == null)
{
Debug.Console(2, this, "WARNING No IR Port assigned to controller");
return;
}
if (!DriverIsLoaded)
{
Debug.Console(2, this, "WARNING IR driver is not loaded");
return;
}
if (state)
{
if (IrPort.IsIRCommandAvailable(IrPortUid, command))
IrPort.Press(IrPortUid, command);
else
NoIrCommandError(command);
}
else
IrPort.Release();
}
/// <summary>
/// Pulses a command on driver. Safe for missing commands
/// </summary>
public virtual void Pulse(string command, ushort time)
{
if (IrPort == null)
{
Debug.Console(2, this, "WARNING No IR Port assigned to controller");
return;
}
if (!DriverIsLoaded)
{
Debug.Console(2, this, "WARNING IR driver is not loaded");
return;
}
if (IrPort.IsIRCommandAvailable(IrPortUid, command))
IrPort.PressAndRelease(IrPortUid, command, time);
else
NoIrCommandError(command);
}
/// <summary>
/// Notifies the console when a bad command is used.
/// </summary>
protected void NoIrCommandError(string command)
{
Debug.Console(2, this, "Device {0}: IR Driver {1} does not contain command {2}",
Key, IrPort.IRDriverFileNameByIRDriverId(IrPortUid), command);
/// <summary>
/// Loads the IR driver at path
/// </summary>
/// <param name="path"></param>
public void LoadDriver(string path)
{
if (string.IsNullOrEmpty(path)) path = DriverFilepath;
try
{
IrPortUid = IrPort.LoadIRDriver(path);
DriverFilepath = path;
StandardIrPulseTime = 200;
DriverIsLoaded = true;
}
catch
{
DriverIsLoaded = false;
var message = string.Format("WARNING IR Driver '{0}' failed to load", path);
Debug.Console(0, this, message);
ErrorLog.Error(message);
}
}
}
/// <summary>
/// Starts and stops IR command on driver. Safe for missing commands
/// </summary>
public virtual void PressRelease(string command, bool state)
{
Debug.Console(2, this, "IR:'{0}'={1}", command, state);
if (IrPort == null)
{
Debug.Console(2, this, "WARNING No IR Port assigned to controller");
return;
}
if (!DriverIsLoaded)
{
Debug.Console(2, this, "WARNING IR driver is not loaded");
return;
}
if (state)
{
if (IrPort.IsIRCommandAvailable(IrPortUid, command))
IrPort.Press(IrPortUid, command);
else
NoIrCommandError(command);
}
else
IrPort.Release();
}
/// <summary>
/// Pulses a command on driver. Safe for missing commands
/// </summary>
public virtual void Pulse(string command, ushort time)
{
if (IrPort == null)
{
Debug.Console(2, this, "WARNING No IR Port assigned to controller");
return;
}
if (!DriverIsLoaded)
{
Debug.Console(2, this, "WARNING IR driver is not loaded");
return;
}
if (IrPort.IsIRCommandAvailable(IrPortUid, command))
IrPort.PressAndRelease(IrPortUid, command, time);
else
NoIrCommandError(command);
}
/// <summary>
/// Notifies the console when a bad command is used.
/// </summary>
protected void NoIrCommandError(string command)
{
Debug.Console(2, this, "Device {0}: IR Driver {1} does not contain command {2}",
Key, IrPort.IRDriverFileNameByIRDriverId(IrPortUid), command);
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.Diagnostics;
@@ -100,25 +101,28 @@ namespace PepperDash.Essentials.Core.Monitoring
UptimeFeedback.FireUpdate();
LastStartFeedback.FireUpdate();
}
private void ParseUptime(string response)
{
var splitString = response.Trim().Split('\r', '\n');
var lastStartRaw = splitString[2];
var lastStartIndex = lastStartRaw.IndexOf(':');
_lastStart = lastStartRaw.Substring(lastStartIndex + 1).Trim();
var uptimeRaw = splitString[0];
var forIndex = uptimeRaw.IndexOf("for", StringComparison.Ordinal);
//4 => "for " to get what's on the right
_uptime = uptimeRaw.Substring(forIndex + 4);
}
}
private void ParseUptime(string response)
{
var splitString = response.Trim().Split('\r', '\n');
var lastStartRaw = splitString.FirstOrDefault(o => o.Contains("started"));
var uptimeRaw = splitString.FirstOrDefault(o => o.Contains("running"));
if (!String.IsNullOrEmpty(lastStartRaw))
{
var lastStartIndex = lastStartRaw.IndexOf(':');
_lastStart = lastStartRaw.Substring(lastStartIndex + 1).Trim();
}
if (String.IsNullOrEmpty(uptimeRaw)) return;
var forIndex = uptimeRaw.IndexOf("for", StringComparison.Ordinal);
//4 => "for " to get what's on the right
_uptime = uptimeRaw.Substring(forIndex + 4);
}
private void CrestronEnvironmentOnEthernetEventHandler(EthernetEventArgs ethernetEventArgs)
{
if (ethernetEventArgs.EthernetEventType != eEthernetEventType.LinkUp) return;

View File

@@ -48,71 +48,83 @@
<ItemGroup>
<Reference Include="Crestron.SimplSharpPro.DeviceSupport, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DeviceSupport.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DeviceSupport.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Crestron.SimplSharpPro.DM, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DM.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DM.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Crestron.SimplSharpPro.EthernetCommunications, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.EthernetCommunications.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.EthernetCommunications.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Crestron.SimplSharpPro.Fusion, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Fusion.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Fusion.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Crestron.SimplSharpPro.Gateways, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Gateways.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Gateways.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Crestron.SimplSharpPro.GeneralIO, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.GeneralIO.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.GeneralIO.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Crestron.SimplSharpPro.Remotes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Remotes.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Remotes.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Crestron.SimplSharpPro.ThreeSeriesCards, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.ThreeSeriesCards.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.ThreeSeriesCards.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Crestron.SimplSharpPro.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="PepperDash_Core, Version=1.0.26.30384, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="PepperDash_Core, Version=1.0.41.31808, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\pepperdashcore-builds\PepperDash_Core.dll</HintPath>
<HintPath>..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll</HintPath>
</Reference>
<Reference Include="SimplSharpCustomAttributesInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll</HintPath>
<HintPath>..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SimplSharpHelperInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll</HintPath>
<HintPath>..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SimplSharpNewtonsoft, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SimplSharpPro, Version=1.5.3.17, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe</HintPath>
<HintPath>..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SimplSharpReflectionInterface, Version=1.0.5583.25238, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SimplSharpTimerEventInterface, Version=1.0.6197.20052, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpTimerEventInterface.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SimplSharpTimerEventInterface.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<package >
<metadata>
<id>PepperDashEssentials</id>
<version>1.5.6</version>
<title>PepperDash Essentials</title>
<authors>PepperDash Technologies</authors>
<owners>pepperdash</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<projectUrl>https://github.com/PepperDash/PepperDashCore</projectUrl>
<copyright>Copyright 2020</copyright>
<description>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. Essentials Framework is a collection of C# / Simpl# Pro libraries that can be utilized in several different manners. It is currently operating as a 100% configuration-driven system, and can be extended to add different workflows and behaviors, either through the addition of further device "types" or via the plug-in mechanism. The framework is a collection of "things" that are all related and interconnected, but in general do not have dependencies on each other.</description>
<tags>crestron 3series 4series</tags>
<repository type="git" url="https://github.com/PepperDash/Essentials"/>
<dependencies>
<dependency id="PepperDashCore" version="[1.0, 1.1)"/>
</dependencies>
</metadata>
<files>
<file src="**" target="lib\net35"/>
<file src="**" target="lib\net47"/>
</files>
</package>

View File

@@ -9,6 +9,7 @@ using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Devices;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials.Core
{
@@ -37,10 +38,32 @@ namespace PepperDash.Essentials.Core
protected abstract Func<bool> IsWarmingFeedbackFunc { get; }
protected abstract Func<bool> IsCoolingFeedbackFunc { get; }
/// <summary>
/// Indicates if this room is Mobile Control Enabled
/// </summary>
public bool IsMobileControlEnabled { get; private set; }
/// <summary>
/// The bridge for this room if Mobile Control is enabled
/// </summary>
public IMobileControlRoomBridge MobileControlRoomBridge { get; private set; }
/// <summary>
/// The config name of the source list
/// </summary>
public string SourceListKey { get; set; }
///
protected string _SourceListKey;
public virtual string SourceListKey {
get
{
return _SourceListKey;
}
set
{
_SourceListKey = value;
}
}
/// <summary>
/// Timer used for informing the UIs of a shutdown
@@ -58,7 +81,9 @@ namespace PepperDash.Essentials.Core
public Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; set; }
public string LogoUrl { get; set; }
public string LogoUrlLightBkgnd { get; set; }
public string LogoUrlDarkBkgnd { get; set; }
protected SecondsCountdownTimer RoomVacancyShutdownTimer { get; private set; }
@@ -128,6 +153,34 @@ namespace PepperDash.Essentials.Core
});
}
public override bool CustomActivate()
{
SetUpMobileControl();
return base.CustomActivate();
}
/// <summary>
/// If mobile control is enabled, sets the appropriate properties
/// </summary>
void SetUpMobileControl()
{
var mcBridgeKey = string.Format("mobileControlBridge-{0}", Key);
var mcBridge = DeviceManager.GetDeviceForKey(mcBridgeKey);
if (mcBridge == null)
{
Debug.Console(1, this, "*********************Mobile Control Bridge Not found for this room.");
IsMobileControlEnabled = false;
return;
}
else
{
MobileControlRoomBridge = mcBridge as IMobileControlRoomBridge;
Debug.Console(1, this, "*********************Mobile Control Bridge found and enabled for this room");
IsMobileControlEnabled = true;
}
}
void RoomVacancyShutdownPromptTimer_HasFinished(object sender, EventArgs e)
{
switch (VacancyMode)

View File

@@ -14,6 +14,8 @@
public UiSetupPropertiesConfig Setup { get; set; }
public string HeaderStyle { get; set; }
public bool IncludeInFusionRoomHealth { get; set; }
public uint ScreenSaverTimeoutMin { get; set; }
public uint ScreenSaverMovePositionIntervalMs { get; set; }
/// <summary>
@@ -26,6 +28,10 @@
{
SourcesOverflowCount = 5;
HeaderStyle = CrestronTouchpanelPropertiesConfig.Habanero;
// Default values
ScreenSaverTimeoutMin = 5;
ScreenSaverMovePositionIntervalMs = 15000;
}
/// <summary>

View File

@@ -48,43 +48,48 @@
<ItemGroup>
<Reference Include="Crestron.SimplSharpPro.DeviceSupport, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DeviceSupport.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DeviceSupport.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Crestron.SimplSharpPro.DM, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DM.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DM.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Crestron.SimplSharpPro.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="PepperDash_Core, Version=1.0.26.30384, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="PepperDash_Core, Version=1.0.41.31808, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\pepperdashcore-builds\PepperDash_Core.dll</HintPath>
<HintPath>..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll</HintPath>
</Reference>
<Reference Include="SimplSharpCustomAttributesInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll</HintPath>
<HintPath>..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SimplSharpHelperInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll</HintPath>
<HintPath>..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SimplSharpNewtonsoft, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SimplSharpPro, Version=1.5.3.17, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe</HintPath>
<HintPath>..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SimplSharpReflectionInterface, Version=1.0.5583.25238, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco;
namespace PepperDash.Essentials.Devices.Common.Codec
{
public interface IHasExternalSourceSwitching
{
bool ExternalSourceListEnabled { get; }
void AddExternalSource(string connectorId, string key, string name, eExternalSourceType type);
void SetExternalSourceState(string key, eExternalSourceMode mode);
void ClearExternalSources();
Action<string, string> RunRouteAction { set;}
}
}

View File

@@ -48,24 +48,28 @@
<ItemGroup>
<Reference Include="Crestron.SimplSharpPro.DeviceSupport, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DeviceSupport.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DeviceSupport.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Crestron.SimplSharpPro.Gateways, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Gateways.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Gateways.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Crestron.SimplSharpPro.GeneralIO, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.GeneralIO.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.GeneralIO.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Crestron.SimplSharpPro.Lighting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Lighting.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Lighting.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="PepperDash_Core, Version=1.0.26.30384, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="PepperDash_Core, Version=1.0.41.31808, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\pepperdashcore-builds\PepperDash_Core.dll</HintPath>
<HintPath>..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll</HintPath>
</Reference>
<Reference Include="PepperDash_Essentials_Core, Version=0.0.0.22043, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -73,26 +77,28 @@
</Reference>
<Reference Include="SimplSharpCustomAttributesInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll</HintPath>
<HintPath>..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SimplSharpHelperInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll</HintPath>
<HintPath>..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SimplSharpNewtonsoft, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SimplSharpPro, Version=1.5.3.17, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe</HintPath>
<HintPath>..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SimplSharpReflectionInterface, Version=1.0.5583.25238, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath>
<HintPath>..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -112,6 +118,7 @@
<Compile Include="Codec\eCodecCallStatus.cs" />
<Compile Include="Codec\eMeetingPrivacy.cs" />
<Compile Include="Codec\iCodecAudio.cs" />
<Compile Include="Codec\IHasExternalSourceSwitching.cs" />
<Compile Include="ImageProcessors\TVOneCorio.cs" />
<Compile Include="ImageProcessors\TVOneCorioPropertiesConfig.cs" />
<Compile Include="Power Controllers\Digitallogger.cs" />

View File

@@ -15,16 +15,17 @@ using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Routing;
using PepperDash.Essentials.Devices.Common.Cameras;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.VideoCodec;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
enum eCommandType { SessionStart, SessionEnd, Command, GetStatus, GetConfiguration };
public enum eExternalSourceType {camera, desktop, document_camera, mediaplayer, PC, whiteboard, other}
public enum eExternalSourceMode {Ready, NotReady, Hidden, Error}
public class CiscoSparkCodec : VideoCodecBase, IHasCallHistory, IHasCallFavorites, IHasDirectory,
IHasScheduleAwareness, IOccupancyStatusProvider, IHasCodecLayouts, IHasCodecSelfView,
ICommunicationMonitor, IRouting, IHasCodecCameras, IHasCameraAutoMode, IHasCodecRoomPresets
ICommunicationMonitor, IRouting, IHasCodecCameras, IHasCameraAutoMode, IHasCodecRoomPresets, IHasExternalSourceSwitching
{
public event EventHandler<DirectoryEventArgs> DirectoryResultReturned;
@@ -348,6 +349,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
CallHistory = new CodecCallHistory();
if (props.Favorites != null)
{
CallFavorites = new CodecCallFavorites();
@@ -398,6 +400,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
SetUpCameras();
CreateOsdSource();
if (props.ExternalSourceListEnabled != null)
{
ExternalSourceListEnabled = props.ExternalSourceListEnabled;
}
}
/// <summary>
@@ -472,7 +479,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
prefix + "/Bookings" + Delimiter +
prefix + "/Event/CallDisconnect" + Delimiter +
prefix + "/Event/Bookings" + Delimiter +
prefix + "/Event/CameraPresetListUpdated" + Delimiter;
prefix + "/Event/CameraPresetListUpdated" + Delimiter +
prefix + "/Event/UserInterface/Presentation/ExternalSource/Selected/SourceIdentifier" + Delimiter;
return base.CustomActivate();
}
@@ -629,6 +637,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
}
}
}
}
@@ -853,6 +862,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
GetBookings(null);
}
else if (response.IndexOf("\"UserInterface\":{") > -1 || response.IndexOf("\"UserInterface\": {") > -1) // External Source Trigger
{
CiscoCodecEvents.RootObject eventReceived = new CiscoCodecEvents.RootObject();
JsonConvert.PopulateObject(response, eventReceived);
Debug.Console(2, this, "*** Got an External Source Selection {0} {1}", eventReceived, eventReceived.Event.UserInterface, eventReceived.Event.UserInterface.Presentation.ExternalSource.Selected.SourceIdentifier.Value);
if (RunRouteAction != null)
{
RunRouteAction(eventReceived.Event.UserInterface.Presentation.ExternalSource.Selected.SourceIdentifier.Value, null);
}
}
}
else if (response.IndexOf("\"CommandResponse\":{") > -1 || response.IndexOf("\"CommandResponse\": {") > -1)
{
@@ -1699,7 +1720,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
get
{
if (CodecConfiguration.Configuration.H323 != null && CodecConfiguration.Configuration.H323.H323Alias.E164 != null)
if (CodecConfiguration.Configuration.H323 != null && CodecConfiguration.Configuration.H323.H323Alias != null
&& CodecConfiguration.Configuration.H323.H323Alias.ID != null)
{
return CodecConfiguration.Configuration.H323.H323Alias.ID.Value;
}
@@ -1801,9 +1823,76 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
SendText(string.Format("xCommand Call FarEndControl RoomPreset Activate CallId: {0} PresetId: {1}", GetCallId(), preset));
}
}
/// <summary>
#region IHasExternalSourceSwitching Members
/// <summary>
/// Weather the Cisco supports External Source Lists or not
/// </summary>
public bool ExternalSourceListEnabled
{
get;
private set;
}
/// <summary>
/// Adds an external source to the Cisco
/// </summary>
/// <param name="connectorId"></param>
/// <param name="key"></param>
/// <param name="name"></param>
public void AddExternalSource(string connectorId, string key, string name, eExternalSourceType type)
{
int id = 2;
if (connectorId.ToLower() == "hdmiin3")
{
id = 3;
}
SendText(string.Format("xCommand UserInterface Presentation ExternalSource Add ConnectorId: {0} SourceIdentifier: \"{1}\" Name: \"{2}\" Type: {3}", id, key, name, type.ToString()));
// SendText(string.Format("xCommand UserInterface Presentation ExternalSource State Set SourceIdentifier: \"{0}\" State: Ready", key));
Debug.Console(2, this, "Adding ExternalSource {0} {1}", connectorId, name);
}
/// <summary>
/// Sets the state of the External Source
/// </summary>
/// <param name="key"></param>
/// <param name="mode"></param>
public void SetExternalSourceState(string key, eExternalSourceMode mode)
{
SendText(string.Format("xCommand UserInterface Presentation ExternalSource State Set SourceIdentifier: \"{0}\" State: {1}", key, mode.ToString()));
}
/// <summary>
/// Clears all external sources on the codec
/// </summary>
public void ClearExternalSources()
{
SendText("xCommand UserInterface Presentation ExternalSource RemoveAll");
}
/// <summary>
/// Action that will run when the External Source is selected.
/// </summary>
public Action<string, string> RunRouteAction { private get; set; }
#endregion
#region ExternalDevices
#endregion
}
/// <summary>
/// Represents a codec command that might need to have a friendly label applied for UI feedback purposes
/// </summary>
public class CodecCommandWithLabel

View File

@@ -1,47 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.Codec
{
public class CiscoSparkCodecPropertiesConfig
{
[JsonProperty("communicationMonitorProperties")]
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
[JsonProperty("favorites")]
public List<CodecActiveCallItem> Favorites { get; set; }
/// <summary>
/// Valid values: "Local" or "Corporate"
/// </summary>
[JsonProperty("phonebookMode")]
public string PhonebookMode { get; set; }
[JsonProperty("showSelfViewByDefault")]
public bool ShowSelfViewByDefault { get; set; }
[JsonProperty("sharing")]
public SharingProperties Sharing { get; set; }
/// <summary>
/// Optionsal property to set the limit of any phonebook queries for directory or searching
/// </summary>
[JsonProperty("phonebookResultsLimit")]
public uint PhonebookResultsLimit { get; set; }
}
public class SharingProperties
{
[JsonProperty("autoShareContentWhileInCall")]
public bool AutoShareContentWhileInCall { get; set; }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.Codec
{
public class CiscoSparkCodecPropertiesConfig
{
[JsonProperty("communicationMonitorProperties")]
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
[JsonProperty("favorites")]
public List<CodecActiveCallItem> Favorites { get; set; }
/// <summary>
/// Valid values: "Local" or "Corporate"
/// </summary>
[JsonProperty("phonebookMode")]
public string PhonebookMode { get; set; }
[JsonProperty("showSelfViewByDefault")]
public bool ShowSelfViewByDefault { get; set; }
[JsonProperty("sharing")]
public SharingProperties Sharing { get; set; }
[JsonProperty("externalSourceListEnabled")]
public bool ExternalSourceListEnabled { get; set; }
/// <summary>
/// Optionsal property to set the limit of any phonebook queries for directory or searching
/// </summary>
[JsonProperty("phonebookResultsLimit")]
public uint PhonebookResultsLimit { get; set; }
}
public class SharingProperties
{
[JsonProperty("autoShareContentWhileInCall")]
public bool AutoShareContentWhileInCall { get; set; }
}
}

View File

@@ -126,11 +126,36 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Encryption Encryption { get; set; }
public RequestedURI RequestedURI { get; set; }
public PeopleCountAverage PeopleCountAverage { get; set; }
}
}
public class UserInterface
{
public string id { get; set; }
public Presentation Presentation { get; set; }
}
public class Presentation
{
public string id { get; set; }
public ExternalSource ExternalSource { get; set; }
}
public class ExternalSource
{
public string id { get; set; }
public Selected Selected { get; set; }
}
public class Selected
{
public string id { get; set; }
public SourceIdentifier SourceIdentifier { get; set; }
}
public class SourceIdentifier
{
public string id { get; set; }
public string Value { get; set; }
}
public class Event
{
public CallDisconnect CallDisconnect { get; set; }
public CallDisconnect CallDisconnect { get; set; }
public UserInterface UserInterface { get; set; }
}
public class RootObject

3
packages.config Normal file
View File

@@ -0,0 +1,3 @@
<packages>
<package id="PepperDashCore" version="1.0.41" targetFramework="net35" allowedVersions="[1.0,1.1)"/>
</packages>