Compare commits

..

110 Commits

Author SHA1 Message Date
Andrew Welker
222c2f6fe2 chore: more miscellaneous cleanup 2025-03-25 22:52:32 -05:00
Andrew Welker
19d0bc73c8 fix: remove LightingBase from core 2025-03-25 22:50:31 -05:00
Andrew Welker
277771d154 chore: miscellaeneous cleanup 2025-03-25 22:46:41 -05:00
Andrew Welker
789111cb9a style: run code cleanup & apply VS suggestions 2025-03-25 22:14:15 -05:00
Andrew Welker
4d98191fa7 chore: remove obsolete log methods 2025-03-25 21:55:37 -05:00
Andrew Welker
f6f731b470 chore: remove 4SERIES compiler directive 2025-03-25 10:21:17 -05:00
Andrew Welker
8316ee22b6 build(force-patch): change names of MC packages
In order to prevent eventual version collision and confusion, and to
allow for deprecation of existing packages, the names of the MC packages
are now reflective of the fact that they are no longer
pluginsbuild(force-patch): change names of MC packages

In order to prevent eventual version collision and confusion, and to
allow for deprecation of existing packages, the names of the MC packages
are now reflective of the fact that they are no longer plugins.
2025-03-25 00:20:56 -05:00
Andrew Welker
aebc694da7 build(force-patch): use version in directory.build.props 2025-03-25 00:16:23 -05:00
Andrew Welker
fe2cd573e5 feat: remove DisplayBase from Core 2025-03-25 00:10:22 -05:00
Andrew Welker
af0855cea3 build(force-patch): publish mc messenger package 2025-03-24 23:36:17 -05:00
Andrew Welker
5ac9efb1fb Merge branch 'development' into feature/move-mc 2025-03-24 22:43:59 -05:00
Andrew Welker
7318dbb04e ci(force-patch): add skip package check prop 2025-03-24 22:39:52 -05:00
Andrew Welker
f6fdc14059 feat: move MC into Essentials
In order to solve some dependency issues that keep cropping up, MC
should be moved back into the Essentials repo and loaded automatically
on startup. This will allow for all plugins that use the MC Messengers
library to use the same version without fear of overwriting a dll due to
loading of plugin libraries.
2025-03-24 22:28:27 -05:00
Andrew Welker
7046205e57 Merge pull request #1224 from PepperDash/feature/inclusive-poll 2025-03-24 14:50:26 -05:00
Jonathan Arndt
d7499662de fix: revise 4-series-caller.yml to include bypassPackageCheck bool. 2025-03-24 11:01:12 -07:00
Jonathan Arndt
fdb04286d6 fix: correct event subscription logic in GenericCommunicationMonitor and poll inclusively. 2025-03-23 16:36:41 -07:00
Neil Dorin
3d91723ab0 Merge pull request #1221 from PepperDash/test-ci
Cleanup leftover files
2025-03-12 12:55:42 -06:00
Andrew Welker
4dcb3946c5 chore: remove unnecessary files 2025-03-12 13:54:13 -05:00
Andrew Welker
a288fc5890 fix: increment minor version 2025-03-12 13:41:21 -05:00
Andrew Welker
9ef8698387 feat: increment minor version 2025-03-12 13:38:52 -05:00
Andrew Welker
daccf9eb77 chore(force-patch): increment patch version 2025-03-12 13:37:13 -05:00
Neil Dorin
6333443ecb Merge pull request #1220 from PepperDash/get-beta-build 2025-03-12 12:27:31 -06:00
Andrew Welker
51414e7d26 chore(force-patch): increment patch version 2025-03-12 13:23:40 -05:00
Andrew Welker
3222c73282 Merge pull request #1218 from PepperDash/update-dev
Update dev
2025-03-07 11:43:16 -06:00
Andrew Welker
5df7b57c43 Merge pull request #1217 from PepperDash/release
Essentials 2.0.0
2025-03-07 11:25:39 -06:00
Andrew Welker
7631c7a8a1 build(force-patch): update PD Core to 2.0.1 2025-03-06 13:53:41 -06:00
Andrew Welker
16e2529378 feat: update to PD Core 2.0.0 2025-03-06 10:04:19 -06:00
Andrew Welker
8f485071c6 chore(force-patch): increment patch version 2025-03-05 18:51:59 -06:00
Andrew Welker
4eabd82878 build(force-update): fix build targets to handle files correctly 2025-03-05 18:50:40 -06:00
Andrew Welker
edfe77cd02 build(force-patch): update PD Core & Crestron libraries 2025-03-05 17:37:48 -06:00
Andrew Welker
fd593d7117 Merge pull request #1216 from PepperDash/release-2.0.0
Merge 2.0.0 stuff into development
2025-03-05 13:51:28 -06:00
Andrew Welker
a141b365ab fix: add missing using for System.Text 2025-03-05 13:40:38 -06:00
Andrew Welker
68ddd76ba5 chore!: update version to 2.0.0
BREAKING CHANGE: remove support for .NET 6 for Essentials 2.0.0
2025-03-05 13:33:49 -06:00
Andrew Welker
9330ebeae2 chore: remove references to Essentials Template UI 2025-03-05 13:32:21 -06:00
Andrew Welker
b398e73024 chore!: remove .NET 6 support for v2.0.0
BREAKING_CHANGE: remove .NET 6 support for v2.0.0
2025-03-05 13:26:50 -06:00
Andrew Welker
7a2b2eece6 ci(force-patch): use same workflow as PD Core for building 2025-03-05 13:24:28 -06:00
Andrew Welker
543176bb08 Merge branch 'development' into release-2.0.0 2025-03-05 13:07:51 -06:00
Jason T Alborough
237fff5398 Merge pull request #1214 from PepperDash/feature-2.0.0/concurrent-routing-issues
Fix issues with concurrent routing actions
2025-02-20 13:19:56 -05:00
Andrew Welker
b2eab21fbd Merge pull request #1211 from PepperDash/hotfix-2.0.0/room-combiner-syncronous-events
fix: improve error handling and await device actions in RoomCombinati…
2025-02-19 17:20:59 -06:00
Andrew Welker
f2545fb1cf Merge pull request #1212 from PepperDash/feature-2.0.0/versiport-room-combiner
Enable using Versiports with Room Combiner
2025-02-19 17:20:40 -06:00
Andrew Welker
27072e3475 fix: #1213 remove key from GenericSoftCodec routing port keys 2025-02-19 17:10:18 -06:00
Andrew Welker
e4755ed9df Merge branch 'feature-2.0.0/concurrent-routing-issues' of https://github.com/PepperDash/Essentials into feature-2.0.0/concurrent-routing-issues 2025-02-19 17:00:45 -06:00
Andrew Welker
316867caf8 chore: update to PD Core 2.0.0-alpha-451
Catch the `SshOperationTimeoutException` and handle it differently.
2025-02-19 16:49:22 -06:00
jtalborough
d8fd774324 Merge branch 'hotfix-2.0.0/room-combiner-syncronous-events' into feature-2.0.0/concurrent-routing-issues 2025-02-19 15:11:46 -05:00
Andrew Welker
e0058d8cfe chore: update PD Core to 2.0.0-alpha-450
Updated to Renci for SSH
2025-02-19 13:24:52 -06:00
Andrew Welker
a055d06bc6 chore: add some logging for route queue processing 2025-02-19 11:18:00 -06:00
Andrew Welker
66cb592c70 chore: add missing curly brace 2025-02-19 11:10:35 -06:00
Andrew Welker
d53a5607e2 chore: reorg methos in routing Extensions class 2025-02-19 11:07:41 -06:00
Andrew Welker
34f59f1410 fix: move ReleaseRoute & RunRouteRequests to use a queue 2025-02-19 11:06:56 -06:00
Andrew Welker
261779d4c4 fix: actually log exception correctly 2025-02-18 14:04:30 -06:00
Andrew Welker
30d5e2b081 fix: add more exception handling
Also add null check for `AddRouteDescriptor` method
2025-02-18 14:00:53 -06:00
Andrew Welker
5516ed16c3 fix: use null instead of empty string to make it clearer what's happening 2025-02-18 12:02:52 -06:00
Andrew Welker
8108b9dfdb fix: attempt to get better logging for exception
Fixed some issues with log messages that were not formatted correctly for Serilog.
2025-02-18 11:59:26 -06:00
Nick Genovese
fb4f1482c7 fix: small null check in the release and make route method 2025-01-31 19:33:31 -05:00
Nick Genovese
54dcb5de08 feat: implement IPartitionStateProvider to Generic VersaPortInput 2025-01-30 15:21:12 -05:00
jtalborough
4ef481375c fix: improve error handling and await device actions in RoomCombinationScenario 2025-01-28 09:00:21 -05:00
Nick Genovese
d8a88b2a07 Merge branch 'development-2.0.0' into feature-2.0.0/emergencyOSD 2025-01-10 07:31:35 -05:00
Andrew Welker
cc724ddf19 Merge pull request #1210 from PepperDash/hotfix-2.0.0/release-routes-clears-the-routes
Hotfix 2.0.0/release routes clears the routes
2024-12-30 13:33:54 -06:00
Nick Genovese
e29e800d9d fix: now pushes the tag whenever not rc 2024-12-10 07:52:43 -05:00
Nick Genovese
134e8ba02e fix: remove null route when releasing route 2024-12-10 07:44:10 -05:00
Andrew Knous
f68b1e9e49 feat: cleans up code, adds versiport comment, changes ShowEmergencyMessage arg name to "url" 2024-11-19 09:19:48 -08:00
Andrew Knous
cd81b8af73 feat: adds roomKey to ShowEmergencyMessage 2024-11-14 17:00:21 -05:00
Andrew Knous
cd52c245a6 feat: adds emergency OSD support 2024-11-14 16:23:31 -05:00
Neil Dorin
0b60f53d0e feat: Adds IEssentialsRoomEmergency interface and implements on contact closure device to provide state 2024-11-13 12:15:25 -07:00
Andrew Welker
e7d7b8638e Merge pull request #1195 from PepperDash/feature/video-wall-mode
Feature/video wall mode
2024-07-12 09:20:25 -04:00
Colin Denig
0eb2436fa0 fix: videowall mode raw fb for dm-rmc-4kz-scaler-c 2024-07-11 15:42:25 -04:00
Colin Denig
192991cc65 fix(wip): DmRmc4kzScalerC VideoWallModeFb not working
- reverted PepperDashCode ref for Essentials_DM to unversioned and latest release
- fixed Scaler_OutputChange function params
- added instantiation of VideoWallModeRawFeedback
- feedback event trigger causing null ref exception
TODO:
-[] trace nullref exception cause
-[] Link Fb to Api
2024-07-10 16:45:02 -04:00
mhengeli
421f87db5e feat: add video wall mode command to dm-rmc-4kz-scaler-c 2024-07-09 20:06:49 -04:00
mhengeli
eb388d28db feat: add scaler mode for videowall set rmc 4kz scaler c 2024-06-21 15:37:28 -04:00
Neil Dorin
a2b7a39082 Merge pull request #1188 from PepperDash/hotfix/add-hdcp-control-to-airmedia
Hotfix/add hdcp control to airmedia
2024-05-16 15:31:35 -06:00
Neil Dorin
428f9f34bd Merge pull request #1187 from PepperDash/hotfix/add-hdcp-control-to-airmedia
main <- hotfix/add-hdcp-control-to-airmedia
2024-05-16 11:29:07 -06:00
Jason T Alborough
78e49871c6 Merge branch 'main' into hotfix/add-hdcp-control-to-airmedia 2024-05-16 12:18:08 -04:00
Andrew Welker
12e81af9e6 Merge pull request #1183 from PepperDash/hotfix/bridge-warning-fix
Hotfix/bridge warning fix
2024-05-16 00:38:44 -05:00
Neil Dorin
544a7a2d73 Merge branch 'main' into hotfix/bridge-warning-fix 2024-05-02 09:46:45 -06:00
Neil Dorin
1d843c6c89 Merge pull request #1184 from PepperDash/hotfix/fix-ghidra-specific-verbiage
fix: ghidra specific verbiage
2024-05-02 09:46:23 -06:00
Neil Dorin
c72db72e7e Merge branch 'main' into feature/bridge-warning-fix 2024-04-26 09:58:02 -06:00
AECohn
9e588f4da5 fix: ghidra specific verbiage 2024-04-25 10:42:40 -04:00
Aviv Cohn
4c466b425c fix: Change console message to include "use eiscApiAdvanced" 2024-04-25 10:24:09 -04:00
Jason T Alborough
d0aed1c1c5 Merge pull request #1173 from PepperDash/release/1.16.0
Release/1.16.0
2024-04-23 11:17:09 -04:00
Jason T Alborough
bf966121f9 Merge branch 'main' into release/1.16.0 2024-04-01 13:20:55 -04:00
Andrew Welker
ecadb439b2 Merge pull request #1176 from PepperDash/hotfix/ssh-fix
fix: Update PepperDashCore version to 1.3.3-hotfix-390
2024-03-21 09:59:17 -05:00
jtalborough
8c1553a026 fix: Update PepperDashCore version to 1.3.3-hotfix-390 2024-02-26 13:22:35 -05:00
Andrew Welker
9755724342 Merge pull request #1164 from PepperDash/feature/hdps-dm-event-updates
Feature/hdps dm event updates
2024-02-02 08:53:29 -06:00
Andrew Welker
4d25c420e5 Merge pull request #1161 from PepperDash/hotfix/video-codec-base
fix: clear selected causes thread abort in 3 series
2024-02-02 08:52:47 -06:00
Andrew Welker
3190dacdf8 Merge branch 'development' into feature/hdps-dm-event-updates 2024-02-02 08:34:30 -06:00
Andrew Welker
44add9aac6 Merge branch 'main' into hotfix/video-codec-base 2024-02-02 08:33:47 -06:00
Andrew Welker
5bb6405874 Merge pull request #1169 from PepperDash/hotfix/latest-dbs
Hotfix/latest dbs
2024-02-02 08:33:23 -06:00
Andrew Welker
fed3d7e13a Merge branch 'development' into hotfix/latest-dbs 2024-01-25 14:44:35 -06:00
Andrew Welker
af848b9ca4 Merge pull request #1168 from PepperDash/hotfix/latest-dbs 2024-01-25 14:03:48 -06:00
jtalborough
b52c13d8e8 fix: Update PepperDashCore package version to 1.3.2 2024-01-25 13:50:44 -05:00
jtalborough
26f9118154 chore: update PepperDashCore package version 2024-01-25 13:15:12 -05:00
Neil Dorin
bba3c347c6 Merge pull request #1166 from PepperDash/feature/add-cen-io-com-x02
feat: add cen-io-com102 and cen-io-com202 support
2023-12-19 14:45:02 -07:00
jkdevito
be96adcc06 feat: add cen-io-com102 and cen-io-com202 support 2023-12-19 10:50:55 -06:00
Jason DeVito
b245016420 fix: updated dminputchange event debug message 2023-12-14 17:02:14 -06:00
Jason DeVito
19f2c6aa79 fix: update dm event handlers, adds debug statements 2023-12-14 16:32:22 -06:00
Jason DeVito
533ca05ac2 feat: adds additional dm input/output event cases to event handlers 2023-12-14 12:43:46 -06:00
Jason DeVito
9c7777fbaa Merge pull request #1163 from PepperDash/feature/hdpsxxxx-volume-control
Feature/hdpsxxxx volume control
2023-12-13 16:54:59 -06:00
Jason DeVito
5530c91b75 refactor: HdPsXxxOutputAudioController & HdPsXxxAnalogAuxMixerController
- Updated audio controllers to implement `Volume(Feedback).ShortValue`
per documentation for set and get
- Changed `VolumeLevel` set to private set
- Removed `VolumeLevel` and `IsMuted` set from constructors
2023-12-13 16:01:15 -06:00
Jason DeVito
67e0378806 fix: cleanup debug statements 2023-12-13 12:41:45 -06:00
Jason DeVito
1c5aca03d2 fix: resolves hdPsXxx audio controllers scaleWithLimits exception 2023-12-13 12:36:45 -06:00
Nick Genovese
6f5fa2c3b8 fix: clear selected causes thread abort in 3 series
- the old method was using _directoryCode, _directoryTrilist, _directoryJoinmap which were never initialized
2023-12-12 15:29:41 -05:00
Neil Dorin
3d760cbedc feat: adds support for hdcp input control and feedback on Airmedia devices 2023-11-14 16:28:32 -07:00
Jason DeVito
d713abf614 fix: update hd-ps audio controllers to resolve control issues 2023-11-09 23:36:54 -06:00
Jason DeVito
a64b5240ad feat: add output audio controller 2023-11-03 18:14:53 -05:00
Jason DeVito
c528fecb9a feat(wip): add HdPsXxx audio control 2023-11-02 17:52:27 -05:00
jkdevito
355e9cde12 chore(wip): save updates 2023-11-02 11:55:48 -05:00
jkdevito
1df8d3f617 feat: create branch to add volume control 2023-11-02 11:54:44 -05:00
Neil Dorin
2f1caff815 Merge pull request #1154 from PepperDash/hotfix/mpc3-button-list
fix: list available buttons on startup
2023-10-27 12:53:52 -06:00
Jason DeVito
4da2f25c3d fix: list available buttons on startup 2023-10-27 12:14:07 -05:00
Andrew Welker
d6334538c0 Merge pull request #1142 from PepperDash/feature/ir-bridge-map
Add default IR join map using Crestron IR File naming conventions
2023-10-25 20:38:39 -06:00
132 changed files with 15665 additions and 1990 deletions

View File

