Compare commits

..

5 Commits

1200 changed files with 121228 additions and 89868 deletions

View File

@@ -1,37 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: "[BUG]-"
labels: bug
assignees: ''
---
**Was this bug identified in a specific build version?**
Please note the build version where this bug was identified
**Describe the bug**
A clear and concise description of what the bug is.
**Stacktrace**
Include a stack trace of the exception if possible.
```
Paste stack trace here
```
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional context**
Add any other context about the problem here.

View File

@@ -1,21 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: "[FEATURE]-"
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
If this is a request for support for a new device or type, be as specific as possible and include any pertinent manufacturer and model information.
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -1,27 +0,0 @@
---
name: Request for Information
about: Request specific information about capabilities of the framework
title: "[RFI]-"
labels: RFI
assignees: ''
---
**What is your request?**
Please provide as much detail as possible.
**What is the intended use case**
- [ ] Essentials Standalone Application
- [ ] Essentials + SIMPL Windows Hybrid
**User Interface Requirements**
- [ ] Not Applicable (logic only)
- [ ] Crestron Smart Graphics Touchpanel
- [ ] Cisco Touch10
- [ ] Mobile Control
- [ ] Crestron CH5 Touchpanel interface
**Additional context**
Add any other context or screenshots about the request here.

View File

@@ -1,23 +0,0 @@
$latestVersion = [version]"2.0.0"
$newVersion = [version]$latestVersion
$phase = ""
$newVersionString = ""
switch -regex ($Env:GITHUB_REF) {
'^refs\/pull\/*.' {
$phase = 'beta';
$newVersionString = "{0}-{1}-{2}" -f $newVersion, $phase, $Env:GITHUB_RUN_NUMBER
}
'^refs\/heads\/feature-2.0.0\/*.' {
$phase = 'alpha'
$newVersionString = "{0}-{1}-{2}" -f $newVersion, $phase, $Env:GITHUB_RUN_NUMBER
}
'development-2.0.0' {
$phase = 'beta'
$newVersionString = "{0}-{1}-{2}" -f $newVersion, $phase, $Env:GITHUB_RUN_NUMBER
}
}
Write-Output $newVersionString

View File

@@ -1,59 +0,0 @@
$latestVersions = $(git tag --merged origin/main)
$latestVersion = [version]"0.0.0"
Write-Host "GITHUB_REF: $($Env:GITHUB_REF)"
Write-Host "GITHUB_HEAD_REF: $($Env:GITHUB_HEAD_REF)"
Write-Host "GITHUB_BASE_REF: $($Env:GITHUB_BASE_REF)"
Foreach ($version in $latestVersions) {
Write-Host $version
try {
if (([version]$version) -ge $latestVersion) {
$latestVersion = $version
Write-Host "Setting latest version to: $latestVersion"
}
}
catch {
Write-Host "Unable to convert $($version). Skipping"
continue;
}
}
$newVersion = [version]$latestVersion
$phase = ""
$newVersionString = ""
switch -regex ($Env:GITHUB_REF) {
'^refs\/pull\/*.' {
$splitRef = $Env:GITHUB_REF -split "/"
$phase = "pr$($splitRef[2])"
$newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER
}
'^refs\/heads\/main*.' {
$newVersionString = "{0}.{1}.{2}" -f $newVersion.Major, $newVersion.Minor, $newVersion.Build
}
'^refs\/heads\/feature\/*.' {
$phase = 'alpha'
$newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER
}
'^refs\/heads\/release\/*.' {
$splitRef = $Env:GITHUB_REF -split "/"
$version = [version]($splitRef[-1] -replace "v", "")
$phase = 'rc'
$newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $version.Major, $version.Minor, $version.Build, $phase, $Env:GITHUB_RUN_NUMBER
}
'^refs\/heads\/development*.' {
$phase = 'beta'
$newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER
}
'^refs\/heads\/hotfix\/*.' {
$phase = 'hotfix'
$newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER
}
'^refs\/heads\/bugfix\/*.' {
$phase = 'hotfix'
$newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER
}
}
Write-Output $newVersionString

View File

@@ -1,40 +0,0 @@
function Update-SourceVersion {
Param ([string]$Version)
#$fullVersion = $Version
$baseVersion = [regex]::Match($Version, "(\d+.\d+.\d+).*").captures.groups[1].value
$NewAssemblyVersion = AssemblyVersion(" + $baseVersion + .*")
Write-Output "AssemblyVersion = $NewAssemblyVersion"
$NewAssemblyInformationalVersion = AssemblyInformationalVersion(" + $Version + ")
Write-Output "AssemblyInformationalVersion = $NewAssemblyInformationalVersion"
foreach ($o in $input) {
Write-output $o.FullName
$TmpFile = $o.FullName + .tmp
get-content $o.FullName |
ForEach-Object {
$_ -replace AssemblyVersion\(".*"\), $NewAssemblyVersion } |
ForEach-Object {
$_ -replace AssemblyInformationalVersion\(".*"\), $NewAssemblyInformationalVersion
} > $TmpFile
move-item $TmpFile $o.FullName -force
}
}
function Update-AllAssemblyInfoFiles ( $version ) {
foreach ($file in AssemblyInfo.cs, AssemblyInfo.vb ) {
get-childitem -Path $Env:GITHUB_WORKSPACE -recurse | Where-Object { $_.Name -eq $file } | Update-SourceVersion $version ;
}
}
# validate arguments
$r = [System.Text.RegularExpressions.Regex]::Match($args[0], "\d+\.\d+\.\d+.*");
if ($r.Success) {
Write-Output "Updating Assembly Version to $args ...";
Update-AllAssemblyInfoFiles $args[0];
}
else {
Write-Output ;
Write-Output Error: Input version does not match x.y.z format!
Write-Output ;
Write-Output "Unable to apply version to AssemblyInfo.cs files";
}

View File

@@ -1,45 +0,0 @@
# Uncomment these for local testing
# $Env:GITHUB_WORKSPACE = "C:\Working Directories\PD\essentials"
# $Env:SOLUTION_FILE = "PepperDashEssentials"
# $Env:VERSION = "0.0.0-buildType-test"
# Sets the root directory for the operation
$destination = "$($Env:GITHUB_HOME)\output"
New-Item -ItemType Directory -Force -Path ($destination)
Get-ChildItem ($destination)
$exclusions = @(git submodule foreach --quiet 'echo $name')
$exclusions += "Newtonsoft.Compact.Json.dll"
# 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", "*.nuspec" | ForEach-Object {
$allowed = $true;
# Exclude any files in submodules
foreach ($exclude in $exclusions) {
if ((Split-Path $_.FullName -Parent).contains("$($exclude)")) {
$allowed = $false;
break;
}
}
if ($allowed) {
Write-Host "allowing $($_)"
$_;
}
} | Copy-Item -Destination ($destination) -Force
Write-Host "Getting matching files..."
# Get any files from the output folder that match the following extensions
Get-ChildItem -Path $destination | Where-Object { ($_.Extension -eq ".clz") -or ($_.Extension -eq ".cpz" -or ($_.Extension -eq ".cplz")) } | ForEach-Object {
# Replace the extensions with dll and xml and create an array
# Removed dll file capture, as previous step should capture all of them. Add if needed-> $($_ -replace "cpz|clz|cplz", "dll"),
$filenames = @($($_ -replace "cpz|clz|cplz", "xml"))
Write-Host "Filenames:"
Write-Host $filenames
if ($filenames.length -gt 0) {
# Attempt to get the files and return them to the output directory
Get-ChildItem -Recurse -Path "$($Env:GITHUB_WORKSPACE)" -include $filenames | Copy-Item -Destination ($destination) -Force
}
}
Get-ChildItem -Path $destination\*.cpz | Rename-Item -NewName { "$($_.BaseName)-$($Env:VERSION)$($_.Extension)" }
Compress-Archive -Path $destination -DestinationPath "$($Env:GITHUB_WORKSPACE)\$($Env:SOLUTION_FILE)-$($Env:VERSION).zip" -Force
Write-Host "Output Contents post Zip"
Get-ChildItem -Path $destination

View File

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

View File

@@ -1,45 +0,0 @@
name: Publish Docs
# Trigger the action on push to main
on:
push:
branches:
- main
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
actions: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
publish-docs:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Dotnet Setup
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.x
- run: dotnet tool update -g docfx
- run: docfx ./docs/docfx.json
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
# Upload entire repository
path: './docs/_site'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

375
.gitignore vendored
View File

@@ -22,378 +22,3 @@ _ReSharper*/
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
essentials-framework/Essentials Interfaces/PepperDash_Essentials_Interfaces/PepperDash_Essentials_Interfaces.csproj
.DS_Store
/._PepperDash.Essentials.sln
.vscode/settings.json
_site/
api/
*.DS_Store
/._PepperDash.Essentials.4Series.sln
dotnet

3
.gitmodules vendored
View File

@@ -0,0 +1,3 @@
[submodule "essentials-framework/pepperdashcore-builds"]
path = essentials-framework/pepperdashcore-builds
url = https://bitbucket.org/Pepperdash_Products/pepperdashcore-builds.git

View File

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

View File

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

View File

@@ -1,110 +0,0 @@
# Contributors Guide
Essentials is an open source project. If you are interested in making it better,
there are many ways you can contribute. For example, you can:
- Submit a bug report
- Suggest a new feature
- Provide feedback by commenting on feature requests/proposals
- Propose a patch by submitting a pull request
- Suggest or submit documentation improvements
- Review outstanding pull requests
- Answer questions from other users
- Share the software with other users who are interested
- Teach others to use the software
## Bugs and Feature Requests
If you believe that you have found a bug or wish to propose a new feature,
please first search the existing [issues] to see if it has already been
reported. If you are unable to find an existing issue, consider using one of
the provided templates to create a new issue and provide as many details as you
can to assist in reproducing the bug or explaining your proposed feature.
## Patch Submission tips
Patches should be submitted in the form of Pull Requests to the Essentials
[repository] on GitHub. But first, consider the following tips to ensure a
smooth process when submitting a patch:
- Ensure that the patch compiles and does not break any build-time tests.
- Be understanding, patient, and friendly; developers may need time to review
your submissions before they can take action or respond. This does not mean
your contribution is not valued. If your contribution has not received a
response in a reasonable time, consider commenting with a polite inquiry for
an update.
- Limit your patches to the smallest reasonable change to achieve your intended
goal. For example, do not make unnecessary indentation changes; but don't go
out of your way to make the patch so minimal that it isn't easy to read,
either. Consider the reviewer's perspective.
- Before submission, please squash your commits to using a message that starts
with the issue number and a description of the changes.
- Isolate multiple patches from each other. If you wish to make several
independent patches, do so in separate, smaller pull requests that can be
reviewed more easily.
- Be prepared to answer questions from reviewers. They may have further
questions before accepting your patch, and may even propose changes. Please
accept this feedback constructively, and not as a rejection of your proposed
change.
## GitFlow Branch Model
This repository adheres to the [GitFlow](https://nvie.com/posts/a-successful-git-branching-model/) branch model and is intitialized for GitFlow to make for consistent branch name prefixes. Please take time to familiarize yourself with this model.
- `master` will contain the latest stable version of the framework and release builds will be created from tagged commits on `master`.
- HotFix/Patch Pull Requests should target `master` as the base branch.
- All other Pull Requests (bug fixes, enhancements, etc.) should target `development` as the base branch.
- `release/vX.Y.X` branches will be used for release candidates when moving new features from `development` to `master`.
Beta builds will be created from tagged commits on release candidate branches.
## Review
- We welcome code reviews from anyone. A committer is required to formally
accept and merge the changes.
- Reviewers will be looking for things like threading issues, performance
implications, API design, duplication of existing functionality, readability
and code style, avoidance of bloat (scope-creep), etc.
- Reviewers will likely ask questions to better understand your change.
- Reviewers will make comments about changes to your patch:
- MUST means that the change is required
- SHOULD means that the change is suggested, further discussion on the
subject may be required
- COULD means that the change is optional
## Timeline and Managing Expectations
As we continue to engage contributors and learn best practices for running a successful open source project, our processes
and guidance will likely evolve. We will try to communicate expectations as we are able and to always be responsive. We
hope that the community will share their suggestions for improving this engagement. Based on the level of initial interest
we receive and the availability of resources to evaluate contributions, we anticipate the following:
- We will initially prioritize pull requests that include small bug fixes and code that addresses potential vulnerabilities
as well as pull requests that include improvements for processor language specifications because these require a
reasonable amount of effort to evaluate and will help us exercise and revise our process for accepting contributions. In
other words, we are going to start small in order to work out the kinks first.
- We are committed to maintaining the integrity and security of our code base. In addition to the careful review the
maintainers will give to code contributions to make sure they do not introduce new bugs or vulnerabilities, we will be
trying to identify best practices to incorporate with our open source project so that contributors can have more control
over whether their contributions are accepted. These might include things like style guides and requirements for tests and
documentation to accompany some code contributions. As a result, it may take a long time for some contributions to be
accepted. This does not mean we are ignoring them.
- We are committed to integrating this GitHub project with our team's regular development work flow so that the open source
project remains dynamic and relevant. This may affect our responsiveness and ability to accept pull requests
quickly. This does not mean we are ignoring them.
- Not all innovative ideas need to be accepted as pull requests into this GitHub project to be valuable to the community.
There may be times when we recommend that you just share your code for some enhancement to Essentials from your own
repository. As we identify and recognize extensions that are of general interest to Essentials, we
may seek to incorporate them with our baseline.
## Legal
Consistent with Section D.6. of the GitHub Terms of Service as of 2019, and the MIT license, the project maintainer for this project accepts contributions using the inbound=outbound model.
When you submit a pull request to this repository (inbound), you are agreeing to license your contribution under the same terms as specified in [LICENSE] (outbound).
This is an open source project.
Contributions you make to this repository are completely voluntary.
When you submit an issue, bug report, question, enhancement, pull request, etc., you are offering your contribution without expectation of payment, you expressly waive any future pay claims against PepperDash related to your contribution, and you acknowledge that this does not create an obligation on the part of PepperDash of any kind.
Furthermore, your contributing to this project does not create an employer-employee relationship between the PepperDash and the contributor.
[issues]: https://github.com/PepperDash/Essentials/issues
[repository]: https://github.com/PepperDash/Essentials
[LICENSE]: https://github.com/PepperDash/Essentials/blob/master/LICENSE.md

View File

@@ -1,282 +0,0 @@
# Crestron Library Usage Analysis - PepperDash Essentials
This document provides a comprehensive analysis of Crestron classes and interfaces used throughout the PepperDash Essentials framework, organized by namespace and library component.
## Executive Summary
The PepperDash Essentials framework extensively leverages Crestron SDK components across 100+ files, providing abstractions for:
- Control system hardware (processors, touchpanels, IO devices)
- Communication interfaces (Serial, TCP/IP, SSH, CEC, IR)
- Device management and routing
- User interface components and smart objects
- System monitoring and diagnostics
## 1. Core Crestron Libraries
### 1.1 Crestron.SimplSharp
**Primary Usage**: Foundational framework components, collections, and basic types.
**Key Files**:
- Multiple files across all projects use `Crestron.SimplSharp` namespaces
- Provides basic C# runtime support for Crestron processors
### 1.2 Crestron.SimplSharpPro
**Primary Usage**: Main hardware abstraction layer for Crestron devices.
**Key Classes Used**:
#### CrestronControlSystem
- **File**: `/src/PepperDash.Essentials/ControlSystem.cs`
- **Usage**: Base class for the main control system implementation
- **Implementation**: `public class ControlSystem : CrestronControlSystem, ILoadConfig`
#### Device (Base Class)
- **Files**: 50+ files inherit from or use this class
- **Key Implementations**:
- `/src/PepperDash.Core/Device.cs` - Core device abstraction
- `/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs` - Extended device base
- `/src/PepperDash.Essentials.Core/Room/Room.cs` - Room device implementation
- `/src/PepperDash.Essentials.Core/Devices/CrestronProcessor.cs` - Processor device wrapper
#### BasicTriList
- **Files**: 30+ files use this class extensively
- **Primary Usage**: Touchpanel communication and SIMPL bridging
- **Key Files**:
- `/src/PepperDash.Essentials.Core/Touchpanels/TriListExtensions.cs` - Extension methods for signal handling
- `/src/PepperDash.Essentials.Core/Devices/EssentialsBridgeableDevice.cs` - Bridge interface
- `/src/PepperDash.Essentials.Core/Touchpanels/ModalDialog.cs` - UI dialog implementation
#### BasicTriListWithSmartObject
- **Files**: Multiple touchpanel and UI files
- **Usage**: Enhanced touchpanel support with smart object integration
- **Key Files**:
- `/src/PepperDash.Essentials.Core/Touchpanels/Interfaces.cs` - Interface definitions
- `/src/PepperDash.Essentials.Core/SmartObjects/SubpageReferenceList/SubpageReferenceList.cs`
## 2. Communication Hardware
### 2.1 Serial Communication (ComPort)
**Primary Class**: `ComPort`
**Key Files**:
- `/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs`
- `/src/PepperDash.Essentials.Core/Comm and IR/CommFactory.cs`
**Usage Pattern**:
```csharp
public class ComPortController : Device, IBasicCommunicationWithStreamDebugging
public static ComPort GetComPort(EssentialsControlPropertiesConfig config)
```
**Interface Support**: `IComPorts` - Used for devices that provide multiple COM ports
### 2.2 IR Communication (IROutputPort)
**Primary Class**: `IROutputPort`
**Key Files**:
- `/src/PepperDash.Essentials.Core/Devices/IrOutputPortController.cs`
- `/src/PepperDash.Essentials.Core/Devices/GenericIRController.cs`
- `/src/PepperDash.Essentials.Core/Comm and IR/IRPortHelper.cs`
**Usage Pattern**:
```csharp
public class IrOutputPortController : Device
IROutputPort IrPort;
public IrOutputPortController(string key, IROutputPort port, string irDriverFilepath)
```
### 2.3 CEC Communication (ICec)
**Primary Interface**: `ICec`
**Key Files**:
- `/src/PepperDash.Essentials.Core/Comm and IR/CecPortController.cs`
- `/src/PepperDash.Essentials.Core/Comm and IR/CommFactory.cs`
**Usage Pattern**:
```csharp
public class CecPortController : Device, IBasicCommunicationWithStreamDebugging
public static ICec GetCecPort(ControlPropertiesConfig config)
```
## 3. Input/Output Hardware
### 3.1 Digital Input
**Primary Interface**: `IDigitalInput`
**Key Files**:
- `/src/PepperDash.Essentials.Core/CrestronIO/GenericDigitalInputDevice.cs`
- `/src/PepperDash.Essentials.Core/Microphone Privacy/MicrophonePrivacyController.cs`
**Usage Pattern**:
```csharp
public List<IDigitalInput> Inputs { get; private set; }
void AddInput(IDigitalInput input)
```
### 3.2 Versiport Support
**Key Files**:
- `/src/PepperDash.Essentials.Core/CrestronIO/GenericVersiportInputDevice.cs`
- `/src/PepperDash.Essentials.Core/CrestronIO/GenericVersiportAnalogInputDevice.cs`
- `/src/PepperDash.Essentials.Core/CrestronIO/GenericVersiportOutputDevice.cs`
**Usage**: Provides flexible I/O port configuration for various signal types
## 4. Touchpanel Hardware
### 4.1 MPC3 Touchpanel
**Primary Class**: `MPC3Basic`
**Key File**: `/src/PepperDash.Essentials.Core/Touchpanels/Mpc3Touchpanel.cs`
**Usage Pattern**:
```csharp
public class Mpc3TouchpanelController : Device
readonly MPC3Basic _touchpanel;
_touchpanel = processor.ControllerTouchScreenSlotDevice as MPC3Basic;
```
### 4.2 TSW Series Support
**Evidence**: References found in messenger files and mobile control components
**Usage**: Integrated through mobile control messaging system for TSW touchpanel features
## 5. Timer and Threading
### 5.1 CTimer
**Primary Class**: `CTimer`
**Key File**: `/src/PepperDash.Core/PasswordManagement/PasswordManager.cs`
**Usage Pattern**:
```csharp
Debug.Console(1, string.Format("PasswordManager.UpdatePassword: CTimer Started"));
Debug.Console(1, string.Format("PasswordManager.UpdatePassword: CTimer Reset"));
```
## 6. Networking and Communication
### 6.1 Ethernet Communication
**Libraries Used**:
- `Crestron.SimplSharpPro.EthernetCommunication`
- `Crestron.SimplSharp.Net.Utilities.EthernetHelper`
**Key Files**:
- `/src/PepperDash.Core/Comm/GenericTcpIpClient.cs`
- `/src/PepperDash.Core/Comm/GenericTcpIpServer.cs`
- `/src/PepperDash.Core/Comm/GenericSecureTcpIpClient.cs`
- `/src/PepperDash.Core/Comm/GenericSshClient.cs`
- `/src/PepperDash.Core/Comm/GenericUdpServer.cs`
**Usage Pattern**:
```csharp
public class GenericTcpIpClient : Device, ISocketStatusWithStreamDebugging, IAutoReconnect
public class GenericSecureTcpIpClient : Device, ISocketStatusWithStreamDebugging, IAutoReconnect
```
## 7. Device Management Libraries
### 7.1 DeviceSupport
**Library**: `Crestron.SimplSharpPro.DeviceSupport`
**Usage**: Core device support infrastructure used throughout the framework
### 7.2 DM (DigitalMedia)
**Library**: `Crestron.SimplSharpPro.DM`
**Usage**: Digital media routing and switching support
**Evidence**: Found in routing configuration and DM output card references
## 8. User Interface Libraries
### 8.1 UI Components
**Library**: `Crestron.SimplSharpPro.UI`
**Usage**: User interface elements and touchpanel controls
### 8.2 Smart Objects
**Key Files**:
- `/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectDynamicList.cs`
- `/src/PepperDash.Essentials.Core/SmartObjects/SubpageReferenceList/SubpageReferenceList.cs`
**Usage**: Advanced UI components with dynamic content
## 9. System Monitoring and Diagnostics
### 9.1 Diagnostics
**Library**: `Crestron.SimplSharpPro.Diagnostics`
**Usage**: System health monitoring and performance tracking
### 9.2 System Information
**Key Files**:
- `/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs`
**Usage**: Provides system status, Ethernet information, and program details
## 10. Integration Patterns
### 10.1 SIMPL Bridging
**Pattern**: Extensive use of `BasicTriList` for SIMPL integration
**Files**: Bridge classes throughout the framework implement `LinkToApi` methods:
```csharp
public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge);
```
### 10.2 Device Factory Pattern
**Implementation**: Factory classes create hardware-specific implementations
**Example**: `CommFactory.cs` provides communication device creation
### 10.3 Extension Methods
**Pattern**: Extensive use of extension methods for Crestron classes
**Example**: `TriListExtensions.cs` adds 30+ extension methods to `BasicTriList`
## 11. Signal Processing
### 11.1 Signal Types
**Bool Signals**: Digital control and feedback
**UShort Signals**: Analog values and numeric data
**String Signals**: Text and configuration data
**Implementation**: Comprehensive signal handling in `TriListExtensions.cs`
## 12. Error Handling and Logging
**Pattern**: Consistent use of Crestron's Debug logging throughout
**Examples**:
```csharp
Debug.LogMessage(LogEventLevel.Information, "Device {0} is not a valid device", dc.PortDeviceKey);
Debug.LogMessage(LogEventLevel.Debug, "Error Waking Panel. Maybe testing with Xpanel?");
```
## 13. Threading and Synchronization
**Components**:
- CTimer for time-based operations
- Thread-safe collections and patterns
- Event-driven programming models
## Conclusion
The PepperDash Essentials framework demonstrates sophisticated integration with the Crestron ecosystem, leveraging:
- **Core Infrastructure**: CrestronControlSystem, Device base classes
- **Communication**: COM, IR, CEC, TCP/IP, SSH protocols
- **Hardware Abstraction**: Touchpanels, I/O devices, processors
- **User Interface**: Smart objects, signal processing, SIMPL bridging
- **System Services**: Monitoring, diagnostics, device management
This analysis shows that Essentials serves as a comprehensive middleware layer, abstracting Crestron hardware complexities while providing modern software development patterns and practices.
---
*Generated: [Current Date]*
*Framework Version: PepperDash Essentials (Based on codebase analysis)*

Binary file not shown.

Binary file not shown.

View File

@@ -1,7 +0,0 @@
Copyright (c) <2020> PepperDash Technology Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,97 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33213.308
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PepperDash.Essentials.Devices.Common", "src\PepperDash.Essentials.Devices.Common\PepperDash.Essentials.Devices.Common.csproj", "{53E204B7-97DD-441D-A96C-721DF014DF82}"
ProjectSection(ProjectDependencies) = postProject
{E5336563-1194-501E-BC4A-79AD9283EF90} = {E5336563-1194-501E-BC4A-79AD9283EF90}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PepperDash.Essentials", "src\PepperDash.Essentials\PepperDash.Essentials.csproj", "{CB3B11BA-625C-4D35-B663-FDC5BE9A230E}"
ProjectSection(ProjectDependencies) = postProject
{E5336563-1194-501E-BC4A-79AD9283EF90} = {E5336563-1194-501E-BC4A-79AD9283EF90}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PepperDash.Essentials.Core", "src\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj", "{3D192FED-8FFC-4CB5-B5F7-BA307ABA254B}"
ProjectSection(ProjectDependencies) = postProject
{E5336563-1194-501E-BC4A-79AD9283EF90} = {E5336563-1194-501E-BC4A-79AD9283EF90}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mobile Control", "Mobile Control", "{B24989D7-32B5-48D5-9AE1-5F3B17D25206}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PepperDash.Essentials.MobileControl", "src\PepperDash.Essentials.MobileControl\PepperDash.Essentials.MobileControl.csproj", "{F6D362DE-2256-44B1-927A-8CE4705D839A}"
ProjectSection(ProjectDependencies) = postProject
{E5336563-1194-501E-BC4A-79AD9283EF90} = {E5336563-1194-501E-BC4A-79AD9283EF90}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PepperDash.Essentials.MobileControl.Messengers", "src\PepperDash.Essentials.MobileControl.Messengers\PepperDash.Essentials.MobileControl.Messengers.csproj", "{B438694F-8FF7-464A-9EC8-10427374471F}"
ProjectSection(ProjectDependencies) = postProject
{E5336563-1194-501E-BC4A-79AD9283EF90} = {E5336563-1194-501E-BC4A-79AD9283EF90}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Essentials", "Essentials", "{AD98B742-8D85-481C-A69D-D8D8ABED39EA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PepperDash.Core", "src\PepperDash.Core\PepperDash.Core.csproj", "{E5336563-1194-501E-BC4A-79AD9283EF90}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug 4.7.2|Any CPU = Debug 4.7.2|Any CPU
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{53E204B7-97DD-441D-A96C-721DF014DF82}.Debug 4.7.2|Any CPU.ActiveCfg = Debug 4.7.2|Any CPU
{53E204B7-97DD-441D-A96C-721DF014DF82}.Debug 4.7.2|Any CPU.Build.0 = Debug 4.7.2|Any CPU
{53E204B7-97DD-441D-A96C-721DF014DF82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53E204B7-97DD-441D-A96C-721DF014DF82}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53E204B7-97DD-441D-A96C-721DF014DF82}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53E204B7-97DD-441D-A96C-721DF014DF82}.Release|Any CPU.Build.0 = Release|Any CPU
{CB3B11BA-625C-4D35-B663-FDC5BE9A230E}.Debug 4.7.2|Any CPU.ActiveCfg = Debug 4.7.2|Any CPU
{CB3B11BA-625C-4D35-B663-FDC5BE9A230E}.Debug 4.7.2|Any CPU.Build.0 = Debug 4.7.2|Any CPU
{CB3B11BA-625C-4D35-B663-FDC5BE9A230E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CB3B11BA-625C-4D35-B663-FDC5BE9A230E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CB3B11BA-625C-4D35-B663-FDC5BE9A230E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CB3B11BA-625C-4D35-B663-FDC5BE9A230E}.Release|Any CPU.Build.0 = Release|Any CPU
{3D192FED-8FFC-4CB5-B5F7-BA307ABA254B}.Debug 4.7.2|Any CPU.ActiveCfg = Debug 4.7.2|Any CPU
{3D192FED-8FFC-4CB5-B5F7-BA307ABA254B}.Debug 4.7.2|Any CPU.Build.0 = Debug 4.7.2|Any CPU
{3D192FED-8FFC-4CB5-B5F7-BA307ABA254B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3D192FED-8FFC-4CB5-B5F7-BA307ABA254B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3D192FED-8FFC-4CB5-B5F7-BA307ABA254B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3D192FED-8FFC-4CB5-B5F7-BA307ABA254B}.Release|Any CPU.Build.0 = Release|Any CPU
{F6D362DE-2256-44B1-927A-8CE4705D839A}.Debug 4.7.2|Any CPU.ActiveCfg = Debug|Any CPU
{F6D362DE-2256-44B1-927A-8CE4705D839A}.Debug 4.7.2|Any CPU.Build.0 = Debug|Any CPU
{F6D362DE-2256-44B1-927A-8CE4705D839A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F6D362DE-2256-44B1-927A-8CE4705D839A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F6D362DE-2256-44B1-927A-8CE4705D839A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F6D362DE-2256-44B1-927A-8CE4705D839A}.Release|Any CPU.Build.0 = Release|Any CPU
{B438694F-8FF7-464A-9EC8-10427374471F}.Debug 4.7.2|Any CPU.ActiveCfg = Debug|Any CPU
{B438694F-8FF7-464A-9EC8-10427374471F}.Debug 4.7.2|Any CPU.Build.0 = Debug|Any CPU
{B438694F-8FF7-464A-9EC8-10427374471F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B438694F-8FF7-464A-9EC8-10427374471F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B438694F-8FF7-464A-9EC8-10427374471F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B438694F-8FF7-464A-9EC8-10427374471F}.Release|Any CPU.Build.0 = Release|Any CPU
{E5336563-1194-501E-BC4A-79AD9283EF90}.Debug 4.7.2|Any CPU.ActiveCfg = Debug|Any CPU
{E5336563-1194-501E-BC4A-79AD9283EF90}.Debug 4.7.2|Any CPU.Build.0 = Debug|Any CPU
{E5336563-1194-501E-BC4A-79AD9283EF90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5336563-1194-501E-BC4A-79AD9283EF90}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5336563-1194-501E-BC4A-79AD9283EF90}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5336563-1194-501E-BC4A-79AD9283EF90}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{53E204B7-97DD-441D-A96C-721DF014DF82} = {AD98B742-8D85-481C-A69D-D8D8ABED39EA}
{CB3B11BA-625C-4D35-B663-FDC5BE9A230E} = {AD98B742-8D85-481C-A69D-D8D8ABED39EA}
{3D192FED-8FFC-4CB5-B5F7-BA307ABA254B} = {AD98B742-8D85-481C-A69D-D8D8ABED39EA}
{F6D362DE-2256-44B1-927A-8CE4705D839A} = {B24989D7-32B5-48D5-9AE1-5F3B17D25206}
{B438694F-8FF7-464A-9EC8-10427374471F} = {B24989D7-32B5-48D5-9AE1-5F3B17D25206}
{E5336563-1194-501E-BC4A-79AD9283EF90} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6907A4BF-7201-47CF-AAB1-3597F3B8E1C3}
EndGlobalSection
EndGlobal

49
PepperDashEssentials.sln Normal file
View File

