Compare commits

...

158 Commits

Author SHA1 Message Date
Neil Dorin
eae089cdf5 fix(essentials): updates to password prompt logic 2022-09-22 15:38:11 -06:00
Neil Dorin
b48859d202 adds missing .csproj update 2022-09-22 13:06:00 -06:00
Neil Dorin
bda46eb1b9 fix(essentials): adds cancel method for password prompt and adds wireless share instructions 2022-09-22 13:05:09 -06:00
Neil Dorin
ee735388bb fix(essentials): reworks SIMPL bridging logic for hiding password prompt 2022-09-15 12:44:17 -06:00
Andrew Welker
77f202b9f4 Merge pull request #1000 from PepperDash/hotfix/zoom-room-content-sharing-fb
fix(essentials): Fixes SharingSourceFeedback value to actually read F…
2022-09-14 17:00:09 -06:00
Neil Dorin
939afb7aae fix(essentials): Fixes SharingSourceFeedback value to actually read FB state instead of which on screen instructions are shown 2022-09-14 16:40:26 -06:00
Andrew Welker
4a98b58b60 Merge pull request #997 from PepperDash/hotfix/zoom-passcode-prompt
Update Zoom passcode bridging logic
2022-09-09 10:39:02 -06:00
Andrew Welker
2bf9336712 Merge branch 'main' into hotfix/zoom-passcode-prompt 2022-09-09 10:24:14 -06:00
Andrew Welker
598886dfd4 Merge pull request #995 from PepperDash/hotfix/zoom-room-privacy-mute-notincall
Set Zoom Room privacy/mic mute to report unmuted when not in a meeting
2022-09-08 15:08:32 -06:00
Neil Dorin
215cf6696e fix(essentials): Set not in call state to report as unmuted 2022-09-08 14:26:18 -06:00
Neil Dorin
c557400f38 fix(essentials): updates ZoomRoom mute state to report muted when not in call 2022-09-08 14:26:18 -06:00
jdevito
f1590aeec8 fix: added 'CancelPasswordPrompt' join, updated linkToZoomApi 2022-09-06 14:10:21 -05:00
jdevito
f1d1ce9722 fix: added OnPasswordRequired event call in SubmitPassword method to clear popup when bridged 2022-09-06 14:04:19 -05:00
Andrew Welker
f5a352cf08 Merge pull request #990 from PepperDash/hotfix/essentials-cooling-routing
Magic Routing holds last requested route until cooling is complete
2022-09-02 11:37:46 -06:00
Neil Dorin
c4a23e0887 feat(essentials): Adds RoomUiBehaviorConfig for disabling activity buttons 2022-09-02 11:19:18 -06:00
Andrew Welker
7fe2d04d31 fix: add removal of RouteRequest when calling ReleaseRoute 2022-09-01 12:29:19 -06:00
Andrew Welker
358f44cfe5 refactor: remove completed request from dictionary 2022-09-01 11:57:40 -06:00
Andrew Welker
d7cccc0709 feat: add cooldown logic to Magic Routing
In some cases, a route can be requested while a sink is cooling down.
In those cases, the routing logic should keep track of requests for a
destination and wait until cooling is complete to request the new
route.
2022-09-01 11:47:52 -06:00
Andrew Welker
81b1117310 Merge pull request #988 from PepperDash/feature/cen-io-ir-104
Add Support for CEN-IO devices
2022-08-31 14:47:58 -06:00
jdevito
fb689c4484 fix: updated CEN-IO classes inheriting from EssentialsDevice to CrestronGenericBaseDevice to resolve activation issues 2022-08-31 14:43:58 -05:00
jdevito
40cb1b0fcf Merge remote-tracking branch 'origin/hotfix/huddle-room-interfaces' into feature/cen-io-ir-104 2022-08-31 11:55:15 -05:00
Jason DeVito
4574941288 fix: updated debug statement for DinCenCnController class referencing building a temp sensor device 2022-08-30 22:11:33 -05:00
Jason DeVito
122abc56e5 fix: added null checks in BuildDevice with debug statements if null 2022-08-30 22:02:47 -05:00
Jason DeVito
074ee190ad feat: added cen-io-ir-104 device and factory 2022-08-30 21:53:41 -05:00
Andrew Welker
68a0157fbe fix: add missing interface 2022-08-30 13:57:53 -06:00
Andrew Welker
e5393deea8 Merge pull request #980 from PepperDash/hotfix/zoomroom-bridge-updates
Hotfix/zoomroom bridge updates
2022-08-10 16:28:16 -06:00
Jason DeVito
c446c3a976 fix: updates to resolve directory display issues on touch panel when bridged 2022-08-10 17:12:30 -05:00
Jason DeVito
49e44ec850 fix: updated VideoCodecBase UpdateDirectoryXSig to handle directory results that are greater than 1023, XSig maximimum index 2022-08-10 15:49:41 -05:00
Andrew Welker
0ec42f8de2 Merge pull request #976 from PepperDash/hotfix/fix-lightingScene-scene-select-index
Lighting and Display Base updates to support extending joinMaps
2022-08-08 13:29:01 -06:00
Jason DeVito
008c82edb9 fix: updated lighting and display base; fix: lightingBase scene recall link to api index out of range exception 2022-08-08 13:54:17 -05:00
Neil Dorin
3033322212 Merge pull request #973 from PepperDash/hotfix/multiple-display-routing-support
Fix interface type check for routing
2022-08-01 12:34:16 -06:00
Neil Dorin
5b350c7a0c Updates interface type for other condition 2022-08-01 12:19:43 -06:00
Neil Dorin
afd2198eef Uses a less specific interface type for routing 2022-08-01 12:19:28 -06:00
Neil Dorin
05dadbe8ee Merge pull request #963 from PepperDash/hotfix/typo-in-RoutingPort-constructor
Hotfix/typo in routing port constructor
2022-06-22 09:54:43 -06:00
Neil Dorin
c39fd231bf Merge pull request #914 from Willis1776/bugfix/routingPort-typo-isInternal-Constructor
Typo in RoutingPort Constructor - isInternal
2022-06-22 09:38:30 -06:00
Neil Dorin
0df587071d Merge branch 'main' into bugfix/routingPort-typo-isInternal-Constructor 2022-06-22 09:14:31 -06:00
Neil Dorin
cd4f2d5edd Merge pull request #952 from PepperDash/hotfix/c2nio-factory-reference-update
fix: corrects issue #951, c2nio incorrect factory reference
2022-06-08 14:29:43 -06:00
Jason DeVito
59b18d713b fix: corrects issue #951, c2nio incorrect factory reference 2022-06-08 15:12:32 -05:00
Neil Dorin
a7db15d9fd Merge pull request #943 from PepperDash/hotfix/zoom-recording-prompt
Hotfix/zoom recording prompt
2022-05-18 17:14:19 -06:00
Neil Dorin
b8442e7048 feat(essentials): Format update for command 2022-05-18 16:33:21 -06:00
Neil Dorin
1e65c961c6 feat(essentials): Adds new interface capabilities
* ability to admit a participant from waiting room
* ability to acknowledge a meeting recording consent prompt
2022-05-17 15:36:00 -06:00
Neil Dorin
bdc4f0ae28 fix(essentials): updates recording property name 2022-05-17 13:20:53 -06:00
Neil Dorin
82ac34d3b6 fix(essentials): Updates Status.Call subscription mechanism to persist properly
Makes sure all subscriptions are un and resubscribed whenever Status.Call is constructed
2022-05-17 11:26:19 -06:00
Neil Dorin
23555e5174 Merge branch 'main' into hotfix/zoom-osd-device 2022-05-16 14:20:38 -06:00
Neil Dorin
7c892b4f71 Merge pull request #936 from PepperDash/hotfix/zoomroom-duplicate-passwordRequired-eventhandlers
fix: removed duplicate PasswordRequired event handler from LinkZoomRo…
2022-04-26 14:50:40 -06:00
Jason DeVito
1abe54fa48 fix: removed duplicate PasswordRequired event handler from LinkZoomRoomToApi method 2022-04-26 15:32:34 -05:00
Jason DeVito
309605ee38 fix: updated packages.config to reference PepperDash Core 1.1.1, previously referencing RC build 2022-03-29 16:04:14 -05:00
Jason DeVito
e2b8e356ff fix: Updated ZoomRoom constructor to build HdmiOutput1,2,3 2022-03-29 16:03:46 -05:00
Jason DeVito
832102f4bb feat: updated ExecuteSwitch to turn the display power on if _PowerIsOn is false 2022-03-29 16:02:59 -05:00
Neil Dorin
b23b7cb813 fix(essentials): #927 moves SetUpRouting() to constructor 2022-03-29 12:49:49 -06:00
Andrew Welker
b42d487c4c Merge pull request #918 from PepperDash/release/1.10.0
Release/1.10.0
2022-03-16 08:05:25 -06:00
Michael Willis
5f668c7173 Typo in RoutingPort Constructor - isInternal 2022-03-08 09:42:53 -07:00
Andrew Welker
6db5a9b2ca Merge pull request #913 from PepperDash/feature/cleanup-debug-statements
Feature/cleanup debug statements
2022-03-03 15:14:34 -07:00
Neil Dorin
89dd098ea6 feat(essentials): #912 Updates to GenericCommunicationMonitor to better monitor socket status 2022-03-03 14:39:54 -07:00
Neil Dorin
787c8eb954 feat(essentials): Adds new interface and event to notify if video unmute is requested 2022-03-01 21:43:38 -07:00
Neil Dorin
97b9ed5016 fix(essentials): Fixes SetupCameras to not add duplicate cameras to the list 2022-02-28 19:21:27 -07:00
Neil Dorin
06fdee313a fix(essentials): adds missing property decorators and unmutes video on camera select 2022-02-25 21:10:44 -07:00
Neil Dorin
b3f7568469 fix(essentials): updates to IHasDirectory and ZoomRoom
Prevents serialization of CurrentDirectoryResults object.
Modified OnDirectoryResultsReturne helper method for ZoomRoom to fix stripping of contacts
2022-02-24 22:03:03 -07:00
Neil Dorin
55ab593d73 feat(essentails): #911 swaps cisco comm monitor poll string 2022-02-24 14:34:38 -07:00
Neil Dorin
a06652ee61 chore(essentials): Cleans up some debug statements no longer needed 2022-02-21 12:06:09 -07:00
Neil Dorin
4f26df3149 Merge pull request #908 from PepperDash/feature/add-cisco-room-kit-features
Feature/add cisco room kit features
2022-02-15 16:16:18 -07:00
Neil Dorin
428edad38a Merge branch 'release/1.10.0' into feature/add-cisco-room-kit-features 2022-02-15 16:05:14 -07:00
Neil Dorin
f3431f287c Merge pull request #907 from PepperDash/feature/refine-zoomroom-addedcontact-feedback-subscription
fix(essentials): #901 Refines initial synchronization sequence
2022-02-15 15:52:14 -07:00
Jonathan Arndt
80b5fb6c7f CiscoSparkCodec > Removed inner IF of processQueuedCommands and added CrestronInvoke to CheckSyncStatus 2022-02-15 11:27:37 -08:00
Jonathan Arndt
6df594dd7f Updates to CiscoSparkCodec queue 2022-02-14 17:21:15 -08:00
Neil Dorin
e39c76001a feat(essentials): Updates to initial sync mechanism
Adds queue for all outgoing commands to codec that blocks until sync is established
2022-02-14 16:16:58 -07:00
Jonathan Arndt
d88a454499 fix(essentials): various bug fixes for hold FB, individual call end, incoming name-number fb, ipv4 address fb 2022-02-11 16:39:47 -08:00
Neil Dorin
b0e3fddec7 fix(essentials): fixes issue with local var scope when assigning actions for ending individual calls
Fixes Incoming call name/number feedback in bridge
2022-02-11 15:50:09 -07:00
Neil Dorin
0e5cecbfc3 fix(essentials): #901 Refines initial synchronization sequence
Makes sure that the AddedContact feedback subscription is excluded right away, but later included after the phonebook is retrieved.  This should ensure we get the initial phonebook and all subsequent additions at runtime while also minimizing initial data volume.
2022-02-11 14:16:40 -07:00
Andrew Welker
57dac392da Merge pull request #906 from PepperDash/feature/revise-zoomroom-gather-methodology
Feature/revise zoomroom gather methodology
2022-02-10 18:05:38 -07:00
Neil Dorin
348981d8cb fix(essntials): Fixes exception in OnLayoutChanged and fixes debug JSON formatting for Zoom responses 2022-02-10 17:33:06 -07:00
Neil Dorin
bee3f0caf3 Merge branch 'release/1.10.0' into feature/revise-zoomroom-gather-methodology 2022-02-10 16:02:55 -07:00
Neil Dorin
79a3a8ed7e fix(essentials): #901 Overhaul's feedback processing for efficiency
Updates to address changes to ZRAAPI v1.1 and ZoomRooms 5.9.4
2022-02-10 15:49:53 -07:00
Neil Dorin
cb3c80ff8f fix(essentials): fixes to on hold feedback and call status xsig 2022-02-09 17:44:53 -07:00
Neil Dorin
0bb4b6edd4 fix(essentials): doh! fixes issue where IsOnHold would get set to false if response contains no PlacedOhHold object 2022-02-09 17:30:26 -07:00
Neil Dorin
e4a4564bbc fix(essentials): Attempts to set OnHold an alternative way 2022-02-09 17:21:19 -07:00
Neil Dorin
b0288951eb fix(essentials): removes logic to disconnect and reinitialize on malformed json response 2022-02-09 17:15:58 -07:00
Neil Dorin
bfdc882eb6 fix(essentials): Adds logic to recover from malformed json response on initial communication.
Adds better formatting for active calls list print to console
2022-02-09 17:07:18 -07:00
Neil Dorin
7a2e99f145 feat(essentials): Adds HoldAllCalls join and action 2022-02-09 16:50:06 -07:00
Neil Dorin
db67f97a1f fix(essentials): add local scope variable for indexer in hold/resume call loop 2022-02-09 16:46:19 -07:00
Neil Dorin
102ae3ad4f fix(essentials): second attempt to get on hold fb working 2022-02-09 16:41:37 -07:00
Neil Dorin
7dd6b3a9b6 fix(essentials): fixes index off by 1 error and updates call status to check for "OnHold" as status value 2022-02-09 16:31:31 -07:00
Neil Dorin
e24965eb54 fix(essentials): fixes ValueChagnedAction to run both feedback updates instead of one 2022-02-09 15:37:55 -07:00
Neil Dorin
9d80954214 fix(essentials): Adds check for SendingMode property value before attempting to set fb 2022-02-09 15:10:39 -07:00
Jonathan Arndt
70c5df9040 Removed add camera to device manager 2022-02-09 14:09:07 -08:00
Neil Dorin
89a7f2aa80 fix(essentials): Add a condition to check for an empty configuration.presentation object response and return to avoid null ref ex 2022-02-09 14:54:19 -07:00
Neil Dorin
90023621dc fix(essentials): Adds some better console log comments and calls SetUpCameras() after reading data from codec. 2022-02-09 14:48:45 -07:00
Neil Dorin
adbce916ba feat(essentials): Adds ability to read camera info from codec rather than just from config 2022-02-09 14:34:25 -07:00
Neil Dorin
b97783603b feat(essentials): Adds analog fb join for recent calls count to VideoCodecControllerJoinMap and bridge 2022-02-09 14:14:44 -07:00
Neil Dorin
db526cdd40 fix(essentials): fixes exception when parsing presentation local instance ghosted response 2022-02-09 14:09:54 -07:00
Neil Dorin
db982f4490 feat(essentials): Adds ability to select and dial contact methods for directory contacts via SIMPL bridge 2022-02-09 14:00:49 -07:00
Jonathan Arndt
c84525ddef Update recent call history and call method to protect for zero value from SIMPL 2022-02-09 11:39:35 -08:00
Andrew Welker
a3b078d327 Merge pull request #904 from PepperDash/hotfix/zoomroom-queue-size
Hotfix/zoomroom queue size
2022-02-09 12:34:29 -07:00
Neil Dorin
b9c07b01e9 Merge pull request #903 from PepperDash/hotfix/zoomroom-fix-phonebook-autodownload
Hotfix/zoomroom fix phonebook autodownload
2022-02-09 09:08:23 -07:00
Andrew Welker
d0097089e6 Merge pull request #902 from PepperDash/hotfix/zoomroom-fix-phonebook-autodownload
Hotfix/zoomroom fix phonebook autodownload
2022-02-09 08:59:51 -07:00
Andrew Welker
582390c7c7 ci: Fix Windows image 2022-02-09 08:38:27 -07:00
Jonathan Arndt
faabdde3f7 Update VideoCodecBase class UpdateDirectoryXSig method removing the check if the FolderId is null or empty as that check would be device specific 2022-02-08 16:31:45 -08:00
Jonathan Arndt
402754b69e Update VideoCodecBase class UpdateDirectoryXSig method removing the check if the FolderId is null or empty as that check would be device specific 2022-02-08 16:31:26 -08:00
Jonathan Arndt
84b39a959e Update VideoCodecBase class UpdateDirectoryXSig method removing the check if the FolderId is null or empty as that check would be device specific 2022-02-08 16:31:18 -08:00
Jonathan Arndt
93bfcc7baa Add logic to subscribe to PhoneBookSyncState during the CustomActivate method within CiscoSparkCodec class 2022-02-08 16:24:54 -08:00
Jonathan Arndt
64352811c5 Update VideoCodecBase.LinkVideoCodecCameraToApi FOR loop checking camera names to first check camera count 2022-02-08 13:31:13 -08:00
Alex Johnson
3a74abd061 Merge branch 'hotfix/zoomroom-fix-phonebook-autodownload' into hotfix/zoomroom-queue-size 2022-02-08 16:07:17 -05:00
Alex Johnson
08aa8fb2e6 Fixes issue where DisableAutoPhonebookDownload is set to true, but phonebook would still auto-download. Check condition was inversed 2022-02-08 16:05:02 -05:00
Jonathan Arndt
b5589364ff Instantiate xConfiguration members of Configuration, AutoAnswer, and Conference classes 2022-02-08 12:15:29 -08:00
Jason DeVito
6cd1a03ee0 fix: Updated LinkVideoCodecToApi trilist.onlinestatus change to fix CameraSupportsAudioMode passing true rather than property. 2022-02-08 09:38:40 -06:00
Jason DeVito
e19b0ba530 fix: updated yaml files to point to windows-2019 to resolve action failures. 2022-02-07 16:58:24 -06:00
Jason DeVito
7b2498ac6b fix: added JSON property decorator to configuration properties. 2022-02-07 16:50:35 -06:00
Jason DeVito
d9181c780f fix: Updated _receiveQueue capacity from 512 to 2048 to help with processing large amounts of push data received from zoom. 2022-02-07 16:45:08 -06:00
Neil Dorin
bc826c9e17 fix(essentials): updates action workflows to specify windows-2019 instead of latest 2022-02-04 16:41:57 -07:00
Neil Dorin
c6023ad700 fix(essentials): Adds missing help message property to tech room config and exposes config 2022-02-04 15:51:29 -07:00
Neil Dorin
742ff4bc1b fix(essentials): Updates config type for Vtc1 type rooms 2022-02-02 10:18:20 -07:00
Neil Dorin
2502947df8 Merge pull request #899 from PepperDash/hotfix/queue-thread-name
Add name to `GenericQueue` Thread
2022-02-02 10:16:38 -07:00
Neil Dorin
7075da5b68 Merge pull request #900 from PepperDash/hotfix/queue-thread-name
Add name to `GenericQueue` Thread - Release Branch
2022-02-02 10:16:17 -07:00
Andrew Welker
abdd1b38f8 feat (Core): #898 Add name to GenericQueue Thread
This name will show up in console using the `SSPTASKS` command and allow for easier troubleshooting.
2022-02-02 09:22:13 -07:00
Andrew Welker
455d85e8f9 Merge pull request #897 from PepperDash/feature/room-combining
Feature/room combining
2022-01-31 21:09:23 -07:00
Neil Dorin
d1509fe94b Merge branch 'development' into feature/room-combining 2022-01-31 20:48:18 -07:00
Neil Dorin
9d87c76ab2 Merge branch 'development' into feature/room-combining 2022-01-31 20:43:56 -07:00
Neil Dorin
c87048a221 Merge pull request #896 from PepperDash/feature/dmps-updates
Feature/dmps updates
2022-01-31 20:43:40 -07:00
Neil Dorin
4dc4565e69 Merge branch 'development' into feature/room-combining 2022-01-27 15:50:37 -07:00
Neil Dorin
5d5dee2e5e Merge pull request #892 from PepperDash/hotfix/generic-relay-dm-rmc-issues
Add `IRelayPorts` interface to `DmRmc4kzScalerCController`
2022-01-26 11:57:13 -07:00
Neil Dorin
611f0bec2e fix(essentials): #865 Adds DialselectedRecentCallItem join 2021-12-07 19:40:03 -07:00
Neil Dorin
90e22e9136 fix(essentials): #865 Adds SelectedContactMethodCount join to report the number of methods for the selected contact 2021-12-07 16:45:14 -07:00
Neil Dorin
4552a15cbb fix(essentials): #865 Updates to join map and bridging based on feedback from testing 2021-12-07 16:22:15 -07:00
Neil Dorin
c685608f67 fix(essentials): reworks logic for setting up cameras to wait until codec communication sync has finished 2021-11-17 12:24:58 -07:00
Neil Dorin
cdafaf1bcb fix(essentials): Adds missing constructor for Configuration RootObject 2021-11-17 11:37:29 -07:00
Neil Dorin
d8aef1a0da feat(essentials): #865 More updates
Adds ability to disable auto dialing behavior of selected directory contact.
Adds XSig to send contact method info across bridge
Adds XSig to send call history data across bridge and also joins to manipulate
2021-11-12 22:07:11 -07:00
Neil Dorin
0ff29695e7 feat(essentials): #865 Updates join map and bridge for new features
Adds control and feedback for presentation source
Updates camera setup, selection and feedback
Adds ringtone volume control/feedback
Adds call hold/resume/join control to bridge
Adds new config properties for camera info
2021-11-11 21:05:57 -07:00
Neil Dorin
8aae23db9e feat(essentials): #865 Updates to Bridging
Adds ability to end individual calls, report connected call count, report call duration and hold status, send DTMF tones to individual call index and select far end presets
2021-11-11 17:23:11 -07:00
Neil Dorin
a043309bb1 feat(essentials): More updates to add ringtone volume and focus near/far to bridge 2021-11-10 18:02:23 -07:00
Neil Dorin
dc53ce42e7 feat(essentials): Adds interface and implementation to join calls 2021-11-10 14:08:12 -07:00
Neil Dorin
6dd882b1a0 feat(essentials): Adds hold/resume/duration features to call status 2021-11-10 13:49:43 -07:00
Neil Dorin
d67a161e32 Merge branch 'development' into feature/room-combining 2021-09-29 17:17:29 -06:00
Neil Dorin
1e98484082 Merge branch 'development' into feature/room-combining 2021-09-22 17:23:38 -06:00
Neil Dorin
acd2be3679 feat(essentials): Updates to get scenarios to activate/deactivate 2021-08-25 17:23:24 -06:00
Neil Dorin
e7cfe1143d fix(essentials): updates MockVc to instantiate the OsdSource and add its tie line 2021-08-25 16:24:18 -06:00
Neil Dorin
26bf7d8f73 feat(essentials): #793 Implements IHasDirectoryHistoryStack on CiscoSparkCodec 2021-08-17 17:58:32 -06:00
Neil Dorin
12e8dca47e fix(essentials): #792 refactors logic to show/hide SelectASourceVisible subpage 2021-08-17 16:41:23 -06:00
Neil Dorin
5c02d72ed1 fix(essentials): Allows SubpageReferenceListSourceItem to deregister from room's CurrentSourceInfoChange event on Clear() 2021-08-17 16:38:51 -06:00
Neil Dorin
115a20d8e6 Merge branch 'feature/room-combining' of https://github.com/PepperDash/Essentials into feature/room-combining 2021-08-17 14:08:38 -06:00
Andrew Welker
c298d37b9f Merge branch 'development' into feature/room-combining 2021-08-16 15:45:43 -06:00
Neil Dorin
5f5ded74fc Merge branch 'development' into feature/room-combining 2021-08-16 14:46:52 -06:00
Neil Dorin
1bf828b8a9 Updates feedback funcs for combined room type 2021-08-12 09:36:03 -06:00
Neil Dorin
397a5b1794 fix(CiscoSparkCodec): Solves exception when in SipUri getter 2021-08-05 17:28:49 -06:00
Neil Dorin
0867d08c5a fix(MockVC): various fixes for local testing
update MockVC and EssentialsVideoCodecUiDriver
updates to Cisco classes to address some exceptions at startup with EssentialsVideoCodecUiDriver
2021-08-04 15:13:35 -06:00
Neil Dorin
5c3e1ca915 Updates IMobileControl to use IEssentialsRoom instead of EssentialsRoomBase again 2021-08-03 14:52:26 -06:00
Neil Dorin
1de42b9e97 Merge branch 'development' into feature/room-combining 2021-08-03 14:32:42 -06:00
Neil Dorin
0e41cafdad Adds some debug comments to assist in debugging 2021-08-02 14:22:31 -06:00
Neil Dorin
77672237e6 Adds some debug comments to assist in debugging 2021-07-30 17:27:38 -06:00
Neil Dorin
8ae03a8187 Merge branch 'development' into feature/room-combining 2021-07-30 16:59:52 -06:00
Neil Dorin
7114e60c04 feat(RoomCombining): #742 Updates EssentialsTouchpanelController
Will now switch room the TP is linked to based on room combination scenario
2021-07-30 16:59:32 -06:00
Neil Dorin
6542c062b9 Working towards getting EssentialsTouchpanelController to switch rooms 2021-07-23 17:35:12 -06:00
Neil Dorin
2db397b474 #742 Adds step to post activation action to determine initial room combination scenario 2021-07-22 12:46:27 -06:00
Neil Dorin
bfa48091d9 #753 Adds methods to build new room type 2021-07-22 12:44:13 -06:00
Neil Dorin
c4752b2ac2 #753 EssentialsCombinedHuddleVtc1Room should be ready for testing 2021-07-21 21:33:57 -06:00
Neil Dorin
152dcbe81e Merge remote-tracking branch 'origin/feature/fixes-for-multiple-room' into feature/room-combining 2021-07-21 14:20:45 -06:00
Neil Dorin
56f9a29c61 #753 Updates some of the Funcs 2021-07-21 14:19:57 -06:00
Neil Dorin
61d8370329 Updates to config type in IEssentialsHuddleVtc1Room 2021-07-20 17:27:30 -06:00
Neil Dorin
c8b0c7dd01 #753 Adds new type and starts updating as needed 2021-07-20 17:12:42 -06:00
71 changed files with 7311 additions and 3541 deletions