@@ -0,0 +1,22 @@
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,94 +0,0 @@
name: Branch Build Using Docker
on:
push:
branches:
- feature-2.0.0/*
- hotfix-2.0.0/*
- release-2.0.0/*
- development-2.0.0
env:
# solution path doesn't need slashes unless there it is multiple folders deep
# solution name does not include extension. .sln is assumed
SOLUTION_PATH: .
SOLUTION_FILE: PepperDash.Essentials
# Do not edit this, we're just creating it here
VERSION: 0.0.0-buildtype-buildnumber
# Defaults to debug for build type
BUILD_TYPE: Debug
# Defaults to main as the release branch. Change as necessary
RELEASE_BRANCH: main
jobs:
Build_Project_4-Series:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- name: Set Version Number
id: setVersion
shell: powershell
run: |
$latestVersion = [version]"2.0.0"
$newVersion = [version]$latestVersion
$phase = ""
$newVersionString = ""
switch -regex ($Env:GITHUB_REF) {
'^refs\/pull\/*.' {
$phase = 'beta';
$newVersionString = "{0}-{1}-{2}" -f $newVersion, $phase, $Env:GITHUB_RUN_NUMBER
}
'^refs\/heads\/hotfix-2.0.0\/*.' {
$phase = 'hotfix'
$newVersionString = "{0}-{1}-{2}" -f $newVersion, $phase, $Env:GITHUB_RUN_NUMBER
}
'^refs\/heads\/release-2.0.0\/*.' {
$splitRef = $Env:GITHUB_REF -split "/"
$version = [version]($splitRef[-1] -replace "v", "")
$phase = 'rc'
$newVersionString = "{0}-{1}-{2}" -f $version, $phase, $Env:GITHUB_RUN_NUMBER
}
'^refs\/heads\/feature-2.0.0\/*.' {
$phase = 'alpha'
$newVersionString = "{0}-{1}-{2}" -f $newVersion, $phase, $Env:GITHUB_RUN_NUMBER
}
'development-2.0.0' {
$phase = 'beta'
$newVersionString = "{0}-{1}-{2}" -f $newVersion, $phase, $Env:GITHUB_RUN_NUMBER
}
}
echo "version=$newVersionString" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
- name: Setup MS Build
uses: microsoft/setup-msbuild@v1.1
- name: restore Nuget Packages
run: nuget restore .\$($Env:SOLUTION_FILE).sln
# Build the solutions in the docker image
- name: Build Solution
run: msbuild .\$($Env:SOLUTION_FILE).sln /p:Platform="Any CPU" /p:Configuration="Debug" /p:Version="${{ steps.setVersion.outputs.version }}" -m
- name: Pack Solution
run: dotnet pack .\$($Env:SOLUTION_FILE).sln --configuration $env:BUILD_TYPE --output ./output /p:Version="${{ steps.setVersion.outputs.version }}"
- name: Create tag for non-rc builds
if: ${{ !contains(steps.setVersion.outputs.version, 'rc') }}
run: |
git tag ${{ steps.setVersion.outputs.version }}
git push --tags origin
# Create the release on the source repo
- name: Create Release
id: create_release
uses: ncipollo/release-action@v1
with:
artifacts: 'output\**\*.*(cpz|cplz)'
generateReleaseNotes: true
prerelease: ${{contains('debug', env.BUILD_TYPE)}}
tag: ${{ steps.setVersion.outputs.version }}
- name: Setup Nuget
run: |
nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username pepperdash -password ${{ secrets.GITHUB_TOKEN }}
nuget setApiKey ${{ secrets.GITHUB_TOKEN }} -Source github
nuget setApiKey ${{ secrets.NUGET_API_KEY }} -Source https://api.nuget.org/v3/index.json
- name: Publish to Nuget
run: nuget push .\output\*.nupkg -Source https://api.nuget.org/v3/index.json
- name: Publish to Github Nuget
run: nuget push .\output\*.nupkg -Source github

View File

@@ -1,57 +0,0 @@
name: main Build using Docker
on:
release:
types:
- published
branches:
- main-2.0.0
env:
# solution path doesn't need slashes unless there it is multiple folders deep
# solution name does not include extension. .sln is assumed
SOLUTION_PATH: PepperDashEssentials
SOLUTION_FILE: PepperDashEssentials
# Do not edit this, we're just creating it here
VERSION: 0.0.0-buildtype-buildnumber
# Defaults to debug for build type
BUILD_TYPE: Release
# Defaults to main as the release branch. Change as necessary
RELEASE_BRANCH: main
jobs:
Build_Project:
runs-on: windows-2019
steps:
# First we checkout the source repo
- name: Checkout repo
uses: actions/checkout@v3
# Generate the appropriate version number
- name: Set Version Number
shell: powershell
id: setVersion
env:
TAG_NAME: ${{ github.event.release.tag_name }}
run: echo "VERSION=$($Env:TAG_NAME)" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
- name: Setup MS Build
uses: microsoft/setup-msbuild@v1.1
- name: restore Nuget Packages
run: nuget restore .\$($Env:SOLUTION_FILE).sln
- name: Build Solution
run: msbuild .\$($Env:SOLUTION_FILE).sln /p:Platform="Any CPU" /p:Configuration="Debug" /p:Version="${{ steps.setVersion.outputs.version }}" -m
- name: Pack Solution
run: dotnet pack .\$($Env:SOLUTION_FILE).sln --configuration $env:BUILD_TYPE --output ./output /p:Version="${{ steps.setVersion.outputs.version }}"
- name: Upload Release
id: create_release
uses: ncipollo/release-action@v1
with:
updateRelease: true
artifacts: 'output\**\*.*(cpz|cplz)'
tag: ${{ steps.setVersion.outputs.version }}
- name: Setup Nuget
run: |
nuget sources add -name github -source https://nuget.pkg.github.com/pepperdash/index.json -username pepperdash -password ${{ secrets.GITHUB_TOKEN }}
nuget setApiKey ${{ secrets.GITHUB_TOKEN }} -Source github
nuget setApiKey ${{ secrets.NUGET_API_KEY }} -Source https://api.nuget.org/v3/index.json
- name: Publish to Nuget
run: nuget push .\output\*.nupkg -Source https://api.nuget.org/v3/index.json
- name: Publish to Github Nuget
run: nuget push .\output\*.nupkg -Source github

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "Essentials-Template-UI"]
path = Essentials-Template-UI
url = https://github.com/PepperDash/Essentials-Template-UI.git

36
.releaserc.json Normal file
View File

@@ -0,0 +1,36 @@
{
"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

@@ -91,8 +91,8 @@ we receive and the availability of resources to evaluate contributions, we antic
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 Ghidra from your own
repository. As we identify and recognize extensions that are of general interest to the reverse engineering community, we
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

View File

@@ -9,6 +9,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PepperDash.Essentials", "sr
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PepperDash.Essentials.Core", "src\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj", "{3D192FED-8FFC-4CB5-B5F7-BA307ABA254B}"
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}"
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}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Essentials", "Essentials", "{AD98B742-8D85-481C-A69D-D8D8ABED39EA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug 4.7.2|Any CPU = Debug 4.7.2|Any CPU
@@ -34,10 +42,29 @@ Global
{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
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}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6907A4BF-7201-47CF-AAB1-3597F3B8E1C3}
EndGlobalSection

View File

@@ -2,10 +2,10 @@
<PropertyGroup>
<Version>2.0.0-local</Version>
<InformationalVersion>$(Version)</InformationalVersion>
<Authors>PepperDash Technologies</Authors>
<Company>PepperDash Technologies</Company>
<Authors>PepperDash Technology</Authors>
<Company>PepperDash Technology</Company>
<Product>PepperDash Essentials</Product>
<Copyright>Copyright © 2023</Copyright>
<Copyright>Copyright © 2025</Copyright>
<RepositoryUrl>https://github.com/PepperDash/Essentials</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>Crestron; 4series</PackageTags>

View File

@@ -1,26 +1,41 @@
<Project>
<ItemGroup>
<None Include="$(PackageOutputPath)\$(AssemblyName)\*.cpz" Condition="$(ProjectType) == 'Program'">
<None Include="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cpz" Condition="$(ProjectType) == 'Program'">
<Pack>true</Pack>
<PackagePath>build;</PackagePath>
</None>
<None Include="$(PackageOutputPath)\$(AssemblyName)\*.cplz" Condition="$(ProjectType) == 'ProgramLibrary'">
<None Include="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cplz" Condition="$(ProjectType) == 'ProgramLibrary'">
<Pack>true</Pack>
<PackagePath>build;</PackagePath>
</None>
</ItemGroup>
<Target Name="Create CPLZ" AfterTargets="Build; AfterRebuild" Condition="$(ProjectType) == 'ProgramLibrary' And $(TargetDir) != ''">
<PropertyGroup Condition="$(ProjectType) == 'ProgramLibrary'">
<FileName>$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cplz</FileName>
</PropertyGroup>
<PropertyGroup Condition="$(ProjectType) == 'Program'">
<FileName>$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cpz</FileName>
</PropertyGroup>
<Target Name="DeleteCPLZ" BeforeTargets="PreBuildEvent" Condition="$(ProjectType) == 'ProgramLibrary' And $(TargetDir) != '' And Exists($(FileName))">
<Delete Files="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cplz">
<Output TaskParameter="DeletedFiles" ItemName="DeletedList"/>
</Delete>
<Message Text="Deleted files: '@(DeletedList)'" />
</Target>
<Target Name="CreateCPLZ" AfterTargets="Build" Condition="$(ProjectType) == 'ProgramLibrary' And $(TargetDir) != ''" DependsOnTargets="DeleteCPLZ">
<Message Text="Creating CPLZ $(TargetDir)"></Message>
<MakeDir Directories="$(PackageOutputPath)" Condition="!Exists($(PackageOutputPath))" />
<MakeDir Directories="$(PackageOutputPath)\$(AssemblyName)" Condition="!Exists('$(PackageOutputPath)\$(AssemblyName)')" />
<ZipDirectory SourceDirectory="$(TargetDir)" DestinationFile="$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cplz" Overwrite="true"/>
<MakeDir Directories="$(PackageOutputPath)" Condition="!Exists($(PackageOutputPath))" />
<ZipDirectory SourceDirectory="$(TargetDir)" DestinationFile="$(PackageOutputPath)\$(TargetName).$(Version).$(TargetFramework).cplz" Overwrite="true"/>
<Copy SourceFiles="$(PackageOutputPath)\$(TargetName).$(Version).$(TargetFramework).cplz" DestinationFiles="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cplz" />
</Target>
<Target Name="Copy CPZ NET6" AfterTargets="SimplSharpPostProcess" Condition="($(ProjectType) == 'Program' And ( '$(TargetFramework)' == 'net6.0' ) Or ( '$(TargetFramework)' == 'net8.0' ))">
<Message Text="Copying CPZ"></Message>
<Move SourceFiles="$(TargetDir)$(TargetName).cpz" DestinationFiles="$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cpz" />
<Target Name="DeleteCPZ" BeforeTargets="PreBuildEvent" Condition="$(ProjectType) == 'Program' And $(TargetDir) != '' And Exists($(FileName))">
<Delete Files="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cpz">
<Output TaskParameter="DeletedFiles" ItemName="DeletedList"/>
</Delete>
<Message Text="Deleted files: '@(DeletedList)'" />
</Target>
<Target Name="Copy CPZ NET47" AfterTargets="SimplSharpPostProcess47" Condition="($(ProjectType) == 'Program' And ( '$(TargetFramework)' != 'net6.0' ) And ( '$(TargetFramework)' != 'net8.0' ))">
<Target Name="Copy CPZ" AfterTargets="SimplSharpPostProcess" Condition="($(ProjectType) == 'Program' And ( '$(TargetFramework)' != 'net6.0' ) And ( '$(TargetFramework)' != 'net8.0' ))">
<Message Text="Copying CPZ"></Message>
<Move SourceFiles="$(TargetDir)$(TargetName).cpz" DestinationFiles="$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cpz" />
<Move SourceFiles="$(TargetDir)$(TargetName).cpz" DestinationFiles="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cpz" />
<Copy SourceFiles="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cpz" DestinationFiles="$(PackageOutputPath)\$(TargetName).$(Version).$(TargetFramework).cpz" />
</Target>
</Project>

View File

@@ -1,4 +1,4 @@
using System;
using System;
namespace PepperDash.Essentials.Core.Bridges
{

View File

@@ -1,4 +1,4 @@
using System;
using System;
namespace PepperDash.Essentials.Core.Bridges
{

View File

@@ -7,17 +7,19 @@ namespace PepperDash.Essentials.Core
[Obsolete("Please use the builtin HttpClient class instead: https://learn.microsoft.com/en-us/dotnet/fundamentals/networking/http/httpclient-guidelines")]
public class GenericHttpClient : Device, IBasicCommunication
{
public HttpClient Client;
private readonly HttpClient Client;
public event EventHandler<GenericHttpClientEventArgs> ResponseRecived;
public GenericHttpClient(string key, string name, string hostname)
: base(key, name)
{
Client = new HttpClient();
Client.HostName = hostname;
}
Client = new HttpClient
{
HostName = hostname
};
}
/// <summary>
///
@@ -54,9 +56,8 @@ namespace PepperDash.Essentials.Core
if (responseReceived.ContentString.Length > 0)
{
if (ResponseRecived != null)
ResponseRecived(this, new GenericHttpClientEventArgs(responseReceived.ContentString, (request as HttpClientRequest).Url.ToString(), error));
}
ResponseRecived?.Invoke(this, new GenericHttpClientEventArgs(responseReceived.ContentString, (request as HttpClientRequest).Url.ToString(), error));
}
}
}

View File

@@ -21,7 +21,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
/// <summary>
/// Represents a generic digital input deviced tied to a versiport
/// </summary>
public class GenericVersiportDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput
public class GenericVersiportDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput, IPartitionStateProvider
{
public Versiport InputPort { get; private set; }
@@ -35,10 +35,15 @@ namespace PepperDash.Essentials.Core.CrestronIO
}
}
public BoolFeedback PartitionPresentFeedback { get; }
public bool PartitionPresent => !InputStateFeedbackFunc();
public GenericVersiportDigitalInputDevice(string key, string name, Func<IOPortConfig, Versiport> postActivationFunc, IOPortConfig config) :
base(key, name)
{
InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc);
PartitionPresentFeedback = new BoolFeedback(() => !InputStateFeedbackFunc());
AddPostActivationAction(() =>
{
@@ -52,7 +57,8 @@ namespace PepperDash.Essentials.Core.CrestronIO
InputPort.VersiportChange += InputPort_VersiportChange;
InputStateFeedback.FireUpdate();
PartitionPresentFeedback.FireUpdate();
Debug.LogMessage(LogEventLevel.Debug, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, InputPort.DisablePullUpResistor);
@@ -65,7 +71,10 @@ namespace PepperDash.Essentials.Core.CrestronIO
Debug.LogMessage(LogEventLevel.Debug, this, "Versiport change: {0}", args.Event);
if(args.Event == eVersiportEvent.DigitalInChange)
{
InputStateFeedback.FireUpdate();
PartitionPresentFeedback.FireUpdate();
}
}

View File

@@ -0,0 +1,8 @@
using PepperDash.Core;
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
{
public interface IDisplay: IHasFeedback, IRoutingSinkWithSwitching, IHasPowerControl, IWarmingCooling, IUsageTracking, IKeyName
{
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
{
public interface IEmergencyOSD
{
void ShowEmergencyMessage(string url);
void HideEmergencyMessage();
}
}

View File

@@ -1,5 +1,3 @@
using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core;
@@ -11,7 +9,6 @@ using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace PepperDash.Essentials.Core
{
public class DeviceJsonApi
@@ -141,18 +138,26 @@ namespace PepperDash.Essentials.Core
.Select((p, i) => ConvertType(action.Params[i], p.ParameterType))
.ToArray();
await Task.Run(() =>
try
{
try
Debug.LogMessage(LogEventLevel.Verbose, "Calling method {methodName} on device {deviceKey} with {@params}", null, method.Name, action.DeviceKey, action.Params);
var result = method.Invoke(obj, convertedParams);
// If the method returns a Task, await it
if (result is Task task)
{
Debug.LogMessage(LogEventLevel.Verbose, "Calling method {methodName} on device {deviceKey} with {@params}", null, method.Name, action.DeviceKey, action.Params);
method.Invoke(obj, convertedParams);
await task;
}
catch (Exception e)
// If the method returns a Task<T>, await it
else if (result != null && result.GetType().IsGenericType && result.GetType().GetGenericTypeDefinition() == typeof(Task<>))
{
Debug.LogMessage(e, "Error invoking method {methodName} on device {deviceKey}", null, method.Name, action.DeviceKey);
await (Task)result;
}
});
}
catch (Exception e)
{
Debug.LogMessage(e, "Error invoking method {methodName} on device {deviceKey}", null, method.Name, action.DeviceKey);
}
}
catch (Exception ex)
{

View File

@@ -1,12 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
@@ -16,22 +8,6 @@ namespace PepperDash.Essentials.Core
BoolFeedback IsOnline { get; }
}
///// <summary>
///// ** WANT THIS AND ALL ITS FRIENDS TO GO AWAY **
///// Defines a class that has a list of CueAction objects, typically
///// for linking functions to user interfaces or API calls
///// </summary>
//public interface IHasCueActionList
//{
// List<CueActionPair> CueActionList { get; }
//}
//public interface IHasComPortsHardware
//{
// IComPorts ComPortsDevice { get; }
//}
/// <summary>
/// Describes a device that can have a video sync providing device attached to it
/// </summary>

View File

@@ -1,81 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Crestron.SimplSharpPro;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Core;
using Serilog.Events;
namespace PepperDash.Essentials.Core.Devices
{
[Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")]
public class Laptop : EssentialsDevice, IHasFeedback, IRoutingOutputs, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking
{
public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } }
public string IconName { get; set; }
public BoolFeedback HasPowerOnFeedback { get; private set; }
public RoutingOutputPort AnyVideoOut { get; private set; }
#region IRoutingOutputs Members
/// <summary>
/// Options: hdmi
/// </summary>
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
#endregion
public Laptop(string key, string name)
: base(key, name)
{
IconName = "Laptop";
HasPowerOnFeedback = new BoolFeedback("HasPowerFeedback",
() => this.GetVideoStatuses() != VideoStatusOutputs.NoStatus);
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
OutputPorts.Add(AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.None, 0, this));
}
#region IHasFeedback Members
/// <summary>
/// Passes through the VideoStatuses list
/// </summary>
public FeedbackCollection<Feedback> Feedbacks
{
get
{
var newList = new FeedbackCollection<Feedback>();
newList.AddRange(this.GetVideoStatuses().ToList());
return newList;
}
}
#endregion
#region IUsageTracking Members
public UsageTracking UsageTracker { get; set; }
#endregion
}
[Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")]
public class LaptopFactory : EssentialsDeviceFactory<Laptop>
{
public LaptopFactory()
{
TypeNames = new List<string>() { "deprecated" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Laptop Device");
return new Core.Devices.Laptop(dc.Key, dc.Name);
}
}
}

View File

@@ -1,229 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Bridges;
using Serilog.Events;
namespace PepperDash.Essentials.Core
{
[Obsolete("Please use PepperDash.Essentials.Device.Common, this will be removed in 2.1")]
public class BasicIrDisplay : DisplayBase, IBasicVolumeControls, IBridgeAdvanced
{
public IrOutputPortController IrPort { get; private set; }
public ushort IrPulseTime { get; set; }
protected Func<bool> PowerIsOnFeedbackFunc
{
get { return () => _PowerIsOn; }
}
protected override Func<bool> IsCoolingDownFeedbackFunc
{
get { return () => _IsCoolingDown; }
}
protected override Func<bool> IsWarmingUpFeedbackFunc
{
get { return () => _IsWarmingUp; }
}
bool _PowerIsOn;
bool _IsWarmingUp;
bool _IsCoolingDown;
public BasicIrDisplay(string key, string name, IROutputPort port, string irDriverFilepath)
: base(key, name)
{
IrPort = new IrOutputPortController(key + "-ir", port, irDriverFilepath);
DeviceManager.AddDevice(IrPort);
IsWarmingUpFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Verbose, this, "Warming up={0}", _IsWarmingUp);
IsCoolingDownFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Verbose, this, "Cooling down={0}", _IsCoolingDown);
InputPorts.AddRange(new RoutingPortCollection<RoutingInputPort>
{
new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Hdmi1), this, false),
new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Hdmi2), this, false),
new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Hdmi3), this, false),
new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Hdmi4), this, false),
new RoutingInputPort(RoutingPortNames.ComponentIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Component1), this, false),
new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Video1), this, false),
new RoutingInputPort(RoutingPortNames.AntennaIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Antenna), this, false),
});
}
public void Hdmi1()
{
IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_1, IrPulseTime);
}
public void Hdmi2()
{
IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_2, IrPulseTime);
}
public void Hdmi3()
{
IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_3, IrPulseTime);
}
public void Hdmi4()
{
IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_4, IrPulseTime);
}
public void Component1()
{
IrPort.Pulse(IROutputStandardCommands.IROut_COMPONENT_1, IrPulseTime);
}
public void Video1()
{
IrPort.Pulse(IROutputStandardCommands.IROut_VIDEO_1, IrPulseTime);
}
public void Antenna()
{
IrPort.Pulse(IROutputStandardCommands.IROut_ANTENNA, IrPulseTime);
}
#region IPower Members
public override void PowerOn()
{
IrPort.Pulse(IROutputStandardCommands.IROut_POWER_ON, IrPulseTime);
_PowerIsOn = true;
}
public override void PowerOff()
{
_PowerIsOn = false;
IrPort.Pulse(IROutputStandardCommands.IROut_POWER_OFF, IrPulseTime);
}
public override void PowerToggle()
{
_PowerIsOn = false;
IrPort.Pulse(IROutputStandardCommands.IROut_POWER, IrPulseTime);
}
#endregion
#region IBasicVolumeControls Members
public void VolumeUp(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_VOL_PLUS, pressRelease);
}
public void VolumeDown(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_VOL_MINUS, pressRelease);
}
public void MuteToggle()
{
IrPort.Pulse(IROutputStandardCommands.IROut_MUTE, 200);
}
#endregion
void StartWarmingTimer()
{
_IsWarmingUp = true;
IsWarmingUpFeedback.FireUpdate();
new CTimer(o => {
_IsWarmingUp = false;
IsWarmingUpFeedback.FireUpdate();
}, 10000);
}
void StartCoolingTimer()
{
_IsCoolingDown = true;
IsCoolingDownFeedback.FireUpdate();
new CTimer(o =>
{
_IsCoolingDown = false;
IsCoolingDownFeedback.FireUpdate();
}, 7000);
}
#region IRoutingSink Members
/// <summary>
/// Typically called by the discovery routing algorithm.
/// </summary>
/// <param name="inputSelector">A delegate containing the input selector method to call</param>
public override void ExecuteSwitch(object inputSelector)
{
Debug.LogMessage(LogEventLevel.Verbose, this, "Switching to input '{0}'", (inputSelector as Action).ToString());
Action finishSwitch = () =>
{
var action = inputSelector as Action;
if (action != null)
action();
};
if (!_PowerIsOn)
{
PowerOn();
EventHandler<FeedbackEventArgs> oneTimer = null;
oneTimer = (o, a) =>
{
if (IsWarmingUpFeedback.BoolValue) return; // Only catch done warming
IsWarmingUpFeedback.OutputChange -= oneTimer;
finishSwitch();
};
IsWarmingUpFeedback.OutputChange += oneTimer;
}
else // Do it!
finishSwitch();
}
#endregion
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge);
}
}
[Obsolete("Please use PepperDash.Essentials.Device.Common, this will be removed in 2.1")]
public class BasicIrDisplayFactory : EssentialsDeviceFactory<BasicIrDisplay>
{
public BasicIrDisplayFactory()
{
TypeNames = new List<string>() { "basicirdisplay" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new BasicIrDisplay Device");
var ir = IRPortHelper.GetIrPort(dc.Properties);
if (ir != null)
{
var display = new BasicIrDisplay(dc.Key, dc.Name, ir.Port, ir.FileName);
display.IrPulseTime = 200; // Set default pulse time for IR commands.
return display;
}
return null;
}
}
}

View File

@@ -1,320 +0,0 @@
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges;
using Serilog.Events;
using System;
using System.Collections.Generic;
using System.Linq;
namespace PepperDash.Essentials.Core
{
[Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")]
public abstract class DisplayBase : EssentialsDevice, IHasFeedback, IRoutingSinkWithSwitching, IHasPowerControl, IWarmingCooling, IUsageTracking
{
public event SourceInfoChangeHandler CurrentSourceChange;
public event InputChangedEventHandler InputChanged;
public string CurrentSourceInfoKey { get; set; }
public SourceListItem CurrentSourceInfo
{
get
{
return _CurrentSourceInfo;
}
set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSourceChange;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.WillChange);
_CurrentSourceInfo = value;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.DidChange);
}
}
SourceListItem _CurrentSourceInfo;
public BoolFeedback IsCoolingDownFeedback { get; protected set; }
public BoolFeedback IsWarmingUpFeedback { get; private set; }
public UsageTracking UsageTracker { get; set; }
public uint WarmupTime { get; set; }
public uint CooldownTime { get; set; }
/// <summary>
/// Bool Func that will provide a value for the PowerIsOn Output. Must be implemented
/// by concrete sub-classes
/// </summary>
abstract protected Func<bool> IsCoolingDownFeedbackFunc { get; }
abstract protected Func<bool> IsWarmingUpFeedbackFunc { get; }
protected CTimer WarmupTimer;
protected CTimer CooldownTimer;
#region IRoutingInputs Members
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
#endregion
protected DisplayBase(string key, string name)
: base(key, name)
{
IsCoolingDownFeedback = new BoolFeedback("IsCoolingDown", IsCoolingDownFeedbackFunc);
IsWarmingUpFeedback = new BoolFeedback("IsWarmingUp", IsWarmingUpFeedbackFunc);
InputPorts = new RoutingPortCollection<RoutingInputPort>();
}
public abstract void PowerOn();
public abstract void PowerOff();
public abstract void PowerToggle();
public virtual FeedbackCollection<Feedback> Feedbacks
{
get
{
return new FeedbackCollection<Feedback>
{
IsCoolingDownFeedback,
IsWarmingUpFeedback
};
}
}
public RoutingInputPort CurrentInputPort => throw new NotImplementedException();
public abstract void ExecuteSwitch(object selector);
protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, uint joinStart, string joinMapKey,
EiscApiAdvanced bridge)
{
var joinMap = new DisplayControllerJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<DisplayControllerJoinMap>(joinMapSerialized);
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.LogMessage(LogEventLevel.Information,this,"Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
LinkDisplayToApi(displayDevice, trilist, joinMap);
}
protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, DisplayControllerJoinMap joinMap)
{
Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.LogMessage(LogEventLevel.Information, "Linking to Display: {0}", displayDevice.Name);
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = displayDevice.Name;
var commMonitor = displayDevice as ICommunicationMonitor;
if (commMonitor != null)
{
commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
}
var inputNumber = 0;
var inputKeys = new List<string>();
var inputNumberFeedback = new IntFeedback(() => inputNumber);
// Two way feedbacks
var twoWayDisplay = displayDevice as TwoWayDisplayBase;
if (twoWayDisplay != null)
{
trilist.SetBool(joinMap.IsTwoWayDisplay.JoinNumber, true);
twoWayDisplay.CurrentInputFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Information, "CurrentInputFeedback_OutputChange {0}", a.StringValue);
inputNumberFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputSelect.JoinNumber]);
}
// Power Off
trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () =>
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOff();
});
var twoWayDisplayDevice = displayDevice as TwoWayDisplayBase;
if (twoWayDisplayDevice != null)
{
twoWayDisplayDevice.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (!a.BoolValue)
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
}
else
{
inputNumber = 0;
inputNumberFeedback.FireUpdate();
}
};
twoWayDisplayDevice.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]);
twoWayDisplayDevice.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]);
}
// PowerOn
trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () =>
{
inputNumber = 0;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOn();
});
for (int i = 0; i < displayDevice.InputPorts.Count; i++)
{
if (i < joinMap.InputNamesOffset.JoinSpan)
{
inputKeys.Add(displayDevice.InputPorts[i].Key);
var tempKey = inputKeys.ElementAt(i);
trilist.SetSigTrueAction((ushort)(joinMap.InputSelectOffset.JoinNumber + i),
() => displayDevice.ExecuteSwitch(displayDevice.InputPorts[tempKey].Selector));
Debug.LogMessage(LogEventLevel.Verbose, displayDevice, "Setting Input Select Action on Digital Join {0} to Input: {1}",
joinMap.InputSelectOffset.JoinNumber + i, displayDevice.InputPorts[tempKey].Key.ToString());
trilist.StringInput[(ushort)(joinMap.InputNamesOffset.JoinNumber + i)].StringValue = displayDevice.InputPorts[i].Key.ToString();
}
else
Debug.LogMessage(LogEventLevel.Information, displayDevice, "Device has {0} inputs. The Join Map allows up to {1} inputs. Discarding inputs {2} - {3} from bridge.",
displayDevice.InputPorts.Count, joinMap.InputNamesOffset.JoinSpan, i + 1, displayDevice.InputPorts.Count);
}
Debug.LogMessage(LogEventLevel.Verbose, displayDevice, "Setting Input Select Action on Analog Join {0}", joinMap.InputSelect);
trilist.SetUShortSigAction(joinMap.InputSelect.JoinNumber, (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) return;
trilist.SetBoolSigAction(joinMap.VolumeUp.JoinNumber, volumeDisplay.VolumeUp);
trilist.SetBoolSigAction(joinMap.VolumeDown.JoinNumber, volumeDisplay.VolumeDown);
trilist.SetSigTrueAction(joinMap.VolumeMute.JoinNumber, volumeDisplay.MuteToggle);
var volumeDisplayWithFeedback = volumeDisplay as IBasicVolumeWithFeedback;
if (volumeDisplayWithFeedback == null) return;
trilist.SetSigTrueAction(joinMap.VolumeMuteOn.JoinNumber, volumeDisplayWithFeedback.MuteOn);
trilist.SetSigTrueAction(joinMap.VolumeMuteOff.JoinNumber, volumeDisplayWithFeedback.MuteOff);
trilist.SetUShortSigAction(joinMap.VolumeLevel.JoinNumber, volumeDisplayWithFeedback.SetVolume);
volumeDisplayWithFeedback.VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[joinMap.VolumeLevel.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMute.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMuteOn.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.VolumeMuteOff.JoinNumber]);
}
}
[Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")]
public abstract class TwoWayDisplayBase : DisplayBase, IRoutingFeedback, IHasPowerControlWithFeedback
{
public StringFeedback CurrentInputFeedback { get; private set; }
abstract protected Func<string> CurrentInputFeedbackFunc { get; }
public BoolFeedback PowerIsOnFeedback { get; protected set; }
abstract protected Func<bool> PowerIsOnFeedbackFunc { get; }
// public static MockDisplay DefaultDisplay
// {
// get
// {
// if (_DefaultDisplay == null)
// _DefaultDisplay = new MockDisplay("default", "Default Display");
// return _DefaultDisplay;
// }
//}
//static MockDisplay _DefaultDisplay;
public TwoWayDisplayBase(string key, string name)
: base(key, name)
{
CurrentInputFeedback = new StringFeedback(CurrentInputFeedbackFunc);
WarmupTime = 7000;
CooldownTime = 15000;
PowerIsOnFeedback = new BoolFeedback("PowerOnFeedback", PowerIsOnFeedbackFunc);
Feedbacks.Add(CurrentInputFeedback);
Feedbacks.Add(PowerIsOnFeedback);
PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange;
}
void PowerIsOnFeedback_OutputChange(object sender, EventArgs e)
{
if (UsageTracker != null)
{
if (PowerIsOnFeedback.BoolValue)
UsageTracker.StartDeviceUsage();
else
UsageTracker.EndDeviceUsage();
}
}
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
protected void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
}
}

View File

@@ -9,6 +9,7 @@ using Crestron.SimplSharpPro.Fusion;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using Serilog.Events;
using System;
using System.Collections.Generic;
@@ -19,7 +20,7 @@ namespace PepperDash.Essentials.Core.Fusion
{
public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupancyStatusProvider
{
protected EssentialsHuddleSpaceRoomFusionRoomJoinMap JoinMap;
private readonly EssentialsHuddleSpaceRoomFusionRoomJoinMap JoinMap;
private const string RemoteOccupancyXml = "<Occupancy><Type>Local</Type><State>{0}</State></Occupancy>";
private readonly bool _guidFileExists;
@@ -29,15 +30,15 @@ namespace PepperDash.Essentials.Core.Fusion
protected StringSigData CurrentRoomSourceNameSig;
public FusionCustomPropertiesBridge CustomPropertiesBridge = new FusionCustomPropertiesBridge();
private readonly FusionCustomPropertiesBridge CustomPropertiesBridge = new FusionCustomPropertiesBridge();
protected FusionOccupancySensorAsset FusionOccSensor;
protected FusionRemoteOccupancySensor FusionRemoteOccSensor;
private readonly FusionRemoteOccupancySensor FusionRemoteOccSensor;
protected FusionRoom FusionRoom;
protected Dictionary<int, FusionAsset> FusionStaticAssets;
public long PushNotificationTimeout = 5000;
protected IEssentialsRoom Room;
public long SchedulePollInterval = 300000;
private readonly long PushNotificationTimeout = 5000;
private readonly IEssentialsRoom Room;
private readonly long SchedulePollInterval = 300000;
private Event _currentMeeting;
private RoomSchedule _currentSchedule;
@@ -85,7 +86,7 @@ namespace PepperDash.Essentials.Core.Fusion
#region Default Display Source Sigs
private BooleanSigData[] _source = new BooleanSigData[10];
private readonly BooleanSigData[] _source = new BooleanSigData[10];
#endregion
@@ -151,9 +152,8 @@ namespace PepperDash.Essentials.Core.Fusion
ReadGuidFile(guidFilePath);
}
var occupancyRoom = Room as IRoomOccupancy;
if (occupancyRoom != null)
if (Room is IRoomOccupancy occupancyRoom)
{
if (occupancyRoom.RoomOccupancy != null)
{
@@ -367,8 +367,7 @@ namespace PepperDash.Essentials.Core.Fusion
CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(JoinMap.Display1CurrentSourceName.JoinNumber, JoinMap.Display1CurrentSourceName.AttributeName,
eSigIoMask.InputSigOnly);
// Don't think we need to get current status of this as nothing should be alive yet.
var hasCurrentSourceInfoChange = Room as IHasCurrentSourceInfoChange;
if (hasCurrentSourceInfoChange != null)
if (Room is IHasCurrentSourceInfoChange hasCurrentSourceInfoChange)
{
hasCurrentSourceInfoChange.CurrentSourceChange += Room_CurrentSourceInfoChange;
}
@@ -377,8 +376,7 @@ namespace PepperDash.Essentials.Core.Fusion
FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction(Room.PowerOnToDefaultOrLastSource);
FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() =>
{
var runRouteAction = Room as IRunRouteAction;
if (runRouteAction != null)
if (Room is IRunRouteAction runRouteAction)
{
runRouteAction.RunRouteAction("roomOff", Room.SourceListKey);
}
@@ -660,7 +658,7 @@ namespace PepperDash.Essentials.Core.Fusion
var extendTime = _currentMeeting.dtEnd - DateTime.Now;
var extendMinutesRaw = extendTime.TotalMinutes;
extendMinutes = extendMinutes + (int) Math.Round(extendMinutesRaw);
extendMinutes += (int) Math.Round(extendMinutesRaw);
}
@@ -901,12 +899,7 @@ namespace PepperDash.Essentials.Core.Fusion
}
}
}
var handler = RoomInfoChange;
if (handler != null)
{
handler(this, new EventArgs());
}
RoomInfoChange?.Invoke(this, new EventArgs());
CustomPropertiesBridge.EvaluateRoomInfo(Room.Key, roomInformation);
}
@@ -1014,12 +1007,7 @@ namespace PepperDash.Essentials.Core.Fusion
}
// Fire Schedule Change Event
var handler = ScheduleChange;
if (handler != null)
{
handler(this, new ScheduleChangeEventArgs {Schedule = _currentSchedule});
}
ScheduleChange?.Invoke(this, new ScheduleChangeEventArgs { Schedule = _currentSchedule });
}
}
}
@@ -1091,7 +1079,7 @@ namespace PepperDash.Essentials.Core.Fusion
}
}
var laptops = dict.Where(d => d.Value.SourceDevice is Devices.Laptop);
var laptops = dict.Where(d => d.Value.SourceDevice is IRoutingSource);
i = 1;
foreach (var kvp in laptops)
{
@@ -1123,9 +1111,7 @@ namespace PepperDash.Essentials.Core.Fusion
/// <param name="e"></param>
protected void UsageTracker_DeviceUsageEnded(object sender, DeviceUsageEventArgs e)
{
var deviceTracker = sender as UsageTracking;
if (deviceTracker == null)
if (!(sender is UsageTracking deviceTracker))
{
return;
}
@@ -1168,8 +1154,7 @@ namespace PepperDash.Essentials.Core.Fusion
// And respond to selection in Fusion
sigD.OutputSig.SetSigFalseAction(() =>
{
var runRouteAction = Room as IRunRouteAction;
if (runRouteAction != null)
if (Room is IRunRouteAction runRouteAction)
{
runRouteAction.RunRouteAction(routeKey, Room.SourceListKey);
}
@@ -1213,12 +1198,11 @@ namespace PepperDash.Essentials.Core.Fusion
//uint attrNum = Convert.ToUInt32(keyNum);
// Check for UI devices
var uiDev = dev as IHasBasicTriListWithSmartObject;
if (uiDev != null)
if (dev is IHasBasicTriListWithSmartObject uiDev)
{
if (uiDev.Panel is Crestron.SimplSharpPro.UI.XpanelForSmartGraphics)
{
attrNum = attrNum + touchpanelNum;
attrNum += touchpanelNum;
if (attrNum > JoinMap.XpanelOnlineStart.JoinSpan)
{
@@ -1231,7 +1215,7 @@ namespace PepperDash.Essentials.Core.Fusion
}
else
{
attrNum = attrNum + xpanelNum;
attrNum += xpanelNum;
if (attrNum > JoinMap.TouchpanelOnlineStart.JoinSpan)
{
@@ -1245,9 +1229,9 @@ namespace PepperDash.Essentials.Core.Fusion
}
//else
if (dev is DisplayBase)
if (dev is IDisplay)
{
attrNum = attrNum + displayNum;
attrNum += displayNum;
if (attrNum > JoinMap.DisplayOnlineStart.JoinSpan)
{
continue;
@@ -1289,23 +1273,21 @@ namespace PepperDash.Essentials.Core.Fusion
{
//Setup Display Usage Monitoring
var displays = DeviceManager.AllDevices.Where(d => d is DisplayBase);
var displays = DeviceManager.AllDevices.Where(d => d is IDisplay);
// Consider updating this in multiple display systems
foreach (var display in displays.Cast<DisplayBase>())
foreach (var display in displays.Cast<IDisplay>())
{
display.UsageTracker = new UsageTracking(display) {UsageIsTracked = true};
display.UsageTracker = new UsageTracking(display as Device) {UsageIsTracked = true};
display.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
}
var hasDefaultDisplay = Room as IHasDefaultDisplay;
if (hasDefaultDisplay == null)
if (!(Room is IHasDefaultDisplay hasDefaultDisplay))
{
return;
}
var defaultDisplay = hasDefaultDisplay.DefaultDisplay as DisplayBase;
if (defaultDisplay == null)
if (!(hasDefaultDisplay.DefaultDisplay is IDisplay defaultDisplay))
{
Debug.LogMessage(LogEventLevel.Debug, this, "Cannot link null display to Fusion because default display is null");
return;
@@ -1357,8 +1339,7 @@ namespace PepperDash.Essentials.Core.Fusion
dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
var defaultTwoWayDisplay = defaultDisplay as IHasPowerControlWithFeedback;
if (defaultTwoWayDisplay != null)
if (defaultDisplay is IHasPowerControlWithFeedback defaultTwoWayDisplay)
{
defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
if (defaultDisplay is IDisplayUsage)
@@ -1370,8 +1351,8 @@ namespace PepperDash.Essentials.Core.Fusion
}
// Use extension methods
dispAsset.TrySetMakeModel(defaultDisplay);
dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay);
dispAsset.TrySetMakeModel(defaultDisplay as Device);
dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay as Device);
}
catch (Exception e)
{
@@ -1386,13 +1367,12 @@ namespace PepperDash.Essentials.Core.Fusion
/// <param name="display"></param>
/// <param name="displayIndex"></param>
/// a
protected virtual void MapDisplayToRoomJoins(int displayIndex, uint joinOffset, DisplayBase display)
protected virtual void MapDisplayToRoomJoins(int displayIndex, uint joinOffset, IDisplay display)
{
var displayName = string.Format("Display {0} - ", displayIndex);
var hasDefaultDisplay = Room as IHasDefaultDisplay;
if (hasDefaultDisplay == null || display != hasDefaultDisplay.DefaultDisplay)
if (!(Room is IHasDefaultDisplay hasDefaultDisplay) || display != hasDefaultDisplay.DefaultDisplay)
{
return;
}
@@ -1401,8 +1381,7 @@ namespace PepperDash.Essentials.Core.Fusion
eSigIoMask.InputOutputSig);
defaultDisplayVolume.OutputSig.UserObject = new Action<ushort>(b =>
{
var basicVolumeWithFeedback = display as IBasicVolumeWithFeedback;
if (basicVolumeWithFeedback == null)
if (!(display is IBasicVolumeWithFeedback basicVolumeWithFeedback))
{
return;
}
@@ -1435,8 +1414,7 @@ namespace PepperDash.Essentials.Core.Fusion
});
var defaultTwoWayDisplay = display as IHasPowerControlWithFeedback;
if (defaultTwoWayDisplay != null)
if (display is IHasPowerControlWithFeedback defaultTwoWayDisplay)
{
defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
defaultTwoWayDisplay.PowerIsOnFeedback.LinkComplementInputSig(defaultDisplayPowerOff.InputSig);
@@ -1449,8 +1427,7 @@ namespace PepperDash.Essentials.Core.Fusion
{
if (!b)
{
var runRouteAction = Room as IRunRouteAction;
if (runRouteAction != null)
if (Room is IRunRouteAction runRouteAction)
{
runRouteAction.RunRouteAction("roomOff", Room.SourceListKey);
}
@@ -1464,8 +1441,7 @@ namespace PepperDash.Essentials.Core.Fusion
_errorMessageRollUp = new StatusMonitorCollection(this);
foreach (var dev in DeviceManager.GetDevices())
{
var md = dev as ICommunicationMonitor;
if (md != null)
if (dev is ICommunicationMonitor md)
{
_errorMessageRollUp.AddMonitor(md.CommunicationMonitor);
Debug.LogMessage(LogEventLevel.Verbose, this, "Adding '{0}' to room's overall error monitor",
@@ -1531,9 +1507,8 @@ namespace PepperDash.Essentials.Core.Fusion
// Tie to method on occupancy object
//occSensorShutdownMinutes.OutputSig.UserObject(new Action(ushort)(b => Room.OccupancyObj.SetShutdownMinutes(b));
var occRoom = Room as IRoomOccupancy;
if (occRoom != null)
if (Room is IRoomOccupancy occRoom)
{
occRoom.RoomOccupancy.RoomIsOccupiedFeedback.LinkInputSig(occSensorAsset.RoomOccupied.InputSig);
occRoom.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
@@ -1600,10 +1575,9 @@ namespace PepperDash.Essentials.Core.Fusion
// The sig/UO method: Need separate handlers for fixed and user sigs, all flavors,
// even though they all contain sigs.
var sigData = args.UserConfiguredSigDetail as BooleanSigDataFixedName;
BoolOutputSig outSig;
if (sigData != null)
if (args.UserConfiguredSigDetail is BooleanSigDataFixedName sigData)
{
outSig = sigData.OutputSig;
if (outSig.UserObject is Action<bool>)
@@ -1759,8 +1733,7 @@ namespace PepperDash.Essentials.Core.Fusion
/// </summary>
public static void TrySetMakeModel(this FusionStaticAsset asset, Device device)
{
var mm = device as IMakeModel;
if (mm != null)
if (device is IMakeModel mm)
{
asset.ParamMake.Value = mm.DeviceMake;
asset.ParamModel.Value = mm.DeviceModel;

View File

@@ -1,171 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges;
using Serilog.Events;
namespace PepperDash.Essentials.Core.Lighting
{
[Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")]
public abstract class LightingBase : EssentialsBridgeableDevice, ILightingScenes
{
#region ILightingScenes Members
public event EventHandler<LightingSceneChangeEventArgs> LightingSceneChange;
public List<LightingScene> LightingScenes { get; protected set; }
public LightingScene CurrentLightingScene { get; protected set; }
public IntFeedback CurrentLightingSceneFeedback { get; protected set; }
#endregion
protected LightingBase(string key, string name)
: base(key, name)
{
LightingScenes = new List<LightingScene>();
CurrentLightingScene = new LightingScene();
//CurrentLightingSceneFeedback = new IntFeedback(() => { return int.Parse(this.CurrentLightingScene.ID); });
}
public abstract void SelectScene(LightingScene scene);
public void SimulateSceneSelect(string sceneName)
{
Debug.LogMessage(LogEventLevel.Debug, this, "Simulating selection of scene '{0}'", sceneName);
var scene = LightingScenes.FirstOrDefault(s => s.Name.Equals(sceneName));
if (scene != null)
{
CurrentLightingScene = scene;
OnLightingSceneChange();
}
}
/// <summary>
/// Sets the IsActive property on each scene and fires the LightingSceneChange event
/// </summary>
protected void OnLightingSceneChange()
{
foreach (var scene in LightingScenes)
{
if (scene == CurrentLightingScene)
scene.IsActive = true;
else
scene.IsActive = false;
}
var handler = LightingSceneChange;
if (handler != null)
{
handler(this, new LightingSceneChangeEventArgs(CurrentLightingScene));
}
}
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart,
string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new GenericLightingJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<GenericLightingJoinMap>(joinMapSerialized);
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
return LinkLightingToApi(lightingDevice, trilist, joinMap);
}
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, GenericLightingJoinMap joinMap)
{
Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.LogMessage(LogEventLevel.Information, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString());
// GenericLighitng Actions & FeedBack
trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u]));
var sceneIndex = 0;
foreach (var scene in lightingDevice.LightingScenes)
{
var index = sceneIndex;
trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + index), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[index]));
scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)]);
trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name;
trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true;
sceneIndex++;
}
trilist.OnlineStatusChange += (sender, args) =>
{
if (!args.DeviceOnLine) return;
sceneIndex = 0;
foreach (var scene in lightingDevice.LightingScenes)
{
var index = sceneIndex;
trilist.StringInput[(uint) (joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name;
trilist.BooleanInput[(uint) (joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true;
scene.IsActiveFeedback.FireUpdate();
sceneIndex++;
}
};
return joinMap;
}
}
public class LightingScene
{
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }
[JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
public string ID { get; set; }
bool _IsActive;
[JsonProperty("isActive", NullValueHandling = NullValueHandling.Ignore)]
public bool IsActive
{
get
{
return _IsActive;
}
set
{
_IsActive = value;
IsActiveFeedback.FireUpdate();
}
}
[JsonIgnore]
public BoolFeedback IsActiveFeedback { get; set; }
public LightingScene()
{
IsActiveFeedback = new BoolFeedback(new Func<bool>(() => IsActive));
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core.Lighting
{
public class LightingScene
{
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }
[JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
public string ID { get; set; }
bool _IsActive;
[JsonProperty("isActive", NullValueHandling = NullValueHandling.Ignore)]
public bool IsActive
{
get
{
return _IsActive;
}
set
{
_IsActive = value;
IsActiveFeedback.FireUpdate();
}
}
[JsonIgnore]
public BoolFeedback IsActiveFeedback { get; set; }
public LightingScene()
{
IsActiveFeedback = new BoolFeedback(new Func<bool>(() => IsActive));
}
}
}

View File

@@ -151,17 +151,16 @@ namespace PepperDash.Essentials.Core
{
if (MonitorBytesReceived)
{
Client.BytesReceived += Client_BytesReceived;
Client.BytesReceived -= Client_BytesReceived;
Client.BytesReceived += Client_BytesReceived;
}
else
{
Client.TextReceived -= Client_TextReceived;
Client.TextReceived += Client_TextReceived;
}
if (!IsSocket)
{
BeginPolling();
}
BeginPolling();
}
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)

View File

@@ -4,8 +4,9 @@
<Configurations>Debug;Release;Debug 4.7.2</Configurations>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>net472;net6</TargetFrameworks>
<TargetFramework>net472</TargetFramework>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<OutputPath>bin\$(Configuration)\</OutputPath>
<AssemblyName>PepperDash_Essentials_Core</AssemblyName>
<RootNamespace>PepperDash.Essentials.Core</RootNamespace>
@@ -13,7 +14,6 @@
<PackageId>PepperDash.Essentials.Core</PackageId>
<InformationalVersion>$(Version)</InformationalVersion>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<Version>2.0.0-local</Version>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType>
@@ -25,10 +25,13 @@
<DebugType>pdbonly</DebugType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.20.66" />
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-424" />
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.21.90" />
<PackageReference Include="PepperDashCore" Version="2.0.1" />
</ItemGroup>
<ItemGroup>
<None Include="Crestron\CrestronGenericBaseDevice.cs.orig" />
</ItemGroup>
<ItemGroup>
<Folder Include="Display\" />
</ItemGroup>
</Project>

View File

@@ -1,432 +0,0 @@
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{A49AD6C8-FC0A-4CC0-9089-DFB4CF92D2B5}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>PepperDash.Essentials.Core</RootNamespace>
<AssemblyName>PepperDash_Essentials_Core</AssemblyName>
<ProjectTypeGuids>{0B4745B0-194B-4BB6-8E21-E9057CA92300};{4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<PlatformFamilyName>WindowsCE</PlatformFamilyName>
<PlatformID>E2BECB1F-8C8C-41ba-B736-9BE7D946A398</PlatformID>
<OSVersion>5.0</OSVersion>
<DeployDirSuffix>SmartDeviceProject1</DeployDirSuffix>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<NativePlatformName>Windows CE</NativePlatformName>
<FormFactorID>
</FormFactorID>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<AllowedReferenceRelatedFileExtensions>.allowedReferenceRelatedFileExtensions</AllowedReferenceRelatedFileExtensions>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<FileAlignment>512</FileAlignment>
<NoStdLib>true</NoStdLib>
<NoConfig>true</NoConfig>
<GenerateSerializationAssemblies>off</GenerateSerializationAssemblies>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<AllowedReferenceRelatedFileExtensions>.allowedReferenceRelatedFileExtensions</AllowedReferenceRelatedFileExtensions>
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<FileAlignment>512</FileAlignment>
<NoStdLib>true</NoStdLib>
<NoConfig>true</NoConfig>
<GenerateSerializationAssemblies>off</GenerateSerializationAssemblies>
</PropertyGroup>
<ItemGroup>
<Reference Include="Crestron.SimplSharpPro.DeviceSupport, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DeviceSupport.dll</HintPath>
</Reference>
<Reference Include="Crestron.SimplSharpPro.DM, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DM.dll</HintPath>
</Reference>
<Reference Include="Crestron.SimplSharpPro.EthernetCommunications, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.EthernetCommunications.dll</HintPath>
</Reference>
<Reference Include="Crestron.SimplSharpPro.Fusion, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Fusion.dll</HintPath>
</Reference>
<Reference Include="Crestron.SimplSharpPro.Gateways, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Gateways.dll</HintPath>
</Reference>
<Reference Include="Crestron.SimplSharpPro.GeneralIO, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.GeneralIO.dll</HintPath>
</Reference>
<Reference Include="Crestron.SimplSharpPro.Remotes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Remotes.dll</HintPath>
</Reference>
<Reference Include="Crestron.SimplSharpPro.ThreeSeriesCards, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.ThreeSeriesCards.dll</HintPath>
</Reference>
<Reference Include="Crestron.SimplSharpPro.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="PepperDash_Core, Version=1.2.1.30543, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll</HintPath>
</Reference>
<Reference Include="SimplSharpCustomAttributesInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SimplSharpCWSHelperInterface, Version=2.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCWSHelperInterface.dll</HintPath>
</Reference>
<Reference Include="SimplSharpHelperInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SimplSharpNewtonsoft, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll</HintPath>
</Reference>
<Reference Include="SimplSharpPro, Version=1.5.3.17, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SimplSharpReflectionInterface, Version=1.0.5583.25238, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath>
</Reference>
<Reference Include="SimplSharpTimerEventInterface, Version=1.0.6197.20052, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpTimerEventInterface.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
</ItemGroup>
<ItemGroup>
<Compile Include="Bridges\BridgeBase.cs" />
<Compile Include="Bridges\IBridge.cs" />
<Compile Include="Bridges\JoinMaps\AirMediaControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\AppleTvJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\GenericIrControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\HdPsXxxControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\IAnalogInputJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\IDigitalOutputJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\PduJoinMapBase.cs" />
<Compile Include="Bridges\JoinMaps\C2nRthsControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\CameraControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\CenOdtOccupancySensorBaseJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DigitalLoggerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DisplayControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmBladeChassisControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmChassisControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmpsAudioOutputControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmpsMicrophoneControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmpsRoutingControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmRmcControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmTxControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\GenericLightingJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\GenericRelayControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\GlsOccupancySensorBaseJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\GlsPartitionSensorJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\HdMdNxM4kEControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\HdMdxxxCEControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\Hrxxx0WirelessRemoteControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\IBasicCommunicationJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\IDigitalInputJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\IRBlurayBaseJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\SetTopBoxControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\StatusSignControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\SystemMonitorJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\VideoCodecControllerJoinMap.cs" />
<Compile Include="Comm and IR\CecPortController.cs" />
<Compile Include="Comm and IR\CommFactory.cs" />
<Compile Include="Comm and IR\CommunicationExtras.cs" />
<Compile Include="Comm and IR\ComPortController.cs" />
<Compile Include="Comm and IR\ComSpecJsonConverter.cs" />
<Compile Include="Comm and IR\ConsoleCommMockDevice.cs" />
<Compile Include="Comm and IR\GenericComm.cs" />
<Compile Include="Comm and IR\GenericHttpClient.cs" />
<Compile Include="Comm and IR\IRPortHelper.cs" />
<Compile Include="Config\Essentials\ConfigUpdater.cs" />
<Compile Include="Config\Essentials\ConfigReader.cs" />
<Compile Include="Config\Essentials\ConfigWriter.cs" />
<Compile Include="Config\Essentials\EssentialsConfig.cs" />
<Compile Include="Config\SourceDevicePropertiesConfigBase.cs" />
<Compile Include="Crestron IO\C2nIo\C2nIoController.cs" />
<Compile Include="Crestron IO\C2nRts\C2nRthsController.cs" />
<Compile Include="Crestron IO\Cards\C3CardControllerBase.cs" />
<Compile Include="Crestron IO\Cards\C3Com3Controller.cs" />
<Compile Include="Crestron IO\Cards\C3Io16Controller.cs" />
<Compile Include="Crestron IO\Cards\C3Ir8Controller.cs" />
<Compile Include="Crestron IO\Cards\C3Ry16Controller.cs" />
<Compile Include="Crestron IO\Cards\C3Ry8Controller.cs" />
<Compile Include="Crestron IO\Cards\CenCi31Controller.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Crestron IO\Cards\CenCi33Controller.cs" />
<Compile Include="Crestron IO\Cards\InternalCardCageController.cs" />
<Compile Include="Crestron IO\DinCenCn\DinCenCnController.cs" />
<Compile Include="Crestron IO\DinCenCn\IHasCresnetBranches.cs" />
<Compile Include="Crestron IO\DinIo8\DinIo8Controller.cs" />
<Compile Include="Crestron IO\Inputs\CenIoDigIn104Controller.cs" />
<Compile Include="Crestron IO\Inputs\GenericVersiportAnalogInputDevice.cs" />
<Compile Include="Crestron IO\Inputs\GenericDigitalInputDevice.cs" />
<Compile Include="Crestron IO\Inputs\GenericVersiportInputDevice.cs" />
<Compile Include="Crestron IO\Inputs\IAnalogInput.cs" />
<Compile Include="Crestron IO\Inputs\IDigitalInput.cs" />
<Compile Include="Crestron IO\IOPortConfig.cs" />
<Compile Include="Crestron IO\Ir\CenIoIr104Controller.cs" />
<Compile Include="Crestron IO\Outputs\GenericVersiportOutputDevice.cs" />
<Compile Include="Crestron IO\Outputs\IDigitalOutput.cs" />
<Compile Include="Crestron IO\Relay\CenIoRy104Controller.cs" />
<Compile Include="Crestron IO\Relay\GenericRelayDevice.cs" />
<Compile Include="Crestron IO\Relay\ISwitchedOutput.cs" />
<Compile Include="Crestron IO\StatusSign\StatusSignController.cs" />
<Compile Include="Device Info\NetworkDeviceHelpers.cs" />
<Compile Include="Devices\PowerInterfaces.cs" />
<Compile Include="Web\RequestHandlers\AppDebugRequestHandler.cs" />
<Compile Include="Web\RequestHandlers\GetFeedbacksForDeviceRequestHandler.cs" />
<Compile Include="Web\EssentialsWebApiHelpers.cs" />
<Compile Include="Web\RequestHandlers\GetTypesByFilterRequestHandler.cs" />
<Compile Include="Web\RequestHandlers\GetJoinMapForDeviceKeyRequestHandler.cs" />
<Compile Include="Web\RequestHandlers\DefaultRequestHandler.cs" />
<Compile Include="Web\RequestHandlers\DevListRequestHandler.cs" />
<Compile Include="Web\RequestHandlers\DevPropsRequestHandler.cs" />
<Compile Include="Web\RequestHandlers\DevJsonRequestHandler.cs" />
<Compile Include="Web\RequestHandlers\SetDeviceStreamDebugRequestHandler.cs" />
<Compile Include="Web\RequestHandlers\DisableAllStreamDebugRequestHandler.cs" />
<Compile Include="Web\RequestHandlers\ShowConfigRequestHandler.cs" />
<Compile Include="Web\RequestHandlers\GetTypesRequestHandler.cs" />
<Compile Include="Web\RequestHandlers\GetJoinMapForBridgeKeyRequestHandler.cs" />
<Compile Include="Web\EssemtialsWebApi.cs" />
<Compile Include="Web\EssentialsWebApiFactory.cs" />
<Compile Include="Web\EssentialsWebApiPropertiesConfig.cs" />
<Compile Include="Web\RequestHandlers\ReportVersionsRequestHandler.cs" />
<Compile Include="Device Info\DeviceInfo.cs" />
<Compile Include="Device Info\DeviceInfoEventArgs.cs" />
<Compile Include="Device Info\IDeviceInfoProvider.cs" />
<Compile Include="Devices\CodecInterfaces.cs" />
<Compile Include="Devices\CrestronProcessor.cs" />
<Compile Include="Devices\DestinationListItem.cs" />
<Compile Include="Devices\DeviceApiBase.cs" />
<Compile Include="Devices\DeviceFeedbackExtensions.cs" />
<Compile Include="Devices\EssentialsBridgeableDevice.cs" />
<Compile Include="Devices\EssentialsDevice.cs" />
<Compile Include="Devices\GenericIRController.cs" />
<Compile Include="Devices\IDspPreset.cs" />
<Compile Include="Devices\IProjectorInterfaces.cs" />
<Compile Include="Devices\IReconfigurableDevice.cs" />
<Compile Include="Devices\PC\InRoomPc.cs" />
<Compile Include="Devices\PC\Laptop.cs" />
<Compile Include="Devices\PduInterfaces.cs" />
<Compile Include="Devices\ReconfigurableDevice.cs" />
<Compile Include="Devices\VolumeDeviceChangeEventArgs.cs" />
<Compile Include="DeviceTypeInterfaces\IPasswordPrompt.cs" />
<Compile Include="DeviceTypeInterfaces\ITvPresetsProvider.cs" />
<Compile Include="DeviceTypeInterfaces\LanguageLabel.cs" />
<Compile Include="DeviceTypeInterfaces\ILanguageProvider.cs" />
<Compile Include="DeviceTypeInterfaces\IHasBranding.cs" />
<Compile Include="DeviceTypeInterfaces\ILanguageDefinition.cs" />
<Compile Include="DeviceTypeInterfaces\IHasFarEndContentStatus.cs" />
<Compile Include="DeviceTypeInterfaces\IHasPhoneDialing.cs" />
<Compile Include="DeviceTypeInterfaces\IMobileControl.cs" />
<Compile Include="Extensions\JsonExtensions.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Factory\DeviceFactory.cs" />
<Compile Include="Factory\IDeviceFactory.cs" />
<Compile Include="Factory\ReadyEventArgs.cs" />
<Compile Include="Feedbacks\BoolFeedback.cs" />
<Compile Include="Feedbacks\FeedbackCollection.cs" />
<Compile Include="Feedbacks\FeedbackEventArgs.cs" />
<Compile Include="Feedbacks\IntFeedback.cs" />
<Compile Include="Feedbacks\SerialFeedback.cs" />
<Compile Include="Feedbacks\StringFeedback.cs" />
<Compile Include="File\FileIO.cs" />
<Compile Include="Fusion\EssentialsHuddleSpaceFusionSystemControllerBase.cs" />
<Compile Include="Fusion\FusionCustomPropertiesBridge.cs" />
<Compile Include="Fusion\FusionEventHandlers.cs" />
<Compile Include="Fusion\FusionProcessorQueries.cs" />
<Compile Include="Fusion\EssentialsHuddleSpaceRoomFusionRoomJoinMap.cs" />
<Compile Include="Fusion\FusionRviDataClasses.cs" />
<Compile Include="Gateways\CenRfgwController.cs" />
<Compile Include="Gateways\EssentialsRfGatewayConfig.cs" />
<Compile Include="Global\EthernetAdapterInfo.cs" />
<Compile Include="Interfaces\ILogStrings.cs" />
<Compile Include="Interfaces\ILogStringsWithLevel.cs" />
<Compile Include="Occupancy\GlsOccupancySensorPropertiesConfig.cs" />
<Compile Include="Occupancy\GlsOirOccupancySensorController.cs" />
<Compile Include="PartitionSensor\EssentialsPartitionController.cs" />
<Compile Include="PartitionSensor\GlsPartitionSensorPropertiesConfig.cs" />
<Compile Include="PartitionSensor\IPartitionStateProvider.cs" />
<Compile Include="Occupancy\OccupancyAggregatorConfig.cs" />
<Compile Include="Queues\ComsMessage.cs" />
<Compile Include="Queues\ProcessStringMessage.cs" />
<Compile Include="Queues\GenericQueue.cs" />
<Compile Include="Global\JobTimer.cs" />
<Compile Include="Global\Scheduler.cs" />
<Compile Include="Queues\IQueue.cs" />
<Compile Include="JoinMaps\JoinMapBase.cs" />
<Compile Include="Lighting\Lighting Interfaces.cs" />
<Compile Include="Lighting\LightingBase.cs" />
<Compile Include="Monitoring\SystemMonitorController.cs" />
<Compile Include="Microphone Privacy\MicrophonePrivacyController.cs" />
<Compile Include="Microphone Privacy\MicrophonePrivacyControllerConfig.cs" />
<Compile Include="Occupancy\CenOdtOccupancySensorBaseController.cs" />
<Compile Include="Occupancy\GlsOccupancySensorBaseController.cs" />
<Compile Include="Occupancy\GlsOdtOccupancySensorController.cs" />
<Compile Include="Occupancy\IOccupancyStatusProviderAggregator.cs" />
<Compile Include="PartitionSensor\GlsPartitionSensorController.cs" />
<Compile Include="Plugins\PluginLoader.cs" />
<Compile Include="Presets\PresetBase.cs" />
<Compile Include="Plugins\IPluginDeviceFactory.cs" />
<Compile Include="Queues\IQueueMessage.cs" />
<Compile Include="Ramps and Increments\ActionIncrementer.cs" />
<Compile Include="Config\BasicConfig.cs" />
<Compile Include="Config\ConfigPropertiesHelpers.cs" />
<Compile Include="Config\InfoConfig.cs" />
<Compile Include="Config\DeviceConfig.cs" />
<Compile Include="Devices\DisplayUiConstants.cs" />
<Compile Include="Devices\IUsageTracking.cs" />
<Compile Include="Devices\DeviceJsonApi.cs" />
<Compile Include="Devices\SourceListItem.cs" />
<Compile Include="DeviceTypeInterfaces\IDisplayBasic.cs" />
<Compile Include="DeviceTypeInterfaces\IDumbSource.cs" />
<Compile Include="DeviceTypeInterfaces\IWarmingCooling.cs" />
<Compile Include="DeviceTypeInterfaces\IDiscPlayerControls.cs" />
<Compile Include="DeviceTypeInterfaces\IPower.cs" />
<Compile Include="DeviceTypeInterfaces\IUiDisplayInfo.cs" />
<Compile Include="DeviceTypeInterfaces\ISetTopBoxControls.cs" />
<Compile Include="DeviceTypeInterfaces\IChannel.cs" />
<Compile Include="DeviceTypeInterfaces\IColorFunctions.cs" />
<Compile Include="DeviceTypeInterfaces\IDPad.cs" />
<Compile Include="DeviceTypeInterfaces\IDvr.cs" />
<Compile Include="DeviceTypeInterfaces\Template.cs" />
<Compile Include="DeviceTypeInterfaces\ITransport.cs" />
<Compile Include="Devices\GenericMonitoredTcpDevice.cs" />
<Compile Include="DeviceTypeInterfaces\INumeric.cs" />
<Compile Include="Devices\IVolumeAndAudioInterfaces.cs" />
<Compile Include="Display\BasicIrDisplay.cs" />
<Compile Include="Feedbacks\BoolFeedbackOneShot.cs" />
<Compile Include="Ramps and Increments\NumericalHelpers.cs" />
<Compile Include="Ramps and Increments\UshortSigIncrementer.cs" />
<Compile Include="Remotes\ButtonExtensions.cs" />
<Compile Include="Remotes\CrestronRemotePropertiesConfig.cs" />
<Compile Include="Remotes\Hrxx0WirelessRemoteController.cs" />
<Compile Include="Room\Behaviours\RoomOnToDefaultSourceWhenOccupied.cs" />
<Compile Include="Room\Combining\EssentialsRoomCombiner.cs" />
<Compile Include="Room\Combining\EssentialsRoomCombinerPropertiesConfig.cs" />
<Compile Include="Room\Combining\IEssentialsRoomCombiner.cs" />
<Compile Include="Room\Combining\RoomCombinationScenario.cs" />
<Compile Include="Room\EssentialsRoomBase.cs" />
<Compile Include="Room\Config\EssentialsRoomScheduledEventsConfig.cs" />
<Compile Include="Room\IEssentialsRoom.cs" />
<Compile Include="Room\Interfaces.cs" />
<Compile Include="Room\iOccupancyStatusProvider.cs" />
<Compile Include="Routing\DummyRoutingInputsDevice.cs" />
<Compile Include="Routing\ICardPortsDevice.cs" />
<Compile Include="InUseTracking\IInUseTracking.cs" />
<Compile Include="InUseTracking\InUseTracking.cs" />
<Compile Include="Routing\IRoutingInputsExtensions.cs" />
<Compile Include="Monitoring\StatusMonitorCollection.cs" />
<Compile Include="Monitoring\CrestronGenericBaseCommunicationMonitor.cs" />
<Compile Include="Monitoring\StatusMonitorBase.cs" />
<Compile Include="Monitoring\Interfaces.cs" />
<Compile Include="Monitoring\GenericCommunicationMonitor.cs" />
<Compile Include="Devices\AudioInterfaces.cs" />
<Compile Include="Devices\IAttachVideoStatusExtensions.cs" />
<Compile Include="Devices\IHasFeedbacks.cs" />
<Compile Include="Devices\SmartObjectBaseTypes.cs" />
<Compile Include="Devices\PresentationDeviceType.cs" />
<Compile Include="Display\MockDisplay.cs" />
<Compile Include="Ethernet\EthernetStatistics.cs" />
<Compile Include="Global\Global.cs" />
<Compile Include="License\EssentialsLicenseManager.cs" />
<Compile Include="Feedbacks\BoolOutputLogicals.cs" />
<Compile Include="Presets\Interfaces.cs" />
<Compile Include="Presets\PresetsListSubpageReferenceListItem.cs" />
<Compile Include="Presets\DevicePresetsView.cs" />
<Compile Include="Presets\PresetChannel.cs" />
<Compile Include="Presets\DevicePresets.cs" />
<Compile Include="Routing\RoutingInterfaces.cs" />
<Compile Include="Routing\RoutingPort.cs" />
<Compile Include="Routing\RoutingPortCollection.cs" />
<Compile Include="Feedbacks\BoolFeedbackPulseExtender.cs" />
<Compile Include="Routing\RoutingPortNames.cs" />
<Compile Include="Routing\TieLineConfig.cs" />
<Compile Include="Secrets\CrestronGlobalSecretsProvider.cs" />
<Compile Include="Secrets\CrestronLocalSecretsProvider.cs" />
<Compile Include="Secrets\CrestronSecret.cs" />
<Compile Include="Secrets\Interfaces.cs" />
<Compile Include="Secrets\SecretsManager.cs" />
<Compile Include="Secrets\SecretsPropertiesConfig.cs" />
<Compile Include="Shades\Shade Interfaces.cs" />
<Compile Include="Shades\ShadeBase.cs" />
<Compile Include="Shades\ShadeController.cs" />
<Compile Include="SmartObjects\SmartObjectNumeric.cs" />
<Compile Include="SmartObjects\SmartObjectDynamicList.cs" />
<Compile Include="SmartObjects\SmartObjectDPad.cs" />
<Compile Include="SmartObjects\SmartObjectHelperBase.cs" />
<Compile Include="Routing\TieLine.cs" />
<Compile Include="Queues\StringResponseProcessor.cs" />
<Compile Include="Timers\CountdownTimer.cs" />
<Compile Include="Timers\RetriggerableTimer.cs" />
<Compile Include="Touchpanels\CrestronTouchpanelPropertiesConfig.cs" />
<Compile Include="Touchpanels\Interfaces.cs" />
<Compile Include="Touchpanels\Keyboards\HabaneroKeyboardController.cs" />
<Compile Include="Touchpanels\Mpc3Touchpanel.cs" />
<Compile Include="Touchpanels\TriListExtensions.cs" />
<Compile Include="UI PageManagers\BlurayPageManager.cs" />
<Compile Include="UI PageManagers\SetTopBoxThreePanelPageManager.cs" />
<Compile Include="UI PageManagers\SinglePageManager.cs" />
<Compile Include="UI PageManagers\PageManager.cs" />
<Compile Include="UI PageManagers\SetTopBoxTwoPanelPageManager.cs" />
<Compile Include="UI\TouchpanelBase.cs" />
<Compile Include="Utilities\ActionSequence.cs" />
<Compile Include="VideoStatus\VideoStatusOutputs.cs" />
<Compile Include="Crestron\CrestronGenericBaseDevice.cs" />
<Compile Include="DeviceControlsParentInterfaces\IPresentationSource.cs" />
<Compile Include="Devices\DeviceManager.cs" />
<Compile Include="Devices\IrOutputPortController.cs" />
<Compile Include="Display\DisplayBase.cs" />
<Compile Include="Feedbacks\FeedbackBase.cs" />
<Compile Include="Room\Room.cs" />
<Compile Include="SmartObjects\SubpageReferencList\SourceListSubpageReferenceList.cs" />
<Compile Include="Touchpanels\ModalDialog.cs" />
<Compile Include="TriListBridges\HandlerBridge.cs" />
<Compile Include="Devices\FIND HOMES Interfaces.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SigHelper.cs" />
<Compile Include="SmartObjects\SubpageReferencList\SubpageReferenceList.cs" />
<Compile Include="SmartObjects\SubpageReferencList\SubpageReferenceListItem.cs" />
<None Include="app.config" />
<None Include="Properties\ControlSystem.cfg" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CompactFramework.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
</VisualStudio>
</ProjectExtensions>
<PropertyGroup>
<PostBuildEvent>rem S# Pro preparation will execute after these operations</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@@ -81,12 +81,10 @@ namespace PepperDash.Essentials.Core
foreach (var action in activationActions)
{
this.LogInformation("Running Activation action {@action}", action);
tasks.Add(DeviceJsonApi.DoDeviceActionAsync(action));
await DeviceJsonApi.DoDeviceActionAsync(action);
}
}
await Task.WhenAll(tasks);
IsActive = true;
}
@@ -101,12 +99,10 @@ namespace PepperDash.Essentials.Core
foreach (var action in deactivationActions)
{
this.LogInformation("Running deactivation action {actionDeviceKey}:{actionMethod}", action.DeviceKey, action.MethodName);
tasks.Add( DeviceJsonApi.DoDeviceActionAsync(action));
await DeviceJsonApi.DoDeviceActionAsync(action);
}
}
await Task.WhenAll(tasks);
IsActive = false;
}

View File

@@ -24,6 +24,7 @@ namespace PepperDash.Essentials.Room.Config
//switch on emergency type here. Right now only contact and shutdown
var e = new EssentialsRoomEmergencyContactClosure(room.Key + "-emergency", props.Emergency, room);
DeviceManager.AddDevice(e);
return e;
}
return null;
}

View File

@@ -16,7 +16,7 @@
public class EssentialsRoomEmergencyTriggerConfig
{
/// <summary>
/// contact,
/// contact,versiport
/// </summary>
public string Type { get; set; }
/// <summary>

View File

@@ -4,12 +4,16 @@ using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials.Core
{
public class EssentialsRoomEmergencyContactClosure : EssentialsRoomEmergencyBase
public class EssentialsRoomEmergencyContactClosure : EssentialsRoomEmergencyBase, IEssentialsRoomEmergency
{
public event EventHandler<EventArgs> EmergencyStateChange;
IEssentialsRoom Room;
string Behavior;
bool TriggerOnClose;
public bool InEmergency { get; private set; }
public EssentialsRoomEmergencyContactClosure(string key, EssentialsRoomEmergencyConfig config, IEssentialsRoom room) :
base(key)
{
@@ -25,14 +29,49 @@ namespace PepperDash.Essentials.Core
cs.DigitalInputPorts[portNum].StateChange += EsentialsRoomEmergencyContactClosure_StateChange;
}
}
else if (config.Trigger.Type.Equals("versiport", StringComparison.OrdinalIgnoreCase))
{
var portNum = (uint)config.Trigger.Number;
if (portNum <= cs.NumberOfVersiPorts)
{
cs.VersiPorts[portNum].Register();
cs.VersiPorts[portNum].SetVersiportConfiguration(eVersiportConfiguration.DigitalInput);
cs.VersiPorts[portNum].DisablePullUpResistor = true;
cs.VersiPorts[portNum].VersiportChange += EssentialsRoomEmergencyContactClosure_VersiportChange;
}
}
Behavior = config.Behavior;
TriggerOnClose = config.Trigger.TriggerOnClose;
}
private void EssentialsRoomEmergencyContactClosure_VersiportChange(Versiport port, VersiportEventArgs args)
{
if (args.Event == eVersiportEvent.DigitalInChange)
{
ContactClosure_StateChange(port.DigitalIn);
}
}
void EsentialsRoomEmergencyContactClosure_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args)
{
if (args.State && TriggerOnClose || !args.State && !TriggerOnClose)
ContactClosure_StateChange(args.State);
}
void ContactClosure_StateChange(bool portState)
{
if (portState && TriggerOnClose || !portState && !TriggerOnClose)
{
InEmergency = true;
if (EmergencyStateChange != null)
EmergencyStateChange(this, new EventArgs());
RunEmergencyBehavior();
}
else
{
InEmergency = false;
if (EmergencyStateChange != null)
EmergencyStateChange(this, new EventArgs());
}
}
/// <summary>
@@ -44,4 +83,14 @@ namespace PepperDash.Essentials.Core
Room.Shutdown();
}
}
/// <summary>
/// Describes the functionality of a room emergency contact closure
/// </summary>
public interface IEssentialsRoomEmergency
{
event EventHandler<EventArgs> EmergencyStateChange;
bool InEmergency { get; }
}
}

View File

@@ -1,4 +1,6 @@
using Serilog.Events;
using PepperDash.Essentials.Core.Queues;
using PepperDash.Essentials.Core.Routing;
using Serilog.Events;
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -17,6 +19,8 @@ namespace PepperDash.Essentials.Core
{
private static readonly Dictionary<string, RouteRequest> RouteRequests = new Dictionary<string, RouteRequest>();
private static readonly GenericQueue routeRequestQueue = new GenericQueue("routingQueue");
/// <summary>
/// Gets any existing RouteDescriptor for a destination, clears it using ReleaseRoute
/// and then attempts a new Route and if sucessful, stores that RouteDescriptor
@@ -33,6 +37,15 @@ namespace PepperDash.Essentials.Core
ReleaseAndMakeRoute(destination, source, signalType, inputPort, outputPort);
}
public static void ReleaseRoute(this IRoutingInputs destination)
{
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, string.Empty));
}
public static void ReleaseRoute(this IRoutingInputs destination, string inputPortKey)
{
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, inputPortKey));
}
public static void RemoveRouteRequestForDestination(string destinationKey)
{
@@ -45,122 +58,6 @@ namespace PepperDash.Essentials.Core
Debug.LogMessage(LogEventLevel.Information, messageTemplate, null, destinationKey);
}
private static void ReleaseAndMakeRoute(IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort = null, RoutingOutputPort sourcePort = null)
{
if (destination == null) throw new ArgumentNullException(nameof(destination));
if (source == null) throw new ArgumentNullException(nameof(source));
if (destinationPort == null) Debug.LogMessage(LogEventLevel.Information, "Destination port is null");
if (sourcePort == null) Debug.LogMessage(LogEventLevel.Information, "Source port is null");
var routeRequest = new RouteRequest
{
Destination = destination,
DestinationPort = destinationPort,
Source = source,
SourcePort = sourcePort,
SignalType = signalType
};
var coolingDevice = destination as IWarmingCooling;
//We already have a route request for this device, and it's a cooling device and is cooling
if (RouteRequests.TryGetValue(destination.Key, out RouteRequest existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true)
{
coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown;
coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown;
RouteRequests[destination.Key] = routeRequest;
Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is cooling down and already has a routing request stored. Storing new route request to route to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key);
return;
}
//New Request
if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true)
{
coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown;
RouteRequests.Add(destination.Key, routeRequest);
Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is cooling down. Storing route request to route to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key);
return;
}
if (RouteRequests.ContainsKey(destination.Key) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == false)
{
var handledRequest = RouteRequests[destination.Key];
coolingDevice.IsCoolingDownFeedback.OutputChange -= handledRequest.HandleCooldown;
RouteRequests.Remove(destination.Key);
Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is NOT cooling down. Removing stored route request and routing to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key);
}
destination.ReleaseRoute(destinationPort?.Key ?? string.Empty);
RunRouteRequest(routeRequest);
}
private static void RunRouteRequest(RouteRequest request)
{
if (request.Source == null)
return;
var (audioOrSingleRoute, videoRoute) = request.Destination.GetRouteToSource(request.Source, request.SignalType, request.DestinationPort, request.SourcePort);
if (audioOrSingleRoute == null && videoRoute == null)
return;
RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(audioOrSingleRoute);
if (videoRoute != null)
{
RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(videoRoute);
}
Debug.LogMessage(LogEventLevel.Verbose, "Executing full route", request.Destination);
audioOrSingleRoute.ExecuteRoutes();
videoRoute?.ExecuteRoutes();
}
public static void ReleaseRoute(this IRoutingInputs destination)
{
ReleaseRoute(destination, string.Empty);
}
/// <summary>
/// Will release the existing route on the destination, if it is found in
/// RouteDescriptorCollection.DefaultCollection
/// </summary>
/// <param name="destination"></param>
public static void ReleaseRoute(this IRoutingInputs destination, string inputPortKey)
{
Debug.LogMessage(LogEventLevel.Information, "Release route for {inputPortKey}", destination, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
if (RouteRequests.TryGetValue(destination.Key, out RouteRequest existingRequest) && destination is IWarmingCooling)
{
var coolingDevice = destination as IWarmingCooling;
coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRequest.HandleCooldown;
}
RouteRequests.Remove(destination.Key);
var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination, inputPortKey);
if (current != null)
{
Debug.LogMessage(LogEventLevel.Debug, "Releasing current route: {0}", destination, current.Source.Key);
current.ReleaseRoutes();
}
}
/// <summary>
/// Builds a RouteDescriptor that contains the steps necessary to make a route between devices.
/// Routes of type AudioVideo will be built as two separate routes, audio and video. If
@@ -179,7 +76,8 @@ namespace PepperDash.Essentials.Core
if (!destination.GetRouteToSource(source, null, null, signalType, 0, singleTypeRouteDescriptor, destinationPort, sourcePort))
singleTypeRouteDescriptor = null;
foreach (var route in singleTypeRouteDescriptor.Routes)
var routes = singleTypeRouteDescriptor?.Routes ?? new List<RouteSwitchDescriptor>();
foreach (var route in routes)
{
Debug.LogMessage(LogEventLevel.Verbose, "Route for device: {route}", destination, route.ToString());
}
@@ -222,6 +120,126 @@ namespace PepperDash.Essentials.Core
return (audioRouteDescriptor, videoRouteDescriptor);
}
private static void ReleaseAndMakeRoute(IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort = null, RoutingOutputPort sourcePort = null)
{
if (destination == null) throw new ArgumentNullException(nameof(destination));
if (source == null) throw new ArgumentNullException(nameof(source));
if (destinationPort == null) Debug.LogMessage(LogEventLevel.Information, "Destination port is null");
if (sourcePort == null) Debug.LogMessage(LogEventLevel.Information, "Source port is null");
var routeRequest = new RouteRequest
{
Destination = destination,
DestinationPort = destinationPort,
Source = source,
SourcePort = sourcePort,
SignalType = signalType
};
var coolingDevice = destination as IWarmingCooling;
//We already have a route request for this device, and it's a cooling device and is cooling
if (RouteRequests.TryGetValue(destination.Key, out RouteRequest existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true)
{
coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown;
coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown;
RouteRequests[destination.Key] = routeRequest;
Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is cooling down and already has a routing request stored. Storing new route request to route to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key);
return;
}
//New Request
if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true)
{
coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown;
RouteRequests.Add(destination.Key, routeRequest);
Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is cooling down. Storing route request to route to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key);
return;
}
if (RouteRequests.ContainsKey(destination.Key) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == false)
{
var handledRequest = RouteRequests[destination.Key];
coolingDevice.IsCoolingDownFeedback.OutputChange -= handledRequest.HandleCooldown;
RouteRequests.Remove(destination.Key);
Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is NOT cooling down. Removing stored route request and routing to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key);
}
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination,destinationPort?.Key ?? string.Empty));
routeRequestQueue.Enqueue(new RouteRequestQueueItem(RunRouteRequest, routeRequest));
}
private static void RunRouteRequest(RouteRequest request)
{
try
{
if (request.Source == null)
return;
var (audioOrSingleRoute, videoRoute) = request.Destination.GetRouteToSource(request.Source, request.SignalType, request.DestinationPort, request.SourcePort);
if (audioOrSingleRoute == null && videoRoute == null)
return;
RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(audioOrSingleRoute);
if (videoRoute != null)
{
RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(videoRoute);
}
Debug.LogMessage(LogEventLevel.Verbose, "Executing full route", request.Destination);
audioOrSingleRoute.ExecuteRoutes();
videoRoute?.ExecuteRoutes();
} catch(Exception ex)
{
Debug.LogMessage(ex, "Exception Running Route Request {request}", null, request);
}
}
/// <summary>
/// Will release the existing route on the destination, if it is found in
/// RouteDescriptorCollection.DefaultCollection
/// </summary>
/// <param name="destination"></param>
private static void ReleaseRouteInternal(IRoutingInputs destination, string inputPortKey)
{
try
{
Debug.LogMessage(LogEventLevel.Information, "Release route for '{destination}':'{inputPortKey}'", destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
if (RouteRequests.TryGetValue(destination.Key, out RouteRequest existingRequest) && destination is IWarmingCooling)
{
var coolingDevice = destination as IWarmingCooling;
coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRequest.HandleCooldown;
}
RouteRequests.Remove(destination.Key);
var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination, inputPortKey);
if (current != null)
{
Debug.LogMessage(LogEventLevel.Information, "Releasing current route: {0}", destination, current.Source.Key);
current.ReleaseRoutes();
}
} catch (Exception ex)
{
Debug.LogMessage(ex, "Exception releasing route for '{destination}':'{inputPortKey}'",null, destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
}
}
/// <summary>
/// The recursive part of this. Will stop on each device, search its inputs for the
/// desired source and if not found, invoke this function for the each input port

View File

@@ -12,19 +12,19 @@ namespace PepperDash.Essentials.Core
/// Represents an collection of individual route steps between Source and Destination
/// </summary>
public class RouteDescriptor
{
public IRoutingInputs Destination { get; private set; }
{
public IRoutingInputs Destination { get; private set; }
public RoutingInputPort InputPort { get; private set; }
public IRoutingOutputs Source { get; private set; }
public eRoutingSignalType SignalType { get; private set; }
public List<RouteSwitchDescriptor> Routes { get; private set; }
public IRoutingOutputs Source { get; private set; }
public eRoutingSignalType SignalType { get; private set; }
public List<RouteSwitchDescriptor> Routes { get; private set; }
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType):this(source,destination, null, signalType)
{
}
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType) : this(source, destination, null, signalType)
{
}
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, RoutingInputPort inputPort, eRoutingSignalType signalType)
{
@@ -35,20 +35,20 @@ namespace PepperDash.Essentials.Core
Routes = new List<RouteSwitchDescriptor>();
}
/// <summary>
/// Executes all routes described in this collection. Typically called via
/// extension method IRoutingInputs.ReleaseAndMakeRoute()
/// </summary>
public void ExecuteRoutes()
{
foreach (var route in Routes)
{
Debug.LogMessage(LogEventLevel.Verbose, "ExecuteRoutes: {0}",null, route.ToString());
/// <summary>
/// Executes all routes described in this collection. Typically called via
/// extension method IRoutingInputs.ReleaseAndMakeRoute()
/// </summary>
public void ExecuteRoutes()
{
foreach (var route in Routes)
{
Debug.LogMessage(LogEventLevel.Verbose, "ExecuteRoutes: {0}", null, route.ToString());
if (route.SwitchingDevice is IRoutingSinkWithSwitching sink)
{
{
sink.ExecuteSwitch(route.InputPort.Selector);
continue;
continue;
}
if (route.SwitchingDevice is IRouting switchingDevice)
@@ -59,15 +59,15 @@ namespace PepperDash.Essentials.Core
Debug.LogMessage(LogEventLevel.Verbose, "Output port {0} routing. Count={1}", null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue);
}
}
}
}
}
/// <summary>
/// Releases all routes in this collection. Typically called via
/// extension method IRoutingInputs.ReleaseAndMakeRoute()
/// </summary>
public void ReleaseRoutes()
{
/// <summary>
/// Releases all routes in this collection. Typically called via
/// extension method IRoutingInputs.ReleaseAndMakeRoute()
/// </summary>
public void ReleaseRoutes()
{
foreach (var route in Routes.Where(r => r.SwitchingDevice is IRouting))
{
if (route.SwitchingDevice is IRouting switchingDevice)
@@ -77,8 +77,6 @@ namespace PepperDash.Essentials.Core
continue;
}
switchingDevice.ExecuteSwitch(null, route.OutputPort.Selector, SignalType);
if (route.OutputPort.InUseTracker != null)
{
route.OutputPort.InUseTracker.RemoveUser(Destination, "destination-" + SignalType);
@@ -92,12 +90,12 @@ namespace PepperDash.Essentials.Core
}
}
public override string ToString()
{
var routesText = Routes.Select(r => r.ToString()).ToArray();
return string.Format("Route table from {0} to {1}:\r{2}", Source.Key, Destination.Key, string.Join("\r", routesText));
}
}
public override string ToString()
{
var routesText = Routes.Select(r => r.ToString()).ToArray();
return string.Format("Route table from {0} to {1}:\r{2}", Source.Key, Destination.Key, string.Join("\r", routesText));
}
}
/*/// <summary>
/// Represents an collection of individual route steps between Source and Destination