@@ -0,0 +1,49 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PepperDashEssentials", ".\PepperDashEssentials\PepperDashEssentials.csproj", "{1BED5BA9-88C4-4365-9362-6F4B128071D3}"
ProjectSection(ProjectDependencies) = postProject
{892B761C-E479-44CE-BD74-243E9214AF13} = {892B761C-E479-44CE-BD74-243E9214AF13}
{9199CE8A-0C9F-4952-8672-3EED798B284F} = {9199CE8A-0C9F-4952-8672-3EED798B284F}
{A49AD6C8-FC0A-4CC0-9089-DFB4CF92D2B5} = {A49AD6C8-FC0A-4CC0-9089-DFB4CF92D2B5}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PepperDash_Essentials_Core", ".\essentials-framework\Essentials Core\PepperDashEssentialsBase\PepperDash_Essentials_Core.csproj", "{A49AD6C8-FC0A-4CC0-9089-DFB4CF92D2B5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Essentials Devices Common", ".\essentials-framework\Essentials Devices Common\Essentials Devices Common\Essentials Devices Common.csproj", "{892B761C-E479-44CE-BD74-243E9214AF13}"
ProjectSection(ProjectDependencies) = postProject
{A49AD6C8-FC0A-4CC0-9089-DFB4CF92D2B5} = {A49AD6C8-FC0A-4CC0-9089-DFB4CF92D2B5}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Essentials_DM", ".\essentials-framework\Essentials DM\Essentials_DM\Essentials_DM.csproj", "{9199CE8A-0C9F-4952-8672-3EED798B284F}"
ProjectSection(ProjectDependencies) = postProject
{A49AD6C8-FC0A-4CC0-9089-DFB4CF92D2B5} = {A49AD6C8-FC0A-4CC0-9089-DFB4CF92D2B5}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1BED5BA9-88C4-4365-9362-6F4B128071D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1BED5BA9-88C4-4365-9362-6F4B128071D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1BED5BA9-88C4-4365-9362-6F4B128071D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1BED5BA9-88C4-4365-9362-6F4B128071D3}.Release|Any CPU.Build.0 = Release|Any CPU
{A49AD6C8-FC0A-4CC0-9089-DFB4CF92D2B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A49AD6C8-FC0A-4CC0-9089-DFB4CF92D2B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A49AD6C8-FC0A-4CC0-9089-DFB4CF92D2B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A49AD6C8-FC0A-4CC0-9089-DFB4CF92D2B5}.Release|Any CPU.Build.0 = Release|Any CPU
{892B761C-E479-44CE-BD74-243E9214AF13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{892B761C-E479-44CE-BD74-243E9214AF13}.Debug|Any CPU.Build.0 = Debug|Any CPU
{892B761C-E479-44CE-BD74-243E9214AF13}.Release|Any CPU.ActiveCfg = Release|Any CPU
{892B761C-E479-44CE-BD74-243E9214AF13}.Release|Any CPU.Build.0 = Release|Any CPU
{9199CE8A-0C9F-4952-8672-3EED798B284F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9199CE8A-0C9F-4952-8672-3EED798B284F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9199CE8A-0C9F-4952-8672-3EED798B284F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9199CE8A-0C9F-4952-8672-3EED798B284F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public static class IChannelExtensions
{
public static void LinkActions(this IChannel dev, MobileControlSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.AddAction(prefix + "chanUp", new PressAndHoldAction(dev.ChannelUp));
controller.AddAction(prefix + "chanDown", new PressAndHoldAction(dev.ChannelDown));
controller.AddAction(prefix + "lastChan", new PressAndHoldAction(dev.LastChannel));
controller.AddAction(prefix + "guide", new PressAndHoldAction(dev.Guide));
controller.AddAction(prefix + "info", new PressAndHoldAction(dev.Info));
controller.AddAction(prefix + "exit", new PressAndHoldAction(dev.Exit));
}
public static void UnlinkActions(this IChannel dev, MobileControlSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.RemoveAction(prefix + "chanUp");
controller.RemoveAction(prefix + "chanDown");
controller.RemoveAction(prefix + "lastChan");
controller.RemoveAction(prefix + "guide");
controller.RemoveAction(prefix + "info");
controller.RemoveAction(prefix + "exit");
}
}
}

View File

@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public static class IColorExtensions
{
public static void LinkActions(this IColor dev, MobileControlSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.AddAction(prefix + "red", new PressAndHoldAction(dev.Red));
controller.AddAction(prefix + "green", new PressAndHoldAction(dev.Green));
controller.AddAction(prefix + "yellow", new PressAndHoldAction(dev.Yellow));
controller.AddAction(prefix + "blue", new PressAndHoldAction(dev.Blue));
}
public static void UnlinkActions(this IColor dev, MobileControlSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.RemoveAction(prefix + "red");
controller.RemoveAction(prefix + "green");
controller.RemoveAction(prefix + "yellow");
controller.RemoveAction(prefix + "blue");
}
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public static class IDPadExtensions
{
public static void LinkActions(this IDPad dev, MobileControlSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.AddAction(prefix + "up", new PressAndHoldAction(dev.Up));
controller.AddAction(prefix + "down", new PressAndHoldAction(dev.Down));
controller.AddAction(prefix + "left", new PressAndHoldAction(dev.Left));
controller.AddAction(prefix + "right", new PressAndHoldAction(dev.Right));
controller.AddAction(prefix + "select", new PressAndHoldAction(dev.Select));
controller.AddAction(prefix + "menu", new PressAndHoldAction(dev.Menu));
controller.AddAction(prefix + "exit", new PressAndHoldAction(dev.Exit));
}
public static void UnlinkActions(this IDPad dev, MobileControlSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.RemoveAction(prefix + "up");
controller.RemoveAction(prefix + "down");
controller.RemoveAction(prefix + "left");
controller.RemoveAction(prefix + "right");
controller.RemoveAction(prefix + "select");
controller.RemoveAction(prefix + "menu");
controller.RemoveAction(prefix + "exit");
}
}
}

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public static class IDvrExtensions
{
public static void LinkActions(this IDvr dev, MobileControlSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.AddAction(prefix + "dvrlist", new PressAndHoldAction(dev.DvrList));
controller.AddAction(prefix + "record", new PressAndHoldAction(dev.Record));
}
public static void UnlinkActions(this IDvr dev, MobileControlSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.RemoveAction(prefix + "dvrlist");
controller.RemoveAction(prefix + "record");
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public static class INumericExtensions
{
public static void LinkActions(this INumericKeypad dev, MobileControlSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.AddAction(prefix + "num0", new PressAndHoldAction(dev.Digit0));
controller.AddAction(prefix + "num1", new PressAndHoldAction(dev.Digit1));
controller.AddAction(prefix + "num2", new PressAndHoldAction(dev.Digit2));
controller.AddAction(prefix + "num3", new PressAndHoldAction(dev.Digit3));
controller.AddAction(prefix + "num4", new PressAndHoldAction(dev.Digit4));
controller.AddAction(prefix + "num5", new PressAndHoldAction(dev.Digit5));
controller.AddAction(prefix + "num6", new PressAndHoldAction(dev.Digit6));
controller.AddAction(prefix + "num7", new PressAndHoldAction(dev.Digit0));
controller.AddAction(prefix + "num8", new PressAndHoldAction(dev.Digit0));
controller.AddAction(prefix + "num9", new PressAndHoldAction(dev.Digit0));
controller.AddAction(prefix + "numDash", new PressAndHoldAction(dev.KeypadAccessoryButton1));
controller.AddAction(prefix + "numEnter", new PressAndHoldAction(dev.KeypadAccessoryButton2));
// Deal with the Accessory functions on the numpad later
}
public static void UnlinkActions(this INumericKeypad dev, MobileControlSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.RemoveAction(prefix + "num0");
controller.RemoveAction(prefix + "num1");
controller.RemoveAction(prefix + "num2");
controller.RemoveAction(prefix + "num3");
controller.RemoveAction(prefix + "num4");
controller.RemoveAction(prefix + "num5");
controller.RemoveAction(prefix + "num6");
controller.RemoveAction(prefix + "num7");
controller.RemoveAction(prefix + "num8");
controller.RemoveAction(prefix + "num9");
controller.RemoveAction(prefix + "numDash");
controller.RemoveAction(prefix + "numEnter");
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public static class IPowerExtensions
{
public static void LinkActions(this IPower dev, MobileControlSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.AddAction(prefix + "powerOn", new Action(dev.PowerOn));
controller.AddAction(prefix + "powerOff", new Action(dev.PowerOff));
controller.AddAction(prefix + "powerToggle", new Action(dev.PowerToggle));
}
public static void UnlinkActions(this IPower dev, MobileControlSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.RemoveAction(prefix + "powerOn");
controller.RemoveAction(prefix + "powerOff");
controller.RemoveAction(prefix + "powerToggle");
}
}
}

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public static class ISetTopBoxControlsExtensions
{
public static void LinkActions(this ISetTopBoxControls dev, MobileControlSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.AddAction(prefix + "dvrList", new PressAndHoldAction(dev.DvrList));
controller.AddAction(prefix + "replay", new PressAndHoldAction(dev.Replay));
}
public static void UnlinkActions(this ISetTopBoxControls dev, MobileControlSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.RemoveAction(prefix + "dvrList");
controller.RemoveAction(prefix + "replay");
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public static class ITransportExtensions
{
public static void LinkActions(this ITransport dev, MobileControlSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.AddAction(prefix + "play", new PressAndHoldAction(dev.Play));
controller.AddAction(prefix + "pause", new PressAndHoldAction(dev.Pause));
controller.AddAction(prefix + "stop", new PressAndHoldAction(dev.Stop));
controller.AddAction(prefix + "prevTrack", new PressAndHoldAction(dev.ChapPlus));
controller.AddAction(prefix + "nextTrack", new PressAndHoldAction(dev.ChapMinus));
controller.AddAction(prefix + "rewind", new PressAndHoldAction(dev.Rewind));
controller.AddAction(prefix + "ffwd", new PressAndHoldAction(dev.FFwd));
controller.AddAction(prefix + "record", new PressAndHoldAction(dev.Record));
}
public static void UnlinkActions(this ITransport dev, MobileControlSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.RemoveAction(prefix + "play");
controller.RemoveAction(prefix + "pause");
controller.RemoveAction(prefix + "stop");
controller.RemoveAction(prefix + "prevTrack");
controller.RemoveAction(prefix + "nextTrack");
controller.RemoveAction(prefix + "rewind");
controller.RemoveAction(prefix + "ffwd");
controller.RemoveAction(prefix + "record");
}
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
/// <summary>
/// Represents a room whose configuration is derived from runtime data,
/// perhaps from another program, and that the data may not be fully
/// available at startup.
/// </summary>
public interface IDelayedConfiguration
{
event EventHandler<EventArgs> ConfigurationIsReady;
}
}

View File

@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.AudioCodec;
namespace PepperDash.Essentials.AppServer.Messengers
{
/// <summary>
/// Provides a messaging bridge for an AudioCodecBase device
/// </summary>
public class AudioCodecBaseMessenger : MessengerBase
{
/// <summary>
/// Device being bridged
/// </summary>
public AudioCodecBase Codec { get; set; }
/// <summary>
/// Constuctor
/// </summary>
/// <param name="key"></param>
/// <param name="codec"></param>
/// <param name="messagePath"></param>
public AudioCodecBaseMessenger(string key, AudioCodecBase codec, string messagePath)
: base(key, messagePath)
{
if (codec == null)
throw new ArgumentNullException("codec");
Codec = codec;
codec.CallStatusChange += new EventHandler<CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
}
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
{
appServerController.AddAction(MessagePath + "/fullStatus", new Action(SendAtcFullMessageObject));
appServerController.AddAction(MessagePath + "/dial", new Action<string>(s => Codec.Dial(s)));
appServerController.AddAction(MessagePath + "/endCallById", new Action<string>(s =>
{
var call = GetCallWithId(s);
if (call != null)
Codec.EndCall(call);
}));
appServerController.AddAction(MessagePath + "/endAllCalls", new Action(Codec.EndAllCalls));
appServerController.AddAction(MessagePath + "/dtmf", new Action<string>(s => Codec.SendDtmf(s)));
appServerController.AddAction(MessagePath + "/rejectById", new Action<string>(s =>
{
var call = GetCallWithId(s);
if (call != null)
Codec.RejectCall(call);
}));
appServerController.AddAction(MessagePath + "/acceptById", new Action<string>(s =>
{
var call = GetCallWithId(s);
if (call != null)
Codec.AcceptCall(call);
}));
}
/// <summary>
/// Helper to grab a call with string ID
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
CodecActiveCallItem GetCallWithId(string id)
{
return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id);
}
void codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
{
SendAtcFullMessageObject();
}
/// <summary>
/// Helper method to build call status for vtc
/// </summary>
/// <returns></returns>
void SendAtcFullMessageObject()
{
var info = Codec.CodecInfo;
PostStatusMessage(new
{
isInCall = Codec.IsInCall,
calls = Codec.ActiveCalls,
info = new
{
phoneNumber = info.PhoneNumber
}
});
}
}
}

View File

@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.AppServer.Messengers
{
/// <summary>
/// Handles interactions with the app server to update the config
/// </summary>
public class ConfigMessenger : MessengerBase
{
public ConfigMessenger(string key, string messagePath)
: base(key, messagePath)
{
ConfigUpdater.ConfigStatusChanged -= ConfigUpdater_ConfigStatusChanged;
ConfigUpdater.ConfigStatusChanged += new EventHandler<ConfigStatusEventArgs>(ConfigUpdater_ConfigStatusChanged);
}
void ConfigUpdater_ConfigStatusChanged(object sender, ConfigStatusEventArgs e)
{
PostUpdateStatus(e.UpdateStatus.ToString());
}
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
{
appServerController.AddAction(MessagePath + "/updateConfig", new Action<string>(s => GetConfigFile(s)));
}
/// <summary>
/// Generates or passes the URL to make the request to GET the config from a server
/// </summary>
/// <param name="url"></param>
void GetConfigFile(string url)
{
try
{
// Attempt to parse the URL
var parser = new Crestron.SimplSharp.Net.Http.UrlParser(url);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Successfully parsed URL from AppServer message: {0}", parser.Url);
}
catch (Exception e)
{
// If unable to parse the URL, generate it from config data
Debug.Console(2, "Error parsing URL: {0}", e);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Unable to parse URL from AppServer message. Generating URL from config data");
url = string.Format("http://{0}/api/system/{1}/config", AppServerController.Config.ServerUrl, AppServerController.SystemUuid);
}
ConfigUpdater.GetConfigFromServer(url);
}
/// <summary>
/// Posts a message with the current status of the config update
/// </summary>
/// <param name="status"></param>
void PostUpdateStatus(string status)
{
PostStatusMessage(new
{
updateStatus = status
});
}
}
}

View File

@@ -0,0 +1,216 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.EthernetCommunication;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.Codec;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class Ddvc01AtcMessenger : MessengerBase
{
BasicTriList EISC;
/// <summary>
/// 221
/// </summary>
const uint BDialHangupOnHook = 221;
/// <summary>
/// 251
/// </summary>
const uint BIncomingAnswer = 251;
/// <summary>
/// 252
/// </summary>
const uint BIncomingReject = 252;
/// <summary>
/// 241
/// </summary>
const uint BSpeedDial1 = 241;
/// <summary>
/// 242
/// </summary>
const uint BSpeedDial2 = 242;
/// <summary>
/// 243
/// </summary>
const uint BSpeedDial3 = 243;
/// <summary>
/// 244
/// </summary>
const uint BSpeedDial4 = 244;
/// <summary>
/// 201
/// </summary>
const uint SCurrentDialString = 201;
/// <summary>
/// 211
/// </summary>
const uint SCurrentCallNumber = 211;
/// <summary>
/// 212
/// </summary>
const uint SCurrentCallName = 212;
/// <summary>
/// 221
/// </summary>
const uint SHookState = 221;
/// <summary>
/// 222
/// </summary>
const uint SCallDirection = 222;
/// <summary>
/// 201-212 0-9*#
/// </summary>
Dictionary<string, uint> DTMFMap = new Dictionary<string, uint>
{
{ "1", 201 },
{ "2", 202 },
{ "3", 203 },
{ "4", 204 },
{ "5", 205 },
{ "6", 206 },
{ "7", 207 },
{ "8", 208 },
{ "9", 209 },
{ "0", 210 },
{ "*", 211 },
{ "#", 212 },
};
/// <summary>
///
/// </summary>
CodecActiveCallItem CurrentCallItem;
/// <summary>
///
/// </summary>
/// <param name="eisc"></param>
/// <param name="messagePath"></param>
public Ddvc01AtcMessenger(string key, BasicTriList eisc, string messagePath)
: base(key, messagePath)
{
EISC = eisc;
CurrentCallItem = new CodecActiveCallItem();
CurrentCallItem.Type = eCodecCallType.Audio;
CurrentCallItem.Id = "-audio-";
}
/// <summary>
///
/// </summary>
void SendFullStatus()
{
this.PostStatusMessage(new
{
calls = GetCurrentCallList(),
currentCallString = EISC.GetString(SCurrentCallNumber),
currentDialString = EISC.GetString(SCurrentDialString),
isInCall = EISC.GetString(SHookState) == "Connected"
});
}
/// <summary>
///
/// </summary>
/// <param name="appServerController"></param>
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
{
//EISC.SetStringSigAction(SCurrentDialString, s => PostStatusMessage(new { currentDialString = s }));
EISC.SetStringSigAction(SHookState, s =>
{
CurrentCallItem.Status = (eCodecCallStatus)Enum.Parse(typeof(eCodecCallStatus), s, true);
//GetCurrentCallList();
SendFullStatus();
});
EISC.SetStringSigAction(SCurrentCallNumber, s =>
{
CurrentCallItem.Number = s;
SendCallsList();
});
EISC.SetStringSigAction(SCurrentCallName, s =>
{
CurrentCallItem.Name = s;
SendCallsList();
});
EISC.SetStringSigAction(SCallDirection, s =>
{
CurrentCallItem.Direction = (eCodecCallDirection)Enum.Parse(typeof(eCodecCallDirection), s, true);
SendCallsList();
});
// Add press and holds using helper
Action<string, uint> addPHAction = (s, u) =>
AppServerController.AddAction(MessagePath + s, new PressAndHoldAction(b => EISC.SetBool(u, b)));
// Add straight pulse calls
Action<string, uint> addAction = (s, u) =>
AppServerController.AddAction(MessagePath + s, new Action(() => EISC.PulseBool(u, 100)));
addAction("/endCallById", BDialHangupOnHook);
addAction("/endAllCalls", BDialHangupOnHook);
addAction("/acceptById", BIncomingAnswer);
addAction("/rejectById", BIncomingReject);
addAction("/speedDial1", BSpeedDial1);
addAction("/speedDial2", BSpeedDial2);
addAction("/speedDial3", BSpeedDial3);
addAction("/speedDial4", BSpeedDial4);
// Get status
AppServerController.AddAction(MessagePath + "/fullStatus", new Action(SendFullStatus));
// Dial on string
AppServerController.AddAction(MessagePath + "/dial", new Action<string>(s => EISC.SetString(SCurrentDialString, s)));
// Pulse DTMF
AppServerController.AddAction(MessagePath + "/dtmf", new Action<string>(s =>
{
if (DTMFMap.ContainsKey(s))
{
EISC.PulseBool(DTMFMap[s], 100);
}
}));
}
/// <summary>
///
/// </summary>
void SendCallsList()
{
PostStatusMessage(new
{
calls = GetCurrentCallList(),
});
}
/// <summary>
/// Turns the
/// </summary>
/// <returns></returns>
List<CodecActiveCallItem> GetCurrentCallList()
{
if (CurrentCallItem.Status == eCodecCallStatus.Disconnected)
{
return new List<CodecActiveCallItem>();
}
else
{
return new List<CodecActiveCallItem>() { CurrentCallItem };
}
}
}
}

View File

@@ -0,0 +1,648 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.EthernetCommunication;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.Codec;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class Ddvc01VtcMessenger : MessengerBase
{
BasicTriList EISC;
/********* Bools *********/
/// <summary>
/// 724
/// </summary>
const uint BDialHangup = 724;
/// <summary>
/// 750
/// </summary>
const uint BCallIncoming = 750;
/// <summary>
/// 751
/// </summary>
const uint BIncomingAnswer = 751;
/// <summary>
/// 752
/// </summary>
const uint BIncomingReject = 752;
/// <summary>
/// 741
/// </summary>
const uint BSpeedDial1 = 741;
/// <summary>
/// 742
/// </summary>
const uint BSpeedDial2 = 742;
/// <summary>
/// 743
/// </summary>
const uint BSpeedDial3 = 743;
/// <summary>
/// 744
/// </summary>
const uint BSpeedDial4 = 744;
/// <summary>
/// 800
/// </summary>
const uint BDirectorySearchBusy = 800;
/// <summary>
/// 801
/// </summary>
const uint BDirectoryLineSelected = 801;
/// <summary>
/// 801 when selected entry is a contact
/// </summary>
const uint BDirectoryEntryIsContact = 801;
/// <summary>
/// 802 To show/hide back button
/// </summary>
const uint BDirectoryIsRoot = 802;
/// <summary>
/// 803 Pulse from system to inform us when directory is ready
/// </summary>
const uint DDirectoryHasChanged = 803;
/// <summary>
/// 804
/// </summary>
const uint BDirectoryRoot = 804;
/// <summary>
/// 805
/// </summary>
const uint BDirectoryFolderBack = 805;
/// <summary>
/// 806
/// </summary>
const uint BDirectoryDialSelectedLine = 806;
/// <summary>
/// 811
/// </summary>
const uint BCameraControlUp = 811;
/// <summary>
/// 812
/// </summary>
const uint BCameraControlDown = 812;
/// <summary>
/// 813
/// </summary>
const uint BCameraControlLeft = 813;
/// <summary>
/// 814
/// </summary>
const uint BCameraControlRight = 814;
/// <summary>
/// 815
/// </summary>
const uint BCameraControlZoomIn = 815;
/// <summary>
/// 816
/// </summary>
const uint BCameraControlZoomOut = 816;
/// <summary>
/// 821 - 826
/// </summary>
const uint BCameraPresetStart = 821;
/// <summary>
/// 831
/// </summary>
const uint BCameraModeAuto = 831;
/// <summary>
/// 832
/// </summary>
const uint BCameraModeManual = 832;
/// <summary>
/// 833
/// </summary>
const uint BCameraModeOff = 833;
/// <summary>
/// 841
/// </summary>
const uint BCameraSelfView = 841;
/// <summary>
/// 842
/// </summary>
const uint BCameraLayout = 842;
/// <summary>
/// 843
/// </summary>
const uint BCameraSupportsAutoMode = 843;
/// <summary>
/// 844
/// </summary>
const uint BCameraSupportsOffMode = 844;
/********* Ushorts *********/
/// <summary>
/// 760
/// </summary>
const uint UCameraNumberSelect = 760;
/// <summary>
/// 801
/// </summary>
const uint UDirectorySelectRow = 801;
/// <summary>
/// 801
/// </summary>
const uint UDirectoryRowCount = 801;
/********* Strings *********/
/// <summary>
/// 701
/// </summary>
const uint SCurrentDialString = 701;
/// <summary>
/// 702
/// </summary>
const uint SCurrentCallName = 702;
/// <summary>
/// 703
/// </summary>
const uint SCurrentCallNumber = 703;
/// <summary>
/// 731
/// </summary>
const uint SHookState = 731;
/// <summary>
/// 722
/// </summary>
const uint SCallDirection = 722;
/// <summary>
/// 751
/// </summary>
const uint SIncomingCallName = 751;
/// <summary>
/// 752
/// </summary>
const uint SIncomingCallNumber = 752;
/// <summary>
/// 800
/// </summary>
const uint SDirectorySearchString = 800;
/// <summary>
/// 801-1055
/// </summary>
const uint SDirectoryEntriesStart = 801;
/// <summary>
/// 1056
/// </summary>
const uint SDirectoryEntrySelectedName = 1056;
/// <summary>
/// 1057
/// </summary>
const uint SDirectoryEntrySelectedNumber = 1057;
/// <summary>
/// 1058
/// </summary>
const uint SDirectorySelectedFolderName = 1058;
/// <summary>
/// 701-712 0-9*#
/// </summary>
Dictionary<string, uint> DTMFMap = new Dictionary<string, uint>
{
{ "1", 701 },
{ "2", 702 },
{ "3", 703 },
{ "4", 704 },
{ "5", 705 },
{ "6", 706 },
{ "7", 707 },
{ "8", 708 },
{ "9", 709 },
{ "0", 710 },
{ "*", 711 },
{ "#", 712 },
};
CodecActiveCallItem CurrentCallItem;
CodecActiveCallItem IncomingCallItem;
ushort PreviousDirectoryLength = 0;
/// <summary>
///
/// </summary>
/// <param name="eisc"></param>
/// <param name="messagePath"></param>
public Ddvc01VtcMessenger(string key, BasicTriList eisc, string messagePath)
: base(key, messagePath)
{
EISC = eisc;
CurrentCallItem = new CodecActiveCallItem();
CurrentCallItem.Type = eCodecCallType.Video;
CurrentCallItem.Id = "-video-";
}
/// <summary>
///
/// </summary>
/// <param name="appServerController"></param>
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
{
var asc = appServerController;
EISC.SetStringSigAction(SHookState, s =>
{
CurrentCallItem.Status = (eCodecCallStatus)Enum.Parse(typeof(eCodecCallStatus), s, true);
PostFullStatus(); // SendCallsList();
});
EISC.SetStringSigAction(SCurrentCallNumber, s =>
{
CurrentCallItem.Number = s;
PostCallsList();
});
EISC.SetStringSigAction(SCurrentCallName, s =>
{
CurrentCallItem.Name = s;
PostCallsList();
});
EISC.SetStringSigAction(SCallDirection, s =>
{
CurrentCallItem.Direction = (eCodecCallDirection)Enum.Parse(typeof(eCodecCallDirection), s, true);
PostCallsList();
});
EISC.SetBoolSigAction(BCallIncoming, b =>
{
if (b)
{
var ica = new CodecActiveCallItem()
{
Direction = eCodecCallDirection.Incoming,
Id = "-video-incoming",
Name = EISC.GetString(SIncomingCallName),
Number = EISC.GetString(SIncomingCallNumber),
Status = eCodecCallStatus.Ringing,
Type = eCodecCallType.Video
};
IncomingCallItem = ica;
}
else
{
IncomingCallItem = null;
}
PostCallsList();
});
EISC.SetBoolSigAction(BCameraSupportsAutoMode, b =>
{
PostStatusMessage(new
{
cameraSupportsAutoMode = b
});
});
EISC.SetBoolSigAction(BCameraSupportsOffMode, b =>
{
PostStatusMessage(new
{
cameraSupportsOffMode = b
});
});
// Directory insanity
EISC.SetUShortSigAction(UDirectoryRowCount, u =>
{
// The length of the list comes in before the list does.
// Splice the sig change operation onto the last string sig that will be changing
// when the directory entries make it through.
if (PreviousDirectoryLength > 0)
{
EISC.ClearStringSigAction(SDirectoryEntriesStart + PreviousDirectoryLength - 1);
}
EISC.SetStringSigAction(SDirectoryEntriesStart + u - 1, s => PostDirectory());
PreviousDirectoryLength = u;
});
EISC.SetStringSigAction(SDirectoryEntrySelectedName, s =>
{
PostStatusMessage(new
{
directoryContactSelected = new
{
name = EISC.GetString(SDirectoryEntrySelectedName),
}
});
});
EISC.SetStringSigAction(SDirectoryEntrySelectedNumber, s =>
{
PostStatusMessage(new
{
directoryContactSelected = new
{
number = EISC.GetString(SDirectoryEntrySelectedNumber),
}
});
});
EISC.SetStringSigAction(SDirectorySelectedFolderName, s => PostStatusMessage(new
{
directorySelectedFolderName = EISC.GetString(SDirectorySelectedFolderName)
}));
EISC.SetSigTrueAction(BCameraModeAuto, () => PostCameraMode());
EISC.SetSigTrueAction(BCameraModeManual, () => PostCameraMode());
EISC.SetSigTrueAction(BCameraModeOff, () => PostCameraMode());
EISC.SetBoolSigAction(BCameraSelfView, b => PostStatusMessage(new
{
cameraSelfView = b
}));
EISC.SetUShortSigAction(UCameraNumberSelect, (u) => PostSelectedCamera());
// Add press and holds using helper action
Action<string, uint> addPHAction = (s, u) =>
AppServerController.AddAction(MessagePath + s, new PressAndHoldAction(b => EISC.SetBool(u, b)));
addPHAction("/cameraUp", BCameraControlUp);
addPHAction("/cameraDown", BCameraControlDown);
addPHAction("/cameraLeft", BCameraControlLeft);
addPHAction("/cameraRight", BCameraControlRight);
addPHAction("/cameraZoomIn", BCameraControlZoomIn);
addPHAction("/cameraZoomOut", BCameraControlZoomOut);
// Add straight pulse calls using helper action
Action<string, uint> addAction = (s, u) =>
AppServerController.AddAction(MessagePath + s, new Action(() => EISC.PulseBool(u, 100)));
addAction("/endCallById", BDialHangup);
addAction("/endAllCalls", BDialHangup);
addAction("/acceptById", BIncomingAnswer);
addAction("/rejectById", BIncomingReject);
addAction("/speedDial1", BSpeedDial1);
addAction("/speedDial2", BSpeedDial2);
addAction("/speedDial3", BSpeedDial3);
addAction("/speedDial4", BSpeedDial4);
addAction("/cameraModeAuto", BCameraModeAuto);
addAction("/cameraModeManual", BCameraModeManual);
addAction("/cameraModeOff", BCameraModeOff);
addAction("/cameraSelfView", BCameraSelfView);
addAction("/cameraLayout", BCameraLayout);
asc.AddAction("/cameraSelect", new Action<string>(SelectCamera));
// camera presets
for(uint i = 0; i < 6; i++)
{
addAction("/cameraPreset" + (i + 1), BCameraPresetStart + i);
}
asc.AddAction(MessagePath + "/isReady", new Action(PostIsReady));
// Get status
asc.AddAction(MessagePath + "/fullStatus", new Action(PostFullStatus));
// Dial on string
asc.AddAction(MessagePath + "/dial", new Action<string>(s =>
EISC.SetString(SCurrentDialString, s)));
// Pulse DTMF
asc.AddAction(MessagePath + "/dtmf", new Action<string>(s =>
{
if (DTMFMap.ContainsKey(s))
{
EISC.PulseBool(DTMFMap[s], 100);
}
}));
// Directory madness
asc.AddAction(MessagePath + "/directoryRoot", new Action(() => EISC.PulseBool(BDirectoryRoot)));
asc.AddAction(MessagePath + "/directoryBack", new Action(() => EISC.PulseBool(BDirectoryFolderBack)));
asc.AddAction(MessagePath + "/directoryById", new Action<string>(s =>
{
// the id should contain the line number to forward to simpl
try
{
var u = ushort.Parse(s);
EISC.SetUshort(UDirectorySelectRow, u);
EISC.PulseBool(BDirectoryLineSelected);
}
catch (Exception)
{
Debug.Console(1, this, Debug.ErrorLogLevel.Warning,
"/directoryById request contains non-numeric ID incompatible with DDVC bridge");
}
}));
asc.AddAction(MessagePath + "/directorySelectContact", new Action<string>(s =>
{
try
{
var u = ushort.Parse(s);
EISC.SetUshort(UDirectorySelectRow, u);
EISC.PulseBool(BDirectoryLineSelected);
}
catch
{
}
}));
asc.AddAction(MessagePath + "/directoryDialContact", new Action(() => {
EISC.PulseBool(BDirectoryDialSelectedLine);
}));
asc.AddAction(MessagePath + "/getDirectory", new Action(() =>
{
if (EISC.GetUshort(UDirectoryRowCount) > 0)
{
PostDirectory();
}
else
{
EISC.PulseBool(BDirectoryRoot);
}
}));
}
/// <summary>
///
/// </summary>
void PostFullStatus()
{
this.PostStatusMessage(new
{
calls = GetCurrentCallList(),
cameraMode = GetCameraMode(),
cameraSelfView = EISC.GetBool(BCameraSelfView),
cameraSupportsAutoMode = EISC.GetBool(BCameraSupportsAutoMode),
cameraSupportsOffMode = EISC.GetBool(BCameraSupportsOffMode),
currentCallString = EISC.GetString(SCurrentCallNumber),
currentDialString = EISC.GetString(SCurrentDialString),
directoryContactSelected = new
{
name = EISC.GetString(SDirectoryEntrySelectedName),
number = EISC.GetString(SDirectoryEntrySelectedNumber)
},
directorySelectedFolderName = EISC.GetString(SDirectorySelectedFolderName),
isInCall = EISC.GetString(SHookState) == "Connected",
hasDirectory = true,
hasDirectorySearch = false,
hasRecents = !EISC.BooleanOutput[502].BoolValue,
hasCameras = true,
showCamerasWhenNotInCall = EISC.BooleanOutput[503].BoolValue,
selectedCamera = GetSelectedCamera(),
});
}
/// <summary>
///
/// </summary>
void PostDirectory()
{
var u = EISC.GetUshort(UDirectoryRowCount);
var items = new List<object>();
for (uint i = 0; i < u; i++)
{
var name = EISC.GetString(SDirectoryEntriesStart + i);
var id = (i + 1).ToString();
// is folder or contact?
if (name.StartsWith("[+]"))
{
items.Add(new
{
folderId = id,
name = name
});
}
else
{
items.Add(new
{
contactId = id,
name = name
});
}
}
var directoryMessage = new
{
currentDirectory = new
{
isRootDirectory = EISC.GetBool(BDirectoryIsRoot),
directoryResults = items
}
};
PostStatusMessage(directoryMessage);
}
/// <summary>
///
/// </summary>
void PostCameraMode()
{
PostStatusMessage(new
{
cameraMode = GetCameraMode()
});
}
/// <summary>
///
/// </summary>
/// <param name="mode"></param>
string GetCameraMode()
{
string m;
if (EISC.GetBool(BCameraModeAuto)) m = "auto";
else if (EISC.GetBool(BCameraModeManual)) m = "manual";
else m = "off";
return m;
}
void PostSelectedCamera()
{
PostStatusMessage(new
{
selectedCamera = GetSelectedCamera()
});
}
/// <summary>
///
/// </summary>
string GetSelectedCamera()
{
var num = EISC.GetUshort(UCameraNumberSelect);
string m;
if (num == 100)
{
m = "cameraFar";
}
else
{
m = "camera" + num;
}
return m;
}
/// <summary>
///
/// </summary>
void PostIsReady()
{
PostStatusMessage(new
{
isReady = true
});
}
/// <summary>
///
/// </summary>
void PostCallsList()
{
PostStatusMessage(new
{
calls = GetCurrentCallList(),
});
}
/// <summary>
///
/// </summary>
/// <param name="s"></param>
void SelectCamera(string s)
{
var cam = s.Substring(6);
if (cam.ToLower() == "far")
{
EISC.SetUshort(UCameraNumberSelect, 100);
}
else
{
EISC.SetUshort(UCameraNumberSelect, UInt16.Parse(cam));
}
}
/// <summary>
/// Turns the
/// </summary>
/// <returns></returns>
List<CodecActiveCallItem> GetCurrentCallList()
{
var list = new List<CodecActiveCallItem>();
if (CurrentCallItem.Status != eCodecCallStatus.Disconnected)
{
list.Add(CurrentCallItem);
}
if (EISC.GetBool(BCallIncoming)) {
}
return list;
}
}
}

View File

@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
namespace PepperDash.Essentials.AppServer.Messengers
{
/// <summary>
/// Provides a messaging bridge for a VideoCodecBase
/// </summary>
public abstract class MessengerBase : IKeyed
{
public string Key { get; private set; }
/// <summary>
///
/// </summary>
public MobileControlSystemController AppServerController { get; private set; }
public string MessagePath { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="codec"></param>
public MessengerBase(string key, string messagePath)
{
Key = key;
if (string.IsNullOrEmpty(messagePath))
throw new ArgumentException("messagePath must not be empty or null");
MessagePath = messagePath;
}
/// <summary>
/// Registers this messenger with appserver controller
/// </summary>
/// <param name="appServerController"></param>
public void RegisterWithAppServer(MobileControlSystemController appServerController)
{
if (appServerController == null)
throw new ArgumentNullException("appServerController");
AppServerController = appServerController;
CustomRegisterWithAppServer(AppServerController);
}
/// <summary>
/// Implemented in extending classes. Wire up API calls and feedback here
/// </summary>
/// <param name="appServerController"></param>
abstract protected void CustomRegisterWithAppServer(MobileControlSystemController appServerController);
/// <summary>
/// Helper for posting status message
/// </summary>
/// <param name="contentObject">The contents of the content object</param>
protected void PostStatusMessage(object contentObject)
{
if (AppServerController != null)
{
AppServerController.SendMessageToServer(JObject.FromObject(new
{
type = MessagePath,
content = contentObject
}));
}
}
}
}

View File

@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Monitoring;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class SystemMonitorMessenger : MessengerBase
{
public SystemMonitorController SysMon { get; private set; }
public SystemMonitorMessenger(string key, SystemMonitorController sysMon, string messagePath)
: base(key, messagePath)
{
if (sysMon == null)
throw new ArgumentNullException("sysMon");
SysMon = sysMon;
SysMon.SystemMonitorPropertiesChanged += new EventHandler<EventArgs>(SysMon_SystemMonitorPropertiesChanged);
foreach (var p in SysMon.ProgramStatusFeedbackCollection)
{
p.Value.ProgramInfoChanged += new EventHandler<ProgramInfoEventArgs>(ProgramInfoChanged);
}
CrestronConsole.AddNewConsoleCommand(s => SendFullStatusMessage(), "SendFullSysMonStatus", "Sends the full System Monitor Status", ConsoleAccessLevelEnum.AccessOperator);
}
/// <summary>
/// Posts the program information message
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void ProgramInfoChanged(object sender, ProgramInfoEventArgs e)
{
if (e.ProgramInfo != null)
{
//Debug.Console(1, "Posting Status Message: {0}", e.ProgramInfo.ToString());
PostStatusMessage(e.ProgramInfo);
}
}
/// <summary>
/// Posts the system monitor properties
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void SysMon_SystemMonitorPropertiesChanged(object sender, EventArgs e)
{
SendSystemMonitorStatusMessage();
}
void SendFullStatusMessage()
{
SendSystemMonitorStatusMessage();
foreach (var p in SysMon.ProgramStatusFeedbackCollection)
{
PostStatusMessage(p.Value.ProgramInfo);
}
}
void SendSystemMonitorStatusMessage()
{
Debug.Console(1, "Posting System Monitor Status Message.");
// This takes a while, launch a new thread
CrestronInvoke.BeginInvoke((o) =>
{
PostStatusMessage(new
{
timeZone = SysMon.TimeZoneFeedback.IntValue,
timeZoneName = SysMon.TimeZoneTextFeedback.StringValue,
ioControllerVersion = SysMon.IOControllerVersionFeedback.StringValue,
snmpVersion = SysMon.SnmpVersionFeedback.StringValue,
bacnetVersion = SysMon.BACnetAppVersionFeedback.StringValue,
controllerVersion = SysMon.ControllerVersionFeedback.StringValue
});
});
}
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
{
AppServerController.AddAction(MessagePath + "/fullStatus", new Action(SendFullStatusMessage));
}
}
}

View File

@@ -0,0 +1,373 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.Cameras;
using PepperDash.Essentials.Devices.Common.VideoCodec;
namespace PepperDash.Essentials.AppServer.Messengers
{
/// <summary>
/// Provides a messaging bridge for a VideoCodecBase device
/// </summary>
public class VideoCodecBaseMessenger : MessengerBase
{
/// <summary>
///
/// </summary>
public VideoCodecBase Codec { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="codec"></param>
public VideoCodecBaseMessenger(string key, VideoCodecBase codec, string messagePath)
: base(key, messagePath)
{
if (codec == null)
throw new ArgumentNullException("codec");
Codec = codec;
codec.CallStatusChange += new EventHandler<CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
codec.IsReadyChange += new EventHandler<EventArgs>(codec_IsReadyChange);
var dirCodec = codec as IHasDirectory;
if (dirCodec != null)
{
dirCodec.DirectoryResultReturned += new EventHandler<DirectoryEventArgs>(dirCodec_DirectoryResultReturned);
}
var recCodec = codec as IHasCallHistory;
if (recCodec != null)
{
recCodec.CallHistory.RecentCallsListHasChanged += new EventHandler<EventArgs>(CallHistory_RecentCallsListHasChanged);
}
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void CallHistory_RecentCallsListHasChanged(object sender, EventArgs e)
{
var recents = (sender as CodecCallHistory).RecentCalls;
if (recents != null)
{
PostStatusMessage(new
{
recentCalls = recents
});
}
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void dirCodec_DirectoryResultReturned(object sender, DirectoryEventArgs e)
{
SendDirectory((Codec as IHasDirectory).CurrentDirectoryResult, e.DirectoryIsOnRoot);
}
/// <summary>
/// Posts the current directory
/// </summary>
void SendDirectory(CodecDirectory directory, bool isRoot)
{
var dirCodec = Codec as IHasDirectory;
if (dirCodec != null)
{
var prefixedDirectoryResults = PrefixDirectoryFolderItems(directory);
var directoryMessage = new
{
currentDirectory = new
{
directoryResults = prefixedDirectoryResults,
isRootDirectory = isRoot
}
};
PostStatusMessage(directoryMessage);
}
}
/// <summary>
/// Iterates a directory object and prefixes any folder items with "[+] "
/// </summary>
/// <param name="directory"></param>
/// <returns></returns>
List<DirectoryItem> PrefixDirectoryFolderItems (CodecDirectory directory)
{
var tempDirectoryList = new List<DirectoryItem>();
if (directory.CurrentDirectoryResults.Count > 0)
{
foreach (var item in directory.CurrentDirectoryResults)
{
if (item is DirectoryFolder)
{
var newFolder = new DirectoryFolder();
newFolder = (DirectoryFolder)item.Clone();
string prefixName = "[+] " + newFolder.Name;
newFolder.Name = prefixName;
tempDirectoryList.Add(newFolder);
}
else
{
tempDirectoryList.Add(item);
}
}
}
//else
//{
// DirectoryItem noResults = new DirectoryItem() { Name = "No Results Found" };
// tempDirectoryList.Add(noResults);
//}
return tempDirectoryList;
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void codec_IsReadyChange(object sender, EventArgs e)
{
PostStatusMessage(new
{
isReady = true
});
}
/// <summary>
/// Called from base's RegisterWithAppServer method
/// </summary>
/// <param name="appServerController"></param>
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
{
appServerController.AddAction("/device/videoCodec/isReady", new Action(SendIsReady));
appServerController.AddAction("/device/videoCodec/fullStatus", new Action(SendVtcFullMessageObject));
appServerController.AddAction("/device/videoCodec/dial", new Action<string>(s => Codec.Dial(s)));
appServerController.AddAction("/device/videoCodec/endCallById", new Action<string>(s =>
{
var call = GetCallWithId(s);
if (call != null)
Codec.EndCall(call);
}));
appServerController.AddAction(MessagePath + "/endAllCalls", new Action(Codec.EndAllCalls));
appServerController.AddAction(MessagePath + "/dtmf", new Action<string>(s => Codec.SendDtmf(s)));
appServerController.AddAction(MessagePath + "/rejectById", new Action<string>(s =>
{
var call = GetCallWithId(s);
if (call != null)
Codec.RejectCall(call);
}));
appServerController.AddAction(MessagePath + "/acceptById", new Action<string>(s =>
{
var call = GetCallWithId(s);
if (call != null)
Codec.AcceptCall(call);
}));
// Directory actions
var dirCodec = Codec as IHasDirectory;
if (dirCodec != null)
{
appServerController.AddAction(MessagePath + "/getDirectory", new Action(GetDirectoryRoot));
appServerController.AddAction(MessagePath + "/directoryById", new Action<string>(s => GetDirectory(s)));
appServerController.AddAction(MessagePath + "/directorySearch", new Action<string>(s => DirectorySearch(s)));
appServerController.AddAction(MessagePath + "/directoryBack", new Action(GetPreviousDirectory));
}
// History actions
var recCodec = Codec as IHasCallHistory;
if (recCodec != null)
{
appServerController.AddAction(MessagePath + "/getCallHistory", new Action(GetCallHistory));
}
appServerController.AddAction(MessagePath + "/privacyModeOn", new Action(Codec.PrivacyModeOn));
appServerController.AddAction(MessagePath + "/privacyModeOff", new Action(Codec.PrivacyModeOff));
appServerController.AddAction(MessagePath + "/privacyModeToggle", new Action(Codec.PrivacyModeToggle));
appServerController.AddAction(MessagePath + "/sharingStart", new Action(Codec.StartSharing));
appServerController.AddAction(MessagePath + "/sharingStop", new Action(Codec.StopSharing));
appServerController.AddAction(MessagePath + "/standbyOn", new Action(Codec.StandbyActivate));
appServerController.AddAction(MessagePath + "/standbyOff", new Action(Codec.StandbyDeactivate));
}
void GetCallHistory()
{
var codec = (Codec as IHasCallHistory);
if (codec != null)
{
var recents = codec.CallHistory.RecentCalls;
if (recents != null)
{
PostStatusMessage(new
{
recentCalls = recents
});
}
}
}
public void GetFullStatusMessage()
{
}
/// <summary>
/// Helper to grab a call with string ID
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
CodecActiveCallItem GetCallWithId(string id)
{
return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id);
}
/// <summary>
///
/// </summary>
/// <param name="s"></param>
void DirectorySearch(string s)
{
var dirCodec = Codec as IHasDirectory;
if (dirCodec != null)
{
dirCodec.SearchDirectory(s);
}
}
/// <summary>
///
/// </summary>
/// <param name="id"></param>
void GetDirectory(string id)
{
var dirCodec = Codec as IHasDirectory;
if(dirCodec == null)
{
return;
}
dirCodec.GetDirectoryFolderContents(id);
}
/// <summary>
///
/// </summary>
void GetDirectoryRoot()
{
var dirCodec = Codec as IHasDirectory;
if (dirCodec == null)
{
// do something else?
return;
}
if (!dirCodec.PhonebookSyncState.InitialSyncComplete)
{
PostStatusMessage(new
{
initialSyncComplete = false
});
return;
}
dirCodec.SetCurrentDirectoryToRoot();
//PostStatusMessage(new
//{
// currentDirectory = dirCodec.DirectoryRoot
//});
}
/// <summary>
/// Requests the parent folder contents
/// </summary>
void GetPreviousDirectory()
{
var dirCodec = Codec as IHasDirectory;
if (dirCodec == null)
{
return;
}
dirCodec.GetDirectoryParentFolderContents();
}
/// <summary>
/// Handler for codec changes
/// </summary>
void codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
{
SendVtcFullMessageObject();
}
/// <summary>
///
/// </summary>
void SendIsReady()
{
PostStatusMessage(new
{
isReady = Codec.IsReady
});
}
/// <summary>
/// Helper method to build call status for vtc
/// </summary>
/// <returns></returns>
void SendVtcFullMessageObject()
{
if (!Codec.IsReady)
{
return;
}
var info = Codec.CodecInfo;
PostStatusMessage(new
{
isInCall = Codec.IsInCall,
privacyModeIsOn = Codec.PrivacyModeIsOnFeedback.BoolValue,
sharingContentIsOn = Codec.SharingContentIsOnFeedback.BoolValue,
sharingSource = Codec.SharingSourceFeedback.StringValue,
standbyIsOn = Codec.StandbyIsOnFeedback.StringValue,
calls = Codec.ActiveCalls,
info = new
{
autoAnswerEnabled = info.AutoAnswerEnabled,
e164Alias = info.E164Alias,
h323Id = info.H323Id,
ipAddress = info.IpAddress,
sipPhoneNumber = info.SipPhoneNumber,
sipURI = info.SipUri
},
showSelfViewByDefault = Codec.ShowSelfViewByDefault,
hasDirectory = Codec is IHasDirectory,
hasDirectorySearch = true,
hasRecents = Codec is IHasCallHistory,
hasCameras = Codec is IHasCodecCameras
});
}
}
}

View File

@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core.Config;
using Newtonsoft.Json;
namespace PepperDash.Essentials
{
/// <summary>
///
/// </summary>
public class MobileControlConfig
{
[JsonProperty("serverUrl")]
public string ServerUrl { get; set; }
[JsonProperty("clientAppUrl")]
public string ClientAppUrl { get; set; }
}
/// <summary>
///
/// </summary>
public class MobileControlDdvc01RoomBridgePropertiesConfig
{
[JsonProperty("eiscId")]
public string EiscId { get; set; }
}
}

View File

@@ -0,0 +1,148 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.EthernetCommunication;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
/// <summary>
/// Represents a generic device connection through to and EISC for DDVC01
/// </summary>
public class MobileControlDdvc01DeviceBridge : Device, IChannel, INumericKeypad
{
/// <summary>
/// EISC used to talk to Simpl
/// </summary>
ThreeSeriesTcpIpEthernetIntersystemCommunications EISC;
public MobileControlDdvc01DeviceBridge(string key, string name, ThreeSeriesTcpIpEthernetIntersystemCommunications eisc)
: base(key, name)
{
EISC = eisc;
}
#region IChannel Members
public void ChannelUp(bool pressRelease)
{
EISC.SetBool(1111, pressRelease);
}
public void ChannelDown(bool pressRelease)
{
EISC.SetBool(1111, pressRelease);
}
public void LastChannel(bool pressRelease)
{
EISC.SetBool(1111, pressRelease);
}
public void Guide(bool pressRelease)
{
EISC.SetBool(1111, pressRelease);
}
public void Info(bool pressRelease)
{
EISC.SetBool(1111, pressRelease);
}
public void Exit(bool pressRelease)
{
EISC.SetBool(1111, pressRelease);
}
#endregion
#region INumericKeypad Members
public void Digit0(bool pressRelease)
{
EISC.SetBool(1111, pressRelease);
}
public void Digit1(bool pressRelease)
{
EISC.SetBool(1111, pressRelease);
}
public void Digit2(bool pressRelease)
{
EISC.SetBool(1111, pressRelease);
}
public void Digit3(bool pressRelease)
{
EISC.SetBool(1111, pressRelease);
}
public void Digit4(bool pressRelease)
{
EISC.SetBool(1111, pressRelease);
}
public void Digit5(bool pressRelease)
{
EISC.SetBool(1111, pressRelease);
}
public void Digit6(bool pressRelease)
{
EISC.SetBool(1111, pressRelease);
}
public void Digit7(bool pressRelease)
{
EISC.SetBool(1111, pressRelease);
}
public void Digit8(bool pressRelease)
{
EISC.SetBool(1111, pressRelease);
}
public void Digit9(bool pressRelease)
{
EISC.SetBool(1111, pressRelease);
}
public bool HasKeypadAccessoryButton1
{
get { throw new NotImplementedException(); }
}
public string KeypadAccessoryButton1Label
{
get { throw new NotImplementedException(); }
}
public void KeypadAccessoryButton1(bool pressRelease)
{
throw new NotImplementedException();
}
public bool HasKeypadAccessoryButton2
{
get { throw new NotImplementedException(); }
}
public string KeypadAccessoryButton2Label
{
get { throw new NotImplementedException(); }
}
public void KeypadAccessoryButton2(bool pressRelease)
{
throw new NotImplementedException();
}
#endregion
}
}

View File

@@ -0,0 +1,864 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Reflection;
using Crestron.SimplSharpPro.CrestronThread;
using Crestron.SimplSharp.CrestronWebSocketClient;
using Crestron.SimplSharpPro;
using Crestron.SimplSharp.Net.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Room.MobileControl;
using PepperDash.Essentials.AppServer.Messengers;
namespace PepperDash.Essentials
{
public class MobileControlSystemController : Device
{
WebSocketClient WSClient;
//bool LinkUp;
/// <summary>
/// Prevents post operations from stomping on each other and getting lost
/// </summary>
CEvent PostLockEvent = new CEvent(true, true);
CEvent RegisterLockEvent = new CEvent(true, true);
public MobileControlConfig Config { get; private set; }
Dictionary<string, Object> ActionDictionary = new Dictionary<string, Object>(StringComparer.InvariantCultureIgnoreCase);
Dictionary<string, CTimer> PushedActions = new Dictionary<string, CTimer>();
public ConfigMessenger ConfigMessenger { get; private set; }
CTimer ServerHeartbeatCheckTimer;
long ServerHeartbeatInterval = 20000;
CTimer ServerReconnectTimer;
long ServerReconnectInterval = 5000;
DateTime LastAckMessage;
public string SystemUuid;
List<MobileControlBridgeBase> RoomBridges = new List<MobileControlBridgeBase>();
long ButtonHeartbeatInterval = 1000;
/// <summary>
/// Used for tracking HTTP debugging
/// </summary>
bool HttpDebugEnabled;
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="name"></param>
/// <param name="config"></param>
public MobileControlSystemController(string key, string name, MobileControlConfig config) : base(key, name)
{
Config = config;
SystemUuid = ConfigReader.ConfigObject.SystemUuid;
Debug.Console(0, this, "Mobile UI controller initializing for server:{0}", config.ServerUrl);
CrestronConsole.AddNewConsoleCommand(AuthorizeSystem,
"mobileauth", "Authorizes system to talk to Mobile Control server", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => ShowInfo(),
"mobileinfo", "Shows information for current mobile control session", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => {
s = s.Trim();
if(!string.IsNullOrEmpty(s))
{
HttpDebugEnabled = (s.Trim() != "0");
}
CrestronConsole.ConsoleCommandResponse("HTTP Debug {0}", HttpDebugEnabled ? "Enabled" : "Disabled");
},
"mobilehttpdebug", "1 enables more verbose HTTP response debugging", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(TestHttpRequest,
"mobilehttprequest", "Tests an HTTP get to URL given", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(PrintActionDictionaryPaths, "mobileshowactionpaths",
"Prints the paths in the Action Dictionary", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => ConnectWebsocketClient(), "mobileconnect",
"Forces connect of websocket", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => CleanUpWebsocketClient(), "mobiledisco",
"Disconnects websocket", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => ParseStreamRx(s), "mobilesimulateaction", "Simulates a message from the server", ConsoleAccessLevelEnum.AccessOperator);
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler);
// Config Messenger
var cmKey = Key + "-config";
ConfigMessenger = new ConfigMessenger(cmKey, "/config");
ConfigMessenger.RegisterWithAppServer(this);
}
/// <summary>
/// If config rooms is empty or null then go
/// </summary>
/// <returns></returns>
public override bool CustomActivate()
{
if (ConfigReader.ConfigObject.Rooms == null || ConfigReader.ConfigObject.Rooms.Count == 0)
{
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Config contains no rooms. Registering with Server.");
RegisterSystemToServer();
}
return base.CustomActivate();
}
/// <summary>
///
/// </summary>
/// <param name="ethernetEventArgs"></param>
void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs args)
{
Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Ethernet status change, port {0}: {1}",
args.EthernetAdapter, args.EthernetEventType);
if (args.EthernetEventType == eEthernetEventType.LinkDown && WSClient != null && args.EthernetAdapter == WSClient.EthernetAdapter)
{
CleanUpWebsocketClient();
}
}
/// <summary>
/// Sends message to server to indicate the system is shutting down
/// </summary>
/// <param name="programEventType"></param>
void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
{
if (programEventType == eProgramStatusEventType.Stopping
&& WSClient != null
&& WSClient.Connected)
{
CleanUpWebsocketClient();
}
}
public void PrintActionDictionaryPaths(object o)
{
Debug.Console(0, this, "ActionDictionary Contents:");
foreach (var item in ActionDictionary)
{
Debug.Console(0, this, "{0}", item.Key);
}
}
/// <summary>
/// Adds an action to the dictionary
/// </summary>
/// <param name="key">The path of the API command</param>
/// <param name="action">The action to be triggered by the commmand</param>
public void AddAction(string key, object action)
{
if (!ActionDictionary.ContainsKey(key))
{
ActionDictionary.Add(key, action);
}
else
{
Debug.Console(1, this, "Cannot add action with key '{0}' because key already exists in ActionDictionary.", key);
}
}
/// <summary>
/// Removes an action from the dictionary
/// </summary>
/// <param name="key"></param>
public void RemoveAction(string key)
{
if (ActionDictionary.ContainsKey(key))
ActionDictionary.Remove(key);
}
/// <summary>
///
/// </summary>
/// <param name="bridge"></param>
public void AddBridge(MobileControlBridgeBase bridge)
{
RoomBridges.Add(bridge);
var b = bridge as IDelayedConfiguration;
if (b != null)
{
Debug.Console(0, this, "Adding room bridge with delayed configuration");
b.ConfigurationIsReady += new EventHandler<EventArgs>(bridge_ConfigurationIsReady);
}
else
{
Debug.Console(0, this, "Adding room bridge and sending configuration");
//SystemUuid = ConfigReader.ConfigObject.SystemUuid;
RegisterSystemToServer();
}
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void bridge_ConfigurationIsReady(object sender, EventArgs e)
{
Debug.Console(1, this, "Bridge ready. Registering");
//SystemUuid = ConfigReader.ConfigObject.SystemUuid;
// send the configuration object to the server
RegisterSystemToServer();
}
/// <summary>
///
/// </summary>
/// <param name="o"></param>
void ReconnectToServerTimerCallback(object o)
{
RegisterSystemToServer();
}
/// <summary>
/// Verifies system connection with servers
/// </summary>
/// <param name="command"></param>
void AuthorizeSystem(string code)
{
//SystemUuid = ConfigReader.ConfigObject.SystemUuid;
if (string.IsNullOrEmpty(SystemUuid))
{
CrestronConsole.ConsoleCommandResponse("System does not have a UUID. Please ensure proper portal-format configuration is loaded and restart.");
return;
}
if (string.IsNullOrEmpty(code))
{
CrestronConsole.ConsoleCommandResponse("Please enter a user code to authorize a system");
return;
}
var req = new HttpClientRequest();
string url = string.Format("http://{0}/api/system/grantcode/{1}/{2}", Config.ServerUrl, code, SystemUuid);
Debug.Console(0, this, "Authorizing to: {0}", url);
if (string.IsNullOrEmpty(Config.ServerUrl))
{
CrestronConsole.ConsoleCommandResponse("Config URL address is not set. Check portal configuration");
return;
}
try
{
req.Url.Parse(url);
new HttpClient().DispatchAsync(req, (r, e) =>
{
CheckHttpDebug(r, e);
if (e == HTTP_CALLBACK_ERROR.COMPLETED)
{
if (r.Code == 200)
{
Debug.Console(0, "System authorized, sending config.");
#warning This registration may need to wait for config ready. Maybe.
RegisterSystemToServer();
}
else if (r.Code == 404)
{
if (r.ContentString.Contains("codeNotFound"))
{
Debug.Console(0, "Authorization failed, code not found for system UUID {0}", SystemUuid);
}
else if (r.ContentString.Contains("uuidNotFound"))
{
Debug.Console(0, "Authorization failed, uuid {0} not found. Check Essentials configuration is correct",
SystemUuid);
}
}
}
else
Debug.Console(0, this, "Error {0} in authorizing system", e);
});
}
catch (Exception e)
{
Debug.Console(0, this, "Error in authorizing: {0}", e);
}
}
/// <summary>
/// Dumps info in response to console command.
/// </summary>
void ShowInfo()
{
var url = Config != null ? Config.ServerUrl : "No config";
string name;
string code;
if (RoomBridges != null && RoomBridges.Count > 0)
{
name = RoomBridges[0].RoomName;
code = RoomBridges[0].UserCode;
}
else
{
name = "No config";
code = "Not available";
}
var conn = WSClient == null ? "No client" : (WSClient.Connected ? "Yes" : "No");
var secSinceLastAck = DateTime.Now - LastAckMessage;
CrestronConsole.ConsoleCommandResponse(@"Mobile Control Information:
Server address: {0}
System Name: {1}
System URL: {2}
System UUID: {3}
System User code: {4}
Connected?: {5}
Seconds Since Last Ack: {6}"
, url, name, ConfigReader.ConfigObject.SystemUrl, SystemUuid,
code, conn, secSinceLastAck.Seconds);
}
/// <summary>
/// Registers the room with the server
/// </summary>
/// <param name="url">URL of the server, including the port number, if not 80. Format: "serverUrlOrIp:port"</param>
void RegisterSystemToServer()
{
ConnectWebsocketClient();
}
/// <summary>
/// Connects the Websocket Client
/// </summary>
/// <param name="o"></param>
void ConnectWebsocketClient()
{
Debug.Console(1, this, "Initializing Stream client to server.");
if (WSClient != null)
{
Debug.Console(1, this, "Cleaning up previous socket");
CleanUpWebsocketClient();
}
WSClient = new WebSocketClient();
WSClient.URL = string.Format("wss://{0}/system/join/{1}", Config.ServerUrl, this.SystemUuid);
WSClient.ConnectionCallBack = Websocket_ConnectCallback;
WSClient.ConnectAsync();
}
/// <summary>
///
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
int Websocket_ConnectCallback(WebSocketClient.WEBSOCKET_RESULT_CODES code)
{
if (code == WebSocketClient.WEBSOCKET_RESULT_CODES.WEBSOCKET_CLIENT_SUCCESS)
{
StopServerReconnectTimer();
Debug.Console(1, this, "Websocket connected");
WSClient.DisconnectCallBack = Websocket_DisconnectCallback;
WSClient.SendCallBack = Websocket_SendCallback;
WSClient.ReceiveCallBack = Websocket_ReceiveCallback;
WSClient.ReceiveAsync();
SendMessageObjectToServer(new
{
type = "hello"
});
}
else
{
if (code == WebSocketClient.WEBSOCKET_RESULT_CODES.WEBSOCKET_CLIENT_HTTP_HANDSHAKE_TOKEN_ERROR)
{
// This is the case when app server is running behind a websever and app server is down
Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Web socket connection failed. Check that app server is running behind web server");
}
else if (code == WebSocketClient.WEBSOCKET_RESULT_CODES.WEBSOCKET_CLIENT_SOCKET_CONNECTION_FAILED)
{
// this will be the case when webserver is unreachable
Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Web socket connection failed");
}
else
{
Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Web socket connection failure: {0}", code);
}
StartServerReconnectTimer();
}
return 0;
}
/// <summary>
/// After a "hello" from the server, sends config and stuff
/// </summary>
void SendInitialMessage()
{
Debug.Console(1, this, "Sending initial join message");
var confObject = ConfigReader.ConfigObject;
confObject.Info.RuntimeInfo.AppName = Assembly.GetExecutingAssembly().GetName().Name;
var version = Assembly.GetExecutingAssembly().GetName().Version;
confObject.Info.RuntimeInfo.AssemblyVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
var msg = new
{
type = "join",
content = new
{
config = confObject
}
};
SendMessageObjectToServer(msg);
}
/// <summary>
/// Sends any object type to server
/// </summary>
/// <param name="o"></param>
public void SendMessageObjectToServer(object o)
{
SendMessageToServer(JObject.FromObject(o));
}
/// <summary>
/// Sends a message to the server from a room
/// </summary>
/// <param name="room">room from which the message originates</param>
/// <param name="o">object to be serialized and sent in post body</param>
public void SendMessageToServer(JObject o)
{
if (WSClient != null && WSClient.Connected)
{
string message = JsonConvert.SerializeObject(o, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
if (!message.Contains("/system/heartbeat"))
Debug.Console(1, this, "Message TX: {0}", message);
//else
// Debug.Console(1, this, "TX messages contains /system/heartbeat");
var messageBytes = System.Text.Encoding.UTF8.GetBytes(message);
var result = WSClient.Send(messageBytes, (uint)messageBytes.Length, WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME);
if (result != WebSocketClient.WEBSOCKET_RESULT_CODES.WEBSOCKET_CLIENT_SUCCESS)
{
Debug.Console(1, this, "Socket send result error: {0}", result);
}
}
else if (WSClient == null)
{
Debug.Console(1, this, "Cannot send. Not connected.");
}
}
/// <summary>
/// Disconnects the SSE Client and stops the heartbeat timer
/// </summary>
/// <param name="command"></param>
void CleanUpWebsocketClient()
{
Debug.Console(1, this, "Disconnecting websocket");
if (WSClient != null)
{
WSClient.SendCallBack = null;
WSClient.ReceiveCallBack = null;
WSClient.ConnectionCallBack = null;
WSClient.DisconnectCallBack = null;
if (WSClient.Connected)
{
WSClient.Disconnect();
}
WSClient = null;
}
}
/// <summary>
///
/// </summary>
/// <param name="dueTime"></param>
/// <param name="repeatTime"></param>
void StartServerReconnectTimer()
{
StopServerReconnectTimer();
ServerReconnectTimer = new CTimer(ReconnectToServerTimerCallback, ServerReconnectInterval);
Debug.Console(1, this, "Reconnect Timer Started.");
}
/// <summary>
/// Does what it says
/// </summary>
void StopServerReconnectTimer()
{
if (ServerReconnectTimer != null)
{
ServerReconnectTimer.Stop();
ServerReconnectTimer = null;
}
}
/// <summary>
/// Executes when we don't get a heartbeat message in time. Triggers reconnect.
/// </summary>
/// <param name="o">For CTimer callback. Not used</param>
void HeartbeatExpiredTimerCallback(object o)
{
Debug.Console(1, this, "Heartbeat Timer Expired.");
if (ServerHeartbeatCheckTimer != null)
{
ServerHeartbeatCheckTimer.Stop();
ServerHeartbeatCheckTimer = null;
}
CleanUpWebsocketClient();
StartServerReconnectTimer();
}
/// <summary>
///
/// </summary>
/// <param name="dueTime"></param>
/// <param name="repeatTime"></param>
void ResetOrStartHearbeatTimer()
{
if (ServerHeartbeatCheckTimer == null)
{
ServerHeartbeatCheckTimer = new CTimer(HeartbeatExpiredTimerCallback, null, ServerHeartbeatInterval, ServerHeartbeatInterval);
Debug.Console(1, this, "Heartbeat Timer Started.");
}
else
{
ServerHeartbeatCheckTimer.Reset(ServerHeartbeatInterval, ServerHeartbeatInterval);
}
}
/// <summary>
/// Waits two and goes again
/// </summary>
void ReconnectStreamClient()
{
new CTimer(o => ConnectWebsocketClient(), 2000);
}
/// <summary>
///
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
int Websocket_DisconnectCallback(WebSocketClient.WEBSOCKET_RESULT_CODES code, object o)
{
Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Websocket disconnected with code: {0}", code);
if (ServerHeartbeatCheckTimer != null)
ServerHeartbeatCheckTimer.Stop();
// Start the reconnect timer
StartServerReconnectTimer();
return 0;
}
/// <summary>
/// Resets reconnect timer and updates usercode
/// </summary>
/// <param name="content"></param>
void HandleHeartBeat(JToken content)
{
SendMessageToServer(JObject.FromObject(new
{
type = "/system/heartbeatAck"
}));
var code = content["userCode"];
if(code != null)
{
foreach (var b in RoomBridges)
{
b.SetUserCode(code.Value<string>());
}
}
ResetOrStartHearbeatTimer();
}
/// <summary>
/// Outputs debug info when enabled
/// </summary>
/// <param name="req"></param>
/// <param name="r"></param>
/// <param name="e"></param>
void CheckHttpDebug(HttpClientResponse r, HTTP_CALLBACK_ERROR e)
{
if (HttpDebugEnabled)
{
try
{
Debug.Console(0, this, "------ Begin HTTP Debug ---------------------------------------");
if (r != null)
{
Debug.Console(0, this, "HTTP Response URL: {0}", r.ResponseUrl != null ? r.ResponseUrl.ToString() : "NONE");
Debug.Console(0, this, "HTTP Response code: {0}", r.Code);
Debug.Console(0, this, "HTTP Response content: \r{0}", r.ContentString);
}
else
{
Debug.Console(0, this, "No HTTP response");
}
Debug.Console(0, this, "HTTP Response 'error' {0}", e);
Debug.Console(0, this, "------ End HTTP Debug -----------------------------------------");
}
catch (Exception ex)
{
Debug.Console(0, this, "HttpDebugError: {0}", ex);
}
}
}
/// <summary>
///
/// </summary>
/// <param name="data"></param>
/// <param name="length"></param>
/// <param name="opcode"></param>
/// <param name="err"></param>
int Websocket_ReceiveCallback(byte[] data, uint length, WebSocketClient.WEBSOCKET_PACKET_TYPES opcode,
WebSocketClient.WEBSOCKET_RESULT_CODES err)
{
if (opcode == WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME)
{
var rx = System.Text.Encoding.UTF8.GetString(data, 0, (int)length);
if (rx.Length > 0)
ParseStreamRx(rx);
WSClient.ReceiveAsync();
}
else if (opcode == WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__CLOSE)
{
Debug.Console(1, this, "Websocket disconnect received from remote");
CleanUpWebsocketClient();
}
else
{
Debug.Console(1, this, "websocket rx opcode/err {0}/{1}", opcode, err);
WSClient.ReceiveAsync();
}
return 0;
}
/// <summary>
/// Callback to catch possible errors in sending via the websocket
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
int Websocket_SendCallback(Crestron.SimplSharp.CrestronWebSocketClient.WebSocketClient.WEBSOCKET_RESULT_CODES result)
{
if(result != WebSocketClient.WEBSOCKET_RESULT_CODES.WEBSOCKET_CLIENT_SUCCESS)
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "SendCallback questionable result: {0}", result);
return 1;
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void ParseStreamRx(string message)
{
if(string.IsNullOrEmpty(message))
return;
if (!message.Contains("/system/heartbeat"))
{
Debug.Console(1, this, "Message RX: {0}", message);
}
else
{
LastAckMessage = DateTime.Now;
}
try
{
var messageObj = JObject.Parse(message);
var type = messageObj["type"].Value<string>();
if (type == "hello")
{
SendInitialMessage();
ResetOrStartHearbeatTimer();
}
else if (type == "/system/heartbeat")
{
HandleHeartBeat(messageObj["content"]);
}
else if (type == "raw")
{
var wrapper = messageObj["content"].ToObject<DeviceActionWrapper>();
DeviceJsonApi.DoDeviceAction(wrapper);
}
else if (type == "close")
{
Debug.Console(1, this, "Received close message from server.");
// DisconnectWebsocketClient();
if (ServerHeartbeatCheckTimer != null)
ServerHeartbeatCheckTimer.Stop();
}
else
{
// Check path against Action dictionary
if (ActionDictionary.ContainsKey(type))
{
var action = ActionDictionary[type];
if (action is Action)
{
(action as Action)();
}
else if (action is PressAndHoldAction)
{
var stateString = messageObj["content"]["state"].Value<string>();
// Look for a button press event
if (!string.IsNullOrEmpty(stateString))
{
switch (stateString)
{
case "true":
{
if (!PushedActions.ContainsKey(type))
{
PushedActions.Add(type, new CTimer(o =>
{
(action as PressAndHoldAction)(false);
PushedActions.Remove(type);
}, null, ButtonHeartbeatInterval, ButtonHeartbeatInterval));
}
// Maybe add an else to reset the timer
break;
}
case "held":
{
if (PushedActions.ContainsKey(type))
{
PushedActions[type].Reset(ButtonHeartbeatInterval, ButtonHeartbeatInterval);
}
return;
}
case "false":
{
if (PushedActions.ContainsKey(type))
{
PushedActions[type].Stop();
PushedActions.Remove(type);
}
break;
}
}
(action as PressAndHoldAction)(stateString == "true");
}
}
else if (action is Action<bool>)
{
var stateString = messageObj["content"]["state"].Value<string>();
if (!string.IsNullOrEmpty(stateString))
{
(action as Action<bool>)(stateString == "true");
}
}
else if (action is Action<ushort>)
{
(action as Action<ushort>)(messageObj["content"]["value"].Value<ushort>());
}
else if (action is Action<string>)
{
(action as Action<string>)(messageObj["content"]["value"].Value<string>());
}
else if (action is Action<SourceSelectMessageContent>)
{
(action as Action<SourceSelectMessageContent>)(messageObj["content"]
.ToObject<SourceSelectMessageContent>());
}
}
else
{
Debug.Console(1, this, "-- Warning: Incoming message has no registered handler");
}
}
}
catch (Exception err)
{
//Debug.Console(1, "SseMessageLengthBeforeFailureCount: {0}", SseMessageLengthBeforeFailureCount);
//SseMessageLengthBeforeFailureCount = 0;
Debug.Console(1, this, "Unable to parse message: {0}", err);
}
}
void TestHttpRequest(string s)
{
{
s = s.Trim();
if (string.IsNullOrEmpty(s))
{
PrintTestHttpRequestUsage();
return;
}
var tokens = s.Split(' ');
if (tokens.Length < 2)
{
CrestronConsole.ConsoleCommandResponse("Too few paramaters\r");
PrintTestHttpRequestUsage();
return;
}
try
{
var url = tokens[1];
if (tokens[0].ToLower() == "get")
{
var resp = new HttpClient().Get(url);
CrestronConsole.ConsoleCommandResponse("RESPONSE:\r{0}\r\r", resp);
}
else if (tokens[0].ToLower() == "post")
{
var resp = new HttpClient().Post(url, new byte[] { });
CrestronConsole.ConsoleCommandResponse("RESPONSE:\r{0}\r\r", resp);
}
else
{
CrestronConsole.ConsoleCommandResponse("Only get or post supported\r");
PrintTestHttpRequestUsage();
}
}
catch (HttpException e)
{
CrestronConsole.ConsoleCommandResponse("Exception in request:\r");
CrestronConsole.ConsoleCommandResponse("Response URL: {0}\r", e.Response.ResponseUrl);
CrestronConsole.ConsoleCommandResponse("Response Error Code: {0}\r", e.Response.Code);
CrestronConsole.ConsoleCommandResponse("Response body: {0}\r", e.Response.ContentString);
}
}
}
void PrintTestHttpRequestUsage()
{
CrestronConsole.ConsoleCommandResponse("Usage: mobilehttprequest:N get/post url\r");
}
}
}

View File

@@ -0,0 +1,62 @@
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>
///
/// </summary>
public abstract class MobileControlBridgeBase: Device
{
public MobileControlSystemController Parent { get; private set; }
public string UserCode { get; private set; }
public abstract string RoomName { get; }
public MobileControlBridgeBase(string key, string name)
: base(key, name)
{
}
/// <summary>
/// Set the parent. Does nothing else. Override to add functionality such
/// as adding actions to parent
/// </summary>
/// <param name="parent"></param>
public virtual void AddParent(MobileControlSystemController parent)
{
Parent = parent;
}
/// <summary>
/// Sets the UserCode on the bridge object. Called from controller. A changed code will
/// fire method UserCodeChange. Override that to handle changes
/// </summary>
/// <param name="code"></param>
public void SetUserCode(string code)
{
var changed = UserCode != code;
UserCode = code;
if (changed)
{
UserCodeChange();
}
}
/// <summary>
/// Empty method in base class. Override this to add functionality
/// when code changes
/// </summary>
protected virtual void UserCodeChange()
{
}
}
}

View File

@@ -0,0 +1,912 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.Reflection;
using Crestron.SimplSharpPro.EthernetCommunication;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials.Room.MobileControl
{
public class MobileControlDdvc01RoomBridge : MobileControlBridgeBase, IDelayedConfiguration
{
public class BoolJoin
{
/// <summary>
/// 301
/// </summary>
public const uint RoomIsOn = 301;
/// <summary>
/// 12
/// </summary>
public const uint PrivacyMute = 12;
/// <summary>
/// 41
/// </summary>
public const uint PromptForCode = 41;
/// <summary>
/// 42
/// </summary>
public const uint ClientJoined = 42;
/// <summary>
/// 51
/// </summary>
public const uint ActivityShare = 51;
/// <summary>
/// 52
/// </summary>
public const uint ActivityPhoneCall = 52;
/// <summary>
/// 53
/// </summary>
public const uint ActivityVideoCall = 53;
/// <summary>
/// 1
/// </summary>
public const uint MasterVolumeIsMuted = 1;
/// <summary>
/// 1
/// </summary>
public const uint MasterVolumeMuteToggle = 1;
/// <summary>
/// 1
/// </summary>
public const uint VolumeMutesJoinStart = 1;
/// <summary>
/// 61
/// </summary>
public const uint ShutdownCancel = 61;
/// <summary>
/// 62
/// </summary>
public const uint ShutdownEnd = 62;
/// <summary>
/// 63
/// </summary>
public const uint ShutdownStart = 63;
/// <summary>
/// 72
/// </summary>
public const uint SourceHasChanged = 71;
/// <summary>
/// 261 - The start of the range of speed dial visibles
/// </summary>
public const uint SpeedDialVisibleStartJoin = 261;
/// <summary>
/// 501
/// </summary>
public const uint ConfigIsReady = 501;
/// <summary>
/// 502
/// </summary>
public const uint HideVideoConfRecents = 502;
/// <summary>
/// 503
/// </summary>
public const uint ShowCameraWhenNotInCall = 503;
/// <summary>
/// 504
/// </summary>
public const uint UseSourceEnabled = 504;
/// <summary>
/// 601
/// </summary>
public const uint SourceShareDisableJoinStart = 601;
/// <summary>
/// 621
/// </summary>
public const uint SourceIsEnabledJoinStart = 621;
}
public class UshortJoin
{
/// <summary>
/// 1
/// </summary>
public const uint MasterVolumeLevel = 1;
/// <summary>
/// 1
/// </summary>
public const uint VolumeSlidersJoinStart = 1;
/// <summary>
/// 61
/// </summary>
public const uint ShutdownPromptDuration = 61;
/// <summary>
/// 101
/// </summary>
public const uint NumberOfAuxFaders = 101;
}
public class StringJoin
{
/// <summary>
/// 1
/// </summary>
public const uint VolumeSliderNamesJoinStart = 1;
/// <summary>
/// 71
/// </summary>
public const uint SelectedSourceKey = 71;
/// <summary>
/// 241
/// </summary>
public const uint SpeedDialNameStartJoin = 241;
/// <summary>
/// 251
/// </summary>
public const uint SpeedDialNumberStartJoin = 251;
/// <summary>
/// 501
/// </summary>
public const uint ConfigRoomName = 501;
/// <summary>
/// 502
/// </summary>
public const uint ConfigHelpMessage = 502;
/// <summary>
/// 503
/// </summary>
public const uint ConfigHelpNumber = 503;
/// <summary>
/// 504
/// </summary>
public const uint ConfigRoomPhoneNumber = 504;
/// <summary>
/// 505
/// </summary>
public const uint ConfigRoomURI = 505;
/// <summary>
/// 401
/// </summary>
public const uint UserCodeToSystem = 401;
/// <summary>
/// 402
/// </summary>
public const uint ServerUrl = 402;
/// <summary>
/// 512
/// </summary>
public const uint RoomSpeedDialNamesJoinStart = 512;
/// <summary>
/// 516
/// </summary>
public const uint RoomSpeedDialNumberssJoinStart = 516;
/// <summary>
/// 601
/// </summary>
public const uint SourceNameJoinStart = 601;
/// <summary>
/// 621
/// </summary>
public const uint SourceIconJoinStart = 621;
/// <summary>
/// 641
/// </summary>
public const uint SourceKeyJoinStart = 641;
/// <summary>
/// 661
/// </summary>
public const uint SourceTypeJoinStart = 661;
/// <summary>
/// 761
/// </summary>
public const uint CameraNearNameStart = 761;
/// <summary>
/// 770 - presence of this name on the input will cause the camera to be added
/// </summary>
public const uint CameraFarName = 770;
}
/// <summary>
/// Fires when config is ready to go
/// </summary>
public event EventHandler<EventArgs> ConfigurationIsReady;
public ThreeSeriesTcpIpEthernetIntersystemCommunications EISC { get; private set; }
/// <summary>
///
/// </summary>
public bool ConfigIsLoaded { get; private set; }
public override string RoomName
{
get {
var name = EISC.StringOutput[StringJoin.ConfigRoomName].StringValue;
return string.IsNullOrEmpty(name) ? "Not Loaded" : name;
}
}
MobileControlDdvc01DeviceBridge SourceBridge;
Ddvc01AtcMessenger AtcMessenger;
Ddvc01VtcMessenger VtcMessenger;
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="name"></param>
/// <param name="ipId"></param>
public MobileControlDdvc01RoomBridge(string key, string name, uint ipId)
: base(key, name)
{
try
{
EISC = new ThreeSeriesTcpIpEthernetIntersystemCommunications(ipId, "127.0.0.2", Global.ControlSystem);
var reg = EISC.Register();
if (reg != Crestron.SimplSharpPro.eDeviceRegistrationUnRegistrationResponse.Success)
Debug.Console(0, this, "Cannot connect EISC at IPID {0}: \r{1}", ipId, reg);
SourceBridge = new MobileControlDdvc01DeviceBridge(key + "-sourceBridge", "DDVC01 source bridge", EISC);
DeviceManager.AddDevice(SourceBridge);
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Finish wiring up everything after all devices are created. The base class will hunt down the related
/// parent controller and link them up.
/// </summary>
/// <returns></returns>
public override bool CustomActivate()
{
Debug.Console(0, this, "Final activation. Setting up actions and feedbacks");
SetupFunctions();
SetupFeedbacks();
var atcKey = string.Format("atc-{0}-{1}", this.Key, Parent.Key);
AtcMessenger = new Ddvc01AtcMessenger(atcKey, EISC, "/device/audioCodec");
AtcMessenger.RegisterWithAppServer(Parent);
var vtcKey = string.Format("atc-{0}-{1}", this.Key, Parent.Key);
VtcMessenger = new Ddvc01VtcMessenger(vtcKey, EISC, "/device/videoCodec");
VtcMessenger.RegisterWithAppServer(Parent);
EISC.SigChange += EISC_SigChange;
EISC.OnlineStatusChange += (o, a) =>
{
Debug.Console(1, this, "DDVC EISC online={0}. Config is ready={1}", a.DeviceOnLine, EISC.BooleanOutput[BoolJoin.ConfigIsReady].BoolValue);
if (a.DeviceOnLine && EISC.BooleanOutput[BoolJoin.ConfigIsReady].BoolValue)
LoadConfigValues();
};
// load config if it's already there
if (EISC.IsOnline && EISC.BooleanOutput[BoolJoin.ConfigIsReady].BoolValue) // || EISC.BooleanInput[BoolJoin.ConfigIsReady].BoolValue)
LoadConfigValues();
CrestronConsole.AddNewConsoleCommand(s =>
{
for (uint i = 1; i < 1000; i++)
{
if (s.ToLower().Equals("b"))
{
CrestronConsole.ConsoleCommandResponse("D{0,6} {1} - ", i, EISC.BooleanOutput[i].BoolValue);
}
else if (s.ToLower().Equals("u"))
{
CrestronConsole.ConsoleCommandResponse("U{0,6} {1,8} - ", i, EISC.UShortOutput[i].UShortValue);
}
else if (s.ToLower().Equals("s"))
{
var val = EISC.StringOutput[i].StringValue;
if(!string.IsNullOrEmpty(val))
CrestronConsole.ConsoleCommandResponse("S{0,6} {1}\r", i, EISC.StringOutput[i].StringValue);
}
}
}, "mobilebridgedump", "Dumps DDVC01 bridge EISC data b,u,s", ConsoleAccessLevelEnum.AccessOperator);
return base.CustomActivate();
}
/// <summary>
/// Setup the actions to take place on various incoming API calls
/// </summary>
void SetupFunctions()
{
Parent.AddAction(@"/room/room1/promptForCode", new Action(() => EISC.PulseBool(BoolJoin.PromptForCode)));
Parent.AddAction(@"/room/room1/clientJoined", new Action(() => EISC.PulseBool(BoolJoin.ClientJoined)));
Parent.AddAction(@"/room/room1/status", new Action(SendFullStatus));
Parent.AddAction(@"/room/room1/source", new Action<SourceSelectMessageContent>(c =>
{
EISC.SetString(StringJoin.SelectedSourceKey, c.SourceListItem);
EISC.PulseBool(BoolJoin.SourceHasChanged);
}));
Parent.AddAction(@"/room/room1/defaultsource", new Action(() =>
EISC.PulseBool(BoolJoin.ActivityShare)));
Parent.AddAction(@"/room/room1/activityPhone", new Action(() =>
EISC.PulseBool(BoolJoin.ActivityPhoneCall)));
Parent.AddAction(@"/room/room1/activityVideo", new Action(() =>
EISC.PulseBool(BoolJoin.ActivityVideoCall)));
Parent.AddAction(@"/room/room1/volumes/master/level", new Action<ushort>(u =>
EISC.SetUshort(UshortJoin.MasterVolumeLevel, u)));
Parent.AddAction(@"/room/room1/volumes/master/muteToggle", new Action(() =>
EISC.PulseBool(BoolJoin.MasterVolumeIsMuted)));
Parent.AddAction(@"/room/room1/volumes/master/privacyMuteToggle", new Action(() =>
EISC.PulseBool(BoolJoin.PrivacyMute)));
// /xyzxyz/volumes/master/muteToggle ---> BoolInput[1]
for (uint i = 2; i <= 7; i++)
{
var index = i;
Parent.AddAction(string.Format(@"/room/room1/volumes/level-{0}/level", index), new Action<ushort>(u =>
EISC.SetUshort(index, u)));
Parent.AddAction(string.Format(@"/room/room1/volumes/level-{0}/muteToggle", index), new Action(() =>
EISC.PulseBool(index)));
}
Parent.AddAction(@"/room/room1/shutdownStart", new Action(() =>
EISC.PulseBool(BoolJoin.ShutdownStart)));
Parent.AddAction(@"/room/room1/shutdownEnd", new Action(() =>
EISC.PulseBool(BoolJoin.ShutdownEnd)));
Parent.AddAction(@"/room/room1/shutdownCancel", new Action(() =>
EISC.PulseBool(BoolJoin.ShutdownCancel)));
}
/// <summary>
///
/// </summary>
/// <param name="devKey"></param>
void SetupSourceFunctions(string devKey)
{
SourceDeviceMapDictionary sourceJoinMap = new SourceDeviceMapDictionary();
var prefix = string.Format("/device/{0}/", devKey);
foreach (var item in sourceJoinMap)
{
var join = item.Value;
Parent.AddAction(string.Format("{0}{1}", prefix, item.Key), new PressAndHoldAction(b => EISC.SetBool(join, b)));
}
}
/// <summary>
/// Links feedbacks to whatever is gonna happen!
/// </summary>
void SetupFeedbacks()
{
// Power
EISC.SetBoolSigAction(BoolJoin.RoomIsOn, b =>
PostStatusMessage(new
{
isOn = b
}));
// Source change things
EISC.SetSigTrueAction(BoolJoin.SourceHasChanged, () =>
PostStatusMessage(new
{
selectedSourceKey = EISC.StringOutput[StringJoin.SelectedSourceKey].StringValue
}));
// Volume things
EISC.SetUShortSigAction(UshortJoin.MasterVolumeLevel, u =>
PostStatusMessage(new
{
volumes = new
{
master = new
{
level = u
}
}
}));
// map MasterVolumeIsMuted join -> status/volumes/master/muted
//
EISC.SetBoolSigAction(BoolJoin.MasterVolumeIsMuted, b =>
PostStatusMessage(new
{
volumes = new
{
master = new
{
muted = b
}
}
}));
EISC.SetBoolSigAction(BoolJoin.PrivacyMute, b =>
PostStatusMessage(new
{
volumes = new
{
master = new
{
privacyMuted = b
}
}
}));
for (uint i = 2; i <= 7; i++)
{
var index = i; // local scope for lambdas
EISC.SetUShortSigAction(index, u => // start at join 2
{
// need a dict in order to create the level-n property on auxFaders
var dict = new Dictionary<string, object>();
dict.Add("level-" + index, new { level = u });
PostStatusMessage(new
{
volumes = new
{
auxFaders = dict,
}
});
});
EISC.SetBoolSigAction(index, b =>
{
// need a dict in order to create the level-n property on auxFaders
var dict = new Dictionary<string, object>();
dict.Add("level-" + index, new { muted = b });
PostStatusMessage(new
{
volumes = new
{
auxFaders = dict,
}
});
});
}
EISC.SetUShortSigAction(UshortJoin.NumberOfAuxFaders, u =>
PostStatusMessage(new {
volumes = new {
numberOfAuxFaders = u,
}
}));
// shutdown things
EISC.SetSigTrueAction(BoolJoin.ShutdownCancel, new Action(() =>
PostMessage("/room/shutdown/", new
{
state = "wasCancelled"
})));
EISC.SetSigTrueAction(BoolJoin.ShutdownEnd, new Action(() =>
PostMessage("/room/shutdown/", new
{
state = "hasFinished"
})));
EISC.SetSigTrueAction(BoolJoin.ShutdownStart, new Action(() =>
PostMessage("/room/shutdown/", new
{
state = "hasStarted",
duration = EISC.UShortOutput[UshortJoin.ShutdownPromptDuration].UShortValue
})));
// Config things
EISC.SetSigTrueAction(BoolJoin.ConfigIsReady, LoadConfigValues);
// Activity modes
EISC.SetSigTrueAction(BoolJoin.ActivityShare, () => UpdateActivity(1));
EISC.SetSigTrueAction(BoolJoin.ActivityPhoneCall, () => UpdateActivity(2));
EISC.SetSigTrueAction(BoolJoin.ActivityVideoCall, () => UpdateActivity(3));
}
/// <summary>
/// Updates activity states
/// </summary>
void UpdateActivity(int mode)
{
PostStatusMessage(new
{
activityMode = mode,
});
}
/// <summary>
/// Reads in config values when the Simpl program is ready
/// </summary>
void LoadConfigValues()
{
Debug.Console(1, this, "Loading configuration from DDVC01 EISC bridge");
ConfigIsLoaded = false;
var co = ConfigReader.ConfigObject;
co.Info.RuntimeInfo.AppName = Assembly.GetExecutingAssembly().GetName().Name;
var version = Assembly.GetExecutingAssembly().GetName().Version;
co.Info.RuntimeInfo.AssemblyVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
//Room
//if (co.Rooms == null)
// always start fresh in case simpl changed
co.Rooms = new List<DeviceConfig>();
var rm = new DeviceConfig();
if (co.Rooms.Count == 0)
{
Debug.Console(0, this, "Adding room to config");
co.Rooms.Add(rm);
}
else
{
Debug.Console(0, this, "Replacing Room[0] in config");
co.Rooms[0] = rm;
}
rm.Name = EISC.StringOutput[StringJoin.ConfigRoomName].StringValue;
rm.Key = "room1";
rm.Type = "ddvc01";
DDVC01RoomPropertiesConfig rmProps;
if (rm.Properties == null)
rmProps = new DDVC01RoomPropertiesConfig();
else
rmProps = JsonConvert.DeserializeObject<DDVC01RoomPropertiesConfig>(rm.Properties.ToString());
rmProps.Help = new EssentialsHelpPropertiesConfig();
rmProps.Help.CallButtonText = EISC.StringOutput[StringJoin.ConfigHelpNumber].StringValue;
rmProps.Help.Message = EISC.StringOutput[StringJoin.ConfigHelpMessage].StringValue;
rmProps.Environment = new EssentialsEnvironmentPropertiesConfig(); // enabled defaults to false
rmProps.RoomPhoneNumber = EISC.StringOutput[StringJoin.ConfigRoomPhoneNumber].StringValue;
rmProps.RoomURI = EISC.StringOutput[StringJoin.ConfigRoomURI].StringValue;
rmProps.SpeedDials = new List<DDVC01SpeedDial>();
// This MAY need a check
rmProps.AudioCodecKey = "audioCodec";
rmProps.VideoCodecKey = "videoCodec";
// volume control names
var volCount = EISC.UShortOutput[UshortJoin.NumberOfAuxFaders].UShortValue;
//// use Volumes object or?
//rmProps.VolumeSliderNames = new List<string>();
//for(uint i = 701; i <= 700 + volCount; i++)
//{
// rmProps.VolumeSliderNames.Add(EISC.StringInput[i].StringValue);
//}
// There should be Mobile Control devices in here, I think...
if(co.Devices == null)
co.Devices = new List<DeviceConfig>();
// clear out previous DDVC devices
co.Devices.RemoveAll(d =>
d.Key.StartsWith("source-", StringComparison.OrdinalIgnoreCase)
|| d.Key.Equals("audioCodec", StringComparison.OrdinalIgnoreCase)
|| d.Key.Equals("videoCodec", StringComparison.OrdinalIgnoreCase));
rmProps.SourceListKey = "default";
rm.Properties = JToken.FromObject(rmProps);
// Source list! This might be brutal!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
var groupMap = GetSourceGroupDictionary();
co.SourceLists = new Dictionary<string,Dictionary<string,SourceListItem>>();
var newSl = new Dictionary<string, SourceListItem>();
// add "none" source if VTC present
if (!string.IsNullOrEmpty(rmProps.VideoCodecKey))
{
var codecOsd = new SourceListItem()
{
Name = "None",
IncludeInSourceList = true,
Order = 1,
Type = eSourceListItemType.Route,
SourceKey = ""
};
newSl.Add("Source-None", codecOsd);
}
// add sources...
for (uint i = 0; i <= 19; i++)
{
var name = EISC.StringOutput[StringJoin.SourceNameJoinStart + i].StringValue;
if (EISC.BooleanOutput[BoolJoin.UseSourceEnabled].BoolValue
&& !EISC.BooleanOutput[BoolJoin.SourceIsEnabledJoinStart + i].BoolValue)
{
continue;
}
else if(!EISC.BooleanOutput[BoolJoin.UseSourceEnabled].BoolValue && string.IsNullOrEmpty(name))
break;
var icon = EISC.StringOutput[StringJoin.SourceIconJoinStart + i].StringValue;
var key = EISC.StringOutput[StringJoin.SourceKeyJoinStart + i].StringValue;
var type = EISC.StringOutput[StringJoin.SourceTypeJoinStart + i].StringValue;
var disableShare = EISC.BooleanOutput[BoolJoin.SourceShareDisableJoinStart + i].BoolValue;
Debug.Console(0, this, "Adding source {0} '{1}'", key, name);
var newSLI = new SourceListItem{
Icon = icon,
Name = name,
Order = (int)i + 10,
SourceKey = key,
Type = eSourceListItemType.Route,
DisableCodecSharing = disableShare,
};
newSl.Add(key, newSLI);
string group = "genericsource";
if (groupMap.ContainsKey(type))
{
group = groupMap[type];
}
// add dev to devices list
var devConf = new DeviceConfig {
Group = group,
Key = key,
Name = name,
Type = type
};
co.Devices.Add(devConf);
if (group.ToLower().StartsWith("settopbox")) // Add others here as needed
{
SetupSourceFunctions(key);
}
}
co.SourceLists.Add("default", newSl);
// Build "audioCodec" config if we need
if (!string.IsNullOrEmpty(rmProps.AudioCodecKey))
{
var acFavs = new List<PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem>();
for (uint i = 0; i < 4; i++)
{
if (!EISC.GetBool(BoolJoin.SpeedDialVisibleStartJoin + i))
{
break;
}
acFavs.Add(new PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem()
{
Name = EISC.GetString(StringJoin.SpeedDialNameStartJoin + i),
Number = EISC.GetString(StringJoin.SpeedDialNumberStartJoin + i),
Type = PepperDash.Essentials.Devices.Common.Codec.eCodecCallType.Audio
});
}
var acProps = new
{
favorites = acFavs
};
var acStr = "audioCodec";
var acConf = new DeviceConfig()
{
Group = acStr,
Key = acStr,
Name = acStr,
Type = acStr,
Properties = JToken.FromObject(acProps)
};
co.Devices.Add(acConf);
}
// Build Video codec config
if (!string.IsNullOrEmpty(rmProps.VideoCodecKey))
{
// No favorites, for now?
var favs = new List<PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem>();
// cameras
var camsProps = new List<object>();
for (uint i = 0; i < 9; i++)
{
var name = EISC.GetString(i + StringJoin.CameraNearNameStart);
if (!string.IsNullOrEmpty(name))
{
camsProps.Add(new
{
name = name,
selector = "camera" + (i + 1),
});
}
}
var farName = EISC.GetString(StringJoin.CameraFarName);
if (!string.IsNullOrEmpty(farName))
{
camsProps.Add(new
{
name = farName,
selector = "cameraFar",
});
}
var props = new
{
favorites = favs,
cameras = camsProps,
};
var str = "videoCodec";
var conf = new DeviceConfig()
{
Group = str,
Key = str,
Name = str,
Type = str,
Properties = JToken.FromObject(props)
};
co.Devices.Add(conf);
}
Debug.Console(0, this, "******* CONFIG FROM DDVC: \r{0}", JsonConvert.SerializeObject(ConfigReader.ConfigObject, Formatting.Indented));
var handler = ConfigurationIsReady;
if (handler != null)
{
handler(this, new EventArgs());
}
ConfigIsLoaded = true;
}
/// <summary>
///
/// </summary>
void SendFullStatus()
{
if (ConfigIsLoaded)
{
var count = EISC.UShortOutput[UshortJoin.NumberOfAuxFaders].UShortValue;
Debug.Console(1, this, "The Fader Count is : {0}", count);
// build volumes object, serialize and put in content of method below
// Create auxFaders
var auxFaderDict = new Dictionary<string, Volume>();
for (uint i = 2; i <= count; i++)
{
auxFaderDict.Add("level-" + i,
new Volume("level-" + i,
EISC.UShortOutput[i].UShortValue,
EISC.BooleanOutput[i].BoolValue,
EISC.StringOutput[i].StringValue,
true,
"someting.png"));
}
var volumes = new Volumes();
volumes.Master = new Volume("master",
EISC.UShortOutput[UshortJoin.MasterVolumeLevel].UShortValue,
EISC.BooleanOutput[BoolJoin.MasterVolumeIsMuted].BoolValue,
EISC.StringOutput[1].StringValue,
true,
"something.png");
volumes.Master.HasPrivacyMute = true;
volumes.Master.PrivacyMuted = EISC.BooleanOutput[BoolJoin.PrivacyMute].BoolValue;
volumes.AuxFaders = auxFaderDict;
volumes.NumberOfAuxFaders = EISC.UShortInput[UshortJoin.NumberOfAuxFaders].UShortValue;
PostStatusMessage(new
{
activityMode = GetActivityMode(),
isOn = EISC.BooleanOutput[BoolJoin.RoomIsOn].BoolValue,
selectedSourceKey = EISC.StringOutput[StringJoin.SelectedSourceKey].StringValue,
volumes = volumes
});
}
else
{
PostStatusMessage(new
{
error = "systemNotReady"
});
}
}
/// <summary>
/// Returns the activity mode int
/// </summary>
/// <returns></returns>
int GetActivityMode()
{
if (EISC.BooleanOutput[BoolJoin.ActivityPhoneCall].BoolValue) return 2;
else if (EISC.BooleanOutput[BoolJoin.ActivityShare].BoolValue) return 1;
else if (EISC.BooleanOutput[BoolJoin.ActivityVideoCall].BoolValue) return 3;
return 0;
}
/// <summary>
/// Helper for posting status message
/// </summary>
/// <param name="contentObject">The contents of the content object</param>
void PostStatusMessage(object contentObject)
{
Parent.SendMessageToServer(JObject.FromObject(new
{
type = "/room/status/",
content = contentObject
}));
}
/// <summary>
///
/// </summary>
/// <param name="messageType"></param>
/// <param name="contentObject"></param>
void PostMessage(string messageType, object contentObject)
{
Parent.SendMessageToServer(JObject.FromObject(new
{
type = messageType,
content = contentObject
}));
}
/// <summary>
///
/// </summary>
/// <param name="currentDevice"></param>
/// <param name="args"></param>
void EISC_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args)
{
if (Debug.Level >= 1)
Debug.Console(1, this, "DDVC EISC change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
var uo = args.Sig.UserObject;
if (uo is Action<bool>)
(uo as Action<bool>)(args.Sig.BoolValue);
else if (uo is Action<ushort>)
(uo as Action<ushort>)(args.Sig.UShortValue);
else if (uo is Action<string>)
(uo as Action<string>)(args.Sig.StringValue);
}
/// <summary>
/// Returns the mapping of types to groups, for setting up devices.
/// </summary>
/// <returns></returns>
Dictionary<string, string> GetSourceGroupDictionary()
{
//type, group
var d = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "laptop", "pc" },
{ "pc", "pc" },
{ "wireless", "genericsource" },
{ "iptv", "settopbox" }
};
return d;
}
/// <summary>
/// updates the usercode from server
/// </summary>
protected override void UserCodeChange()
{
Debug.Console(1, this, "Server user code changed: {0}", UserCode);
EISC.StringInput[StringJoin.UserCodeToSystem].StringValue = UserCode;
EISC.StringInput[StringJoin.ServerUrl].StringValue = Parent.Config.ClientAppUrl;
}
}
}

View File

@@ -0,0 +1,441 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Room.MobileControl;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Common.AudioCodec;
namespace PepperDash.Essentials
{
public class MobileConrolEssentialsHuddleSpaceRoomBridge : MobileControlBridgeBase
{
public EssentialsRoomBase Room { get; private set; }
public VideoCodecBaseMessenger VCMessenger { get; private set; }
public AudioCodecBaseMessenger ACMessenger { get; private set; }
/// <summary>
///
/// </summary>
public override string RoomName
{
get
{
return Room.Name;
}
}
/// <summary>
///
/// </summary>
/// <param name="parent"></param>
/// <param name="room"></param>
public MobileConrolEssentialsHuddleSpaceRoomBridge(EssentialsRoomBase room):
base("mobileControlBridge-essentialsHuddle", "Essentials Mobile Control Bridge-Huddle")
{
Room = room;
}
/// <summary>
/// Override of base: calls base to add parent and then registers actions and events.
/// </summary>
/// <param name="parent"></param>
public override void AddParent(MobileControlSystemController parent)
{
base.AddParent(parent);
// we add actions to the messaging system with a path, and a related action. Custom action
// content objects can be handled in the controller's LineReceived method - and perhaps other
// sub-controller parsing could be attached to these classes, so that the systemController
// doesn't need to know about everything.
// Source Changes and room off
Parent.AddAction(string.Format(@"/room/{0}/status", Room.Key), new Action(() => SendFullStatus(Room)));
var routeRoom = Room as IRunRouteAction;
if(routeRoom != null)
Parent.AddAction(string.Format(@"/room/{0}/source", Room.Key), new Action<SourceSelectMessageContent>(c =>
routeRoom.RunRouteAction(c.SourceListItem)));
var defaultRoom = Room as IRunDefaultPresentRoute;
if(defaultRoom != null)
Parent.AddAction(string.Format(@"/room/{0}/defaultsource", Room.Key), new Action(() => defaultRoom.RunDefaultPresentRoute()));
var volumeRoom = Room as IHasCurrentVolumeControls;
if (volumeRoom != null)
{
Parent.AddAction(string.Format(@"/room/{0}/volumes/master/level", Room.Key), new Action<ushort>(u =>
(volumeRoom.CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(u)));
Parent.AddAction(string.Format(@"/room/{0}/volumes/master/muteToggle", Room.Key), new Action(() =>
volumeRoom.CurrentVolumeControls.MuteToggle()));
volumeRoom.CurrentVolumeDeviceChange += new EventHandler<VolumeDeviceChangeEventArgs>(Room_CurrentVolumeDeviceChange);
// Registers for initial volume events, if possible
var currentVolumeDevice = volumeRoom.CurrentVolumeControls as IBasicVolumeWithFeedback;
if (currentVolumeDevice != null)
{
currentVolumeDevice.MuteFeedback.OutputChange += MuteFeedback_OutputChange;
currentVolumeDevice.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
}
}
var sscRoom = Room as IHasCurrentSourceInfoChange;
if(sscRoom != null)
sscRoom.CurrentSourceChange += new SourceInfoChangeHandler(Room_CurrentSingleSourceChange);
var vcRoom = Room as IHasVideoCodec;
if (vcRoom != null && vcRoom.VideoCodec != null)
{
var codec = vcRoom.VideoCodec;
var key = vcRoom.VideoCodec.Key + "-" + parent.Key;
VCMessenger = new VideoCodecBaseMessenger(key, vcRoom.VideoCodec, "/device/videoCodec");
VCMessenger.RegisterWithAppServer(Parent);
vcRoom.IsSharingFeedback.OutputChange += new EventHandler<FeedbackEventArgs>(IsSharingFeedback_OutputChange);
}
var acRoom = Room as IHasAudioCodec;
if (acRoom != null && acRoom.AudioCodec != null)
{
var codec = acRoom.AudioCodec;
var key = acRoom.AudioCodec.Key + "-" + parent.Key;
ACMessenger = new AudioCodecBaseMessenger(key, acRoom.AudioCodec, "/device/audioCodec");
ACMessenger.RegisterWithAppServer(Parent);
}
var defCallRm = Room as IRunDefaultCallRoute;
if (defCallRm != null)
{
Parent.AddAction(string.Format(@"/room/{0}/activityVideo", Room.Key), new Action(()=>defCallRm.RunDefaultCallRoute()));
}
Parent.AddAction(string.Format(@"/room/{0}/shutdownStart", Room.Key), new Action(() => Room.StartShutdown(eShutdownType.Manual)));
Parent.AddAction(string.Format(@"/room/{0}/shutdownEnd", Room.Key), new Action(() => Room.ShutdownPromptTimer.Finish()));
Parent.AddAction(string.Format(@"/room/{0}/shutdownCancel", Room.Key), new Action(() => Room.ShutdownPromptTimer.Cancel()));
Room.OnFeedback.OutputChange += OnFeedback_OutputChange;
Room.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange;
Room.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange;
Room.ShutdownPromptTimer.HasStarted += ShutdownPromptTimer_HasStarted;
Room.ShutdownPromptTimer.HasFinished += ShutdownPromptTimer_HasFinished;
Room.ShutdownPromptTimer.WasCancelled += ShutdownPromptTimer_WasCancelled;
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void IsSharingFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
// sharing source
string shareText;
bool isSharing;
#warning This share update needs to happen on source change as well!
var vcRoom = Room as IHasVideoCodec;
var srcInfoRoom = Room as IHasCurrentSourceInfoChange;
if (vcRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue && srcInfoRoom.CurrentSourceInfo != null)
{
shareText = srcInfoRoom.CurrentSourceInfo.PreferredName;
isSharing = true;
}
else
{
shareText = "None";
isSharing = false;
}
PostStatusMessage(new
{
share = new
{
currentShareText = shareText,
isSharing = isSharing
}
});
}
/// <summary>
/// Helper for posting status message
/// </summary>
/// <param name="contentObject">The contents of the content object</param>
void PostStatusMessage(object contentObject)
{
Parent.SendMessageToServer(JObject.FromObject(new
{
type = "/room/status/",
content = contentObject
}));
}
/// <summary>
/// Handler for cancelled shutdown
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void ShutdownPromptTimer_WasCancelled(object sender, EventArgs e)
{
JObject roomStatus = new JObject();
roomStatus.Add("state", "wasCancelled");
JObject message = new JObject();
message.Add("type", "/room/shutdown/");
message.Add("content", roomStatus);
Parent.SendMessageToServer(message);
}
/// <summary>
/// Handler for when shutdown finishes
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void ShutdownPromptTimer_HasFinished(object sender, EventArgs e)
{
JObject roomStatus = new JObject();
roomStatus.Add("state", "hasFinished");
JObject message = new JObject();
message.Add("type", "/room/shutdown/");
message.Add("content", roomStatus);
Parent.SendMessageToServer(message);
}
/// <summary>
/// Handler for when shutdown starts
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void ShutdownPromptTimer_HasStarted(object sender, EventArgs e)
{
JObject roomStatus = new JObject();
roomStatus.Add("state", "hasStarted");
roomStatus.Add("duration", Room.ShutdownPromptTimer.SecondsToCount);
JObject message = new JObject();
message.Add("type", "/room/shutdown/");
message.Add("content", roomStatus);
Parent.SendMessageToServer(message);
// equivalent JS message:
// Post( { type: '/room/status/', content: { shutdown: 'hasStarted', duration: Room.ShutdownPromptTimer.SecondsToCount })
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void IsWarmingUpFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
PostStatusMessage(new
{
isWarmingUp = e.BoolValue
});
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
PostStatusMessage(new
{
isCoolingDown = e.BoolValue
});
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void OnFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
PostStatusMessage(new
{
isOn = e.BoolValue
});
}
void Room_CurrentVolumeDeviceChange(object sender, VolumeDeviceChangeEventArgs e)
{
if (e.OldDev is IBasicVolumeWithFeedback)
{
var oldDev = e.OldDev as IBasicVolumeWithFeedback;
oldDev.MuteFeedback.OutputChange -= MuteFeedback_OutputChange;
oldDev.VolumeLevelFeedback.OutputChange -= VolumeLevelFeedback_OutputChange;
}
if (e.NewDev is IBasicVolumeWithFeedback)
{
var newDev = e.NewDev as IBasicVolumeWithFeedback;
newDev.MuteFeedback.OutputChange += MuteFeedback_OutputChange;
newDev.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
}
}
/// <summary>
/// Event handler for mute changes
/// </summary>
void MuteFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
PostStatusMessage(new
{
volumes = new
{
master = new
{
muted = e.BoolValue
}
}
});
}
/// <summary>
/// Handles Volume changes on room
/// </summary>
void VolumeLevelFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
PostStatusMessage(new
{
volumes = new
{
master = new
{
level = e.IntValue
}
}
});
}
void Room_CurrentSingleSourceChange(PepperDash.Essentials.Core.SourceListItem info, ChangeType type)
{
/* Example message
* {
"type":"/room/status",
"content": {
"selectedSourceKey": "off",
}
}
*/
if (type == ChangeType.WillChange)
{
// Disconnect from previous source
if (info != null)
{
var previousDev = info.SourceDevice;
// device type interfaces
if (previousDev is ISetTopBoxControls)
(previousDev as ISetTopBoxControls).UnlinkActions(Parent);
// common interfaces
if (previousDev is IChannel)
(previousDev as IChannel).UnlinkActions(Parent);
if (previousDev is IColor)
(previousDev as IColor).UnlinkActions(Parent);
if (previousDev is IDPad)
(previousDev as IDPad).UnlinkActions(Parent);
if (previousDev is IDvr)
(previousDev as IDvr).UnlinkActions(Parent);
if (previousDev is INumericKeypad)
(previousDev as INumericKeypad).UnlinkActions(Parent);
if (previousDev is IPower)
(previousDev as IPower).UnlinkActions(Parent);
if (previousDev is ITransport)
(previousDev as ITransport).UnlinkActions(Parent);
}
}
else // did change
{
if (info != null)
{
var dev = info.SourceDevice;
if (dev is ISetTopBoxControls)
(dev as ISetTopBoxControls).LinkActions(Parent);
if (dev is IChannel)
(dev as IChannel).LinkActions(Parent);
if (dev is IColor)
(dev as IColor).LinkActions(Parent);
if (dev is IDPad)
(dev as IDPad).LinkActions(Parent);
if (dev is IDvr)
(dev as IDvr).LinkActions(Parent);
if (dev is INumericKeypad)
(dev as INumericKeypad).LinkActions(Parent);
if (dev is IPower)
(dev as IPower).LinkActions(Parent);
if (dev is ITransport)
(dev as ITransport).LinkActions(Parent);
var srcRm = Room as IHasCurrentSourceInfoChange;
if (srcRm != null)
{
PostStatusMessage(new
{
selectedSourceKey = srcRm.CurrentSourceInfoKey
});
}
}
}
}
/// <summary>
/// Posts the full status of the room to the server
/// </summary>
/// <param name="room"></param>
void SendFullStatus(EssentialsRoomBase room)
{
var sourceKey = room is IHasCurrentSourceInfoChange ? (room as IHasCurrentSourceInfoChange).CurrentSourceInfoKey : null;
var rmVc = room as IHasCurrentVolumeControls;
var volumes = new Volumes();
if (rmVc != null)
{
var vc = rmVc.CurrentVolumeControls as IBasicVolumeWithFeedback;
if (vc != null)
{
volumes.Master = new Volume("master", vc.VolumeLevelFeedback.UShortValue, vc.MuteFeedback.BoolValue, "Volume", true, "");
}
}
PostStatusMessage(new
{
//calls = GetCallsMessageObject(),
isOn = room.OnFeedback.BoolValue,
selectedSourceKey = sourceKey,
//vtc = GetVtcCallsMessageObject(),
volumes = volumes
});
}
}
/// <summary>
///
/// </summary>
public class SourceSelectMessageContent
{
public string SourceListItem { get; set; }
}
/// <summary>
///
/// </summary>
/// <param name="b"></param>
public delegate void PressAndHoldAction(bool b);
}

View File

@@ -1,13 +1,19 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Room.MobileControl
{
/// <summary>
/// Represents a SourceDeviceMapDictionary
/// Contains all of the default joins that map to API funtions
/// </summary>
public class SourceDeviceMapDictionary : Dictionary<string, uint>
{
public SourceDeviceMapDictionary()
public SourceDeviceMapDictionary(): base()
{
var dictionary = new Dictionary<string, uint>
{
@@ -35,6 +41,7 @@ namespace PepperDash.Essentials.Room.MobileControl
{"preset22", 122},
{"preset23", 123},
{"preset24", 124},
{"num0", 130},
{"num1", 131},
{"num2", 132},
@@ -74,7 +81,7 @@ namespace PepperDash.Essentials.Room.MobileControl
{"guide", 166},
{"reboot", 167},
{"dvrList", 168},
{"replay", 169},
{"replay", 169},
{"play", 170},
{"select", 171},
{"record", 172},
@@ -85,11 +92,12 @@ namespace PepperDash.Essentials.Room.MobileControl
{"powerOn", 177},
{"powerOff", 178},
{"dot", 179}
};
foreach (var item in dictionary)
{
Add(item.Key, item.Value);
this.Add(item.Key, item.Value);
}
}
}

View File

@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Room.MobileControl
{
public class Volumes
{
[JsonProperty("master")]
public Volume Master { get; set; }
[JsonProperty("auxFaders")]
public Dictionary<string, Volume> AuxFaders { get; set; }
[JsonProperty("numberOfAuxFaders")]
public int NumberOfAuxFaders { get; set; }
public Volumes()
{
AuxFaders = new Dictionary<string, Volume>();
}
}
public class Volume
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("level")]
public ushort Level { get; set; }
[JsonProperty("muted")]
public bool Muted { get; set; }
[JsonProperty("label")]
public string Label { get; set; }
[JsonProperty("hasMute")]
public bool HasMute { get; set; }
[JsonProperty("hasPrivacyMute")]
public bool HasPrivacyMute { get; set; }
[JsonProperty("privacyMuted")]
public bool PrivacyMuted { get; set; }
[JsonProperty("muteIcon")]
public string MuteIcon { get; set; }
public Volume(string key, ushort level, bool muted, string label, bool hasMute, string muteIcon)
{
Key = key;
Level = level;
Muted = muted;
Label = label;
HasMute = hasMute;
MuteIcon = muteIcon;
}
}
}

View File

@@ -1,16 +1,24 @@
using System;
using PepperDash.Essentials.Core;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Room.Config
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Devices.Common.DSP;
using PepperDash.Essentials.DM;
namespace PepperDash.Essentials
{
/// <summary>
/// Represents a EssentialsRoomVolumesConfig
///
/// </summary>
public class EssentialsRoomVolumesConfig
{
/// <summary>
/// Gets or sets the Master
/// </summary>
public EssentialsVolumeLevelConfig Master { get; set; }
public EssentialsVolumeLevelConfig Program { get; set; }
public EssentialsVolumeLevelConfig AudioCallRx { get; set; }
@@ -18,21 +26,12 @@ namespace PepperDash.Essentials.Room.Config
}
/// <summary>
/// Represents a EssentialsVolumeLevelConfig
///
/// </summary>
public class EssentialsVolumeLevelConfig
{
/// <summary>
/// Gets or sets the DeviceKey
/// </summary>
public string DeviceKey { get; set; }
/// <summary>
/// Gets or sets the Label
/// </summary>
public string Label { get; set; }
/// <summary>
/// Gets or sets the Level
/// </summary>
public int Level { get; set; }
/// <summary>
@@ -40,8 +39,6 @@ namespace PepperDash.Essentials.Room.Config
/// </summary>
public IBasicVolumeWithFeedback GetDevice()
{
throw new NotImplementedException("This method references DM CHASSIS Directly");
/*
// DM output card format: deviceKey--output~number, dm8x8-1--output~4
var match = Regex.Match(DeviceKey, @"([-_\w]+)--(\w+)~(\d+)");
if (match.Success)
@@ -58,7 +55,7 @@ namespace PepperDash.Essentials.Room.Config
return null;
}
// DSP/DMPS format: deviceKey--levelName, biampTesira-1--master
// DSP format: deviceKey--levelName, biampTesira-1--master
match = Regex.Match(DeviceKey, @"([-_\w]+)--(.+)");
if (match.Success)
{
@@ -70,34 +67,11 @@ namespace PepperDash.Essentials.Room.Config
if (dsp.LevelControlPoints.ContainsKey(levelTag)) // should always...
return dsp.LevelControlPoints[levelTag];
}
var dmps = DeviceManager.GetDeviceForKey(devKey) as DmpsAudioOutputController;
if (dmps != null)
{
var levelTag = match.Groups[2].Value;
switch (levelTag)
{
case "master":
return dmps.MasterVolumeLevel;
case "source":
return dmps.SourceVolumeLevel;
case "micsmaster":
return dmps.MicsMasterVolumeLevel;
case "codec1":
return dmps.Codec1VolumeLevel;
case "codec2":
return dmps.Codec2VolumeLevel;
default:
return dmps.MasterVolumeLevel;
}
}
// No volume for some reason. We have failed as developers
return null;
}
return null;
}
* */
}
}
}

View File

@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common;
using PepperDash.Essentials.DM.AirMedia;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class AirMediaControllerApiExtensions
{
public static void LinkToApi(this AirMediaController airMedia, BasicTriList trilist, uint joinStart, string joinMapKey)
{
AirMediaControllerJoinMap joinMap = new AirMediaControllerJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<AirMediaControllerJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, "Linking to Airmedia: {0}", airMedia.Name);
trilist.StringInput[joinMap.Name].StringValue = airMedia.Name;
var commMonitor = airMedia as ICommunicationMonitor;
if (commMonitor != null)
{
commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline]);
}
airMedia.IsInSessionFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsInSession]);
airMedia.HdmiVideoSyncDetectedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.HdmiVideoSync]);
trilist.SetSigTrueAction(joinMap.AutomaticInputRoutingEnabled, new Action( airMedia.AirMedia.DisplayControl.EnableAutomaticRouting));
trilist.SetSigFalseAction(joinMap.AutomaticInputRoutingEnabled, new Action( airMedia.AirMedia.DisplayControl.DisableAutomaticRouting));
airMedia.AutomaticInputRoutingEnabledFeedback.LinkInputSig(trilist.BooleanInput[joinMap.AutomaticInputRoutingEnabled]);
trilist.SetUShortSigAction(joinMap.VideoOut, new Action<ushort>((u) => airMedia.SelectVideoOut(u)));
airMedia.VideoOutFeedback.LinkInputSig(trilist.UShortInput[joinMap.VideoOut]);
airMedia.ErrorFeedback.LinkInputSig(trilist.UShortInput[joinMap.ErrorFB]);
airMedia.NumberOfUsersConnectedFeedback.LinkInputSig(trilist.UShortInput[joinMap.NumberOfUsersConnectedFB]);
trilist.SetUShortSigAction(joinMap.LoginCode, new Action<ushort>((u) => airMedia.AirMedia.AirMedia.LoginCode.UShortValue = u));
airMedia.LoginCodeFeedback.LinkInputSig(trilist.UShortInput[joinMap.LoginCode]);
airMedia.ConnectionAddressFeedback.LinkInputSig(trilist.StringInput[joinMap.ConnectionAddressFB]);
airMedia.HostnameFeedback.LinkInputSig(trilist.StringInput[joinMap.HostnameFB]);
airMedia.SerialNumberFeedback.LinkInputSig(trilist.StringInput[joinMap.SerialNumberFeedback]);
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class AppleTvApiExtensions
{
public static void LinkToApi(this AppleTV appleTv, BasicTriList trilist, uint joinStart, string joinMapKey)
{
AppleTvJoinMap joinMap = new AppleTvJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if(!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<AppleTvJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, "Linking to Bridge Type {0}", appleTv.GetType().Name.ToString());
trilist.SetBoolSigAction(joinMap.UpArrow, (b) => appleTv.Up(b));
trilist.SetBoolSigAction(joinMap.DnArrow, (b) => appleTv.Down(b));
trilist.SetBoolSigAction(joinMap.LeftArrow, (b) => appleTv.Left(b));
trilist.SetBoolSigAction(joinMap.RightArrow, (b) => appleTv.Right(b));
trilist.SetBoolSigAction(joinMap.Select, (b) => appleTv.Select(b));
trilist.SetBoolSigAction(joinMap.Menu, (b) => appleTv.Menu(b));
trilist.SetBoolSigAction(joinMap.PlayPause, (b) => appleTv.Play(b));
}
}
}