View File

@@ -22,7 +22,7 @@ env:
RELEASE_BRANCH: main
jobs:
Build_Project:
runs-on: windows-latest
runs-on: windows-2019
steps:
# First we checkout the source repo
- name: Checkout repo
@@ -98,7 +98,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Push_Nuget_Package:
needs: Build_Project
runs-on: windows-latest
runs-on: windows-2019
steps:
- name: Download Build Version Info
uses: actions/download-artifact@v1

View File

@@ -19,7 +19,7 @@ env:
RELEASE_BRANCH: main
jobs:
Build_Project:
runs-on: windows-latest
runs-on: windows-2019
steps:
# First we checkout the source repo
- name: Checkout repo
@@ -82,7 +82,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Push_Nuget_Package:
needs: Build_Project
runs-on: windows-latest
runs-on: windows-2019
steps:
- name: Download Build Version Info
uses: actions/download-artifact@v1

View File

@@ -506,8 +506,11 @@ namespace PepperDash.Essentials
{
DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((IEssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey));
if (!(room is EssentialsCombinedHuddleVtc1Room))
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((IEssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey));
}
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge...");

View File

@@ -144,6 +144,7 @@
<Compile Include="Room\Config\EssentialsRoomEmergencyConfig.cs" />
<Compile Include="Room\Config\EssentialsTechRoomConfig.cs" />
<Compile Include="Room\Emergency\EsentialsRoomEmergencyContactClosure.cs" />
<Compile Include="Room\Types\EssentialsCombinedHuddleVtc1Room.cs" />
<Compile Include="Room\Types\EssentialsDualDisplayRoom.cs" />
<Compile Include="Room\Types\EssentialsHuddleVtc1Room.cs" />
<Compile Include="Room\Types\EssentialsNDisplayRoomBase.cs" />

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<ControlSystem>
<Name>192.168.10.1</Name>
<Address>auto 192.168.10.1</Address>
<Name>Test RMC3</Name>
<Address>auto 192.168.1.40;username crestron</Address>
<ProgramSlot>Program01</ProgramSlot>
<Storage>Internal Flash</Storage>
</ControlSystem>

View File