View File

@@ -41,7 +41,7 @@ namespace PepperDash.Essentials.Core
&& RouteDescriptors.Any(t => t.Destination == descriptor.Destination && t.InputPort != null && descriptor.InputPort != null && t.InputPort.Key == descriptor.InputPort.Key))
{
Debug.LogMessage(LogEventLevel.Debug, descriptor.Destination,
"Route to [{0}] already exists in global routes table", descriptor.Source.Key);
"Route to [{0}] already exists in global routes table", descriptor?.Source?.Key);
return;
}
RouteDescriptors.Add(descriptor);
@@ -53,14 +53,14 @@ namespace PepperDash.Essentials.Core
/// <returns>null if no RouteDescriptor for a destination exists</returns>
public RouteDescriptor GetRouteDescriptorForDestination(IRoutingInputs destination)
{
Debug.LogMessage(LogEventLevel.Debug, "Getting route descriptor", destination);
Debug.LogMessage(LogEventLevel.Information, "Getting route descriptor for '{destination}'", destination?.Key ?? null);
return RouteDescriptors.FirstOrDefault(rd => rd.Destination == destination);
}
public RouteDescriptor GetRouteDescriptorForDestinationAndInputPort(IRoutingInputs destination, string inputPortKey)
{
Debug.LogMessage(LogEventLevel.Debug, "Getting route descriptor for {inputPortKey}", destination, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
Debug.LogMessage(LogEventLevel.Information, "Getting route descriptor for '{destination}':'{inputPortKey}'", destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
return RouteDescriptors.FirstOrDefault(rd => rd.Destination == destination && rd.InputPort != null && rd.InputPort.Key == inputPortKey);
}
@@ -70,7 +70,7 @@ namespace PepperDash.Essentials.Core
/// </summary>
public RouteDescriptor RemoveRouteDescriptor(IRoutingInputs destination, string inputPortKey = "")
{
Debug.LogMessage(LogEventLevel.Debug, "Removing route descriptor for {inputPortKey}", destination, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
Debug.LogMessage(LogEventLevel.Information, "Removing route descriptor for '{destination}':'{inputPortKey}'", destination.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
var descr = string.IsNullOrEmpty(inputPortKey)
? GetRouteDescriptorForDestination(destination)
@@ -78,7 +78,7 @@ namespace PepperDash.Essentials.Core
if (descr != null)
RouteDescriptors.Remove(descr);
Debug.LogMessage(LogEventLevel.Debug, "Found route descriptor {routeDescriptor}", destination, descr);
Debug.LogMessage(LogEventLevel.Information, "Found route descriptor {routeDescriptor}", destination, descr);
return descr;
}

View File

@@ -38,5 +38,10 @@ namespace PepperDash.Essentials.Core
Debug.LogMessage(ex, "Exception handling cooldown", Destination);
}
}
public override string ToString()
{
return $"Route {Source?.Key ?? "No Source Device"}:{SourcePort?.Key ?? "auto"} to {Destination?.Key ?? "No Destination Device"}:{DestinationPort?.Key ?? "auto"}";
}
}
}