View File

@@ -0,0 +1,290 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.EthernetCommunication;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Lighting;
using PepperDash.Essentials.Core.Devices;
using PepperDash.Essentials.Devices.Common;
using PepperDash.Essentials.Devices.Common.Cameras;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.CrestronIO;
using PepperDash.Essentials.DM;
//using PepperDash.Essentials.Devices.Common.Cameras;
namespace PepperDash.Essentials.Bridges
{
/// <summary>
/// Base class for all bridge class variants
/// </summary>
public class BridgeBase : Device
{
public BridgeApi Api { get; private set; }
public BridgeBase(string key) :
base(key)
{
}
}
/// <summary>
/// Base class for bridge API variants
/// </summary>
public abstract class BridgeApi : Device
{
public BridgeApi(string key) :
base(key)
{
}
}
/// <summary>
/// Bridge API using EISC
/// </summary>
public class EiscApi : BridgeApi
{
public EiscApiPropertiesConfig PropertiesConfig { get; private set; }
public ThreeSeriesTcpIpEthernetIntersystemCommunications Eisc { get; private set; }
public EiscApi(DeviceConfig dc) :
base(dc.Key)
{
PropertiesConfig = JsonConvert.DeserializeObject<EiscApiPropertiesConfig>(dc.Properties.ToString());
Eisc = new ThreeSeriesTcpIpEthernetIntersystemCommunications(PropertiesConfig.Control.IpIdInt, PropertiesConfig.Control.TcpSshProperties.Address, Global.ControlSystem);
Eisc.SigChange += new Crestron.SimplSharpPro.DeviceSupport.SigEventHandler(Eisc_SigChange);
Eisc.Register();
AddPostActivationAction( () =>
{
Debug.Console(1, this, "Linking Devices...");
foreach (var d in PropertiesConfig.Devices)
{
var device = DeviceManager.GetDeviceForKey(d.DeviceKey);
if (device != null)
{
if (device is IBridge) // Check for this first to allow bridges in plugins to override existing bridges that apply to the same type.
{
(device as IBridge).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is PepperDash.Essentials.Core.Monitoring.SystemMonitorController)
{
(device as PepperDash.Essentials.Core.Monitoring.SystemMonitorController).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is GenericComm)
{
(device as GenericComm).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is CameraBase)
{
(device as CameraBase).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is PepperDash.Essentials.Core.DisplayBase)
{
(device as DisplayBase).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is DmChassisController) {
(device as DmChassisController).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is DmBladeChassisController) {
(device as DmBladeChassisController).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is DmpsRoutingController)
{
(device as DmpsRoutingController).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is DmpsAudioOutputController)
{
(device as DmpsAudioOutputController).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is DmTxControllerBase)
{
(device as DmTxControllerBase).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is DmRmcControllerBase)
{
(device as DmRmcControllerBase).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is GenericRelayDevice)
{
(device as GenericRelayDevice).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is IDigitalInput)
{
(device as IDigitalInput).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is AppleTV)
{
(device as AppleTV).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is HdMdxxxCEController)
{
(device as HdMdxxxCEController).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is LightingBase)
{
(device as LightingBase).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is DigitalLogger)
{
(device as DigitalLogger).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
else if (device is PepperDash.Essentials.Devices.Common.Occupancy.GlsOccupancySensorBaseController)
{
(device as PepperDash.Essentials.Devices.Common.Occupancy.GlsOccupancySensorBaseController).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
continue;
}
}
}
Debug.Console(1, this, "Devices Linked.");
});
}
/// <summary>
/// Used for debugging to trigger an action based on a join number and type
/// </summary>
/// <param name="join"></param>
/// <param name="type"></param>
public void ExecuteJoinAction(uint join, string type, object state)
{
try
{
switch (type.ToLower())
{
case "digital":
{
var uo = Eisc.BooleanOutput[join].UserObject as Action<bool>;
if (uo != null)
{
Debug.Console(1, this, "Executing Action: {0}", uo.ToString());
uo(Convert.ToBoolean(state));
}
else
Debug.Console(1, this, "User Action is null. Nothing to Execute");
break;
}
case "analog":
{
var uo = Eisc.BooleanOutput[join].UserObject as Action<ushort>;
if (uo != null)
{
Debug.Console(1, this, "Executing Action: {0}", uo.ToString());
uo(Convert.ToUInt16(state));
}
else
Debug.Console(1, this, "User Action is null. Nothing to Execute"); break;
}
case "serial":
{
var uo = Eisc.BooleanOutput[join].UserObject as Action<string>;
if (uo != null)
{
Debug.Console(1, this, "Executing Action: {0}", uo.ToString());
uo(Convert.ToString(state));
}
else
Debug.Console(1, this, "User Action is null. Nothing to Execute");
break;
}
default:
{
Debug.Console(1, "Unknown join type. Use digital/serial/analog");
break;
}
}
}
catch (Exception e)
{
Debug.Console(1, this, "Error: {0}", e);
}
}
/// <summary>
/// Handles incoming sig changes
/// </summary>
/// <param name="currentDevice"></param>
/// <param name="args"></param>
void Eisc_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args)
{
try
{
if (Debug.Level >= 1)
Debug.Console(1, this, "EiscApi change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
var uo = args.Sig.UserObject;
if (uo != null)
{
Debug.Console(1, this, "Executing Action: {0}", uo.ToString());
if (uo is Action<bool>)
(uo as Action<bool>)(args.Sig.BoolValue);
else if (uo is Action<ushort>)
(uo as Action<ushort>)(args.Sig.UShortValue);
else if (uo is Action<string>)
(uo as Action<string>)(args.Sig.StringValue);
}
}
catch (Exception e)
{
Debug.Console(2, this, "Error in Eisc_SigChange handler: {0}", e);
}
}
}
public class EiscApiPropertiesConfig
{
[JsonProperty("control")]
public EssentialsControlPropertiesConfig Control { get; set; }
[JsonProperty("devices")]
public List<ApiDevice> Devices { get; set; }
public class ApiDevice
{
[JsonProperty("deviceKey")]
public string DeviceKey { get; set; }
[JsonProperty("joinStart")]
public uint JoinStart { get; set; }
[JsonProperty("joinMapKey")]
public string JoinMapKey { get; set; }
}
}
}

View File

@@ -0,0 +1,139 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Core;
using PepperDash.Essentials.Core.Routing;
using PepperDash.Essentials.Bridges;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.EthernetCommunication;
namespace PepperDash.Essentials
{
public class BridgeFactory
{
public static IKeyed GetDevice(DeviceConfig dc)
{
// ? why is this static JTA 2018-06-13?
var key = dc.Key;
var name = dc.Name;
var type = dc.Type;
var properties = dc.Properties;
var propAnon = new { };
var typeName = dc.Type.ToLower();
var groupName = dc.Group.ToLower();
//Debug.Console(2, "Name {0}, Key {1}, Type {2}, Properties {3}", name, key, type, properties.ToString());
if (typeName == "eiscapi")
{
return new EiscApi(dc);
}
return null;
}
}
public class CommBridge : Device
{
public CommBridgeProperties Properties { get; private set; }
public List<IBasicCommunication> CommDevices { get; private set; }
public CommBridge(string key, string name, JToken properties)
: base(key, name)
{
Properties = JsonConvert.DeserializeObject<CommBridgeProperties>(properties.ToString());
}
public override bool CustomActivate()
{
// Create EiscApis
if (Properties.Eiscs != null)
{
foreach (var eisc in Properties.Eiscs)
{
var ApiEisc = new BridgeApiEisc(eisc.IpId, eisc.Hostname);
}
}
foreach (var deviceKey in Properties.CommDevices)
{
var device = DeviceManager.GetDeviceForKey(deviceKey);
if (device != null)
{
Debug.Console(0, "deviceKey {0} Found in Device Manager", device.Key);
CommDevices.Add(device as IBasicCommunication);
}
else
{
Debug.Console(0, "deviceKey {0} Not Found in Device Manager", deviceKey);
}
}
// Iterate through all the CommDevices and link up their Actions and Feedbacks
Debug.Console(0, "Bridge {0} Activated", this.Name);
return true;
}
}
public class EiscBridgeProperties
{
public string ParentDeviceKey { get; set; }
public eApiType ApiType { get; set; }
public List<EiscProperties> Eiscs { get; set; }
public string ApiOverrideFilePath { get; set; }
public class EiscProperties
{
public string IpId { get; set; }
public string Hostname { get; set; }
}
}
public class CommBridgeProperties : EiscBridgeProperties
{
public List<string> CommDevices { get; set; }
}
public enum eApiType { Eisc = 0 }
public class BridgeApiEisc
{
public uint Ipid { get; private set; }
public ThreeSeriesTcpIpEthernetIntersystemCommunications Eisc { get; private set; }
public BridgeApiEisc(string ipid, string hostname)
{
Ipid = (UInt32)int.Parse(ipid, System.Globalization.NumberStyles.HexNumber);
Eisc = new ThreeSeriesTcpIpEthernetIntersystemCommunications(Ipid, hostname, Global.ControlSystem);
Eisc.Register();
Eisc.SigChange += Eisc_SigChange;
Debug.Console(0, "BridgeApiEisc Created at Ipid {0}", ipid);
}
void Eisc_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args)
{
if (Debug.Level >= 1)
Debug.Console(1, "BridgeApiEisc change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
var uo = args.Sig.UserObject;
if (uo is Action<bool>)
(uo as Action<bool>)(args.Sig.BoolValue);
else if (uo is Action<ushort>)
(uo as Action<ushort>)(args.Sig.UShortValue);
else if (uo is Action<string>)
(uo as Action<string>)(args.Sig.StringValue);
}
}
}

View File

@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Core;
using PepperDash.Essentials.Core.Routing;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.EthernetCommunication;
using PepperDash.Essentials.Bridges;
namespace PepperDash.Essentials {
public class BridgeFactory {
public static IKeyed GetDevice(PepperDash.Essentials.Core.Config.DeviceConfig dc) {
// ? why is this static JTA 2018-06-13?
var key = dc.Key;
var name = dc.Name;
var type = dc.Type;
var properties = dc.Properties;
var propAnon = new { };
JsonConvert.DeserializeAnonymousType(dc.Properties.ToString(), propAnon);
var typeName = dc.Type.ToLower();
var groupName = dc.Group.ToLower();
Debug.Console(2, "Name {0}, Key {1}, Type {2}, Properties {3}", name, key, type, properties.ToString());
if (typeName == "essentialdm")
{
return new EssentialDM(key, name, properties);
}
else if (typeName == "essentialcomm")
{
Debug.Console(2, "Launch Essential Comm");
return new EssentialComm(key, name, properties);
}
else if (typeName == "essentialdsp")
{
Debug.Console(2, "Launch EssentialDsp");
return new EssentialDsp(key, name, properties);
}
else if (typeName == "essentialstvone")
{
Debug.Console(2, "Launch essentialstvone");
return new EssentialsTVOne(key, name, properties);
}
else if (typeName == "essentialslighting")
{
Debug.Console(2, "Launch essentialslighting");
return new EssentialsLightsBridge(key, name, properties);
}
else if (typeName == "eiscapi")
{
return new EiscApi(dc);
}
return null;
}
}
public class BridgeApiEisc {
public uint Ipid;
public ThreeSeriesTcpIpEthernetIntersystemCommunications Eisc;
public BridgeApiEisc(string ipid) {
Ipid = (UInt32)int.Parse(ipid, System.Globalization.NumberStyles.HexNumber);
Eisc = new ThreeSeriesTcpIpEthernetIntersystemCommunications(Ipid, "127.0.0.2", Global.ControlSystem);
Eisc.Register();
Eisc.SigChange += Eisc_SigChange;
Debug.Console(2, "BridgeApiEisc Created at Ipid {0}", ipid);
}
void Eisc_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args) {
if (Debug.Level >= 1)
Debug.Console(2, "DDVC EISC change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
var uo = args.Sig.UserObject;
if (uo is Action<bool>)
(uo as Action<bool>)(args.Sig.BoolValue);
else if (uo is Action<ushort>)
(uo as Action<ushort>)(args.Sig.UShortValue);
else if (uo is Action<string>)
(uo as Action<string>)(args.Sig.StringValue);
}
}
}

View File

@@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common;
using PepperDash.Essentials.Devices.Common.Cameras;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class CameraControllerApiExtensions
{
public static void LinkToApi(this PepperDash.Essentials.Devices.Common.Cameras.CameraBase cameraDevice, BasicTriList trilist, uint joinStart, string joinMapKey)
{
CameraControllerJoinMap joinMap = new CameraControllerJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<CameraControllerJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, "Linking to Bridge Type {0}", cameraDevice.GetType().Name.ToString());
var commMonitor = cameraDevice as ICommunicationMonitor;
commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline]);
var ptzCamera = cameraDevice as IHasCameraPtzControl;
if (ptzCamera != null)
{
trilist.SetBoolSigAction(joinMap.Left, (b) =>
{
if (b)
{
ptzCamera.PanLeft();
}
else
{
ptzCamera.PanStop();
}
});
trilist.SetBoolSigAction(joinMap.Right, (b) =>
{
if (b)
{
ptzCamera.PanRight();
}
else
{
ptzCamera.PanStop();
}
});
trilist.SetBoolSigAction(joinMap.Up, (b) =>
{
if (b)
{
ptzCamera.TiltUp();
}
else
{
ptzCamera.TiltStop();
}
});
trilist.SetBoolSigAction(joinMap.Down, (b) =>
{
if (b)
{
ptzCamera.TiltDown();
}
else
{
ptzCamera.TiltStop();
}
});
trilist.SetBoolSigAction(joinMap.ZoomIn, (b) =>
{
if (b)
{
ptzCamera.ZoomIn();
}
else
{
ptzCamera.ZoomStop();
}
});
trilist.SetBoolSigAction(joinMap.ZoomOut, (b) =>
{
if (b)
{
ptzCamera.ZoomOut();
}
else
{
ptzCamera.ZoomStop();
}
});
}
if (cameraDevice.GetType().Name.ToString().ToLower() == "cameravisca")
{
var viscaCamera = cameraDevice as PepperDash.Essentials.Devices.Common.Cameras.CameraVisca;
trilist.SetSigTrueAction(joinMap.PowerOn, () => viscaCamera.PowerOn());
trilist.SetSigTrueAction(joinMap.PowerOff, () => viscaCamera.PowerOff());
viscaCamera.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn]);
viscaCamera.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff]);
viscaCamera.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline]);
for (int i = 0; i < joinMap.NumberOfPresets; i++)
{
int tempNum = i;
trilist.SetSigTrueAction((ushort)(joinMap.PresetRecallOffset + tempNum), () =>
{
viscaCamera.RecallPreset(tempNum);
});
trilist.SetSigTrueAction((ushort)(joinMap.PresetSaveOffset + tempNum), () =>
{
viscaCamera.SavePreset(tempNum);
});
}
}
}
}
}