@@ -39,6 +39,10 @@ namespace PepperDash.Essentials.Room.Config
{
return new EssentialsDualDisplayRoom(roomConfig);
}
if (typeName == "combinedhuddlevtc1")
{
return new EssentialsCombinedHuddleVtc1Room(roomConfig);
}
return typeName != "techroom" ? null : new EssentialsTechRoom(roomConfig);
}
@@ -198,9 +202,18 @@ namespace PepperDash.Essentials.Room.Config
[JsonProperty("fusion")]
public EssentialsRoomFusionConfig Fusion { get; set; }
[JsonProperty("essentialsRoomUiBehaviorConfig", NullValueHandling=NullValueHandling.Ignore)]
public EssentialsRoomUiBehaviorConfig UiBehavior { get; set; }
[JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")]
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; }
/// <summary>
/// Indicates if this room represents a combination of other rooms
/// </summary>
[JsonProperty("isRoomCombinationScenario")]
public bool IsRoomCombinationScenario { get; set; }
public EssentialsRoomPropertiesConfig()
{
LogoLight = new EssentialsLogoPropertiesConfig();
@@ -208,6 +221,12 @@ namespace PepperDash.Essentials.Room.Config
}
}
public class EssentialsRoomUiBehaviorConfig
{
[JsonProperty("disableActivityButtonsWhileWarmingCooling")]
public bool DisableActivityButtonsWhileWarmingCooling { get; set; }
}
public class EssentialsAvRoomPropertiesConfig : EssentialsRoomPropertiesConfig
{
[JsonProperty("defaultAudioKey")]

View File

@@ -56,6 +56,9 @@ namespace PepperDash.Essentials.Room.Config
[JsonProperty("mirroredTuners")]
public Dictionary<uint, string> MirroredTuners { get; set; }
[JsonProperty("helpMessage")]
public string HelpMessage { get; set; }
/// <summary>
/// Indicates the room
/// </summary>

View File

@@ -0,0 +1,821 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Common.AudioCodec;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials
{
public class EssentialsCombinedHuddleVtc1Room : EssentialsRoomBase, IEssentialsHuddleVtc1Room
{
private bool _codecExternalSourceChange;
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
public event SourceInfoChangeHandler CurrentSourceChange;
//************************
// Call-related stuff
public BoolFeedback InCallFeedback { get; private set; }
///// <summary>
///// Make this more specific
///// </summary>
//public List<CodecActiveCallItem> ActiveCalls { get; private set; }
/// <summary>
/// States: 0 for on hook, 1 for video, 2 for audio, 3 for telekenesis
/// </summary>
public IntFeedback CallTypeFeedback { get; private set; }
/// <summary>
///
/// </summary>
public BoolFeedback PrivacyModeIsOnFeedback { get; private set; }
/// <summary>
/// When something in the room is sharing with the far end or through other means
/// </summary>
public BoolFeedback IsSharingFeedback { get; private set; }
//************************
protected override Func<bool> OnFeedbackFunc
{
get
{
return () =>
{
var displays = Displays.OfType<DisplayBase>().ToList();
var val = CurrentSourceInfo != null
&& CurrentSourceInfo.Type == eSourceListItemType.Route
&& displays.Count > 0;
//&& disp.PowerIsOnFeedback.BoolValue;
return val;
};
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsWarmingFeedbackFunc
{
get
{
return () => Displays.OfType<TwoWayDisplayBase>().Any((d) => d.IsWarmingUpFeedback.BoolValue);
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsCoolingFeedbackFunc
{
get
{
return () => Displays.OfType<TwoWayDisplayBase>().Any((d) => d.IsCoolingDownFeedback.BoolValue);
}
}
public EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; private set; }
private List<IRoutingSinkWithSwitching> Displays;
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
public IBasicVolumeControls DefaultAudioDevice { get; private set; }
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
public VideoCodecBase VideoCodec { get; private set; }
public AudioCodecBase AudioCodec { get; private set; }
public bool ExcludeFromGlobalFunctions { get; set; }
public string DefaultSourceItem { get; set; }
public ushort DefaultVolume { get; set; }
/// <summary>
/// If room is off, enables power on to last source. Default true
/// </summary>
public bool EnablePowerOnToLastSource { get; set; }
string LastSourceKey;
/// <summary>
/// Sets the volume control device, and attaches/removes InUseTrackers with "audio"
/// tag to device.
/// </summary>
public IBasicVolumeControls CurrentVolumeControls
{
get { return _CurrentAudioDevice; }
set
{
if (value == _CurrentAudioDevice) return;
var oldDev = _CurrentAudioDevice;
// derigister this room from the device, if it can
if (oldDev is IInUseTracking)
(oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
var handler = CurrentVolumeDeviceChange;
if (handler != null)
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
_CurrentAudioDevice = value;
if (handler != null)
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
// register this room with new device, if it can
if (_CurrentAudioDevice is IInUseTracking)
(_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
}
}
IBasicVolumeControls _CurrentAudioDevice;
/// <summary>
/// The SourceListItem last run - containing names and icons
/// </summary>
public SourceListItem CurrentSourceInfo
{
get { return _CurrentSourceInfo; }
set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSourceChange;
// remove from in-use tracker, if so equipped
if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.WillChange);
_CurrentSourceInfo = value;
// add to in-use tracking
if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.DidChange);
var vc = VideoCodec as IHasExternalSourceSwitching;
if (vc != null && !_codecExternalSourceChange)
{
vc.SetSelectedSource(CurrentSourceInfoKey);
}
_codecExternalSourceChange = false;
}
}
SourceListItem _CurrentSourceInfo;
public string CurrentSourceInfoKey { get; set; }
/// <summary>
/// "codecOsd"
/// </summary>
public string DefaultCodecRouteString { get { return "codecOsd"; } }
/// <summary>
/// Temporary implementation. Returns the schedule-ready object or null if none. Fow now,
/// always returns the VideoCodec if it is capable
/// </summary>
public IHasScheduleAwareness ScheduleSource { get { return VideoCodec as IHasScheduleAwareness; } }
CCriticalSection SourceSelectLock = new CCriticalSection();
public EssentialsCombinedHuddleVtc1Room(DeviceConfig config)
: base(config)
{
try
{
PropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>
(config.Properties.ToString());
VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as
PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;
if (VideoCodec == null)
throw new ArgumentNullException("codec cannot be null");
AudioCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.AudioCodecKey) as
PepperDash.Essentials.Devices.Common.AudioCodec.AudioCodecBase;
if (AudioCodec == null)
Debug.Console(0, this, "No Audio Codec Found");
DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IBasicVolumeControls;
Displays = new List<IRoutingSinkWithSwitching>();
Initialize();
}
catch (Exception e)
{
Debug.Console(1, this, "Error building room: \n{0}", e);
}
}
void Initialize()
{
try
{
if (DefaultAudioDevice is IBasicVolumeControls)
DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls;
else if (DefaultAudioDevice is IHasVolumeDevice)
DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice;
CurrentVolumeControls = DefaultVolumeControls;
// Combines call feedback from both codecs if available
InCallFeedback = new BoolFeedback(() =>
{
bool inAudioCall = false;
bool inVideoCall = false;
if (AudioCodec != null)
inAudioCall = AudioCodec.IsInCall;
if (VideoCodec != null)
inVideoCall = VideoCodec.IsInCall;
if (inAudioCall || inVideoCall)
return true;
else
return false;
});
SetupDisplays();
// Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback
this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this);
Debug.Console(2, this, "Microphone Privacy Config evaluated.");
// Get emergency object, if any
this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this);
Debug.Console(2, this, "Emergency Config evaluated.");
VideoCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate();
VideoCodec.IsReadyChange += (o, a) => { this.SetCodecExternalSources(); SetCodecBranding(); };
if (AudioCodec != null)
AudioCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate();
IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue);
VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => this.IsSharingFeedback.FireUpdate();
// link privacy to VC (for now?)
PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue);
VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => this.PrivacyModeIsOnFeedback.FireUpdate();
CallTypeFeedback = new IntFeedback(() => 0);
SetSourceListKey();
EnablePowerOnToLastSource = true;
}
catch (Exception e)
{
Debug.Console(0, this, "Error Initializing Room: {0}", e);
}
}
private void SetupDisplays()
{
//DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching;
var destinationList = ConfigReader.ConfigObject.DestinationLists[PropertiesConfig.DestinationListKey];
foreach (var destination in destinationList)
{
var dest = destination.Value.SinkDevice as IRoutingSinkWithSwitching;
if (dest != null)
{
Displays.Add(dest);
}
var display = dest as DisplayBase;
if (display != null)
{
// Link power, warming, cooling to display
var dispTwoWay = display as IHasPowerControlWithFeedback;
if (dispTwoWay != null)
{
dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
{
//if (!dispTwoWay.PowerIsOnFeedback.BoolValue)
// CurrentSourceInfo = null;
OnFeedback.FireUpdate();
}
if (dispTwoWay.PowerIsOnFeedback.BoolValue)
{
SetDefaultLevels();
}
};
}
display.IsWarmingUpFeedback.OutputChange += (o, a) =>
{
IsWarmingUpFeedback.FireUpdate();
if (!IsWarmingUpFeedback.BoolValue)
(CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
};
display.IsCoolingDownFeedback.OutputChange += (o, a) =>
{
IsCoolingDownFeedback.FireUpdate();
};
}
}
}
private void SetSourceListKey()
{
if (!string.IsNullOrEmpty(PropertiesConfig.SourceListKey))
{
SetSourceListKey(PropertiesConfig.SourceListKey);
}
else
{
SetSourceListKey(Key);
}
SetCodecExternalSources();
}
protected override void CustomSetConfig(DeviceConfig config)
{
var newPropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>(config.Properties.ToString());
if (newPropertiesConfig != null)
PropertiesConfig = newPropertiesConfig;
ConfigWriter.UpdateRoomConfig(config);
}
public override bool CustomActivate()
{
// Add Occupancy object from config
if (PropertiesConfig.Occupancy != null)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Setting Occupancy Provider for room");
this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes);
}
this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight();
this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark();
this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);
return base.CustomActivate();
}
/// <summary>
///
/// </summary>
protected override void EndShutdown()
{
VideoCodec.EndAllCalls();
SetDefaultLevels();
RunDefaultPresentRoute();
CrestronEnvironment.Sleep(1000);
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting down room");
RunRouteAction("roomOff");
VideoCodec.StopSharing();
VideoCodec.StandbyActivate();
}
/// <summary>
/// Routes the default source item, if any. Returns true when default route exists
/// </summary>
public override bool RunDefaultPresentRoute()
{
if (DefaultSourceItem != null)
RunRouteAction(DefaultSourceItem);
return DefaultSourceItem != null;
}
/// <summary>
/// Sets up the room when started into call mode without presenting a source
/// </summary>
/// <returns></returns>
public bool RunDefaultCallRoute()
{
RunRouteAction(DefaultCodecRouteString);
return true;
}
public void RunRouteActionCodec(string routeKey, string sourceListKey)
{
_codecExternalSourceChange = true;
RunRouteAction(routeKey, sourceListKey);
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
public void RunRouteAction(string routeKey)
{
RunRouteAction(routeKey, new Action(() => { }));
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
/// <param name="souceListKey"></param>
/// <param name="successCallback"></param>
public void RunRouteAction(string routeKey, string sourceListKey)
{
if (string.IsNullOrEmpty(sourceListKey))
{
Debug.Console(1, this, "No sourceListKey present. RunRouteAction assumes default source list.");
RunRouteAction(routeKey, new Action(() => { }));
}
else
{
Debug.Console(1, this, "sourceListKey present but not yet implemented");
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
/// <param name="souceListKey"></param>
/// <param name="successCallback"></param>
public void RunRouteAction(string routeKey, string sourceListKey, Action successCallback)
{
if (string.IsNullOrEmpty(sourceListKey))
{
RunRouteAction(routeKey, successCallback);
}
else
throw new NotImplementedException();
}
/// <summary>
/// Gets a source from config list SourceListKey and dynamically build and executes the
/// route or commands
/// </summary>
/// <param name="name"></param>
public void RunRouteAction(string routeKey, Action successCallback)
{
// Run this on a separate thread
new CTimer(o =>
{
// try to prevent multiple simultaneous selections
SourceSelectLock.TryEnter();
try
{
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Run route action '{0}'", routeKey);
var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
if (dict == null)
{
Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
return;
}
// Try to get the list item by it's string key
if (!dict.ContainsKey(routeKey))
{
Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
routeKey, SourceListKey);
return;
}
// End usage timer on last source
if (!string.IsNullOrEmpty(LastSourceKey))
{
var usageLastSource = dict[LastSourceKey].SourceDevice as IUsageTracking;
if (usageLastSource != null && usageLastSource.UsageTracker != null)
{
try
{
// There MAY have been failures in here. Protect
usageLastSource.UsageTracker.EndDeviceUsage();
}
catch (Exception e)
{
Debug.Console(1, this, "*#* EXCEPTION in end usage tracking:\r{0}", e);
}
}
}
// Let's run it
var item = dict[routeKey];
if (routeKey.ToLower() != "roomoff")
{
LastSourceKey = routeKey;
}
else
CurrentSourceInfoKey = null;
// hand off the individual routes to this helper
foreach (var route in item.RouteList)
DoRouteItem(route);
// Start usage timer on routed source
var usageNewSource = item.SourceDevice as IUsageTracking;
if (usageNewSource != null && usageNewSource.UsageTracker != null) // Have to make sure there is a usage tracker!
{
(item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
}
// See if this can be moved into common, base-class method -------------
// Set volume control, using default if non provided
IBasicVolumeControls volDev = null;
// Handle special cases for volume control
if (string.IsNullOrEmpty(item.VolumeControlKey)
|| item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
volDev = DefaultVolumeControls;
//else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
// volDev = DefaultDisplay as IBasicVolumeControls;
// Or a specific device, probably rarely used.
else
{
var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
if (dev is IBasicVolumeControls)
volDev = dev as IBasicVolumeControls;
else if (dev is IHasVolumeDevice)
volDev = (dev as IHasVolumeDevice).VolumeDevice;
}
if (volDev != CurrentVolumeControls)
{
// zero the volume on the device we are leaving.
// Set the volume to default on device we are entering
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
{
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
SavedVolumeLevels[vd] = (uint)vd.VolumeLevelFeedback.IntValue;
vd.SetVolume(0);
}
CurrentVolumeControls = volDev;
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
{
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
ushort vol = (SavedVolumeLevels.ContainsKey(vd) ? (ushort)SavedVolumeLevels[vd] : DefaultVolume);
vd.SetVolume(vol);
}
}
// -----------------------------------------------------------------------
// store the name and UI info for routes
if (item.SourceKey == "$off")
{
CurrentSourceInfoKey = routeKey;
CurrentSourceInfo = null;
}
else if (item.SourceKey != null)
{
CurrentSourceInfoKey = routeKey;
CurrentSourceInfo = item;
}
OnFeedback.FireUpdate();
if (OnFeedback.BoolValue)
{
if (VideoCodec.UsageTracker.InUseTracker.InUseFeedback.BoolValue)
{
Debug.Console(1, this, "Video Codec in use, deactivating standby on codec");
VideoCodec.StandbyDeactivate();
}
if (VideoCodec.StandbyIsOnFeedback.BoolValue)
{
VideoCodec.StandbyDeactivate();
}
else
{
Debug.Console(1, this, "Video codec not in standby. No need to wake.");
}
}
else
{
Debug.Console(1, this, "Room OnFeedback state: {0}", OnFeedback.BoolValue);
}
// report back when done
if (successCallback != null)
successCallback();
}
catch (Exception e)
{
Debug.Console(1, this, "ERROR in routing: {0}", e);
}
SourceSelectLock.Leave();
}, 0); // end of CTimer
}
/// <summary>
///
/// </summary>
/// <param name="route"></param>
void DoRouteItem(SourceRouteListItem route)
{
// if there is a $defaultAll on route, run two separate
if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
{
foreach (var display in Displays)
{
var tempVideo = new SourceRouteListItem
{
DestinationKey = display.Key,
SourceKey = route.SourceKey,
Type = eRoutingSignalType.Video
};
DoRoute(tempVideo);
}
}
else
DoRoute(route);
}
/// <summary>
///
/// </summary>
/// <param name="route"></param>
/// <returns></returns>
bool DoRoute(SourceRouteListItem route)
{
IRoutingSink dest = null;
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
dest = DefaultAudioDevice as IRoutingSink;
//else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
// dest = DefaultDisplay;
else
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSink;
if (dest == null)
{
Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
return false;
}
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
{
dest.ReleaseRoute();
if (dest is IHasPowerControl)
(dest as IHasPowerControl).PowerOff();
}
else
{
var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
if (source == null)
{
Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
return false;
}
dest.ReleaseAndMakeRoute(source, route.Type);
}
return true;
}
public override void RoomVacatedForTimeoutPeriod(object o)
{
//Implement this
}
/// <summary>
/// Does what it says
/// </summary>
public override void SetDefaultLevels()
{
Debug.Console(1, this, "Restoring default levels");
var vc = CurrentVolumeControls as IBasicVolumeWithFeedback;
if (vc != null)
vc.SetVolume(DefaultVolume);
}
/// <summary>
/// Will power the room on with the last-used source
/// </summary>
public override void PowerOnToDefaultOrLastSource()
{
if (!EnablePowerOnToLastSource || LastSourceKey == null)
return;
RunRouteAction(LastSourceKey);
}
/// <summary>
/// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
/// </summary>
public static void AllRoomsOff()
{
var allRooms = DeviceManager.AllDevices.Where(d =>
d is IEssentialsRoom && !(d as IEssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
foreach (var room in allRooms)
(room as IEssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
}
/// <summary>
/// Setup the external sources for the Cisco Touch 10 devices that support IHasExternalSourceSwitch
/// </summary>
private void SetCodecExternalSources()
{
var videoCodecWithExternalSwitching = VideoCodec as IHasExternalSourceSwitching;
if (videoCodecWithExternalSwitching == null || !videoCodecWithExternalSwitching.ExternalSourceListEnabled)
{
return;
}
try
{
// Get the tie line that the external switcher is connected to
string codecInputConnectorName = ConfigReader.ConfigObject.TieLines.SingleOrDefault(
x => x.DestinationKey == VideoCodec.Key && x.DestinationPort == videoCodecWithExternalSwitching.ExternalSourceInputPort).DestinationPort;
videoCodecWithExternalSwitching.ClearExternalSources();
videoCodecWithExternalSwitching.RunRouteAction = RunRouteActionCodec;
var srcList = ConfigReader.ConfigObject.SourceLists.SingleOrDefault(x => x.Key == SourceListKey).Value.OrderBy(kv => kv.Value.Order); ;
foreach (var kvp in srcList)
{
var srcConfig = kvp.Value;
if (kvp.Key != DefaultCodecRouteString && kvp.Key != "roomOff")
{
videoCodecWithExternalSwitching.AddExternalSource(codecInputConnectorName, kvp.Key, srcConfig.PreferredName, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceType.desktop);
videoCodecWithExternalSwitching.SetExternalSourceState(kvp.Key, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceMode.Ready);
}
}
}
catch (Exception e)
{
Debug.Console(2, this, "Error setting codec external sources: {0}", e);
}
}
private void SetCodecBranding()
{
var vcWithBranding = VideoCodec as IHasBranding;
if (vcWithBranding == null) return;
Debug.Console(1, this, "Setting Codec Branding");
vcWithBranding.InitializeBranding(Key);
}
#region IPrivacy Members
public void PrivacyModeOff()
{
VideoCodec.PrivacyModeOff();
}
public void PrivacyModeOn()
{
VideoCodec.PrivacyModeOn();
}
public void PrivacyModeToggle()
{
VideoCodec.PrivacyModeToggle();
}
#endregion
}
}

View File

@@ -210,7 +210,7 @@ namespace PepperDash.Essentials
{
PropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>
(config.Properties.ToString());
DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching;
DefaultDisplay = DeviceManager.GetDeviceForKey((PropertiesConfig as EssentialsHuddleVtc1PropertiesConfig).DefaultDisplayKey) as IRoutingSinkWithSwitching;
VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as
PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;
@@ -708,11 +708,12 @@ namespace PepperDash.Essentials
IRoutingSink dest = null;
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
dest = DefaultAudioDevice as IRoutingSinkNoSwitching;
dest = DefaultAudioDevice as IRoutingSink;
else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
dest = DefaultDisplay;
else
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSink;
if (dest == null)
{

View File

@@ -19,7 +19,7 @@ namespace PepperDash.Essentials
{
public class EssentialsTechRoom : EssentialsRoomBase, ITvPresetsProvider, IBridgeAdvanced, IRunDirectRouteAction
{
private readonly EssentialsTechRoomConfig _config;
public EssentialsTechRoomConfig PropertiesConfig { get; private set; }
private readonly Dictionary<string, TwoWayDisplayBase> _displays;
private readonly DevicePresetsModel _tunerPresets;
@@ -57,16 +57,16 @@ namespace PepperDash.Essentials
public EssentialsTechRoom(DeviceConfig config) : base(config)
{
_config = config.Properties.ToObject<EssentialsTechRoomConfig>();
PropertiesConfig = config.Properties.ToObject<EssentialsTechRoomConfig>();
_tunerPresets = new DevicePresetsModel(String.Format("{0}-presets", config.Key), _config.PresetsFileName);
_tunerPresets = new DevicePresetsModel(String.Format("{0}-presets", config.Key), PropertiesConfig.PresetsFileName);
_tunerPresets.SetFileName(_config.PresetsFileName);
_tunerPresets.SetFileName(PropertiesConfig.PresetsFileName);
_tunerPresets.PresetRecalled += TunerPresetsOnPresetRecalled;
_tuners = GetDevices<IRSetTopBoxBase>(_config.Tuners);
_displays = GetDevices<TwoWayDisplayBase>(_config.Displays);
_tuners = GetDevices<IRSetTopBoxBase>(PropertiesConfig.Tuners);
_displays = GetDevices<TwoWayDisplayBase>(PropertiesConfig.Displays);
RoomPowerIsOnFeedback = new BoolFeedback(() => RoomPowerIsOn);
@@ -153,7 +153,7 @@ namespace PepperDash.Essentials
private void CreateOrUpdateScheduledEvents()
{
var eventsConfig = _config.ScheduledEvents;
var eventsConfig = PropertiesConfig.ScheduledEvents;
GetOrCreateScheduleGroup();
@@ -207,21 +207,21 @@ namespace PepperDash.Essentials
{
//update config based on key of scheduleEvent
GetOrCreateScheduleGroup();
var existingEventIndex = _config.ScheduledEvents.FindIndex((e) => e.Key == scheduledEvent.Key);
var existingEventIndex = PropertiesConfig.ScheduledEvents.FindIndex((e) => e.Key == scheduledEvent.Key);
if (existingEventIndex < 0)
{
_config.ScheduledEvents.Add(scheduledEvent);
PropertiesConfig.ScheduledEvents.Add(scheduledEvent);
}
else
{
_config.ScheduledEvents[existingEventIndex] = scheduledEvent;
PropertiesConfig.ScheduledEvents[existingEventIndex] = scheduledEvent;
}
//create or update event based on config
CreateOrUpdateSingleEvent(scheduledEvent);
//save config
Config.Properties = JToken.FromObject(_config);
Config.Properties = JToken.FromObject(PropertiesConfig);
CustomSetConfig(Config);
//Fire Event
@@ -230,7 +230,7 @@ namespace PepperDash.Essentials
public List<ScheduledEventConfig> GetScheduledEvents()
{
return _config.ScheduledEvents ?? new List<ScheduledEventConfig>();
return PropertiesConfig.ScheduledEvents ?? new List<ScheduledEventConfig>();
}
private void OnScheduledEventUpdate()
@@ -242,14 +242,14 @@ namespace PepperDash.Essentials
return;
}
handler(this, new ScheduledEventEventArgs {ScheduledEvents = _config.ScheduledEvents});
handler(this, new ScheduledEventEventArgs {ScheduledEvents = PropertiesConfig.ScheduledEvents});
}
public event EventHandler<ScheduledEventEventArgs> ScheduledEventsChanged;
private void HandleScheduledEvent(ScheduledEvent schevent, ScheduledEventCommon.eCallbackReason type)
{
var eventConfig = _config.ScheduledEvents.FirstOrDefault(e => e.Key == schevent.Name);
var eventConfig = PropertiesConfig.ScheduledEvents.FirstOrDefault(e => e.Key == schevent.Name);
if (eventConfig == null)
{
@@ -286,11 +286,11 @@ Params: {2}"
{
Debug.Console(2, this, "Room Powering On");
var dummySource = DeviceManager.GetDeviceForKey(_config.DummySourceKey) as IRoutingOutputs;
var dummySource = DeviceManager.GetDeviceForKey(PropertiesConfig.DummySourceKey) as IRoutingOutputs;
if (dummySource == null)
{
Debug.Console(1, this, "Unable to get source with key: {0}", _config.DummySourceKey);
Debug.Console(1, this, "Unable to get source with key: {0}", PropertiesConfig.DummySourceKey);
return;
}
@@ -376,12 +376,12 @@ Params: {2}"
bridge.AddJoinMap(Key, joinMap);
}
if (_config.IsPrimary)
if (PropertiesConfig.IsPrimary)
{
Debug.Console(1, this, "Linking Primary system Tuner Preset Mirroring");
if (_config.MirroredTuners != null && _config.MirroredTuners.Count > 0)
if (PropertiesConfig.MirroredTuners != null && PropertiesConfig.MirroredTuners.Count > 0)
{
foreach (var tuner in _config.MirroredTuners)
foreach (var tuner in PropertiesConfig.MirroredTuners)
{
var f = CurrentPresetsFeedbacks[tuner.Value];
@@ -423,9 +423,9 @@ Params: {2}"
{
Debug.Console(1, this, "Linking Secondary system Tuner Preset Mirroring");
if (_config.MirroredTuners != null && _config.MirroredTuners.Count > 0)
if (PropertiesConfig.MirroredTuners != null && PropertiesConfig.MirroredTuners.Count > 0)
{
foreach (var tuner in _config.MirroredTuners)
foreach (var tuner in PropertiesConfig.MirroredTuners)
{
var t = _tuners[tuner.Value];

View File

@@ -7,7 +7,7 @@ using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials
{
public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay
public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay, IHasCurrentVolumeControls
{
bool ExcludeFromGlobalFunctions { get; }

View File

@@ -12,6 +12,8 @@ namespace PepperDash.Essentials
{
EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; }
bool ExcludeFromGlobalFunctions { get; }
void RunRouteAction(string routeKey);
IHasScheduleAwareness ScheduleSource { get; }

View File

@@ -16,6 +16,8 @@ namespace PepperDash.Essentials
{
public class EssentialsTouchpanelController : EssentialsDevice, IHasBasicTriListWithSmartObject
{
private CrestronTouchpanelPropertiesConfig _propertiesConfig;
public BasicTriListWithSmartObject Panel { get; private set; }
public PanelDriverBase PanelDriver { get; private set; }
@@ -27,7 +29,14 @@ namespace PepperDash.Essentials
: base(key, name)
{
Panel = tsw;
tsw.LoadSmartObjects(sgdPath);
if (!string.IsNullOrEmpty(sgdPath))
Panel.LoadSmartObjects(sgdPath);
else
Debug.Console(1, this, "No SGD file path defined");
tsw.SigChange += Panel_SigChange;
}
@@ -37,7 +46,7 @@ namespace PepperDash.Essentials
Panel = dge;
if (!string.IsNullOrEmpty(sgdPath))
dge.LoadSmartObjects(sgdPath);
Panel.LoadSmartObjects(sgdPath);
else
Debug.Console(1, this, "No SGD file path defined");
@@ -50,6 +59,7 @@ namespace PepperDash.Essentials
public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id)
: base(key, name)
{
_propertiesConfig = props;
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating touchpanel hardware...");
type = type.ToLower();
@@ -61,6 +71,8 @@ namespace PepperDash.Essentials
app.ParameterProjectName.Value = props.ProjectName;
Panel = app;
}
else if (type == "xpanel")
Panel = new XpanelForSmartGraphics(id, Global.ControlSystem);
else if (type == "tsw550")
Panel = new Tsw550(id, Global.ControlSystem);
else if (type == "tsw552")
@@ -134,10 +146,194 @@ namespace PepperDash.Essentials
Panel.LoadSmartObjects(sgdName);
Panel.SigChange += Panel_SigChange;
AddPostActivationAction(() =>
{
// Check for IEssentialsRoomCombiner in DeviceManager and if found, subscribe to its event
var roomCombiner = DeviceManager.AllDevices.FirstOrDefault((d) => d is IEssentialsRoomCombiner) as IEssentialsRoomCombiner;
if (roomCombiner != null)
{
// Subscribe to the even
roomCombiner.RoomCombinationScenarioChanged += new EventHandler<EventArgs>(roomCombiner_RoomCombinationScenarioChanged);
// Connect to the initial roomKey
if (roomCombiner.CurrentScenario != null)
{
// Use the current scenario
DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario);
}
else
{
// Current Scenario not yet set. Use default
SetupPanelDrivers(_propertiesConfig.DefaultRoomKey);
}
}
else
{
// No room combiner, use the default key
SetupPanelDrivers(_propertiesConfig.DefaultRoomKey);
}
});
}
void roomCombiner_RoomCombinationScenarioChanged(object sender, EventArgs e)
{
var roomCombiner = sender as IEssentialsRoomCombiner;
DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario);
}
/// <summary>
/// Determines the room key to use based on the scenario
/// </summary>
/// <param name="scenario"></param>
void DetermineRoomKeyFromScenario(IRoomCombinationScenario scenario)
{
string newRoomKey = null;
if (scenario.UiMap.ContainsKey(Key))
{
newRoomKey = scenario.UiMap[Key];
}
else if (scenario.UiMap.ContainsKey(_propertiesConfig.DefaultRoomKey))
{
newRoomKey = scenario.UiMap[_propertiesConfig.DefaultRoomKey];
}
SetupPanelDrivers(newRoomKey);
}
/// <summary>
/// Sets up drivers and links them to the room specified
/// </summary>
/// <param name="roomKey">key of room to link the drivers to</param>
void SetupPanelDrivers(string roomKey)
{
// Clear out any existing actions
Panel.ClearAllSigActions();
Debug.Console(0, this, "Linking TP '{0}' to Room '{1}'", Key, roomKey);
var mainDriver = new EssentialsPanelMainInterfaceDriver(Panel, _propertiesConfig);
// Then the sub drivers
// spin up different room drivers depending on room type
var room = DeviceManager.GetDeviceForKey(roomKey);
if (room is IEssentialsHuddleSpaceRoom)
{
// Screen Saver Driver
mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, _propertiesConfig);
// Header Driver
Debug.Console(0, this, "Adding header driver");
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _propertiesConfig);
// AV Driver
Debug.Console(0, this, "Adding huddle space AV driver");
var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, _propertiesConfig);
avDriver.DefaultRoomKey = roomKey;
mainDriver.AvDriver = avDriver;
avDriver.CurrentRoom = room as IEssentialsHuddleSpaceRoom;
// Environment Driver
if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0)
{
Debug.Console(0, this, "Adding environment driver");
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, _propertiesConfig);
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment);
}
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
if (Panel is TswFt5ButtonSystem)
{
var tsw = Panel as TswFt5ButtonSystem;
// Wire up hard keys
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
if (mainDriver.EnvironmentDriver != null)
tsw.Lights.UserObject = new Action<bool>(b =>
{
if (!b)
{
mainDriver.EnvironmentDriver.Toggle();
}
});
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
}
}
else if (room is IEssentialsHuddleVtc1Room)
{
Debug.Console(0, this, "Adding huddle space VTC AV driver");
// Screen Saver Driver
mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, _propertiesConfig);
// Header Driver
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _propertiesConfig);
// AV Driver
var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, _propertiesConfig);
var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(Panel, avDriver,
(room as IEssentialsHuddleVtc1Room).VideoCodec, mainDriver.HeaderDriver);
avDriver.SetVideoCodecDriver(codecDriver);
avDriver.DefaultRoomKey = roomKey;
mainDriver.AvDriver = avDriver;
avDriver.CurrentRoom = room as IEssentialsHuddleVtc1Room;
// Environment Driver
if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0)
{
Debug.Console(0, this, "Adding environment driver");
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, _propertiesConfig);
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment);
}
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
if (Panel is TswFt5ButtonSystem)
{
var tsw = Panel as TswFt5ButtonSystem;
// Wire up hard keys
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.EndMeetingPress(); });
if (mainDriver.EnvironmentDriver != null)
tsw.Lights.UserObject = new Action<bool>(b =>
{
if (!b)
{
mainDriver.EnvironmentDriver.Toggle();
}
});
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
}
LoadAndShowDriver(mainDriver);
}
else
{
Debug.Console(0, this, "ERROR: Cannot load AvFunctionsDriver for room '{0}'", roomKey);
}
}
public void LoadAndShowDriver(PanelDriverBase driver)
{
if (PanelDriver != null)
{
var mainDriver = PanelDriver as EssentialsPanelMainInterfaceDriver;
if (mainDriver != null)
{
mainDriver.Dispose();
}
}
PanelDriver = driver;
driver.Show();
}
@@ -148,7 +344,6 @@ namespace PepperDash.Essentials
PanelDriver.BackButtonPressed();
}
void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
{
// If the sig is transitioning on, mark it in case it was home button that transitioned it
@@ -225,119 +420,6 @@ namespace PepperDash.Essentials
var panelController = new EssentialsTouchpanelController(dc.Key, dc.Name, dc.Type, props, comm.IpIdInt);
panelController.AddPostActivationAction(() =>
{
var mainDriver = new EssentialsPanelMainInterfaceDriver(panelController.Panel, props);
// Then the sub drivers
// spin up different room drivers depending on room type
var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey);
if (room is IEssentialsHuddleSpaceRoom)
{
// Screen Saver Driver
mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, props);
// Header Driver
Debug.Console(0, panelController, "Adding header driver");
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, props);
// AV Driver
Debug.Console(0, panelController, "Adding huddle space AV driver");
var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, props);
avDriver.DefaultRoomKey = props.DefaultRoomKey;
mainDriver.AvDriver = avDriver;
avDriver.CurrentRoom = room as IEssentialsHuddleSpaceRoom;
// Environment Driver
if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0)
{
Debug.Console(0, panelController, "Adding environment driver");
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, props);
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment);
}
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
panelController.LoadAndShowDriver(mainDriver); // This is a little convoluted.
if (panelController.Panel is TswFt5ButtonSystem)
{
var tsw = panelController.Panel as TswFt5ButtonSystem;
// Wire up hard keys
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
if (mainDriver.EnvironmentDriver != null)
tsw.Lights.UserObject = new Action<bool>(b =>
{
if (!b)
{
//mainDriver.AvDriver.PopupInterlock.ShowInterlockedWithToggle(mainDriver.EnvironmentDriver.BackgroundSubpageJoin);
mainDriver.EnvironmentDriver.Toggle();
}
});
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
}
}
else if (room is IEssentialsHuddleVtc1Room)
{
Debug.Console(0, panelController, "Adding huddle space VTC AV driver");
// Screen Saver Driver
mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, props);
// Header Driver
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, props);
// AV Driver
var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, props);
var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(panelController.Panel, avDriver,
(room as IEssentialsHuddleVtc1Room).VideoCodec, mainDriver.HeaderDriver);
avDriver.SetVideoCodecDriver(codecDriver);
avDriver.DefaultRoomKey = props.DefaultRoomKey;
mainDriver.AvDriver = avDriver;
avDriver.CurrentRoom = room as IEssentialsHuddleVtc1Room;
// Environment Driver
if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0)
{
Debug.Console(0, panelController, "Adding environment driver");
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, props);
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment);
}
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
panelController.LoadAndShowDriver(mainDriver); // This is a little convoluted.
if (panelController.Panel is TswFt5ButtonSystem)
{
var tsw = panelController.Panel as TswFt5ButtonSystem;
// Wire up hard keys
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.EndMeetingPress(); });
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
if (mainDriver.EnvironmentDriver != null)
tsw.Lights.UserObject = new Action<bool>(b =>
{
if (!b)
{
//mainDriver.AvDriver.PopupInterlock.ShowInterlockedWithToggle(mainDriver.EnvironmentDriver.BackgroundSubpageJoin);
mainDriver.EnvironmentDriver.Toggle();
}
});
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
}
}
else
{
Debug.Console(0, panelController, "ERROR: Cannot load AvFunctionsDriver for room '{0}'", props.DefaultRoomKey);
}
});
return panelController;
}
}