View File

@@ -0,0 +1,45 @@
using PepperDash.Core;
using PepperDash.Essentials.Core.Queues;
using System;
using Serilog.Events;
namespace PepperDash.Essentials.Core.Routing
{
public class RouteRequestQueueItem : IQueueMessage
{
private readonly Action<RouteRequest> action;
private readonly RouteRequest routeRequest;
public RouteRequestQueueItem(Action<RouteRequest> routeAction, RouteRequest request)
{
action = routeAction;
routeRequest = request;
}
public void Dispatch()
{
Debug.LogMessage(LogEventLevel.Information, "Dispatching route request {routeRequest}", null, routeRequest);
action(routeRequest);
}
}
public class ReleaseRouteQueueItem : IQueueMessage
{
private readonly Action<IRoutingInputs, string> action;
private readonly IRoutingInputs destination;
private readonly string inputPortKey;
public ReleaseRouteQueueItem(Action<IRoutingInputs, string> action, IRoutingInputs destination, string inputPortKey)
{
this.action = action;
this.destination = destination;
this.inputPortKey = inputPortKey;
}
public void Dispatch()
{
Debug.LogMessage(LogEventLevel.Information, "Dispatching release route request for {destination}:{inputPortKey}", null, destination?.Key ?? "no destination", string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
action(destination, inputPortKey);
}
}
}

View File

@@ -4,6 +4,7 @@ using System.Globalization;
using Crestron.SimplSharpPro;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Core.Logging;
using Serilog.Events;
namespace PepperDash.Essentials.Core.Touchpanels
@@ -34,9 +35,9 @@ namespace PepperDash.Essentials.Core.Touchpanels
Debug.LogMessage(LogEventLevel.Information, this, "touchpanel registration response: {0}", registrationResponse);
}
_touchpanel.BaseEvent += _touchpanel_BaseEvent;
_touchpanel.ButtonStateChange += _touchpanel_ButtonStateChange;
_touchpanel.PanelStateChange += _touchpanel_PanelStateChange;
_touchpanel.BaseEvent += Touchpanel_BaseEvent;
_touchpanel.ButtonStateChange += Touchpanel_ButtonStateChange;
_touchpanel.PanelStateChange += Touchpanel_PanelStateChange;
_buttons = buttons;
if (_buttons == null)
@@ -56,6 +57,8 @@ namespace PepperDash.Essentials.Core.Touchpanels
InitializeButton(buttonKey, buttonConfig);
InitializeButtonFeedback(buttonKey, buttonConfig);
}
ListButtons();
});
}
@@ -72,10 +75,9 @@ namespace PepperDash.Essentials.Core.Touchpanels
return;
}
int buttonNumber;
TryParseInt(key, out buttonNumber);
TryParseInt(key, out int buttonNumber);
var buttonEventTypes = config.EventTypes;
var buttonEventTypes = config.EventTypes;
BoolOutputSig enabledFb = null;
BoolOutputSig disabledFb = null;
@@ -159,11 +161,10 @@ namespace PepperDash.Essentials.Core.Touchpanels
return;
}
int buttonNumber;
TryParseInt(key, out buttonNumber);
TryParseInt(key, out int buttonNumber);
// Link up the button feedbacks to the specified device feedback
var buttonFeedback = config.Feedback;
// Link up the button feedbacks to the specified device feedback
var buttonFeedback = config.Feedback;
if (buttonFeedback == null || string.IsNullOrEmpty(buttonFeedback.DeviceKey))
{
Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' feedback not configured, skipping.",
@@ -175,15 +176,14 @@ namespace PepperDash.Essentials.Core.Touchpanels
try
{
var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device;
if (device == null)
{
Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' feedback deviceKey '{1}' not found.",
key, buttonFeedback.DeviceKey);
return;
}
if (!(DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) is Device device))
{
Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' feedback deviceKey '{1}' not found.",
key, buttonFeedback.DeviceKey);
return;
}
deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName);
deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName);
if (deviceFeedback == null)
{
Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' feedbackName property '{1}' not found.",
@@ -222,38 +222,37 @@ namespace PepperDash.Essentials.Core.Touchpanels
}
var boolFeedback = deviceFeedback as BoolFeedback;
var intFeedback = deviceFeedback as IntFeedback;
switch (key)
{
case ("power"):
{
if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackPower);
break;
}
case ("volumeup"):
case ("volumedown"):
case ("volumefeedback"):
{
if (intFeedback != null)
{
var volumeFeedback = intFeedback;
volumeFeedback.LinkInputSig(_touchpanel.VolumeBargraph);
}
break;
}
case ("mute"):
{
if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackMute);
break;
}
default:
{
if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.Feedbacks[(uint)buttonNumber]);
break;
}
}
}
switch (key)
{
case ("power"):
{
boolFeedback?.LinkCrestronFeedback(_touchpanel.FeedbackPower);
break;
}
case ("volumeup"):
case ("volumedown"):
case ("volumefeedback"):
{
if (deviceFeedback is IntFeedback intFeedback)
{
var volumeFeedback = intFeedback;
volumeFeedback.LinkInputSig(_touchpanel.VolumeBargraph);
}
break;
}
case ("mute"):
{
boolFeedback?.LinkCrestronFeedback(_touchpanel.FeedbackMute);
break;
}
default:
{
boolFeedback?.LinkCrestronFeedback(_touchpanel.Feedbacks[(uint)buttonNumber]);
break;
}
}
}
/// <summary>
/// Try parse int helper method
@@ -275,12 +274,12 @@ namespace PepperDash.Essentials.Core.Touchpanels
}
}
private void _touchpanel_BaseEvent(GenericBase device, BaseEventArgs args)
private void Touchpanel_BaseEvent(GenericBase device, BaseEventArgs args)
{
Debug.LogMessage(LogEventLevel.Debug, this, "BaseEvent: eventId-'{0}', index-'{1}'", args.EventId, args.Index);
}
private void _touchpanel_ButtonStateChange(GenericBase device, Crestron.SimplSharpPro.DeviceSupport.ButtonEventArgs args)
private void Touchpanel_ButtonStateChange(GenericBase device, Crestron.SimplSharpPro.DeviceSupport.ButtonEventArgs args)
{
Debug.LogMessage(LogEventLevel.Debug, this, "ButtonStateChange: buttonNumber-'{0}' buttonName-'{1}', buttonState-'{2}'", args.Button.Number, args.Button.Name, args.NewButtonState);
var type = args.NewButtonState.ToString();
@@ -295,7 +294,7 @@ namespace PepperDash.Essentials.Core.Touchpanels
}
}
private void _touchpanel_PanelStateChange(GenericBase device, BaseEventArgs args)
private void Touchpanel_PanelStateChange(GenericBase device, BaseEventArgs args)
{
Debug.LogMessage(LogEventLevel.Debug, this, "PanelStateChange: eventId-'{0}', index-'{1}'", args.EventId, args.Index);
}
@@ -308,7 +307,7 @@ namespace PepperDash.Essentials.Core.Touchpanels
/// <param name="type"></param>
public void Press(string buttonKey, string type)
{
Debug.LogMessage(LogEventLevel.Verbose, this, "Press: buttonKey-'{0}', type-'{1}'", buttonKey, type);
this.LogVerbose("Press: buttonKey-'{buttonKey}', type-'{type}'", buttonKey, type);
// TODO: In future, consider modifying this to generate actions at device activation time
// to prevent the need to dynamically call the method via reflection on each button press
@@ -319,6 +318,17 @@ namespace PepperDash.Essentials.Core.Touchpanels
foreach (var eventType in button.EventTypes[type]) DeviceJsonApi.DoDeviceAction(eventType);
}
public void ListButtons()
{
this.LogVerbose("MPC3 Controller {0} - Available Buttons", Key);
foreach (var button in _buttons)
{
this.LogVerbose("Key: {key}", button.Key);
}
}
}
/// <summary>

View File

@@ -119,23 +119,23 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers
return;
}
var device = DeviceManager.GetDeviceForKey(body.DeviceKey) as IStreamDebugging;
if (device == null)
{
context.Response.StatusCode = 404;
context.Response.StatusDescription = "Not Found";
context.Response.End();
if (!(DeviceManager.GetDeviceForKey(body.DeviceKey) is IStreamDebugging device))
{
context.Response.StatusCode = 404;
context.Response.StatusDescription = "Not Found";
context.Response.End();
return;
}
eStreamDebuggingSetting debugSetting;
return;
}
eStreamDebuggingSetting debugSetting;
try
{
debugSetting = (eStreamDebuggingSetting) Enum.Parse(typeof (eStreamDebuggingSetting), body.Setting, true);
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Exception handling set debug request");
context.Response.StatusCode = 500;
context.Response.StatusDescription = "Internal Server Error";
context.Response.End();
@@ -161,6 +161,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Exception handling set debug request");
context.Response.StatusCode = 500;
context.Response.StatusDescription = "Internal Server Error";
context.Response.End();

View File

@@ -21,7 +21,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
{
public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IHasPowerControlWithFeedback, IBridgeAdvanced, IHasCameraFocusControl, IHasAutoFocusMode
{
CameraViscaPropertiesConfig PropertiesConfig;
private readonly CameraViscaPropertiesConfig PropertiesConfig;
public IBasicCommunication Communication { get; private set; }
@@ -30,7 +30,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// <summary>
/// Used to store the actions to parse inquiry responses as the inquiries are sent
/// </summary>
private CrestronQueue<Action<byte[]>> InquiryResponseQueue;
private readonly CrestronQueue<Action<byte[]>> InquiryResponseQueue;
/// <summary>
/// Camera ID (Default 1)
@@ -45,7 +45,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
public byte PanSpeedFast = 0x13;
public byte TiltSpeedFast = 0x13;
private bool IsMoving;
// private bool IsMoving;
private bool IsZooming;
bool _powerIsOn;
@@ -101,18 +101,17 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom | eCameraCapabilities.Focus;
Communication = comm;
var socket = comm as ISocketStatus;
if (socket != null)
{
// This instance uses IP control
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
}
else
{
// This instance uses RS-232 control
}
if (comm is ISocketStatus socket)
{
// This instance uses IP control
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(Socket_ConnectionChange);
}
else
{
// This instance uses RS-232 control
}
Communication.BytesReceived += new EventHandler<GenericCommMethodReceiveBytesArgs>(Communication_BytesReceived);
Communication.BytesReceived += new EventHandler<GenericCommMethodReceiveBytesArgs>(Communication_BytesReceived);
PowerIsOnFeedback = new BoolFeedback(() => { return PowerIsOn; });
CameraIsOffFeedback = new BoolFeedback(() => { return !PowerIsOn; });
@@ -175,7 +174,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
LinkCameraToApi(this, trilist, joinStart, joinMapKey, bridge);
}
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
void Socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
{
Debug.LogMessage(LogEventLevel.Verbose, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
@@ -449,12 +448,12 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
public void PanLeft()
{
SendPanTiltCommand(new byte[] {0x01, 0x03}, false);
IsMoving = true;
// IsMoving = true;
}
public void PanRight()
{
SendPanTiltCommand(new byte[] { 0x02, 0x03 }, false);
IsMoving = true;
// IsMoving = true;
}
public void PanStop()
{
@@ -463,12 +462,12 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
public void TiltDown()
{
SendPanTiltCommand(new byte[] { 0x03, 0x02 }, false);
IsMoving = true;
// IsMoving = true;
}
public void TiltUp()
{
SendPanTiltCommand(new byte[] { 0x03, 0x01 }, false);
IsMoving = true;
// IsMoving = true;
}
public void TiltStop()
{
@@ -507,7 +506,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
{
StopSpeedTimer();
SendPanTiltCommand(new byte[] { 0x03, 0x03 }, false);
IsMoving = false;
// IsMoving = false;
}
}
public void PositionHome()

View File

@@ -40,9 +40,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec
private int _meetingWarningMinutes = 5;
private Meeting _previousChangedMeeting;
//private Meeting _previousChangedMeeting;
private eMeetingEventChangeType _previousChangeType = eMeetingEventChangeType.Unknown;
//private eMeetingEventChangeType _previousChangeType = eMeetingEventChangeType.Unknown;
public int MeetingWarningMinutes
{
@@ -62,16 +62,11 @@ namespace PepperDash.Essentials.Devices.Common.Codec
set
{
_meetings = value;
var handler = MeetingsListHasChanged;
if (handler != null)
{
handler(this, new EventArgs());
}
MeetingsListHasChanged?.Invoke(this, new EventArgs());
}
}
private CTimer _scheduleChecker;
private readonly CTimer _scheduleChecker;
public CodecScheduleAwareness()
{
@@ -99,12 +94,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec
{
// Add this change type to the NotifiedChangeTypes
meeting.NotifiedChangeTypes |= changeType;
var handler = MeetingEventChange;
if (handler != null)
{
handler(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting });
}
MeetingEventChange?.Invoke(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting });
}
else
{

View File

@@ -4,6 +4,7 @@ using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using Serilog.Events;
using System;
using System.Collections.Generic;
@@ -12,12 +13,7 @@ using Feedback = PepperDash.Essentials.Core.Feedback;
namespace PepperDash.Essentials.Devices.Common.Displays
{
public abstract class DisplayBase : EssentialsDevice
, IHasFeedback
, IRoutingSinkWithSwitching
, IHasPowerControl
, IWarmingCooling
, IUsageTracking
public abstract class DisplayBase : EssentialsDevice, IDisplay
{
private RoutingInputPort _currentInputPort;
public RoutingInputPort CurrentInputPort

View File

@@ -12,7 +12,7 @@ using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.Displays
{
public class MockDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, IBridgeAdvanced, IHasInputs<string, string>, IRoutingSinkWithSwitchingWithInputPort, IHasPowerControlWithFeedback
public class MockDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, IBridgeAdvanced, IHasInputs<string>, IRoutingSinkWithSwitchingWithInputPort, IHasPowerControlWithFeedback
{
public ISelectableItems<string> Inputs { get; private set; }

View File

@@ -16,7 +16,6 @@ using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.Lighting
{
[Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")]
public abstract class LightingBase : EssentialsBridgeableDevice, ILightingScenes
{
#region ILightingScenes Members
@@ -68,12 +67,7 @@ namespace PepperDash.Essentials.Devices.Common.Lighting
else
scene.IsActive = false;
}
var handler = LightingSceneChange;
if (handler != null)
{
handler(this, new LightingSceneChangeEventArgs(CurrentLightingScene));
}
LightingSceneChange?.Invoke(this, new LightingSceneChangeEventArgs(CurrentLightingScene));
}
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart,

View File

@@ -4,15 +4,14 @@
<Configurations>Debug;Release;Debug 4.7.2</Configurations>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>net472;net6</TargetFrameworks>
<TargetFramework>net472</TargetFramework>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<OutputPath>bin\$(Configuration)\</OutputPath>
<AssemblyName>Essentials Devices Common</AssemblyName>
<RootNamespace>PepperDash.Essentials.Devices.Common</RootNamespace>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Title>PepperDash Essentials Devices Common</Title>
<PackageId>PepperDash.Essentials.Devices.Common</PackageId>
<Version>2.0.0-local</Version>
<InformationalVersion>$(Version)</InformationalVersion>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
</PropertyGroup>
@@ -29,7 +28,7 @@
<ProjectReference Include="..\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.20.66" />
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-424" />
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.21.90" />
<PackageReference Include="PepperDashCore" Version="2.0.1" />
</ItemGroup>
</Project>

View File

@@ -28,14 +28,14 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
for(var i = 1; i <= props.OutputCount; i++)
{
var outputPort = new RoutingOutputPort($"{Key}-output{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this);
var outputPort = new RoutingOutputPort($"output{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this);
OutputPorts.Add(outputPort);
}
for(var i = 1; i<= props.ContentInputCount; i++)
{
var inputPort = new RoutingInputPort($"{Key}-contentInput{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, $"contentInput{i}", this);
var inputPort = new RoutingInputPort($"contentInput{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, $"contentInput{i}", this);
InputPorts.Add(inputPort);
}
@@ -47,7 +47,7 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
for(var i = 1; i <=props.CameraInputCount; i++)
{
var cameraPort = new RoutingInputPort($"{Key}-cameraInput{i}", eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, $"cameraInput{i}", this);
var cameraPort = new RoutingInputPort($"cameraInput{i}", eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, $"cameraInput{i}", this);
InputPorts.Add(cameraPort);
}

View File

@@ -1,7 +1,6 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Reflection;
using Crestron.SimplSharpPro.DeviceSupport;
@@ -21,6 +20,7 @@ using PepperDash.Essentials.Core.Bridges.JoinMaps;
using Feedback = PepperDash.Essentials.Core.Feedback;
using Serilog.Events;
using PepperDash.Essentials.Core.Routing;
using System.Text;
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
@@ -31,9 +31,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
protected const int MaxParticipants = 50;
private readonly byte[] _clearBytes = XSigHelpers.ClearOutputs();
private IHasDirectory _directoryCodec;
private BasicTriList _directoryTrilist;
private VideoCodecControllerJoinMap _directoryJoinmap;
private readonly IHasDirectory _directoryCodec;
private readonly BasicTriList _directoryTrilist;
private readonly VideoCodecControllerJoinMap _directoryJoinmap;
protected string _timeFormatSpecifier;
protected string _dateFormatSpecifier;
@@ -216,11 +216,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
/// <param name="item"></param>
protected virtual void OnCallStatusChange(CodecActiveCallItem item)
{
var handler = CallStatusChange;
if (handler != null)
{
handler(this, new CodecCallStatusItemChangeEventArgs(item));
}
CallStatusChange?.Invoke(this, new CodecCallStatusItemChangeEventArgs(item));
PrivacyModeIsOnFeedback.FireUpdate();
@@ -252,12 +248,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
try
{
IsReady = true;
var h = IsReadyChange;
if (h != null)
{
h(this, new EventArgs());
}
}
IsReadyChange?.Invoke(this, new EventArgs());
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Verbose, this, "Error in SetIsReady() : {0}", e);
@@ -309,10 +301,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
joinMap.SetCustomJoinData(customJoins);
}
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
bridge?.AddJoinMap(Key, joinMap);
LinkVideoCodecToApi(codec, trilist, joinMap);
@@ -530,11 +519,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false);
var autoCodec = codec as IHasCameraAutoMode;
if (autoCodec == null) return;
if (!(codec is IHasCameraAutoMode autoCodec)) return;
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoCodec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoCodec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !autoCodec.CameraAutoModeIsOnFeedback.BoolValue);
};
@@ -548,11 +536,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false);
var autoModeCodec = codec as IHasCameraAutoMode;
if (autoModeCodec == null) return;
if (!(codec is IHasCameraAutoMode autoModeCodec)) return;
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue);
}
@@ -649,8 +636,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
var p = participant;
if (index > MaxParticipants) break;
var audioMuteCodec = this as IHasParticipantAudioMute;
if (audioMuteCodec != null)
if (this is IHasParticipantAudioMute audioMuteCodec)
{
trilist.SetSigFalseAction(joinMap.ParticipantAudioMuteToggleStart.JoinNumber + index,
() => audioMuteCodec.ToggleAudioForParticipant(p.UserId));
@@ -659,8 +645,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
() => audioMuteCodec.ToggleVideoForParticipant(p.UserId));
}
var pinCodec = this as IHasParticipantPinUnpin;
if (pinCodec != null)
if (this is IHasParticipantPinUnpin pinCodec)
{
trilist.SetSigFalseAction(joinMap.ParticipantPinToggleStart.JoinNumber + index,
() => pinCodec.ToggleParticipantPinState(p.UserId, pinCodec.ScreenIndexToPinUserTo));
@@ -1089,29 +1074,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
// Allow auto dial of selected line. Always dials first contact method
if (!trilist.GetBool(joinMap.DirectoryDisableAutoDialSelectedLine.JoinNumber))
{
var invitableEntry = _selectedDirectoryItem as IInvitableContact;
if (invitableEntry != null)
if (_selectedDirectoryItem is IInvitableContact invitableEntry)
{
Dial(invitableEntry);
return;
}
var entryToDial = _selectedDirectoryItem as DirectoryContact;
trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber,
trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber,
selectedContact != null ? selectedContact.ContactMethods[0].Number : string.Empty);
if (entryToDial == null) return;
if (!(_selectedDirectoryItem is DirectoryContact entryToDial)) return;
Dial(entryToDial.ContactMethods[0].Number);
}
else
{
// If auto dial is disabled...
var entryToDial = _selectedDirectoryItem as DirectoryContact;
if (entryToDial == null)
if (!(_selectedDirectoryItem is DirectoryContact entryToDial))
{
// Clear out values and actions from last selected item
trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0);
@@ -1296,78 +1277,76 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetUshort(joinMap.ConnectedCallCount.JoinNumber, (ushort)ActiveCalls.Count);
};
var joinCodec = this as IJoinCalls;
if (joinCodec != null)
{
trilist.SetSigFalseAction(joinMap.JoinAllCalls.JoinNumber, () => joinCodec.JoinAllCalls());
if (this is IJoinCalls joinCodec)
{
trilist.SetSigFalseAction(joinMap.JoinAllCalls.JoinNumber, () => joinCodec.JoinAllCalls());
for (int i = 0; i < joinMap.JoinCallStart.JoinSpan; i++)
{
trilist.SetSigFalseAction((uint)(joinMap.JoinCallStart.JoinNumber + i), () =>
{
var call = ActiveCalls[i];
if (call != null)
{
joinCodec.JoinCall(call);
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "[Join Call] Unable to find call at index '{0}'", i);
}
});
}
}
for (int i = 0; i < joinMap.JoinCallStart.JoinSpan; i++)
{
trilist.SetSigFalseAction((uint)(joinMap.JoinCallStart.JoinNumber + i), () =>
{
var call = ActiveCalls[i];
if (call != null)
{
joinCodec.JoinCall(call);
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "[Join Call] Unable to find call at index '{0}'", i);
}
});
}
}
var holdCodec = this as IHasCallHold;
if (holdCodec != null)
{
trilist.SetSigFalseAction(joinMap.HoldAllCalls.JoinNumber, () =>
{
foreach (var call in ActiveCalls)
{
holdCodec.HoldCall(call);
}
});
if (this is IHasCallHold holdCodec)
{
trilist.SetSigFalseAction(joinMap.HoldAllCalls.JoinNumber, () =>
{
foreach (var call in ActiveCalls)
{
holdCodec.HoldCall(call);
}
});
for (int i = 0; i < joinMap.HoldCallsStart.JoinSpan; i++)
{
var index = i;
for (int i = 0; i < joinMap.HoldCallsStart.JoinSpan; i++)
{
var index = i;
trilist.SetSigFalseAction((uint)(joinMap.HoldCallsStart.JoinNumber + index), () =>
{
if (index < 0 || index >= ActiveCalls.Count) return;
trilist.SetSigFalseAction((uint)(joinMap.HoldCallsStart.JoinNumber + index), () =>
{
if (index < 0 || index >= ActiveCalls.Count) return;
var call = ActiveCalls[index];
if (call != null)
{
holdCodec.HoldCall(call);
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "[Hold Call] Unable to find call at index '{0}'", i);
}
});
var call = ActiveCalls[index];
if (call != null)
{
holdCodec.HoldCall(call);
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "[Hold Call] Unable to find call at index '{0}'", i);
}
});
trilist.SetSigFalseAction((uint)(joinMap.ResumeCallsStart.JoinNumber + index), () =>
{
if (index < 0 || index >= ActiveCalls.Count) return;
trilist.SetSigFalseAction((uint)(joinMap.ResumeCallsStart.JoinNumber + index), () =>
{
if (index < 0 || index >= ActiveCalls.Count) return;
var call = ActiveCalls[index];
if (call != null)
{
holdCodec.ResumeCall(call);
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "[Resume Call] Unable to find call at index '{0}'", i);
}
});
}
}
var call = ActiveCalls[index];
if (call != null)
{
holdCodec.ResumeCall(call);
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "[Resume Call] Unable to find call at index '{0}'", i);
}
});
}
}
trilist.OnlineStatusChange += (device, args) =>
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
@@ -1505,48 +1484,45 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
codec.CameraAutoModeIsOnFeedback.OutputChange += (o, a) =>
{
var offCodec = codec as IHasCameraOff;
if (codec is IHasCameraOff offCodec)
{
if (offCodec.CameraIsOffFeedback.BoolValue)
{
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true);
return;
}
if (offCodec != null)
{
if (offCodec.CameraIsOffFeedback.BoolValue)
{
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true);
return;
}
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false);
return;
}
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false);
return;
}
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue);
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false);
};
var offModeCodec = codec as IHasCameraOff;
if (offModeCodec != null)
{
if (offModeCodec.CameraIsOffFeedback.BoolValue)
{
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true);
return;
}
if (codec is IHasCameraOff offModeCodec)
{
if (offModeCodec.CameraIsOffFeedback.BoolValue)
{
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true);
return;
}
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false);
return;
}
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false);
return;
}
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false);
}
@@ -1565,64 +1541,58 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetBoolSigAction(joinMap.CameraTiltUp.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraPtzControl;
if (camera == null) return;
if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return;
if (b) camera.TiltUp();
if (b) camera.TiltUp();
else camera.TiltStop();
});
trilist.SetBoolSigAction(joinMap.CameraTiltDown.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraPtzControl;
if (camera == null) return;
if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return;
if (b) camera.TiltDown();
if (b) camera.TiltDown();
else camera.TiltStop();
});
trilist.SetBoolSigAction(joinMap.CameraPanLeft.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraPtzControl;
if (camera == null) return;
if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return;
if (b) camera.PanLeft();
if (b) camera.PanLeft();
else camera.PanStop();
});
trilist.SetBoolSigAction(joinMap.CameraPanRight.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraPtzControl;
if (camera == null) return;
if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return;
if (b) camera.PanRight();
if (b) camera.PanRight();
else camera.PanStop();
});
trilist.SetBoolSigAction(joinMap.CameraZoomIn.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraPtzControl;
if (camera == null) return;
if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return;
if (b) camera.ZoomIn();
if (b) camera.ZoomIn();
else camera.ZoomStop();
});
trilist.SetBoolSigAction(joinMap.CameraZoomOut.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraPtzControl;
if (camera == null) return;
if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return;
if (b) camera.ZoomOut();
if (b) camera.ZoomOut();
else camera.ZoomStop();
});
@@ -1630,9 +1600,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetBoolSigAction(joinMap.CameraFocusNear.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraFocusControl;
if (camera == null) return;
if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return;
if (b) camera.FocusNear();
else camera.FocusStop();
@@ -1641,9 +1610,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetBoolSigAction(joinMap.CameraFocusFar.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraFocusControl;
if (camera == null) return;
if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return;
if (b) camera.FocusFar();
else camera.FocusStop();
@@ -1652,9 +1620,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetSigFalseAction(joinMap.CameraFocusAuto.JoinNumber, () =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraFocusControl;
if (camera == null) return;
if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return;
camera.TriggerAutoFocus();
});
@@ -1773,7 +1740,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
// Following fields only used for Bridging
private int _selectedRecentCallItemIndex;
private CodecCallHistory.CallHistoryEntry _selectedRecentCallItem;
private DirectoryItem _selectedDirectoryItem;
private void LinkVideoCodecCallHistoryToApi(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
@@ -1820,7 +1786,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
// Clear out selected item
_selectedRecentCallItemIndex = 0;
_selectedRecentCallItem = null;
trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, 0);
trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty);
trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty);
@@ -1929,12 +1895,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
if (value == true)
{
var handler = InitialSyncCompleted;
if (handler != null)
{
handler(this, new EventArgs());
}
}
InitialSyncCompleted?.Invoke(this, new EventArgs());
}
_InitialSyncComplete = value;
}
}

View File

@@ -0,0 +1,31 @@
using Newtonsoft.Json;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer
{
public class SourceSelectMessageContent
{
[JsonProperty("sourceListItemKey")]
public string SourceListItemKey { get; set; }
[JsonProperty("sourceListKey")]
public string SourceListKey { get; set; }
}
public class DirectRoute
{
[JsonProperty("sourceKey")]
public string SourceKey { get; set; }
[JsonProperty("destinationKey")]
public string DestinationKey { get; set; }
[JsonProperty("signalType")]
public eRoutingSignalType SignalType { get; set; }
}
/// <summary>
///
/// </summary>
/// <param name="b"></param>
public delegate void PressAndHoldAction(bool b);
}

View File

@@ -0,0 +1,60 @@
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.AppServer;
using PepperDash.Essentials.AppServer.Messengers;
using System.Linq;
using DisplayBase = PepperDash.Essentials.Devices.Common.Displays.DisplayBase;
namespace PepperDash.Essentials.Room.MobileControl
{
public class DisplayBaseMessenger : MessengerBase
{
private readonly DisplayBase display;
public DisplayBaseMessenger(string key, string messagePath, DisplayBase device) : base(key, messagePath, device)
{
display = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
/*AddAction("/powerOn", (id, content) => display.PowerOn());
AddAction("/powerOff", (id, content) => display.PowerOff());
AddAction("/powerToggle", (id, content) => display.PowerToggle());*/
AddAction("/inputSelect", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
var inputPort = display.InputPorts.FirstOrDefault(i => i.Key == s.Value);
if (inputPort == null)
{
this.LogWarning("No input named {inputName} found for {deviceKey}", s, display.Key);
return;
}
display.ExecuteSwitch(inputPort.Selector);
});
AddAction("/inputs", (id, content) =>
{
var inputsList = display.InputPorts.Select(p => p.Key).ToList();
var messageObject = new MobileControlMessage
{
Type = MessagePath + "/inputs",
Content = JToken.FromObject(new
{
inputKeys = inputsList,
})
};
AppServerController.SendMessageObject(messageObject);
});
}
}
}

View File

@@ -0,0 +1,29 @@
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public class IChannelMessenger : MessengerBase
{
private readonly IChannel channelDevice;
public IChannelMessenger(string key, string messagePath, Device device) : base(key, messagePath, device)
{
channelDevice = device as IChannel;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/chanUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.ChannelUp(b)));
AddAction("/chanDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.ChannelDown(b)));
AddAction("/lastChan", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.LastChannel(b)));
AddAction("/guide", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.Guide(b)));
AddAction("/info", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.Info(b)));
AddAction("/exit", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.Exit(b)));
}
}
}

View File

@@ -0,0 +1,25 @@
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public class IColorMessenger : MessengerBase
{
private readonly IColor colorDevice;
public IColorMessenger(string key, string messagePath, Device device) : base(key, messagePath, device)
{
colorDevice = device as IColor;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/red", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => colorDevice?.Red(b)));
AddAction("/green", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => colorDevice?.Green(b)));
AddAction("/yellow", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => colorDevice?.Yellow(b)));
AddAction("/blue", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => colorDevice?.Blue(b)));
}
}
}

View File

@@ -0,0 +1,29 @@
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public class IDPadMessenger : MessengerBase
{
private readonly IDPad dpadDevice;
public IDPadMessenger(string key, string messagePath, Device device) : base(key, messagePath, device)
{
dpadDevice = device as IDPad;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/up", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Up(b)));
AddAction("/down", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Down(b)));
AddAction("/left", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Left(b)));
AddAction("/right", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Right(b)));
AddAction("/select", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Select(b)));
AddAction("/menu", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Menu(b)));
AddAction("/exit", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Exit(b)));
}
}
}

View File

@@ -0,0 +1,24 @@
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public class IDvrMessenger : MessengerBase
{
private readonly IDvr dvrDevice;
public IDvrMessenger(string key, string messagePath, Device device) : base(key, messagePath, device)
{
dvrDevice = device as IDvr;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/dvrlist", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dvrDevice?.DvrList(b)));
AddAction("/record", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dvrDevice?.Record(b)));
}
}
}

View File

@@ -0,0 +1,24 @@
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public class IHasPowerMessenger : MessengerBase
{
private readonly IHasPowerControl powerDevice;
public IHasPowerMessenger(string key, string messagePath, Device device) : base(key, messagePath, device)
{
powerDevice = device as IHasPowerControl;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/powerOn", (id, content) => powerDevice?.PowerOn());
AddAction("/powerOff", (id, content) => powerDevice?.PowerOff());
AddAction("/powerToggle", (id, content) => powerDevice?.PowerToggle());
}
}
}

View File

@@ -0,0 +1,34 @@
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public class INumericKeypadMessenger : MessengerBase
{
private readonly INumericKeypad keypadDevice;
public INumericKeypadMessenger(string key, string messagePath, Device device) : base(key, messagePath, device)
{
keypadDevice = device as INumericKeypad;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/num0", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit0(b)));
AddAction("/num1", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit1(b)));
AddAction("/num2", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit2(b)));
AddAction("/num3", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit3(b)));
AddAction("/num4", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit4(b)));
AddAction("/num5", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit5(b)));
AddAction("/num6", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit6(b)));
AddAction("/num7", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit7(b)));
AddAction("/num8", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit8(b)));
AddAction("/num9", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit9(b)));
AddAction("/numDash", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.KeypadAccessoryButton1(b)));
AddAction("/numEnter", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.KeypadAccessoryButton2(b)));
// Deal with the Accessory functions on the numpad later
}
}
}

View File