View File

@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class DigitalLoggerApiExtensions
{
public static void LinkToApi(this DigitalLogger DigitalLogger, BasicTriList trilist, uint joinStart, string joinMapKey)
{
DigitalLoggerJoinMap joinMap = new DigitalLoggerJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<DigitalLoggerJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
Debug.Console(1, DigitalLogger, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
for (uint i = 1; i <= DigitalLogger.CircuitCount; i++)
{
var circuit = i;
DigitalLogger.CircuitNameFeedbacks[circuit - 1].LinkInputSig(trilist.StringInput[joinMap.CircuitNames + circuit]);
DigitalLogger.CircuitIsCritical[circuit - 1].LinkInputSig(trilist.BooleanInput[joinMap.CircuitIsCritical + circuit]);
DigitalLogger.CircuitState[circuit - 1].LinkInputSig(trilist.BooleanInput[joinMap.CircuitState + circuit]);
trilist.SetSigTrueAction(joinMap.CircuitCycle + circuit, () => DigitalLogger.CycleCircuit(circuit - 1));
trilist.SetSigTrueAction(joinMap.CircuitOnCmd + circuit, () => DigitalLogger.TurnOnCircuit(circuit - 1));
trilist.SetSigTrueAction(joinMap.CircuitOffCmd + circuit, () => DigitalLogger.TurnOffCircuit(circuit - 1));
}
}
}
}