View File

@@ -14,6 +14,8 @@ namespace PepperDash.Essentials
{
public SourceListItem SourceItem { get; private set; }
private IHasCurrentSourceInfoChange _room;
public SubpageReferenceListSourceItem(uint index, SubpageReferenceList owner,
SourceListItem sourceItem, Action<bool> routeAction)
: base(index, owner)
@@ -25,6 +27,7 @@ namespace PepperDash.Essentials
public void RegisterForSourceChange(IHasCurrentSourceInfoChange room)
{
_room = room;
room.CurrentSourceChange -= room_CurrentSourceInfoChange;
room.CurrentSourceChange += room_CurrentSourceInfoChange;
}
@@ -44,6 +47,9 @@ namespace PepperDash.Essentials
{
Owner.BoolInputSig(Index, 1).UserObject = null;
Owner.StringInputSig(Index, 1).StringValue = "";
if(_room != null)
_room.CurrentSourceChange -= room_CurrentSourceInfoChange;
}
/// <summary>

View File

@@ -11,7 +11,7 @@ namespace PepperDash.Essentials
/// <summary>
///
/// </summary>
public class EssentialsPanelMainInterfaceDriver : PanelDriverBase, IHasScreenSaverController
public class EssentialsPanelMainInterfaceDriver : PanelDriverBase, IHasScreenSaverController, IDisposable
{
CTimer InactivityTimer;
@@ -69,6 +69,35 @@ namespace PepperDash.Essentials
}
}
#region IDisposable Members
public void Dispose()
{
var avDriver = AvDriver as PanelDriverBase;
if (avDriver != null)
{
avDriver.Hide();
}
if (ScreenSaverController != null)
{
ScreenSaverController.Dispose();
}
if (HeaderDriver != null)
{
HeaderDriver.Hide();
}
if (EnvironmentDriver != null)
{
EnvironmentDriver.Hide();
}
if (CurrentChildDriver != null)
{
CurrentChildDriver.Hide();
}
}
#endregion
void ExtenderTouchDetectionReservedSigs_DeviceExtenderSigChange(Crestron.SimplSharpPro.DeviceExtender currentDeviceExtender, Crestron.SimplSharpPro.SigEventArgs args)
{
@@ -130,7 +159,7 @@ namespace PepperDash.Essentials
if(CurrentChildDriver != null)
CurrentChildDriver.BackButtonPressed();
}
}
}
public interface IHasScreenSaverController
{

View File

@@ -306,7 +306,7 @@ namespace PepperDash.Essentials
TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () =>
{
if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IHasPowerControl)
if (CurrentRoom != null && CurrentRoom.DefaultDisplay != null && CurrentRoom.DefaultDisplay is IHasPowerControl)
(CurrentRoom.DefaultDisplay as IHasPowerControl).PowerToggle();
});

View File

@@ -354,7 +354,7 @@ namespace PepperDash.Essentials
TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () =>
{
if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IHasPowerControl)
if (CurrentRoom != null && CurrentRoom.DefaultDisplay != null && CurrentRoom.DefaultDisplay is IHasPowerControl)
(CurrentRoom.DefaultDisplay as IHasPowerControl).PowerToggle();
});
@@ -493,10 +493,10 @@ namespace PepperDash.Essentials
// and the LastMeetingDismissed != this meeting
var lastMeetingDismissed = meetings.FirstOrDefault(m => m.Id == LastMeetingDismissedId);
Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*",
CurrentRoom.OnFeedback.BoolValue,
LastMeetingDismissedId,
lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToString("t", Global.Culture) : "");
//Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*",
// CurrentRoom.OnFeedback.BoolValue,
// LastMeetingDismissedId,
// lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToString("t", Global.Culture) : "");
var meeting = meetings.LastOrDefault(m => m.Joinable);
if (CurrentRoom.OnFeedback.BoolValue

View File

@@ -52,7 +52,7 @@ namespace PepperDash.Essentials
{
var prevJoin = CurrentJoin;
var wasShown = _IsShown;
Debug.Console(2, "Trilist {0:X2}, interlock swapping {1} for {2}", TriList.ID, CurrentJoin, join);
//Debug.Console(2, "Trilist {0:X2}, interlock swapping {1} for {2}", TriList.ID, CurrentJoin, join);
if (CurrentJoin == join && TriList.BooleanInput[join].BoolValue)
return;
SetButDontShow(join);
@@ -71,7 +71,7 @@ namespace PepperDash.Essentials
var prevJoin = CurrentJoin;
var wasShown = IsShown;
Debug.Console(2, "Trilist {0:X2}, interlock swapping {1} for {2}", TriList.ID, CurrentJoin, join);
//Debug.Console(2, "Trilist {0:X2}, interlock swapping {1} for {2}", TriList.ID, CurrentJoin, join);
if (CurrentJoin == join)
HideAndClear();
else
@@ -92,7 +92,7 @@ namespace PepperDash.Essentials
{
var prevJoin = CurrentJoin;
var wasShown = IsShown;
Debug.Console(2, "Trilist {0:X2}, interlock hiding {1}", TriList.ID, CurrentJoin);
//Debug.Console(2, "Trilist {0:X2}, interlock hiding {1}", TriList.ID, CurrentJoin);
Hide();
CurrentJoin = 0;
@@ -108,7 +108,7 @@ namespace PepperDash.Essentials
var prevJoin = CurrentJoin;
var wasShown = IsShown;
Debug.Console(2, "Trilist {0:X2}, interlock hiding {1}", TriList.ID, CurrentJoin);
//Debug.Console(2, "Trilist {0:X2}, interlock hiding {1}", TriList.ID, CurrentJoin);
if (CurrentJoin > 0)
{
TriList.BooleanInput[CurrentJoin].BoolValue = false;
@@ -125,7 +125,7 @@ namespace PepperDash.Essentials
var prevJoin = CurrentJoin;
var wasShown = IsShown;
Debug.Console(2, "Trilist {0:X2}, interlock showing {1}", TriList.ID, CurrentJoin);
//Debug.Console(2, "Trilist {0:X2}, interlock showing {1}", TriList.ID, CurrentJoin);
if (CurrentJoin > 0)
{
TriList.BooleanInput[CurrentJoin].BoolValue = true;

View File

@@ -12,7 +12,7 @@ namespace PepperDash.Essentials
/// <summary>
/// Driver responsible for controlling the screenshaver showing the client logo, MC connection information and QR Code. Moves the elements around to prevent screen burn in
/// </summary>
public class ScreenSaverController : PanelDriverBase
public class ScreenSaverController : PanelDriverBase, IDisposable
{
/// <summary>
@@ -42,7 +42,7 @@ namespace PepperDash.Essentials
PositionInterlock = new JoinedSigInterlock(parent.TriList);
var cmdName = String.Format("shwscrsvr-{0}", parent.TriList.ID);
var cmdName = String.Format("shwscrsvr-{0:X2}", parent.TriList.ID);
CrestronConsole.AddNewConsoleCommand((o) => Show(), cmdName, "Shows Panel Screensaver", ConsoleAccessLevelEnum.AccessOperator);
@@ -51,6 +51,8 @@ namespace PepperDash.Essentials
public override void Show()
{
//Debug.Console(2, "Showing ScreenSaverController: {0:X2}", TriList.ID);
if (_parent.AvDriver != null)
{
_parent.AvDriver.PopupInterlock.ShowInterlocked(UIBoolJoin.MCScreenSaverVisible);
@@ -65,10 +67,11 @@ namespace PepperDash.Essentials
public override void Hide()
{
Debug.Console(1, "Hiding ScreenSaverController");
//Debug.Console(2, "Hiding ScreenSaverController: {0:X2}", TriList.ID);
if (PositionTimer != null)
{
//Debug.Console(2, "Stopping PositionTimer: {0:X2}", TriList.ID);
PositionTimer.Stop();
PositionTimer.Dispose();
PositionTimer = null;
@@ -86,6 +89,8 @@ namespace PepperDash.Essentials
void StartPositionTimer()
{
//Debug.Console(2, "Starting Position Timer: {0:X2}", TriList.ID);
if (PositionTimer == null)
{
PositionTimer = new CTimer((o) => PositionTimerExpired(), PositionTimeoutMs);
@@ -117,7 +122,7 @@ namespace PepperDash.Essentials
CurrentPositionIndex = 0;
}
Debug.Console(1, "ScreenSaver Position Timer Expired: Setting new position: {0}", CurrentPositionIndex);
//Debug.Console(2, "ScreenSaver Position Timer Expired: Setting new position: {0} ID: {1:X2}", CurrentPositionIndex, TriList.ID);
}
//
@@ -129,9 +134,19 @@ namespace PepperDash.Essentials
void ClearAllPositions()
{
Debug.Console(1, "Hiding all screensaver positions");
//Debug.Console(2, "Hiding all screensaver positions: {0:X2}", TriList.ID);
PositionInterlock.HideAndClear();
}
#region IDisposable Members
public void Dispose()
{
Hide();
}
#endregion
}
}

View File

@@ -632,7 +632,6 @@ namespace PepperDash.Essentials.UIDrivers.VC
VCControlsInterlock.StatusChanged += new EventHandler<StatusChangedEventArgs>(VCControlsInterlock_StatusChanged);
var codecOffCameras = Codec as IHasCameraOff;
var supportsCameraOffMode = Codec.SupportsCameraOff;
@@ -643,6 +642,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
if (codecAutoCameras != null && supportsAutoCameraMode)
{
CameraModeList.SetItemButtonAction(1,(b) => codecAutoCameras.CameraAutoModeOn());
TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 1 Visible"].BoolValue = true;
codecAutoCameras.CameraAutoModeIsOnFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 1 Selected"]);
@@ -672,6 +672,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
}
};
}
// Manual button always visible
@@ -683,6 +684,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
if (codecOffCameras != null && supportsCameraOffMode)
{
TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 3 Visible"].BoolValue = true;
codecOffCameras.CameraIsOffFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 3 Selected"]);
CameraModeList.SetItemButtonAction(3, (b) => codecOffCameras.CameraOff());
@@ -710,6 +712,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
}
};
}
}

View File

@@ -42,3 +42,6 @@ devjson:2 {"deviceKey":"display01Comm-com", "methodName":"SendText", "params": [
devjson:10 {"deviceKey":"dmLink-ssh", "methodName":"Connect", "params": []}
devjson:2 {"deviceKey":"roomCombiner", "methodName":"SetRoomCombinationScenario", "params": ["combined"]}
devjson:2 {"deviceKey":"roomCombiner", "methodName":"SetRoomCombinationScenario", "params": ["divided"]}

View File

@@ -66,7 +66,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
#endregion
}
public class C2NIoControllerFactory : EssentialsDeviceFactory<C2nRthsController>
public class C2NIoControllerFactory : EssentialsDeviceFactory<C2NIoController>
{
public C2NIoControllerFactory()
{

View File

@@ -34,7 +34,7 @@ namespace PepperDash.Essentials.Core
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new C2N-RTHS Device");
Debug.Console(1, "Factory Attempting to create new DIN-CEN-CN2 Device");
var control = CommFactory.GetControlPropertiesConfig(dc);
var ipid = control.IpIdInt;

View File

@@ -16,7 +16,7 @@ namespace PepperDash.Essentials.Core
/// Wrapper class for CEN-IO-DIGIN-104 digital input module
/// </summary>
[Description("Wrapper class for the CEN-IO-DIGIN-104 diginal input module")]
public class CenIoDigIn104Controller : EssentialsDevice, IDigitalInputPorts
public class CenIoDigIn104Controller : CrestronGenericBaseDevice, IDigitalInputPorts
{
public CenIoDi104 Di104 { get; private set; }
@@ -52,10 +52,17 @@ namespace PepperDash.Essentials.Core
{
Debug.Console(1, "Factory Attempting to create new CEN-DIGIN-104 Device");
var control = CommFactory.GetControlPropertiesConfig(dc);
var ipid = control.IpIdInt;
return new CenIoDigIn104Controller(dc.Key, dc.Name, new Crestron.SimplSharpPro.GeneralIO.CenIoDi104(ipid, Global.ControlSystem));
var control = CommFactory.GetControlPropertiesConfig(dc);
if (control == null)
{
Debug.Console(1, "Factory failed to create a new CEN-DIGIN-104 Device, control properties not found");
return null;
}
var ipid = control.IpIdInt;
if (ipid != 0) return new CenIoDigIn104Controller(dc.Key, dc.Name, new CenIoDi104(ipid, Global.ControlSystem));
Debug.Console(1, "Factory failed to create a new CEN-IO-IR-104 Device using IP-ID-{0}", ipid);
return null;
}
}

View File

@@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.GeneralIO;
using PepperDash.Essentials.Core.Config;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Wrapper class for CEN-IO-IR-104 module
/// </summary>
[Description("Wrapper class for the CEN-IO-IR-104 module")]
public class CenIoIr104Controller : CrestronGenericBaseDevice, IIROutputPorts
{
private readonly CenIoIr104 _ir104;
/// <summary>
/// Constructor
/// </summary>
/// <param name="key"></param>
/// <param name="name"></param>
/// <param name="ir104"></param>
public CenIoIr104Controller(string key, string name, CenIoIr104 ir104)
: base(key, name, ir104)
{
_ir104 = ir104;
}
#region IDigitalInputPorts Members
/// <summary>
/// IR port collection
/// </summary>
public CrestronCollection<IROutputPort> IROutputPorts
{
get { return _ir104.IROutputPorts; }
}
/// <summary>
/// Number of relay ports property
/// </summary>
public int NumberOfIROutputPorts
{
get { return _ir104.NumberOfIROutputPorts; }
}
#endregion
}
/// <summary>
/// CEN-IO-IR-104 controller fatory
/// </summary>
public class CenIoIr104ControllerFactory : EssentialsDeviceFactory<CenIoIr104Controller>
{
/// <summary>
/// Constructor
/// </summary>
public CenIoIr104ControllerFactory()
{
TypeNames = new List<string>() { "cenioir104" };
}
/// <summary>
/// Build device CEN-IO-IR-104
/// </summary>
/// <param name="dc"></param>
/// <returns></returns>
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new CEN-IO-IR-104 Device");
var control = CommFactory.GetControlPropertiesConfig(dc);
if (control == null)
{
Debug.Console(1, "Factory failed to create a new CEN-IO-IR-104 Device, control properties not found");
return null;
}
var ipid = control.IpIdInt;
if(ipid != 0) return new CenIoIr104Controller(dc.Key, dc.Name, new CenIoIr104(ipid, Global.ControlSystem));
Debug.Console(1, "Factory failed to create a new CEN-IO-IR-104 Device using IP-ID-{0}", ipid);
return null;
}
}
}

View File

@@ -10,7 +10,7 @@ namespace PepperDash.Essentials.Core
/// Wrapper class for CEN-IO-RY-104 relay module
/// </summary>
[Description("Wrapper class for the CEN-IO-RY-104 relay module")]
public class CenIoRy104Controller : EssentialsDevice, IRelayPorts
public class CenIoRy104Controller : CrestronGenericBaseDevice, IRelayPorts
{
private readonly CenIoRy104 _ry104;
@@ -21,7 +21,7 @@ namespace PepperDash.Essentials.Core
/// <param name="name"></param>
/// <param name="ry104"></param>
public CenIoRy104Controller(string key, string name, CenIoRy104 ry104)
: base(key, name)
: base(key, name, ry104)
{
_ry104 = ry104;
}
@@ -62,8 +62,8 @@ namespace PepperDash.Essentials.Core
var controlPropertiesConfig = CommFactory.GetControlPropertiesConfig(dc);
if (controlPropertiesConfig == null)
{
Debug.Console(1, "Factory failed to create a new CEN-IO-RY-104 Device");
{
Debug.Console(1, "Factory failed to create a new CEN-IO-RY-104 Device, control properties not found");
return null;
}

View File

@@ -8,7 +8,7 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
/// </summary>
public interface IMobileControl : IKeyed
{
void CreateMobileControlRoomBridge(EssentialsRoomBase room, IMobileControl parent);
void CreateMobileControlRoomBridge(IEssentialsRoom room, IMobileControl parent);
void LinkSystemMonitorToAppServer();
}

View File

@@ -20,7 +20,12 @@ namespace PepperDash.Essentials.Core
/// Submits the password
/// </summary>
/// <param name="password"></param>
void SubmitPassword(string password);
void SubmitPassword(string password);
/// <summary>
/// Cancels the password submission
/// </summary>
void CancelPasswordPrompt();
}
public class PasswordPromptEventArgs : EventArgs

View File

@@ -105,9 +105,6 @@ namespace PepperDash.Essentials.Core
protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, uint joinStart, string joinMapKey,
EiscApiAdvanced bridge)
{
var inputNumber = 0;
var inputKeys = new List<string>();
var joinMap = new DisplayControllerJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
@@ -124,133 +121,141 @@ namespace PepperDash.Essentials.Core
Debug.Console(0,this,"Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, "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 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.Console(0, "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.Console(2, 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.Console(0, displayDevice, Debug.ErrorLogLevel.Warning, "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.Console(2, 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]);
LinkDisplayToApi(displayDevice, trilist, joinMap);
}
protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, DisplayControllerJoinMap joinMap)
{
Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, "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.Console(0, "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.Console(2, 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.Console(0, displayDevice, Debug.ErrorLogLevel.Warning, "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.Console(2, 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]);
}
}
/// <summary>

View File

@@ -30,11 +30,40 @@ namespace PepperDash.Essentials.Core
bool _PowerIsOn;
bool _IsWarmingUp;
bool _IsCoolingDown;
protected override Func<bool> PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } }
protected override Func<bool> IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } }
protected override Func<bool> IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } }
bool _IsCoolingDown;
protected override Func<bool> PowerIsOnFeedbackFunc
{
get
{
return () =>
{
Debug.Console(2, this, "*************************************************** Display Power is {0}", _PowerIsOn ? "on" : "off");
return _PowerIsOn;
};
} }
protected override Func<bool> IsCoolingDownFeedbackFunc
{
get
{
return () =>
{
Debug.Console(2, this, "*************************************************** {0}", _IsCoolingDown ? "Display is cooling down" : "Display has finished cooling down");
return _IsCoolingDown;
};
}
}
protected override Func<bool> IsWarmingUpFeedbackFunc
{
get
{
return () =>
{
Debug.Console(2, this, "*************************************************** {0}", _IsWarmingUp ? "Display is warming up" : "Display has finished warming up");
return _IsWarmingUp;
};
}
}
protected override Func<string> CurrentInputFeedbackFunc { get { return () => "Not Implemented"; } }
int VolumeHeldRepeatInterval = 200;
@@ -61,7 +90,7 @@ namespace PepperDash.Essentials.Core
MuteFeedback = new BoolFeedback("MuteOn", () => _IsMuted);
WarmupTime = 10000;
CooldownTime = 5000;
CooldownTime = 10000;
}
public override void PowerOn()
@@ -88,15 +117,15 @@ namespace PepperDash.Essentials.Core
if (PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
{
_IsCoolingDown = true;
_PowerIsOn = false;
PowerIsOnFeedback.InvokeFireUpdate();
IsCoolingDownFeedback.InvokeFireUpdate();
// Fake cool-down cycle
CooldownTimer = new CTimer(o =>
{
Debug.Console(2, this, "Cooldown timer ending");
_IsCoolingDown = false;
IsCoolingDownFeedback.InvokeFireUpdate();
IsCoolingDownFeedback.InvokeFireUpdate();
_PowerIsOn = false;
PowerIsOnFeedback.InvokeFireUpdate();
}, CooldownTime);
}
}
@@ -111,7 +140,12 @@ namespace PepperDash.Essentials.Core
public override void ExecuteSwitch(object selector)
{
Debug.Console(2, this, "ExecuteSwitch: {0}", selector);
Debug.Console(2, this, "ExecuteSwitch: {0}", selector);
if (!_PowerIsOn)
{
PowerOn();
}
}