@@ -0,0 +1,39 @@
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public class ISetTopBoxControlsMessenger : MessengerBase
{
private readonly ISetTopBoxControls stbDevice;
public ISetTopBoxControlsMessenger(string key, string messagePath, IKeyName device) : base(key, messagePath, device)
{
stbDevice = device as ISetTopBoxControls;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendISetTopBoxControlsFullMessageObject());
AddAction("/dvrList", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => stbDevice?.DvrList(b)));
AddAction("/replay", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => stbDevice?.Replay(b)));
}
/// <summary>
/// Helper method to build call status for vtc
/// </summary>
/// <returns></returns>
private void SendISetTopBoxControlsFullMessageObject()
{
PostStatusMessage(new SetTopBoxControlsState());
}
}
public class SetTopBoxControlsState : DeviceStateMessageBase
{
}
}

View File

@@ -0,0 +1,30 @@
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public class ITransportMessenger : MessengerBase
{
private readonly ITransport transportDevice;
public ITransportMessenger(string key, string messagePath, Device device) : base(key, messagePath, device)
{
transportDevice = device as ITransport;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/play", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Play(b)));
AddAction("/pause", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Pause(b)));
AddAction("/stop", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Stop(b)));
AddAction("/prevTrack", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.ChapPlus(b)));
AddAction("/nextTrack", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.ChapMinus(b)));
AddAction("/rewind", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Rewind(b)));
AddAction("/ffwd", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.FFwd(b)));
AddAction("/record", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Record(b)));
}
}
}

View File

@@ -0,0 +1,116 @@
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Devices.Common.AudioCodec;
using PepperDash.Essentials.Devices.Common.Codec;
using System;
using System.Linq;
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; private 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, codec)
{
Codec = codec ?? throw new ArgumentNullException("codec");
codec.CallStatusChange += Codec_CallStatusChange;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendAtcFullMessageObject());
AddAction("/dial", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
Codec.Dial(msg.Value);
});
AddAction("/endCallById", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
var call = GetCallWithId(msg.Value);
if (call != null)
Codec.EndCall(call);
});
AddAction("/endAllCalls", (id, content) => Codec.EndAllCalls());
AddAction("/dtmf", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
Codec.SendDtmf(msg.Value);
});
AddAction("/rejectById", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
var call = GetCallWithId(msg.Value);
if (call != null)
Codec.RejectCall(call);
});
AddAction("/acceptById", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
var call = GetCallWithId(msg.Value);
if (call != null)
Codec.AcceptCall(call);
});
}
/// <summary>
/// Helper to grab a call with string ID
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
private CodecActiveCallItem GetCallWithId(string id)
{
return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id);
}
private void Codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
{
SendAtcFullMessageObject();
}
/// <summary>
/// Helper method to build call status for vtc
/// </summary>
/// <returns></returns>
private void SendAtcFullMessageObject()
{
var info = Codec.CodecInfo;
PostStatusMessage(JToken.FromObject(new
{
isInCall = Codec.IsInCall,
calls = Codec.ActiveCalls,
info = new
{
phoneNumber = info.PhoneNumber
}
})
);
}
}
}

View File

@@ -0,0 +1,204 @@
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.Cameras;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class CameraBaseMessenger : MessengerBase
{
/// <summary>
/// Device being bridged
/// </summary>
public CameraBase Camera { get; set; }
/// <summary>
/// Constructor
/// </summary>
/// <param name="key"></param>
/// <param name="camera"></param>
/// <param name="messagePath"></param>
public CameraBaseMessenger(string key, CameraBase camera, string messagePath)
: base(key, messagePath, camera)
{
Camera = camera ?? throw new ArgumentNullException("camera");
if (Camera is IHasCameraPresets presetsCamera)
{
presetsCamera.PresetsListHasChanged += PresetsCamera_PresetsListHasChanged;
}
}
private void PresetsCamera_PresetsListHasChanged(object sender, EventArgs e)
{
var presetList = new List<CameraPreset>();
if (Camera is IHasCameraPresets presetsCamera)
presetList = presetsCamera.Presets;
PostStatusMessage(JToken.FromObject(new
{
presets = presetList
})
);
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendCameraFullMessageObject());
if (Camera is IHasCameraPtzControl ptzCamera)
{
// Need to evaluate how to pass through these P&H actions. Need a method that takes a bool maybe?
AddAction("/cameraUp", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
ptzCamera.TiltUp();
return;
}
ptzCamera.TiltStop();
}));
AddAction("/cameraDown", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
ptzCamera.TiltDown();
return;
}
ptzCamera.TiltStop();
}));
AddAction("/cameraLeft", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
ptzCamera.PanLeft();
return;
}
ptzCamera.PanStop();
}));
AddAction("/cameraRight", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
ptzCamera.PanRight();
return;
}
ptzCamera.PanStop();
}));
AddAction("/cameraZoomIn", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
ptzCamera.ZoomIn();
return;
}
ptzCamera.ZoomStop();
}));
AddAction("/cameraZoomOut", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
ptzCamera.ZoomOut();
return;
}
ptzCamera.ZoomStop();
}));
}
if (Camera is IHasCameraAutoMode)
{
AddAction("/cameraModeAuto", (id, content) => (Camera as IHasCameraAutoMode).CameraAutoModeOn());
AddAction("/cameraModeManual", (id, content) => (Camera as IHasCameraAutoMode).CameraAutoModeOff());
}
if (Camera is IHasPowerControl)
{
AddAction("/cameraModeOff", (id, content) => (Camera as IHasPowerControl).PowerOff());
AddAction("/cameraModeManual", (id, content) => (Camera as IHasPowerControl).PowerOn());
}
if (Camera is IHasCameraPresets presetsCamera)
{
for (int i = 1; i <= 6; i++)
{
var preset = i;
AddAction("/cameraPreset" + i, (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<int>>();
presetsCamera.PresetSelect(msg.Value);
});
}
}
}
private void HandleCameraPressAndHold(JToken content, Action<bool> cameraAction)
{
var state = content.ToObject<MobileControlSimpleContent<string>>();
var timerHandler = PressAndHoldHandler.GetPressAndHoldHandler(state.Value);
if (timerHandler == null)
{
return;
}
timerHandler(state.Value, cameraAction);
cameraAction(state.Value.Equals("true", StringComparison.InvariantCultureIgnoreCase));
}
/// <summary>
/// Helper method to update the full status of the camera
/// </summary>
private void SendCameraFullMessageObject()
{
var presetList = new List<CameraPreset>();
if (Camera is IHasCameraPresets presetsCamera)
presetList = presetsCamera.Presets;
PostStatusMessage(JToken.FromObject(new
{
cameraManualSupported = Camera is IHasCameraControls,
cameraAutoSupported = Camera is IHasCameraAutoMode,
cameraOffSupported = Camera is IHasCameraOff,
cameraMode = GetCameraMode(),
hasPresets = Camera is IHasCameraPresets,
presets = presetList
})
);
}
/// <summary>
/// Computes the current camera mode
/// </summary>
/// <returns></returns>
private string GetCameraMode()
{
string m;
if (Camera is IHasCameraAutoMode && (Camera as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.BoolValue)
m = eCameraControlMode.Auto.ToString().ToLower();
else if (Camera is IHasPowerControlWithFeedback && !(Camera as IHasPowerControlWithFeedback).PowerIsOnFeedback.BoolValue)
m = eCameraControlMode.Off.ToString().ToLower();
else
m = eCameraControlMode.Manual.ToString().ToLower();
return m;
}
}
}

View File

@@ -0,0 +1,42 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core.DeviceInfo;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class DeviceInfoMessenger : MessengerBase
{
private readonly IDeviceInfoProvider _deviceInfoProvider;
public DeviceInfoMessenger(string key, string messagePath, IDeviceInfoProvider device) : base(key, messagePath, device as Device)
{
_deviceInfoProvider = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
_deviceInfoProvider.DeviceInfoChanged += (o, a) =>
{
PostStatusMessage(JToken.FromObject(new
{
deviceInfo = a.DeviceInfo
}));
};
AddAction("/fullStatus", (id, context) => PostStatusMessage(new DeviceInfoStateMessage
{
DeviceInfo = _deviceInfoProvider.DeviceInfo
}));
AddAction("/update", (id, context) => _deviceInfoProvider.UpdateDeviceInfo());
}
}
public class DeviceInfoStateMessage : DeviceStateMessageBase
{
[JsonProperty("deviceInfo")]
public DeviceInfo DeviceInfo { get; set; }
}
}

View File

@@ -0,0 +1,100 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Core.Presets;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class DevicePresetsModelMessenger : MessengerBase
{
private readonly ITvPresetsProvider _presetsDevice;
public DevicePresetsModelMessenger(string key, string messagePath, ITvPresetsProvider presetsDevice)
: base(key, messagePath, presetsDevice as Device)
{
_presetsDevice = presetsDevice;
}
private void SendPresets()
{
PostStatusMessage(new PresetStateMessage
{
Favorites = _presetsDevice.TvPresets.PresetsList
});
}
private void RecallPreset(ISetTopBoxNumericKeypad device, string channel)
{
_presetsDevice.TvPresets.Dial(channel, device);
}
private void SavePresets(List<PresetChannel> presets)
{
_presetsDevice.TvPresets.UpdatePresets(presets);
}
#region Overrides of MessengerBase
protected override void RegisterActions()
{
AddAction("/presets/fullStatus", (id, content) =>
{
this.LogInformation("getting full status for client {id}", id);
try
{
SendPresets();
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Exception sending preset full status", this);
}
});
AddAction("/presets/recall", (id, content) =>
{
var p = content.ToObject<PresetChannelMessage>();
if (!(DeviceManager.GetDeviceForKey(p.DeviceKey) is ISetTopBoxNumericKeypad dev))
{
this.LogDebug("Unable to find device with key {0}", p.DeviceKey);
return;
}
RecallPreset(dev, p.Preset.Channel);
});
AddAction("/presets/save", (id, content) =>
{
var presets = content.ToObject<List<PresetChannel>>();
SavePresets(presets);
});
_presetsDevice.TvPresets.PresetsSaved += (p) => SendPresets();
}
#endregion
}
public class PresetChannelMessage
{
[JsonProperty("preset")]
public PresetChannel Preset;
[JsonProperty("deviceKey")]
public string DeviceKey;
}
public class PresetStateMessage : DeviceStateMessageBase
{
[JsonProperty("favorites", NullValueHandling = NullValueHandling.Ignore)]
public List<PresetChannel> Favorites { get; set; } = new List<PresetChannel>();
}
}

View File

@@ -0,0 +1,172 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using System;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class DeviceVolumeMessenger : MessengerBase
{
private readonly IBasicVolumeWithFeedback _localDevice;
public DeviceVolumeMessenger(string key, string messagePath, IBasicVolumeWithFeedback device)
: base(key, messagePath, device as IKeyName)
{
_localDevice = device;
}
private void SendStatus()
{
try
{
var messageObj = new VolumeStateMessage
{
Volume = new Volume
{
Level = _localDevice?.VolumeLevelFeedback.IntValue ?? -1,
Muted = _localDevice?.MuteFeedback.BoolValue ?? false,
HasMute = true, // assume all devices have mute for now
}
};
if (_localDevice is IBasicVolumeWithFeedbackAdvanced volumeAdvanced)
{
messageObj.Volume.RawValue = volumeAdvanced.RawVolumeLevel.ToString();
messageObj.Volume.Units = volumeAdvanced.Units;
}
PostStatusMessage(messageObj);
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Exception sending full status", this);
}
}
#region Overrides of MessengerBase
protected override void RegisterActions()
{
AddAction("/fullStatus", (id, content) => SendStatus());
AddAction("/level", (id, content) =>
{
var volume = content.ToObject<MobileControlSimpleContent<ushort>>();
_localDevice.SetVolume(volume.Value);
});
AddAction("/muteToggle", (id, content) =>
{
_localDevice.MuteToggle();
});
AddAction("/muteOn", (id, content) =>
{
_localDevice.MuteOn();
});
AddAction("/muteOff", (id, content) =>
{
_localDevice.MuteOff();
});
AddAction("/volumeUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) =>
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Calling {localDevice} volume up with {value}", DeviceKey, b);
try
{
_localDevice.VolumeUp(b);
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Got exception during volume up: {Exception}", null, ex);
}
}));
AddAction("/volumeDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) =>
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Calling {localDevice} volume down with {value}", DeviceKey, b);
try
{
_localDevice.VolumeDown(b);
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Got exception during volume down: {Exception}", null, ex);
}
}));
_localDevice.MuteFeedback.OutputChange += (sender, args) =>
{
PostStatusMessage(JToken.FromObject(
new
{
volume = new
{
muted = args.BoolValue
}
})
);
};
_localDevice.VolumeLevelFeedback.OutputChange += (sender, args) =>
{
var rawValue = "";
if (_localDevice is IBasicVolumeWithFeedbackAdvanced volumeAdvanced)
{
rawValue = volumeAdvanced.RawVolumeLevel.ToString();
}
var message = new
{
volume = new
{
level = args.IntValue,
rawValue
}
};
PostStatusMessage(JToken.FromObject(message));
};
}
#endregion
}
public class VolumeStateMessage : DeviceStateMessageBase
{
[JsonProperty("volume", NullValueHandling = NullValueHandling.Ignore)]
public Volume Volume { get; set; }
}
public class Volume
{
[JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)]
public int? Level { get; set; }
[JsonProperty("hasMute", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasMute { get; set; }
[JsonProperty("muted", NullValueHandling = NullValueHandling.Ignore)]
public bool? Muted { get; set; }
[JsonProperty("label", NullValueHandling = NullValueHandling.Ignore)]
public string Label { get; set; }
[JsonProperty("rawValue", NullValueHandling = NullValueHandling.Ignore)]
public string RawValue { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
[JsonProperty("units", NullValueHandling = NullValueHandling.Ignore)]
public eVolumeLevelUnits? Units { get; set; }
}
}

View File

@@ -0,0 +1,25 @@
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class GenericMessenger : MessengerBase
{
public GenericMessenger(string key, EssentialsDevice device, string messagePath) : base(key, messagePath, device)
{
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
}
private void SendFullStatus()
{
var state = new DeviceStateMessageBase();
PostStatusMessage(state);
}
}
}

View File

@@ -0,0 +1,74 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class ICommunicationMonitorMessenger : MessengerBase
{
private readonly ICommunicationMonitor _communicationMonitor;
public ICommunicationMonitorMessenger(string key, string messagePath, ICommunicationMonitor device) : base(key, messagePath, device as IKeyName)
{
_communicationMonitor = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) =>
{
PostStatusMessage(new CommunicationMonitorState
{
CommunicationMonitor = new CommunicationMonitorProps
{
IsOnline = _communicationMonitor.CommunicationMonitor.IsOnline,
Status = _communicationMonitor.CommunicationMonitor.Status
}
});
});
_communicationMonitor.CommunicationMonitor.StatusChange += (sender, args) =>
{
PostStatusMessage(JToken.FromObject(new
{
commMonitor = new CommunicationMonitorProps
{
IsOnline = _communicationMonitor.CommunicationMonitor.IsOnline,
Status = _communicationMonitor.CommunicationMonitor.Status
}
}));
};
}
}
/// <summary>
/// Represents the state of the communication monitor
/// </summary>
public class CommunicationMonitorState : DeviceStateMessageBase
{
[JsonProperty("commMonitor", NullValueHandling = NullValueHandling.Ignore)]
public CommunicationMonitorProps CommunicationMonitor { get; set; }
}
public class CommunicationMonitorProps
{ /// <summary>
/// For devices that implement ICommunicationMonitor, reports the online status of the device
/// </summary>
[JsonProperty("isOnline", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsOnline { get; set; }
/// <summary>
/// For devices that implement ICommunicationMonitor, reports the online status of the device
/// </summary>
[JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))]
public MonitorStatus Status { get; set; }
}
}

View File

@@ -0,0 +1,50 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IDspPresetsMessenger : MessengerBase
{
private readonly IDspPresets device;
public IDspPresetsMessenger(string key, string messagePath, IDspPresets device)
: base(key, messagePath, device as IKeyName)
{
this.device = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) =>
{
var message = new IHasDspPresetsStateMessage
{
Presets = device.Presets
};
PostStatusMessage(message);
});
AddAction("/recallPreset", (id, content) =>
{
var presetKey = content.ToObject<string>();
if (!string.IsNullOrEmpty(presetKey))
{
device.RecallPreset(presetKey);
}
});
}
}
public class IHasDspPresetsStateMessage : DeviceStateMessageBase
{
[JsonProperty("presets")]
public Dictionary<string, IKeyName> Presets { get; set; }
}
}

View File

@@ -0,0 +1,154 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IEssentialsRoomCombinerMessenger : MessengerBase
{
private readonly IEssentialsRoomCombiner _roomCombiner;
public IEssentialsRoomCombinerMessenger(string key, string messagePath, IEssentialsRoomCombiner roomCombiner)
: base(key, messagePath, roomCombiner as Device)
{
_roomCombiner = roomCombiner;
}
protected override void RegisterActions()
{
AddAction("/fullStatus", (id, content) => SendFullStatus());
AddAction("/setAutoMode", (id, content) =>
{
_roomCombiner.SetAutoMode();
});
AddAction("/setManualMode", (id, content) =>
{
_roomCombiner.SetManualMode();
});
AddAction("/toggleMode", (id, content) =>
{
_roomCombiner.ToggleMode();
});
AddAction("/togglePartitionState", (id, content) =>
{
try
{
var partitionKey = content.ToObject<string>();
_roomCombiner.TogglePartitionState(partitionKey);
}
catch (Exception e)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Error toggling partition state: {e}", this);
}
});
AddAction("/setRoomCombinationScenario", (id, content) =>
{
try
{
var scenarioKey = content.ToObject<string>();
_roomCombiner.SetRoomCombinationScenario(scenarioKey);
}
catch (Exception e)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Error toggling partition state: {e}", this);
}
});
_roomCombiner.RoomCombinationScenarioChanged += (sender, args) =>
{
SendFullStatus();
};
_roomCombiner.IsInAutoModeFeedback.OutputChange += (sender, args) =>
{
var message = new
{
isInAutoMode = _roomCombiner.IsInAutoModeFeedback.BoolValue
};
PostStatusMessage(JToken.FromObject(message));
};
foreach (var partition in _roomCombiner.Partitions)
{
partition.PartitionPresentFeedback.OutputChange += (sender, args) =>
{
var message = new
{
partitions = _roomCombiner.Partitions
};
PostStatusMessage(JToken.FromObject(message));
};
}
}
private void SendFullStatus()
{
try
{
var rooms = new List<IKeyName>();
foreach (var room in _roomCombiner.Rooms)
{
rooms.Add(new RoomCombinerRoom { Key = room.Key, Name = room.Name });
}
var message = new IEssentialsRoomCombinerStateMessage
{
IsInAutoMode = _roomCombiner.IsInAutoMode,
CurrentScenario = _roomCombiner.CurrentScenario,
Rooms = rooms,
RoomCombinationScenarios = _roomCombiner.RoomCombinationScenarios,
Partitions = _roomCombiner.Partitions
};
PostStatusMessage(message);
}
catch (Exception e)
{
this.LogException(e, "Error sending full status");
}
}
private class RoomCombinerRoom : IKeyName
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
}
public class IEssentialsRoomCombinerStateMessage : DeviceStateMessageBase
{
[JsonProperty("isInAutoMode", NullValueHandling = NullValueHandling.Ignore)]
public bool IsInAutoMode { get; set; }
[JsonProperty("currentScenario", NullValueHandling = NullValueHandling.Ignore)]
public IRoomCombinationScenario CurrentScenario { get; set; }
[JsonProperty("rooms", NullValueHandling = NullValueHandling.Ignore)]
public List<IKeyName> Rooms { get; set; }
[JsonProperty("roomCombinationScenarios", NullValueHandling = NullValueHandling.Ignore)]
public List<IRoomCombinationScenario> RoomCombinationScenarios { get; set; }
[JsonProperty("partitions", NullValueHandling = NullValueHandling.Ignore)]
public List<IPartitionController> Partitions { get; set; }
}
}

View File

@@ -0,0 +1,57 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IHasCurrentSourceInfoMessenger : MessengerBase
{
private readonly IHasCurrentSourceInfoChange sourceDevice;
public IHasCurrentSourceInfoMessenger(string key, string messagePath, IHasCurrentSourceInfoChange device) : base(key, messagePath, device as IKeyName)
{
sourceDevice = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) =>
{
var message = new CurrentSourceStateMessage
{
CurrentSourceKey = sourceDevice.CurrentSourceInfoKey,
CurrentSource = sourceDevice.CurrentSourceInfo
};
PostStatusMessage(message);
});
sourceDevice.CurrentSourceChange += (sender, e) =>
{
switch (e)
{
case ChangeType.DidChange:
{
PostStatusMessage(JToken.FromObject(new
{
currentSourceKey = string.IsNullOrEmpty(sourceDevice.CurrentSourceInfoKey) ? string.Empty : sourceDevice.CurrentSourceInfoKey,
currentSource = sourceDevice.CurrentSourceInfo
}));
break;
}
}
};
}
}
public class CurrentSourceStateMessage : DeviceStateMessageBase
{
[JsonProperty("currentSourceKey", NullValueHandling = NullValueHandling.Ignore)]
public string CurrentSourceKey { get; set; }
[JsonProperty("currentSource")]
public SourceListItem CurrentSource { get; set; }
}
}

View File

@@ -0,0 +1,52 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IHasPowerControlWithFeedbackMessenger : MessengerBase
{
private readonly IHasPowerControlWithFeedback _powerControl;
public IHasPowerControlWithFeedbackMessenger(string key, string messagePath, IHasPowerControlWithFeedback powerControl)
: base(key, messagePath, powerControl as Device)
{
_powerControl = powerControl;
}
public void SendFullStatus()
{
var messageObj = new PowerControlWithFeedbackStateMessage
{
PowerState = _powerControl.PowerIsOnFeedback.BoolValue
};
PostStatusMessage(messageObj);
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
_powerControl.PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange; ;
}
private void PowerIsOnFeedback_OutputChange(object sender, FeedbackEventArgs args)
{
PostStatusMessage(JToken.FromObject(new
{
powerState = args.BoolValue
})
);
}
}
public class PowerControlWithFeedbackStateMessage : DeviceStateMessageBase
{
[JsonProperty("powerState", NullValueHandling = NullValueHandling.Ignore)]
public bool? PowerState { get; set; }
}
}

View File

@@ -0,0 +1,81 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Devices.Common.Codec;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IHasScheduleAwarenessMessenger : MessengerBase
{
public IHasScheduleAwareness ScheduleSource { get; private set; }
public IHasScheduleAwarenessMessenger(string key, IHasScheduleAwareness scheduleSource, string messagePath)
: base(key, messagePath, scheduleSource as Device)
{
ScheduleSource = scheduleSource ?? throw new ArgumentNullException("scheduleSource");
ScheduleSource.CodecSchedule.MeetingsListHasChanged += new EventHandler<EventArgs>(CodecSchedule_MeetingsListHasChanged);
ScheduleSource.CodecSchedule.MeetingEventChange += new EventHandler<MeetingEventArgs>(CodecSchedule_MeetingEventChange);
}
protected override void RegisterActions()
{
AddAction("/schedule/fullStatus", (id, content) => SendFullScheduleObject());
}
private void CodecSchedule_MeetingEventChange(object sender, MeetingEventArgs e)
{
PostStatusMessage(JToken.FromObject(new MeetingChangeMessage
{
MeetingChange = new MeetingChange
{
ChangeType = e.ChangeType.ToString(),
Meeting = e.Meeting
}
})
);
}
private void CodecSchedule_MeetingsListHasChanged(object sender, EventArgs e)
{
SendFullScheduleObject();
}
/// <summary>
/// Helper method to send the full schedule data
/// </summary>
private void SendFullScheduleObject()
{
PostStatusMessage(new FullScheduleMessage
{
Meetings = ScheduleSource.CodecSchedule.Meetings,
MeetingWarningMinutes = ScheduleSource.CodecSchedule.MeetingWarningMinutes
});
}
}
public class FullScheduleMessage : DeviceStateMessageBase
{
[JsonProperty("meetings", NullValueHandling = NullValueHandling.Ignore)]
public List<Meeting> Meetings { get; set; }
[JsonProperty("meetingWarningMinutes", NullValueHandling = NullValueHandling.Ignore)]
public int MeetingWarningMinutes { get; set; }
}
public class MeetingChangeMessage
{
[JsonProperty("meetingChange", NullValueHandling = NullValueHandling.Ignore)]
public MeetingChange MeetingChange { get; set; }
}
public class MeetingChange
{
[JsonProperty("changeType", NullValueHandling = NullValueHandling.Ignore)]
public string ChangeType { get; set; }
[JsonProperty("meeting", NullValueHandling = NullValueHandling.Ignore)]
public Meeting Meeting { get; set; }
}
}

View File

@@ -0,0 +1,43 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using System;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IHumiditySensorMessenger : MessengerBase
{
private readonly IHumiditySensor device;
public IHumiditySensorMessenger(string key, IHumiditySensor device, string messagePath)
: base(key, messagePath, device as Device)
{
this.device = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
device.HumidityFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>((o, a) => SendFullStatus());
}
private void SendFullStatus()
{
var state = new IHumiditySensorStateMessage
{
Humidity = string.Format("{0}%", device.HumidityFeedback.UShortValue)
};
PostStatusMessage(state);
}
}
public class IHumiditySensorStateMessage : DeviceStateMessageBase
{
[JsonProperty("humidity")]
public string Humidity { get; set; }
}
}

View File

@@ -0,0 +1,91 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using System.Collections.Generic;
using System.Linq;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class ILevelControlsMessenger : MessengerBase
{
private ILevelControls levelControlsDevice;
public ILevelControlsMessenger(string key, string messagePath, ILevelControls device) : base(key, messagePath, device as Device)
{
levelControlsDevice = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, context) =>
{
var message = new LevelControlStateMessage
{
Levels = levelControlsDevice.LevelControlPoints.ToDictionary(kv => kv.Key, kv => new Volume { Level = kv.Value.VolumeLevelFeedback.IntValue, Muted = kv.Value.MuteFeedback.BoolValue })
};
PostStatusMessage(message);
});
foreach (var levelControl in levelControlsDevice.LevelControlPoints)
{
// reassigning here just in case of lambda closure issues
var key = levelControl.Key;
var control = levelControl.Value;
AddAction($"/{key}/level", (id, content) =>
{
var request = content.ToObject<MobileControlSimpleContent<ushort>>();
control.SetVolume(request.Value);
});
AddAction($"/{key}/muteToggle", (id, content) =>
{
control.MuteToggle();
});
AddAction($"/{key}/muteOn", (id, content) => control.MuteOn());
AddAction($"/{key}/muteOff", (id, content) => control.MuteOff());
AddAction($"/{key}/volumeUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => control.VolumeUp(b)));
AddAction($"/{key}/volumeDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => control.VolumeDown(b)));
control.VolumeLevelFeedback.OutputChange += (o, a) => PostStatusMessage(JToken.FromObject(new
{
levelControls = new Dictionary<string, Volume>
{
{key, new Volume{Level = a.IntValue} }
}
}));
control.MuteFeedback.OutputChange += (o, a) => PostStatusMessage(JToken.FromObject(new
{
levelControls = new Dictionary<string, Volume>
{
{key, new Volume{Muted = a.BoolValue} }
}
}));
}
}
}
public class LevelControlStateMessage : DeviceStateMessageBase
{
[JsonProperty("levelControls")]
public Dictionary<string, Volume> Levels { get; set; }
}
public class LevelControlRequestMessage
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)]
public ushort? Level { get; set; }
}
}

View File

@@ -0,0 +1,168 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Routing;
using Serilog.Events;
using System;
using System.Collections.Generic;
using System.Linq;
namespace PepperDash.Essentials.AppServer.Messengers
{
/// <summary>
/// Messenger for devices that implment IMatrixRouting
/// </summary>
public class IMatrixRoutingMessenger : MessengerBase
{
private readonly IMatrixRouting matrixDevice;
public IMatrixRoutingMessenger(string key, string messagePath, IMatrixRouting device) : base(key, messagePath, device as Device)
{
matrixDevice = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) =>
{
try
{
Debug.LogMessage(LogEventLevel.Verbose, "InputCount: {inputCount}, OutputCount: {outputCount}", this, matrixDevice.InputSlots.Count, matrixDevice.OutputSlots.Count);
var message = new MatrixStateMessage
{
Outputs = matrixDevice.OutputSlots.ToDictionary(kvp => kvp.Key, kvp => new RoutingOutput(kvp.Value)),
Inputs = matrixDevice.InputSlots.ToDictionary(kvp => kvp.Key, kvp => new RoutingInput(kvp.Value)),
};
PostStatusMessage(message);
}
catch (Exception e)
{
Debug.LogMessage(e, "Exception Getting full status: {@exception}", this, e);
}
});
AddAction("/route", (id, content) =>
{
var request = content.ToObject<MatrixRouteRequest>();
matrixDevice.Route(request.InputKey, request.OutputKey, request.RouteType);
});
foreach (var output in matrixDevice.OutputSlots)
{
var key = output.Key;
var outputSlot = output.Value;
outputSlot.OutputSlotChanged += (sender, args) =>
{
PostStatusMessage(JToken.FromObject(new
{
outputs = matrixDevice.OutputSlots.ToDictionary(kvp => kvp.Key, kvp => new RoutingOutput(kvp.Value))
}));
};
}
foreach (var input in matrixDevice.InputSlots)
{
var key = input.Key;
var inputSlot = input.Value;
inputSlot.VideoSyncChanged += (sender, args) =>
{
PostStatusMessage(JToken.FromObject(new
{
inputs = matrixDevice.InputSlots.ToDictionary(kvp => kvp.Key, kvp => new RoutingInput(kvp.Value))
}));
};
}
}
}
public class MatrixStateMessage : DeviceStateMessageBase
{
[JsonProperty("outputs")]
public Dictionary<string, RoutingOutput> Outputs;
[JsonProperty("inputs")]
public Dictionary<string, RoutingInput> Inputs;
}
public class RoutingInput
{
private IRoutingInputSlot _input;
[JsonProperty("txDeviceKey", NullValueHandling = NullValueHandling.Ignore)]
public string TxDeviceKey => _input?.TxDeviceKey;
[JsonProperty("slotNumber", NullValueHandling = NullValueHandling.Ignore)]
public int? SlotNumber => _input?.SlotNumber;
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
[JsonProperty("supportedSignalTypes", NullValueHandling = NullValueHandling.Ignore)]
public eRoutingSignalType? SupportedSignalTypes => _input?.SupportedSignalTypes;
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name => _input?.Name;
[JsonProperty("isOnline", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsOnline => _input?.IsOnline.BoolValue;
[JsonProperty("videoSyncDetected", NullValueHandling = NullValueHandling.Ignore)]
public bool? VideoSyncDetected => _input?.VideoSyncDetected;
[JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)]
public string Key => _input?.Key;
public RoutingInput(IRoutingInputSlot input)
{
_input = input;
}
}
public class RoutingOutput
{
private IRoutingOutputSlot _output;
public RoutingOutput(IRoutingOutputSlot output)
{
_output = output;
}
[JsonProperty("rxDeviceKey")]
public string RxDeviceKey => _output.RxDeviceKey;
[JsonProperty("currentRoutes")]
public Dictionary<string, RoutingInput> CurrentRoutes => _output.CurrentRoutes.ToDictionary(kvp => kvp.Key.ToString(), kvp => new RoutingInput(kvp.Value));
[JsonProperty("slotNumber")]
public int SlotNumber => _output.SlotNumber;
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
[JsonProperty("supportedSignalTypes")]
public eRoutingSignalType SupportedSignalTypes => _output.SupportedSignalTypes;
[JsonProperty("name")]
public string Name => _output.Name;
[JsonProperty("key")]
public string Key => _output.Key;
}
public class MatrixRouteRequest
{
[JsonProperty("outputKey")]
public string OutputKey { get; set; }
[JsonProperty("inputKey")]
public string InputKey { get; set; }
[JsonProperty("routeType")]
public eRoutingSignalType RouteType { get; set; }
}
}

View File

@@ -0,0 +1,78 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using System;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IProjectorScreenLiftControlMessenger : MessengerBase
{
private readonly IProjectorScreenLiftControl device;
public IProjectorScreenLiftControlMessenger(string key, string messagePath, IProjectorScreenLiftControl screenLiftDevice)
: base(key, messagePath, screenLiftDevice as Device)
{
device = screenLiftDevice;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
AddAction("/raise", (id, content) =>
{
device.Raise();
});
AddAction("/lower", (id, content) =>
{
device.Lower();
});
device.PositionChanged += Device_PositionChanged;
}
private void Device_PositionChanged(object sender, EventArgs e)
{
var state = new
{
inUpPosition = device.InUpPosition
};
PostStatusMessage(JToken.FromObject(state));
}
private void SendFullStatus()
{
var state = new ScreenLiftStateMessage
{
InUpPosition = device.InUpPosition,
Type = device.Type,
DisplayDeviceKey = device.DisplayDeviceKey
};
PostStatusMessage(state);
}
}
public class ScreenLiftStateMessage : DeviceStateMessageBase
{
[JsonProperty("inUpPosition", NullValueHandling = NullValueHandling.Ignore)]
public bool? InUpPosition { get; set; }
[JsonProperty("displayDeviceKey", NullValueHandling = NullValueHandling.Ignore)]
public string DisplayDeviceKey { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
public eScreenLiftControlType Type { get; set; }
}
}

View File

@@ -0,0 +1,84 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core;
using System;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class RunRouteActionMessenger : MessengerBase
{
/// <summary>
/// Device being bridged
/// </summary>
public IRunRouteAction RoutingDevice { get; private set; }
public RunRouteActionMessenger(string key, IRunRouteAction routingDevice, string messagePath)
: base(key, messagePath, routingDevice as Device)
{
RoutingDevice = routingDevice ?? throw new ArgumentNullException("routingDevice");
if (RoutingDevice is IRoutingSink routingSink)
{
routingSink.CurrentSourceChange += RoutingSink_CurrentSourceChange;
}
}
private void RoutingSink_CurrentSourceChange(SourceListItem info, ChangeType type)
{
SendRoutingFullMessageObject();
}
protected override void RegisterActions()
{
AddAction("/fullStatus", (id, content) => SendRoutingFullMessageObject());
AddAction("/source", (id, content) =>
{
var c = content.ToObject<SourceSelectMessageContent>();
// assume no sourceListKey
var sourceListKey = string.Empty;
if (!string.IsNullOrEmpty(c.SourceListKey))
{
// Check for source list in content of message
sourceListKey = c.SourceListKey;
}
RoutingDevice.RunRouteAction(c.SourceListItemKey, sourceListKey);
});
if (RoutingDevice is IRoutingSink sinkDevice)
{
sinkDevice.CurrentSourceChange += (o, a) => SendRoutingFullMessageObject();
}
}
/// <summary>
/// Helper method to update full status of the routing device
/// </summary>
private void SendRoutingFullMessageObject()
{
if (RoutingDevice is IRoutingSink sinkDevice)
{
var sourceKey = sinkDevice.CurrentSourceInfoKey;
if (string.IsNullOrEmpty(sourceKey))
sourceKey = "none";
PostStatusMessage(new RoutingStateMessage
{
SelectedSourceKey = sourceKey
});
}
}
}
public class RoutingStateMessage : DeviceStateMessageBase
{
[JsonProperty("selectedSourceKey")]
public string SelectedSourceKey { get; set; }
}
}

View File