View File

@@ -0,0 +1,153 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class DisplayControllerApiExtensions
{
public static void LinkToApi(this PepperDash.Essentials.Core.DisplayBase displayDevice, BasicTriList trilist, uint joinStart, string joinMapKey)
{
int inputNumber = 0;
IntFeedback inputNumberFeedback;
List<string> inputKeys = new List<string>();
DisplayControllerJoinMap joinMap = new DisplayControllerJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if(!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<DisplayControllerJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
Debug.Console(1, "Linking to Trilist '{0}'",trilist.ID.ToString("X"));
Debug.Console(0, "Linking to Display: {0}", displayDevice.Name);
trilist.StringInput[joinMap.Name].StringValue = displayDevice.Name;
var commMonitor = displayDevice as ICommunicationMonitor;
if (commMonitor != null)
{
commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline]);
}
inputNumberFeedback = new IntFeedback(() => { return inputNumber; });
// Two way feedbacks
var twoWayDisplay = displayDevice as PepperDash.Essentials.Core.TwoWayDisplayBase;
if (twoWayDisplay != null)
{
trilist.SetBool(joinMap.IsTwoWayDisplay, true);
twoWayDisplay.CurrentInputFeedback.OutputChange += new EventHandler<FeedbackEventArgs>(CurrentInputFeedback_OutputChange);
inputNumberFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputSelect]);
}
// Power Off
trilist.SetSigTrueAction(joinMap.PowerOff, () =>
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOff();
});
displayDevice.PowerIsOnFeedback.OutputChange += new EventHandler<FeedbackEventArgs>( (o,a) => {
if (!a.BoolValue)
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
}
else
{
inputNumber = 0;
inputNumberFeedback.FireUpdate();
}
});
displayDevice.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff]);
// PowerOn
trilist.SetSigTrueAction(joinMap.PowerOn, () =>
{
inputNumber = 0;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOn();
});
displayDevice.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn]);
int count = 1;
foreach (var input in displayDevice.InputPorts)
{
inputKeys.Add(input.Key.ToString());
var tempKey = inputKeys.ElementAt(count - 1);
trilist.SetSigTrueAction((ushort)(joinMap.InputSelectOffset + count), () => { displayDevice.ExecuteSwitch(displayDevice.InputPorts[tempKey].Selector); });
Debug.Console(2, displayDevice, "Setting Input Select Action on Digital Join {0} to Input: {1}", joinMap.InputSelectOffset + count, displayDevice.InputPorts[tempKey].Key.ToString());
trilist.StringInput[(ushort)(joinMap.InputNamesOffset + count)].StringValue = input.Key.ToString();
count++;
}
Debug.Console(2, displayDevice, "Setting Input Select Action on Analog Join {0}", joinMap.InputSelect);
trilist.SetUShortSigAction(joinMap.InputSelect, (a) =>
{
if (a == 0)
{
displayDevice.PowerOff();
inputNumber = 0;
}
else if (a > 0 && a < displayDevice.InputPorts.Count && a != inputNumber)
{
displayDevice.ExecuteSwitch(displayDevice.InputPorts.ElementAt(a - 1).Selector);
inputNumber = a;
}
else if (a == 102)
{
displayDevice.PowerToggle();
}
if (twoWayDisplay != null)
inputNumberFeedback.FireUpdate();
});
var volumeDisplay = displayDevice as IBasicVolumeControls;
if (volumeDisplay != null)
{
trilist.SetBoolSigAction(joinMap.VolumeUp, (b) => volumeDisplay.VolumeUp(b));
trilist.SetBoolSigAction(joinMap.VolumeDown, (b) => volumeDisplay.VolumeDown(b));
trilist.SetSigTrueAction(joinMap.VolumeMute, () => volumeDisplay.MuteToggle());
var volumeDisplayWithFeedback = volumeDisplay as IBasicVolumeWithFeedback;
if(volumeDisplayWithFeedback != null)
{
trilist.SetUShortSigAction(joinMap.VolumeLevel, new Action<ushort>((u) => volumeDisplayWithFeedback.SetVolume(u)));
volumeDisplayWithFeedback.VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[joinMap.VolumeLevel]);
volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMute]);
}
}
}
static void CurrentInputFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
Debug.Console(0, "CurrentInputFeedback_OutputChange {0}", e.StringValue);
}
}
}

View File

@@ -0,0 +1,222 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Endpoints;
using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.DM;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges {
public static class DmBladeChassisControllerApiExtentions {
public static void LinkToApi(this DmBladeChassisController dmChassis, BasicTriList trilist, uint joinStart, string joinMapKey) {
DmBladeChassisControllerJoinMap joinMap = new DmBladeChassisControllerJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<DmBladeChassisControllerJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
Debug.Console(1, dmChassis, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
var chassis = dmChassis.Chassis as BladeSwitch;
dmChassis.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline]);
// Link up outputs
for (uint i = 1; i <= dmChassis.Chassis.NumberOfOutputs; i++) {
var ioSlot = i;
// Control
trilist.SetUShortSigAction(joinMap.OutputVideo + ioSlot, new Action<ushort>(o => dmChassis.ExecuteSwitch(o, ioSlot, eRoutingSignalType.Video)));
if (dmChassis.TxDictionary.ContainsKey(ioSlot)) {
Debug.Console(2, "Creating Tx Feedbacks {0}", ioSlot);
var txKey = dmChassis.TxDictionary[ioSlot];
var basicTxDevice = DeviceManager.GetDeviceForKey(txKey) as BasicDmTxControllerBase;
var advancedTxDevice = basicTxDevice as DmTxControllerBase;
if (dmChassis.Chassis is DmMd128x128 || dmChassis.Chassis is DmMd64x64) {
dmChassis.InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.InputEndpointOnline + ioSlot]);
}
else {
if (advancedTxDevice != null) {
advancedTxDevice.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.InputEndpointOnline + ioSlot]);
Debug.Console(2, "Linking Tx Online Feedback from Advanced Transmitter at input {0}", ioSlot);
}
else if (dmChassis.InputEndpointOnlineFeedbacks[ioSlot] != null) {
Debug.Console(2, "Linking Tx Online Feedback from Input Card {0}", ioSlot);
dmChassis.InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.InputEndpointOnline + ioSlot]);
}
}
if (basicTxDevice != null && advancedTxDevice == null)
trilist.BooleanInput[joinMap.TxAdvancedIsPresent + ioSlot].BoolValue = true;
if (advancedTxDevice != null) {
advancedTxDevice.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus + ioSlot]);
}
else if (advancedTxDevice == null || basicTxDevice != null) {
Debug.Console(1, "Setting up actions and feedbacks on input card {0}", ioSlot);
dmChassis.VideoInputSyncFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus + ioSlot]);
var inputPort = dmChassis.InputPorts[string.Format("inputCard{0}--hdmiIn", ioSlot)];
if (inputPort != null) {
Debug.Console(1, "Port value for input card {0} is set", ioSlot);
var port = inputPort.Port;
if (port != null) {
if (port is HdmiInputWithCEC) {
Debug.Console(1, "Port is HdmiInputWithCec");
var hdmiInPortWCec = port as HdmiInputWithCEC;
if (hdmiInPortWCec.HdcpSupportedLevel != eHdcpSupportedLevel.Unknown) {
SetHdcpStateAction(true, hdmiInPortWCec, joinMap.HdcpSupportState + ioSlot, trilist);
}
dmChassis.InputCardHdcpCapabilityFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.HdcpSupportState + ioSlot]);
if (dmChassis.InputCardHdcpCapabilityTypes.ContainsKey(ioSlot))
trilist.UShortInput[joinMap.HdcpSupportCapability + ioSlot].UShortValue = (ushort)dmChassis.InputCardHdcpCapabilityTypes[ioSlot];
else
trilist.UShortInput[joinMap.HdcpSupportCapability + ioSlot].UShortValue = 1;
}
}
}
else {
inputPort = dmChassis.InputPorts[string.Format("inputCard{0}--dmIn", ioSlot)];
if (inputPort != null) {
var port = inputPort.Port;
if (port is DMInputPortWithCec) {
Debug.Console(1, "Port is DMInputPortWithCec");
var dmInPortWCec = port as DMInputPortWithCec;
if (dmInPortWCec != null) {
SetHdcpStateAction(dmChassis.PropertiesConfig.InputSlotSupportsHdcp2[ioSlot], dmInPortWCec, joinMap.HdcpSupportState + ioSlot, trilist);
}
dmChassis.InputCardHdcpCapabilityFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.HdcpSupportState + ioSlot]);
if (dmChassis.InputCardHdcpCapabilityTypes.ContainsKey(ioSlot))
trilist.UShortInput[joinMap.HdcpSupportCapability + ioSlot].UShortValue = (ushort)dmChassis.InputCardHdcpCapabilityTypes[ioSlot];
else
trilist.UShortInput[joinMap.HdcpSupportCapability + ioSlot].UShortValue = 1;
}
}
}
}
}
else {
dmChassis.VideoInputSyncFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus + ioSlot]);
var inputPort = dmChassis.InputPorts[string.Format("inputCard{0}--hdmiIn", ioSlot)];
if (inputPort != null) {
var hdmiPort = inputPort.Port as EndpointHdmiInput;
if (hdmiPort != null) {
SetHdcpStateAction(true, hdmiPort, joinMap.HdcpSupportState + ioSlot, trilist);
dmChassis.InputCardHdcpCapabilityFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.HdcpSupportState + ioSlot]);
}
}
}
if (dmChassis.RxDictionary.ContainsKey(ioSlot)) {
Debug.Console(2, "Creating Rx Feedbacks {0}", ioSlot);
//var rxKey = dmChassis.RxDictionary[ioSlot];
//var rxDevice = DeviceManager.GetDeviceForKey(rxKey) as DmRmcControllerBase;
//var hdBaseTDevice = DeviceManager.GetDeviceForKey(rxKey) as DmHdBaseTControllerBase;
//if (hdBaseTDevice != null) {
dmChassis.OutputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.OutputEndpointOnline + ioSlot]);
//}
//else if (rxDevice != null) {
// rxDevice.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.OutputEndpointOnline + ioSlot]);
//}
}
// Feedback
dmChassis.VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo + ioSlot]);
dmChassis.OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames + ioSlot]);
dmChassis.InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames + ioSlot]);
dmChassis.OutputVideoRouteNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputCurrentVideoInputNames + ioSlot]);
}
}
static void SetHdcpStateAction(bool hdcpTypeSimple, HdmiInputWithCEC port, uint join, BasicTriList trilist) {
if (hdcpTypeSimple) {
trilist.SetUShortSigAction(join,
new Action<ushort>(s => {
if (s == 0) {
port.HdcpSupportOff();
}
else if (s > 0) {
port.HdcpSupportOn();
}
}));
}
else {
trilist.SetUShortSigAction(join,
new Action<ushort>(u => {
port.HdcpReceiveCapability = (eHdcpCapabilityType)u;
}));
}
}
static void SetHdcpStateAction(bool hdcpTypeSimple, EndpointHdmiInput port, uint join, BasicTriList trilist) {
if (hdcpTypeSimple) {
trilist.SetUShortSigAction(join,
new Action<ushort>(s => {
if (s == 0) {
port.HdcpSupportOff();
}
else if (s > 0) {
port.HdcpSupportOn();
}
}));
}
else {
trilist.SetUShortSigAction(join,
new Action<ushort>(u => {
port.HdcpCapability = (eHdcpCapabilityType)u;
}));
}
}
static void SetHdcpStateAction(bool supportsHdcp2, DMInputPortWithCec port, uint join, BasicTriList trilist) {
if (!supportsHdcp2) {
trilist.SetUShortSigAction(join,
new Action<ushort>(s => {
if (s == 0) {
port.HdcpSupportOff();
}
else if (s > 0) {
port.HdcpSupportOn();
}
}));
}
else {
trilist.SetUShortSigAction(join,
new Action<ushort>(u => {
port.HdcpReceiveCapability = (eHdcpCapabilityType)u;
}));
}
}
}
}

View File

@@ -0,0 +1,284 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Endpoints;
using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.DM;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class DmChassisControllerApiExtentions
{
public static void LinkToApi(this DmChassisController dmChassis, BasicTriList trilist, uint joinStart, string joinMapKey)
{
DmChassisControllerJoinMap joinMap = new DmChassisControllerJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<DmChassisControllerJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
Debug.Console(1, dmChassis, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
var chassis = dmChassis.Chassis as DmMDMnxn;
dmChassis.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline]);
trilist.SetUShortSigAction(joinMap.SystemId, new Action<ushort>(o => chassis.SystemId.UShortValue = o));
trilist.SetSigTrueAction(joinMap.SystemId, new Action(() => chassis.ApplySystemId()));
dmChassis.SystemIdFeebdack.LinkInputSig(trilist.UShortInput[joinMap.SystemId]);
dmChassis.SystemIdBusyFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SystemId]);
// Link up outputs
for (uint i = 1; i <= dmChassis.Chassis.NumberOfOutputs; i++)
{
var ioSlot = i;
// Control
trilist.SetUShortSigAction(joinMap.OutputVideo + ioSlot, new Action<ushort>(o => dmChassis.ExecuteSwitch(o, ioSlot, eRoutingSignalType.Video)));
trilist.SetUShortSigAction(joinMap.OutputAudio + ioSlot, new Action<ushort>(o => dmChassis.ExecuteSwitch(o, ioSlot, eRoutingSignalType.Audio)));
trilist.SetUShortSigAction(joinMap.OutputUsb + ioSlot, new Action<ushort>(o => dmChassis.ExecuteSwitch(o, ioSlot, eRoutingSignalType.UsbOutput)));
trilist.SetUShortSigAction(joinMap.InputUsb + ioSlot, new Action<ushort>(o => dmChassis.ExecuteSwitch(o, ioSlot, eRoutingSignalType.UsbInput)));
if (dmChassis.TxDictionary.ContainsKey(ioSlot))
{
Debug.Console(2, "Creating Tx Feedbacks {0}", ioSlot);
var txKey = dmChassis.TxDictionary[ioSlot];
var basicTxDevice = DeviceManager.GetDeviceForKey(txKey) as BasicDmTxControllerBase;
var advancedTxDevice = basicTxDevice as DmTxControllerBase;
if (dmChassis.Chassis is DmMd8x8Cpu3 || dmChassis.Chassis is DmMd8x8Cpu3rps
|| dmChassis.Chassis is DmMd16x16Cpu3 || dmChassis.Chassis is DmMd16x16Cpu3rps
|| dmChassis.Chassis is DmMd32x32Cpu3 || dmChassis.Chassis is DmMd32x32Cpu3rps)
{
dmChassis.InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.InputEndpointOnline + ioSlot]);
}
else
{
if (advancedTxDevice != null)
{
advancedTxDevice.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.InputEndpointOnline + ioSlot]);
Debug.Console(2, "Linking Tx Online Feedback from Advanced Transmitter at input {0}", ioSlot);
}
else if (dmChassis.InputEndpointOnlineFeedbacks[ioSlot] != null)
{
Debug.Console(2, "Linking Tx Online Feedback from Input Card {0}", ioSlot);
dmChassis.InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.InputEndpointOnline + ioSlot]);
}
}
if (basicTxDevice != null && advancedTxDevice == null)
trilist.BooleanInput[joinMap.TxAdvancedIsPresent + ioSlot].BoolValue = true;
if (advancedTxDevice != null)
{
advancedTxDevice.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus + ioSlot]);
}
else if(advancedTxDevice == null || basicTxDevice != null)
{
Debug.Console(1, "Setting up actions and feedbacks on input card {0}", ioSlot);
dmChassis.VideoInputSyncFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus + ioSlot]);
var inputPort = dmChassis.InputPorts[string.Format("inputCard{0}--hdmiIn", ioSlot)];
if (inputPort != null)
{
Debug.Console(1, "Port value for input card {0} is set", ioSlot);
var port = inputPort.Port;
if (port != null)
{
if (port is HdmiInputWithCEC)
{
Debug.Console(1, "Port is HdmiInputWithCec");
var hdmiInPortWCec = port as HdmiInputWithCEC;
if (hdmiInPortWCec.HdcpSupportedLevel != eHdcpSupportedLevel.Unknown)
{
SetHdcpStateAction(true, hdmiInPortWCec, joinMap.HdcpSupportState + ioSlot, trilist);
}
dmChassis.InputCardHdcpCapabilityFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.HdcpSupportState + ioSlot]);
if(dmChassis.InputCardHdcpCapabilityTypes.ContainsKey(ioSlot))
trilist.UShortInput[joinMap.HdcpSupportCapability + ioSlot].UShortValue = (ushort)dmChassis.InputCardHdcpCapabilityTypes[ioSlot];
else
trilist.UShortInput[joinMap.HdcpSupportCapability + ioSlot].UShortValue = 1;
}
}
}
else
{
inputPort = dmChassis.InputPorts[string.Format("inputCard{0}--dmIn", ioSlot)];
if(inputPort != null)
{
var port = inputPort.Port;
if (port is DMInputPortWithCec)
{
Debug.Console(1, "Port is DMInputPortWithCec");
var dmInPortWCec = port as DMInputPortWithCec;
if (dmInPortWCec != null)
{
SetHdcpStateAction(dmChassis.PropertiesConfig.InputSlotSupportsHdcp2[ioSlot], dmInPortWCec, joinMap.HdcpSupportState + ioSlot, trilist);
}
dmChassis.InputCardHdcpCapabilityFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.HdcpSupportState + ioSlot]);
if (dmChassis.InputCardHdcpCapabilityTypes.ContainsKey(ioSlot))
trilist.UShortInput[joinMap.HdcpSupportCapability + ioSlot].UShortValue = (ushort)dmChassis.InputCardHdcpCapabilityTypes[ioSlot];
else
trilist.UShortInput[joinMap.HdcpSupportCapability + ioSlot].UShortValue = 1;
}
}
}
}
}
else
{
dmChassis.VideoInputSyncFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus + ioSlot]);
var inputPort = dmChassis.InputPorts[string.Format("inputCard{0}--hdmiIn", ioSlot)];
if (inputPort != null)
{
var hdmiPort = inputPort.Port as EndpointHdmiInput;
if (hdmiPort != null)
{
SetHdcpStateAction(true, hdmiPort, joinMap.HdcpSupportState + ioSlot, trilist);
dmChassis.InputCardHdcpCapabilityFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.HdcpSupportState + ioSlot]);
}
}
}
if (dmChassis.RxDictionary.ContainsKey(ioSlot))
{
Debug.Console(2, "Creating Rx Feedbacks {0}", ioSlot);
var rxKey = dmChassis.RxDictionary[ioSlot];
var rxDevice = DeviceManager.GetDeviceForKey(rxKey) as DmRmcControllerBase;
var hdBaseTDevice = DeviceManager.GetDeviceForKey(rxKey) as DmHdBaseTControllerBase;
if (dmChassis.Chassis is DmMd8x8Cpu3 || dmChassis.Chassis is DmMd8x8Cpu3rps
|| dmChassis.Chassis is DmMd16x16Cpu3 || dmChassis.Chassis is DmMd16x16Cpu3rps
|| dmChassis.Chassis is DmMd32x32Cpu3 || dmChassis.Chassis is DmMd32x32Cpu3rps || hdBaseTDevice != null)
{
dmChassis.OutputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.OutputEndpointOnline + ioSlot]);
}
else if (rxDevice != null)
{
rxDevice.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.OutputEndpointOnline + ioSlot]);
}
}
// Feedback
dmChassis.VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo + ioSlot]);
dmChassis.AudioOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio + ioSlot]);
dmChassis.UsbOutputRoutedToFeebacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputUsb + ioSlot]);
dmChassis.UsbInputRoutedToFeebacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.InputUsb + ioSlot]);
dmChassis.OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames + ioSlot]);
dmChassis.InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames + ioSlot]);
dmChassis.OutputVideoRouteNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputCurrentVideoInputNames + ioSlot]);
dmChassis.OutputAudioRouteNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputCurrentAudioInputNames + ioSlot]);
}
}
static void SetHdcpStateAction(bool hdcpTypeSimple, HdmiInputWithCEC port, uint join, BasicTriList trilist)
{
if (hdcpTypeSimple)
{
trilist.SetUShortSigAction(join,
new Action<ushort>(s =>
{
if (s == 0)
{
port.HdcpSupportOff();
}
else if (s > 0)
{
port.HdcpSupportOn();
}
}));
}
else
{
trilist.SetUShortSigAction(join,
new Action<ushort>(u =>
{
port.HdcpReceiveCapability = (eHdcpCapabilityType)u;
}));
}
}
static void SetHdcpStateAction(bool hdcpTypeSimple, EndpointHdmiInput port, uint join, BasicTriList trilist)
{
if (hdcpTypeSimple)
{
trilist.SetUShortSigAction(join,
new Action<ushort>(s =>
{
if (s == 0)
{
port.HdcpSupportOff();
}
else if (s > 0)
{
port.HdcpSupportOn();
}
}));
}
else
{
trilist.SetUShortSigAction(join,
new Action<ushort>(u =>
{
port.HdcpCapability = (eHdcpCapabilityType)u;
}));
}
}
static void SetHdcpStateAction(bool supportsHdcp2, DMInputPortWithCec port, uint join, BasicTriList trilist)
{
if (!supportsHdcp2)
{
trilist.SetUShortSigAction(join,
new Action<ushort>(s =>
{
if (s == 0)
{
port.HdcpSupportOff();
}
else if (s > 0)
{
port.HdcpSupportOn();
}
}));
}
else
{
trilist.SetUShortSigAction(join,
new Action<ushort>(u =>
{
port.HdcpReceiveCapability = (eHdcpCapabilityType)u;
}));
}
}
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.DM;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class DmRmcControllerApiExtensions
{
public static void LinkToApi(this DmRmcControllerBase rmc, BasicTriList trilist, uint joinStart, string joinMapKey)
{
DmRmcControllerJoinMap joinMap = new DmRmcControllerJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<DmRmcControllerJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
Debug.Console(1, rmc, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
rmc.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline]);
if(rmc.VideoOutputResolutionFeedback != null)
rmc.VideoOutputResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentOutputResolution]);
if(rmc.EdidManufacturerFeedback != null)
rmc.EdidManufacturerFeedback.LinkInputSig(trilist.StringInput[joinMap.EdidManufacturer]);
if(rmc.EdidNameFeedback != null)
rmc.EdidNameFeedback.LinkInputSig(trilist.StringInput[joinMap.EdidName]);
if(rmc.EdidPreferredTimingFeedback != null)
rmc.EdidPreferredTimingFeedback.LinkInputSig(trilist.StringInput[joinMap.EdidPrefferedTiming]);
if(rmc.EdidSerialNumberFeedback != null)
rmc.EdidSerialNumberFeedback.LinkInputSig(trilist.StringInput[joinMap.EdidSerialNumber]);
}
}
}

View File

@@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Endpoints;
using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.DM;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class DmTxControllerApiExtensions
{
public static void LinkToApi(this DmTxControllerBase tx, BasicTriList trilist, uint joinStart, string joinMapKey)
{
DmTxControllerJoinMap joinMap = new DmTxControllerJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<DmTxControllerJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
Debug.Console(1, tx, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
tx.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline]);
tx.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus]);
tx.AnyVideoInput.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentInputResolution]);
trilist.UShortInput[joinMap.HdcpSupportCapability].UShortValue = (ushort)tx.HdcpSupportCapability;
bool hdcpTypeSimple;
if (tx.Hardware is DmTx4kX02CBase || tx.Hardware is DmTx4kzX02CBase)
hdcpTypeSimple = false;
else
hdcpTypeSimple = true;
if (tx is ITxRouting)
{
var txR = tx as ITxRouting;
trilist.SetUShortSigAction(joinMap.VideoInput,
new Action<ushort>(i => txR.ExecuteNumericSwitch(i, 0, eRoutingSignalType.Video)));
trilist.SetUShortSigAction(joinMap.AudioInput,
new Action<ushort>(i => txR.ExecuteNumericSwitch(i, 0, eRoutingSignalType.Audio)));
txR.VideoSourceNumericFeedback.LinkInputSig(trilist.UShortInput[joinMap.VideoInput]);
txR.AudioSourceNumericFeedback.LinkInputSig(trilist.UShortInput[joinMap.AudioInput]);
trilist.UShortInput[joinMap.HdcpSupportCapability].UShortValue = (ushort)tx.HdcpSupportCapability;
if(txR.InputPorts[DmPortName.HdmiIn] != null)
{
var inputPort = txR.InputPorts[DmPortName.HdmiIn];
if (tx.Feedbacks["HdmiInHdcpCapability"] != null)
(tx.Feedbacks["HdmiInHdcpCapability"] as IntFeedback).LinkInputSig(trilist.UShortInput[joinMap.Port1HdcpState]);
if (inputPort.ConnectionType == eRoutingPortConnectionType.Hdmi && inputPort.Port != null)
{
var port = inputPort.Port as EndpointHdmiInput;
SetHdcpCapabilityAction(hdcpTypeSimple, port, joinMap.Port1HdcpState, trilist);
}
}
if (txR.InputPorts[DmPortName.HdmiIn1] != null)
{
var inputPort = txR.InputPorts[DmPortName.HdmiIn1];
if (tx.Feedbacks["HdmiIn1HdcpCapability"] != null)
(tx.Feedbacks["HdmiIn1HdcpCapability"] as IntFeedback).LinkInputSig(trilist.UShortInput[joinMap.Port1HdcpState]);
if (inputPort.ConnectionType == eRoutingPortConnectionType.Hdmi && inputPort.Port != null)
{
var port = inputPort.Port as EndpointHdmiInput;
SetHdcpCapabilityAction(hdcpTypeSimple, port, joinMap.Port1HdcpState, trilist);
}
}
if (txR.InputPorts[DmPortName.HdmiIn2] != null)
{
var inputPort = txR.InputPorts[DmPortName.HdmiIn2];
if (tx.Feedbacks["HdmiIn2HdcpCapability"] != null)
(tx.Feedbacks["HdmiIn2HdcpCapability"] as IntFeedback).LinkInputSig(trilist.UShortInput[joinMap.Port1HdcpState]);
if (inputPort.ConnectionType == eRoutingPortConnectionType.Hdmi && inputPort.Port != null)
{
var port = inputPort.Port as EndpointHdmiInput;
SetHdcpCapabilityAction(hdcpTypeSimple, port, joinMap.Port2HdcpState, trilist);
}
}
}
}
static void SetHdcpCapabilityAction(bool hdcpTypeSimple, EndpointHdmiInput port, uint join, BasicTriList trilist)
{
if (hdcpTypeSimple)
{
trilist.SetUShortSigAction(join,
new Action<ushort>(s =>
{
if (s == 0)
{
port.HdcpSupportOff();
}
else if (s > 0)
{
port.HdcpSupportOn();
}
}));
}
else
{
trilist.SetUShortSigAction(join,
new Action<ushort>(s =>
{
port.HdcpCapability = (eHdcpCapabilityType)s;
}));
}
}
}
}

View File