View File

@@ -70,44 +70,71 @@ namespace PepperDash.Essentials.Core.Lighting
}
}
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart,
string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new GenericLightingJoinMap(joinStart);
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart,
string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new GenericLightingJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<GenericLightingJoinMap>(joinMapSerialized);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<GenericLightingJoinMap>(joinMapSerialized);
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
return LinkLightingToApi(lightingDevice, trilist, joinMap);
}
Debug.Console(0, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString());
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, GenericLightingJoinMap joinMap)
{
// GenericLighitng Actions & FeedBack
trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u]));
var sceneIndex = 0;
foreach (var scene in lightingDevice.LightingScenes)
{
trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + sceneIndex), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[sceneIndex]));
scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + sceneIndex)]);
trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + sceneIndex)].StringValue = scene.Name;
trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + sceneIndex)].BoolValue = true;
sceneIndex++;
}
Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
return joinMap;
}
Debug.Console(0, "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;
}
}

View File

@@ -16,11 +16,28 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// Used for monitoring comms that are IBasicCommunication. Will send a poll string and provide an event when
/// statuses change.
/// Default monitoring uses TextReceived event on Client.
/// </summary>
public class GenericCommunicationMonitor : StatusMonitorBase
{
public IBasicCommunication Client { get; private set; }
/// <summary>
/// Will monitor Client.BytesReceived if set to true. Otherwise the default is to monitor Client.TextReceived
/// </summary>
public bool MonitorBytesReceived { get; private set; }
/// <summary>
/// Return true if the Client is ISocketStatus
/// </summary>
public bool IsSocket
{
get
{
return Client is ISocketStatus;
}
}
long PollTime;
CTimer PollTimer;
string PollString;
@@ -46,8 +63,20 @@ namespace PepperDash.Essentials.Core
Client = client;
PollTime = pollTime;
PollString = pollString;
if (IsSocket)
{
(Client as ISocketStatus).ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
}
}
public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime,
long warningTime, long errorTime, string pollString, bool monitorBytesReceived) :
this(parent, client, pollTime, warningTime, errorTime, pollString)
{
SetMonitorBytesReceived(monitorBytesReceived);
}
/// <summary>
/// Poll is a provided action instead of string
/// </summary>
@@ -69,6 +98,19 @@ namespace PepperDash.Essentials.Core
Client = client;
PollTime = pollTime;
PollAction = pollAction;
if (IsSocket)
{
(Client as ISocketStatus).ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
}
}
public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime,
long warningTime, long errorTime, Action pollAction, bool monitorBytesReceived) :
this(parent, client, pollTime, warningTime, errorTime, pollAction)
{
SetMonitorBytesReceived(monitorBytesReceived);
}
@@ -79,23 +121,96 @@ namespace PepperDash.Essentials.Core
CommunicationMonitorConfig props) :
this(parent, client, props.PollInterval, props.TimeToWarning, props.TimeToError, props.PollString)
{
if (IsSocket)
{
(Client as ISocketStatus).ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
}
}
/// <summary>
/// Builds the monitor from a config object and takes a bool to specify whether to monitor BytesReceived
/// Default is to monitor TextReceived
/// </summary>
/// <param name="parent"></param>
/// <param name="client"></param>
/// <param name="props"></param>
/// <param name="monitorBytesReceived"></param>
public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, CommunicationMonitorConfig props, bool monitorBytesReceived) :
this(parent, client, props.PollInterval, props.TimeToWarning, props.TimeToError, props.PollString)
{
SetMonitorBytesReceived(monitorBytesReceived);
}
void SetMonitorBytesReceived(bool monitorBytesReceived)
{
MonitorBytesReceived = monitorBytesReceived;
}
public override void Start()
{
Client.BytesReceived += Client_BytesReceived;
Poll();
PollTimer = new CTimer(o => Poll(), null, PollTime, PollTime);
if (MonitorBytesReceived)
{
Client.BytesReceived += Client_BytesReceived;
}
else
{
Client.TextReceived += Client_TextReceived;
}
if (!IsSocket)
{
BeginPolling();
}
}
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
{
if (!e.Client.IsConnected)
{
// Immediately stop polling and notify that device is offline
Stop();
Status = MonitorStatus.InError;
ResetErrorTimers();
}
else
{
// Start polling and set status to unknow and let poll result update the status to IsOk when a response is received
Status = MonitorStatus.StatusUnknown;
Start();
BeginPolling();
}
}
void BeginPolling()
{
Poll();
PollTimer = new CTimer(o => Poll(), null, PollTime, PollTime);
}
public override void Stop()
{
Client.BytesReceived -= this.Client_BytesReceived;
PollTimer.Stop();
PollTimer = null;
StopErrorTimers();
if(MonitorBytesReceived)
{
Client.BytesReceived -= this.Client_BytesReceived;
}
else
{
Client.TextReceived -= Client_TextReceived;
}
if (PollTimer != null)
{
PollTimer.Stop();
PollTimer = null;
StopErrorTimers();
}
}
void Client_TextReceived(object sender, GenericCommMethodReceiveTextArgs e)
{
DataReceived();
}
/// <summary>
/// Upon any receipt of data, set everything to ok!
/// </summary>
@@ -103,10 +218,14 @@ namespace PepperDash.Essentials.Core
/// <param name="e"></param>
void Client_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e)
{
Status = MonitorStatus.IsOk;
ResetErrorTimers();
//
}
DataReceived();
}
void DataReceived()
{
Status = MonitorStatus.IsOk;
ResetErrorTimers();
}
void Poll()
{
@@ -124,19 +243,6 @@ namespace PepperDash.Essentials.Core
Debug.Console(2, this, "Comm not connected");
}
}
/// <summary>
/// When the client connects, and we're waiting for it, respond and disconect from event
/// </summary>
void OneTimeConnectHandler(object o, EventArgs a)
{
if (Client.IsConnected)
{
//Client.IsConnected -= OneTimeConnectHandler;
Debug.Console(2, this, "Comm connected");
Poll();
}
}
}

View File

@@ -183,6 +183,7 @@
<Compile Include="Crestron IO\Inputs\GenericVersiportInputDevice.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\Relay\CenIoRy104Controller.cs" />
<Compile Include="Crestron IO\Relay\GenericRelayDevice.cs" />
<Compile Include="Crestron IO\Relay\ISwitchedOutput.cs" />

View File

@@ -118,7 +118,7 @@ namespace PepperDash.Essentials.Core.Queues
/// <param name="capacity"></param>
public GenericQueue(string key, int pacing, Thread.eThreadPriority priority, int capacity)
: this(key, priority, capacity, pacing)
{
{
}
/// <summary>
@@ -139,7 +139,8 @@ namespace PepperDash.Essentials.Core.Queues
_queue = new CrestronQueue<IQueueMessage>(cap);
_worker = new Thread(ProcessQueue, null, Thread.eThreadStartOptions.Running)
{
Priority = priority
Priority = priority,
Name = _key
};
SetDelayValues(pacing);

View File

@@ -54,13 +54,20 @@ namespace PepperDash.Essentials.Core
SetupPartitionStateProviders();
SetRooms();
if (isInAutoMode)
{
DetermineRoomCombinationScenario();
}
else
{
SetRoomCombinationScenario(_propertiesConfig.defaultScenarioKey);
}
});
}
void CreateScenarios()
{
RoomCombinationScenarios = new List<IRoomCombinationScenario>();
foreach (var scenarioConfig in _propertiesConfig.Scenarios)
{
var scenario = new RoomCombinationScenario(scenarioConfig);
@@ -160,12 +167,26 @@ namespace PepperDash.Essentials.Core
{
return _currentScenario;
}
set
private set
{
if (value != _currentScenario)
{
// Deactivate the old scenario first
if (_currentScenario != null)
{
_currentScenario.Deactivate();
}
_currentScenario = value;
Debug.Console(1, this, "Current Scenario: {0}", _currentScenario.Name);
// Activate the new scenario
if (_currentScenario != null)
{
_currentScenario.Activate();
Debug.Console(1, this, "Current Scenario: {0}", _currentScenario.Name);
}
var handler = RoomCombinationScenarioChanged;
if (handler != null)
{
@@ -220,9 +241,11 @@ namespace PepperDash.Essentials.Core
// Get the scenario
var scenario = RoomCombinationScenarios.FirstOrDefault((s) => s.Key.Equals(scenarioKey));
// Set the parition states from the scenario manually
if (scenario != null)
{
Debug.Console(0, this, "Manually setting scenario to '{0}'", scenario.Key);
foreach (var partitionState in scenario.PartitionStates)
{
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionState.PartitionKey));
@@ -231,15 +254,25 @@ namespace PepperDash.Essentials.Core
{
if (partitionState.PartitionPresent)
{
Debug.Console(0, this, "Manually setting state to Present for: '{0}'", partition.Key);
partition.SetPartitionStatePresent();
}
else
{
Debug.Console(0, this, "Manually setting state to Not Present for: '{0}'", partition.Key);
partition.SetPartitionStateNotPresent();
}
}
else
{
Debug.Console(1, this, "Unable to find partition with key: '{0}'", partitionState.PartitionKey);
}
}
}
else
{
Debug.Console(1, this, "Unable to find scenario with key: '{0}'", scenarioKey);
}
}
#endregion

View File

@@ -30,7 +30,7 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// The list of rooms keys that can be combined
/// </summary>
[JsonProperty("roomMap")]
[JsonProperty("roomKeys")]
public List<string> RoomKeys {get; set;}
/// <summary>
@@ -87,6 +87,9 @@ namespace PepperDash.Essentials.Core
[JsonProperty("partitionStates")]
public List<PartitionState> PartitionStates { get; set; }
/// <summary>
/// Determines which UI devices get mapped to which room in this scenario. The Key should be the key of the UI device and the Value should be the key of the room to map to
/// </summary>
[JsonProperty("uiMap")]
public Dictionary<string, string> UiMap { get; set; }

View File

@@ -78,6 +78,11 @@ namespace PepperDash.Essentials.Core
/// </summary>
void Activate();
/// <summary>
/// Deactivates this room combination scenario
/// </summary>
void Deactivate();
/// <summary>
/// The state of the partitions that would activate this scenario
/// </summary>

View File

@@ -4,6 +4,8 @@ using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core
@@ -27,9 +29,9 @@ namespace PepperDash.Essentials.Core
public BoolFeedback IsActiveFeedback { get; private set; }
List<DeviceActionWrapper> activationActions;
private List<DeviceActionWrapper> activationActions;
List<DeviceActionWrapper> deactivationActions;
private List<DeviceActionWrapper> deactivationActions;
public RoomCombinationScenario(RoomCombinationScenarioConfig config)
{
@@ -52,6 +54,8 @@ namespace PepperDash.Essentials.Core
public void Activate()
{
Debug.Console(1, "Activating Scenario: '{0}' with {1} action(s) defined", Name, activationActions.Count);
if (activationActions != null)
{
foreach (var action in activationActions)
@@ -66,6 +70,8 @@ namespace PepperDash.Essentials.Core
public void Deactivate()
{
Debug.Console(1, "Deactivating Scenario: '{0}' with {1} action(s) defined", Name, deactivationActions.Count);
if (deactivationActions != null)
{
foreach (var action in deactivationActions)

View File

@@ -11,12 +11,34 @@ using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
public class RouteRequest
{
public IRoutingSink Destination {get; set;}
public IRoutingOutputs Source {get; set;}
public eRoutingSignalType SignalType {get; set;}
public void HandleCooldown(object sender, FeedbackEventArgs args)
{
var coolingDevice = sender as IWarmingCooling;
if(args.BoolValue == false)
{
Destination.ReleaseAndMakeRoute(Source, SignalType);
if(sender == null) return;
coolingDevice.IsCoolingDownFeedback.OutputChange -= HandleCooldown;
}
}
}
/// <summary>
/// Extensions added to any IRoutingInputs classes to provide discovery-based routing
/// on those destinations.
/// </summary>
public static class IRoutingInputsExtensions
{
private static Dictionary<string, RouteRequest> RouteRequests = new Dictionary<string, RouteRequest>();
/// <summary>
/// Gets any existing RouteDescriptor for a destination, clears it using ReleaseRoute
/// and then attempts a new Route and if sucessful, stores that RouteDescriptor
@@ -24,16 +46,64 @@ namespace PepperDash.Essentials.Core
/// </summary>
public static void ReleaseAndMakeRoute(this IRoutingSink destination, IRoutingOutputs source, eRoutingSignalType signalType)
{
destination.ReleaseRoute();
var routeRequest = new RouteRequest {
Destination = destination,
Source = source,
SignalType = signalType
};
if (source == null) return;
var newRoute = destination.GetRouteToSource(source, signalType);
if (newRoute == null) return;
RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(newRoute);
Debug.Console(2, destination, "Executing full route");
newRoute.ExecuteRoutes();
var coolingDevice = destination as IWarmingCooling;
RouteRequest existingRouteRequest;
//We already have a route request for this device, and it's a cooling device and is cooling
if (RouteRequests.TryGetValue(destination.Key, out existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true)
{
coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown;
coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown;
RouteRequests[destination.Key] = routeRequest;
Debug.Console(2, "******************************************************** Device: {0} is cooling down and already has a routing request stored. Storing new route request to route to source key: {1}", destination.Key, routeRequest.Source.Key);
return;
}
//New Request
if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true)
{
coolingDevice.IsCoolingDownFeedback.OutputChange -= routeRequest.HandleCooldown;
coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown;
RouteRequests.Add(destination.Key, routeRequest);
Debug.Console(2, "******************************************************** Device: {0} is cooling down. Storing route request to route to source key: {1}", destination.Key, routeRequest.Source.Key);
return;
}
if (RouteRequests.ContainsKey(destination.Key) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == false)
{
RouteRequests.Remove(destination.Key);
Debug.Console(2, "******************************************************** Device: {0} is NOT cooling down. Removing stored route request and routing to source key: {1}", destination.Key, routeRequest.Source.Key);
}
destination.ReleaseRoute();
RunRouteRequest(routeRequest);
}
public static void RunRouteRequest(RouteRequest request)
{
if (request.Source == null) return;
var newRoute = request.Destination.GetRouteToSource(request.Source, request.SignalType);
if (newRoute == null) return;
RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(newRoute);
Debug.Console(2, request.Destination, "Executing full route");
newRoute.ExecuteRoutes();
}
/// <summary>
/// Will release the existing route on the destination, if it is found in
/// RouteDescriptorCollection.DefaultCollection
@@ -41,6 +111,17 @@ namespace PepperDash.Essentials.Core
/// <param name="destination"></param>
public static void ReleaseRoute(this IRoutingSink destination)
{
RouteRequest existingRequest;
if (RouteRequests.TryGetValue(destination.Key, out existingRequest) && destination is IWarmingCooling)
{
var coolingDevice = destination as IWarmingCooling;
coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRequest.HandleCooldown;
}
RouteRequests.Remove(destination.Key);
var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination);
if (current != null)
{

View File

@@ -25,7 +25,7 @@ namespace PepperDash.Essentials.Core
Type = type;
ConnectionType = connType;
Selector = selector;
IsInternal = IsInternal;
IsInternal = isInternal;
}
}

View File

@@ -206,6 +206,27 @@ namespace PepperDash.Essentials.Core
return ClearSigAction(tl.StringOutput[sigNum]) as StringOutputSig;
}
/// <summary>
/// Clears all actions on all sigs
/// </summary>
public static void ClearAllSigActions(this BasicTriList t1)
{
foreach (var sig in t1.BooleanOutput)
{
ClearSigAction(sig);
}
foreach (var sig in t1.UShortOutput)
{
ClearSigAction(sig);
}
foreach (var sig in t1.StringOutput)
{
ClearSigAction(sig);
}
}
/// <summary>
/// Helper method to set the value of a bool Sig on TriList
/// </summary>

View File

@@ -29,6 +29,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
public abstract class CameraBase : ReconfigurableDevice, IRoutingOutputs
{
[JsonProperty("controlMode", NullValueHandling = NullValueHandling.Ignore)]
public eCameraControlMode ControlMode { get; protected set; }
#region IRoutingOutputs Members
@@ -37,6 +38,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
#endregion
[JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)]
public bool CanPan
{
get
@@ -44,7 +46,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
return (Capabilities & eCameraCapabilities.Pan) == eCameraCapabilities.Pan;
}
}
[JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)]
public bool CanTilt
{
get
@@ -52,7 +54,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
return (Capabilities & eCameraCapabilities.Tilt) == eCameraCapabilities.Tilt;
}
}
[JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)]
public bool CanZoom
{
get
@@ -60,7 +62,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
return (Capabilities & eCameraCapabilities.Zoom) == eCameraCapabilities.Zoom;
}
}
[JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)]
public bool CanFocus
{
get

View File

@@ -57,6 +57,11 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
void CameraMuteToggle();
}
public interface IHasCameraMuteWithUnmuteReqeust : IHasCameraMute
{
event EventHandler VideoUnmuteRequested;
}
public class CameraSelectedEventArgs : EventArgs
{
public CameraBase SelectedCamera { get; private set; }

View File

@@ -12,34 +12,40 @@ namespace PepperDash.Essentials.Devices.Common.Codec
{
public class CodecActiveCallItem
{
[JsonProperty("name")]
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }
[JsonProperty("number")]
[JsonProperty("number", NullValueHandling = NullValueHandling.Ignore)]
public string Number { get; set; }
[JsonProperty("type")]
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))]
public eCodecCallType Type { get; set; }
[JsonProperty("status")]
[JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))]
public eCodecCallStatus Status { get; set; }
[JsonProperty("direction")]
[JsonProperty("direction", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))]
public eCodecCallDirection Direction { get; set; }
[JsonProperty("id")]
[JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
public string Id { get; set; }
[JsonProperty("isOnHold", NullValueHandling = NullValueHandling.Ignore)]
public bool IsOnHold { get; set; }
[JsonProperty("duration", NullValueHandling = NullValueHandling.Ignore)]
public TimeSpan Duration { get; set; }
//public object CallMetaData { get; set; }
/// <summary>
/// Returns true when this call is any status other than
/// Unknown, Disconnected, Disconnecting
/// </summary>
[JsonProperty("isActiveCall")]
[JsonProperty("isActiveCall", NullValueHandling = NullValueHandling.Ignore)]
public bool IsActiveCall
{
get

View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Common.Codec
{
public interface IHasCallHold
{
/// <summary>
/// Put the specified call on hold
/// </summary>
/// <param name="activeCall"></param>
void HoldCall(CodecActiveCallItem activeCall);
/// <summary>
/// Resume the specified call
/// </summary>
/// <param name="activeCall"></param>
void ResumeCall(CodecActiveCallItem activeCall);
}
}

View File

@@ -23,9 +23,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec
public enum eCodecOccurrenceType
{
Unknown = 0,
Placed,
Received,
NoAnswer
Placed = 1,
Received = 2,
NoAnswer = 3,
}
/// <summary>

View File

@@ -65,8 +65,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Represents the contents of the directory
/// We don't want to serialize this for messages to MobileControl. MC can combine Contacts and Folders to get the same data
/// </summary>
[JsonProperty("directoryResults")]
[JsonIgnore]
public List<DirectoryItem> CurrentDirectoryResults { get; private set; }
[JsonProperty("contacts")]

View File

@@ -99,7 +99,7 @@ namespace PepperDash.Essentials.Devices.Displays
WarmupTime = 10000;
CooldownTime = 8000;
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 2000, 120000, 300000, StatusGet);
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 2000, 120000, 300000, StatusGet, true);
DeviceManager.AddDevice(CommunicationMonitor);
VolumeIncrementer = new ActionIncrementer(655, 0, 65535, 800, 80,

View File

@@ -108,6 +108,7 @@
<Compile Include="Codec\eCodecCallStatus.cs" />
<Compile Include="Codec\eMeetingPrivacy.cs" />
<Compile Include="Codec\iCodecAudio.cs" />
<Compile Include="Codec\IHasCallHold.cs" />
<Compile Include="Codec\IHasDoNotDisturb.cs" />
<Compile Include="Codec\IHasExternalSourceSwitching.cs" />
<Compile Include="ImageProcessors\TVOneCorio.cs" />
@@ -131,6 +132,7 @@
<Compile Include="VideoCodec\Interfaces\IHasSelfviewSize.cs" />
<Compile Include="VideoCodec\Interfaces\IHasStandbyMode.cs" />
<Compile Include="VideoCodec\Interfaces\IHasStartMeeting.cs" />
<Compile Include="VideoCodec\Interfaces\IJoinCalls.cs" />
<Compile Include="VideoCodec\Interfaces\iVideoCodecInfo.cs" />
<Compile Include="Codec\iHasCallFavorites.cs" />
<Compile Include="Codec\iHasCallHistory.cs" />
@@ -182,6 +184,7 @@
<Compile Include="VideoCodec\MockVC\MockVC.cs" />
<Compile Include="VideoCodec\CiscoCodec\xStatus.cs" />
<Compile Include="VideoCodec\VideoCodecBase.cs" />
<Compile Include="VideoCodec\ZoomRoom\IZoomWirelessShareInstructions.cs" />
<Compile Include="VideoCodec\ZoomRoom\ResponseObjects.cs" />
<Compile Include="VideoCodec\ZoomRoom\ZoomRoom.cs" />
<Compile Include="VideoCodec\ZoomRoom\ZoomRoomCamera.cs" />

View File

@@ -41,12 +41,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public void PanLeft()
{
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: Left CallId: {0}", CallId));
ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: Left CallId: {0}", CallId));
}
public void PanRight()
{
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: Right CallId: {0}", CallId));
ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: Right CallId: {0}", CallId));
}
public void PanStop()
@@ -60,12 +60,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public void TiltDown()
{
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: Down CallId: {0}", CallId));
ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: Down CallId: {0}", CallId));
}
public void TiltUp()
{
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: Up CallId: {0}", CallId));
ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: Up CallId: {0}", CallId));
}
public void TiltStop()
@@ -79,12 +79,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public void ZoomIn()
{
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: ZoomIn CallId: {0}", CallId));
ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: ZoomIn CallId: {0}", CallId));
}
public void ZoomOut()
{
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: ZoomOut CallId: {0}", CallId));
ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: ZoomOut CallId: {0}", CallId));
}
public void ZoomStop()
@@ -97,7 +97,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
void Stop()
{
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Stop CallId: {0}", CallId));
ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Stop CallId: {0}", CallId));
}
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
@@ -116,7 +116,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
/// <summary>
/// The ID of the camera on the codec
/// </summary>
protected uint CameraId { get; private set; }
public uint CameraId { get; private set; }
/// <summary>
/// Valid range 1-15
@@ -202,7 +202,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
if (!isMoving)
{
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Left PanSpeed: {1}", CameraId, PanSpeed));
ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Left PanSpeed: {1}", CameraId, PanSpeed));
isPanning = true;
}
}
@@ -211,14 +211,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
if (!isMoving)
{
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Right PanSpeed: {1}", CameraId, PanSpeed));
ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Right PanSpeed: {1}", CameraId, PanSpeed));
isPanning = true;
}
}
public void PanStop()
{
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Stop", CameraId));
ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Stop", CameraId));
isPanning = false;
}
@@ -232,7 +232,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
if (!isMoving)
{
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Down TiltSpeed: {1}", CameraId, TiltSpeed));
ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Down TiltSpeed: {1}", CameraId, TiltSpeed));
isTilting = true;
}
}
@@ -241,14 +241,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
if (!isMoving)
{
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Up TiltSpeed: {1}", CameraId, TiltSpeed));
ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Up TiltSpeed: {1}", CameraId, TiltSpeed));
isTilting = true;
}
}
public void TiltStop()
{
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Stop", CameraId));
ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Stop", CameraId));
isTilting = false;
}
@@ -260,7 +260,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
if (!isMoving)
{
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: In ZoomSpeed: {1}", CameraId, ZoomSpeed));
ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: In ZoomSpeed: {1}", CameraId, ZoomSpeed));
isZooming = true;
}
}
@@ -269,14 +269,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
if (!isMoving)
{
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: Out ZoomSpeed: {1}", CameraId, ZoomSpeed));
ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: Out ZoomSpeed: {1}", CameraId, ZoomSpeed));
isZooming = true;
}
}
public void ZoomStop()
{
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: Stop", CameraId));
ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: Stop", CameraId));
isZooming = false;
}
@@ -288,7 +288,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
if (!isMoving)
{
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Near", CameraId));
ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Near", CameraId));
isFocusing = true;
}
}
@@ -297,20 +297,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
if (!isMoving)
{
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Far", CameraId));
ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Far", CameraId));
isFocusing = true;
}
}
public void FocusStop()
{
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Stop", CameraId));
ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Stop", CameraId));
isFocusing = false;
}
public void TriggerAutoFocus()
{
ParentCodec.SendText(string.Format("xCommand Camera TriggerAutofocus CameraId: {0}", CameraId));
ParentCodec.EnqueueCommand(string.Format("xCommand Camera TriggerAutofocus CameraId: {0}", CameraId));
}
#endregion