@@ -0,0 +1,65 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class ISelectableItemsMessenger<TKey> : MessengerBase
{
private static readonly JsonSerializer serializer = new JsonSerializer { Converters = { new StringEnumConverter() } };
private ISelectableItems<TKey> itemDevice;
private readonly string _propName;
public ISelectableItemsMessenger(string key, string messagePath, ISelectableItems<TKey> device, string propName) : base(key, messagePath, device as Device)
{
itemDevice = device;
_propName = propName;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, context) =>
{
SendFullStatus();
});
itemDevice.ItemsUpdated += (sender, args) =>
{
SendFullStatus();
};
itemDevice.CurrentItemChanged += (sender, args) =>
{
SendFullStatus();
};
foreach (var input in itemDevice.Items)
{
var key = input.Key;
var localItem = input.Value;
AddAction($"/{key}", (id, content) =>
{
localItem.Select();
});
localItem.ItemUpdated += (sender, args) =>
{
SendFullStatus();
};
}
}
private void SendFullStatus()
{
var stateObject = new JObject();
stateObject[_propName] = JToken.FromObject(itemDevice, serializer);
PostStatusMessage(stateObject);
}
}
}

View File

@@ -0,0 +1,93 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IShutdownPromptTimerMessenger : MessengerBase
{
private readonly IShutdownPromptTimer _room;
public IShutdownPromptTimerMessenger(string key, string messagePath, IShutdownPromptTimer room)
: base(key, messagePath, room as Device)
{
_room = room;
}
protected override void RegisterActions()
{
AddAction("/status", (id, content) =>
{
SendFullStatus();
});
AddAction("/setShutdownPromptSeconds", (id, content) =>
{
var response = content.ToObject<int>();
_room.SetShutdownPromptSeconds(response);
SendFullStatus();
});
AddAction("/shutdownStart", (id, content) => _room.StartShutdown(eShutdownType.Manual));
AddAction("/shutdownEnd", (id, content) => _room.ShutdownPromptTimer.Finish());
AddAction("/shutdownCancel", (id, content) => _room.ShutdownPromptTimer.Cancel());
_room.ShutdownPromptTimer.HasStarted += (sender, args) =>
{
PostEventMessage("timerStarted");
};
_room.ShutdownPromptTimer.HasFinished += (sender, args) =>
{
PostEventMessage("timerFinished");
};
_room.ShutdownPromptTimer.WasCancelled += (sender, args) =>
{
PostEventMessage("timerCancelled");
};
_room.ShutdownPromptTimer.SecondsRemainingFeedback.OutputChange += (sender, args) =>
{
var status = new
{
secondsRemaining = _room.ShutdownPromptTimer.SecondsRemainingFeedback.IntValue,
percentageRemaining = _room.ShutdownPromptTimer.PercentFeedback.UShortValue
};
PostStatusMessage(JToken.FromObject(status));
};
}
private void SendFullStatus()
{
var status = new IShutdownPromptTimerStateMessage
{
ShutdownPromptSeconds = _room.ShutdownPromptTimer.SecondsToCount,
SecondsRemaining = _room.ShutdownPromptTimer.SecondsRemainingFeedback.IntValue,
PercentageRemaining = _room.ShutdownPromptTimer.PercentFeedback.UShortValue
};
PostStatusMessage(status);
}
}
public class IShutdownPromptTimerStateMessage : DeviceStateMessageBase
{
[JsonProperty("secondsRemaining")]
public int SecondsRemaining { get; set; }
[JsonProperty("percentageRemaining")]
public int PercentageRemaining { get; set; }
[JsonProperty("shutdownPromptSeconds")]
public int ShutdownPromptSeconds { get; set; }
}
}

View File

@@ -0,0 +1,58 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.CrestronIO;
using System;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class ISwitchedOutputMessenger : MessengerBase
{
private readonly ISwitchedOutput device;
public ISwitchedOutputMessenger(string key, ISwitchedOutput device, string messagePath)
: base(key, messagePath, device as Device)
{
this.device = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
AddAction("/on", (id, content) =>
{
device.On();
});
AddAction("/off", (id, content) =>
{
device.Off();
});
device.OutputIsOnFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>((o, a) => SendFullStatus());
}
private void SendFullStatus()
{
var state = new ISwitchedOutputStateMessage
{
IsOn = device.OutputIsOnFeedback.BoolValue
};
PostStatusMessage(state);
}
}
public class ISwitchedOutputStateMessage : DeviceStateMessageBase
{
[JsonProperty("isOn")]
public bool IsOn { get; set; }
}
}

View File

@@ -0,0 +1,88 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class ITechPasswordMessenger : MessengerBase
{
private readonly ITechPassword _room;
public ITechPasswordMessenger(string key, string messagePath, ITechPassword room)
: base(key, messagePath, room as Device)
{
_room = room;
}
protected override void RegisterActions()
{
AddAction("/status", (id, content) =>
{
SendFullStatus();
});
AddAction("/validateTechPassword", (id, content) =>
{
var password = content.Value<string>("password");
_room.ValidateTechPassword(password);
});
AddAction("/setTechPassword", (id, content) =>
{
var response = content.ToObject<SetTechPasswordContent>();
_room.SetTechPassword(response.OldPassword, response.NewPassword);
});
_room.TechPasswordChanged += (sender, args) =>
{
PostEventMessage("passwordChangedSuccessfully");
};
_room.TechPasswordValidateResult += (sender, args) =>
{
var evt = new ITechPasswordEventMessage
{
IsValid = args.IsValid
};
PostEventMessage(evt, "passwordValidationResult");
};
}
private void SendFullStatus()
{
var status = new ITechPasswordStateMessage
{
TechPasswordLength = _room.TechPasswordLength
};
PostStatusMessage(status);
}
}
public class ITechPasswordStateMessage : DeviceStateMessageBase
{
[JsonProperty("techPasswordLength", NullValueHandling = NullValueHandling.Ignore)]
public int? TechPasswordLength { get; set; }
}
public class ITechPasswordEventMessage : DeviceEventMessageBase
{
[JsonProperty("isValid", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsValid { get; set; }
}
internal class SetTechPasswordContent
{
[JsonProperty("oldPassword")]
public string OldPassword { get; set; }
[JsonProperty("newPassword")]
public string NewPassword { get; set; }
}
}

View File

@@ -0,0 +1,61 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using System;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class ITemperatureSensorMessenger : MessengerBase
{
private readonly ITemperatureSensor device;
public ITemperatureSensorMessenger(string key, ITemperatureSensor device, string messagePath)
: base(key, messagePath, device as Device)
{
this.device = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
AddAction("/setTemperatureUnitsToCelcius", (id, content) =>
{
device.SetTemperatureFormat(true);
});
AddAction("/setTemperatureUnitsToFahrenheit", (id, content) =>
{
device.SetTemperatureFormat(false);
});
device.TemperatureFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>((o, a) => SendFullStatus());
device.TemperatureInCFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>((o, a) => SendFullStatus());
}
private void SendFullStatus()
{
// format the temperature to a string with one decimal place
var tempString = string.Format("{0}.{1}", device.TemperatureFeedback.UShortValue / 10, device.TemperatureFeedback.UShortValue % 10);
var state = new ITemperatureSensorStateMessage
{
Temperature = tempString,
TemperatureInCelsius = device.TemperatureInCFeedback.BoolValue
};
PostStatusMessage(state);
}
}
public class ITemperatureSensorStateMessage : DeviceStateMessageBase
{
[JsonProperty("temperature")]
public string Temperature { get; set; }
[JsonProperty("temperatureInCelsius")]
public bool TemperatureInCelsius { get; set; }
}
}

View File

@@ -0,0 +1,66 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Lighting;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class ILightingScenesMessenger : MessengerBase
{
protected ILightingScenes Device { get; private set; }
public ILightingScenesMessenger(string key, ILightingScenes device, string messagePath)
: base(key, messagePath, device as Device)
{
Device = device ?? throw new ArgumentNullException("device");
Device.LightingSceneChange += new EventHandler<LightingSceneChangeEventArgs>(LightingDevice_LightingSceneChange);
}
private void LightingDevice_LightingSceneChange(object sender, LightingSceneChangeEventArgs e)
{
var state = new LightingBaseStateMessage
{
CurrentLightingScene = e.CurrentLightingScene
};
PostStatusMessage(state);
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
AddAction("/selectScene", (id, content) =>
{
var s = content.ToObject<LightingScene>();
Device.SelectScene(s);
});
}
private void SendFullStatus()
{
var state = new LightingBaseStateMessage
{
Scenes = Device.LightingScenes,
CurrentLightingScene = Device.CurrentLightingScene
};
PostStatusMessage(state);
}
}
public class LightingBaseStateMessage : DeviceStateMessageBase
{
[JsonProperty("scenes", NullValueHandling = NullValueHandling.Ignore)]
public List<LightingScene> Scenes { get; set; }
[JsonProperty("currentLightingScene", NullValueHandling = NullValueHandling.Ignore)]
public LightingScene CurrentLightingScene { get; set; }
}
}

View File

@@ -0,0 +1,288 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using System;
using System.Collections.Generic;
using System.Linq;
namespace PepperDash.Essentials.AppServer.Messengers
{
/// <summary>
/// Provides a messaging bridge
/// </summary>
public abstract class MessengerBase : EssentialsDevice, IMobileControlMessenger
{
protected IKeyName _device;
private readonly List<string> _deviceInterfaces;
private readonly Dictionary<string, Action<string, JToken>> _actions = new Dictionary<string, Action<string, JToken>>();
public string DeviceKey => _device?.Key ?? "";
/// <summary>
///
/// </summary>
public IMobileControl AppServerController { get; private set; }
public string MessagePath { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="messagePath"></param>
protected MessengerBase(string key, string messagePath)
: base(key)
{
Key = key;
if (string.IsNullOrEmpty(messagePath))
throw new ArgumentException("messagePath must not be empty or null");
MessagePath = messagePath;
}
protected MessengerBase(string key, string messagePath, IKeyName device)
: this(key, messagePath)
{
_device = device;
_deviceInterfaces = GetInterfaces(_device as Device);
}
/// <summary>
/// Gets the interfaces implmented on the device
/// </summary>
/// <param name="device"></param>
/// <returns></returns>
private List<string> GetInterfaces(Device device)
{
return device?.GetType().GetInterfaces().Select((i) => i.Name).ToList() ?? new List<string>();
}
/// <summary>
/// Registers this messenger with appserver controller
/// </summary>
/// <param name="appServerController"></param>
public void RegisterWithAppServer(IMobileControl appServerController)
{
AppServerController = appServerController ?? throw new ArgumentNullException("appServerController");
AppServerController.AddAction(this, HandleMessage);
RegisterActions();
}
private void HandleMessage(string path, string id, JToken content)
{
// replace base path with empty string. Should leave something like /fullStatus
var route = path.Replace(MessagePath, string.Empty);
if (!_actions.TryGetValue(route, out var action))
{
return;
}
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Executing action for path {path}", this, path);
action(id, content);
}
protected void AddAction(string path, Action<string, JToken> action)
{
if (_actions.ContainsKey(path))
{
//Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Messenger {Key} already has action registered at {path}", this);
return;
}
_actions.Add(path, action);
}
public List<string> GetActionPaths()
{
return _actions.Keys.ToList();
}
protected void RemoveAction(string path)
{
if (!_actions.ContainsKey(path))
{
return;
}
_actions.Remove(path);
}
/// <summary>
/// Implemented in extending classes. Wire up API calls and feedback here
/// </summary>
/// <param name="appServerController"></param>
protected virtual void RegisterActions()
{
}
/// <summary>
/// Helper for posting status message
/// </summary>
/// <param name="type"></param>
/// <param name="message"></param>
protected void PostStatusMessage(DeviceStateMessageBase message, string clientId = null)
{
try
{
if (message == null)
{
throw new ArgumentNullException("message");
}
if (_device == null)
{
throw new ArgumentNullException("device");
}
message.SetInterfaces(_deviceInterfaces);
message.Key = _device.Key;
message.Name = _device.Name;
PostStatusMessage(JToken.FromObject(message), MessagePath, clientId);
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Exception posting status message", this);
}
}
protected void PostStatusMessage(string type, DeviceStateMessageBase deviceState, string clientId = null)
{
try
{
//Debug.Console(2, this, "*********************Setting DeviceStateMessageProperties on MobileControlResponseMessage");
deviceState.SetInterfaces(_deviceInterfaces);
deviceState.Key = _device.Key;
deviceState.Name = _device.Name;
deviceState.MessageBasePath = MessagePath;
PostStatusMessage(JToken.FromObject(deviceState), type, clientId);
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Exception posting status message", this);
}
}
protected void PostStatusMessage(JToken content, string type = "", string clientId = null)
{
try
{
AppServerController?.SendMessageObject(new MobileControlMessage { Type = !string.IsNullOrEmpty(type) ? type : MessagePath, ClientId = clientId, Content = content });
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Exception posting status message", this);
}
}
protected void PostEventMessage(DeviceEventMessageBase message)
{
message.Key = _device.Key;
message.Name = _device.Name;
AppServerController?.SendMessageObject(new MobileControlMessage
{
Type = $"/event{MessagePath}/{message.EventType}",
Content = JToken.FromObject(message),
});
}
protected void PostEventMessage(DeviceEventMessageBase message, string eventType)
{
message.Key = _device.Key;
message.Name = _device.Name;
message.EventType = eventType;
AppServerController?.SendMessageObject(new MobileControlMessage
{
Type = $"/event{MessagePath}/{eventType}",
Content = JToken.FromObject(message),
});
}
protected void PostEventMessage(string eventType)
{
AppServerController?.SendMessageObject(new MobileControlMessage
{
Type = $"/event{MessagePath}/{eventType}",
Content = JToken.FromObject(new { }),
});
}
}
public abstract class DeviceMessageBase
{
/// <summary>
/// The device key
/// </summary>
[JsonProperty("key")]
public string Key { get; set; }
/// <summary>
/// The device name
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// The type of the message class
/// </summary>
[JsonProperty("messageType")]
public string MessageType => GetType().Name;
[JsonProperty("messageBasePath")]
public string MessageBasePath { get; set; }
}
/// <summary>
/// Base class for state messages that includes the type of message and the implmented interfaces
/// </summary>
public class DeviceStateMessageBase : DeviceMessageBase
{
/// <summary>
/// The interfaces implmented by the device sending the messsage
/// </summary>
[JsonProperty("interfaces")]
public List<string> Interfaces { get; private set; }
public void SetInterfaces(List<string> interfaces)
{
Interfaces = interfaces;
}
}
/// <summary>
/// Base class for event messages that include the type of message and an event type
/// </summary>
public abstract class DeviceEventMessageBase : DeviceMessageBase
{
/// <summary>
/// The event type
/// </summary>
[JsonProperty("eventType")]
public string EventType { get; set; }
}
}

View File

@@ -0,0 +1,116 @@
using Crestron.SimplSharp;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public static class PressAndHoldHandler
{
private const long ButtonHeartbeatInterval = 1000;
private static readonly Dictionary<string, CTimer> _pushedActions = new Dictionary<string, CTimer>();
private static readonly Dictionary<string, Action<string, Action<bool>>> _pushedActionHandlers;
static PressAndHoldHandler()
{
_pushedActionHandlers = new Dictionary<string, Action<string, Action<bool>>>
{
{"pressed", AddTimer },
{"held", ResetTimer },
{"released", StopTimer }
};
}
private static void AddTimer(string deviceKey, Action<bool> action)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to add timer for {deviceKey}", deviceKey);
if (_pushedActions.TryGetValue(deviceKey, out CTimer cancelTimer))
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Timer for {deviceKey} already exists", deviceKey);
return;
}
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Adding timer for {deviceKey} with due time {dueTime}", deviceKey, ButtonHeartbeatInterval);
action(true);
cancelTimer = new CTimer(o =>
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Timer expired for {deviceKey}", deviceKey);
action(false);
_pushedActions.Remove(deviceKey);
}, ButtonHeartbeatInterval);
_pushedActions.Add(deviceKey, cancelTimer);
}
private static void ResetTimer(string deviceKey, Action<bool> action)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to reset timer for {deviceKey}", deviceKey);
if (!_pushedActions.TryGetValue(deviceKey, out CTimer cancelTimer))
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Timer for {deviceKey} not found", deviceKey);
return;
}
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Resetting timer for {deviceKey} with due time {dueTime}", deviceKey, ButtonHeartbeatInterval);
cancelTimer.Reset(ButtonHeartbeatInterval);
}
private static void StopTimer(string deviceKey, Action<bool> action)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to stop timer for {deviceKey}", deviceKey);
if (!_pushedActions.TryGetValue(deviceKey, out CTimer cancelTimer))
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Timer for {deviceKey} not found", deviceKey);
return;
}
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Stopping timer for {deviceKey} with due time {dueTime}", deviceKey, ButtonHeartbeatInterval);
action(false);
cancelTimer.Stop();
_pushedActions.Remove(deviceKey);
}
public static Action<string, Action<bool>> GetPressAndHoldHandler(string value)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Getting press and hold handler for {value}", value);
if (!_pushedActionHandlers.TryGetValue(value, out Action<string, Action<bool>> handler))
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Press and hold handler for {value} not found", value);
return null;
}
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Got handler for {value}", value);
return handler;
}
public static void HandlePressAndHold(string deviceKey, JToken content, Action<bool> action)
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Handling press and hold message of {type} for {deviceKey}", msg.Value, deviceKey);
var timerHandler = GetPressAndHoldHandler(msg.Value);
if (timerHandler == null)
{
return;
}
timerHandler(deviceKey, action);
}
}
}

View File

@@ -0,0 +1,76 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Room.Config;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class RoomEventScheduleMessenger : MessengerBase
{
private readonly IRoomEventSchedule _room;
public RoomEventScheduleMessenger(string key, string messagePath, IRoomEventSchedule room)
: base(key, messagePath, room as Device)
{
_room = room;
}
#region Overrides of MessengerBase
protected override void RegisterActions()
{
AddAction("/saveScheduledEvents", (id, content) => SaveScheduledEvents(content.ToObject<List<ScheduledEventConfig>>()));
AddAction("/status", (id, content) =>
{
var events = _room.GetScheduledEvents();
SendFullStatus(events);
});
_room.ScheduledEventsChanged += (sender, args) => SendFullStatus(args.ScheduledEvents);
}
#endregion
private void SaveScheduledEvents(List<ScheduledEventConfig> events)
{
foreach (var evt in events)
{
SaveScheduledEvent(evt);
}
}
private void SaveScheduledEvent(ScheduledEventConfig eventConfig)
{
try
{
_room.AddOrUpdateScheduledEvent(eventConfig);
}
catch (Exception ex)
{
this.LogException(ex,"Exception saving event");
}
}
private void SendFullStatus(List<ScheduledEventConfig> events)
{
var message = new RoomEventScheduleStateMessage
{
ScheduleEvents = events,
};
PostStatusMessage(message);
}
}
public class RoomEventScheduleStateMessage : DeviceStateMessageBase
{
[JsonProperty("scheduleEvents")]
public List<ScheduledEventConfig> ScheduleEvents { get; set; }
}
}

View File

@@ -0,0 +1,158 @@
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.Codec;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
// ReSharper disable once InconsistentNaming
public class SIMPLAtcMessenger : MessengerBase
{
private readonly BasicTriList _eisc;
public SIMPLAtcJoinMap JoinMap { get; private set; }
/// <summary>
///
/// </summary>
private readonly CodecActiveCallItem _currentCallItem;
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="eisc"></param>
/// <param name="messagePath"></param>
public SIMPLAtcMessenger(string key, BasicTriList eisc, string messagePath)
: base(key, messagePath)
{
_eisc = eisc;
JoinMap = new SIMPLAtcJoinMap(201);
_currentCallItem = new CodecActiveCallItem { Type = eCodecCallType.Audio, Id = "-audio-" };
}
/// <summary>
///
/// </summary>
private void SendFullStatus()
{
PostStatusMessage(JToken.FromObject(new
{
calls = GetCurrentCallList(),
currentCallString = _eisc.GetString(JoinMap.CurrentCallName.JoinNumber),
currentDialString = _eisc.GetString(JoinMap.CurrentDialString.JoinNumber),
isInCall = _eisc.GetString(JoinMap.HookState.JoinNumber) == "Connected"
})
);
}
/// <summary>
///
/// </summary>
/// <param name="appServerController"></param>
protected override void RegisterActions()
{
//EISC.SetStringSigAction(SCurrentDialString, s => PostStatusMessage(new { currentDialString = s }));
_eisc.SetStringSigAction(JoinMap.HookState.JoinNumber, s =>
{
_currentCallItem.Status = (eCodecCallStatus)Enum.Parse(typeof(eCodecCallStatus), s, true);
//GetCurrentCallList();
SendFullStatus();
});
_eisc.SetStringSigAction(JoinMap.CurrentCallNumber.JoinNumber, s =>
{
_currentCallItem.Number = s;
SendCallsList();
});
_eisc.SetStringSigAction(JoinMap.CurrentCallName.JoinNumber, s =>
{
_currentCallItem.Name = s;
SendCallsList();
});
_eisc.SetStringSigAction(JoinMap.CallDirection.JoinNumber, 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
void addAction(string s, uint u) =>
AddAction(s, (id, content) => _eisc.PulseBool(u, 100));
addAction("/endCallById", JoinMap.EndCall.JoinNumber);
addAction("/endAllCalls", JoinMap.EndCall.JoinNumber);
addAction("/acceptById", JoinMap.IncomingAnswer.JoinNumber);
addAction("/rejectById", JoinMap.IncomingReject.JoinNumber);
var speeddialStart = JoinMap.SpeedDialStart.JoinNumber;
var speeddialEnd = JoinMap.SpeedDialStart.JoinNumber + JoinMap.SpeedDialStart.JoinSpan;
var speedDialIndex = 1;
for (uint i = speeddialStart; i < speeddialEnd; i++)
{
addAction(string.Format("/speedDial{0}", speedDialIndex), i);
speedDialIndex++;
}
// Get status
AddAction("/fullStatus", (id, content) => SendFullStatus());
// Dial on string
AddAction("/dial",
(id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
_eisc.SetString(JoinMap.CurrentDialString.JoinNumber, msg.Value);
});
// Pulse DTMF
AddAction("/dtmf", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
var join = JoinMap.Joins[s.Value];
if (join != null)
{
if (join.JoinNumber > 0)
{
_eisc.PulseBool(join.JoinNumber, 100);
}
}
});
}
/// <summary>
///
/// </summary>
private void SendCallsList()
{
PostStatusMessage(JToken.FromObject(new
{
calls = GetCurrentCallList(),
})
);
}
/// <summary>
/// Turns the
/// </summary>
/// <returns></returns>
private List<CodecActiveCallItem> GetCurrentCallList()
{
return _currentCallItem.Status == eCodecCallStatus.Disconnected
? new List<CodecActiveCallItem>()
: new List<CodecActiveCallItem> { _currentCallItem };
}
}
}

View File

@@ -0,0 +1,161 @@
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Devices.Common.Cameras;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
// ReSharper disable once InconsistentNaming
public class SIMPLCameraMessenger : MessengerBase
{
private readonly BasicTriList _eisc;
private readonly CameraControllerJoinMap _joinMap;
public SIMPLCameraMessenger(string key, BasicTriList eisc, string messagePath, uint joinStart)
: base(key, messagePath)
{
_eisc = eisc;
_joinMap = new CameraControllerJoinMap(joinStart);
_eisc.SetUShortSigAction(_joinMap.NumberOfPresets.JoinNumber, u => SendCameraFullMessageObject());
_eisc.SetBoolSigAction(_joinMap.CameraModeAuto.JoinNumber, b => PostCameraMode());
_eisc.SetBoolSigAction(_joinMap.CameraModeManual.JoinNumber, b => PostCameraMode());
_eisc.SetBoolSigAction(_joinMap.CameraModeOff.JoinNumber, b => PostCameraMode());
}
protected override void RegisterActions()
{
AddAction("/fullStatus", (id, content) => SendCameraFullMessageObject());
// Add press and holds using helper action
void addPhAction(string s, uint u) =>
AddAction(s, (id, content) => HandleCameraPressAndHold(content, b => _eisc.SetBool(u, b)));
addPhAction("/cameraUp", _joinMap.TiltUp.JoinNumber);
addPhAction("/cameraDown", _joinMap.TiltDown.JoinNumber);
addPhAction("/cameraLeft", _joinMap.PanLeft.JoinNumber);
addPhAction("/cameraRight", _joinMap.PanRight.JoinNumber);
addPhAction("/cameraZoomIn", _joinMap.ZoomIn.JoinNumber);
addPhAction("/cameraZoomOut", _joinMap.ZoomOut.JoinNumber);
void addAction(string s, uint u) =>
AddAction(s, (id, content) => _eisc.PulseBool(u, 100));
addAction("/cameraModeAuto", _joinMap.CameraModeAuto.JoinNumber);
addAction("/cameraModeManual", _joinMap.CameraModeManual.JoinNumber);
addAction("/cameraModeOff", _joinMap.CameraModeOff.JoinNumber);
var presetStart = _joinMap.PresetRecallStart.JoinNumber;
var presetEnd = _joinMap.PresetRecallStart.JoinNumber + _joinMap.PresetRecallStart.JoinSpan;
int presetId = 1;
// camera presets
for (uint i = presetStart; i <= presetEnd; i++)
{
addAction("/cameraPreset" + (presetId), i);
presetId++;
}
}
private void HandleCameraPressAndHold(JToken content, Action<bool> cameraAction)
{
var state = content.ToObject<MobileControlSimpleContent<string>>();
var timerHandler = PressAndHoldHandler.GetPressAndHoldHandler(state.Value);
if (timerHandler == null)
{
return;
}
timerHandler(state.Value, cameraAction);
cameraAction(state.Value.Equals("true", StringComparison.InvariantCultureIgnoreCase));
}
public void CustomUnregisterWithAppServer(IMobileControl appServerController)
{
appServerController.RemoveAction(MessagePath + "/fullStatus");
appServerController.RemoveAction(MessagePath + "/cameraUp");
appServerController.RemoveAction(MessagePath + "/cameraDown");
appServerController.RemoveAction(MessagePath + "/cameraLeft");
appServerController.RemoveAction(MessagePath + "/cameraRight");
appServerController.RemoveAction(MessagePath + "/cameraZoomIn");
appServerController.RemoveAction(MessagePath + "/cameraZoomOut");
appServerController.RemoveAction(MessagePath + "/cameraModeAuto");
appServerController.RemoveAction(MessagePath + "/cameraModeManual");
appServerController.RemoveAction(MessagePath + "/cameraModeOff");
_eisc.SetUShortSigAction(_joinMap.NumberOfPresets.JoinNumber, null);
_eisc.SetBoolSigAction(_joinMap.CameraModeAuto.JoinNumber, null);
_eisc.SetBoolSigAction(_joinMap.CameraModeManual.JoinNumber, null);
_eisc.SetBoolSigAction(_joinMap.CameraModeOff.JoinNumber, null);
}
/// <summary>
/// Helper method to update the full status of the camera
/// </summary>
private void SendCameraFullMessageObject()
{
var presetList = new List<CameraPreset>();
// Build a list of camera presets based on the names and count
if (_eisc.GetBool(_joinMap.SupportsPresets.JoinNumber))
{
var presetStart = _joinMap.PresetLabelStart.JoinNumber;
var presetEnd = _joinMap.PresetLabelStart.JoinNumber + _joinMap.NumberOfPresets.JoinNumber;
var presetId = 1;
for (uint i = presetStart; i < presetEnd; i++)
{
var presetName = _eisc.GetString(i);
var preset = new CameraPreset(presetId, presetName, string.IsNullOrEmpty(presetName), true);
presetList.Add(preset);
presetId++;
}
}
PostStatusMessage(JToken.FromObject(new
{
cameraMode = GetCameraMode(),
hasPresets = _eisc.GetBool(_joinMap.SupportsPresets.JoinNumber),
presets = presetList
})
);
}
/// <summary>
///
/// </summary>
private void PostCameraMode()
{
PostStatusMessage(JToken.FromObject(new
{
cameraMode = GetCameraMode()
}));
}
/// <summary>
/// Computes the current camera mode
/// </summary>
/// <returns></returns>
private string GetCameraMode()
{
string m;
if (_eisc.GetBool(_joinMap.CameraModeAuto.JoinNumber)) m = eCameraControlMode.Auto.ToString().ToLower();
else if (_eisc.GetBool(_joinMap.CameraModeManual.JoinNumber))
m = eCameraControlMode.Manual.ToString().ToLower();
else m = eCameraControlMode.Off.ToString().ToLower();
return m;
}
}
}

View File

@@ -0,0 +1,127 @@
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class SimplDirectRouteMessenger : MessengerBase
{
private readonly BasicTriList _eisc;
public MobileControlSIMPLRunDirectRouteActionJoinMap JoinMap { get; private set; }
public Dictionary<string, DestinationListItem> DestinationList { get; set; }
public SimplDirectRouteMessenger(string key, BasicTriList eisc, string messagePath) : base(key, messagePath)
{
_eisc = eisc;
JoinMap = new MobileControlSIMPLRunDirectRouteActionJoinMap(851);
DestinationList = new Dictionary<string, DestinationListItem>();
}
#region Overrides of MessengerBase
protected override void RegisterActions()
{
Debug.Console(2, "********** Direct Route Messenger CustomRegisterWithAppServer **********");
//Audio source
_eisc.SetStringSigAction(JoinMap.SourceForDestinationAudio.JoinNumber,
s => PostStatusMessage(JToken.FromObject(new
{
selectedSourceKey = s,
})
));
AddAction("/programAudio/selectSource", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
_eisc.StringInput[JoinMap.SourceForDestinationAudio.JoinNumber].StringValue = msg.Value;
});
AddAction("/fullStatus", (id, content) =>
{
foreach (var dest in DestinationList)
{
var key = dest.Key;
var item = dest.Value;
var source =
_eisc.StringOutput[(uint)(JoinMap.SourceForDestinationJoinStart.JoinNumber + item.Order)].StringValue;
UpdateSourceForDestination(source, key);
}
PostStatusMessage(JToken.FromObject(new
{
selectedSourceKey = _eisc.StringOutput[JoinMap.SourceForDestinationAudio.JoinNumber].StringValue
})
);
PostStatusMessage(JToken.FromObject(new
{
advancedSharingActive = _eisc.BooleanOutput[JoinMap.AdvancedSharingModeFb.JoinNumber].BoolValue
})
);
});
AddAction("/advancedSharingMode", (id, content) =>
{
var b = content.ToObject<MobileControlSimpleContent<bool>>();
Debug.Console(1, "Current Sharing Mode: {2}\r\nadvanced sharing mode: {0} join number: {1}", b.Value,
JoinMap.AdvancedSharingModeOn.JoinNumber,
_eisc.BooleanOutput[JoinMap.AdvancedSharingModeOn.JoinNumber].BoolValue);
_eisc.SetBool(JoinMap.AdvancedSharingModeOn.JoinNumber, b.Value);
_eisc.SetBool(JoinMap.AdvancedSharingModeOff.JoinNumber, !b.Value);
_eisc.PulseBool(JoinMap.AdvancedSharingModeToggle.JoinNumber);
});
_eisc.SetBoolSigAction(JoinMap.AdvancedSharingModeFb.JoinNumber,
(b) => PostStatusMessage(JToken.FromObject(new
{
advancedSharingActive = b
})
));
}
public void RegisterForDestinationPaths()
{
//handle routing feedback from SIMPL
foreach (var destination in DestinationList)
{
var key = destination.Key;
var dest = destination.Value;
_eisc.SetStringSigAction((uint)(JoinMap.SourceForDestinationJoinStart.JoinNumber + dest.Order),
s => UpdateSourceForDestination(s, key));
AddAction($"/{key}/selectSource", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
_eisc.StringInput[(uint)(JoinMap.SourceForDestinationJoinStart.JoinNumber + dest.Order)].StringValue = s.Value;
});
}
}
#endregion
private void UpdateSourceForDestination(string sourceKey, string destKey)
{
PostStatusMessage(JToken.FromObject(new
{
selectedSourceKey = sourceKey
}), $"{MessagePath}/{destKey}/currentSource");
}
}
}

View File

@@ -0,0 +1,69 @@
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class SIMPLRouteMessenger : MessengerBase
{
private readonly BasicTriList _eisc;
private readonly uint _joinStart;
public class StringJoin
{
/// <summary>
/// 1
/// </summary>
public const uint CurrentSource = 1;
}
public SIMPLRouteMessenger(string key, BasicTriList eisc, string messagePath, uint joinStart)
: base(key, messagePath)
{
_eisc = eisc;
_joinStart = joinStart - 1;
_eisc.SetStringSigAction(_joinStart + StringJoin.CurrentSource, SendRoutingFullMessageObject);
}
protected override void RegisterActions()
{
AddAction("/fullStatus",
(id, content) => SendRoutingFullMessageObject(_eisc.GetString(_joinStart + StringJoin.CurrentSource)));
AddAction("/source", (id, content) =>
{
var c = content.ToObject<SourceSelectMessageContent>();
_eisc.SetString(_joinStart + StringJoin.CurrentSource, c.SourceListItemKey);
});
}
public void CustomUnregisterWithAppServer(IMobileControl appServerController)
{
appServerController.RemoveAction(MessagePath + "/fullStatus");
appServerController.RemoveAction(MessagePath + "/source");
_eisc.SetStringSigAction(_joinStart + StringJoin.CurrentSource, null);
}
/// <summary>
/// Helper method to update full status of the routing device
/// </summary>
private void SendRoutingFullMessageObject(string sourceKey)
{
if (string.IsNullOrEmpty(sourceKey))
sourceKey = "none";
PostStatusMessage(JToken.FromObject(new
{
selectedSourceKey = sourceKey
})
);
}
}
}

View File