@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.DM;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class DmpsAudioOutputControllerApiExtensions
{
public static void LinkToApi(this DmpsAudioOutputController dmAudioOutputController, BasicTriList trilist, uint joinStart, string joinMapKey)
{
DmpsAudioOutputControllerJoinMap joinMap = new DmpsAudioOutputControllerJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<DmpsAudioOutputControllerJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
Debug.Console(1, dmAudioOutputController, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
if (dmAudioOutputController.MasterVolumeLevel != null)
{
SetUpDmpsAudioOutputJoins(trilist, dmAudioOutputController.MasterVolumeLevel, joinMap.MasterVolume);
}
if (dmAudioOutputController.SourceVolumeLevel != null)
{
SetUpDmpsAudioOutputJoins(trilist, dmAudioOutputController.SourceVolumeLevel, joinMap.SourceVolume);
}
if (dmAudioOutputController.Codec1VolumeLevel != null)
{
SetUpDmpsAudioOutputJoins(trilist, dmAudioOutputController.Codec1VolumeLevel, joinMap.Codec1Volume);
}
if (dmAudioOutputController.Codec2VolumeLevel != null)
{
SetUpDmpsAudioOutputJoins(trilist, dmAudioOutputController.Codec2VolumeLevel, joinMap.Codec2Volume);
}
}
static void SetUpDmpsAudioOutputJoins(BasicTriList trilist, DmpsAudioOutput output, uint joinStart)
{
var volumeLevelJoin = joinStart;
var muteOnJoin = joinStart;
var muteOffJoin = joinStart + 1;
var volumeUpJoin = joinStart + 2;
var volumeDownJoin = joinStart + 3;
trilist.SetUShortSigAction(volumeLevelJoin, new Action<ushort>(o => output.SetVolume(o)));
output.VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[volumeLevelJoin]);
trilist.SetSigTrueAction(muteOnJoin, new Action(output.MuteOn));
output.MuteFeedback.LinkInputSig(trilist.BooleanInput[muteOnJoin]);
trilist.SetSigTrueAction(muteOffJoin, new Action(output.MuteOff));
output.MuteFeedback.LinkComplementInputSig(trilist.BooleanInput[muteOffJoin]);
trilist.SetBoolSigAction(volumeUpJoin, new Action<bool>(b => output.VolumeUp(b)));
trilist.SetBoolSigAction(volumeDownJoin, new Action<bool>(b => output.VolumeDown(b)));
}
}
}

View File

@@ -0,0 +1,128 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.DM;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class DmpsRoutingControllerApiExtentions
{
public static void LinkToApi(this DmpsRoutingController dmpsRouter, BasicTriList trilist, uint joinStart, string joinMapKey)
{
DmpsRoutingControllerJoinMap joinMap = new DmpsRoutingControllerJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<DmpsRoutingControllerJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
Debug.Console(1, dmpsRouter, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
// Link up outputs
for (uint i = 1; i <= dmpsRouter.Dmps.NumberOfSwitcherInputs; i++)
{
Debug.Console(2, dmpsRouter, "Linking Input Card {0}", i);
var ioSlot = i;
//if (dmpsRouter.TxDictionary.ContainsKey(ioSlot))
//{
// Debug.Console(2, "Creating Tx Feedbacks {0}", ioSlot);
// var TxKey = dmpsRouter.TxDictionary[ioSlot];
// var TxDevice = DeviceManager.GetDeviceForKey(TxKey) as DmTxControllerBase;
// //TxDevice.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.InputEndpointOnline + ioSlot]);
// // TxDevice.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputEndpointOnline + ioSlot]);
// // trilist.SetUShortSigAction((ApiMap.HdcpSupport[ioSlot]), u => TxDevice.SetHdcpSupportAll((ePdtHdcpSupport)(u)));
// // TxDevice.HdcpSupportAllFeedback.LinkInputSig(trilist.UShortInput[joinMap. + ioSlot]);
// // trilist.UShortInput[ApiMap.HdcpSupportCapability[ioSlot]].UShortValue = TxDevice.HdcpSupportCapability;
//}
//else
//{
// // dmChassis.VideoInputSyncFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[ApiMap.TxVideoSyncStatus[ioSlot]]);
//}
if(dmpsRouter.VideoInputSyncFeedbacks[ioSlot] != null)
dmpsRouter.VideoInputSyncFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus + ioSlot]);
if (dmpsRouter.InputNameFeedbacks[ioSlot] != null)
dmpsRouter.InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames + ioSlot]);
trilist.SetStringSigAction(joinMap.InputNames + ioSlot, new Action<string>(s =>
{
var inputCard = dmpsRouter.Dmps.SwitcherInputs[ioSlot] as DMInput;
if (inputCard != null)
{
if (inputCard.NameFeedback != null && !string.IsNullOrEmpty(inputCard.NameFeedback.StringValue) && inputCard.NameFeedback.StringValue != s)
if(inputCard.Name != null)
inputCard.Name.StringValue = s;
}
}));
if(dmpsRouter.InputEndpointOnlineFeedbacks[ioSlot] != null)
dmpsRouter.InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.InputEndpointOnline + ioSlot]);
}
for (uint i = 1; i <= dmpsRouter.Dmps.NumberOfSwitcherOutputs; i++)
{
Debug.Console(2, dmpsRouter, "Linking Output Card {0}", i);
var ioSlot = i;
// Control
trilist.SetUShortSigAction(joinMap.OutputVideo + ioSlot, new Action<ushort>(o => dmpsRouter.ExecuteSwitch(o, ioSlot, eRoutingSignalType.Video)));
trilist.SetUShortSigAction(joinMap.OutputAudio + ioSlot, new Action<ushort>(o => dmpsRouter.ExecuteSwitch(o, ioSlot, eRoutingSignalType.Audio)));
trilist.SetStringSigAction(joinMap.OutputNames + ioSlot, new Action<string>(s =>
{
var outputCard = dmpsRouter.Dmps.SwitcherOutputs[ioSlot] as DMOutput;
//Debug.Console(2, dmpsRouter, "Output Name String Sig Action for Output Card {0}", ioSlot);
if (outputCard != null)
{
//Debug.Console(2, dmpsRouter, "Card Type: {0}", outputCard.CardInputOutputType);
if (!(outputCard is Crestron.SimplSharpPro.DM.Cards.Card.Dmps3CodecOutput) && outputCard.NameFeedback != null)
{
if (!string.IsNullOrEmpty(outputCard.NameFeedback.StringValue))
{
//Debug.Console(2, dmpsRouter, "NameFeedabck: {0}", outputCard.NameFeedback.StringValue);
if (outputCard.NameFeedback.StringValue != s && outputCard.Name != null)
{
outputCard.Name.StringValue = s;
}
}
}
}
}));
// Feedback
if(dmpsRouter.VideoOutputFeedbacks[ioSlot] != null)
dmpsRouter.VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo + ioSlot]);
if (dmpsRouter.AudioOutputFeedbacks[ioSlot] != null)
dmpsRouter.AudioOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio + ioSlot]);
if (dmpsRouter.OutputNameFeedbacks[ioSlot] != null)
dmpsRouter.OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames + ioSlot]);
if (dmpsRouter.OutputVideoRouteNameFeedbacks[ioSlot] != null)
dmpsRouter.OutputVideoRouteNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputCurrentVideoInputNames + ioSlot]);
if (dmpsRouter.OutputAudioRouteNameFeedbacks[ioSlot] != null)
dmpsRouter.OutputAudioRouteNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputCurrentAudioInputNames + ioSlot]);
if (dmpsRouter.OutputEndpointOnlineFeedbacks[ioSlot] != null)
dmpsRouter.OutputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.OutputEndpointOnline + ioSlot]);
}
}
}
}

View File

@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common;
namespace PepperDash.Essentials.Bridges
{
public static class SamsungDisplayControllerApiExtensions
{
public static void LinkToApi(this PepperDash.Essentials.Core.TwoWayDisplayBase displayDevice, BasicTriList trilist, uint joinStart, string joinMapKey)
{
var joinMap = JoinMapHelper.GetJoinMapForDevice(joinMapKey) as DisplayControllerJoinMap;
if (joinMap == null)
{
joinMap = new DisplayControllerJoinMap();
}
joinMap.OffsetJoinNumbers(joinStart);
Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, "Linking to lighting Type {0}", displayDevice.GetType().Name.ToString());
var commMonitor = displayDevice as ICommunicationMonitor;
commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline]);
// Poewer Off
trilist.SetSigTrueAction(joinMap.PowerOff, () => displayDevice.PowerOff());
displayDevice.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff]);
// Poewer On
trilist.SetSigTrueAction(joinMap.PowerOn, () => displayDevice.PowerOn());
displayDevice.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn]);
// GenericLighitng Actions & FeedBack
// int sceneIndex = 1;
/*
foreach (var scene in displayDevice.LightingScenes)
{
var tempIndex = sceneIndex - 1;
//trilist.SetSigTrueAction((uint)(joinMap.LightingSceneOffset + sceneIndex), () => displayDevice.SelectScene(displayDevice.LightingScenes[tempIndex]));
scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.LightingSceneOffset + sceneIndex)]);
trilist.StringInput[(uint)(joinMap.LightingSceneOffset + sceneIndex)].StringValue = scene.Name;
trilist.BooleanInput[(uint)(joinMap.ButtonVisibilityOffset + sceneIndex)].BoolValue = true;
sceneIndex++;
}
if (displayDevice.GetType().Name.ToString() == "LutronQuantumArea")
{
var lutronDevice = displayDevice as PepperDash.Essentials.Devices.Common.Environment.Lutron.LutronQuantumArea;
lutronDevice.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline]);
trilist.SetStringSigAction(joinMap.IntegrationIdSet, s => lutronDevice.IntegrationId = s);
}
*/
//ApiEisc.Eisc.SetStringSigAction(ApiMap.integrationID, (s) => { lutronLights.IntegrationId = s; });
/*
var lutronLights = displayDevice as PepperDash.Essentials.Devices.Common.Environment.Lutron.LutronQuantumArea;
for (uint i = 1; i <= lightingBase.CircuitCount; i++)
{
var circuit = i;
lightingBase.CircuitNameFeedbacks[circuit - 1].LinkInputSig(trilist.StringInput[joinMap.CircuitNames + circuit]);
lightingBase.CircuitIsCritical[circuit - 1].LinkInputSig(trilist.BooleanInput[joinMap.CircuitIsCritical + circuit]);
lightingBase.CircuitState[circuit - 1].LinkInputSig(trilist.BooleanInput[joinMap.CircuitState + circuit]);
trilist.SetSigTrueAction(joinMap.CircuitCycle + circuit, () => lightingBase.CycleCircuit(circuit - 1));
trilist.SetSigTrueAction(joinMap.CircuitOnCmd + circuit, () => lightingBase.TurnOnCircuit(circuit - 1));
trilist.SetSigTrueAction(joinMap.CircuitOffCmd + circuit, () => lightingBase.TurnOffCircuit(circuit - 1));
}
*/
}
}
public class DisplayControllerJoinMap : JoinMapBase
{
public uint IsOnline { get; set; }
public uint PowerOff { get; set; }
public uint PowerOn { get; set; }
public uint SelectScene { get; set; }
public uint LightingSceneOffset { get; set; }
public uint ButtonVisibilityOffset { get; set; }
public uint IntegrationIdSet { get; set; }
public DisplayControllerJoinMap()
{
// Digital
IsOnline = 1;
PowerOff = 1;
PowerOn = 2;
SelectScene = 1;
IntegrationIdSet = 1;
LightingSceneOffset = 10;
ButtonVisibilityOffset = 40;
// Analog
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
IsOnline = IsOnline + joinOffset;
PowerOff = PowerOff + joinOffset;
PowerOn = PowerOn + joinOffset;
SelectScene = SelectScene + joinOffset;
LightingSceneOffset = LightingSceneOffset + joinOffset;
ButtonVisibilityOffset = ButtonVisibilityOffset + joinOffset;
}
}
}

View File

@@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Core;
using PepperDash.Essentials.Core.Routing;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.EthernetCommunication;
using Crestron.SimplSharpPro.CrestronThread;
namespace PepperDash.Essentials {
public class EssentialCommConfig {
public string[] EiscApiIpids;
public EssentialCommCommConnectionConfigs[] CommConnections;
}
public class EssentialCommCommConnectionConfigs {
public uint joinNumber {get; set; }
public EssentialsControlPropertiesConfig control { get; set; }
}
public class EssentialCommsPort {
public IBasicCommunication Comm;
public IntFeedback StatusFeedback;
public BoolFeedback ConnectedFeedback;
public List<EssentialComApiMap> Outputs = new List<EssentialComApiMap>();
public String RxBuffer;
public EssentialCommsPort(EssentialsControlPropertiesConfig config, string keyPrefix) {
Comm = CommFactory.CreateCommForConfig(config, keyPrefix);
// var PortGather = new CommunicationGather(Comm, config.EndOfLineChar);
Comm.TextReceived += new EventHandler<GenericCommMethodReceiveTextArgs>(Communication_TextReceived);
var socket = Comm as ISocketStatus;
StatusFeedback = new IntFeedback(() => { return (int)socket.ClientStatus; });
ConnectedFeedback = new BoolFeedback(() => { return Comm.IsConnected; });
if (socket != null) {
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
} else {
}
}
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e) {
StatusFeedback.FireUpdate();
ConnectedFeedback.FireUpdate();
if (e.Client.IsConnected) {
// Tasks on connect
} else {
// Cleanup items from this session
}
}
void Communication_TextReceived(object sender, GenericCommMethodReceiveTextArgs args) {
try {
foreach (var Output in Outputs) {
Output.Api.Eisc.StringInput[Output.Join].StringValue = args.Text;
}
}
catch (Exception) {
throw new FormatException(string.Format("ERROR:{0}"));
}
}
}
public class EssentialComm : Device {
public EssentialCommConfig Properties;
public CommunicationGather PortGather { get; private set; }
public List<BridgeApiEisc> Apis {get; set;}
public Dictionary<string, StringFeedback> CommFeedbacks {get; private set; }
public StatusMonitorBase CommunicationMonitor { get; private set; }
public Dictionary<uint, EssentialCommsPort> CommDictionary { get; private set; }
public EssentialComm(string key, string name, JToken properties) : base(key, name) {
Properties = JsonConvert.DeserializeObject<EssentialCommConfig>(properties.ToString());
CommFeedbacks = new Dictionary<string, StringFeedback>();
CommDictionary = new Dictionary<uint, EssentialCommsPort>();
Apis = new List<BridgeApiEisc>();
int commNumber = 1;
foreach (var commConfig in Properties.CommConnections) {
var commPort = new EssentialCommsPort(commConfig.control, string.Format("{0}-{1}", this.Key, commConfig.joinNumber));
CommDictionary.Add(commConfig.joinNumber, commPort);
commNumber++;
}
foreach (var Ipid in Properties.EiscApiIpids) {
var ApiEisc = new BridgeApiEisc(Ipid);
Apis.Add(ApiEisc);
foreach (var commConnection in CommDictionary) {
Debug.Console(2, "Joining Api{0} to comm {1}", Ipid, commConnection.Key);
var tempComm = commConnection.Value;
var tempJoin = (uint)commConnection.Key;
EssentialComApiMap ApiMap = new EssentialComApiMap(ApiEisc, (uint)tempJoin);
tempComm.Outputs.Add(ApiMap);
// Check for ApiMap Overide Values here
ApiEisc.Eisc.SetBoolSigAction(tempJoin, b => {if (b) { tempComm.Comm.Connect(); } else { tempComm.Comm.Disconnect(); }});
ApiEisc.Eisc.SetStringSigAction(tempJoin, s => tempComm.Comm.SendText(s));
tempComm.StatusFeedback.LinkInputSig(ApiEisc.Eisc.UShortInput[tempJoin]);
tempComm.ConnectedFeedback.LinkInputSig(ApiEisc.Eisc.BooleanInput[tempJoin]);
}
ApiEisc.Eisc.Register();
}
}
public override bool CustomActivate()
{
try {
Debug.Console(2, "Name {0} Activated", this.Name);
return true;
}
catch (Exception e) {
Debug.Console(0, "Bridge {0}", e);
return false;
}
}
}
public class EssentialComApiMap {
public uint Join;
public BridgeApiEisc Api;
public uint connectJoin;
public EssentialComApiMap(BridgeApiEisc api, uint join) {
Join = join;
Api = api;
}
}
}

View File

@@ -0,0 +1,150 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.DM;
using PepperDash.Core;
using PepperDash.Essentials.Core.Routing;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.EthernetCommunication;
using Crestron.SimplSharpPro.DM;
namespace PepperDash.Essentials {
public class EssentialDM : PepperDash.Core.Device {
public EssentialDMProperties Properties;
public List<BridgeApiEisc> BridgeApiEiscs;
private PepperDash.Essentials.DM.DmChassisController DmSwitch;
private EssentialDMApiMap ApiMap = new EssentialDMApiMap();
public EssentialDM(string key, string name, JToken properties)
: base(key, name) {
Properties = JsonConvert.DeserializeObject<EssentialDMProperties>(properties.ToString());
}
public override bool CustomActivate() {
// Create EiscApis
try {
foreach (var device in DeviceManager.AllDevices) {
if (device.Key == this.Properties.connectionDeviceKey) {
Debug.Console(2, "deviceKey {0} Matches", device.Key);
DmSwitch = DeviceManager.GetDeviceForKey(device.Key) as PepperDash.Essentials.DM.DmChassisController;
}
else {
Debug.Console(2, "deviceKey {0} doesn't match", device.Key);
}
}
if (Properties.EiscApiIpids != null) {
foreach (string Ipid in Properties.EiscApiIpids) {
var ApiEisc = new BridgeApiEisc(Ipid);
for (uint x = 1; x <= DmSwitch.Chassis.NumberOfInputs;x++ ) {
uint tempX = x;
Debug.Console(2, "Creating EiscActions {0}", tempX);
ApiEisc.Eisc.SetUShortSigAction(ApiMap.OutputVideoRoutes[tempX], u => DmSwitch.ExecuteSwitch(u, tempX, eRoutingSignalType.Video));
ApiEisc.Eisc.SetUShortSigAction(ApiMap.OutputAudioRoutes[tempX], u => DmSwitch.ExecuteSwitch(u, tempX, eRoutingSignalType.Audio));
if (DmSwitch.TxDictionary.ContainsKey(tempX)) {
Debug.Console(2, "Creating Tx Feedbacks {0}", tempX);
var TxKey = DmSwitch.TxDictionary[tempX];
var TxDevice = DeviceManager.GetDeviceForKey(TxKey) as DmTxControllerBase;
TxDevice.IsOnline.LinkInputSig(ApiEisc.Eisc.BooleanInput[ApiMap.TxOnlineStatus[tempX]]);
TxDevice.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig(ApiEisc.Eisc.BooleanInput[ApiMap.TxVideoSyncStatus[tempX]]);
ApiEisc.Eisc.SetUShortSigAction((ApiMap.HdcpSupport[tempX]), u => TxDevice.SetHdcpSupportAll((ePdtHdcpSupport)(u)));
TxDevice.HdcpSupportAllFeedback.LinkInputSig(ApiEisc.Eisc.UShortInput[ApiMap.HdcpSupport[tempX]]);
ApiEisc.Eisc.UShortInput[ApiMap.HdcpSupportCapability[tempX]].UShortValue = TxDevice.HdcpSupportCapability;
}
else {
DmSwitch.VideoInputSyncFeedbacks[tempX].LinkInputSig(ApiEisc.Eisc.BooleanInput[ApiMap.TxVideoSyncStatus[tempX]]);
}
if (DmSwitch.RxDictionary.ContainsKey(tempX)) {
Debug.Console(2, "Creating Rx Feedbacks {0}", tempX);
var RxKey = DmSwitch.RxDictionary[tempX];
var RxDevice = DeviceManager.GetDeviceForKey(RxKey) as DmRmcControllerBase;
RxDevice.IsOnline.LinkInputSig(ApiEisc.Eisc.BooleanInput[ApiMap.RxOnlineStatus[tempX]]);
}
// DmSwitch.InputEndpointOnlineFeedbacks[(ushort)tempOutputNum].LinkInputSig(ApiEisc.Eisc.BooleanInput[ApiMap.OutputVideoRoutes[tempOutputNum]]);
DmSwitch.VideoOutputFeedbacks[(ushort)tempX].LinkInputSig(ApiEisc.Eisc.UShortInput[ApiMap.OutputVideoRoutes[tempX]]);
DmSwitch.AudioOutputFeedbacks[(ushort)tempX].LinkInputSig(ApiEisc.Eisc.UShortInput[ApiMap.OutputAudioRoutes[tempX]]);
DmSwitch.InputNameFeedbacks[(ushort)tempX].LinkInputSig(ApiEisc.Eisc.StringInput[ApiMap.InputNames[tempX]]);
DmSwitch.OutputNameFeedbacks[(ushort)tempX].LinkInputSig(ApiEisc.Eisc.StringInput[ApiMap.OutputNames[tempX]]);
DmSwitch.OutputRouteNameFeedbacks[(ushort)tempX].LinkInputSig(ApiEisc.Eisc.StringInput[ApiMap.OutputRouteNames[tempX]]);
}
DmSwitch.IsOnline.LinkInputSig(ApiEisc.Eisc.BooleanInput[ApiMap.ChassisOnline]);
ApiEisc.Eisc.Register();
}
}
Debug.Console(2, "Name {0} Activated", this.Name);
return true;
}
catch (Exception e) {
Debug.Console(2, "BRidge {0}", e);
return false;
}
}
}
public class EssentialDMProperties {
public string connectionDeviceKey;
public string[] EiscApiIpids;
}
public class EssentialDMApiMap {
public ushort ChassisOnline = 11;
public Dictionary<uint, ushort> OutputVideoRoutes;
public Dictionary<uint, ushort> OutputAudioRoutes;
public Dictionary<uint, ushort> TxOnlineStatus;
public Dictionary<uint, ushort> RxOnlineStatus;
public Dictionary<uint, ushort> TxVideoSyncStatus;
public Dictionary<uint, ushort> InputNames;
public Dictionary<uint, ushort> OutputNames;
public Dictionary<uint, ushort> OutputRouteNames;
public Dictionary<uint, ushort> HdcpSupport;
public Dictionary<uint, ushort> HdcpSupportCapability;
public EssentialDMApiMap() {
OutputVideoRoutes = new Dictionary<uint, ushort>();
OutputAudioRoutes = new Dictionary<uint, ushort>();
TxOnlineStatus = new Dictionary<uint, ushort>();
RxOnlineStatus = new Dictionary<uint, ushort>();
TxVideoSyncStatus = new Dictionary<uint, ushort>();
InputNames = new Dictionary<uint, ushort>();
OutputNames = new Dictionary<uint, ushort>();
OutputRouteNames = new Dictionary<uint, ushort>();
HdcpSupport = new Dictionary<uint, ushort>();
HdcpSupportCapability = new Dictionary<uint, ushort>();
for (uint x = 1; x <= 200; x++) {
// Debug.Console(0, "Init Value {0}", x);
uint tempNum = x;
HdcpSupportCapability[tempNum] = (ushort)(tempNum + 1200);
HdcpSupport[tempNum] = (ushort)(tempNum + 1000);
OutputVideoRoutes[tempNum] = (ushort)(tempNum + 100);
OutputAudioRoutes[tempNum] = (ushort)(tempNum + 300);
TxOnlineStatus[tempNum] = (ushort)(tempNum + 500);
RxOnlineStatus[tempNum] = (ushort)(tempNum + 700);
TxVideoSyncStatus[tempNum] = (ushort)(tempNum + 100);
InputNames[tempNum] = (ushort)(tempNum + 100);
OutputNames[tempNum] = (ushort)(tempNum + 300);
OutputRouteNames[tempNum] = (ushort)(tempNum + 2000);
}
}
}
}

View File

@@ -0,0 +1,217 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.DM;
using PepperDash.Core;
using PepperDash.Essentials.Core.Routing;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.EthernetCommunication;
using Crestron.SimplSharpPro.DM;
namespace PepperDash.Essentials {
public class EssentialDsp : PepperDash.Core.Device {
public EssentialDspProperties Properties;
public List<BridgeApiEisc> BridgeApiEiscs;
private PepperDash.Essentials.Devices.Common.DSP.QscDsp Dsp;
private EssentialDspApiMap ApiMap = new EssentialDspApiMap();
public EssentialDsp(string key, string name, JToken properties)
: base(key, name) {
Properties = JsonConvert.DeserializeObject<EssentialDspProperties>(properties.ToString());
}
public override bool CustomActivate() {
// Create EiscApis
try
{
ICommunicationMonitor comm = null;
foreach (var device in DeviceManager.AllDevices)
{
if (device.Key == this.Properties.connectionDeviceKey)
{
if (!(device is ICommunicationMonitor))
{
comm = device as ICommunicationMonitor;
}
Debug.Console(2, "deviceKey {0} Matches", device.Key);
Dsp = DeviceManager.GetDeviceForKey(device.Key) as PepperDash.Essentials.Devices.Common.DSP.QscDsp;
break;
}
else
{
Debug.Console(2, "deviceKey {0} doesn't match", device.Key);
}
}
if (Properties.EiscApiIpids != null && Dsp != null)
{
foreach (string Ipid in Properties.EiscApiIpids)
{
var ApiEisc = new BridgeApiEisc(Ipid);
Debug.Console(2, "Connecting EiscApi {0} to {1}", ApiEisc.Ipid, Dsp.Name);
ushort x = 1;
if (comm != null)
{
comm.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(ApiEisc.Eisc.BooleanInput[ApiMap.Online]);
}
foreach (var channel in Dsp.LevelControlPoints)
{
//var QscChannel = channel.Value as PepperDash.Essentials.Devices.Common.DSP.QscDspLevelControl;
Debug.Console(2, "QscChannel {0} connect", x);
var genericChannel = channel.Value as IBasicVolumeWithFeedback;
if (channel.Value.Enabled)
{
ApiEisc.Eisc.StringInput[ApiMap.channelName[x]].StringValue = channel.Value.LevelCustomName;
ApiEisc.Eisc.UShortInput[ApiMap.channelType[x]].UShortValue = (ushort)channel.Value.Type;
genericChannel.MuteFeedback.LinkInputSig(ApiEisc.Eisc.BooleanInput[ApiMap.channelMuteToggle[x]]);
genericChannel.VolumeLevelFeedback.LinkInputSig(ApiEisc.Eisc.UShortInput[ApiMap.channelVolume[x]]);
ApiEisc.Eisc.SetSigTrueAction(ApiMap.channelMuteToggle[x], () => genericChannel.MuteToggle());
ApiEisc.Eisc.SetSigTrueAction(ApiMap.channelMuteOn[x], () => genericChannel.MuteOn());
ApiEisc.Eisc.SetSigTrueAction(ApiMap.channelMuteOff[x], () => genericChannel.MuteOff());
ApiEisc.Eisc.SetBoolSigAction(ApiMap.channelVolumeUp[x], b => genericChannel.VolumeUp(b));
ApiEisc.Eisc.SetBoolSigAction(ApiMap.channelVolumeDown[x], b => genericChannel.VolumeDown(b));
ApiEisc.Eisc.SetUShortSigAction(ApiMap.channelVolume[x], u => genericChannel.SetVolume(u));
ApiEisc.Eisc.SetStringSigAction(ApiMap.presetString, s => Dsp.RunPreset(s));
}
x++;
}
x = 1;
foreach (var preset in Dsp.PresetList)
{
ApiEisc.Eisc.StringInput[ApiMap.presets[x]].StringValue = preset.label;
ApiEisc.Eisc.SetSigTrueAction(ApiMap.presets[x], () => Dsp.RunPresetNumber(x));
x++;
}
foreach (var dialer in Dsp.Dialers)
{
ApiEisc.Eisc.SetSigTrueAction(ApiMap.Keypad0, () => dialer.Value.SendKeypad(PepperDash.Essentials.Devices.Common.DSP.QscDspDialer.eKeypadKeys.Num0));
ApiEisc.Eisc.SetSigTrueAction(ApiMap.Keypad1, () => dialer.Value.SendKeypad(PepperDash.Essentials.Devices.Common.DSP.QscDspDialer.eKeypadKeys.Num1));
ApiEisc.Eisc.SetSigTrueAction(ApiMap.Keypad2, () => dialer.Value.SendKeypad(PepperDash.Essentials.Devices.Common.DSP.QscDspDialer.eKeypadKeys.Num2));
ApiEisc.Eisc.SetSigTrueAction(ApiMap.Keypad3, () => dialer.Value.SendKeypad(PepperDash.Essentials.Devices.Common.DSP.QscDspDialer.eKeypadKeys.Num3));
ApiEisc.Eisc.SetSigTrueAction(ApiMap.Keypad4, () => dialer.Value.SendKeypad(PepperDash.Essentials.Devices.Common.DSP.QscDspDialer.eKeypadKeys.Num4));
ApiEisc.Eisc.SetSigTrueAction(ApiMap.Keypad5, () => dialer.Value.SendKeypad(PepperDash.Essentials.Devices.Common.DSP.QscDspDialer.eKeypadKeys.Num5));
ApiEisc.Eisc.SetSigTrueAction(ApiMap.Keypad6, () => dialer.Value.SendKeypad(PepperDash.Essentials.Devices.Common.DSP.QscDspDialer.eKeypadKeys.Num6));
ApiEisc.Eisc.SetSigTrueAction(ApiMap.Keypad7, () => dialer.Value.SendKeypad(PepperDash.Essentials.Devices.Common.DSP.QscDspDialer.eKeypadKeys.Num7));
ApiEisc.Eisc.SetSigTrueAction(ApiMap.Keypad8, () => dialer.Value.SendKeypad(PepperDash.Essentials.Devices.Common.DSP.QscDspDialer.eKeypadKeys.Num8));
ApiEisc.Eisc.SetSigTrueAction(ApiMap.Keypad9, () => dialer.Value.SendKeypad(PepperDash.Essentials.Devices.Common.DSP.QscDspDialer.eKeypadKeys.Num9));
ApiEisc.Eisc.SetSigTrueAction(ApiMap.KeypadStar, () => dialer.Value.SendKeypad(PepperDash.Essentials.Devices.Common.DSP.QscDspDialer.eKeypadKeys.Star));
ApiEisc.Eisc.SetSigTrueAction(ApiMap.KeypadPound, () => dialer.Value.SendKeypad(PepperDash.Essentials.Devices.Common.DSP.QscDspDialer.eKeypadKeys.Pound));
ApiEisc.Eisc.SetSigTrueAction(ApiMap.KeypadClear, () => dialer.Value.SendKeypad(PepperDash.Essentials.Devices.Common.DSP.QscDspDialer.eKeypadKeys.Clear));
ApiEisc.Eisc.SetSigTrueAction(ApiMap.KeypadBackspace, () => dialer.Value.SendKeypad(PepperDash.Essentials.Devices.Common.DSP.QscDspDialer.eKeypadKeys.Backspace));
ApiEisc.Eisc.SetSigTrueAction(ApiMap.Dial, () => dialer.Value.Dial());
ApiEisc.Eisc.SetSigTrueAction(ApiMap.DoNotDisturbToggle, () => dialer.Value.DoNotDisturbToggle());
ApiEisc.Eisc.SetSigTrueAction(ApiMap.DoNotDisturbOn, () => dialer.Value.DoNotDisturbOn());
ApiEisc.Eisc.SetSigTrueAction(ApiMap.DoNotDisturbOff, () => dialer.Value.DoNotDisturbOff());
ApiEisc.Eisc.SetSigTrueAction(ApiMap.AutoAnswerToggle, () => dialer.Value.AutoAnswerToggle());
ApiEisc.Eisc.SetSigTrueAction(ApiMap.AutoAnswerOn, () => dialer.Value.AutoAnswerOn());
ApiEisc.Eisc.SetSigTrueAction(ApiMap.AutoAnswerOff, () => dialer.Value.AutoAnswerOff());
dialer.Value.DoNotDisturbFeedback.LinkInputSig(ApiEisc.Eisc.BooleanInput[ApiMap.DoNotDisturbToggle]);
dialer.Value.DoNotDisturbFeedback.LinkInputSig(ApiEisc.Eisc.BooleanInput[ApiMap.DoNotDisturbOn]);
dialer.Value.DoNotDisturbFeedback.LinkComplementInputSig(ApiEisc.Eisc.BooleanInput[ApiMap.DoNotDisturbOff]);
dialer.Value.AutoAnswerFeedback.LinkInputSig(ApiEisc.Eisc.BooleanInput[ApiMap.AutoAnswerToggle]);
dialer.Value.AutoAnswerFeedback.LinkInputSig(ApiEisc.Eisc.BooleanInput[ApiMap.AutoAnswerOn]);
dialer.Value.AutoAnswerFeedback.LinkComplementInputSig(ApiEisc.Eisc.BooleanInput[ApiMap.AutoAnswerOff]);
dialer.Value.OffHookFeedback.LinkInputSig(ApiEisc.Eisc.BooleanInput[ApiMap.Dial]);
dialer.Value.DialStringFeedback.LinkInputSig(ApiEisc.Eisc.StringInput[ApiMap.DialString]);
}
}
}
Debug.Console(2, "Name {0} Activated", this.Name);
return true;
}
catch (Exception e) {
Debug.Console(0, "Bridge {0}", e);
return false;
}
}
}
public class EssentialDspProperties {
public string connectionDeviceKey;
public string[] EiscApiIpids;
}
public class EssentialDspApiMap {
public ushort Online = 1;
public ushort presetString = 2000;
public Dictionary<uint, ushort> channelMuteToggle;
public Dictionary<uint, ushort> channelMuteOn;
public Dictionary<uint, ushort> channelMuteOff;
public Dictionary<uint, ushort> channelVolume;
public Dictionary<uint, ushort> channelType;
public Dictionary<uint, ushort> channelName;
public Dictionary<uint, ushort> channelVolumeUp;
public Dictionary<uint, ushort> channelVolumeDown;
public Dictionary<uint, ushort> presets;
public ushort DialString = 3100;
public ushort Keypad0 = 3110;
public ushort Keypad1 = 3111;
public ushort Keypad2 = 3112;
public ushort Keypad3 = 3113;
public ushort Keypad4 = 3114;
public ushort Keypad5 = 3115;
public ushort Keypad6 = 3116;
public ushort Keypad7 = 3117;
public ushort Keypad8 = 3118;
public ushort Keypad9 = 3119;
public ushort KeypadStar = 3120;
public ushort KeypadPound = 3121;
public ushort KeypadClear = 3122;
public ushort KeypadBackspace = 3123;
public ushort Dial = 3124;
public ushort DoNotDisturbToggle = 3132;
public ushort DoNotDisturbOn = 3133;
public ushort DoNotDisturbOff = 3134;
public ushort AutoAnswerToggle = 3127;
public ushort AutoAnswerOn = 3125;
public ushort AutoAnswerOff = 3126;
public EssentialDspApiMap() {
channelMuteToggle = new Dictionary<uint, ushort>();
channelMuteOn = new Dictionary<uint, ushort>();
channelMuteOff = new Dictionary<uint, ushort>();
channelVolume = new Dictionary<uint, ushort>();
channelName = new Dictionary<uint, ushort>();
channelType = new Dictionary<uint, ushort>();
presets = new Dictionary<uint, ushort>();
channelVolumeUp = new Dictionary<uint, ushort>();
channelVolumeDown = new Dictionary<uint, ushort>();
for (uint x = 1; x <= 100; x++) {
uint tempNum = x;
presets[tempNum] = (ushort)(tempNum + 100);
channelMuteToggle[tempNum] = (ushort)(tempNum + 400);
channelMuteOn[tempNum] = (ushort)(tempNum + 600);
channelMuteOff[tempNum] = (ushort)(tempNum + 800);
channelVolume[tempNum] = (ushort)(tempNum + 200);
channelName[tempNum] = (ushort)(tempNum + 200);
channelType[tempNum] = (ushort)(tempNum + 400);
channelVolumeUp[tempNum] = (ushort)(tempNum + 1000);
channelVolumeDown[tempNum] = (ushort)(tempNum + 1200);
}
}
}
}

View File

@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.DM;
using PepperDash.Core;
using PepperDash.Essentials.Core.Routing;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.EthernetCommunication;
using Crestron.SimplSharpPro.DM;
namespace PepperDash.Essentials
{
public class EssentialsTVOne : PepperDash.Core.Device
{
public EssentialTVOneProperties Properties;
public List<BridgeApiEisc> BridgeApiEiscs;
private PepperDash.Essentials.Devices.Common.TVOneCorio TVOneCorio;
private EssentialsTVOneApiMap ApiMap = new EssentialsTVOneApiMap();
public EssentialsTVOne(string key, string name, JToken properties)
: base(key, name)
{
Properties = JsonConvert.DeserializeObject<EssentialTVOneProperties>(properties.ToString());
}
public override bool CustomActivate() {
// Create EiscApis
try
{
foreach (var device in DeviceManager.AllDevices)
{
if (device.Key == this.Properties.connectionDeviceKey)
{
Debug.Console(2, "deviceKey {0} Matches", device.Key);
TVOneCorio = DeviceManager.GetDeviceForKey(device.Key) as PepperDash.Essentials.Devices.Common.TVOneCorio;
break;
}
else
{
Debug.Console(2, "deviceKey {0} doesn't match", device.Key);
}
}
if (Properties.EiscApiIpids != null && TVOneCorio != null)
{
foreach (string Ipid in Properties.EiscApiIpids)
{
var ApiEisc = new BridgeApiEisc(Ipid);
Debug.Console(2, "Connecting EiscApi {0} to {1}", ApiEisc.Ipid, TVOneCorio.Name);
ushort x = 1;
TVOneCorio.OnlineFeedback.LinkInputSig(ApiEisc.Eisc.BooleanInput[ApiMap.Online]);
ApiEisc.Eisc.SetUShortSigAction(ApiMap.CallPreset, u => TVOneCorio.CallPreset(u));
TVOneCorio.PresetFeedback.LinkInputSig(ApiEisc.Eisc.UShortInput[ApiMap.PresetFeedback]);
}
}
Debug.Console(2, "Name {0} Activated", this.Name);
return true;
}
catch (Exception e) {
Debug.Console(0, "Bridge {0}", e);
return false;
}
}
}
public class EssentialTVOneProperties
{
public string connectionDeviceKey;
public string[] EiscApiIpids;
}
public class EssentialsTVOneApiMap
{
public ushort CallPreset = 1;
public ushort PresetFeedback = 1;
public ushort Online = 1;
public EssentialsTVOneApiMap()
{
}
}
}

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class GenericLightingApiExtensions
{
public static void LinkToApi(this PepperDash.Essentials.Core.Lighting.LightingBase lightingDevice, BasicTriList trilist, uint joinStart, string joinMapKey)
{
GenericLightingJoinMap joinMap = new GenericLightingJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<GenericLightingJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString());
// GenericLighitng Actions & FeedBack
trilist.SetUShortSigAction(joinMap.SelectScene, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u]));
int sceneIndex = 1;
foreach (var scene in lightingDevice.LightingScenes)
{
var tempIndex = sceneIndex - 1;
trilist.SetSigTrueAction((uint)(joinMap.LightingSceneOffset + sceneIndex), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[tempIndex]));
scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.LightingSceneOffset + sceneIndex)]);
trilist.StringInput[(uint)(joinMap.LightingSceneOffset + sceneIndex)].StringValue = scene.Name;
trilist.BooleanInput[(uint)(joinMap.ButtonVisibilityOffset + sceneIndex)].BoolValue = true;
sceneIndex++;
}
if (lightingDevice.GetType().Name.ToString() == "LutronQuantumArea")
{
var lutronDevice = lightingDevice as PepperDash.Essentials.Devices.Common.Environment.Lutron.LutronQuantumArea;
lutronDevice.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline]);
trilist.SetStringSigAction(joinMap.IntegrationIdSet, s => lutronDevice.IntegrationId = s);
}
//ApiEisc.Eisc.SetStringSigAction(ApiMap.integrationID, (s) => { lutronLights.IntegrationId = s; });
/*
var lutronLights = lightingDevice as PepperDash.Essentials.Devices.Common.Environment.Lutron.LutronQuantumArea;
for (uint i = 1; i <= lightingBase.CircuitCount; i++)
{
var circuit = i;
lightingBase.CircuitNameFeedbacks[circuit - 1].LinkInputSig(trilist.StringInput[joinMap.CircuitNames + circuit]);
lightingBase.CircuitIsCritical[circuit - 1].LinkInputSig(trilist.BooleanInput[joinMap.CircuitIsCritical + circuit]);
lightingBase.CircuitState[circuit - 1].LinkInputSig(trilist.BooleanInput[joinMap.CircuitState + circuit]);
trilist.SetSigTrueAction(joinMap.CircuitCycle + circuit, () => lightingBase.CycleCircuit(circuit - 1));
trilist.SetSigTrueAction(joinMap.CircuitOnCmd + circuit, () => lightingBase.TurnOnCircuit(circuit - 1));
trilist.SetSigTrueAction(joinMap.CircuitOffCmd + circuit, () => lightingBase.TurnOffCircuit(circuit - 1));
}
*/
}
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.CrestronIO;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class GenericRelayDeviceApiExtensions
{
public static void LinkToApi(this GenericRelayDevice relay, BasicTriList trilist, uint joinStart, string joinMapKey)
{
GenericRelayControllerJoinMap joinMap = new GenericRelayControllerJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<GenericRelayControllerJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
if (relay.RelayOutput == null)
{
Debug.Console(1, relay, "Unable to link device '{0}'. Relay is null", relay.Key);
return;
}
Debug.Console(1, relay, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
trilist.SetBoolSigAction(joinMap.Relay, new Action<bool>(b =>
{
if (b)
relay.CloseRelay();
else
relay.OpenRelay();
}));
// feedback for relay state
relay.OutputIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Relay]);
}
}
}