View File

@@ -9,11 +9,39 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
#region Digital
[JoinName("PresentationLocalOnly")]
public JoinDataComplete PresentationLocalOnly = new JoinDataComplete(
new JoinData
{
JoinNumber = 205,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Presentation Local Only Feedback",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("PresentationLocalRemote")]
public JoinDataComplete PresentationLocalRemote = new JoinDataComplete(
new JoinData
{
JoinNumber = 206,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Presentation Local and Remote Feedback",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ActivateDoNotDisturbMode")]
public JoinDataComplete ActivateDoNotDisturbMode = new JoinDataComplete(
new JoinData
{
JoinNumber = 221,
JoinNumber = 241,
JoinSpan = 1
},
new JoinMetadata
@@ -27,7 +55,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public JoinDataComplete DeactivateDoNotDisturbMode = new JoinDataComplete(
new JoinData
{
JoinNumber = 222,
JoinNumber = 242,
JoinSpan = 1
},
new JoinMetadata
@@ -41,7 +69,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public JoinDataComplete ToggleDoNotDisturbMode = new JoinDataComplete(
new JoinData
{
JoinNumber = 223,
JoinNumber = 243,
JoinSpan = 1
},
new JoinMetadata
@@ -55,7 +83,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public JoinDataComplete ActivateStandby = new JoinDataComplete(
new JoinData
{
JoinNumber = 226,
JoinNumber = 246,
JoinSpan = 1
},
new JoinMetadata
@@ -69,7 +97,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public JoinDataComplete DeactivateStandby = new JoinDataComplete(
new JoinData
{
JoinNumber = 227,
JoinNumber = 247,
JoinSpan = 1
},
new JoinMetadata
@@ -83,7 +111,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public JoinDataComplete ActivateHalfWakeMode = new JoinDataComplete(
new JoinData
{
JoinNumber = 228,
JoinNumber = 248,
JoinSpan = 1
},
new JoinMetadata
@@ -97,7 +125,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public JoinDataComplete EnteringStandbyMode = new JoinDataComplete(
new JoinData
{
JoinNumber = 229,
JoinNumber = 249,
JoinSpan = 1
},
new JoinMetadata
@@ -112,12 +140,55 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
#region Analog
[JoinName("RingtoneVolume")]
public JoinDataComplete RingtoneVolume = new JoinDataComplete(
new JoinData
{
JoinNumber = 21,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Ringtone volume set/FB. Valid values are 0 - 100 in increments of 5 (5, 10, 15, 20, etc.)",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("PresentationSource")]
public JoinDataComplete PresentationSource = new JoinDataComplete(
new JoinData
{
JoinNumber = 201,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Presentation set/FB. Valid values are 0 - 6 depending on the codec model.",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Analog
});
#endregion
#region Serials
[JoinName("CommandToDevice")]
public JoinDataComplete CommandToDevice = new JoinDataComplete(
new JoinData
{
JoinNumber = 5,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Sends a serial command to the device. Do not include the delimiter, it will be added automatically.",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
#endregion

View File

@@ -50,8 +50,16 @@ namespace PepperDash.Essentials.Devices.Common.Codec
public uint PhonebookResultsLimit { get; set; }
[JsonProperty("UiBranding")]
public BrandingLogoProperties UiBranding { get; set; }
public BrandingLogoProperties UiBranding { get; set; }
[JsonProperty("cameraInfo")]
public List<CameraInfo> CameraInfo { get; set; }
public CiscoSparkCodecPropertiesConfig()
{
CameraInfo = new List<CameraInfo>();
}
}
public class SharingProperties
@@ -68,4 +76,14 @@ namespace PepperDash.Essentials.Devices.Common.Codec
[JsonProperty("brandingUrl")]
public string BrandingUrl { get; set; }
}
/// <summary>
/// Describes configuration information for the near end cameras
/// </summary>
public class CameraInfo
{
public int CameraNumber { get; set; }
public string Name { get; set; }
public int SourceId { get; set; }
}
}

View File

@@ -26,6 +26,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
void CodecRoomPresetSelect(int preset);
void CodecRoomPresetStore(int preset, string description);
void SelectFarEndPreset(int preset);
}
public static class RoomPresets

View File

@@ -112,16 +112,46 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public string Value { get; set; }
}
public class RingVolume
public class RingVolume : ValueProperty
{
public string valueSpaceRef { get; set; }
public string Value { get; set; }
string _Value;
/// <summary>
/// Sets Value and triggers the action when set
/// </summary>
public string Value
{
get
{
return _Value;
}
set
{
_Value = value;
OnValueChanged();
}
}
public int Volume
{
get
{
return Int32.Parse(_Value);
}
}
}
public class SoundsAndAlerts
{
public RingTone RingTone { get; set; }
public RingVolume RingVolume { get; set; }
public SoundsAndAlerts()
{
RingVolume = new RingVolume();
}
}
public class Audio
@@ -131,6 +161,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Microphones Microphones { get; set; }
public Output Output { get; set; }
public SoundsAndAlerts SoundsAndAlerts { get; set; }
public Audio()
{
SoundsAndAlerts = new SoundsAndAlerts();
}
}
public class DefaultMode
@@ -340,6 +376,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Delay Delay { get; set; }
public Mode9 Mode { get; set; }
public Mute2 Mute { get; set; }
public AutoAnswer()
{
Mode = new Mode9();
Delay = new Delay();
Mute = new Mute2();
}
}
public class Protocol
@@ -440,6 +483,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public MaxTotalTransmitCallRate MaxTotalTransmitCallRate { get; set; }
public MaxTransmitCallRate MaxTransmitCallRate { get; set; }
public MultiStream MultiStream { get; set; }
public Conference()
{
AutoAnswer = new AutoAnswer();
}
}
public class LoginName
@@ -690,6 +738,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Assignment Assignment { get; set; }
public Gateway Gateway { get; set; }
public SubnetMask SubnetMask { get; set; }
public IPv4()
{
Address = new Address4();
}
}
public class Address5
@@ -841,6 +894,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public RemoteAccess RemoteAccess { get; set; }
public Speed Speed { get; set; }
public VLAN VLAN { get; set; }
public Network()
{
IPv4 = new IPv4();
}
}
public class Mode19
@@ -1797,11 +1855,23 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public UserInterface UserInterface { get; set; }
public UserManagement UserManagement { get; set; }
public Video2 Video { get; set; }
public Configuration()
{
Audio = new Audio();
Conference = new Conference();
Network = new List<Network>();
}
}
public class RootObject
{
public Configuration Configuration { get; set; }
public RootObject()
{
Configuration = new Configuration();
}
}
}
}

View File

@@ -12,28 +12,28 @@ using PepperDash.Essentials.Devices.Common.VideoCodec.CiscoCodec;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
// Helper Classes for Proerties
public abstract class ValueProperty
{
/// <summary>
/// Triggered when Value is set
/// </summary>
public Action ValueChangedAction { get; set; }
protected void OnValueChanged()
{
var a = ValueChangedAction;
if (a != null)
a();
}
}
/// <summary>
/// This class exists to capture serialized data sent back by a Cisco codec in JSON output mode
/// </summary>
public class CiscoCodecStatus
{
// Helper Classes for Proerties
public abstract class ValueProperty
{
/// <summary>
/// Triggered when Value is set
/// </summary>
public Action ValueChangedAction { get; set; }
protected void OnValueChanged()
{
var a = ValueChangedAction;
if (a != null)
a();
}
}
public class ConnectionStatus
{
@@ -262,11 +262,30 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public string Value { get; set; }
}
public class DectectedConnector
{
public string Value { get; set; }
public int ConnectorId
{
get
{
if(!string.IsNullOrEmpty(Value))
{
return Convert.ToUInt16(Value);
}
else
return -1;
}
}
}
public class Camera
{
public string id { get; set; }
public Capabilities Capabilities { get; set; }
public Connected Connected { get; set; }
public DectectedConnector DetectedConnector { get; set; }
public Flip Flip { get; set; }
public HardwareID HardwareID { get; set; }
public MacAddress MacAddress { get; set; }
@@ -275,6 +294,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Position Position { get; set; }
public SerialNumber SerialNumber { get; set; }
public SoftwareID SoftwareID { get; set; }
public Camera()
{
Manufacturer = new Manufacturer();
Model = new Model();
DetectedConnector = new DectectedConnector();
}
}
public class Availability : ValueProperty
@@ -298,11 +324,34 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
}
}
public class CallStatus : ValueProperty
{
string _Value;
public bool BoolValue { get; private set; }
public string Value
{
get
{
return _Value;
}
set
{
// If the incoming value is "Active" it sets the BoolValue true, otherwise sets it false
_Value = value;
BoolValue = value == "Connected";
OnValueChanged();
}
}
}
public class Status2 : ValueProperty
{
string _Value;
public bool BoolValue { get; private set; }
public string Value
{
get
@@ -558,9 +607,47 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
}
}
public class SendingMode
public class SendingMode : ValueProperty
{
public string Value { get; set; }
string _Value;
/// <summary>
/// Sets Value and triggers the action when set
/// </summary>
public string Value
{
get
{
return _Value;
}
set
{
_Value = value;
OnValueChanged();
}
}
public bool LocalOnly
{
get
{
if(string.IsNullOrEmpty(_Value))
return false;
return _Value.ToLower() == "localonly";
}
}
public bool LocalRemote
{
get
{
if(string.IsNullOrEmpty(_Value))
return false;
return _Value.ToLower() == "localremote";
}
}
}
public class LocalInstance
@@ -573,6 +660,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public LocalInstance()
{
Source = new Source2();
SendingMode = new SendingMode();
}
}
@@ -881,6 +969,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Address4 Address { get; set; }
public Gateway Gateway { get; set; }
public SubnetMask SubnetMask { get; set; }
public IPv4()
{
Address = new Address4();
}
}
public class Address5
@@ -923,6 +1016,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public IPv4 IPv4 { get; set; }
public IPv6 IPv6 { get; set; }
public VLAN VLAN { get; set; }
public Network()
{
IPv4 = new IPv4();
}
}
public class CurrentAddress
@@ -1949,9 +2047,30 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public string Value { get; set; }
}
public class Duration
public class Duration : ValueProperty
{
public string Value { get; set; }
private string _Value;
public string Value
{
get
{
return _Value;
}
set
{
_Value = value;
OnValueChanged();
}
}
public TimeSpan DurationValue
{
get
{
return new TimeSpan(0, 0, Int32.Parse(_Value));
}
}
}
public class FacilityServiceId
@@ -1964,9 +2083,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public string Value { get; set; }
}
public class PlacedOnHold
public class PlacedOnHold : ValueProperty
{
public string Value { get; set; }
public bool BoolValue { get; private set; }
public string Value
{
set
{
// If the incoming value is "True" it sets the BoolValue true, otherwise sets it false
BoolValue = value == "True";
OnValueChanged();
}
}
}
public class Protocol
@@ -2007,13 +2136,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Protocol Protocol { get; set; }
public ReceiveCallRate ReceiveCallRate { get; set; }
public RemoteNumber RemoteNumber { get; set; }
public Status2 Status { get; set; }
public CallStatus Status { get; set; }
public TransmitCallRate TransmitCallRate { get; set; }
public Call()
{
CallType = new CallType();
Status = new Status2();
Status = new CallStatus();
Duration = new Duration();
}
}
@@ -2114,6 +2244,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
SystemUnit = new SystemUnit();
Video = new Video();
Conference = new Conference2();
Network = new List<Network>();
}
}

View File

@@ -42,9 +42,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
public Boolean WaitingForHost { get; private set; }
[JsonProperty("isLocked", NullValueHandling = NullValueHandling.Ignore)]
public Boolean IsLocked { get; private set; }
[JsonProperty("isRecording", NullValueHandling = NullValueHandling.Ignore)]
public Boolean IsRecording { get; private set; }
public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked)
public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked, bool isRecording)
{
Id = id;
Name = name;
@@ -55,6 +57,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
IsSharingMeeting = isSharingMeeting;
WaitingForHost = waitingForHost;
IsLocked = isLocked;
IsRecording = isRecording;
}
}

View File

@@ -15,4 +15,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
void StopRecording();
void ToggleRecording();
}
public interface IHasMeetingRecordingWithPrompt : IHasMeetingRecording
{
BoolFeedback RecordConsentPromptIsVisible { get; }
/// <summary>
/// Used to agree or disagree to the meeting being recorded when prompted
/// </summary>
/// <param name="agree"></param>
void RecordingPromptAcknowledgement(bool agree);
}
}

View File

@@ -24,6 +24,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
/// </summary>
/// <param name="participant"></param>
void SetParticipantAsHost(int userId);
/// <summary>
/// Admits a participant from the waiting room
/// </summary>
/// <param name="userId"></param>
void AdmitParticipantFromWaitingRoom(int userId);
}
/// <summary>

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Devices.Common.Codec;
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
public interface IJoinCalls
{
void JoinCall(CodecActiveCallItem activeCall);
void JoinAllCalls();
}
}