@@ -0,0 +1,475 @@
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.Cameras;
using PepperDash.Essentials.Devices.Common.Codec;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
// ReSharper disable once InconsistentNaming
public class SIMPLVtcMessenger : MessengerBase
{
private readonly BasicTriList _eisc;
public SIMPLVtcJoinMap JoinMap { get; private set; }
private readonly CodecActiveCallItem _currentCallItem;
private CodecActiveCallItem _incomingCallItem;
private ushort _previousDirectoryLength = 701;
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="eisc"></param>
/// <param name="messagePath"></param>
public SIMPLVtcMessenger(string key, BasicTriList eisc, string messagePath)
: base(key, messagePath)
{
_eisc = eisc;
JoinMap = new SIMPLVtcJoinMap(1001);
_currentCallItem = new CodecActiveCallItem { Type = eCodecCallType.Video, Id = "-video-" };
}
/// <summary>
///
/// </summary>
/// <param name="appServerController"></param>
protected override void RegisterActions()
{
_eisc.SetStringSigAction(JoinMap.HookState.JoinNumber, s =>
{
_currentCallItem.Status = (eCodecCallStatus)Enum.Parse(typeof(eCodecCallStatus), s, true);
PostFullStatus(); // SendCallsList();
});
_eisc.SetStringSigAction(JoinMap.CurrentCallNumber.JoinNumber, s =>
{
_currentCallItem.Number = s;
PostCallsList();
});
_eisc.SetStringSigAction(JoinMap.CurrentCallName.JoinNumber, s =>
{
_currentCallItem.Name = s;
PostCallsList();
});
_eisc.SetStringSigAction(JoinMap.CallDirection.JoinNumber, s =>
{
_currentCallItem.Direction = (eCodecCallDirection)Enum.Parse(typeof(eCodecCallDirection), s, true);
PostCallsList();
});
_eisc.SetBoolSigAction(JoinMap.IncomingCall.JoinNumber, b =>
{
if (b)
{
var ica = new CodecActiveCallItem
{
Direction = eCodecCallDirection.Incoming,
Id = "-video-incoming",
Name = _eisc.GetString(JoinMap.IncomingCallName.JoinNumber),
Number = _eisc.GetString(JoinMap.IncomingCallNumber.JoinNumber),
Status = eCodecCallStatus.Ringing,
Type = eCodecCallType.Video
};
_incomingCallItem = ica;
}
else
{
_incomingCallItem = null;
}
PostCallsList();
});
_eisc.SetStringSigAction(JoinMap.IncomingCallName.JoinNumber, s =>
{
if (_incomingCallItem != null)
{
_incomingCallItem.Name = s;
PostCallsList();
}
});
_eisc.SetStringSigAction(JoinMap.IncomingCallNumber.JoinNumber, s =>
{
if (_incomingCallItem != null)
{
_incomingCallItem.Number = s;
PostCallsList();
}
});
_eisc.SetBoolSigAction(JoinMap.CameraSupportsAutoMode.JoinNumber, b => PostStatusMessage(JToken.FromObject(new
{
cameraSupportsAutoMode = b
})));
_eisc.SetBoolSigAction(JoinMap.CameraSupportsOffMode.JoinNumber, b => PostStatusMessage(JToken.FromObject(new
{
cameraSupportsOffMode = b
})));
// Directory insanity
_eisc.SetUShortSigAction(JoinMap.DirectoryRowCount.JoinNumber, 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(JoinMap.DirectoryEntriesStart.JoinNumber + _previousDirectoryLength - 1);
}
_eisc.SetStringSigAction(JoinMap.DirectoryEntriesStart.JoinNumber + u - 1, s => PostDirectory());
_previousDirectoryLength = u;
});
_eisc.SetStringSigAction(JoinMap.DirectoryEntrySelectedName.JoinNumber, s => PostStatusMessage(JToken.FromObject(new
{
directoryContactSelected = new
{
name = _eisc.GetString(JoinMap.DirectoryEntrySelectedName.JoinNumber),
}
})));
_eisc.SetStringSigAction(JoinMap.DirectoryEntrySelectedNumber.JoinNumber, s => PostStatusMessage(JToken.FromObject(new
{
directoryContactSelected = new
{
number = _eisc.GetString(JoinMap.DirectoryEntrySelectedNumber.JoinNumber),
}
})));
_eisc.SetStringSigAction(JoinMap.DirectorySelectedFolderName.JoinNumber, s => PostStatusMessage(JToken.FromObject(new
{
directorySelectedFolderName = _eisc.GetString(JoinMap.DirectorySelectedFolderName.JoinNumber)
})));
_eisc.SetSigTrueAction(JoinMap.CameraModeAuto.JoinNumber, PostCameraMode);
_eisc.SetSigTrueAction(JoinMap.CameraModeManual.JoinNumber, PostCameraMode);
_eisc.SetSigTrueAction(JoinMap.CameraModeOff.JoinNumber, PostCameraMode);
_eisc.SetBoolSigAction(JoinMap.CameraSelfView.JoinNumber, b => PostStatusMessage(JToken.FromObject(new
{
cameraSelfView = b
})));
_eisc.SetUShortSigAction(JoinMap.CameraNumberSelect.JoinNumber, u => PostSelectedCamera());
// Add press and holds using helper action
void addPhAction(string s, uint u) =>
AddAction(s, (id, content) => HandleCameraPressAndHold(content, b => _eisc.SetBool(u, b)));
addPhAction("/cameraUp", JoinMap.CameraTiltUp.JoinNumber);
addPhAction("/cameraDown", JoinMap.CameraTiltDown.JoinNumber);
addPhAction("/cameraLeft", JoinMap.CameraPanLeft.JoinNumber);
addPhAction("/cameraRight", JoinMap.CameraPanRight.JoinNumber);
addPhAction("/cameraZoomIn", JoinMap.CameraZoomIn.JoinNumber);
addPhAction("/cameraZoomOut", JoinMap.CameraZoomOut.JoinNumber);
// Add straight pulse calls using helper action
void addAction(string s, uint u) =>
AddAction(s, (id, content) => _eisc.PulseBool(u, 100));
addAction("/endCallById", JoinMap.EndCall.JoinNumber);
addAction("/endAllCalls", JoinMap.EndCall.JoinNumber);
addAction("/acceptById", JoinMap.IncomingAnswer.JoinNumber);
addAction("/rejectById", JoinMap.IncomingReject.JoinNumber);
var speeddialStart = JoinMap.SpeedDialStart.JoinNumber;
var speeddialEnd = JoinMap.SpeedDialStart.JoinNumber + JoinMap.SpeedDialStart.JoinSpan;
var speedDialIndex = 1;
for (uint i = speeddialStart; i < speeddialEnd; i++)
{
addAction(string.Format("/speedDial{0}", speedDialIndex), i);
speedDialIndex++;
}
addAction("/cameraModeAuto", JoinMap.CameraModeAuto.JoinNumber);
addAction("/cameraModeManual", JoinMap.CameraModeManual.JoinNumber);
addAction("/cameraModeOff", JoinMap.CameraModeOff.JoinNumber);
addAction("/cameraSelfView", JoinMap.CameraSelfView.JoinNumber);
addAction("/cameraLayout", JoinMap.CameraLayout.JoinNumber);
AddAction("/cameraSelect", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
SelectCamera(s.Value);
});
// camera presets
for (uint i = 0; i < 6; i++)
{
addAction("/cameraPreset" + (i + 1), JoinMap.CameraPresetStart.JoinNumber + i);
}
AddAction("/isReady", (id, content) => PostIsReady());
// Get status
AddAction("/fullStatus", (id, content) => PostFullStatus());
// Dial on string
AddAction("/dial", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
_eisc.SetString(JoinMap.CurrentDialString.JoinNumber, s.Value);
});
// Pulse DTMF
AddAction("/dtmf", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
var join = JoinMap.Joins[s.Value];
if (join != null)
{
if (join.JoinNumber > 0)
{
_eisc.PulseBool(join.JoinNumber, 100);
}
}
});
// Directory madness
AddAction("/directoryRoot",
(id, content) => _eisc.PulseBool(JoinMap.DirectoryRoot.JoinNumber));
AddAction("/directoryBack",
(id, content) => _eisc.PulseBool(JoinMap.DirectoryFolderBack.JoinNumber));
AddAction("/directoryById", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
// the id should contain the line number to forward to simpl
try
{
var u = ushort.Parse(s.Value);
_eisc.SetUshort(JoinMap.DirectorySelectRow.JoinNumber, u);
_eisc.PulseBool(JoinMap.DirectoryLineSelected.JoinNumber);
}
catch (Exception)
{
Debug.Console(1, this, Debug.ErrorLogLevel.Warning,
"/directoryById request contains non-numeric ID incompatible with SIMPL bridge");
}
});
AddAction("/directorySelectContact", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
try
{
var u = ushort.Parse(s.Value);
_eisc.SetUshort(JoinMap.DirectorySelectRow.JoinNumber, u);
_eisc.PulseBool(JoinMap.DirectoryLineSelected.JoinNumber);
}
catch
{
Debug.Console(2, this, "Error parsing contact from {0} for path /directorySelectContact", s);
}
});
AddAction("/directoryDialContact",
(id, content) => _eisc.PulseBool(JoinMap.DirectoryDialSelectedLine.JoinNumber));
AddAction("/getDirectory", (id, content) =>
{
if (_eisc.GetUshort(JoinMap.DirectoryRowCount.JoinNumber) > 0)
{
PostDirectory();
}
else
{
_eisc.PulseBool(JoinMap.DirectoryRoot.JoinNumber);
}
});
}
private void HandleCameraPressAndHold(JToken content, Action<bool> cameraAction)
{
var state = content.ToObject<MobileControlSimpleContent<string>>();
var timerHandler = PressAndHoldHandler.GetPressAndHoldHandler(state.Value);
if (timerHandler == null)
{
return;
}
timerHandler(state.Value, cameraAction);
cameraAction(state.Value.Equals("true", StringComparison.InvariantCultureIgnoreCase));
}
/// <summary>
///
/// </summary>
///
private void PostFullStatus()
{
PostStatusMessage(JToken.FromObject(new
{
calls = GetCurrentCallList(),
cameraMode = GetCameraMode(),
cameraSelfView = _eisc.GetBool(JoinMap.CameraSelfView.JoinNumber),
cameraSupportsAutoMode = _eisc.GetBool(JoinMap.CameraSupportsAutoMode.JoinNumber),
cameraSupportsOffMode = _eisc.GetBool(JoinMap.CameraSupportsOffMode.JoinNumber),
currentCallString = _eisc.GetString(JoinMap.CurrentCallNumber.JoinNumber),
currentDialString = _eisc.GetString(JoinMap.CurrentDialString.JoinNumber),
directoryContactSelected = new
{
name = _eisc.GetString(JoinMap.DirectoryEntrySelectedName.JoinNumber),
number = _eisc.GetString(JoinMap.DirectoryEntrySelectedNumber.JoinNumber)
},
directorySelectedFolderName = _eisc.GetString(JoinMap.DirectorySelectedFolderName.JoinNumber),
isInCall = _eisc.GetString(JoinMap.HookState.JoinNumber) == "Connected",
hasDirectory = true,
hasDirectorySearch = false,
hasRecents = !_eisc.BooleanOutput[502].BoolValue,
hasCameras = true,
showCamerasWhenNotInCall = _eisc.BooleanOutput[503].BoolValue,
selectedCamera = GetSelectedCamera(),
}));
}
/// <summary>
///
/// </summary>
private void PostDirectory()
{
var u = _eisc.GetUshort(JoinMap.DirectoryRowCount.JoinNumber);
var items = new List<object>();
for (uint i = 0; i < u; i++)
{
var name = _eisc.GetString(JoinMap.DirectoryEntriesStart.JoinNumber + i);
var id = (i + 1).ToString();
// is folder or contact?
if (name.StartsWith("[+]"))
{
items.Add(new
{
folderId = id,
name
});
}
else
{
items.Add(new
{
contactId = id,
name
});
}
}
var directoryMessage = new
{
currentDirectory = new
{
isRootDirectory = _eisc.GetBool(JoinMap.DirectoryIsRoot.JoinNumber),
directoryResults = items
}
};
PostStatusMessage(JToken.FromObject(directoryMessage));
}
/// <summary>
///
/// </summary>
private void PostCameraMode()
{
PostStatusMessage(JToken.FromObject(new
{
cameraMode = GetCameraMode()
}));
}
/// <summary>
///
/// </summary>
private string GetCameraMode()
{
string m;
if (_eisc.GetBool(JoinMap.CameraModeAuto.JoinNumber)) m = eCameraControlMode.Auto.ToString().ToLower();
else if (_eisc.GetBool(JoinMap.CameraModeManual.JoinNumber))
m = eCameraControlMode.Manual.ToString().ToLower();
else m = eCameraControlMode.Off.ToString().ToLower();
return m;
}
private void PostSelectedCamera()
{
PostStatusMessage(JToken.FromObject(new
{
selectedCamera = GetSelectedCamera()
}));
}
/// <summary>
///
/// </summary>
private string GetSelectedCamera()
{
var num = _eisc.GetUshort(JoinMap.CameraNumberSelect.JoinNumber);
string m;
if (num == 100)
{
m = "cameraFar";
}
else
{
m = "camera" + num;
}
return m;
}
/// <summary>
///
/// </summary>
private void PostIsReady()
{
PostStatusMessage(JToken.FromObject(new
{
isReady = true
}));
}
/// <summary>
///
/// </summary>
private void PostCallsList()
{
PostStatusMessage(JToken.FromObject(new
{
calls = GetCurrentCallList(),
}));
}
/// <summary>
///
/// </summary>
/// <param name="s"></param>
private void SelectCamera(string s)
{
var cam = s.Substring(6);
_eisc.SetUshort(JoinMap.CameraNumberSelect.JoinNumber,
(ushort)(cam.ToLower() == "far" ? 100 : ushort.Parse(cam)));
}
/// <summary>
/// Turns the
/// </summary>
/// <returns></returns>
private List<CodecActiveCallItem> GetCurrentCallList()
{
var list = new List<CodecActiveCallItem>();
if (_currentCallItem.Status != eCodecCallStatus.Disconnected)
{
list.Add(_currentCallItem);
}
if (_eisc.GetBool(JoinMap.IncomingCall.JoinNumber))
{
list.Add(_incomingCallItem);
}
return list;
}
}
}

View File