View File

@@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Essentials.Devices.Common.Occupancy;
using PepperDash.Essentials.Core;
using PepperDash.Core;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class GlsOccupancySensorBaseControllerApiExtensions
{
public static void LinkToApi(this GlsOccupancySensorBaseController occController, BasicTriList trilist, uint joinStart, string joinMapKey)
{
GlsOccupancySensorBaseJoinMap joinMap = new GlsOccupancySensorBaseJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<GlsOccupancySensorBaseJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
Debug.Console(1, occController, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
#region Single and Dual Sensor Stuff
occController.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline]);
// Occupied status
trilist.SetSigTrueAction(joinMap.ForceOccupied, new Action(() => occController.ForceOccupied()));
trilist.SetSigTrueAction(joinMap.ForceVacant, new Action(() => occController.ForceVacant()));
occController.RoomIsOccupiedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.RoomOccupiedFeedback]);
occController.RoomIsOccupiedFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.RoomVacantFeedback]);
occController.RawOccupancyFeedback.LinkInputSig(trilist.BooleanInput[joinMap.RawOccupancyFeedback]);
// Timouts
trilist.SetUShortSigAction(joinMap.Timeout, new Action<ushort>((u) => occController.SetRemoteTimeout(u)));
occController.CurrentTimeoutFeedback.LinkInputSig(trilist.UShortInput[joinMap.Timeout]);
occController.LocalTimoutFeedback.LinkInputSig(trilist.UShortInput[joinMap.TimeoutLocalFeedback]);
// LED Flash
trilist.SetSigTrueAction(joinMap.EnableLedFlash, new Action(() => occController.SetLedFlashEnable(true)));
trilist.SetSigTrueAction(joinMap.DisableLedFlash, new Action(() => occController.SetLedFlashEnable(false)));
occController.LedFlashEnabledFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.EnableLedFlash]);
// Short Timeout
trilist.SetSigTrueAction(joinMap.EnableShortTimeout, new Action(() => occController.SetShortTimeoutState(true)));
trilist.SetSigTrueAction(joinMap.DisableShortTimeout, new Action(() => occController.SetShortTimeoutState(false)));
occController.ShortTimeoutEnabledFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableShortTimeout]);
// PIR Sensor
trilist.SetSigTrueAction(joinMap.EnablePir, new Action(() => occController.SetPirEnable(true)));
trilist.SetSigTrueAction(joinMap.DisablePir, new Action(() => occController.SetPirEnable(false)));
occController.PirSensorEnabledFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnablePir]);
// PIR Sensitivity in Occupied State
trilist.SetBoolSigAction(joinMap.IncrementPirInOccupiedState, new Action<bool>((b) => occController.IncrementPirSensitivityInOccupiedState(b)));
trilist.SetBoolSigAction(joinMap.DecrementPirInOccupiedState, new Action<bool>((b) => occController.DecrementPirSensitivityInOccupiedState(b)));
occController.PirSensitivityInOccupiedStateFeedback.LinkInputSig(trilist.UShortInput[joinMap.PirSensitivityInOccupiedState]);
// PIR Sensitivity in Vacant State
trilist.SetBoolSigAction(joinMap.IncrementPirInVacantState, new Action<bool>((b) => occController.IncrementPirSensitivityInVacantState(b)));
trilist.SetBoolSigAction(joinMap.DecrementPirInVacantState, new Action<bool>((b) => occController.DecrementPirSensitivityInVacantState(b)));
occController.PirSensitivityInVacantStateFeedback.LinkInputSig(trilist.UShortInput[joinMap.PirSensitivityInVacantState]);
#endregion
#region Dual Technology Sensor Stuff
var odtOccController = occController as GlsOdtOccupancySensorController;
if (odtOccController != null)
{
// OR When Vacated
trilist.SetBoolSigAction(joinMap.OrWhenVacated, new Action<bool>((b) => odtOccController.SetOrWhenVacatedState(b)));
odtOccController.OrWhenVacatedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.OrWhenVacated]);
// AND When Vacated
trilist.SetBoolSigAction(joinMap.AndWhenVacated, new Action<bool>((b) => odtOccController.SetAndWhenVacatedState(b)));
odtOccController.AndWhenVacatedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.AndWhenVacated]);
// Ultrasonic A Sensor
trilist.SetSigTrueAction(joinMap.EnableUsA, new Action(() => odtOccController.SetUsAEnable(true)));
trilist.SetSigTrueAction(joinMap.DisableUsA, new Action(() => odtOccController.SetUsAEnable(false)));
odtOccController.UltrasonicAEnabledFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableUsA]);
// Ultrasonic B Sensor
trilist.SetSigTrueAction(joinMap.EnableUsB, new Action(() => odtOccController.SetUsBEnable(true)));
trilist.SetSigTrueAction(joinMap.DisableUsB, new Action(() => odtOccController.SetUsBEnable(false)));
odtOccController.UltrasonicAEnabledFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableUsB]);
// US Sensitivity in Occupied State
trilist.SetBoolSigAction(joinMap.IncrementUsInOccupiedState, new Action<bool>((b) => odtOccController.IncrementUsSensitivityInOccupiedState(b)));
trilist.SetBoolSigAction(joinMap.DecrementUsInOccupiedState, new Action<bool>((b) => odtOccController.DecrementUsSensitivityInOccupiedState(b)));
odtOccController.UltrasonicSensitivityInOccupiedStateFeedback.LinkInputSig(trilist.UShortInput[joinMap.UsSensitivityInOccupiedState]);
// US Sensitivity in Vacant State
trilist.SetBoolSigAction(joinMap.IncrementUsInVacantState, new Action<bool>((b) => odtOccController.IncrementUsSensitivityInVacantState(b)));
trilist.SetBoolSigAction(joinMap.DecrementUsInVacantState, new Action<bool>((b) => odtOccController.DecrementUsSensitivityInVacantState(b)));
odtOccController.UltrasonicSensitivityInVacantStateFeedback.LinkInputSig(trilist.UShortInput[joinMap.UsSensitivityInVacantState]);
}
#endregion
}
}
}

View File

@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Endpoints;
using Crestron.SimplSharpPro.DM.Endpoints.Receivers;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.DM;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class HdMdxxxCEControllerApiExtensions
{
public static void LinkToApi(this HdMdxxxCEController hdMdPair, BasicTriList trilist, uint joinStart, string joinMapKey)
{
HdMdxxxCEControllerJoinMap joinMap = new HdMdxxxCEControllerJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<HdMdxxxCEControllerJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
Debug.Console(1, hdMdPair, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
hdMdPair.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline]);
hdMdPair.RemoteEndDetectedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.RemoteEndDetected]);
trilist.SetSigTrueAction(joinMap.AutoRouteOn, new Action(() => hdMdPair.AutoRouteOn()));
hdMdPair.AutoRouteOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.AutoRouteOn]);
trilist.SetSigTrueAction(joinMap.AutoRouteOff, new Action(() => hdMdPair.AutoRouteOff()));
hdMdPair.AutoRouteOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.AutoRouteOff]);
trilist.SetSigTrueAction(joinMap.PriorityRoutingOn, new Action(() => hdMdPair.PriorityRouteOn()));
hdMdPair.PriorityRoutingOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PriorityRoutingOn]);
trilist.SetSigTrueAction(joinMap.PriorityRoutingOff, new Action(() => hdMdPair.PriorityRouteOff()));
hdMdPair.PriorityRoutingOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PriorityRoutingOff]);
trilist.SetSigTrueAction(joinMap.InputOnScreenDisplayEnabled, new Action(() => hdMdPair.OnScreenDisplayEnable()));
hdMdPair.InputOnScreenDisplayEnabledFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputOnScreenDisplayEnabled]);
trilist.SetSigTrueAction(joinMap.AutoRouteOff, new Action(() => hdMdPair.OnScreenDisplayDisable()));
hdMdPair.InputOnScreenDisplayEnabledFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.InputOnScreenDisplayDisabled]);
trilist.SetUShortSigAction(joinMap.VideoSource, new Action<ushort>((i) => hdMdPair.ExecuteSwitch(i, null, eRoutingSignalType.Video | eRoutingSignalType.Audio)));
hdMdPair.VideoSourceFeedback.LinkInputSig(trilist.UShortInput[joinMap.VideoSource]);
trilist.UShortInput[joinMap.SourceCount].UShortValue = (ushort)hdMdPair.InputPorts.Count;
foreach (var input in hdMdPair.InputPorts)
{
var number = Convert.ToUInt16(input.Selector);
hdMdPair.SyncDetectedFeedbacks[number].LinkInputSig(trilist.BooleanInput[joinMap.SyncDetected + number]);
trilist.StringInput[joinMap.SourceNames + number].StringValue = input.Key;
}
}
}
}

View File

@@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class IBasicCommunicationApiExtensions
{
public static void LinkToApi(this GenericComm comm, BasicTriList trilist, uint joinStart, string joinMapKey)
{
IBasicCommunicationJoinMap joinMap = new IBasicCommunicationJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<IBasicCommunicationJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
if (comm.CommPort == null)
{
Debug.Console(1, comm, "Unable to link device '{0}'. CommPort is null", comm.Key);
return;
}
Debug.Console(1, comm, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
// this is a permanent event handler. This cannot be -= from event
comm.CommPort.TextReceived += (s, a) =>
{
Debug.Console(2, comm, "RX: {0}", a.Text);
trilist.SetString(joinMap.TextReceived, a.Text);
};
trilist.SetStringSigAction(joinMap.SendText, new Action<string>(s => comm.CommPort.SendText(s)));
trilist.SetStringSigAction(joinMap.SetPortConfig, new Action<string>(s => comm.SetPortConfig(s)));
var sComm = comm.CommPort as ISocketStatus;
if (sComm != null)
{
sComm.ConnectionChange += (s, a) =>
{
trilist.SetUshort(joinMap.Status, (ushort)(a.Client.ClientStatus));
trilist.SetBool(joinMap.Connected, a.Client.ClientStatus ==
Crestron.SimplSharp.CrestronSockets.SocketStatus.SOCKET_STATUS_CONNECTED);
};
trilist.SetBoolSigAction(joinMap.Connect, new Action<bool>(b =>
{
if (b)
{
sComm.Connect();
}
else
{
sComm.Disconnect();
}
}));
}
}
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
namespace PepperDash.Essentials.Bridges
{
public interface IBridge
{
void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey);
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.CrestronIO;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class IDigitalInputApiExtenstions
{
public static void LinkToApi(this IDigitalInput input, BasicTriList trilist, uint joinStart, string joinMapKey)
{
IDigitalInputJoinMap joinMap = new IDigitalInputJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<IDigitalInputJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
try
{
Debug.Console(1, input as Device, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
// Link feedback for input state
input.InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState]);
}
catch (Exception e)
{
Debug.Console(1, input as Device, "Unable to link device '{0}'. Input is null", (input as Device).Key);
Debug.Console(1, input as Device, "Error: {0}", e);
return;
}
}
}
}

View File

@@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class AirMediaControllerJoinMap : JoinMapBase
{
#region Digitals
/// <summary>
/// Indicates that the device is online when high
/// </summary>
public uint IsOnline { get; set; }
/// <summary>
/// Indicates that the device is in session when high
/// </summary>
public uint IsInSession { get; set; }
/// <summary>
/// Indicates sync detected on HDMI input when high
/// </summary>
public uint HdmiVideoSync { get; set; }
/// <summary>
/// Set High to enable automatic input routing and low to disable. Feedback high when enabled
/// </summary>
public uint AutomaticInputRoutingEnabled { get; set; }
#endregion
#region Analogs
/// <summary>
/// Selects source and provides feedback
/// </summary>
public uint VideoOut { get; set; }
/// <summary>
/// Provided error feedback
/// </summary>
public uint ErrorFB { get; set; }
/// <summary>
/// Indicates the number of connected users as feedback
/// </summary>
public uint NumberOfUsersConnectedFB { get; set; }
/// <summary>
/// Sets the login code and provides the current code as feedback
/// </summary>
public uint LoginCode { get; set; }
#endregion
#region Serials
/// <summary>
/// Provides the name defined in config as feedback
/// </summary>
public uint Name { get; set; }
/// <summary>
/// Provides the connection address as feedback
/// </summary>
public uint ConnectionAddressFB { get; set; }
/// <summary>
/// Provides the hostname as feedback
/// </summary>
public uint HostnameFB { get; set; }
/// <summary>
/// Provides the serial number as feedback
/// </summary>
public uint SerialNumberFeedback { get; set; }
#endregion
public AirMediaControllerJoinMap()
{
// Digital
IsOnline = 1;
IsInSession = 2;
HdmiVideoSync = 3;
AutomaticInputRoutingEnabled = 4;
// Analog
VideoOut = 1;
ErrorFB = 2;
NumberOfUsersConnectedFB = 3;
LoginCode = 4;
// Serial
Name = 1;
ConnectionAddressFB = 2;
HostnameFB = 3;
SerialNumberFeedback = 4;
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
IsOnline = IsOnline + joinOffset;
IsInSession = IsInSession + joinOffset;
HdmiVideoSync = HdmiVideoSync + joinOffset;
AutomaticInputRoutingEnabled = AutomaticInputRoutingEnabled + joinOffset;
VideoOut = VideoOut + joinOffset;
ErrorFB = ErrorFB + joinOffset;
NumberOfUsersConnectedFB = NumberOfUsersConnectedFB + joinOffset;
LoginCode = LoginCode + joinOffset;
Name = Name + joinOffset;
ConnectionAddressFB = ConnectionAddressFB + joinOffset;
HostnameFB = HostnameFB + joinOffset;
SerialNumberFeedback = SerialNumberFeedback + joinOffset;
}
}
}

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class AppleTvJoinMap : JoinMapBase
{
#region Digitals
/// <summary>
/// Sends up arrow command while high
/// </summary>
public uint UpArrow { get; set; }
/// <summary>
/// Sends down arrow command while high
/// </summary>
public uint DnArrow { get; set; }
/// <summary>
/// Sends left arrow command while high
/// </summary>
public uint LeftArrow { get; set; }
/// <summary>
/// Sends right arrow command while high
/// </summary>
public uint RightArrow { get; set; }
/// <summary>
/// Sends menu command
/// </summary>
public uint Menu { get; set; }
/// <summary>
/// Sends select command
/// </summary>
public uint Select { get; set; }
/// <summary>
/// Sends play/pause command
/// </summary>
public uint PlayPause { get; set; }
#endregion
public AppleTvJoinMap()
{
UpArrow = 1;
DnArrow = 2;
LeftArrow = 3;
RightArrow = 4;
Menu = 5;
Select = 6;
PlayPause = 7;
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
UpArrow = UpArrow + joinOffset;
DnArrow = DnArrow + joinOffset;
LeftArrow = LeftArrow + joinOffset;
RightArrow = RightArrow + joinOffset;
Menu = Menu + joinOffset;
Select = Select + joinOffset;
PlayPause = PlayPause + joinOffset;
}
}
}

View File

@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class CameraControllerJoinMap : JoinMapBase
{
public uint IsOnline { get; set; }
public uint PowerOff { get; set; }
public uint PowerOn { get; set; }
public uint Up { get; set; }
public uint Down { get; set; }
public uint Left { get; set; }
public uint Right { get; set; }
public uint ZoomIn { get; set; }
public uint ZoomOut { get; set; }
public uint PresetRecallOffset { get; set; }
public uint PresetSaveOffset { get; set; }
public uint NumberOfPresets { get; set; }
public CameraControllerJoinMap()
{
// Digital
IsOnline = 9;
PowerOff = 8;
PowerOn = 7;
Up = 1;
Down = 2;
Left = 3;
Right = 4;
ZoomIn = 5;
ZoomOut = 6;
PresetRecallOffset = 10;
PresetSaveOffset = 30;
NumberOfPresets = 5;
// Analog
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
IsOnline = IsOnline + joinOffset;
PowerOff = PowerOff + joinOffset;
PowerOn = PowerOn + joinOffset;
Up = Up + joinOffset;
Down = Down + joinOffset;
Left = Left + joinOffset;
Right = Right + joinOffset;
ZoomIn = ZoomIn + joinOffset;
ZoomOut = ZoomOut + joinOffset;
PresetRecallOffset = PresetRecallOffset + joinOffset;
PresetSaveOffset = PresetSaveOffset + joinOffset;
}
}
}

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class DigitalLoggerJoinMap : JoinMapBase
{
public uint IsOnline { get; set; }
public uint CircuitNames { get; set; }
public uint CircuitState { get; set; }
public uint CircuitCycle { get; set; }
public uint CircuitIsCritical { get; set; }
public uint CircuitOnCmd { get; set; }
public uint CircuitOffCmd { get; set; }
public DigitalLoggerJoinMap()
{
// Digital
IsOnline = 9;
CircuitState = 0;
CircuitCycle = 0;
CircuitIsCritical = 10;
CircuitOnCmd = 10;
CircuitOffCmd = 20;
// Serial
CircuitNames = 0;
// Analog
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
IsOnline = IsOnline + joinOffset;
CircuitNames = CircuitNames + joinOffset;
CircuitState = CircuitState + joinOffset;
CircuitCycle = CircuitCycle + joinOffset;
CircuitIsCritical = CircuitIsCritical + joinOffset;
CircuitOnCmd = CircuitOnCmd + joinOffset;
CircuitOffCmd = CircuitOffCmd + joinOffset;
}
}
}

View File

@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class DisplayControllerJoinMap : JoinMapBase
{
#region Digitals
/// <summary>
/// Turns the display off and reports power off feedback
/// </summary>
public uint PowerOff { get; set; }
/// <summary>
/// Turns the display on and repots power on feedback
/// </summary>
public uint PowerOn { get; set; }
/// <summary>
/// Indicates that the display device supports two way communication when high
/// </summary>
public uint IsTwoWayDisplay { get; set; }
/// <summary>
/// Increments the volume while high
/// </summary>
public uint VolumeUp { get; set; }
/// <summary>
/// Decrements teh volume while high
/// </summary>
public uint VolumeDown { get; set; }
/// <summary>
/// Toggles the mute state. Feedback is high when volume is muted
/// </summary>
public uint VolumeMute { get; set; }
/// <summary>
/// Range of digital joins to select inputs and report current input as feedback
/// </summary>
public uint InputSelectOffset { get; set; }
/// <summary>
/// Range of digital joins to report visibility for input buttons
/// </summary>
public uint ButtonVisibilityOffset { get; set; }
/// <summary>
/// High if the device is online
/// </summary>
public uint IsOnline { get; set; }
#endregion
#region Analogs
/// <summary>
/// Analog join to set the input and report current input as feedback
/// </summary>
public uint InputSelect { get; set; }
/// <summary>
/// Sets the volume level and reports the current level as feedback
/// </summary>
public uint VolumeLevel { get; set; }
#endregion
#region Serials
/// <summary>
/// Reports the name of the display as defined in config as feedback
/// </summary>
public uint Name { get; set; }
/// <summary>
/// Range of serial joins that reports the names of the inputs as feedback
/// </summary>
public uint InputNamesOffset { get; set; }
#endregion
public DisplayControllerJoinMap()
{
// Digital
IsOnline = 50;
PowerOff = 1;
PowerOn = 2;
IsTwoWayDisplay = 3;
VolumeUp = 5;
VolumeDown = 6;
VolumeMute = 7;
ButtonVisibilityOffset = 40;
InputSelectOffset = 10;
// Analog
InputSelect = 11;
VolumeLevel = 5;
// Serial
Name = 1;
InputNamesOffset = 10;
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
IsOnline = IsOnline + joinOffset;
PowerOff = PowerOff + joinOffset;
PowerOn = PowerOn + joinOffset;
IsTwoWayDisplay = IsTwoWayDisplay + joinOffset;
ButtonVisibilityOffset = ButtonVisibilityOffset + joinOffset;
Name = Name + joinOffset;
InputNamesOffset = InputNamesOffset + joinOffset;
InputSelectOffset = InputSelectOffset + joinOffset;
InputSelect = InputSelect + joinOffset;
VolumeUp = VolumeUp + joinOffset;
VolumeDown = VolumeDown + joinOffset;
VolumeMute = VolumeMute + joinOffset;
VolumeLevel = VolumeLevel + joinOffset;
}
}
}

View File

@@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges {
public class DmBladeChassisControllerJoinMap : JoinMapBase {
#region Digital/Analogs
#endregion
#region Digitals
/// <summary>
/// High when device is online
/// </summary>
public uint IsOnline { get; set; }
/// <summary>
/// Range reports video sync feedback for each input
/// </summary>
public uint VideoSyncStatus { get; set; }
/// <summary>
/// Range reports high if corresponding input's endpoint is online
/// </summary>
public uint InputEndpointOnline { get; set; }
/// <summary>
/// Range reports high if corresponding output's endpoint is online
/// </summary>
public uint OutputEndpointOnline { get; set; }
/// <summary>
/// Range reports high if corresponding input's transmitter supports bridging as a separate device for detailed AV switching, HDCP control, etc.
/// </summary>
public uint TxAdvancedIsPresent { get; set; } // indicates that there is an attached transmitter that should be bridged to be interacted with
#endregion
#region Analogs
/// <summary>
/// Range sets and reports the current video source for the corresponding output
/// </summary>
public uint OutputVideo { get; set; }
/// <summary>
/// Range sets and reports the current HDCP state for the corresponding input card
/// </summary>
public uint HdcpSupportState { get; set; }
/// <summary>
/// Range reports the highest supported HDCP state level for the corresponding input card
/// </summary>
public uint HdcpSupportCapability { get; set; }
#endregion
#region Serials
/// <summary>
/// Range sets and reports the name for the corresponding input card
/// </summary>
public uint InputNames { get; set; }
/// <summary>
/// Range sets and reports the name for the corresponding output card
/// </summary>
public uint OutputNames { get; set; }
/// <summary>
/// Range reports the name of the current video source for the corresponding output card
/// </summary>
public uint OutputCurrentVideoInputNames { get; set; }
/// <summary>
/// Range reports the current input resolution for each corresponding input card
/// </summary>
public uint InputCurrentResolution { get; set; }
#endregion
public DmBladeChassisControllerJoinMap() {
//Digital/Analog
//Digital
IsOnline = 11;
VideoSyncStatus = 100; //101-299
InputEndpointOnline = 500; //501-699
OutputEndpointOnline = 700; //701-899
TxAdvancedIsPresent = 1000; //1001-1199
//Analog
OutputVideo = 100; //101-299
HdcpSupportState = 1000; //1001-1199
HdcpSupportCapability = 1200; //1201-1399
//Serial
InputNames = 100; //101-299
OutputNames = 300; //301-499
OutputCurrentVideoInputNames = 2000; //2001-2199
InputCurrentResolution = 2400; // 2401-2599
}
public override void OffsetJoinNumbers(uint joinStart) {
var joinOffset = joinStart - 1;
IsOnline = IsOnline + joinOffset;
OutputVideo = OutputVideo + joinOffset;
VideoSyncStatus = VideoSyncStatus + joinOffset;
InputNames = InputNames + joinOffset;
OutputNames = OutputNames + joinOffset;
OutputCurrentVideoInputNames = OutputCurrentVideoInputNames + joinOffset;
InputCurrentResolution = InputCurrentResolution + joinOffset;
InputEndpointOnline = InputEndpointOnline + joinOffset;
OutputEndpointOnline = OutputEndpointOnline + joinOffset;
HdcpSupportState = HdcpSupportState + joinOffset;
HdcpSupportCapability = HdcpSupportCapability + joinOffset;
}
}
}

View File

@@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class DmChassisControllerJoinMap : JoinMapBase
{
#region Digital/Analogs
/// <summary>
/// Analog input sets System ID, output reports current ID as feedback.
/// Digital input applies System ID, output is high when applying busy.
/// </summary>
public uint SystemId { get; set; }
#endregion
#region Digitals
/// <summary>
/// High when device is online
/// </summary>
public uint IsOnline { get; set; }
/// <summary>
/// Range reports video sync feedback for each input
/// </summary>
public uint VideoSyncStatus { get; set; }
/// <summary>
/// Range reports high if corresponding input's endpoint is online
/// </summary>
public uint InputEndpointOnline { get; set; }
/// <summary>
/// Range reports high if corresponding output's endpoint is online
/// </summary>
public uint OutputEndpointOnline { get; set; }
/// <summary>
/// Range reports high if corresponding input's transmitter supports bridging as a separate device for detailed AV switching, HDCP control, etc.
/// </summary>
public uint TxAdvancedIsPresent { get; set; } // indicates that there is an attached transmitter that should be bridged to be interacted with
#endregion
#region Analogs
/// <summary>
/// Range sets and reports the current video source for the corresponding output
/// </summary>
public uint OutputVideo { get; set; }
/// <summary>
/// Range sets and reports the current audio source for the corresponding output
/// </summary>
public uint OutputAudio { get; set; }
/// <summary>
/// Range sets and reports the current Usb source for the corresponding output
/// </summary>
public uint OutputUsb { get; set; }
/// <summary>
/// Range sets and reports the current Usb source for the corresponding input
/// </summary>
public uint InputUsb { get; set; }
/// <summary>
/// Range sets and reports the current HDCP state for the corresponding input card
/// </summary>
public uint HdcpSupportState { get; set; }
/// <summary>
/// Range reports the highest supported HDCP state level for the corresponding input card
/// </summary>
public uint HdcpSupportCapability { get; set; }
#endregion
#region Serials
/// <summary>
/// Range sets and reports the name for the corresponding input card
/// </summary>
public uint InputNames { get; set; }
/// <summary>
/// Range sets and reports the name for the corresponding output card
/// </summary>
public uint OutputNames { get; set; }
/// <summary>
/// Range reports the name of the current video source for the corresponding output card
/// </summary>
public uint OutputCurrentVideoInputNames { get; set; }
/// <summary>
/// Range reports the name of the current audio source for the corresponding output card
/// </summary>
public uint OutputCurrentAudioInputNames { get; set; }
/// <summary>
/// Range reports the current input resolution for each corresponding input card
/// </summary>
public uint InputCurrentResolution { get; set; }
#endregion
public DmChassisControllerJoinMap()
{
//Digital/Analog
SystemId = 10; // Analog sets/gets SystemId, digital input applies and provides feedback of ID change busy
//Digital
IsOnline = 11;
VideoSyncStatus = 100; //101-299
InputEndpointOnline = 500; //501-699
OutputEndpointOnline = 700; //701-899
TxAdvancedIsPresent = 1000; //1001-1199
//Analog
OutputVideo = 100; //101-299
OutputAudio = 300; //301-499
OutputUsb = 500; //501-699
InputUsb = 700; //701-899
HdcpSupportState = 1000; //1001-1199
HdcpSupportCapability = 1200; //1201-1399
//Serial
InputNames = 100; //101-299
OutputNames = 300; //301-499
OutputCurrentVideoInputNames = 2000; //2001-2199
OutputCurrentAudioInputNames = 2200; //2201-2399
InputCurrentResolution = 2400; // 2401-2599
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
SystemId = SystemId + joinOffset;
IsOnline = IsOnline + joinOffset;
OutputVideo = OutputVideo + joinOffset;
OutputAudio = OutputAudio + joinOffset;
OutputUsb = OutputUsb + joinOffset;
InputUsb = InputUsb + joinOffset;
VideoSyncStatus = VideoSyncStatus + joinOffset;
InputNames = InputNames + joinOffset;
OutputNames = OutputNames + joinOffset;
OutputCurrentVideoInputNames = OutputCurrentVideoInputNames + joinOffset;
OutputCurrentAudioInputNames = OutputCurrentAudioInputNames + joinOffset;
InputCurrentResolution = InputCurrentResolution + joinOffset;
InputEndpointOnline = InputEndpointOnline + joinOffset;
OutputEndpointOnline = OutputEndpointOnline + joinOffset;
HdcpSupportState = HdcpSupportState + joinOffset;
HdcpSupportCapability = HdcpSupportCapability + joinOffset;
}
}
}

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class DmRmcControllerJoinMap : JoinMapBase
{
#region Digitals
/// <summary>
/// High when device is online (if not attached to a DMP3 or DM chassis with a CPU3 card
/// </summary>
public uint IsOnline { get; set; }
#endregion
#region Serials
/// <summary>
/// Reports the current output resolution
/// </summary>
public uint CurrentOutputResolution { get; set; }
/// <summary>
/// Reports the EDID manufacturer value
/// </summary>
public uint EdidManufacturer { get; set; }
/// <summary>
/// Reports the EDID Name value
/// </summary>
public uint EdidName { get; set; }
/// <summary>
/// Reports the EDID preffered timing value
/// </summary>
public uint EdidPrefferedTiming { get; set; }
/// <summary>
/// Reports the EDID serial number value
/// </summary>
public uint EdidSerialNumber { get; set; }
#endregion
public DmRmcControllerJoinMap()
{
// Digital
IsOnline = 1;
// Serial
CurrentOutputResolution = 1;
EdidManufacturer = 2;
EdidName = 3;
EdidPrefferedTiming = 4;
EdidSerialNumber = 5;
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
IsOnline = IsOnline + joinOffset;
CurrentOutputResolution = CurrentOutputResolution + joinOffset;
EdidManufacturer = EdidManufacturer + joinOffset;
EdidName = EdidName + joinOffset;
EdidPrefferedTiming = EdidPrefferedTiming + joinOffset;
EdidSerialNumber = EdidSerialNumber + joinOffset;
}
}
}

View File

@@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class DmTxControllerJoinMap : JoinMapBase
{
#region Digitals
/// <summary>
/// High when device is online (if not attached to a DMP3 or DM chassis with a CPU3 card
/// </summary>
public uint IsOnline { get; set; }
/// <summary>
/// High when video sync is detected
/// </summary>
public uint VideoSyncStatus { get; set; }
#endregion
#region Analogs
/// <summary>
/// Sets and reports the video source
/// </summary>
public uint VideoInput { get; set; }
/// <summary>
/// Sets and reports the audio source
/// </summary>
public uint AudioInput { get; set; }
/// <summary>
/// Reports the highest supported HDCP state level for the corresponding input card
/// </summary>
public uint HdcpSupportCapability { get; set; }
/// <summary>
/// Sets and reports the current HDCP state for the corresponding input port
/// </summary>
public uint Port1HdcpState { get; set; }
/// <summary>
/// Sets and reports the current HDCP state for the corresponding input port
/// </summary>
public uint Port2HdcpState { get; set; }
#endregion
#region Serials
/// <summary>
/// Reports the current input resolution
/// </summary>
public uint CurrentInputResolution { get; set; }
#endregion
public DmTxControllerJoinMap()
{
// Digital
IsOnline = 1;
VideoSyncStatus = 2;
// Serial
CurrentInputResolution = 1;
// Analog
VideoInput = 1;
AudioInput = 2;
HdcpSupportCapability = 3;
Port1HdcpState = 4;
Port2HdcpState = 5;
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
IsOnline = IsOnline + joinOffset;
VideoSyncStatus = VideoSyncStatus + joinOffset;
CurrentInputResolution = CurrentInputResolution + joinOffset;
VideoInput = VideoInput + joinOffset;
AudioInput = AudioInput + joinOffset;
HdcpSupportCapability = HdcpSupportCapability + joinOffset;
Port1HdcpState = Port1HdcpState + joinOffset;
Port2HdcpState = Port2HdcpState + joinOffset;
}
}
}

View File

@@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class DmpsAudioOutputControllerJoinMap : JoinMapBase
{
#region Digital/Analog
/// <summary>
/// Range of joins for Master Volume
/// Analog join 1 is volume level and feedback
/// Digital join 1 is Mute on and feedback
/// Digital join 2 is Mute off and feedback
/// Digital join 3 is volume up
/// Digital join 4 is volume down
/// </summary>
public uint MasterVolume { get; set; }
/// <summary>
/// Range of joins for Source Volume
/// Analog join 11 is volume level and feedback
/// Digital join 11 is Mute on and feedback
/// Digital join 12 is Mute off and feedback
/// Digital join 13 is volume up
/// Digital join 14 is volume down
/// </summary>
public uint SourceVolume { get; set; }
/// <summary>
/// Range of joins for Codec1 Volume (if applicable)
/// Analog join 21 is volume level and feedback
/// Digital join 21 is Mute on and feedback
/// Digital join 22 is Mute off and feedback
/// Digital join 23 is volume up
/// Digital join 24 is volume down
/// </summary>
public uint Codec1Volume { get; set; }
/// <summary>
/// Range of joins for Codec2 Volume (if applicable)
/// Analog join 31 is volume level and feedback
/// Digital join 31 is Mute on and feedback
/// Digital join 32 is Mute off and feedback
/// Digital join 33 is volume up
/// Digital join 34 is volume down
/// </summary>
public uint Codec2Volume { get; set; }
#endregion
public DmpsAudioOutputControllerJoinMap()
{
MasterVolume = 1; // 1-10
SourceVolume = 11; // 11-20
Codec1Volume = 21; // 21-30
Codec2Volume = 31; // 31-40
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart;
MasterVolume = MasterVolume + joinOffset;
SourceVolume = SourceVolume + joinOffset;
Codec1Volume = Codec1Volume + joinOffset;
Codec2Volume = Codec2Volume + joinOffset;
}
}
}

View File