View File

@@ -431,8 +431,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
m.MinutesBeforeMeeting = 5;
m.Id = i.ToString();
m.Organizer = "Employee " + 1;
m.StartTime = DateTime.Now.AddMinutes(6).AddHours(i);
m.EndTime = DateTime.Now.AddHours(i).AddMinutes(16);
m.StartTime = DateTime.Now.AddMinutes(5).AddHours(i);
m.EndTime = DateTime.Now.AddHours(i).AddMinutes(50);
m.Title = "Meeting " + i;
m.Calls.Add(new Call() { Number = i + "meeting@fake.com"});
_CodecSchedule.Meetings.Add(m);
@@ -602,6 +602,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
CameraAutoModeIsOnFeedback = new BoolFeedback(() => _CameraAutoModeIsOn);
SupportsCameraAutoMode = true;
CameraAutoModeIsOnFeedback.FireUpdate();
DeviceManager.AddDevice(internalCamera);
@@ -609,7 +611,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
NearEndPresets = new List<CodecRoomPreset>(15); // Fix the capacity to emulate Cisco
NearEndPresets = PropertiesConfig.Presets;
if (PropertiesConfig.Presets != null && PropertiesConfig.Presets.Count > 0)
{
NearEndPresets = PropertiesConfig.Presets;
}
else
{
for (int i = 1; i <= NearEndPresets.Capacity; i++)
{
var label = string.Format("Near End Preset {0}", i);
NearEndPresets.Add(new CodecRoomPreset(i, label, true, false));
}
}
FarEndRoomPresets = new List<CodecRoomPreset>(15); // Fix the capacity to emulate Cisco
@@ -751,6 +764,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
SetConfig(Config);
}
public void SelectFarEndPreset(int i)
{
Debug.Console(1, this, "Selecting Far End Preset: {0}", i);
}
#endregion
protected override void CustomSetConfig(DeviceConfig config)

View File

@@ -18,5 +18,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
[JsonProperty("presets")]
public List<CodecRoomPreset> Presets { get; set; }
public MockVcPropertiesConfig()
{
Favorites = new List<CodecActiveCallItem>();
Presets = new List<CodecRoomPreset>();
}
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Reflection;
using Crestron.SimplSharp.Ssh;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharp;
@@ -152,6 +153,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
public abstract void AcceptCall(CodecActiveCallItem call);
public abstract void RejectCall(CodecActiveCallItem call);
public abstract void SendDtmf(string s);
public virtual void SendDtmf(string s, CodecActiveCallItem call) { }
#endregion
@@ -212,6 +214,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
handler(this, new CodecCallStatusItemChangeEventArgs(item));
}
PrivacyModeIsOnFeedback.FireUpdate();
if (AutoShareContentWhileInCall)
{
StartSharing();
@@ -259,10 +263,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
/// </summary>
public virtual void ListCalls()
{
Debug.Console(1, this, "Active Calls:");
var sb = new StringBuilder();
foreach (var c in ActiveCalls)
{
sb.AppendFormat("{0} {1} -- {2} {3}\n", c.Id, c.Number, c.Name, c.Status);
sb.AppendFormat("id: {0} number: {1} -- name: {2} status: {3} onHold: {4}\r\n", c.Id, c.Number, c.Name, c.Status, c.IsOnHold);
}
Debug.Console(1, this, "\n{0}\n", sb.ToString());
}
@@ -328,15 +334,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
LinkVideoCodecVolumeToApi(trilist, joinMap);
LinkVideoCodecInfoToApi(trilist, joinMap);
// Register for this event to link any functions that require the codec to be ready first
codec.IsReadyChange += (o, a) =>
{
if (codec is IHasCodecCameras)
{
LinkVideoCodecCameraToApi(codec as IHasCodecCameras, trilist, joinMap);
}
};
if (codec is ICommunicationMonitor)
{
LinkVideoCodecCommMonitorToApi(codec as ICommunicationMonitor, trilist, joinMap);
}
if (codec is IHasCodecCameras)
{
LinkVideoCodecCameraToApi(codec as IHasCodecCameras, trilist, joinMap);
}
if (codec is IHasCodecSelfView)
{
@@ -390,6 +403,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
LinkVideoCodecPhoneToApi(codec as IHasPhoneDialing, trilist, joinMap);
}
if (codec is IHasCallHistory)
{
LinkVideoCodecCallHistoryToApi(codec as IHasCallHistory, trilist, joinMap);
}
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
@@ -411,7 +429,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
if (codec is IHasCameraAutoMode)
{
trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, true);
trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, SupportsCameraAutoMode);
(codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate();
}
@@ -436,6 +454,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
(codec as IHasPhoneDialing).PhoneOffHookFeedback.FireUpdate();
}
if (codec is IHasCallHistory)
{
UpdateCallHistory((codec as IHasCallHistory), trilist, joinMap);
}
SharingContentIsOnFeedback.FireUpdate();
trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall);
@@ -444,6 +467,31 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
};
}
private void LinkVideoCodecInfoToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
trilist.SetBool(joinMap.MultiSiteOptionIsEnabled.JoinNumber, this.CodecInfo.MultiSiteOptionIsEnabled);
trilist.SetBool(joinMap.AutoAnswerEnabled.JoinNumber, this.CodecInfo.AutoAnswerEnabled);
trilist.SetString(joinMap.DeviceIpAddresss.JoinNumber, this.CodecInfo.IpAddress);
trilist.SetString(joinMap.SipPhoneNumber.JoinNumber, this.CodecInfo.SipPhoneNumber);
trilist.SetString(joinMap.E164Alias.JoinNumber, this.CodecInfo.E164Alias);
trilist.SetString(joinMap.H323Id.JoinNumber, this.CodecInfo.H323Id);
trilist.SetString(joinMap.SipUri.JoinNumber, this.CodecInfo.SipUri);
trilist.OnlineStatusChange += (o, a) =>
{
if (a.DeviceOnLine)
{
trilist.SetBool(joinMap.MultiSiteOptionIsEnabled.JoinNumber, this.CodecInfo.MultiSiteOptionIsEnabled);
trilist.SetBool(joinMap.AutoAnswerEnabled.JoinNumber, this.CodecInfo.AutoAnswerEnabled);
trilist.SetString(joinMap.DeviceIpAddresss.JoinNumber, this.CodecInfo.IpAddress);
trilist.SetString(joinMap.SipPhoneNumber.JoinNumber, this.CodecInfo.SipPhoneNumber);
trilist.SetString(joinMap.E164Alias.JoinNumber, this.CodecInfo.E164Alias);
trilist.SetString(joinMap.H323Id.JoinNumber, this.CodecInfo.H323Id);
trilist.SetString(joinMap.SipUri.JoinNumber, this.CodecInfo.SipUri);
}
};
}
private void LinkVideoCodecPhoneToApi(IHasPhoneDialing codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
codec.PhoneOffHookFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PhoneHookState.JoinNumber]);
@@ -645,37 +693,37 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
if (meetingIndex >= maxParticipants * offset) break;
Debug.Console(2, this,
@"Updating Participant on xsig:
Name: {0} (s{9})
AudioMute: {1} (d{10})
VideoMute: {2} (d{11})
CanMuteVideo: {3} (d{12})
CanUMuteVideo: {4} (d{13})
IsHost: {5} (d{14})
HandIsRaised: {6} (d{15})
IsPinned: {7} (d{16})
ScreenIndexIsPinnedTo: {8} (a{17})
",
participant.Name,
participant.AudioMuteFb,
participant.VideoMuteFb,
participant.CanMuteVideo,
participant.CanUnmuteVideo,
participant.IsHost,
participant.HandIsRaisedFb,
participant.IsPinnedFb,
participant.ScreenIndexIsPinnedToFb,
stringIndex + 1,
digitalIndex + 1,
digitalIndex + 2,
digitalIndex + 3,
digitalIndex + 4,
digitalIndex + 5,
digitalIndex + 6,
digitalIndex + 7,
analogIndex + 1
);
// Debug.Console(2, this,
//@"Updating Participant on xsig:
//Name: {0} (s{9})
//AudioMute: {1} (d{10})
//VideoMute: {2} (d{11})
//CanMuteVideo: {3} (d{12})
//CanUMuteVideo: {4} (d{13})
//IsHost: {5} (d{14})
//HandIsRaised: {6} (d{15})
//IsPinned: {7} (d{16})
//ScreenIndexIsPinnedTo: {8} (a{17})
//",
// participant.Name,
// participant.AudioMuteFb,
// participant.VideoMuteFb,
// participant.CanMuteVideo,
// participant.CanUnmuteVideo,
// participant.IsHost,
// participant.HandIsRaisedFb,
// participant.IsPinnedFb,
// participant.ScreenIndexIsPinnedToFb,
// stringIndex + 1,
// digitalIndex + 1,
// digitalIndex + 2,
// digitalIndex + 3,
// digitalIndex + 4,
// digitalIndex + 5,
// digitalIndex + 6,
// digitalIndex + 7,
// analogIndex + 1
// );
//digitals
@@ -945,18 +993,33 @@ ScreenIndexIsPinnedTo: {8} (a{17})
private void LinkVideoCodecDirectoryToApi(IHasDirectory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
codec.CurrentDirectoryResultIsNotDirectoryRoot.LinkComplementInputSig(
trilist.BooleanInput[joinMap.DirectoryIsRoot.JoinNumber]);
trilist.SetSigFalseAction(joinMap.DirectoryRoot.JoinNumber, codec.SetCurrentDirectoryToRoot);
trilist.BooleanInput[joinMap.DirectoryIsRoot.JoinNumber]);
trilist.SetStringSigAction(joinMap.DirectorySearchString.JoinNumber, codec.SearchDirectory);
trilist.SetUShortSigAction(joinMap.DirectorySelectRow.JoinNumber, (i) => SelectDirectoryEntry(codec, i));
trilist.SetUShortSigAction(joinMap.DirectorySelectRow.JoinNumber, (i) => SelectDirectoryEntry(codec, i, trilist, joinMap));
// Report feedback for number of contact methods for selected contact
trilist.SetSigFalseAction(joinMap.DirectoryRoot.JoinNumber, codec.SetCurrentDirectoryToRoot);
trilist.SetSigFalseAction(joinMap.DirectoryFolderBack.JoinNumber, codec.GetDirectoryParentFolderContents);
if (codec.DirectoryRoot != null)
{
trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort)codec.DirectoryRoot.CurrentDirectoryResults.Count);
var clearBytes = XSigHelpers.ClearOutputs();
trilist.SetString(joinMap.DirectoryEntries.JoinNumber,
Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length));
var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false);
Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length);
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig);
}
codec.DirectoryResultReturned += (sender, args) =>
{
trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort)args.Directory.CurrentDirectoryResults.Count);
@@ -965,7 +1028,9 @@ ScreenIndexIsPinnedTo: {8} (a{17})
trilist.SetString(joinMap.DirectoryEntries.JoinNumber,
Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length));
var directoryXSig = UpdateDirectoryXSig(args.Directory, !codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue);
var directoryXSig = UpdateDirectoryXSig(args.Directory, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false);
Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length);
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig);
};
@@ -974,63 +1039,187 @@ ScreenIndexIsPinnedTo: {8} (a{17})
{
if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, "\xFC");
UpdateDirectoryXSig(codec.CurrentDirectoryResult,
!codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue);
codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false);
};
}
private void SelectDirectoryEntry(IHasDirectory codec, ushort i)
private void SelectDirectoryEntry(IHasDirectory codec, ushort i, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
var entry = codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1];
if (i < 1 || i > codec.CurrentDirectoryResult.CurrentDirectoryResults.Count) return;
if (entry is DirectoryFolder)
_selectedDirectoryItem = codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1];
if (_selectedDirectoryItem is DirectoryFolder)
{
codec.GetDirectoryFolderContents(entry.FolderId);
return;
codec.GetDirectoryFolderContents(_selectedDirectoryItem.FolderId);
trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0);
trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, _selectedDirectoryItem.Name);
trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, string.Empty);
trilist.ClearUShortSigAction(joinMap.SelectContactMethod.JoinNumber);
trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedLine.JoinNumber);
trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber);
return;
}
var dialableEntry = entry as IInvitableContact;
// not a folder. Clear this value
trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, string.Empty);
if (dialableEntry != null)
{
Dial(dialableEntry);
return;
}
var selectedContact = _selectedDirectoryItem as DirectoryContact;
if (selectedContact != null)
{
trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, selectedContact.Name);
}
var entryToDial = entry as DirectoryContact;
// Allow auto dial of selected line. Always dials first contact method
if (!trilist.GetBool(joinMap.DirectoryDisableAutoDialSelectedLine.JoinNumber))
{
var invitableEntry = _selectedDirectoryItem as IInvitableContact;
if (entryToDial == null) return;
if (invitableEntry != null)
{
Dial(invitableEntry);
return;
}
Dial(entryToDial.ContactMethods[0].Number);
var entryToDial = _selectedDirectoryItem as DirectoryContact;
trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber, selectedContact.ContactMethods[0].Number);
if (entryToDial == null) return;
Dial(entryToDial.ContactMethods[0].Number);
return;
}
else
{
// If auto dial is disabled...
var entryToDial = _selectedDirectoryItem as DirectoryContact;
if (entryToDial == null)
{
// Clear out values and actions from last selected item
trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0);
trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, string.Empty);
trilist.ClearUShortSigAction(joinMap.SelectContactMethod.JoinNumber);
trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedLine.JoinNumber);
trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber);
return;
}
trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, (ushort)entryToDial.ContactMethods.Count);
// Update the action to dial the selected contact method
trilist.SetUShortSigAction(joinMap.SelectContactMethod.JoinNumber, (u) =>
{
if (u < 1 || u > entryToDial.ContactMethods.Count) return;
trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber, () => Dial(entryToDial.ContactMethods[u - 1].Number));
});
// Sets DirectoryDialSelectedLine join action to dial first contact method
trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedLine.JoinNumber, () => Dial(entryToDial.ContactMethods[0].Number));
var clearBytes = XSigHelpers.ClearOutputs();
trilist.SetString(joinMap.ContactMethods.JoinNumber,
Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length));
var contactMethodsXSig = UpdateContactMethodsXSig(entryToDial);
trilist.SetString(joinMap.ContactMethods.JoinNumber, contactMethodsXSig);
}
}
/// <summary>
/// Generates the XSig data representing the available contact methods for the selected DirectoryContact
/// </summary>
/// <param name="contact"></param>
/// <returns></returns>
private string UpdateContactMethodsXSig(DirectoryContact contact)
{
const int maxMethods = 10;
const int maxStrings = 3;
const int offset = maxStrings;
var stringIndex = 0;
var arrayIndex = 0;
// Create a new token array and set the size to the number of methods times the total number of signals
var tokenArray = new XSigToken[maxMethods * offset];
Debug.Console(2, this, "Creating XSIG token array with size {0}", maxMethods * offset);
// TODO: Add code to generate XSig data
foreach (var method in contact.ContactMethods)
{
if (arrayIndex >= maxMethods * offset)
break;
//serials
tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, method.Number);
tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, method.ContactMethodId.ToString());
tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, method.Device.ToString());
arrayIndex += offset;
stringIndex += maxStrings;
}
while (arrayIndex < maxMethods)
{
tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, String.Empty);
tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, String.Empty);
tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, String.Empty);
arrayIndex += offset;
stringIndex += maxStrings;
}
return GetXSigString(tokenArray);
}
private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot)
{
var contactIndex = 1;
var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count];
var xSigMaxIndex = 1023;
var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count > xSigMaxIndex
? xSigMaxIndex
: directory.CurrentDirectoryResults.Count];
foreach (var entry in directory.CurrentDirectoryResults)
Debug.Console(2, this, "IsRoot: {0}, Directory Count: {1}, TokenArray.Length: {2}", isRoot, directory.CurrentDirectoryResults.Count, tokenArray.Length);
var contacts = directory.CurrentDirectoryResults.Count > xSigMaxIndex
? directory.CurrentDirectoryResults.Take(xSigMaxIndex)
: directory.CurrentDirectoryResults;
var contactsToDisplay = isRoot
? contacts.Where(c => c.ParentFolderId == "root")
: contacts.Where(c => c.ParentFolderId != "root");
var counterIndex = 1;
foreach (var entry in contactsToDisplay)
{
var arrayIndex = contactIndex - 1;
var arrayIndex = counterIndex - 1;
var entryIndex = counterIndex;
if (entry is DirectoryFolder && entry.ParentFolderId == "root")
Debug.Console(2, this, "Entry{2:0000} Name: {0}, Folder ID: {1}, Type: {3}, ParentFolderId: {4}",
entry.Name, entry.FolderId, entryIndex, entry.GetType().GetCType().FullName, entry.ParentFolderId);
if (entry is DirectoryFolder)
{
tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, String.Format("[+] {0}", entry.Name));
tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, String.Format("[+] {0}", entry.Name));
contactIndex++;
counterIndex++;
continue;
}
if (isRoot && String.IsNullOrEmpty(entry.FolderId)) continue;
tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, entry.Name);
tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, entry.Name);
contactIndex++;
counterIndex++;
}
return GetXSigString(tokenArray);
}
@@ -1039,8 +1228,34 @@ ScreenIndexIsPinnedTo: {8} (a{17})
trilist.SetSigFalseAction(joinMap.ManualDial.JoinNumber,
() => Dial(trilist.StringOutput[joinMap.CurrentDialString.JoinNumber].StringValue));
//End All calls for now
trilist.SetSigFalseAction(joinMap.EndCall.JoinNumber, EndAllCalls);
//End All calls
trilist.SetSigFalseAction(joinMap.EndAllCalls.JoinNumber, EndAllCalls);
//End a specific call, specified by index. Maximum 8 calls supported
for (int i = 0; i < joinMap.EndCallStart.JoinSpan; i++)
{
var callIndex = i;
trilist.SetSigFalseAction((uint)(joinMap.EndCallStart.JoinNumber + i), () =>
{
if (callIndex < 0 || callIndex >= ActiveCalls.Count)
{
Debug.Console(2, this, "Cannot end call. No call found at index: {0}", callIndex);
return;
}
var call = ActiveCalls[callIndex];
if (call != null)
{
EndCall(call);
}
else
{
Debug.Console(0, this, "[End Call] Unable to find call at index '{0}'", i);
}
});
}
trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall);
@@ -1052,30 +1267,112 @@ ScreenIndexIsPinnedTo: {8} (a{17})
Debug.Console(1, this, "Call is incoming: {0}", args.CallItem.Direction == eCodecCallDirection.Incoming);
trilist.SetBool(joinMap.IncomingCall.JoinNumber, args.CallItem.Direction == eCodecCallDirection.Incoming && args.CallItem.Status == eCodecCallStatus.Ringing);
if (args.CallItem.Direction == eCodecCallDirection.Incoming)
{
trilist.SetSigFalseAction(joinMap.IncomingAnswer.JoinNumber, () => AcceptCall(args.CallItem));
trilist.SetSigFalseAction(joinMap.IncomingReject.JoinNumber, () => RejectCall(args.CallItem));
}
if (args.CallItem.Direction == eCodecCallDirection.Incoming)
{
trilist.SetSigFalseAction(joinMap.IncomingAnswer.JoinNumber, () => AcceptCall(args.CallItem));
trilist.SetSigFalseAction(joinMap.IncomingReject.JoinNumber, () => RejectCall(args.CallItem));
trilist.SetString(joinMap.IncomingCallName.JoinNumber, args.CallItem.Name);
trilist.SetString(joinMap.IncomingCallNumber.JoinNumber, args.CallItem.Number);
}
else
{
trilist.SetString(joinMap.IncomingCallName.JoinNumber, string.Empty);
trilist.SetString(joinMap.IncomingCallNumber.JoinNumber, string.Empty);
}
trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig());
trilist.SetUshort(joinMap.ConnectedCallCount.JoinNumber, (ushort)ActiveCalls.Count);
};
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
var joinCodec = this as IJoinCalls;
if (joinCodec != null)
{
trilist.SetSigFalseAction(joinMap.JoinAllCalls.JoinNumber, () => joinCodec.JoinAllCalls());
// TODO [ ] Issue #868
trilist.SetString(joinMap.CurrentCallData.JoinNumber, "\xFC");
UpdateCallStatusXSig();
};
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.Console(0, 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);
}
});
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;
var call = ActiveCalls[index];
if (call != null)
{
holdCodec.HoldCall(call);
}
else
{
Debug.Console(0, 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;
var call = ActiveCalls[index];
if (call != null)
{
holdCodec.ResumeCall(call);
}
else
{
Debug.Console(0, this, "[Resume Call] Unable to find call at index '{0}'", i);
}
});
}
}
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.CurrentCallData.JoinNumber, "\xFC");
UpdateCallStatusXSig();
};
}
private string UpdateCallStatusXSig()
{
const int maxCalls = 8;
const int maxStrings = 5;
const int offset = 6;
const int maxStrings = 6;
const int maxDigitals = 2;
const int offset = maxStrings + maxDigitals;
var stringIndex = 0;
var digitalIndex = maxStrings * maxCalls;
var arrayIndex = 0;
@@ -1087,7 +1384,8 @@ ScreenIndexIsPinnedTo: {8} (a{17})
if (arrayIndex >= maxCalls * offset)
break;
//digitals
tokenArray[arrayIndex] = new XSigDigitalToken(digitalIndex + 1, call.IsActiveCall);
tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, call.IsActiveCall);
tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, call.IsOnHold);
//serials
tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, call.Name ?? String.Empty);
@@ -1095,6 +1393,12 @@ ScreenIndexIsPinnedTo: {8} (a{17})
tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, call.Direction.ToString());
tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 4, call.Type.ToString());
tokenArray[arrayIndex + 5] = new XSigSerialToken(stringIndex + 5, call.Status.ToString());
if(call.Duration != null)
{
// May need to verify correct string format here
var dur = string.Format("{0:c}", call.Duration);
tokenArray[arrayIndex + 6] = new XSigSerialToken(stringIndex + 6, dur);
}
arrayIndex += offset;
stringIndex += maxStrings;
@@ -1103,14 +1407,17 @@ ScreenIndexIsPinnedTo: {8} (a{17})
while (digitalIndex < maxCalls)
{
//digitals
tokenArray[arrayIndex] = new XSigDigitalToken(digitalIndex + 1, false);
tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false);
tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false);
//serials
//serials
tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, String.Empty);
tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, String.Empty);
tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, String.Empty);
tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 4, String.Empty);
tokenArray[arrayIndex + 5] = new XSigSerialToken(stringIndex + 5, String.Empty);
tokenArray[arrayIndex + 6] = new XSigSerialToken(stringIndex + 6, String.Empty);
arrayIndex += offset;
stringIndex += maxStrings;
@@ -1122,25 +1429,61 @@ ScreenIndexIsPinnedTo: {8} (a{17})
private void LinkVideoCodecDtmfToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
trilist.SetSigFalseAction(joinMap.Dtmf0.JoinNumber, () => SendDtmf("0"));
trilist.SetSigFalseAction(joinMap.Dtmf1.JoinNumber, () => SendDtmf("1"));
trilist.SetSigFalseAction(joinMap.Dtmf2.JoinNumber, () => SendDtmf("2"));
trilist.SetSigFalseAction(joinMap.Dtmf3.JoinNumber, () => SendDtmf("3"));
trilist.SetSigFalseAction(joinMap.Dtmf4.JoinNumber, () => SendDtmf("4"));
trilist.SetSigFalseAction(joinMap.Dtmf5.JoinNumber, () => SendDtmf("5"));
trilist.SetSigFalseAction(joinMap.Dtmf6.JoinNumber, () => SendDtmf("6"));
trilist.SetSigFalseAction(joinMap.Dtmf7.JoinNumber, () => SendDtmf("7"));
trilist.SetSigFalseAction(joinMap.Dtmf8.JoinNumber, () => SendDtmf("8"));
trilist.SetSigFalseAction(joinMap.Dtmf9.JoinNumber, () => SendDtmf("9"));
trilist.SetSigFalseAction(joinMap.DtmfStar.JoinNumber, () => SendDtmf("*"));
trilist.SetSigFalseAction(joinMap.DtmfPound.JoinNumber, () => SendDtmf("#"));
trilist.SetSigFalseAction(joinMap.Dtmf0.JoinNumber, () => SendDtmfAction("0", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf1.JoinNumber, () => SendDtmfAction("1", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf2.JoinNumber, () => SendDtmfAction("2", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf3.JoinNumber, () => SendDtmfAction("3", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf4.JoinNumber, () => SendDtmfAction("4", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf5.JoinNumber, () => SendDtmfAction("5", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf6.JoinNumber, () => SendDtmfAction("6", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf7.JoinNumber, () => SendDtmfAction("7", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf8.JoinNumber, () => SendDtmfAction("8", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf9.JoinNumber, () => SendDtmfAction("9", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.DtmfStar.JoinNumber, () => SendDtmfAction("*", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.DtmfPound.JoinNumber, () => SendDtmfAction("#", trilist, joinMap));
}
/// <summary>
/// Sends the specified string as a DTMF command.
/// Reads the value of the SendDtmfToSpecificCallInstance digital join and SelectCall analog join to determine
/// Whther to send to a specific call index or to the last connected call
/// </summary>
/// <param name="s"></param>
/// <param name="trilist"></param>
/// <param name="joinMap"></param>
private void SendDtmfAction(string s, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
if (!trilist.GetBool(joinMap.SendDtmfToSpecificCallIndex.JoinNumber))
{
SendDtmf(s);
}
else
{
var callIndex = trilist.GetUshort(joinMap.SelectCall.JoinNumber);
if (callIndex > 0 && callIndex <= 8)
{
var call = ActiveCalls[callIndex - 1];
if (call != null && call.IsActiveCall)
{
SendDtmf(s, call);
}
else
{
Debug.Console(0, this, "Warning: No call found at index {0} or call is not active.", callIndex);
}
}
else
{
Debug.Console(0, this, "Warning: Invalid call index specified. Please use a value of 1-8.");
}
}
}
private void LinkVideoCodecCameraLayoutsToApi(IHasCodecLayouts codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
trilist.SetSigFalseAction(joinMap.CameraLayout.JoinNumber, codec.LocalLayoutToggle);
codec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.CameraLayoutStringFb.JoinNumber]);
codec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentLayoutStringFb.JoinNumber]);
}
private void LinkVideoCodecCameraModeToApi(IHasCameraAutoMode codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
@@ -1271,18 +1614,81 @@ ScreenIndexIsPinnedTo: {8} (a{17})
else camera.ZoomStop();
});
trilist.SetBoolSigAction(joinMap.CameraFocusNear.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraFocusControl;
if (camera == null) return;
if (b) camera.FocusNear();
else camera.FocusStop();
});
trilist.SetBoolSigAction(joinMap.CameraFocusFar.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraFocusControl;
if (camera == null) return;
if (b) camera.FocusFar();
else camera.FocusStop();
});
trilist.SetSigFalseAction(joinMap.CameraFocusAuto.JoinNumber, () =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraFocusControl;
if (camera == null) return;
camera.TriggerAutoFocus();
});
// Camera count
trilist.SetUshort(joinMap.CameraCount.JoinNumber, (ushort)codec.Cameras.Count);
// Camera names
for (uint i = 0; i < joinMap.CameraNamesFb.JoinSpan; i++)
{
//Check the count first
if (i < codec.Cameras.Count && codec.Cameras[(int)i] != null)
{
trilist.SetString(joinMap.CameraNamesFb.JoinNumber + i, codec.Cameras[(int)i].Name);
}
else
{
trilist.SetString(joinMap.CameraNamesFb.JoinNumber + i, "");
}
}
//Camera Select
trilist.SetUShortSigAction(joinMap.CameraNumberSelect.JoinNumber, (i) =>
{
if (codec.SelectedCamera == null) return;
codec.SelectCamera(codec.Cameras[i].Key);
if (i > 0 && i <= codec.Cameras.Count)
{
codec.SelectCamera(codec.Cameras[i - 1].Key);
}
else
{
Debug.Console(0, this, "Unable to select. No camera found at index {0}", i);
}
});
// Set initial selected camera feedback
if (codec.SelectedCamera != null)
{
trilist.SetUshort(joinMap.CameraNumberSelect.JoinNumber, (ushort)codec.Cameras.FindIndex((c) => c.Key == codec.SelectedCamera.Key));
}
codec.CameraSelected += (sender, args) =>
{
var i = (ushort)codec.Cameras.FindIndex((c) => c.Key == args.SelectedCamera.Key);
trilist.SetUshort(joinMap.CameraNumberSelect.JoinNumber, (ushort)(i + 1));
if (codec is IHasCodecRoomPresets)
{
return;
@@ -1325,10 +1731,16 @@ ScreenIndexIsPinnedTo: {8} (a{17})
trilist.SetUShortSigAction(joinMap.CameraPresetSelect.JoinNumber, (i) =>
{
presetCodec.CodecRoomPresetSelect(i);
trilist.SetUshort(joinMap.CameraPresetSelect.JoinNumber, i);
});
// Far End Presets
trilist.SetUShortSigAction(joinMap.FarEndPresetSelect.JoinNumber, (i) =>
{
presetCodec.SelectFarEndPreset(i);
});
trilist.SetSigFalseAction(joinMap.CameraPresetSave.JoinNumber,
() =>
{
@@ -1347,7 +1759,96 @@ ScreenIndexIsPinnedTo: {8} (a{17})
};
}
private string SetCameraPresetNames(IEnumerable<CodecRoomPreset> presets)
// 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)
{
codec.CallHistory.RecentCallsListHasChanged += (o, a) =>
{
UpdateCallHistory(codec, trilist, joinMap);
};
// Selected item action and feedback
trilist.SetUShortSigAction(joinMap.SelectRecentCallItem.JoinNumber, (u) =>
{
if (u == 0 || u > codec.CallHistory.RecentCalls.Count)
{
Debug.Console(2, this, "Recent Call History index out of range");
return;
}
_selectedRecentCallItemIndex = (int)(u - 1);
trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, u);
var _selectedRecentCallItem = codec.CallHistory.RecentCalls[_selectedRecentCallItemIndex];
if (_selectedRecentCallItem != null)
{
trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, _selectedRecentCallItem.Name);
trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, _selectedRecentCallItem.Number);
trilist.SetSigFalseAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber, () => codec.RemoveCallHistoryEntry(_selectedRecentCallItem));
trilist.SetSigFalseAction(joinMap.DialSelectedRecentCallItem.JoinNumber, () => this.Dial(_selectedRecentCallItem.Number));
}
else
{
trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty);
trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty);
trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber);
trilist.ClearBoolSigAction(joinMap.DialSelectedRecentCallItem.JoinNumber);
}
});
}
private void UpdateCallHistory(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
// 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);
trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber);
//
trilist.SetUshort(joinMap.RecentCallCount.JoinNumber, (ushort)codec.CallHistory.RecentCalls.Count);
// Update the call history joins
var maxItems = joinMap.RecentCallNamesStart.JoinSpan;
// Create history
uint index = 0;
for (uint i = 0; i < maxItems && i < codec.CallHistory.RecentCalls.Count; i++)
{
trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, codec.CallHistory.RecentCalls[(int)i].Name);
trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, codec.CallHistory.RecentCalls[(int)i].StartTime.ToShortTimeString());
trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)codec.CallHistory.RecentCalls[(int)i].OccurrenceType);
//i++;
index = i;
}
//foreach(var item in codec.CallHistory.RecentCalls)
//{
// trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, item.Name);
// trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, item.StartTime.ToShortTimeString());
// trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)item.OccurrenceType);
// i++;
//}
// Clears existing items
for (uint j = index; j < maxItems; j++)
{
trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + j, string.Empty);
trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + j, string.Empty);
trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + j, 0);
}
}
private string SetCameraPresetNames(IEnumerable<CodecRoomPreset> presets)
{
return SetCameraPresetNames(presets.Select(p => p.Description).ToList());
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
public class ShareInfoEventArgs : EventArgs
{
public zStatus.Sharing SharingStatus { get; private set; }
public ShareInfoEventArgs(zStatus.Sharing status)
{
SharingStatus = status;
}
}
public interface IZoomWirelessShareInstructions
{
event EventHandler<ShareInfoEventArgs> ShareInfoChanged;
zStatus.Sharing SharingState { get; }
}
}