@@ -0,0 +1,100 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Shades;
using System;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IShadesOpenCloseStopMessenger : MessengerBase
{
private readonly IShadesOpenCloseStop device;
public IShadesOpenCloseStopMessenger(string key, IShadesOpenCloseStop shades, string messagePath)
: base(key, messagePath, shades as Device)
{
device = shades;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
AddAction("/shadeUp", (id, content) =>
{
device.Open();
});
AddAction("/shadeDown", (id, content) =>
{
device.Close();
});
var stopDevice = device;
if (stopDevice != null)
{
AddAction("/stopOrPreset", (id, content) =>
{
stopDevice.Stop();
});
}
if (device is IShadesOpenClosedFeedback feedbackDevice)
{
feedbackDevice.ShadeIsOpenFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>(ShadeIsOpenFeedback_OutputChange);
feedbackDevice.ShadeIsClosedFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>(ShadeIsClosedFeedback_OutputChange);
}
}
private void ShadeIsOpenFeedback_OutputChange(object sender, Core.FeedbackEventArgs e)
{
var state = new ShadeBaseStateMessage
{
IsOpen = e.BoolValue
};
PostStatusMessage(state);
}
private void ShadeIsClosedFeedback_OutputChange(object sender, Core.FeedbackEventArgs e)
{
var state = new ShadeBaseStateMessage
{
IsClosed = e.BoolValue
};
PostStatusMessage(state);
}
private void SendFullStatus()
{
var state = new ShadeBaseStateMessage();
if (device is IShadesOpenClosedFeedback feedbackDevice)
{
state.IsOpen = feedbackDevice.ShadeIsOpenFeedback.BoolValue;
state.IsClosed = feedbackDevice.ShadeIsClosedFeedback.BoolValue;
}
PostStatusMessage(state);
}
}
public class ShadeBaseStateMessage : DeviceStateMessageBase
{
[JsonProperty("middleButtonLabel", NullValueHandling = NullValueHandling.Ignore)]
public string MiddleButtonLabel { get; set; }
[JsonProperty("isOpen", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsOpen { get; set; }
[JsonProperty("isClosed", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsClosed { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.AppServer.Messengers
{
/// <summary>
/// Properties to configure a SIMPL Messenger
/// </summary>
public class SimplMessengerPropertiesConfig : EiscApiPropertiesConfig.ApiDevicePropertiesConfig
{
}
}

View File

@@ -0,0 +1,109 @@
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core.Monitoring;
using System;
using System.Threading.Tasks;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class SystemMonitorMessenger : MessengerBase
{
private readonly SystemMonitorController systemMonitor;
public SystemMonitorMessenger(string key, SystemMonitorController sysMon, string messagePath)
: base(key, messagePath, sysMon)
{
systemMonitor = sysMon ?? throw new ArgumentNullException("sysMon");
systemMonitor.SystemMonitorPropertiesChanged += SysMon_SystemMonitorPropertiesChanged;
foreach (var p in systemMonitor.ProgramStatusFeedbackCollection)
{
p.Value.ProgramInfoChanged += 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>
private void ProgramInfoChanged(object sender, ProgramInfoEventArgs e)
{
if (e.ProgramInfo != null)
{
//Debug.Console(1, "Posting Status Message: {0}", e.ProgramInfo.ToString());
PostStatusMessage(JToken.FromObject(e.ProgramInfo)
);
}
}
/// <summary>
/// Posts the system monitor properties
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SysMon_SystemMonitorPropertiesChanged(object sender, EventArgs e)
{
SendSystemMonitorStatusMessage();
}
private void SendFullStatusMessage()
{
SendSystemMonitorStatusMessage();
foreach (var p in systemMonitor.ProgramStatusFeedbackCollection)
{
PostStatusMessage(JToken.FromObject(p.Value.ProgramInfo));
}
}
private void SendSystemMonitorStatusMessage()
{
// This takes a while, launch a new thread
Task.Run(() => PostStatusMessage(JToken.FromObject(new SystemMonitorStateMessage
{
TimeZone = systemMonitor.TimeZoneFeedback.IntValue,
TimeZoneName = systemMonitor.TimeZoneTextFeedback.StringValue,
IoControllerVersion = systemMonitor.IoControllerVersionFeedback.StringValue,
SnmpVersion = systemMonitor.SnmpVersionFeedback.StringValue,
BacnetVersion = systemMonitor.BaCnetAppVersionFeedback.StringValue,
ControllerVersion = systemMonitor.ControllerVersionFeedback.StringValue
})
));
}
protected override void RegisterActions()
{
AddAction("/fullStatus", (id, content) => SendFullStatusMessage());
}
}
public class SystemMonitorStateMessage
{
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
public int TimeZone { get; set; }
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
public string TimeZoneName { get; set; }
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
public string IoControllerVersion { get; set; }
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
public string SnmpVersion { get; set; }
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
public string BacnetVersion { get; set; }
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
public string ControllerVersion { get; set; }
}
}

View File

@@ -0,0 +1,97 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.Displays;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class TwoWayDisplayBaseMessenger : MessengerBase
{
private readonly TwoWayDisplayBase _display;
public TwoWayDisplayBaseMessenger(string key, string messagePath) : base(key, messagePath)
{
}
public TwoWayDisplayBaseMessenger(string key, string messagePath, TwoWayDisplayBase display)
: this(key, messagePath)
{
_display = display;
}
#region Overrides of MessengerBase
public void SendFullStatus()
{
var messageObj = new TwoWayDisplayBaseStateMessage
{
//PowerState = _display.PowerIsOnFeedback.BoolValue,
CurrentInput = _display.CurrentInputFeedback.StringValue
};
PostStatusMessage(messageObj);
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
//_display.PowerIsOnFeedback.OutputChange += PowerIsOnFeedbackOnOutputChange;
_display.CurrentInputFeedback.OutputChange += CurrentInputFeedbackOnOutputChange;
_display.IsCoolingDownFeedback.OutputChange += IsCoolingFeedbackOnOutputChange;
_display.IsWarmingUpFeedback.OutputChange += IsWarmingFeedbackOnOutputChange;
}
private void CurrentInputFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs)
{
PostStatusMessage(JToken.FromObject(new
{
currentInput = feedbackEventArgs.StringValue
})
);
}
//private void PowerIsOnFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs)
//{
// PostStatusMessage(JToken.FromObject(new
// {
// powerState = feedbackEventArgs.BoolValue
// })
// );
//}
private void IsWarmingFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs)
{
PostStatusMessage(JToken.FromObject(new
{
isWarming = feedbackEventArgs.BoolValue
})
);
}
private void IsCoolingFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs)
{
PostStatusMessage(JToken.FromObject(new
{
isCooling = feedbackEventArgs.BoolValue
})
);
}
#endregion
}
public class TwoWayDisplayBaseStateMessage : DeviceStateMessageBase
{
//[JsonProperty("powerState", NullValueHandling = NullValueHandling.Ignore)]
//public bool? PowerState { get; set; }
[JsonProperty("currentInput", NullValueHandling = NullValueHandling.Ignore)]
public string CurrentInput { get; set; }
}
}

View File

@@ -0,0 +1,999 @@
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Devices.Common.Cameras;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using static PepperDash.Essentials.AppServer.Messengers.VideoCodecBaseStateMessage.CameraStatus;
namespace PepperDash.Essentials.AppServer.Messengers
{
/// <summary>
/// Provides a messaging bridge for a VideoCodecBase device
/// </summary>
public class VideoCodecBaseMessenger : MessengerBase
{
/// <summary>
///
/// </summary>
protected VideoCodecBase Codec { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="codec"></param>
/// <param name="messagePath"></param>
public VideoCodecBaseMessenger(string key, VideoCodecBase codec, string messagePath)
: base(key, messagePath, codec)
{
Codec = codec ?? throw new ArgumentNullException("codec");
codec.CallStatusChange += Codec_CallStatusChange;
codec.IsReadyChange += Codec_IsReadyChange;
if (codec is IHasDirectory dirCodec)
{
dirCodec.DirectoryResultReturned += DirCodec_DirectoryResultReturned;
}
if (codec is IHasCallHistory recCodec)
{
recCodec.CallHistory.RecentCallsListHasChanged += CallHistory_RecentCallsListHasChanged;
}
if (codec is IPasswordPrompt pwPromptCodec)
{
pwPromptCodec.PasswordRequired += OnPasswordRequired;
}
}
private void OnPasswordRequired(object sender, PasswordPromptEventArgs args)
{
var eventMsg = new PasswordPromptEventMessage
{
Message = args.Message,
LastAttemptWasIncorrect = args.LastAttemptWasIncorrect,
LoginAttemptFailed = args.LoginAttemptFailed,
LoginAttemptCancelled = args.LoginAttemptCancelled,
EventType = "passwordPrompt"
};
PostEventMessage(eventMsg);
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CallHistory_RecentCallsListHasChanged(object sender, EventArgs e)
{
var state = new VideoCodecBaseStateMessage();
if (!(sender is CodecCallHistory codecCallHistory)) return;
var recents = codecCallHistory.RecentCalls;
if (recents != null)
{
state.RecentCalls = recents;
PostStatusMessage(state);
}
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected virtual void DirCodec_DirectoryResultReturned(object sender, DirectoryEventArgs e)
{
if (Codec is IHasDirectory)
SendDirectory(e.Directory);
}
/// <summary>
/// Posts the current directory
/// </summary>
protected void SendDirectory(CodecDirectory directory)
{
var state = new VideoCodecBaseStateMessage();
if (Codec is IHasDirectory dirCodec)
{
this.LogVerbose("Sending Directory. Directory Item Count: {directoryItemCount}", directory.CurrentDirectoryResults.Count);
//state.CurrentDirectory = PrefixDirectoryFolderItems(directory);
state.CurrentDirectory = directory;
CrestronInvoke.BeginInvoke((o) => PostStatusMessage(state));
/* var directoryMessage = new
{
currentDirectory = new
{
directoryResults = prefixedDirectoryResults,
isRootDirectory = isRoot
}
};
//Spool up a thread in case this is a large quantity of data
CrestronInvoke.BeginInvoke((o) => PostStatusMessage(directoryMessage)); */
}
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Codec_IsReadyChange(object sender, EventArgs e)
{
var state = new VideoCodecBaseStateMessage
{
IsReady = true
};
PostStatusMessage(state);
SendFullStatus();
}
/// <summary>
/// Called from base's RegisterWithAppServer method
/// </summary>
/// <param name="appServerController"></param>
protected override void RegisterActions()
{
try
{
base.RegisterActions();
AddAction("/isReady", (id, content) => SendIsReady());
AddAction("/fullStatus", (id, content) => SendFullStatus());
AddAction("/dial", (id, content) =>
{
var value = content.ToObject<MobileControlSimpleContent<string>>();
Codec.Dial(value.Value);
});
AddAction("/dialMeeting", (id, content) => Codec.Dial(content.ToObject<Meeting>()));
AddAction("/endCallById", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
var call = GetCallWithId(s.Value);
if (call != null)
Codec.EndCall(call);
});
AddAction("/endAllCalls", (id, content) => Codec.EndAllCalls());
AddAction("/dtmf", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
Codec.SendDtmf(s.Value);
});
AddAction("/rejectById", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
var call = GetCallWithId(s.Value);
if (call != null)
Codec.RejectCall(call);
});
AddAction("/acceptById", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
var call = GetCallWithId(s.Value);
if (call != null)
Codec.AcceptCall(call);
});
Codec.SharingContentIsOnFeedback.OutputChange += SharingContentIsOnFeedback_OutputChange;
Codec.SharingSourceFeedback.OutputChange += SharingSourceFeedback_OutputChange;
// Directory actions
if (Codec is IHasDirectory dirCodec)
{
AddAction("/getDirectory", (id, content) => GetDirectoryRoot());
AddAction("/directoryById", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
GetDirectory(msg.Value);
});
AddAction("/directorySearch", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
GetDirectory(msg.Value);
});
AddAction("/directoryBack", (id, content) => GetPreviousDirectory());
dirCodec.PhonebookSyncState.InitialSyncCompleted += PhonebookSyncState_InitialSyncCompleted;
}
// History actions
if (Codec is IHasCallHistory recCodec)
{
AddAction("/getCallHistory", (id, content) => PostCallHistory());
}
if (Codec is IHasCodecCameras cameraCodec)
{
this.LogVerbose("Adding IHasCodecCameras Actions");
cameraCodec.CameraSelected += CameraCodec_CameraSelected;
AddAction("/cameraSelect", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
cameraCodec.SelectCamera(msg.Value);
});
MapCameraActions();
if (Codec is IHasCodecRoomPresets presetsCodec)
{
this.LogVerbose("Adding IHasCodecRoomPresets Actions");
presetsCodec.CodecRoomPresetsListHasChanged += PresetsCodec_CameraPresetsListHasChanged;
AddAction("/cameraPreset", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<int>>();
presetsCodec.CodecRoomPresetSelect(msg.Value);
});
AddAction("/cameraPresetStore", (id, content) =>
{
var msg = content.ToObject<CodecRoomPreset>();
presetsCodec.CodecRoomPresetStore(msg.ID, msg.Description);
});
}
if (Codec is IHasCameraAutoMode speakerTrackCodec)
{
this.LogVerbose("Adding IHasCameraAutoMode Actions");
speakerTrackCodec.CameraAutoModeIsOnFeedback.OutputChange += CameraAutoModeIsOnFeedback_OutputChange;
AddAction("/cameraModeAuto", (id, content) => speakerTrackCodec.CameraAutoModeOn());
AddAction("/cameraModeManual", (id, content) => speakerTrackCodec.CameraAutoModeOff());
}
if (Codec is IHasCameraOff cameraOffCodec)
{
this.LogVerbose("Adding IHasCameraOff Actions");
cameraOffCodec.CameraIsOffFeedback.OutputChange += (CameraIsOffFeedback_OutputChange);
AddAction("/cameraModeOff", (id, content) => cameraOffCodec.CameraOff());
}
}
if (Codec is IHasCodecSelfView selfViewCodec)
{
this.LogVerbose("Adding IHasCodecSelfView Actions");
AddAction("/cameraSelfView", (id, content) => selfViewCodec.SelfViewModeToggle());
selfViewCodec.SelfviewIsOnFeedback.OutputChange += new EventHandler<FeedbackEventArgs>(SelfviewIsOnFeedback_OutputChange);
}
if (Codec is IHasCodecLayouts layoutsCodec)
{
this.LogVerbose("Adding IHasCodecLayouts Actions");
AddAction("/cameraRemoteView", (id, content) => layoutsCodec.LocalLayoutToggle());
AddAction("/cameraLayout", (id, content) => layoutsCodec.LocalLayoutToggle());
}
if (Codec is IPasswordPrompt pwCodec)
{
this.LogVerbose("Adding IPasswordPrompt Actions");
AddAction("/password", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
pwCodec.SubmitPassword(msg.Value);
});
}
if (Codec is IHasFarEndContentStatus farEndContentStatus)
{
farEndContentStatus.ReceivingContent.OutputChange +=
(sender, args) => PostReceivingContent(args.BoolValue);
}
this.LogVerbose("Adding Privacy & Standby Actions");
AddAction("/privacyModeOn", (id, content) => Codec.PrivacyModeOn());
AddAction("/privacyModeOff", (id, content) => Codec.PrivacyModeOff());
AddAction("/privacyModeToggle", (id, content) => Codec.PrivacyModeToggle());
AddAction("/sharingStart", (id, content) => Codec.StartSharing());
AddAction("/sharingStop", (id, content) => Codec.StopSharing());
AddAction("/standbyOn", (id, content) => Codec.StandbyActivate());
AddAction("/standbyOff", (id, content) => Codec.StandbyDeactivate());
}
catch (Exception e)
{
this.LogException(e, "Exception adding paths");
}
}
private void SharingSourceFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
var state = new VideoCodecBaseStateMessage
{
SharingSource = e.StringValue
};
PostStatusMessage(state);
}
private void SharingContentIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
var state = new VideoCodecBaseStateMessage
{
SharingContentIsOn = e.BoolValue
};
PostStatusMessage(state);
}
private void PhonebookSyncState_InitialSyncCompleted(object sender, EventArgs e)
{
var state = new VideoCodecBaseStateMessage
{
InitialPhonebookSyncComplete = true
};
PostStatusMessage(state);
}
private void CameraIsOffFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
PostCameraMode();
}
private void SelfviewIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
PostCameraSelfView();
}
private void PresetsCodec_CameraPresetsListHasChanged(object sender, EventArgs e)
{
PostCameraPresets();
}
private void CameraAutoModeIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
PostCameraMode();
}
private void CameraCodec_CameraSelected(object sender, CameraSelectedEventArgs e)
{
MapCameraActions();
PostSelectedCamera();
}
/// <summary>
/// Maps the camera control actions to the current selected camera on the codec
/// </summary>
private void MapCameraActions()
{
if (Codec is IHasCameras cameraCodec && cameraCodec.SelectedCamera != null)
{
RemoveAction("/cameraUp");
RemoveAction("/cameraDown");
RemoveAction("/cameraLeft");
RemoveAction("/cameraRight");
RemoveAction("/cameraZoomIn");
RemoveAction("/cameraZoomOut");
RemoveAction("/cameraHome");
if (cameraCodec.SelectedCamera is IHasCameraPtzControl camera)
{
AddAction("/cameraUp", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
camera.TiltUp();
return;
}
camera.TiltStop();
}));
AddAction("/cameraDown", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
camera.TiltDown();
return;
}
camera.TiltStop();
}));
AddAction("/cameraLeft", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
camera.PanLeft();
return;
}
camera.PanStop();
}));
AddAction("/cameraRight", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
camera.PanRight();
return;
}
camera.PanStop();
}));
AddAction("/cameraZoomIn", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
camera.ZoomIn();
return;
}
camera.ZoomStop();
}));
AddAction("/cameraZoomOut", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
camera.ZoomOut();
return;
}
camera.ZoomStop();
}));
AddAction("/cameraHome", (id, content) => camera.PositionHome());
RemoveAction("/cameraAutoFocus");
RemoveAction("/cameraFocusNear");
RemoveAction("/cameraFocusFar");
if (cameraCodec is IHasCameraFocusControl focusCamera)
{
AddAction("/cameraAutoFocus", (id, content) => focusCamera.TriggerAutoFocus());
AddAction("/cameraFocusNear", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
focusCamera.FocusNear();
return;
}
focusCamera.FocusStop();
}));
AddAction("/cameraFocusFar", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
focusCamera.FocusFar();
return;
}
focusCamera.FocusStop();
}));
}
}
}
}
private void HandleCameraPressAndHold(JToken content, Action<bool> cameraAction)
{
var state = content.ToObject<MobileControlSimpleContent<string>>();
var timerHandler = PressAndHoldHandler.GetPressAndHoldHandler(state.Value);
if (timerHandler == null)
{
return;
}
timerHandler(state.Value, cameraAction);
cameraAction(state.Value.Equals("true", StringComparison.InvariantCultureIgnoreCase));
}
private string GetCameraMode()
{
string m = "";
if (Codec is IHasCameraAutoMode speakerTrackCodec)
{
m = speakerTrackCodec.CameraAutoModeIsOnFeedback.BoolValue
? eCameraControlMode.Auto.ToString().ToLower()
: eCameraControlMode.Manual.ToString().ToLower();
}
if (Codec is IHasCameraOff cameraOffCodec)
{
if (cameraOffCodec.CameraIsOffFeedback.BoolValue)
m = eCameraControlMode.Off.ToString().ToLower();
}
return m;
}
private void PostCallHistory()
{
var codec = (Codec as IHasCallHistory);
if (codec != null)
{
var status = new VideoCodecBaseStateMessage();
var recents = codec.CallHistory.RecentCalls;
if (recents != null)
{
status.RecentCalls = codec.CallHistory.RecentCalls;
PostStatusMessage(status);
}
}
}
/// <summary>
/// Helper to grab a call with string ID
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
private CodecActiveCallItem GetCallWithId(string id)
{
return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id);
}
/// <summary>
///
/// </summary>
/// <param name="id"></param>
private void GetDirectory(string id)
{
if (!(Codec is IHasDirectory dirCodec))
{
return;
}
dirCodec.GetDirectoryFolderContents(id);
}
/// <summary>
///
/// </summary>
private void GetDirectoryRoot()
{
if (!(Codec is IHasDirectory dirCodec))
{
// do something else?
return;
}
if (!dirCodec.PhonebookSyncState.InitialSyncComplete)
{
var state = new VideoCodecBaseStateMessage
{
InitialPhonebookSyncComplete = false
};
PostStatusMessage(state);
return;
}
dirCodec.SetCurrentDirectoryToRoot();
}
/// <summary>
/// Requests the parent folder contents
/// </summary>
private void GetPreviousDirectory()
{
if (!(Codec is IHasDirectory dirCodec))
{
return;
}
dirCodec.GetDirectoryParentFolderContents();
}
/// <summary>
/// Handler for codec changes
/// </summary>
private void Codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
{
SendFullStatus();
}
/// <summary>
///
/// </summary>
private void SendIsReady()
{
var status = new VideoCodecBaseStateMessage();
var codecType = Codec.GetType();
status.IsReady = Codec.IsReady;
status.IsZoomRoom = codecType.GetInterface("IHasZoomRoomLayouts") != null;
PostStatusMessage(status);
}
/// <summary>
/// Helper method to build call status for vtc
/// </summary>
/// <returns></returns>
protected VideoCodecBaseStateMessage GetStatus()
{
var status = new VideoCodecBaseStateMessage();
if (Codec is IHasCodecCameras camerasCodec)
{
status.Cameras = new VideoCodecBaseStateMessage.CameraStatus
{
CameraManualIsSupported = true,
CameraAutoIsSupported = Codec.SupportsCameraAutoMode,
CameraOffIsSupported = Codec.SupportsCameraOff,
CameraMode = GetCameraMode(),
Cameras = camerasCodec.Cameras,
SelectedCamera = GetSelectedCamera(camerasCodec)
};
}
if (Codec is IHasDirectory directoryCodec)
{
status.HasDirectory = true;
status.HasDirectorySearch = true;
status.CurrentDirectory = directoryCodec.CurrentDirectoryResult;
}
var codecType = Codec.GetType();
status.CameraSelfViewIsOn = Codec is IHasCodecSelfView && (Codec as IHasCodecSelfView).SelfviewIsOnFeedback.BoolValue;
status.IsInCall = Codec.IsInCall;
status.PrivacyModeIsOn = Codec.PrivacyModeIsOnFeedback.BoolValue;
status.SharingContentIsOn = Codec.SharingContentIsOnFeedback.BoolValue;
status.SharingSource = Codec.SharingSourceFeedback.StringValue;
status.StandbyIsOn = Codec.StandbyIsOnFeedback.BoolValue;
status.Calls = Codec.ActiveCalls;
status.Info = Codec.CodecInfo;
status.ShowSelfViewByDefault = Codec.ShowSelfViewByDefault;
status.SupportsAdHocMeeting = Codec is IHasStartMeeting;
status.HasRecents = Codec is IHasCallHistory;
status.HasCameras = Codec is IHasCameras;
status.Presets = GetCurrentPresets();
status.IsZoomRoom = codecType.GetInterface("IHasZoomRoomLayouts") != null;
status.ReceivingContent = Codec is IHasFarEndContentStatus && (Codec as IHasFarEndContentStatus).ReceivingContent.BoolValue;
if (Codec is IHasMeetingInfo meetingInfoCodec)
{
status.MeetingInfo = meetingInfoCodec.MeetingInfo;
}
//Debug.Console(2, this, "VideoCodecBaseStatus:\n{0}", JsonConvert.SerializeObject(status));
return status;
}
protected virtual void SendFullStatus()
{
if (!Codec.IsReady)
{
return;
}
CrestronInvoke.BeginInvoke((o) => PostStatusMessage(GetStatus()));
}
private void PostReceivingContent(bool receivingContent)
{
var state = new VideoCodecBaseStateMessage
{
ReceivingContent = receivingContent
};
PostStatusMessage(state);
}
private void PostCameraSelfView()
{
var status = new VideoCodecBaseStateMessage
{
CameraSelfViewIsOn = Codec is IHasCodecSelfView
&& (Codec as IHasCodecSelfView).SelfviewIsOnFeedback.BoolValue
};
PostStatusMessage(status);
}
/// <summary>
///
/// </summary>
private void PostCameraMode()
{
var status = new VideoCodecBaseStateMessage
{
CameraMode = GetCameraMode()
};
PostStatusMessage(status);
}
private void PostSelectedCamera()
{
var camerasCodec = Codec as IHasCodecCameras;
var status = new VideoCodecBaseStateMessage
{
Cameras = new VideoCodecBaseStateMessage.CameraStatus() { SelectedCamera = GetSelectedCamera(camerasCodec) },
Presets = GetCurrentPresets()
};
PostStatusMessage(status);
}
private void PostCameraPresets()
{
var status = new VideoCodecBaseStateMessage
{
Presets = GetCurrentPresets()
};
PostStatusMessage(status);
}
private Camera GetSelectedCamera(IHasCodecCameras camerasCodec)
{
var camera = new Camera();
if (camerasCodec.SelectedCameraFeedback != null)
camera.Key = camerasCodec.SelectedCameraFeedback.StringValue;
if (camerasCodec.SelectedCamera != null)
{
camera.Name = camerasCodec.SelectedCamera.Name;
camera.Capabilities = new Camera.CameraCapabilities()
{
CanPan = camerasCodec.SelectedCamera.CanPan,
CanTilt = camerasCodec.SelectedCamera.CanTilt,
CanZoom = camerasCodec.SelectedCamera.CanZoom,
CanFocus = camerasCodec.SelectedCamera.CanFocus,
};
}
if (camerasCodec.ControllingFarEndCameraFeedback != null)
camera.IsFarEnd = camerasCodec.ControllingFarEndCameraFeedback.BoolValue;
return camera;
}
private List<CodecRoomPreset> GetCurrentPresets()
{
var presetsCodec = Codec as IHasCodecRoomPresets;
List<CodecRoomPreset> currentPresets = null;
if (presetsCodec != null && Codec is IHasFarEndCameraControl &&
(Codec as IHasFarEndCameraControl).ControllingFarEndCameraFeedback.BoolValue)
currentPresets = presetsCodec.FarEndRoomPresets;
else if (presetsCodec != null) currentPresets = presetsCodec.NearEndPresets;
return currentPresets;
}
}
/// <summary>
/// A class that represents the state data to be sent to the user app
/// </summary>
public class VideoCodecBaseStateMessage : DeviceStateMessageBase
{
[JsonProperty("calls", NullValueHandling = NullValueHandling.Ignore)]
public List<CodecActiveCallItem> Calls { get; set; }
[JsonProperty("cameraMode", NullValueHandling = NullValueHandling.Ignore)]
public string CameraMode { get; set; }
[JsonProperty("cameraSelfView", NullValueHandling = NullValueHandling.Ignore)]
public bool? CameraSelfViewIsOn { get; set; }
[JsonProperty("cameras", NullValueHandling = NullValueHandling.Ignore)]
public CameraStatus Cameras { get; set; }
[JsonProperty("cameraSupportsAutoMode", NullValueHandling = NullValueHandling.Ignore)]
public bool? CameraSupportsAutoMode { get; set; }
[JsonProperty("cameraSupportsOffMode", NullValueHandling = NullValueHandling.Ignore)]
public bool? CameraSupportsOffMode { get; set; }
[JsonProperty("currentDialString", NullValueHandling = NullValueHandling.Ignore)]
public string CurrentDialString { get; set; }
[JsonProperty("currentDirectory", NullValueHandling = NullValueHandling.Ignore)]
public CodecDirectory CurrentDirectory { get; set; }
[JsonProperty("directorySelectedFolderName", NullValueHandling = NullValueHandling.Ignore)]
public string DirectorySelectedFolderName { get; set; }
[JsonProperty("hasCameras", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasCameras { get; set; }
[JsonProperty("hasDirectory", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasDirectory { get; set; }
[JsonProperty("hasDirectorySearch", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasDirectorySearch { get; set; }
[JsonProperty("hasPresets", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasPresets { get; set; }
[JsonProperty("hasRecents", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasRecents { get; set; }
[JsonProperty("initialPhonebookSyncComplete", NullValueHandling = NullValueHandling.Ignore)]
public bool? InitialPhonebookSyncComplete { get; set; }
[JsonProperty("info", NullValueHandling = NullValueHandling.Ignore)]
public VideoCodecInfo Info { get; set; }
[JsonProperty("isInCall", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsInCall { get; set; }
[JsonProperty("isReady", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsReady { get; set; }
[JsonProperty("isZoomRoom", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsZoomRoom { get; set; }
[JsonProperty("meetingInfo", NullValueHandling = NullValueHandling.Ignore)]
public MeetingInfo MeetingInfo { get; set; }
[JsonProperty("presets", NullValueHandling = NullValueHandling.Ignore)]
public List<CodecRoomPreset> Presets { get; set; }
[JsonProperty("privacyModeIsOn", NullValueHandling = NullValueHandling.Ignore)]
public bool? PrivacyModeIsOn { get; set; }
[JsonProperty("receivingContent", NullValueHandling = NullValueHandling.Ignore)]
public bool? ReceivingContent { get; set; }
[JsonProperty("recentCalls", NullValueHandling = NullValueHandling.Ignore)]
public List<CodecCallHistory.CallHistoryEntry> RecentCalls { get; set; }
[JsonProperty("sharingContentIsOn", NullValueHandling = NullValueHandling.Ignore)]
public bool? SharingContentIsOn { get; set; }
[JsonProperty("sharingSource", NullValueHandling = NullValueHandling.Ignore)]
public string SharingSource { get; set; }
[JsonProperty("showCamerasWhenNotInCall", NullValueHandling = NullValueHandling.Ignore)]
public bool? ShowCamerasWhenNotInCall { get; set; }
[JsonProperty("showSelfViewByDefault", NullValueHandling = NullValueHandling.Ignore)]
public bool? ShowSelfViewByDefault { get; set; }
[JsonProperty("standbyIsOn", NullValueHandling = NullValueHandling.Ignore)]
public bool? StandbyIsOn { get; set; }
[JsonProperty("supportsAdHocMeeting", NullValueHandling = NullValueHandling.Ignore)]
public bool? SupportsAdHocMeeting { get; set; }
public class CameraStatus
{
[JsonProperty("cameraManualSupported", NullValueHandling = NullValueHandling.Ignore)]
public bool? CameraManualIsSupported { get; set; }
[JsonProperty("cameraAutoSupported", NullValueHandling = NullValueHandling.Ignore)]
public bool? CameraAutoIsSupported { get; set; }
[JsonProperty("cameraOffSupported", NullValueHandling = NullValueHandling.Ignore)]
public bool? CameraOffIsSupported { get; set; }
[JsonProperty("cameraMode", NullValueHandling = NullValueHandling.Ignore)]
public string CameraMode { get; set; }
[JsonProperty("cameraList", NullValueHandling = NullValueHandling.Ignore)]
public List<CameraBase> Cameras { get; set; }
[JsonProperty("selectedCamera", NullValueHandling = NullValueHandling.Ignore)]
public Camera SelectedCamera { get; set; }
public class Camera
{
[JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)]
public string Key { get; set; }
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }
[JsonProperty("isFarEnd", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsFarEnd { get; set; }
[JsonProperty("capabilities", NullValueHandling = NullValueHandling.Ignore)]
public CameraCapabilities Capabilities { get; set; }
public class CameraCapabilities
{
[JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)]
public bool? CanPan { get; set; }
[JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)]
public bool? CanTilt { get; set; }
[JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)]
public bool? CanZoom { get; set; }
[JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)]
public bool? CanFocus { get; set; }
}
}
}
}
public class VideoCodecBaseEventMessage : DeviceEventMessageBase
{
}
public class PasswordPromptEventMessage : VideoCodecBaseEventMessage
{
[JsonProperty("message", NullValueHandling = NullValueHandling.Ignore)]
public string Message { get; set; }
[JsonProperty("lastAttemptWasIncorrect", NullValueHandling = NullValueHandling.Ignore)]
public bool LastAttemptWasIncorrect { get; set; }
[JsonProperty("loginAttemptFailed", NullValueHandling = NullValueHandling.Ignore)]
public bool LoginAttemptFailed { get; set; }
[JsonProperty("loginAttemptCancelled", NullValueHandling = NullValueHandling.Ignore)]
public bool LoginAttemptCancelled { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class MobileControlMessage : IMobileControlMessage
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("clientId")]
public string ClientId { get; set; }
[JsonProperty("content")]
public JToken Content { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
using Newtonsoft.Json;
namespace PepperDash.Essentials.AppServer
{
public class MobileControlSimpleContent<T>
{
[JsonProperty("value", NullValueHandling = NullValueHandling.Ignore)]
public T Value { get; set; }
}
}

View File

@@ -0,0 +1,56 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectType>ProgramLibrary</ProjectType>
</PropertyGroup>
<PropertyGroup>
<RootNamespace>PepperDash.Essentials.AppServer</RootNamespace>
<TargetFramework>net472</TargetFramework>
<AssemblyTitle>mobile-control-messengers</AssemblyTitle>
<AssemblyName>mobile-control-messengers</AssemblyName>
<Product>mobile-control-messengers</Product>
<Copyright>Copyright © 2024</Copyright>
<OutputPath>bin\$(Configuration)\</OutputPath>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<InformationalVersion>$(Version)</InformationalVersion>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<Authors>PepperDash Technology</Authors>
<PackageId>PepperDash.Essentials.MobileControl.Messengers</PackageId>
<PackageTags>crestron 4series</PackageTags>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType>
<DefineConstants>$(DefineConstants);SERIES4</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<DefineConstants>$(DefineConstants);SERIES4</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Messengers\SIMPLAtcMessenger.cs" />
<Compile Remove="Messengers\SIMPLCameraMessenger.cs" />
<Compile Remove="Messengers\SIMPLDirectRouteMessenger.cs" />
<Compile Remove="Messengers\SimplMessengerPropertiesConfig.cs" />
<Compile Remove="Messengers\SIMPLRouteMessenger.cs" />
<Compile Remove="Messengers\SIMPLVtcMessenger.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.21.90" />
<PackageReference Include="PepperDashCore" Version="2.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj">
<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
<ProjectReference Include="..\PepperDash.Essentials.Devices.Common\PepperDash.Essentials.Devices.Common.csproj">
<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Net.Http" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,570 @@
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer
{
// ReSharper disable once InconsistentNaming
public class MobileControlSIMPLRoomJoinMap : JoinMapBaseAdvanced
{
[JoinName("QrCodeUrl")]
public JoinDataComplete QrCodeUrl =
new JoinDataComplete(new JoinData { JoinNumber = 403, JoinSpan = 1 },
new JoinMetadata
{
Description = "QR Code URL",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("PortalSystemUrl")]
public JoinDataComplete PortalSystemUrl =
new JoinDataComplete(new JoinData { JoinNumber = 404, JoinSpan = 1 },
new JoinMetadata
{
Description = "Portal System URL",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("MasterVolume")]
public JoinDataComplete MasterVolume =
new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata
{
Description = "Master Volume Mute Toggle/FB/Level/Label",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.DigitalAnalogSerial
});
[JoinName("VolumeJoinStart")]
public JoinDataComplete VolumeJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 8 },
new JoinMetadata
{
Description = "Volume Mute Toggle/FB/Level/Label",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.DigitalAnalogSerial
});
[JoinName("PrivacyMute")]
public JoinDataComplete PrivacyMute =
new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 },
new JoinMetadata
{
Description = "Privacy Mute Toggle/FB",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("PromptForCode")]
public JoinDataComplete PromptForCode =
new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 },
new JoinMetadata
{
Description = "Prompt User for Code",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ClientJoined")]
public JoinDataComplete ClientJoined =
new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 },
new JoinMetadata
{
Description = "Client Joined",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ActivityPhoneCallEnable")]
public JoinDataComplete ActivityPhoneCallEnable =
new JoinDataComplete(new JoinData { JoinNumber = 48, JoinSpan = 1 },
new JoinMetadata
{
Description = "Enable Activity Phone Call",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ActivityVideoCallEnable")]
public JoinDataComplete ActivityVideoCallEnable =
new JoinDataComplete(new JoinData { JoinNumber = 49, JoinSpan = 1 },
new JoinMetadata
{
Description = "Enable Activity Video Call",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ActivityShare")]
public JoinDataComplete ActivityShare =
new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 },
new JoinMetadata
{
Description = "Activity Share",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ActivityPhoneCall")]
public JoinDataComplete ActivityPhoneCall =
new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1 },
new JoinMetadata
{
Description = "Activity Phone Call",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ActivityVideoCall")]
public JoinDataComplete ActivityVideoCall =
new JoinDataComplete(new JoinData { JoinNumber = 53, JoinSpan = 1 },
new JoinMetadata
{
Description = "Activity Video Call",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ShutdownPromptDuration")]
public JoinDataComplete ShutdownPromptDuration =
new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1 },
new JoinMetadata
{
Description = "Shutdown Cancel",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("ShutdownCancel")]
public JoinDataComplete ShutdownCancel =
new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1 },
new JoinMetadata
{
Description = "Shutdown Cancel",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ShutdownEnd")]
public JoinDataComplete ShutdownEnd =
new JoinDataComplete(new JoinData { JoinNumber = 62, JoinSpan = 1 },
new JoinMetadata
{
Description = "Shutdown End",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ShutdownStart")]
public JoinDataComplete ShutdownStart =
new JoinDataComplete(new JoinData { JoinNumber = 63, JoinSpan = 1 },
new JoinMetadata
{
Description = "Shutdown Start",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SourceHasChanged")]
public JoinDataComplete SourceHasChanged =
new JoinDataComplete(new JoinData { JoinNumber = 71, JoinSpan = 1 },
new JoinMetadata
{
Description = "Source Changed",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CurrentSourceKey")]
public JoinDataComplete CurrentSourceKey =
new JoinDataComplete(new JoinData { JoinNumber = 71, JoinSpan = 1 },
new JoinMetadata
{
Description = "Key of selected source",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ConfigIsLocal")]
public JoinDataComplete ConfigIsLocal =
new JoinDataComplete(new JoinData { JoinNumber = 100, JoinSpan = 1 },
new JoinMetadata
{
Description = "Config is local to Essentials",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("NumberOfAuxFaders")]
public JoinDataComplete NumberOfAuxFaders =
new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 },
new JoinMetadata
{
Description = "Number of Auxilliary Faders",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("SpeedDialNameStartJoin")]
public JoinDataComplete SpeedDialNameStartJoin =
new JoinDataComplete(new JoinData { JoinNumber = 241, JoinSpan = 10 },
new JoinMetadata
{
Description = "Speed Dial names",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SpeedDialNumberStartJoin")]
public JoinDataComplete SpeedDialNumberStartJoin =
new JoinDataComplete(new JoinData { JoinNumber = 251, JoinSpan = 10 },
new JoinMetadata
{
Description = "Speed Dial numbers",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SpeedDialVisibleStartJoin")]
public JoinDataComplete SpeedDialVisibleStartJoin =
new JoinDataComplete(new JoinData { JoinNumber = 261, JoinSpan = 10 },
new JoinMetadata
{
Description = "Speed Dial Visible",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("RoomIsOn")]
public JoinDataComplete RoomIsOn =
new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 1 },
new JoinMetadata
{
Description = "Room Is On",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("UserCodeToSystem")]
public JoinDataComplete UserCodeToSystem =
new JoinDataComplete(new JoinData { JoinNumber = 401, JoinSpan = 1 },
new JoinMetadata
{
Description = "User Code",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ServerUrl")]
public JoinDataComplete ServerUrl =
new JoinDataComplete(new JoinData { JoinNumber = 402, JoinSpan = 1 },
new JoinMetadata
{
Description = "Server URL",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ConfigRoomName")]
public JoinDataComplete ConfigRoomName =
new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 1 },
new JoinMetadata
{
Description = "Room Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ConfigHelpMessage")]
public JoinDataComplete ConfigHelpMessage =
new JoinDataComplete(new JoinData { JoinNumber = 502, JoinSpan = 1 },
new JoinMetadata
{
Description = "Room help message",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ConfigHelpNumber")]
public JoinDataComplete ConfigHelpNumber =
new JoinDataComplete(new JoinData { JoinNumber = 503, JoinSpan = 1 },
new JoinMetadata
{
Description = "Room help number",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ConfigRoomPhoneNumber")]
public JoinDataComplete ConfigRoomPhoneNumber =
new JoinDataComplete(new JoinData { JoinNumber = 504, JoinSpan = 1 },
new JoinMetadata
{
Description = "Room phone number",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ConfigRoomURI")]
public JoinDataComplete ConfigRoomUri =
new JoinDataComplete(new JoinData { JoinNumber = 505, JoinSpan = 1 },
new JoinMetadata
{
Description = "Room URI",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ApiOnlineAndAuthorized")]
public JoinDataComplete ApiOnlineAndAuthorized =
new JoinDataComplete(new JoinData { JoinNumber = 500, JoinSpan = 1 },
new JoinMetadata
{
Description = "Config info from SIMPL is ready",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ConfigIsReady")]
public JoinDataComplete ConfigIsReady =
new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 1 },
new JoinMetadata
{
Description = "Config info from SIMPL is ready",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ReadyForConfig")]
public JoinDataComplete ReadyForConfig =
new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 1 },
new JoinMetadata
{
Description = "Config info from SIMPL is ready",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("HideVideoConfRecents")]
public JoinDataComplete HideVideoConfRecents =
new JoinDataComplete(new JoinData { JoinNumber = 502, JoinSpan = 1 },
new JoinMetadata
{
Description = "Hide Video Conference Recents",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ShowCameraWhenNotInCall")]
public JoinDataComplete ShowCameraWhenNotInCall =
new JoinDataComplete(new JoinData { JoinNumber = 503, JoinSpan = 1 },
new JoinMetadata
{
Description = "Show camera when not in call",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("UseSourceEnabled")]
public JoinDataComplete UseSourceEnabled =
new JoinDataComplete(new JoinData { JoinNumber = 504, JoinSpan = 1 },
new JoinMetadata
{
Description = "Use Source Enabled Joins",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SourceShareDisableJoinStart")]
public JoinDataComplete SourceShareDisableJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 601, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source is not sharable",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SourceIsEnabledJoinStart")]
public JoinDataComplete SourceIsEnabledJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 621, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source is enabled/visible",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SourceIsControllableJoinStart")]
public JoinDataComplete SourceIsControllableJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 641, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source is controllable",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SourceIsAudioSourceJoinStart")]
public JoinDataComplete SourceIsAudioSourceJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 661, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source is Audio Source",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SourceNameJoinStart")]
public JoinDataComplete SourceNameJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 601, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source Names",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SourceIconJoinStart")]
public JoinDataComplete SourceIconJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 621, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source Icons",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SourceKeyJoinStart")]
public JoinDataComplete SourceKeyJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 641, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source Keys",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SourceControlDeviceKeyJoinStart")]
public JoinDataComplete SourceControlDeviceKeyJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source Control Device Keys",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SourceTypeJoinStart")]
public JoinDataComplete SourceTypeJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 661, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source Types",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CameraNearNameStart")]
public JoinDataComplete CameraNearNameStart =
new JoinDataComplete(new JoinData { JoinNumber = 761, JoinSpan = 10 },
new JoinMetadata
{
Description = "Near End Camera Names",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CameraFarName")]
public JoinDataComplete CameraFarName =
new JoinDataComplete(new JoinData { JoinNumber = 771, JoinSpan = 1 },
new JoinMetadata
{
Description = "Far End Camera Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
#region Advanced Sharing
[JoinName("SupportsAdvancedSharing")]
public JoinDataComplete SupportsAdvancedSharing =
new JoinDataComplete(new JoinData { JoinNumber = 505, JoinSpan = 1 },
new JoinMetadata
{
Description = "Supports Advanced Sharing",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("UseDestinationEnable")]
public JoinDataComplete UseDestinationEnable =
new JoinDataComplete(new JoinData { JoinNumber = 506, JoinSpan = 1 },
new JoinMetadata
{
Description = "Use Destination Enable",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("UserCanChangeShareMode")]
public JoinDataComplete UserCanChangeShareMode =
new JoinDataComplete(new JoinData { JoinNumber = 507, JoinSpan = 1 },
new JoinMetadata
{
Description = "Share Mode Toggle Visible to User",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DestinationNameJoinStart")]
public JoinDataComplete DestinationNameJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 801, JoinSpan = 10 },
new JoinMetadata
{
Description = "Destination Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DestinationDeviceKeyJoinStart")]
public JoinDataComplete DestinationDeviceKeyJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 811, JoinSpan = 10 },
new JoinMetadata
{
Description = "Destination Device Key",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DestinationTypeJoinStart")]
public JoinDataComplete DestinationTypeJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 821, JoinSpan = 10 },
new JoinMetadata
{
Description = "Destination type. Should be Audio, Video, AudioVideo",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DestinationIsEnabledJoinStart")]
public JoinDataComplete DestinationIsEnabledJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 801, JoinSpan = 10 },
new JoinMetadata
{
Description = "Show Destination on UI",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
#endregion
public MobileControlSIMPLRoomJoinMap(uint joinStart)
: base(joinStart, typeof(MobileControlSIMPLRoomJoinMap))
{
}
}
}

View File

@@ -0,0 +1,72 @@
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer
{
public class MobileControlSIMPLRunDirectRouteActionJoinMap : JoinMapBaseAdvanced
{
[JoinName("AdvancedSharingModeFb")]
public JoinDataComplete AdvancedSharingModeFb =
new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata
{
Description = "Use Advanced Sharing Mode",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("AdvancedSharingModeOn")]
public JoinDataComplete AdvancedSharingModeOn =
new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata
{
Description = "Use Advanced Sharing Mode",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("AdvancedSharingModeOff")]
public JoinDataComplete AdvancedSharingModeOff =
new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata
{
Description = "Use Advanced Sharing Mode",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("AdvancedSharingModeToggle")]
public JoinDataComplete AdvancedSharingModeToggle =
new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 },
new JoinMetadata
{
Description = "Use Advanced Sharing Mode",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SourceForDestinationJoinStart")]
public JoinDataComplete SourceForDestinationJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 10 },
new JoinMetadata
{
Description = "Source to Route to Destination & FB",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SourceForDestinationAudio")]
public JoinDataComplete SourceForDestinationAudio =
new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1 },
new JoinMetadata
{
Description = "Source to Route to Destination & FB",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial
});
public MobileControlSIMPLRunDirectRouteActionJoinMap(uint joinStart)
: base(joinStart, typeof(MobileControlSIMPLRunDirectRouteActionJoinMap))
{
}
}
}

View File

@@ -0,0 +1,247 @@
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer
{
public class SIMPLAtcJoinMap : JoinMapBaseAdvanced
{
[JoinName("EndCall")]
public JoinDataComplete EndCall =
new JoinDataComplete(new JoinData() { JoinNumber = 21, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Hang Up",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("IncomingAnswer")]
public JoinDataComplete IncomingAnswer =
new JoinDataComplete(new JoinData() { JoinNumber = 51, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Answer Incoming Call",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("IncomingReject")]
public JoinDataComplete IncomingReject =
new JoinDataComplete(new JoinData() { JoinNumber = 52, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Reject Incoming Call",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SpeedDialStart")]
public JoinDataComplete SpeedDialStart =
new JoinDataComplete(new JoinData() { JoinNumber = 41, JoinSpan = 4 },
new JoinMetadata()
{
Description = "Speed Dial",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CurrentDialString")]
public JoinDataComplete CurrentDialString =
new JoinDataComplete(new JoinData() { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Dial String",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CurrentCallNumber")]
public JoinDataComplete CurrentCallNumber =
new JoinDataComplete(new JoinData() { JoinNumber = 11, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Call Number",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CurrentCallName")]
public JoinDataComplete CurrentCallName =
new JoinDataComplete(new JoinData() { JoinNumber = 12, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Call Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("HookState")]
public JoinDataComplete HookState =
new JoinDataComplete(new JoinData() { JoinNumber = 21, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Hook State",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CallDirection")]
public JoinDataComplete CallDirection =
new JoinDataComplete(new JoinData() { JoinNumber = 22, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Call Direction",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("IncomingCallName")]
public JoinDataComplete IncomingCallName =
new JoinDataComplete(new JoinData() { JoinNumber = 51, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Incoming Call Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("IncomingCallNumber")]
public JoinDataComplete IncomingCallNumber =
new JoinDataComplete(new JoinData() { JoinNumber = 52, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Incoming Call Number",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("0")]
public JoinDataComplete Dtmf0 =
new JoinDataComplete(new JoinData() { JoinNumber = 10, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 0",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("1")]
public JoinDataComplete Dtmf1 =
new JoinDataComplete(new JoinData() { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 1",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("2")]
public JoinDataComplete Dtmf2 =
new JoinDataComplete(new JoinData() { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 2",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("3")]
public JoinDataComplete Dtmf3 =
new JoinDataComplete(new JoinData() { JoinNumber = 3, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 3",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("4")]
public JoinDataComplete Dtmf4 =
new JoinDataComplete(new JoinData() { JoinNumber = 4, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 4",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("5")]
public JoinDataComplete Dtmf5 =
new JoinDataComplete(new JoinData() { JoinNumber = 5, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 5",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("6")]
public JoinDataComplete Dtmf6 =
new JoinDataComplete(new JoinData() { JoinNumber = 6, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 6",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("7")]
public JoinDataComplete Dtmf7 =
new JoinDataComplete(new JoinData() { JoinNumber = 7, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 7",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("8")]
public JoinDataComplete Dtmf8 =
new JoinDataComplete(new JoinData() { JoinNumber = 8, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 8",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("9")]
public JoinDataComplete Dtmf9 =
new JoinDataComplete(new JoinData() { JoinNumber = 9, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 9",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("*")]
public JoinDataComplete DtmfStar =
new JoinDataComplete(new JoinData() { JoinNumber = 11, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF *",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("#")]
public JoinDataComplete DtmfPound =
new JoinDataComplete(new JoinData() { JoinNumber = 12, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF #",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
/// <summary>
/// Constructor that passes the joinStart to the base class
/// </summary>
/// <param name="joinStart"></param>
public SIMPLAtcJoinMap(uint joinStart)
: base(joinStart, typeof(SIMPLAtcJoinMap))
{
}
}
}

View File

@@ -0,0 +1,553 @@
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer
{
public class SIMPLVtcJoinMap : JoinMapBaseAdvanced
{
[JoinName("EndCall")]
public JoinDataComplete EndCall =
new JoinDataComplete(new JoinData() { JoinNumber = 24, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Hang Up",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("IncomingCall")]
public JoinDataComplete IncomingCall =
new JoinDataComplete(new JoinData() { JoinNumber = 50, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Incoming Call",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("IncomingAnswer")]
public JoinDataComplete IncomingAnswer =
new JoinDataComplete(new JoinData() { JoinNumber = 51, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Answer Incoming Call",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("IncomingReject")]
public JoinDataComplete IncomingReject =
new JoinDataComplete(new JoinData() { JoinNumber = 52, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Reject Incoming Call",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SpeedDialStart")]
public JoinDataComplete SpeedDialStart =
new JoinDataComplete(new JoinData() { JoinNumber = 41, JoinSpan = 4 },
new JoinMetadata()
{
Description = "Speed Dial",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectorySearchBusy")]
public JoinDataComplete DirectorySearchBusy =
new JoinDataComplete(new JoinData() { JoinNumber = 100, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Directory Search Busy FB",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectoryLineSelected")]
public JoinDataComplete DirectoryLineSelected =
new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Directory Line Selected FB",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectoryEntryIsContact")]
public JoinDataComplete DirectoryEntryIsContact =
new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Directory Selected Entry Is Contact FB",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectoryIsRoot")]
public JoinDataComplete DirectoryIsRoot =
new JoinDataComplete(new JoinData() { JoinNumber = 102, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Directory is on Root FB",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DDirectoryHasChanged")]
public JoinDataComplete DDirectoryHasChanged =
new JoinDataComplete(new JoinData() { JoinNumber = 103, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Directory has changed FB",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectoryRoot")]
public JoinDataComplete DirectoryRoot =
new JoinDataComplete(new JoinData() { JoinNumber = 104, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Go to Directory Root",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectoryFolderBack")]
public JoinDataComplete DirectoryFolderBack =
new JoinDataComplete(new JoinData() { JoinNumber = 105, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Go back one directory level",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectoryDialSelectedLine")]
public JoinDataComplete DirectoryDialSelectedLine =
new JoinDataComplete(new JoinData() { JoinNumber = 106, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Dial selected directory line",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraTiltUp")]
public JoinDataComplete CameraTiltUp =
new JoinDataComplete(new JoinData() { JoinNumber = 111, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Tilt Up",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraTiltDown")]
public JoinDataComplete CameraTiltDown =
new JoinDataComplete(new JoinData() { JoinNumber = 112, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Tilt Down",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraPanLeft")]
public JoinDataComplete CameraPanLeft =
new JoinDataComplete(new JoinData() { JoinNumber = 113, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Pan Left",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraPanRight")]
public JoinDataComplete CameraPanRight =
new JoinDataComplete(new JoinData() { JoinNumber = 114, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Pan Right",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraZoomIn")]
public JoinDataComplete CameraZoomIn =
new JoinDataComplete(new JoinData() { JoinNumber = 115, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Zoom In",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraZoomOut")]
public JoinDataComplete CameraZoomOut =
new JoinDataComplete(new JoinData() { JoinNumber = 116, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Zoom Out",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraPresetStart")]
public JoinDataComplete CameraPresetStart =
new JoinDataComplete(new JoinData() { JoinNumber = 121, JoinSpan = 5 },
new JoinMetadata()
{
Description = "Camera Presets",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraModeAuto")]
public JoinDataComplete CameraModeAuto =
new JoinDataComplete(new JoinData() { JoinNumber = 131, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Mode Auto",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraModeManual")]
public JoinDataComplete CameraModeManual =
new JoinDataComplete(new JoinData() { JoinNumber = 132, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Mode Manual",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraModeOff")]
public JoinDataComplete CameraModeOff =
new JoinDataComplete(new JoinData() { JoinNumber = 133, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Mode Off",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraSelfView")]
public JoinDataComplete CameraSelfView =
new JoinDataComplete(new JoinData() { JoinNumber = 141, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Self View Toggle/FB",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraLayout")]
public JoinDataComplete CameraLayout =
new JoinDataComplete(new JoinData() { JoinNumber = 142, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Layout Toggle",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraSupportsAutoMode")]
public JoinDataComplete CameraSupportsAutoMode =
new JoinDataComplete(new JoinData() { JoinNumber = 143, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Supports Auto Mode FB",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraSupportsOffMode")]
public JoinDataComplete CameraSupportsOffMode =
new JoinDataComplete(new JoinData() { JoinNumber = 144, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Supports Off Mode FB",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraNumberSelect")]
public JoinDataComplete CameraNumberSelect =
new JoinDataComplete(new JoinData() { JoinNumber = 60, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Number Select/FB",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectorySelectRow")]
public JoinDataComplete DirectorySelectRow =
new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Directory Select Row",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("DirectoryRowCount")]
public JoinDataComplete DirectoryRowCount =
new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Directory Row Count FB",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("CurrentDialString")]
public JoinDataComplete CurrentDialString =
new JoinDataComplete(new JoinData() { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Dial String",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CurrentCallName")]
public JoinDataComplete CurrentCallName =
new JoinDataComplete(new JoinData() { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Call Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CurrentCallNumber")]
public JoinDataComplete CurrentCallNumber =
new JoinDataComplete(new JoinData() { JoinNumber = 3, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Call Number",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("HookState")]
public JoinDataComplete HookState =
new JoinDataComplete(new JoinData() { JoinNumber = 31, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Hook State",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CallDirection")]
public JoinDataComplete CallDirection =
new JoinDataComplete(new JoinData() { JoinNumber = 22, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Call Direction",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("IncomingCallName")]
public JoinDataComplete IncomingCallName =
new JoinDataComplete(new JoinData() { JoinNumber = 51, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Incoming Call Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("IncomingCallNumber")]
public JoinDataComplete IncomingCallNumber =
new JoinDataComplete(new JoinData() { JoinNumber = 52, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Incoming Call Number",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DirectorySearchString")]
public JoinDataComplete DirectorySearchString =
new JoinDataComplete(new JoinData() { JoinNumber = 100, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Directory Search String",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DirectoryEntriesStart")]
public JoinDataComplete DirectoryEntriesStart =
new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 255 },
new JoinMetadata()
{
Description = "Directory Entries",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DirectoryEntrySelectedName")]
public JoinDataComplete DirectoryEntrySelectedName =
new JoinDataComplete(new JoinData() { JoinNumber = 356, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Selected Directory Entry Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DirectoryEntrySelectedNumber")]
public JoinDataComplete DirectoryEntrySelectedNumber =
new JoinDataComplete(new JoinData() { JoinNumber = 357, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Selected Directory Entry Number",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DirectorySelectedFolderName")]
public JoinDataComplete DirectorySelectedFolderName =
new JoinDataComplete(new JoinData() { JoinNumber = 358, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Selected Directory Folder Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("1")]
public JoinDataComplete Dtmf1 =
new JoinDataComplete(new JoinData() { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 1",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("2")]
public JoinDataComplete Dtmf2 =
new JoinDataComplete(new JoinData() { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 2",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("3")]
public JoinDataComplete Dtmf3 =
new JoinDataComplete(new JoinData() { JoinNumber = 3, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 3",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("4")]
public JoinDataComplete Dtmf4 =
new JoinDataComplete(new JoinData() { JoinNumber = 4, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 4",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("5")]
public JoinDataComplete Dtmf5 =
new JoinDataComplete(new JoinData() { JoinNumber = 5, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 5",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("6")]
public JoinDataComplete Dtmf6 =
new JoinDataComplete(new JoinData() { JoinNumber = 6, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 6",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("7")]
public JoinDataComplete Dtmf7 =
new JoinDataComplete(new JoinData() { JoinNumber = 7, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 7",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("8")]
public JoinDataComplete Dtmf8 =
new JoinDataComplete(new JoinData() { JoinNumber = 8, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 8",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("9")]
public JoinDataComplete Dtmf9 =
new JoinDataComplete(new JoinData() { JoinNumber = 9, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 9",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("0")]
public JoinDataComplete Dtmf0 =
new JoinDataComplete(new JoinData() { JoinNumber = 10, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 0",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("*")]
public JoinDataComplete DtmfStar =
new JoinDataComplete(new JoinData() { JoinNumber = 11, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF *",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("#")]
public JoinDataComplete DtmfPound =
new JoinDataComplete(new JoinData() { JoinNumber = 12, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF #",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
public SIMPLVtcJoinMap(uint joinStart)
: base(joinStart, typeof(SIMPLVtcJoinMap))
{
}
}
}

View File

@@ -0,0 +1,19 @@
using Newtonsoft.Json;
namespace PepperDash.Essentials
{
public class AuthorizationResponse
{
[JsonProperty("authorized")]
public bool Authorized { get; set; }
[JsonProperty("reason", NullValueHandling = NullValueHandling.Ignore)]
public string Reason { get; set; } = null;
}
public class AuthorizationRequest
{
[JsonProperty("grantCode")]
public string GrantCode { get; set; }
}
}

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