@@ -0,0 +1,127 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class DmpsRoutingControllerJoinMap : JoinMapBase
{
#region Digitals
/// <summary>
/// Range reports video sync feedback for each input
/// </summary>
public uint VideoSyncStatus { get; set; }
/// <summary>
/// Range reports high if corresponding input's endpoint is online
/// </summary>
public uint InputEndpointOnline { get; set; }
/// <summary>
/// Range reports high if corresponding output's endpoint is online
/// </summary>
public uint OutputEndpointOnline { get; set; }
#endregion
#region Analogs
/// <summary>
/// Range sets and reports the current video source for the corresponding output
/// </summary>
public uint OutputVideo { get; set; }
/// <summary>
/// Range sets and reports the current audio source for the corresponding output
/// </summary>
public uint OutputAudio { get; set; }
/// <summary>
/// Range sets and reports the current Usb source for the corresponding output
/// </summary>
//public uint OutputUsb { get; set; }
///// <summary>
///// Range sets and reports the current Usb source for the corresponding input
///// </summary>
//public uint InputUsb { get; set; }
///// <summary>
///// Range sets and reports the current HDCP state for the corresponding input card
///// </summary>
//public uint HdcpSupportState { get; set; }
///// <summary>
///// Range reports the highest supported HDCP state level for the corresponding input card
///// </summary>
//public uint HdcpSupportCapability { get; set; }
#endregion
#region Serials
/// <summary>
/// Range sets and reports the name for the corresponding input card
/// </summary>
public uint InputNames { get; set; }
/// <summary>
/// Range sets and reports the name for the corresponding output card
/// </summary>
public uint OutputNames { get; set; }
/// <summary>
/// Range reports the name of the current video source for the corresponding output card
/// </summary>
public uint OutputCurrentVideoInputNames { get; set; }
/// <summary>
/// Range reports the name of the current audio source for the corresponding output card
/// </summary>
public uint OutputCurrentAudioInputNames { get; set; }
/// <summary>
/// Range reports the current input resolution for each corresponding input card
/// </summary>
public uint InputCurrentResolution { get; set; }
#endregion
public DmpsRoutingControllerJoinMap()
{
//Digital
VideoSyncStatus = 100; //101-299
InputEndpointOnline = 500; //501-699
OutputEndpointOnline = 700; //701-899
//Analog
OutputVideo = 100; //101-299
OutputAudio = 300; //301-499
//OutputUsb = 500; //501-699
//InputUsb = 700; //701-899
VideoSyncStatus = 100; //101-299
//HdcpSupportState = 1000; //1001-1199
//HdcpSupportCapability = 1200; //1201-1399
//Serial
InputNames = 100; //101-299
OutputNames = 300; //301-499
OutputCurrentVideoInputNames = 2000; //2001-2199
OutputCurrentAudioInputNames = 2200; //2201-2399
InputCurrentResolution = 2400; // 2401-2599
InputEndpointOnline = 500; //501-699
OutputEndpointOnline = 700; //701-899
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
OutputVideo = OutputVideo + joinOffset;
OutputAudio = OutputAudio + joinOffset;
//OutputUsb = OutputUsb + joinOffset;
//InputUsb = InputUsb + joinOffset;
VideoSyncStatus = VideoSyncStatus + joinOffset;
InputNames = InputNames + joinOffset;
OutputNames = OutputNames + joinOffset;
OutputCurrentVideoInputNames = OutputCurrentVideoInputNames + joinOffset;
OutputCurrentAudioInputNames = OutputCurrentAudioInputNames + joinOffset;
InputCurrentResolution = InputCurrentResolution + joinOffset;
InputEndpointOnline = InputEndpointOnline + joinOffset;
OutputEndpointOnline = OutputEndpointOnline + joinOffset;
//HdcpSupportState = HdcpSupportState + joinOffset;
//HdcpSupportCapability = HdcpSupportCapability + joinOffset;
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class GenericLightingJoinMap : JoinMapBase
{
public uint IsOnline { get; set; }
public uint SelectScene { get; set; }
public uint LightingSceneOffset { get; set; }
public uint ButtonVisibilityOffset { get; set; }
public uint IntegrationIdSet { get; set; }
public GenericLightingJoinMap()
{
// Digital
IsOnline = 1;
SelectScene = 1;
IntegrationIdSet = 1;
LightingSceneOffset = 10;
ButtonVisibilityOffset = 40;
// Analog
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
IsOnline = IsOnline + joinOffset;
SelectScene = SelectScene + joinOffset;
LightingSceneOffset = LightingSceneOffset + joinOffset;
ButtonVisibilityOffset = ButtonVisibilityOffset + joinOffset;
}
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class GenericRelayControllerJoinMap : JoinMapBase
{
#region Digitals
/// <summary>
/// Sets and reports the state of the relay (High = closed, Low = Open)
/// </summary>
public uint Relay { get; set; }
#endregion
public GenericRelayControllerJoinMap()
{
Relay = 1;
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
Relay = Relay + joinOffset;
}
}
}

View File

@@ -0,0 +1,219 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class GlsOccupancySensorBaseJoinMap : JoinMapBase
{
#region Digitals
/// <summary>
/// High when device is online
/// </summary>
public uint IsOnline { get; set; }
/// <summary>
/// Forces the device to report occupied status
/// </summary>
public uint ForceOccupied { get; set; }
/// <summary>
/// Forces the device to report vacant status
/// </summary>
public uint ForceVacant { get; set; }
/// <summary>
/// Enables raw status reporting
/// </summary>
public uint EnableRawStates { get; set; }
/// <summary>
/// High when raw occupancy is detected
/// </summary>
public uint RawOccupancyFeedback { get; set; }
/// <summary>
/// High when occupancy is detected
/// </summary>
public uint RoomOccupiedFeedback { get; set; }
/// <summary>
/// Hich when occupancy is detected in the grace period
/// </summary>
public uint GraceOccupancyDetectedFeedback { get; set; }
/// <summary>
/// High when vacancy is detected
/// </summary>
public uint RoomVacantFeedback { get; set; }
/// <summary>
/// Enables the LED Flash when set high
/// </summary>
public uint EnableLedFlash { get; set; }
/// <summary>
/// Disables the LED flash when set high
/// </summary>
public uint DisableLedFlash { get; set; }
/// <summary>
/// Enables the Short Timeout
/// </summary>
public uint EnableShortTimeout { get; set; }
/// <summary>
/// Disables the Short Timout
/// </summary>
public uint DisableShortTimeout { get; set; }
/// <summary>
/// Set high to enable one technology to trigger occupancy
/// </summary>
public uint OrWhenVacated { get; set; }
/// <summary>
/// Set high to require both technologies to trigger occupancy
/// </summary>
public uint AndWhenVacated { get; set; }
/// <summary>
/// Enables Ultrasonic Sensor A
/// </summary>
public uint EnableUsA { get; set; }
/// <summary>
/// Disables Ultrasonic Sensor A
/// </summary>
public uint DisableUsA { get; set; }
/// <summary>
/// Enables Ultrasonic Sensor B
/// </summary>
public uint EnableUsB { get; set; }
/// <summary>
/// Disables Ultrasonic Sensor B
/// </summary>
public uint DisableUsB { get; set; }
/// <summary>
/// Enables Pir
/// </summary>
public uint EnablePir { get; set; }
/// <summary>
/// Disables Pir
/// </summary>
public uint DisablePir { get; set; }
public uint IncrementUsInOccupiedState { get; set; }
public uint DecrementUsInOccupiedState { get; set; }
public uint IncrementUsInVacantState { get; set; }
public uint DecrementUsInVacantState { get; set; }
public uint IncrementPirInOccupiedState { get; set; }
public uint DecrementPirInOccupiedState { get; set; }
public uint IncrementPirInVacantState { get; set; }
public uint DecrementPirInVacantState { get; set; }
#endregion
#region Analogs
/// <summary>
/// Sets adn reports the remote timeout value
/// </summary>
public uint Timeout { get; set; }
/// <summary>
/// Reports the local timeout value
/// </summary>
public uint TimeoutLocalFeedback { get; set; }
/// <summary>
/// Sets the minimum internal photo sensor value and reports the current level
/// </summary>
public uint InternalPhotoSensorValue { get; set; }
/// <summary>
/// Sets the minimum external photo sensor value and reports the current level
/// </summary>
public uint ExternalPhotoSensorValue { get; set; }
public uint UsSensitivityInOccupiedState { get; set; }
public uint UsSensitivityInVacantState { get; set; }
public uint PirSensitivityInOccupiedState { get; set; }
public uint PirSensitivityInVacantState { get; set; }
#endregion
public GlsOccupancySensorBaseJoinMap()
{
IsOnline = 1;
ForceOccupied = 2;
ForceVacant = 3;
EnableRawStates = 4;
RoomOccupiedFeedback = 2;
GraceOccupancyDetectedFeedback = 3;
RoomVacantFeedback = 4;
RawOccupancyFeedback = 5;
EnableLedFlash = 11;
DisableLedFlash = 12;
EnableShortTimeout = 13;
DisableShortTimeout = 14;
OrWhenVacated = 15;
AndWhenVacated = 16;
EnableUsA = 17;
DisableUsA = 18;
EnableUsB = 19;
DisableUsB = 20;
EnablePir = 21;
DisablePir = 22;
DisablePir = 23;
IncrementUsInOccupiedState = 24;
DecrementUsInOccupiedState = 25;
IncrementUsInVacantState = 26;
DecrementUsInVacantState = 27;
IncrementPirInOccupiedState = 28;
DecrementPirInOccupiedState = 29;
IncrementPirInVacantState = 30;
DecrementPirInVacantState = 31;
Timeout = 1;
TimeoutLocalFeedback = 2;
InternalPhotoSensorValue = 3;
ExternalPhotoSensorValue = 4;
UsSensitivityInOccupiedState = 5;
UsSensitivityInVacantState = 6;
PirSensitivityInOccupiedState = 7;
PirSensitivityInVacantState = 8;
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
IsOnline = IsOnline + joinOffset;
ForceOccupied = ForceOccupied + joinOffset;
ForceVacant = ForceVacant + joinOffset;
EnableRawStates = EnableRawStates + joinOffset;
RoomOccupiedFeedback = RoomOccupiedFeedback + joinOffset;
GraceOccupancyDetectedFeedback = GraceOccupancyDetectedFeedback + joinOffset;
RoomVacantFeedback = RoomVacantFeedback + joinOffset;
RawOccupancyFeedback = RawOccupancyFeedback + joinOffset;
EnableLedFlash = EnableLedFlash + joinOffset;
DisableLedFlash = DisableLedFlash + joinOffset;
EnableShortTimeout = EnableShortTimeout + joinOffset;
DisableShortTimeout = DisableShortTimeout + joinOffset;
OrWhenVacated = OrWhenVacated + joinOffset;
AndWhenVacated = AndWhenVacated + joinOffset;
EnableUsA = EnableUsA + joinOffset;
DisableUsA = DisableUsA + joinOffset;
EnableUsB = EnableUsB + joinOffset;
DisableUsB = DisableUsB + joinOffset;
EnablePir = EnablePir + joinOffset;
DisablePir = DisablePir + joinOffset;
DisablePir = DisablePir + joinOffset;
IncrementUsInOccupiedState = IncrementUsInOccupiedState + joinOffset;
DecrementUsInOccupiedState = DecrementUsInOccupiedState + joinOffset;
IncrementUsInVacantState = IncrementUsInVacantState + joinOffset;
DecrementUsInVacantState = DecrementUsInVacantState + joinOffset;
IncrementPirInOccupiedState = IncrementPirInOccupiedState + joinOffset;
DecrementPirInOccupiedState = DecrementPirInOccupiedState + joinOffset;
IncrementPirInVacantState = IncrementPirInVacantState + joinOffset;
DecrementPirInVacantState = DecrementPirInVacantState + joinOffset;
Timeout = Timeout + joinOffset;
TimeoutLocalFeedback = TimeoutLocalFeedback + joinOffset;
InternalPhotoSensorValue = InternalPhotoSensorValue + joinOffset;
ExternalPhotoSensorValue = ExternalPhotoSensorValue + joinOffset;
UsSensitivityInOccupiedState = UsSensitivityInOccupiedState + joinOffset;
UsSensitivityInVacantState = UsSensitivityInVacantState + joinOffset;
PirSensitivityInOccupiedState = PirSensitivityInOccupiedState + joinOffset;
PirSensitivityInVacantState = PirSensitivityInVacantState + joinOffset;
}
}
}

View File

@@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class HdMdxxxCEControllerJoinMap : JoinMapBase
{
#region Digitals
/// <summary>
/// High when the pair is online
/// </summary>
public uint IsOnline { get; set; }
/// <summary>
/// High when the remote end device is online
/// </summary>
public uint RemoteEndDetected { get; set; }
/// <summary>
/// Sets Auto Route On and provides feedback
/// </summary>
public uint AutoRouteOn { get; set; }
/// <summary>
/// Sets Auto Route Off and provides feedback
/// </summary>
public uint AutoRouteOff { get; set; }
/// <summary>
/// Sets Priority Routing On and provides feedback
/// </summary>
public uint PriorityRoutingOn { get; set; }
/// <summary>
/// Sets Priority Routing Off and provides feedback
/// </summary>
public uint PriorityRoutingOff { get; set; }
/// <summary>
/// Enables OSD and provides feedback
/// </summary>
public uint InputOnScreenDisplayEnabled { get; set; }
/// <summary>
/// Disables OSD and provides feedback
/// </summary>
public uint InputOnScreenDisplayDisabled { get; set; }
/// <summary>
/// Provides Video Sync Detected feedback for each input
/// </summary>
public uint SyncDetected { get; set; }
#endregion
#region Analogs
/// <summary>
/// Sets the video source for the receiver's HDMI out and provides feedback
/// </summary>
public uint VideoSource { get; set; }
/// <summary>
/// Indicates the number of sources supported by the Tx/Rx pair
/// </summary>
public uint SourceCount { get; set; }
#endregion
#region Serials
/// <summary>
/// Indicates the name of each input port
/// </summary>
public uint SourceNames { get; set; }
#endregion
public HdMdxxxCEControllerJoinMap()
{
//Digital
IsOnline = 1;
RemoteEndDetected = 2;
AutoRouteOn = 3;
AutoRouteOff = 4;
PriorityRoutingOn = 5;
PriorityRoutingOff = 6;
InputOnScreenDisplayEnabled = 7;
InputOnScreenDisplayDisabled = 8;
SyncDetected = 10; // 11-15
//Analog
VideoSource = 1;
SourceCount = 2;
//Serials
SourceNames = 10; // 11-15
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
IsOnline = IsOnline + joinOffset;
RemoteEndDetected = RemoteEndDetected + joinOffset;
AutoRouteOn = AutoRouteOn + joinOffset;
AutoRouteOff = AutoRouteOff + joinOffset;
PriorityRoutingOn = PriorityRoutingOn + joinOffset;
PriorityRoutingOff = PriorityRoutingOff + joinOffset;
InputOnScreenDisplayEnabled = InputOnScreenDisplayEnabled + joinOffset;
InputOnScreenDisplayDisabled = InputOnScreenDisplayDisabled + joinOffset;
SyncDetected = SyncDetected + joinOffset;
VideoSource = VideoSource + joinOffset;
SourceCount = SourceCount + joinOffset;
SourceNames = SourceNames + joinOffset;
}
}
}

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class IBasicCommunicationJoinMap : JoinMapBase
{
#region Digitals
/// <summary>
/// Set High to connect, Low to disconnect
/// </summary>
public uint Connect { get; set; }
/// <summary>
/// Reports Connected State (High = Connected)
/// </summary>
public uint Connected { get; set; }
#endregion
#region Analogs
/// <summary>
/// Reports the connections status value
/// </summary>
public uint Status { get; set; }
#endregion
#region Serials
/// <summary>
/// Data back from port
/// </summary>
public uint TextReceived { get; set; }
/// <summary>
/// Sends data to the port
/// </summary>
public uint SendText { get; set; }
/// <summary>
/// Takes a JSON serialized string that sets a COM port's parameters
/// </summary>
public uint SetPortConfig { get; set; }
#endregion
public IBasicCommunicationJoinMap()
{
TextReceived = 1;
SendText = 1;
SetPortConfig = 2;
Connect = 1;
Connected = 1;
Status = 1;
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
TextReceived = TextReceived + joinOffset;
SendText = SendText + joinOffset;
SetPortConfig = SetPortConfig + joinOffset;
Connect = Connect + joinOffset;
Connected = Connected + joinOffset;
Status = Status + joinOffset;
}
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class IDigitalInputJoinMap : JoinMapBase
{
#region Digitals
/// <summary>
/// Reports the state of the digital input
/// </summary>
public uint InputState { get; set; }
#endregion
public IDigitalInputJoinMap()
{
InputState = 1;
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
InputState = InputState + joinOffset;
}
}
}

View File

@@ -0,0 +1,136 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
public class SystemMonitorJoinMap : JoinMapBase
{
/// <summary>
/// Offset to indicate where the range of iterated program joins will start
/// </summary>
public uint ProgramStartJoin { get; set; }
/// <summary>
/// Offset between each program join set
/// </summary>
public uint ProgramOffsetJoin { get; set; }
#region Digitals
/// <summary>
/// Range Sets and reports whether the corresponding program slot is started
/// </summary>
public uint ProgramStart { get; set; }
/// <summary>
/// Range Sets and reports whether the corresponding program slot is stopped
/// </summary>
public uint ProgramStop { get; set; }
/// <summary>
/// Range Sets and reports whether the corresponding program is registered
/// </summary>
public uint ProgramRegister { get; set; }
/// <summary>
/// Range Sets and reports whether the corresponding program is unregistered
/// </summary>
public uint ProgramUnregister { get; set; }
#endregion
#region Analogs
/// <summary>
/// Sets and reports the time zone
/// </summary>
public uint TimeZone { get; set; }
#endregion
#region Serials
/// <summary>
/// Reports the time zone name
/// </summary>
public uint TimeZoneName { get; set; }
/// <summary>
/// Reports the IO Controller Version
/// </summary>
public uint IOControllerVersion { get; set; }
/// <summary>
/// Reports the SNMP App Version
/// </summary>
public uint SnmpAppVersion { get; set; }
/// <summary>
/// Reports the BACnet App Version
/// </summary>
public uint BACnetAppVersion { get; set; }
/// <summary>
/// Reports the firmware version
/// </summary>
public uint ControllerVersion { get; set; }
/// <summary>
/// Reports the name of the corresponding program
/// </summary>
public uint ProgramName { get; set; }
/// <summary>
/// Reports the compile time of the corresponding program
/// </summary>
public uint ProgramCompiledTime { get; set; }
/// <summary>
/// Reports the Crestron Database version of the corresponding program
/// </summary>
public uint ProgramCrestronDatabaseVersion { get; set; }
/// <summary>
/// Reports the Environment Version of the corresponding program
/// </summary>
public uint ProgramEnvironmentVersion { get; set; }
/// <summary>
/// Serialized JSON output that aggregates the program info of the corresponding program
/// </summary>
public uint AggregatedProgramInfo { get; set; }
#endregion
public SystemMonitorJoinMap()
{
TimeZone = 1;
TimeZoneName = 1;
IOControllerVersion = 2;
SnmpAppVersion = 3;
BACnetAppVersion = 4;
ControllerVersion = 5;
ProgramStartJoin = 10;
ProgramOffsetJoin = 5;
// Offset in groups of 5 joins
ProgramStart = 1;
ProgramStop = 2;
ProgramRegister = 3;
ProgramUnregister = 4;
ProgramName = 1;
ProgramCompiledTime = 2;
ProgramCrestronDatabaseVersion = 3;
ProgramEnvironmentVersion = 4;
AggregatedProgramInfo = 5;
}
public override void OffsetJoinNumbers(uint joinStart)
{
var joinOffset = joinStart - 1;
TimeZone = TimeZone + joinOffset;
TimeZoneName = TimeZoneName + joinOffset;
IOControllerVersion = IOControllerVersion + joinOffset;
SnmpAppVersion = SnmpAppVersion + joinOffset;
BACnetAppVersion = BACnetAppVersion + joinOffset;
ControllerVersion = ControllerVersion + joinOffset;
// Sets the initial join value where the iterated program joins will begin
ProgramStartJoin = ProgramStartJoin + joinOffset;
}
}
}

View File

@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.Diagnostics;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Monitoring;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Bridges
{
public static class SystemMonitorBridge
{
public static void LinkToApi(this SystemMonitorController systemMonitorController, BasicTriList trilist, uint joinStart, string joinMapKey)
{
SystemMonitorJoinMap joinMap = new SystemMonitorJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
if(!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<SystemMonitorJoinMap>(joinMapSerialized);
joinMap.OffsetJoinNumbers(joinStart);
Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(2, systemMonitorController, "Linking API starting at join: {0}", joinStart);
systemMonitorController.TimeZoneFeedback.LinkInputSig(trilist.UShortInput[joinMap.TimeZone]);
//trilist.SetUShortSigAction(joinMap.TimeZone, new Action<ushort>(u => systemMonitorController.SetTimeZone(u)));
systemMonitorController.TimeZoneTextFeedback.LinkInputSig(trilist.StringInput[joinMap.TimeZoneName]);
systemMonitorController.IOControllerVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.IOControllerVersion]);
systemMonitorController.SnmpVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.SnmpAppVersion]);
systemMonitorController.BACnetAppVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.BACnetAppVersion]);
systemMonitorController.ControllerVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.ControllerVersion]);
// iterate the program status feedback collection and map all the joins
var programSlotJoinStart = joinMap.ProgramStartJoin;
foreach (var p in systemMonitorController.ProgramStatusFeedbackCollection)
{
var programNumber = p.Value.Program.Number;
trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramStart, new Action<bool>
(b => SystemMonitor.ProgramCollection[programNumber].OperatingState = eProgramOperatingState.Start));
p.Value.ProgramStartedFeedback.LinkInputSig(trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramStart]);
trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramStop, new Action<bool>
(b => SystemMonitor.ProgramCollection[programNumber].OperatingState = eProgramOperatingState.Stop));
p.Value.ProgramStoppedFeedback.LinkInputSig(trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramStop]);
trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramRegister, new Action<bool>
(b => SystemMonitor.ProgramCollection[programNumber].RegistrationState = eProgramRegistrationState.Register));
p.Value.ProgramRegisteredFeedback.LinkInputSig(trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramRegister]);
trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramUnregister, new Action<bool>
(b => SystemMonitor.ProgramCollection[programNumber].RegistrationState = eProgramRegistrationState.Unregister));
p.Value.ProgramUnregisteredFeedback.LinkInputSig(trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramUnregister]);
programSlotJoinStart = programSlotJoinStart + joinMap.ProgramOffsetJoin;
}
}
}
}

View File

@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials
{
//public class TPConfig : DeviceConfig
//{
// new public TPConfigProperties Properties { get; set; }
//}
//public class TPConfigProperties
//{
// /*
// "properties": {
// "ipId": "aa",
// "defaultSystemKey": "system1",
// "sgdPath": "\\NVRAM\\Program1\\Sgds\\PepperDash Essentials TSW1050_v0.9.sgd",
// "usesSplashPage": true,
// "showDate": true,
// "showTime": false
// }
// */
// public uint IpId { get; set; }
// public string deafultSystemKey { get; set; }
// public string SgdPath { get; set; }
// public bool UsesSplashPage { get; set; }
// public bool ShowDate { get; set; }
// public bool ShowTime { get; set; }
//}
///// <summary>
///// The gist of this converter: The comspec JSON comes in with normal values that need to be converted
///// into enum names. This converter takes the value and applies the appropriate enum's name prefix to the value
///// and then returns the enum value using Enum.Parse
///// </summary>
//public class TPPropertiesConverter : JsonConverter
//{
// public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
// {
// return JObject.Load(reader);
// }
// /// <summary>
// /// This will be hit with every value in the ComPortConfig class. We only need to
// /// do custom conversion on the comspec items.
// /// </summary>
// public override bool CanConvert(Type objectType)
// {
// return true;
// }
// public override bool CanRead { get { return true; } }
// public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
// {
// throw new NotImplementedException();
// }
//}
}

View File

@@ -0,0 +1,82 @@
using System.Linq;
using Newtonsoft.Json;
using PepperDash.Essentials.Core;
using PepperDash.Core;
namespace PepperDash.Essentials
{
public class ConfigTieLine
{
[JsonProperty(Required=Required.Always)]
public string SourceDeviceKey { get; set; }
[JsonProperty(Required = Required.Always)]
public string SourcePortKey { get; set; }
[JsonProperty(Required = Required.Always)]
public string DestinationDeviceKey { get; set; }
[JsonProperty(Required = Required.Always)]
public string DestinationPortKey { get; set; }
public override string ToString()
{
return string.Format("Tie line: [{0}]{1} --> [{2}]{3}", SourceDeviceKey, SourcePortKey, DestinationDeviceKey, DestinationPortKey);
}
/// <summary>
/// Returns a tie line if one can be constructed between the two devices and ports
/// </summary>
/// <returns>TieLine or null if devices or ports don't exist</returns>
public TieLine GetTieLine()
{
var sourceDevice = (IRoutingOutputs)DeviceManager.GetDeviceForKey(SourceDeviceKey);
var destinationDevice = (IRoutingInputs)DeviceManager.GetDeviceForKey(DestinationDeviceKey);
if (sourceDevice == null)
{
Debug.Console(0, " Cannot create TieLine. Source device '{0}' not found or does not have outputs",
SourceDeviceKey);
return null;
}
else if (destinationDevice == null)
{
Debug.Console(0, " Cannot create TieLine. Destination device '{0}' not found or does not have inputs",
DestinationDeviceKey);
return null;
}
else
{
// Get the ports by key name from the lists
RoutingOutputPort sourcePort = sourceDevice.OutputPorts.FirstOrDefault(
p => p.Key.Equals(SourcePortKey, System.StringComparison.OrdinalIgnoreCase));
//RoutingOutputPort sourcePort = null;
//sourceDevice.OutputPorts.TryGetValue(SourcePortKey, out sourcePort);
if (sourcePort == null)
{
Debug.Console(0, " Cannot create TieLine {0}-->{1}. Source device does not have output port '{2}'",
sourceDevice.Key, destinationDevice.Key, SourcePortKey);
return null;
}
RoutingInputPort destinationPort = destinationDevice.InputPorts.FirstOrDefault(
p => p.Key.Equals(DestinationPortKey, System.StringComparison.OrdinalIgnoreCase));
//RoutingInputPort destinationPort = null;
//destinationDevice.InputPorts.TryGetValue(DestinationPortKey, out destinationPort);
if (destinationPort == null)
{
Debug.Console(0, " Cannot create TieLine {0}-->{1}. Destination device does not have input port '{2}'",
sourceDevice.Key, destinationDevice.Key, DestinationPortKey);
return null;
}
var tl = new TieLine(sourcePort, destinationPort);
Debug.Console(1, " Created {0}", this);
return tl;
}
}
}
}

View File

@@ -0,0 +1,287 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.CrestronThread;
using Crestron.SimplSharpPro.Diagnostics;
using Crestron.SimplSharpPro.EthernetCommunication;
using Crestron.SimplSharpPro.UI;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices;
//using PepperDash.Essentials.Core.Devices.Dm;
//using PepperDash.Essentials.Fusion;
using PepperDash.Core;
namespace PepperDash.Essentials
{
public static class Configuration
{
public static string LastPath { get; private set; }
public static CrestronControlSystem ControlSystem { get; private set; }
public static void Initialize(CrestronControlSystem cs)
{
CrestronConsole.AddNewConsoleCommand(ReloadFromConsole, "configreload", "Reloads configuration file",
ConsoleAccessLevelEnum.AccessOperator);
ControlSystem = cs;
}
public static bool ReadConfiguration(string filePath)
{
try
{
// Read file
if (File.Exists(filePath))
{
LastPath = filePath;
string json = File.ReadToEnd(filePath, System.Text.Encoding.ASCII);
JObject jo = JObject.Parse(json);
var info = JsonConvert.DeserializeObject<ConfigInfo>(jo["info"].ToString());
Debug.Console(0, "\r[Config] file read:");
Debug.Console(0, " File: {0}", filePath);
Debug.Console(0, " Name: {0}", info.Name);
Debug.Console(0, " Type: {0}", info.SystemTemplateType);
Debug.Console(0, " Date: {0}", info.EditDate);
Debug.Console(0, " ConfigVersion: {0}", info.Version);
Debug.Console(0, " EditedBy: {0}", info.EditedBy);
Debug.Console(0, " Comment: {0}\r", info.Comment);
// Get the main config object
var jConfig = jo["configuration"];
// Devices
var jDevices = (JArray)jConfig["devices"];
CreateDevices(jDevices);
// TieLines
var jRouting = jConfig["routing"];
CreateRouting(jRouting);
/// Parse the available source list(s)
var jSourceLists = (JArray)jConfig["sourceLists"];
var jSourceListJson = jSourceLists.ToString();
List<ConfigSourceList> sourceLists = JsonConvert.DeserializeObject<List<ConfigSourceList>>(jSourceListJson);
// System
var jSystems = (JArray)jConfig["systems"];
CreateSystems(jSystems, sourceLists);
// Activate everything
DeviceManager.ActivateAll();
}
else
{
Debug.Console(0, "[Config] file not found '{0}'", filePath);
return false;
}
}
catch (Exception e)
{
Debug.Console(0, "Configuration read error: \r {0}", e);
return false;
}
return true;
}
static void CreateDevices(JArray jDevices)
{
//Debug.Console(0, " Creating {0} devices", jDevices.Count);
//for (int i = 0; i < jDevices.Count; i++)
//{
// var jDev = jDevices[i];
// //var devConfig = JsonConvert.DeserializeObject<DeviceConfig>(jDev.ToString());
// //Debug.Console(0, "++++++++++++{0}", devConfig);
// var group = jDev["group"].Value<string>();
// Debug.Console(0, " [{0}], creating {1}:{2}", jDev["key"].Value<string>(),
// group, jDev["type"].Value<string>());
// Device dev = null;
// if (group.Equals("Display", StringComparison.OrdinalIgnoreCase))
// dev = DisplayFactory.CreateDisplay(jDev);
// else if (group.Equals("DeviceMonitor", StringComparison.OrdinalIgnoreCase))
// dev = DeviceManagerFactory.Create(jDev);
// //else if (group.Equals("Pc", StringComparison.OrdinalIgnoreCase))
// // dev = PcFactory.Create(jDev);
// //else if (group.Equals("SetTopBox", StringComparison.OrdinalIgnoreCase))
// // dev = SetTopBoxFactory.Create(jDev);
// //else if (group.Equals("DiscPlayer", StringComparison.OrdinalIgnoreCase))
// // dev = DiscPlayerFactory.Create(jDev);
// //else if (group.Equals("Touchpanel", StringComparison.OrdinalIgnoreCase))
// // dev = TouchpanelFactory.Create(jDev);
// else if (group.Equals("dmEndpoint", StringComparison.OrdinalIgnoreCase)) // Add Transmitter and Receiver
// dev = DmFactory.Create(jDev);
// else if (group.Equals("dmChassic", StringComparison.OrdinalIgnoreCase))
// dev = DmFactory.CreateChassis(jDev);
// else if (group.Equals("processor", StringComparison.OrdinalIgnoreCase))
// continue; // ignore it. Has no value right now.
// //else if (group.Equals("remote", StringComparison.OrdinalIgnoreCase))
// // dev = RemoteFactory.Create(jDev);
// else
// {
// Debug.Console(0, " ERROR: Device [{0}] has unknown Group '{1}'. Skipping",
// jDev["key"].Value<string>(), group);
// continue;
// }
// if (dev != null)
// DeviceManager.AddDevice(dev);
// else
// Debug.Console(0, " ERROR: failed to create device {0}",
// jDev["key"].Value<string>());
//}
}
static void CreateSystems(JArray jSystems, List<ConfigSourceList> sourceLists)
{
// // assuming one system
// var jSystem = jSystems[0];
// var name = jSystem.Value<string>("name");
// var key = FactoryHelper.KeyOrConvertName(jSystem.Value<string>("key"), name);
// if (jSystem.Value<string>("type").Equals("EssentialsHuddleSpace", StringComparison.OrdinalIgnoreCase))
// {
// var sys = new HuddleSpaceRoom(key, name);
// var props = jSystem["properties"];
// var displayKey = props["displayKey"].Value<string>();
// if (displayKey != null)
// sys.DefaultDisplay = (DisplayBase)DeviceManager.GetDeviceForKey(displayKey);
// // Add sources from passed in config list
// var myList = sourceLists.FirstOrDefault(
// l => l.Key.Equals(props.Value<string>("sourceListKey"), StringComparison.OrdinalIgnoreCase));
// if (myList != null)
// AddSourcesToSystem(sys, myList);
// DeviceManager.AddDevice(sys);
// //spin up a fusion thing too
//#warning add this fusion connector back in later
// //DeviceManager.AddDevice(new EssentialsHuddleSpaceFusionSystemController(sys, 0xf1));
//}
}
//static void AddSourcesToSystem(Room system, ConfigSourceList configList)
//{
//foreach (var configItem in configList.PresentationSources)
//{
// var src = (IPresentationSource)DeviceManager.GetDeviceForKey(configItem.SourceKey);
// if (src != null)
// system.Sources.Add(configItem.Number, src);
// else
// Debug.Console(0, system, "cannot find source '{0}' from list {1}",
// configItem.SourceKey, configList.Name);
//}
//}
/// <summary>
/// Links up routing, creates tie lines
/// </summary>
/// <param name="jRouting">The "Routing" JArray from configuration</param>
static void CreateRouting(JToken jRouting)
{
var jsonTieLines = jRouting["tieLines"].ToString();
var tieLineConfigs = JsonConvert.DeserializeObject<List<ConfigTieLine>>(jsonTieLines);
foreach (var c in tieLineConfigs)
{
var tl = c.GetTieLine();
if (tl != null)
TieLineCollection.Default.Add(tl);
}
}
/// <summary>
/// Returns the IIROutputPorts device (control system, etc) that contains a given IR port
/// </summary>
/// <param name="propsToken"></param>
static IROutputPort GetIrPort(JToken propsToken)
{
var portDevName = propsToken.Value<string>("IrPortDevice");
var portNum = propsToken.Value<uint>("IrPortNumber");
if (portDevName.Equals("controlSystem", StringComparison.OrdinalIgnoreCase))
{
IIROutputPorts irDev = ControlSystem;
if (portNum <= irDev.NumberOfIROutputPorts)
return ControlSystem.IROutputPorts[portNum];
else
Debug.Console(0, "[Config] ERROR: IR Port {0} out of range. Range 0-{1} on {2}", portNum,
ControlSystem.IROutputPorts.Count, irDev.ToString());
}
return null;
}
static void HandleUnknownType(JToken devToken, string type)
{
Debug.Console(0, "[Config] ERROR: Type '{0}' not found in group '{1}'", type,
devToken.Value<string>("Group"));
}
static void HandleDeviceCreationError(JToken devToken, Exception e)
{
Debug.Console(0, "[Config] ERROR creating device [{0}]: \r{1}",
devToken["Key"].Value<string>(), e);
}
/// <summary>
/// Console helper to reload
/// </summary>
static void ReloadFromConsole(string s)
{
// Gotta tear down everything first!
if (!string.IsNullOrEmpty(LastPath))
{
ReadConfiguration(LastPath);
}
}
}
public class ConfigSourceList
{
[JsonProperty(Required = Required.Always)]
public string Key { get; set; }
[JsonProperty(Required = Required.Always)]
public string Name { get; set; }
[JsonProperty(Required = Required.Always)]
public List<ConfigSourceItem> PresentationSources { get; set; }
}
public class ConfigSourceItem
{
[JsonProperty(Required = Required.Always)]
public uint Number { get; set; }
[JsonProperty(Required = Required.Always)]
public string SourceKey { get; set; }
public string AlternateName { get; set; }
}
public class ConfigInfo
{
public string SystemTemplateType { get; set; }
public string ProcessorType { get; set; }
public string Name { get; set; }
public uint ProgramSlotNumber { get; set; }
public string Version { get; set; }
public string EditedBy { get; set; }
public string EditDate { get; set; }
public string Comment { get; set; }
}
}

View File

@@ -0,0 +1,20 @@
using Newtonsoft.Json;
namespace PepperDash.Essentials
{
public class SourceListConfigProperties
{
[JsonProperty(Required= Required.Always)]
public uint Number { get; set; }
[JsonProperty(Required= Required.Always)]
public string SourceKey { get; set; }
public string AltName { get; set; }
public string AltIcon { get; set; }
public SourceListConfigProperties()
{
AltName = "";
AltIcon = "";
}
}
}

View File

@@ -0,0 +1,54 @@
//using System;
//using Crestron.SimplSharpPro;
//using Newtonsoft.Json;
//using Newtonsoft.Json.Linq;
//using PepperDash.Essentials.Core;
//using PepperDash.Essentials.Devices;
//using PepperDash.Core;
//namespace PepperDash.Essentials
//{
// public class CommFactory
// {
// public static IBasicCommunication CreateCommForDevice(JToken devToken)
// {
// var devKey = devToken.Value<string>("key");
// IBasicCommunication comm = null;
// try
// {
// var control = devToken["properties"]["control"];
// var commMethod = control["method"].Value<string>();
// if (commMethod == "com")
// {
// var comConfig = JsonConvert.DeserializeObject<ComPortConfig>(
// control["comParams"].ToString(),
// new JsonSerializerSettings
// {
// // Needs ObjectCreationHandling to make the ComSpec struct populate
// ObjectCreationHandling = ObjectCreationHandling.Replace,
// Converters = new JsonConverter[] { new ComSpecJsonConverter() }
// });
// comm = new ComPortController(devKey + "-com", comConfig.GetComPort(), comConfig.ComSpec);
// }
// else if (commMethod == "tcpIp")
// {
// var tcpConfig = JsonConvert.DeserializeObject<TcpIpConfig>(control["tcpParams"].ToString());
// comm = new GenericTcpIpClient(devKey + "-tcp", tcpConfig.Address, tcpConfig.Port, tcpConfig.BufferSize);
// }
// }
// catch (Exception e)
// {
// Debug.Console(0, "Cannot create communication from JSON:\r{0}\r\rException:\r{1}", devToken.ToString(), e);
// }
// // put it in the device manager if it's the right flavor
// var comDev = comm as Device;
// if (comDev != null)
// DeviceManager.AddDevice(comDev);
// return comm;
// }
// }
//}

View File

@@ -0,0 +1,38 @@
//using System;
//using Crestron.SimplSharpPro;
//using Newtonsoft.Json.Linq;
//using PepperDash.Essentials.Core;
//using PepperDash.Essentials.Core.Devices;
//using PepperDash.Core;
//namespace PepperDash.Essentials
//{
// public class DeviceManagerFactory
// {
// public static Device Create(JToken devToken)
// {
// Device dev = null;
// try
// {
// var devType = devToken.Value<string>("type");
// var devKey = devToken.Value<string>("key");
// var devName = devToken.Value<string>("name");
// if (devType.Equals("DeviceMonitor", StringComparison.OrdinalIgnoreCase))
// {
// var comm = CommFactory.CreateCommForDevice(devToken);
// if (comm == null) return null;
// dev = new GenericCommunicationMonitoredDevice(devKey, devName, comm, devToken["properties"]["pollString"].Value<string>());
// }
// else
// FactoryHelper.HandleUnknownType(devToken, devType);
// }
// catch (Exception e)
// {
// FactoryHelper.HandleDeviceCreationError(devToken, e);
// }
// return dev;
// }
// }
//}

View File

@@ -0,0 +1,122 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using Crestron.SimplSharp;
//using Newtonsoft.Json;
//using Newtonsoft.Json.Linq;
//using PepperDash.Essentials.Core;
//using PepperDash.Essentials.Devices;
//using PepperDash.Essentials.Displays;
//using PepperDash.Core;
//namespace PepperDash.Essentials
//{
// public class DisplayFactory
// {
// public static DisplayBase CreateDisplay(JToken devToken)
// {
// DisplayBase dev = null;
// try
// {
// var devType = devToken.Value<string>("type");
// var devKey = devToken.Value<string>("key");
// var devName = devToken.Value<string>("name");
// var properties = devToken["properties"];
// if (devType.Equals("MockDisplay", StringComparison.OrdinalIgnoreCase))
// dev = new MockDisplay(devKey, devName);
// else if (devType.Equals("NecMPSX", StringComparison.OrdinalIgnoreCase))
// {
// var comm = CommFactory.CreateCommForDevice(devToken);
// if (comm == null) return null;
// dev = new NecPSXMDisplayCom(devKey, devName, comm);
// //var commMethod = properties["control"]["method"].Value<string>();
// //// Helper-ize this?
// //if(commMethod == "com")
// //{
// // // Move some of this up above???
// // var comConfig = JsonConvert.DeserializeObject<ComPortConfig>(
// // properties["control"]["comParams"].ToString(),
// // new JsonSerializerSettings {
// // // Needs ObjectCreationHandling to make the ComSpec struct populate
// // ObjectCreationHandling = ObjectCreationHandling.Replace,
// // Converters = new JsonConverter[] { new ComSpecJsonConverter() }
// // });
// // dev = new NecPSXMDisplayCom(devKey, devName, comConfig.GetComPort(), comConfig.ComSpec);
// //}
// //else if (commMethod == "tcpIp")
// //{
// // var spec = properties["control"]["tcpSpec"];
// // var host = spec["address"].Value<string>();
// // var port = spec["port"].Value<int>();
// // dev = new NecPSXMDisplayCom(devKey, devName, host, port);
// //}
// }
// else if (devType.Equals("NecNpPa550", StringComparison.OrdinalIgnoreCase))
// {
// var proj = new NecPaSeriesProjector(devKey, devName);
// var comm = CreateCommunicationFromPropertiesToken(
// devKey + "-comm", properties, 3000);
// proj.CommunicationMethod = comm;
// dev = proj;
// }
// else
// FactoryHelper.HandleUnknownType(devToken, devType);
// }
// catch (Exception e)
// {
// FactoryHelper.HandleDeviceCreationError(devToken, e);
// }
// return dev;
// }
// public static IBasicCommunication CreateCommunicationFromPropertiesToken(
// string commKey, JToken properties, int bufferSize)
// {
// Debug.Console(2, "Building port from: {0}", properties.ToString());
// var tcpToken = properties["TcpIp"];
// if (tcpToken != null)
// {
// // Convert the Tcp property
// var spec = JsonConvert.DeserializeObject<TcpIpConfig>(tcpToken.ToString());
// var tcp = new GenericTcpIpClient(commKey, spec.Address, spec.Port, bufferSize);
// DeviceManager.AddDevice(tcp);
// return tcp;
// }
// var com = properties["Com"];
// if (com != null)
// {
// // Make the interim config object
// var comConfig = JsonConvert.DeserializeObject<ComPortConfig>(com.ToString(),
// new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace });
// // Get the IComPorts hardware device from the Device or Control System
// var comDev = comConfig.GetIComPortsDeviceFromManagedDevice();
// if (comDev != null)
// {
// var controller = new ComPortController(commKey, comDev.ComPorts[comConfig.ComPortNumber], comConfig.ComSpec);
// DeviceManager.AddDevice(controller);
// return controller;
// }
// }
// Debug.Console(0, "No Tcp or Com port information for port {0}", commKey);
// return null;
// }
// }
//}

Some files were not shown because too many files have changed in this diff Show More