View File

@@ -31,10 +31,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
else
{
Debug.Console(2, "PropertyChanged event is NULL");
}
}
#endregion
@@ -429,9 +434,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public bool supports_Web_Settings_Push { get; set; }
}
public enum eDisplayState
{
None,
Laptop,
IOS,
}
public class Sharing : NotifiableObject
{
private string _dispState;
private eDisplayState _dispState;
private string _password;
private bool _isAirHostClientConnected;
private bool _isSharingBlackMagic;
@@ -443,7 +455,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// Laptop client sharing key
/// </summary>
public string directPresentationSharingKey { get; set; }
public string dispState
public eDisplayState dispState
{
get
{
@@ -501,8 +513,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
/// <summary>
/// IOS Airplay code
/// </summary>
@@ -778,13 +788,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
set
{
//Debug.Console(2, "************************************setting value of meetingIsBeingRecorded to: {0}", value);
if (value != _meetingIsBeingRecorded)
{
_meetingIsBeingRecorded = value;
//Debug.Console(2, "********************************set value of meetingIsBeingRecorded to: {0}", _meetingIsBeingRecorded);
NotifyPropertyChanged("meetingIsBeingRecorded");
}
}
}
public CallRecordInfo()
{
Debug.Console(2, Debug.ErrorLogLevel.Notice, "********************************************* CallRecordInfo() ******************************************");
}
}
}

View File

@@ -7,6 +7,8 @@ using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Devices.Common.Cameras;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
public enum eZoomRoomCameraState
@@ -34,7 +36,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
protected ZoomRoom ParentCodec { get; private set; }
public int Id = 0; // ID of near end selected camara is always 0
[JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
public int? Id = 0; // ID of near end selected camara is always 0
private int ContinueTime = 10; // number of milliseconds between issuing continue commands

View File

@@ -8,9 +8,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
#region Digital
// TODO [ ] Issue #868
[JoinName("ShowPasswordPrompt")]
public JoinDataComplete ShowPasswordPrompt = new JoinDataComplete(
[JoinName("CancelJoinAttempt")]
public JoinDataComplete CancelJoinAttempt = new JoinDataComplete(
new JoinData
{
JoinNumber = 5,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to hide the password prompt",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("MeetingPasswordRequired")]
public JoinDataComplete MeetingPasswordRequired = new JoinDataComplete(
new JoinData
{
JoinNumber = 6,
@@ -23,7 +36,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("PasswordIncorrect")]
public JoinDataComplete PasswordIncorrect = new JoinDataComplete(
new JoinData
@@ -38,8 +50,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("PassowrdLoginFailed")]
[JoinName("PasswordLoginFailed")]
public JoinDataComplete PasswordLoginFailed = new JoinDataComplete(
new JoinData
{
@@ -53,7 +64,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("WaitingForHost")]
public JoinDataComplete WaitingForHost = new JoinDataComplete(
new JoinData
@@ -68,7 +78,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("IsHost")]
public JoinDataComplete IsHost = new JoinDataComplete(
new JoinData
@@ -83,7 +92,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("StartMeetingNow")]
public JoinDataComplete StartMeetingNow = new JoinDataComplete(
new JoinData
@@ -98,7 +106,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("ShareOnlyMeeting")]
public JoinDataComplete ShareOnlyMeeting = new JoinDataComplete(
new JoinData
@@ -113,7 +120,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("StartNormalMeetingFromSharingOnlyMeeting")]
public JoinDataComplete StartNormalMeetingFromSharingOnlyMeeting = new JoinDataComplete(
new JoinData
@@ -295,8 +301,112 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Description = "Toggles the selfview pip size, (aka layout size)",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
});
[JoinName("StartRecording")]
public JoinDataComplete StartRecording = new JoinDataComplete(
new JoinData
{
JoinNumber = 241,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to start the Meeting Recording. FB high if meeting is currently recording",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("StopRecording")]
public JoinDataComplete StopRecording = new JoinDataComplete(
new JoinData
{
JoinNumber = 242,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to stop the Meeting Recording. FB high if meeting is currently NOT recording",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("RecordConsentPromptIsVisible")]
public JoinDataComplete RecordConsentPromptIsVisible = new JoinDataComplete(
new JoinData
{
JoinNumber = 243,
JoinSpan = 1
},
new JoinMetadata
{
Description = "When high, indicates that the recording consent prompt is visible on the ZoomRoom UI",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("RecordingPromptAgree")]
public JoinDataComplete RecordingPromptAgree = new JoinDataComplete(
new JoinData
{
JoinNumber = 244,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to agree to consent for meeting recording",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("RecordingPromptDisagree")]
public JoinDataComplete RecordingPromptDisagree = new JoinDataComplete(
new JoinData
{
JoinNumber = 245,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to disagree to consent for meeting recording",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
#region Sharing Status
[JoinName("IsSharingAirplay")]
public JoinDataComplete IsSharingAirplay = new JoinDataComplete(
new JoinData
{
JoinNumber = 250,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Indicates an Airplay source is sharing",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("IsSharingHdmi")]
public JoinDataComplete IsSharingHdmi = new JoinDataComplete(
new JoinData
{
JoinNumber = 251,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Indicates an HDMI source is sharing",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
#endregion
//[JoinName("ParticipantAudioMuteToggleStart")]
//public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete(
// new JoinData
@@ -481,6 +591,92 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.DigitalSerial
});
[JoinName("DisplayState")]
public JoinDataComplete DisplayState = new JoinDataComplete(
new JoinData
{
JoinNumber = 250,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Reports the instructions the ZoomRoom is displaying on the monitor. <None | Laptop | IOS>",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("AirplayShareCode")]
public JoinDataComplete AirplayShareCode = new JoinDataComplete(
new JoinData
{
JoinNumber = 251,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Reports the current code for Airplay Sharing.",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("LaptopShareKey")]
public JoinDataComplete LaptopShareKey = new JoinDataComplete(
new JoinData
{
JoinNumber = 252,
JoinSpan = 1
},
new JoinMetadata
{
Description = "The alpha-only sharing key that users type into a laptop client to share with the Zoom Room.",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("LaptopSharePairingCode")]
public JoinDataComplete LaptopSharePairingCode = new JoinDataComplete(
new JoinData
{
JoinNumber = 253,
JoinSpan = 1
},
new JoinMetadata
{
Description = "This is the paring code that is broadcast via an ultrasonic signal from the ZRC. It is different than the user-supplied paring code. The ZRC uses a Zoom-proprietary method of advertizing the ultrasonic pairing code, so it\'s not possible to advertize it using commonly available libraries.",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("WifiName")]
public JoinDataComplete WifiName = new JoinDataComplete(
new JoinData
{
JoinNumber = 254,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Reports the Wifi SSID used by the ZoomRoom.",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ServerName")]
public JoinDataComplete ServerName = new JoinDataComplete(
new JoinData
{
JoinNumber = 255,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Reports the namne of the the ZoomRoom.",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
#endregion
public ZoomRoomJoinMap(uint joinStart)

View File

@@ -2,30 +2,40 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
public class ZoomRoomPropertiesConfig
{
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
public bool DisablePhonebookAutoDownload { get; set; }
public bool SupportsCameraAutoMode { get; set; }
{
[JsonProperty("communicationMonitorProperties")]
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
[JsonProperty("disablePhonebookAutoDownload")]
public bool DisablePhonebookAutoDownload { get; set; }
[JsonProperty("supportsCameraAutoMode")]
public bool SupportsCameraAutoMode { get; set; }
[JsonProperty("supportsCameraOff")]
public bool SupportsCameraOff { get; set; }
//if true, the layouts will be set automatically when sharing starts/ends or a call is joined
//if true, the layouts will be set automatically when sharing starts/ends or a call is joined
[JsonProperty("autoDefaultLayouts")]
public bool AutoDefaultLayouts { get; set; }
/* This layout will be selected when Sharing starts (either from Far end or locally)*/
/* This layout will be selected when Sharing starts (either from Far end or locally)*/
[JsonProperty("defaultSharingLayout")]
public string DefaultSharingLayout { get; set; }
//This layout will be selected when a call is connected and no content is being shared
public string DefaultCallLayout { get; set; }
//This layout will be selected when a call is connected and no content is being shared
[JsonProperty("defaultCallLayout")]
public string DefaultCallLayout { get; set; }
[JsonProperty("minutesBeforeMeetingStart")]
public int MinutesBeforeMeetingStart { get; set; }
}
}

View File

@@ -1,3 +1,3 @@
<packages>
<package id="PepperDashCore" version="1.1.0" targetFramework="net35" allowedVersions="[1.0,2.0)"/>
<package id="PepperDashCore" version="1.1.1" targetFramework="net35" allowedVersions="[1.0,2.0)"/>
</packages>