Compare commits

..

186 Commits

Author SHA1 Message Date
Neil Dorin
50b2c7d3af Merge pull request #543 from PepperDash/release/1.7.0
Release/1.7.0
2021-01-12 10:31:21 -07:00
Neil Dorin
bdb007f6ed Merge pull request #540 from PepperDash/hotfix/dge-devinfo-issues
Hotfix/dge devinfo issues
2021-01-07 15:25:53 -07:00
Neil Dorin
91abe4c09a Updates to IR files and Enter command 2021-01-07 15:23:35 -07:00
Neil Dorin
82029894e4 Changed to use passed in type value for signal type instead of assuming both audio and video 2021-01-07 14:46:49 -07:00
Trevor Payne
3c1ed6e58a Added debug statements to ExecuteNumericSwitch in DmTx4kz302CController 2021-01-07 12:41:29 -06:00
Neil Dorin
8999097100 Adds additional debug to help with room on/off events 2021-01-06 16:12:12 -07:00
Andrew Welker
3b0a5285ab fix order for comm monitor 2020-12-21 17:00:37 -07:00
Andrew Welker
ae03b8cd7e fix PresetsList saving to file 2020-12-21 16:19:45 -07:00
Andrew Welker
cc159e306e update Essentials to use PepperDash Core 1.0.43 2020-12-21 14:40:19 -07:00
Andrew Welker
0a43f43f66 add ICommunicationMonitor to EiscApiAdvanced 2020-12-21 12:31:00 -07:00
Andrew Welker
0f924360c1 fix issues in LinkToApi 2020-12-21 10:51:12 -07:00
Neil Dorin
870f2f8fa6 properly defines the IsWarming/Cooling FeedbackFuncs and fires feedbacks 2020-12-18 14:34:15 -07:00
Andrew Welker
aa61479adc remove device info stuff from DGE for now 2020-12-18 09:16:40 -07:00
Andrew Welker
522c107ce6 Merge pull request #532 from PepperDash/feature/room-updates
Feature/room updates
2020-12-17 16:31:37 -07:00
Andrew Welker
cb29775004 Merge branch 'development' into feature/room-updates 2020-12-17 16:13:45 -07:00
Neil Dorin
fccbb55344 Merge pull request #528 from PepperDash/feature/update-plugin-dependency-check
Update Plugin Dependency Check
2020-12-17 16:13:30 -07:00
Andrew Welker
b2402402d9 remove dummy device add 2020-12-17 14:48:01 -07:00
Neil Dorin
f0a3b27e3b Adds dummy source and room power on implementation 2020-12-17 14:28:27 -07:00
Neil Dorin
57ebd2b608 Adds IRunDirectAction to EssentialsTechRoom 2020-12-17 14:07:48 -07:00
Andrew Welker
695ff5487f actually fire the PresetsSaved event 2020-12-17 10:38:31 -07:00
Andrew Welker
66cd39c013 changed event names and added saved event 2020-12-16 16:21:10 -07:00
Andrew Welker
91eec8c258 fix scheduled event saving 2020-12-15 16:43:09 -07:00
Andrew Welker
d2c308c009 Add methods & logic to make sure...
...day & time is in the list of recurrence days
2020-12-15 09:47:35 -07:00
Andrew Welker
a4a99f4a9b remove JsonConverter Attribute 2020-12-15 09:47:08 -07:00
Andrew Welker
eb114b4a95 make Days enum serialize to string 2020-12-15 08:44:10 -07:00
Andrew Welker
93e8d50e55 Merge branch 'development' into feature/update-plugin-dependency-check 2020-12-11 15:51:10 -07:00
Andrew Welker
3c6fc978d4 Merge pull request #530 from PepperDash/hotfix/displayBase-fixes
Hotfix/display base fixes
2020-12-11 15:50:55 -07:00
Andrew Welker
01ddf1721c add method to get scheduled events 2020-12-11 15:42:38 -07:00
Andrew Welker
1ee87c0499 add some debug statements and fix presets file loading 2020-12-09 16:37:14 -07:00
Andrew Welker
f8ae6264f7 add some debug statements and fix presets file loading 2020-12-09 16:18:21 -07:00
Andrew Welker
3e56859943 add UpdatePresets method 2020-12-09 15:14:52 -07:00
Andrew Welker
945db8a233 Merge branch 'development' into hotfix/displayBase-fixes 2020-12-09 13:02:59 -07:00
Neil Dorin
823f7447c3 Merge pull request #529 from PepperDash/hotfix/displayBase-fixes
Add PowerIsOnFeedback back to DisplayBase and marked it as Obsolete
2020-12-09 13:02:25 -07:00
Andrew Welker
6e4fa48b9d rearrange message formatting 2020-12-08 16:34:00 -07:00
Andrew Welker
7e8f216afb added logic to send presets to far end 2020-12-08 16:24:35 -07:00
Andrew Welker
b09c151738 Added logic to send presets to far end 2020-12-08 16:24:22 -07:00
Andrew Welker
56cf54a644 Added LinkRooms as a PostActivationAction 2020-12-08 16:24:03 -07:00
Andrew Welker
169e897748 Add CriticalSection for file ops 2020-12-08 12:54:35 -07:00
Andrew Welker
748b1ca147 Add config properties
Implement ITvPresetsProvider
2020-12-08 12:51:20 -07:00
Andrew Welker
2e636082bb #526 Add ITvPresetsProvider interface 2020-12-08 12:50:55 -07:00
Andrew Welker
9204ad2701 #525 Add Rooms Array & LinkToRooms method 2020-12-08 12:48:26 -07:00
Andrew Welker
8feb7a142c #524 Fix Fusion Printing 2020-12-08 11:06:06 -07:00
Andrew Welker
d990930b19 #523 Add return statement 2020-12-08 11:05:52 -07:00
Andrew Welker
4d67279827 Log message to error log when configured com port doesn't exist 2020-12-08 08:02:35 -07:00
Andrew Welker
a78b29b0a1 #523 Add NullCheck and Debug message for com Port 2020-12-08 08:01:58 -07:00
Andrew Welker
2c36c0f2cb Run GoWithLoad command in separate thread
when using donotloadonnextboot
2020-12-08 08:01:25 -07:00
Andrew Welker
2eaf21b1e0 Fix event retrieval 2020-12-08 08:01:01 -07:00
Andrew Welker
099e387570 getting things in the right order for scheduling 2020-12-07 17:21:05 -07:00
Andrew Welker
c4755f23cd added logic to subscribe to scheduled event 2020-12-07 16:58:33 -07:00
Andrew Welker
9c4650b4af fixes to get it to load 2020-12-07 16:32:06 -07:00
Andrew Welker
43d7fab04d refactored Fusion Base Class 2020-12-07 11:50:48 -07:00
Andrew Welker
d2b7e71c4a Added GetScheduledEventGroup Method
added logic to enable/disable events
2020-12-07 11:49:30 -07:00
Andrew Welker
ab6d44e604 added enable property to ScheduledEventConfig 2020-12-07 11:48:48 -07:00
Andrew Welker
0dc2e9d134 Added logic to create EssentialsTechRoom 2020-12-07 11:48:34 -07:00
Andrew Welker
3a024b8d4c moved ScheduledEvents list to main object 2020-12-07 11:48:21 -07:00
Andrew Welker
05e2422cb4 refactoring some methods
add handling for Scheduled Events
2020-12-07 11:48:07 -07:00
Andrew Welker
fc5d4f946d added scheduled events config 2020-12-04 21:36:07 -07:00
Andrew Welker
45c1e25e4f Change to list of actions instead of dictionary 2020-12-04 21:35:31 -07:00
Andrew Welker
f11bdcfd53 add schedule config and schedule stuff 2020-12-04 16:21:48 -07:00
Andrew Welker
9888fbf047 added save presets method & expose some properties 2020-12-04 13:44:39 -07:00
Andrew Welker
9171610e34 getting files back in the project 2020-12-04 13:44:39 -07:00
Andrew Welker
7a8c1f3165 adding some overloads 2020-12-04 13:44:39 -07:00
Andrew Welker
008a052045 getting started with EssentialsTechRoom 2020-12-04 13:44:39 -07:00
Andrew Welker
93a5f2e3b2 fix slases 2020-12-04 12:18:08 -07:00
Andrew Welker
0e4edca08a update plugin dependency check message 2020-12-04 11:05:46 -07:00
Andrew Welker
f9925f9ec9 Add PowerIsOnFeedback back to DisplayBase and marked it as Obsolete 2020-12-03 16:46:10 -07:00
Andrew Welker
f283f82bbc Merge pull request #520 from PepperDash/feature/add-dm-streaming-start-stop-support
Add dm streaming start stop support
2020-12-02 12:09:50 -07:00
Alex Johnson
ab5dd5f756 Fixes streaming card feedback and removes excess debug 2020-12-02 13:51:44 -05:00
Alex Johnson
e22c71853f Starts adding support for starting and stopping dm stream cards via API bridge 2020-12-02 13:10:47 -05:00
Andrew Welker
8bf27ecbd9 Merge pull request #518 from PepperDash/hotfix/zoom-auto-layout
Hotfix/zoom auto layout
2020-11-30 14:46:43 -07:00
Andrew Welker
d94d003050 Merge branch 'development' into hotfix/zoom-auto-layout 2020-11-30 14:08:08 -07:00
Andrew Welker
25c4d94366 Merge pull request #517 from PepperDash/hotfix/zoom-auto-layout
Fix some issues with Zoom Rooms
2020-11-30 14:05:35 -07:00
Andrew Welker
91dda3213e fix an IF statement to be correct 2020-11-30 13:42:27 -07:00
jkdevito
b41dd23c7f Hotfix testing with Zoom PC to find what is triggering a layout change. Currently unresolved 2020-11-30 14:29:57 -06:00
Andrew Welker
14ad0eee48 adding some debug statements to try and suss out what's going on 2020-11-24 16:04:01 -07:00
Andrew Welker
56e106ff32 #512 add null check and return unknown if it is null 2020-11-24 15:46:33 -07:00
Andrew Welker
b67424c1e1 Merge pull request #507 from PepperDash/hotfix/missing-logo-info-in-room-config
Hotfix/missing logo info in room config
2020-11-24 11:25:06 -07:00
Andrew Welker
c366ee9d12 Merge branch 'development' into hotfix/missing-logo-info-in-room-config 2020-11-24 10:55:09 -07:00
Andrew Welker
5ec97f2e31 Merge pull request #506 from PepperDash/hotfix/missing-logo-info-in-room-config
Addresses #505
2020-11-24 10:52:30 -07:00
Neil Dorin
98c20464d7 Addresses #505 2020-11-24 10:26:55 -07:00
Neil Dorin
b1aa9c3306 Merge pull request #498 from PepperDash/feature/mc-qr-code-checksum
#497 Add logic to set checksum value
2020-11-19 16:01:28 -07:00
Andrew Welker
db6ab3ee98 #497 Add logic to set checksum value 2020-11-18 09:36:39 -07:00
Neil Dorin
2ccf4be559 Merge pull request #496 from PepperDash/release/1.6.7
Release/1.6.7
2020-11-16 12:01:44 -07:00
Neil Dorin
ce86255119 Merge pull request #494 from PepperDash/release/1.6.7
Release/1.6.7
2020-11-16 12:01:01 -07:00
Andrew Welker
d69e81972e Merge branch 'main' into release/1.6.7 2020-11-16 11:44:39 -07:00
Andrew Welker
3f9d306a34 fix conditions for getting mc 2020-11-13 16:03:02 -07:00
Andrew Welker
14c3914e5c remove commented-out MC Stuff 2020-11-13 15:53:02 -07:00
Andrew Welker
b5337572c4 update nuspec for correct dependencies 2020-11-13 15:44:02 -07:00
Andrew Welker
1d1b4f0790 update mobileControl retrieval method
remove commented out MC stuff
2020-11-13 15:43:48 -07:00
Neil Dorin
ccdd8005d0 Fixes inverted standby state feedback 2020-11-13 14:54:26 -07:00
Neil Dorin
1d184f0f5e Updates to deactivate standby on codec 2020-11-13 14:46:15 -07:00
Neil Dorin
2ed9e632c6 Updates to deactivate standby on codec 2020-11-13 14:24:38 -07:00
Neil Dorin
ecba28c9cd Moves the stop sharing and standby commands to later in the EndShutdown() sequence 2020-11-13 13:32:04 -07:00
Neil Dorin
06e8cac597 Adds more helpful message to Obsolete attribute on IRoutingSinkNoSwitching 2020-11-12 16:41:40 -07:00
Neil Dorin
1dfdd4dd28 Adds StandbyActivate to EndShutdown 2020-11-12 16:29:22 -07:00
Neil Dorin
48585469f6 Additional updates to resolve external switching with multiple upstream tie lines 2020-11-12 16:28:43 -07:00
Neil Dorin
f9ba562b0b Updates to work when there are multiple tie lines from codec inputs to sources and using ExternalSourceSwitching 2020-11-12 16:23:14 -07:00
Neil Dorin
5c63a49071 Updates IMobileControl interface. Adds VideoCodec.StopSharing() to EndShutdown() method in Vtc1 room 2020-11-12 15:57:10 -07:00
Neil Dorin
3d224496a8 Adds new event to DeviceManager to indicate that all devices have been activated. Necessary for MicrophonePrivacyManager
#485
2020-11-12 12:33:04 -07:00
Neil Dorin
73addfefe7 More fixes to Generic IO classes 2020-11-12 12:11:18 -07:00
Neil Dorin
af0e2180bd Adds back in a factory and necessary methods to build a GenericVersiportInputDevice 2020-11-12 11:44:11 -07:00
Neil Dorin
a431015853 Adds legacy typename to factory for CiscoSparkCodec 2020-11-12 11:16:43 -07:00
Andrew Welker
788244fbf4 Merge pull request #484 from PepperDash/feature/device-info
Add Device Info interfaces and retrievals
2020-11-12 09:11:06 -07:00
Andrew Welker
282230b28e Merge branch 'development' into feature/device-info 2020-11-12 09:50:23 -06:00
Andrew Welker
dc010ce28c Merge pull request #483 from PepperDash/feature/update-PD-Core
Feature/update pd core
2020-11-12 09:50:06 -06:00
Andrew Welker
5a3597f2a7 minor change to generate new build number 2020-11-12 08:28:19 -07:00
Andrew Welker
5b889ea59c back to original version 2020-11-11 16:36:56 -07:00
Andrew Welker
faa6e20034 specifying version for nuget action 2020-11-11 15:45:50 -07:00
Andrew Welker
82a97f8c1f Merge branch 'feature/update-PD-Core' of https://github.com/PepperDash/Essentials into feature/update-PD-Core 2020-11-11 14:42:20 -07:00
Andrew Welker
6557d21aa8 change action to use master instead of v1 2020-11-11 14:41:58 -07:00
Andrew Welker
a733ed69cb Merge branch 'development' into feature/update-PD-Core 2020-11-11 14:05:44 -06:00
Andrew Welker
9877ba93a0 Merge pull request #472 from PepperDash/hotfix/DMPS-Routing-issues
Hotfix/dmps routing issues
2020-11-11 14:05:28 -06:00
Andrew Welker
669f9e71bc Merge branch 'development' into feature/device-info 2020-11-11 13:04:58 -07:00
Andrew Welker
5d2f20efd5 initial implementations for DM Rmc & DGE 2020-11-11 13:02:12 -07:00
Andrew Welker
06dccdd97f Merge branch 'development' into hotfix/DMPS-Routing-issues 2020-11-11 13:42:09 -06:00
Andrew Welker
e705f67333 Merge pull request #480 from PepperDash/feature/resolve-cisco-bugs
Feature/resolve cisco bugs
2020-11-11 13:41:53 -06:00
Andrew Welker
4903b99eb5 fix main workflow 2020-11-11 12:38:50 -07:00
Andrew Welker
38ab6626fc update PD Core to 1.0.43 2020-11-11 12:30:15 -07:00
Andrew Welker
b44bc8fae3 Merge branch 'development' into hotfix/DMPS-Routing-issues 2020-11-11 12:25:36 -07:00
Neil Dorin
7d72d54862 Gets ExternalSourceSwitching feedback working 2020-11-11 12:08:30 -07:00
Neil Dorin
0a218cebb4 Merge pull request #471 from PepperDash/hotfix/DMPS-Routing-issues
Fix DMPS Routing Issues for 4K DMPS units
2020-11-11 12:02:34 -07:00
Andrew Welker
ed6ad6ae76 updates for device info 2020-11-11 11:29:43 -07:00
Andrew Welker
1689b15d95 make IDeviceInfoProvider inherit from IKeyed 2020-11-10 12:00:58 -07:00
Trevor Payne
010fdde45c Fixes issues with Adding HDMI LoopOut Ports 2020-11-10 11:46:51 -06:00
Andrew Welker
10509991c1 updates for getting connected IP stuff 2020-11-10 10:39:49 -07:00
Andrew Welker
c686ee394d update event to use delegate 2020-11-10 10:28:39 -07:00
Neil Dorin
985902092e Merge branch 'feature/add-camera-config-props' into feature/resolve-cisco-bugs 2020-11-10 09:33:06 -07:00
Neil Dorin
944b72e2a8 Adds IHasCameraOff to CameraVisca 2020-11-10 09:32:16 -07:00
Neil Dorin
d074be323c Remove zoom speeds 2020-11-10 09:31:37 -07:00
Neil Dorin
0098401584 Adds SpeedTimer implmentation to CameraVisca 2020-11-10 09:31:37 -07:00
Neil Dorin
0d7d5fe380 Adds feedback parsing to CameraVisca as well as some new focus controls. 2020-11-10 09:31:35 -07:00
Neil Dorin
1cb9fb6058 Removes unnecessary null check in SendDtmf method 2020-11-10 09:29:37 -07:00
Andrew Welker
5076ba405e add logic to update device info when IP-ID comes online 2020-11-10 09:23:51 -07:00
Andrew Welker
3c60dfdf7b add IDeviceInfoProvider & start implementation 2020-11-10 09:14:43 -07:00
Andrew Welker
5d44b5f3ef Merge pull request #477 from PepperDash/feature/update-ipower-interface
Feature/update ipower interface
2020-11-09 21:11:32 -06:00
Neil Dorin
40cdd4c1e7 Makes IPower Obsolete and replaces with IHasPowerControl and IHasPowerControlWithFeedback
Includes major refactor to resolve IPower update

Closes #476
Closes #474 more properly
2020-11-09 16:57:35 -07:00
Neil Dorin
f5753109d5 Fixes multiple issues
closes #474
closes #473
closes #470
2020-11-09 15:14:47 -07:00
Andrew Welker
51e338749a Implement IDeviceInfoProvider on DGE100 2020-11-09 12:11:39 -07:00
Andrew Welker
e37fb33afe add DeviceInfo class 2020-11-09 12:10:44 -07:00
Andrew Welker
47af06578a added IDeviceInfoProvider interface 2020-11-09 09:58:51 -07:00
Andrew Welker
ad0cbba0b1 Merge pull request #465 from PepperDash/bugfix/logo-server-crashing
Bugfix/logo server crashing
2020-11-04 19:54:48 -07:00
Andrew Welker
c7a3282dd9 Merge branch 'development' into bugfix/logo-server-crashing 2020-11-04 13:58:15 -07:00
Andrew Welker
fd593baa07 Merge pull request #468 from PepperDash/feature/IRoutingNumericFeedback
Add IRoutingNumericFeedback interface and implementations
2020-11-04 13:57:58 -07:00
Andrew Welker
88f1230620 got it all working 2020-11-04 14:43:17 -06:00
Trevor Payne
cad558980f Merge branch 'development' into feature/IRoutingNumericFeedback 2020-11-04 13:59:22 -06:00
Trevor Payne
e879aba801 Expanded the event to include RoutingPorts
Triggers for events are now based on FeedbackMatchObject
2020-11-04 13:32:28 -06:00
Neil Dorin
114fdb9545 Merge pull request #469 from PepperDash/feature/update-ci-cd-workflows
Remove deprecated set-env commands
2020-11-03 11:29:54 -07:00
Andrew Welker
1886ddfbaf remove submodule step and udpate set-env 2020-11-03 10:34:37 -07:00
Andrew Welker
39d2c3aab6 remove submodule checkout & update set-env 2020-11-03 10:34:14 -07:00
Andrew Welker
3cd8a1f310 update output change event & feedbacks 2020-11-03 08:30:13 -07:00
Andrew Welker
b457886ee3 Update to route correctly for DMPS3-4K 2020-11-02 12:38:23 -07:00
Trevor Payne
e27c041256 Resolves #467
Made the event trigger private and removed it from the interface
2020-11-02 09:59:22 -06:00
Trevor Payne
5fcafe0b38 Resolves #467
Added new interface IRoutingNumericFeedback

Added New Interface ITxRoutingWithFeedback

Added New Interface IRmcRoutingWithFeedback

Added new interface IRoutingNumericWithFeedback

Implemented new interfaces in applicable classes
2020-10-30 14:00:05 -05:00
Andrew Welker
8250246f34 Merge branch 'development' into bugfix/logo-server-crashing 2020-10-27 17:09:34 -06:00
Neil Dorin
d9bcaa0b1d Merge pull request #464 from PepperDash/bugfix/logo-server-crashing
Logo Server Updates
2020-10-27 16:55:18 -06:00
Andrew Welker
dd6e26ae4b add logic to only start logo server if it's required 2020-10-27 13:43:58 -06:00
Andrew Welker
fac1dd3d61 add protections for invalid paths in logo server 2020-10-27 13:43:37 -06:00
Andrew Welker
e573749aa0 Merge pull request #462 from PepperDash/release/1.6.5
Release/1.6.5 Development
2020-10-22 13:31:38 -06:00
Andrew Welker
f22bf60eb6 Merge pull request #461 from PepperDash/release/1.6.5
Release/1.6.5 Main
2020-10-22 13:31:25 -06:00
Andrew Welker
d1b99fdda3 Merge pull request #460 from PepperDash/feature/i18n-addition
Add lists for optional things
2020-10-22 11:26:52 -06:00
Andrew Welker
e1a4cfca4e Add lists for additional values 2020-10-22 11:23:32 -06:00
Andrew Welker
8a43824f3d Merge pull request #459 from PepperDash/hotfix/dm-rx-DMPS
Multiple fixes for DMPS and Essentials
2020-10-21 16:15:09 -06:00
Andrew Welker
b948fc7264 Merge pull request #458 from PepperDash/feature/IDspPreset
Add IDspPreset Interface
2020-10-21 16:14:54 -06:00
Trevor Payne
d9f891dfb1 removed IHasDspPreset from Tesira Classes 2020-10-21 16:59:45 -05:00
Trevor Payne
a9524bcc33 Updated Interface to be more genericized 2020-10-21 16:30:48 -05:00
Andrew Welker
4b537cb79d Fixing some things for Essentials routing and linking to bridge 2020-10-21 13:00:12 -06:00
Trevor Payne
1484c26434 added IDspPreset Interface
Implemented IDspPreset Interface on internal Tesira DSP

Resolves #457
2020-10-21 12:55:41 -05:00
Andrew Welker
36e8dc9fa5 Add check for NameSig Support 2020-10-21 11:53:52 -06:00
Andrew Welker
8feb7037aa Change cast to ACTUAL Dmps3Dmoutput 2020-10-21 11:53:32 -06:00
Andrew Welker
d8863142c7 Refactor CustomActivate & LinkToApi 2020-10-21 10:21:40 -06:00
Andrew Welker
061109c901 add method to create a rmc for DMPS chassis 2020-10-21 10:05:19 -06:00
Andrew Welker
f95b50c99d Merge pull request #445 from PepperDash/feature/I18N-Support
Add interfaces for I18N support
2020-10-20 09:56:27 -06:00
Andrew Welker
def5cc273c Merge branch 'development' into feature/I18N-Support 2020-10-19 17:04:39 -06:00
Andrew Welker
e01d2c9569 Merge pull request #450 from PepperDash/bugfix/fix-docker-image
Update docker.yml
2020-10-19 17:04:11 -06:00
Andrew Welker
415dbbb195 Update docker.yml 2020-10-16 08:16:47 -06:00
Andrew Welker
765d90214d Merge branch 'feature/I18N-Support' of https://github.com/PepperDash/Essentials into feature/I18N-Support 2020-10-15 17:00:01 -06:00
Andrew Welker
36fd1dcda9 file name change 2020-10-15 16:59:39 -06:00
Andrew Welker
812b9b731b Merge branch 'development' into feature/I18N-Support 2020-10-15 16:59:20 -06:00
Andrew Welker
7bbdf43452 add full implementation for LanguageLabel 2020-10-15 16:37:41 -06:00
Neil Dorin
81f27fcbde Merge branch 'development' into feature/I18N-Support 2020-10-15 12:41:49 -06:00
Andrew Welker
f6a826505c Merge branch 'development' into feature/I18N-Support 2020-10-13 23:39:12 -06:00
Andrew Welker
1150d9e497 add IKeyed to ILanguageLabel to easily get the key 2020-10-13 15:18:31 -06:00
Andrew Welker
cb752850ff correct interfaces 2020-10-13 13:30:29 -06:00
Andrew Welker
08c929699f #440 Updates for csproj file 2020-10-13 10:29:30 -06:00
Andrew Welker
1862090a89 #440 add interfaces 2020-10-13 09:53:18 -06:00
Neil Dorin
f036c3f1cc Merge pull request #401 from PepperDash/hotfix/unable-to-use-hightest-IR-port-number
Multiple Fixes for IR
2020-09-01 10:56:13 -06:00
90 changed files with 12265 additions and 9162 deletions

View File

@@ -32,7 +32,6 @@ jobs:
uses: actions/checkout@v2
with:
fetch-depth: 0
submodules: true
# Fetch all tags
- name: Fetch tags
run: git fetch --tags
@@ -41,12 +40,11 @@ jobs:
shell: powershell
run: |
$version = ./.github/scripts/GenerateVersionNumber.ps1
Write-Output "::set-env name=VERSION::$version"
echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
# Use the version number to set the version of the assemblies
- name: Update AssemblyInfo.cs
shell: powershell
run: |
Write-Output ${{ env.VERSION }}
./.github/scripts/UpdateAssemblyVersion.ps1 ${{ env.VERSION }}
- name: restore Nuget Packages
run: nuget install .\packages.config -OutputDirectory .\packages -ExcludeVersion
@@ -60,7 +58,7 @@ jobs:
- name: Build Solution
shell: powershell
run: |
Invoke-Expression "docker run --rm --mount type=bind,source=""$($Env:GITHUB_WORKSPACE)"",target=""c:/project"" pepperdash/sspbuilder:v1.4.1 c:\cihelpers\vsidebuild.exe -Solution ""c:\project\$($Env:SOLUTION_FILE).sln"" -BuildSolutionConfiguration $($ENV:BUILD_TYPE)"
Invoke-Expression "docker run --rm --mount type=bind,source=""$($Env:GITHUB_WORKSPACE)"",target=""c:/project"" pepperdash/sspbuilder c:\cihelpers\vsidebuild.exe -Solution ""c:\project\$($Env:SOLUTION_FILE).sln"" -BuildSolutionConfiguration $($ENV:BUILD_TYPE)"
# Zip up the output files as needed
- name: Zip Build Output
shell: powershell
@@ -123,7 +121,7 @@ jobs:
Get-ChildItem "./Version"
$version = Get-Content -Path ./Version/version.txt
Write-Host "Version: $version"
Write-Output "::set-env name=VERSION::$version"
echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
Remove-Item -Path ./Version/version.txt
Remove-Item -Path ./Version
- name: Download Build output
@@ -180,7 +178,7 @@ jobs:
Get-ChildItem "./Version"
$version = Get-Content -Path ./Version/version.txt
Write-Host "Version: $version"
Write-Output "::set-env name=VERSION::$version"
echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
Remove-Item -Path ./Version/version.txt
Remove-Item -Path ./Version
# Checkout/Create the branch
@@ -259,7 +257,7 @@ jobs:
Get-ChildItem "./Version"
$version = Get-Content -Path ./Version/version.txt
Write-Host "Version: $version"
Write-Output "::set-env name=VERSION::$version"
echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
Remove-Item -Path ./Version/version.txt
Remove-Item -Path ./Version
# Checkout/Create the branch

View File

@@ -24,25 +24,18 @@ jobs:
# First we checkout the source repo
- name: Checkout repo
uses: actions/checkout@v2
# And any submodules
- name: Checkout submodules
shell: bash
run: |
git config --global url."https://github.com/".insteadOf "git@github.com:"
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
git submodule sync --recursive
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
with:
fetch-depth: 0
# Generate the appropriate version number
- name: Set Version Number
shell: powershell
env:
TAG_NAME: ${{ github.event.release.tag_name }}
run: Write-Output "::set-env name=VERSION::$($Env:TAG_NAME)"
run: echo "VERSION=$($Env:TAG_NAME)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
# Use the version number to set the version of the assemblies
- name: Update AssemblyInfo.cs
shell: powershell
run: |
Write-Output ${{ env.VERSION }}
./.github/scripts/UpdateAssemblyVersion.ps1 ${{ env.VERSION }}
- name: restore Nuget Packages
run: nuget install .\packages.config -OutputDirectory .\packages -ExcludeVersion
@@ -101,7 +94,7 @@ jobs:
Get-ChildItem "./Version"
$version = Get-Content -Path ./Version/version.txt
Write-Host "Version: $version"
Write-Output "::set-env name=VERSION::$version"
echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
Remove-Item -Path ./Version/version.txt
Remove-Item -Path ./Version
- name: Download Build output
@@ -155,7 +148,7 @@ jobs:
Get-ChildItem "./Version"
$version = Get-Content -Path ./Version/version.txt
Write-Host "Version: $version"
Write-Output "::set-env name=VERSION::$version"
echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
Remove-Item -Path ./Version/version.txt
Remove-Item -Path ./Version
# Checkout/Create the branch
@@ -228,7 +221,7 @@ jobs:
Get-ChildItem "./Version"
$version = Get-Content -Path ./Version/version.txt
Write-Host "Version: $version"
Write-Output "::set-env name=VERSION::$version"
echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
Remove-Item -Path ./Version/version.txt
Remove-Item -Path ./Version
# Checkout main branch

Binary file not shown.

Binary file not shown.

View File

@@ -70,6 +70,14 @@ namespace PepperDash.Essentials.Bridges
/// Range reports the highest supported HDCP state level for the corresponding input card
/// </summary>
public uint HdcpSupportCapability { get; set; }
/// <summary>
/// DM Chassis Stream Input Start (1), Stop (2), Pause (3) with Feedback
/// </summary>
public uint InputStreamCardStatus { get; set; }
/// <summary>
/// DM Chassis Stream Output Start (1), Stop (2), Pause (3) with Feedback
/// </summary>
public uint OutputStreamCardStatus { get; set; }
#endregion
#region Serials
@@ -115,6 +123,8 @@ namespace PepperDash.Essentials.Bridges
InputUsb = 700; //701-899
HdcpSupportState = 1000; //1001-1199
HdcpSupportCapability = 1200; //1201-1399
InputStreamCardStatus = 1500; //1501-1532
OutputStreamCardStatus = 1600; //1601-1632
//Serial
@@ -145,6 +155,8 @@ namespace PepperDash.Essentials.Bridges
OutputEndpointOnline = OutputEndpointOnline + joinOffset;
HdcpSupportState = HdcpSupportState + joinOffset;
HdcpSupportCapability = HdcpSupportCapability + joinOffset;
InputStreamCardStatus = InputStreamCardStatus + joinOffset;
OutputStreamCardStatus = OutputStreamCardStatus + joinOffset;
OutputDisabledByHdcp = OutputDisabledByHdcp + joinOffset;
TxAdvancedIsPresent = TxAdvancedIsPresent + joinOffset;
}

View File

@@ -12,11 +12,11 @@ using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Fusion;
using PepperDash.Essentials.Devices.Common;
using PepperDash.Essentials.DM;
using PepperDash.Essentials.Fusion;
using PepperDash.Essentials.Room.Config;
//using PepperDash.Essentials.Room.MobileControl;
using Newtonsoft.Json;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
@@ -53,7 +53,7 @@ namespace PepperDash.Essentials
if (Debug.DoNotLoadOnNextBoot)
{
CrestronConsole.AddNewConsoleCommand(s => GoWithLoad(), "go", "Loads configuration file",
CrestronConsole.AddNewConsoleCommand(s => CrestronInvoke.BeginInvoke((o) => GoWithLoad()), "go", "Loads configuration file",
ConsoleAccessLevelEnum.AccessOperator);
}
@@ -290,33 +290,14 @@ namespace PepperDash.Essentials
DeviceManager.ActivateAll();
var mobileControl = DeviceManager.GetDeviceForKey("appServer") as IMobileControl;
var mobileControl = GetMobileControlDevice();
if (mobileControl == null) return;
mobileControl.LinkSystemMonitorToAppServer();
//LinkSystemMonitorToAppServer();
}
//void LinkSystemMonitorToAppServer()
//{
// var sysMon = DeviceManager.GetDeviceForKey("systemMonitor") as PepperDash.Essentials.Core.Monitoring.SystemMonitorController;
// var appServer = DeviceManager.GetDeviceForKey("appServer") as MobileControlSystemController;
// if (sysMon != null && appServer != null)
// {
// var key = sysMon.Key + "-" + appServer.Key;
// var messenger = new PepperDash.Essentials.AppServer.Messengers.SystemMonitorMessenger
// (key, sysMon, "/device/systemMonitor");
// messenger.RegisterWithAppServer(appServer);
// DeviceManager.AddDevice(messenger);
// }
//}
/// <summary>
/// Reads all devices from config and adds them to DeviceManager
/// </summary>
@@ -394,11 +375,6 @@ namespace PepperDash.Essentials
if (newDev == null)
newDev = PepperDash.Essentials.Core.DeviceFactory.GetDevice(devConf);
//
//if (newDev == null)
// newDev = PepperDash.Essentials.Devices.Displays.DisplayDeviceFactory.GetDevice(devConf);
//
if (newDev != null)
DeviceManager.AddDevice(newDev);
else
@@ -461,14 +437,10 @@ namespace PepperDash.Essentials
DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion");
DeviceManager.AddDevice(new Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase((EssentialsHuddleSpaceRoom)room, 0xf1));
DeviceManager.AddDevice(new Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase(room, 0xf1));
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge...");
// Mobile Control bridge
//var bridge = new MobileConrolEssentialsHuddleSpaceRoomBridge(room as EssentialsHuddleSpaceRoom);
//AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present
//DeviceManager.AddDevice(bridge);
CreateMobileControlBridge(room);
}
@@ -480,10 +452,18 @@ namespace PepperDash.Essentials
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, 0xf1));
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge...");
// Mobile Control bridge
//var bridge = new MobileConrolEssentialsHuddleSpaceRoomBridge(room);
//AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present
//DeviceManager.AddDevice(bridge);
CreateMobileControlBridge(room);
}
else if (room is EssentialsTechRoom)
{
DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice,
"Room is EssentialsTechRoom, Attempting to add to DeviceManager with Fusion");
DeviceManager.AddDevice(new EssentialsHuddleSpaceFusionSystemControllerBase(room, 0xF1));
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge");
CreateMobileControlBridge(room);
}
@@ -504,40 +484,55 @@ namespace PepperDash.Essentials
private static void CreateMobileControlBridge(EssentialsRoomBase room)
{
var mobileControl = DeviceManager.GetDeviceForKey("appServer") as IMobileControl;
var mobileControl = GetMobileControlDevice();
if (mobileControl == null) return;
mobileControl.CreateMobileControlRoomBridge(room);
mobileControl.CreateMobileControlRoomBridge(room, mobileControl);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Mobile Control Bridge Added...");
}
/// <summary>
/// Helps add the post activation steps that link bridges to main controller
/// </summary>
/// <param name="bridge"></param>
//void AddBridgePostActivationHelper(MobileControlBridgeBase bridge)
//{
// bridge.AddPostActivationAction(() =>
// {
// var parent = DeviceManager.AllDevices.FirstOrDefault(d => d.Key == "appServer") as MobileControlSystemController;
// if (parent == null)
// {
// Debug.Console(0, bridge, "ERROR: Cannot connect app server room bridge. System controller not present");
// return;
// }
// Debug.Console(0, bridge, "Linking to parent controller");
// bridge.AddParent(parent);
// parent.AddBridge(bridge);
// });
//}
private static IMobileControl GetMobileControlDevice()
{
var mobileControlList = DeviceManager.AllDevices.OfType<IMobileControl>().ToList();
if (mobileControlList.Count > 1)
{
Debug.Console(0, Debug.ErrorLogLevel.Warning,
"Multiple instances of Mobile Control Server found.");
return null;
}
if (mobileControlList.Count > 0)
{
return mobileControlList[0];
}
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Mobile Control not enabled for this system");
return null;
}
/// <summary>
/// Fires up a logo server if not already running
/// </summary>
void LoadLogoServer()
{
if (ConfigReader.ConfigObject.Rooms == null)
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "No rooms configured. Bypassing Logo server startup.");
return;
}
if (
!ConfigReader.ConfigObject.Rooms.Any(
CheckRoomConfig))
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "No rooms configured to use system Logo server. Bypassing Logo server startup");
return;
}
try
{
LogoServer = new HttpLogoServer(8080, Global.DirectorySeparator + "html" + Global.DirectorySeparator + "logo");
@@ -547,5 +542,38 @@ namespace PepperDash.Essentials
Debug.Console(0, Debug.ErrorLogLevel.Notice, "NOTICE: Logo server cannot be started. Likely already running in another program");
}
}
private bool CheckRoomConfig(DeviceConfig c)
{
string logoDark = null;
string logoLight = null;
string logo = null;
try
{
if (c.Properties["logoDark"] != null)
{
logoDark = c.Properties["logoDark"].Value<string>("type");
}
if (c.Properties["logoLight"] != null)
{
logoLight = c.Properties["logoLight"].Value<string>("type");
}
if (c.Properties["logo"] != null)
{
logo = c.Properties["logo"].Value<string>("type");
}
return ((logoDark != null && logoDark == "system") ||
(logoLight != null && logoLight == "system") || (logo != null && logo == "system"));
}
catch (Exception e)
{
Debug.Console(1, Debug.ErrorLogLevel.Notice, "Unable to find logo information in any room config");
return false;
}
}
}
}

View File

@@ -273,15 +273,18 @@ namespace PepperDash.Essentials.Fusion
// Display to fusion room sigs
FusionRoom.DisplayPowerOn.OutputSig.UserObject = dispPowerOnAction;
FusionRoom.DisplayPowerOff.OutputSig.UserObject = dispPowerOffAction;
defaultDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
var defaultDisplayTwoWay = defaultDisplay as IHasPowerControlWithFeedback;
if (defaultDisplayTwoWay != null)
{
defaultDisplayTwoWay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
}
if (defaultDisplay is IDisplayUsage)
(defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
MapDisplayToRoomJoins(1, 158, defaultDisplay);
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key));
//Check for existing asset in GUIDs collection
@@ -302,8 +305,18 @@ namespace PepperDash.Essentials.Fusion
var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
defaultDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
// NO!! display.PowerIsOn.LinkComplementInputSig(dispAsset.PowerOff.InputSig);
var defaultTwoWayDisplay = defaultDisplay as IHasPowerControlWithFeedback;
if (defaultTwoWayDisplay != null)
{
defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
if (defaultDisplay is IDisplayUsage)
(defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
}
// Use extension methods
dispAsset.TrySetMakeModel(defaultDisplay);
dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay);
@@ -325,12 +338,17 @@ namespace PepperDash.Essentials.Fusion
// Power on
var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig);
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b => { if (!b) display.PowerOn(); });
display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
// Power Off
var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off", eSigIoMask.InputOutputSig);
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b => { if (!b) display.PowerOff(); }); ;
display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
var displayTwoWay = display as IHasPowerControlWithFeedback;
if (displayTwoWay != null)
{
displayTwoWay.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
displayTwoWay.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
}
// Current Source
var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig);

View File

@@ -71,7 +71,7 @@
<HintPath>..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="PepperDash_Core, Version=1.0.41.31808, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="PepperDash_Core, Version=1.0.42.30563, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll</HintPath>
</Reference>
@@ -141,11 +141,13 @@
<Compile Include="Room\Config\EssentialsHuddleRoomPropertiesConfig.cs" />
<Compile Include="Room\Config\EssentialsHuddleVtc1PropertiesConfig.cs" />
<Compile Include="Room\Config\EssentialsRoomEmergencyConfig.cs" />
<Compile Include="Room\Config\EssentialsTechRoomConfig.cs" />
<Compile Include="Room\Emergency\EsentialsRoomEmergencyContactClosure.cs" />
<Compile Include="Room\Types\EssentialsDualDisplayRoom.cs" />
<Compile Include="Room\Types\EssentialsHuddleVtc1Room.cs" />
<Compile Include="Room\Types\EssentialsNDisplayRoomBase.cs" />
<Compile Include="Room\Config\EssentialsRoomConfig.cs" />
<Compile Include="Room\Types\EssentialsTechRoom.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsEnvironmentDriver.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsLightingDriver.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsShadeDriver.cs" />

View File

@@ -22,30 +22,25 @@ namespace PepperDash.Essentials.Room.Config
public static Device GetRoomObject(DeviceConfig roomConfig)
{
var typeName = roomConfig.Type.ToLower();
if (typeName == "huddle")
{
var huddle = new EssentialsHuddleSpaceRoom(roomConfig);
return huddle;
return new EssentialsHuddleSpaceRoom(roomConfig);
}
else if (typeName == "huddlevtc1")
{
var rm = new EssentialsHuddleVtc1Room(roomConfig);
return rm;
}
else if (typeName == "ddvc01Bridge")
{
return new Device(roomConfig.Key, roomConfig.Name); // placeholder device that does nothing.
}
else if (typeName == "dualdisplay")
{
var rm = new EssentialsDualDisplayRoom(roomConfig);
if (typeName == "huddlevtc1")
{
return new EssentialsHuddleVtc1Room(roomConfig);
}
if (typeName == "ddvc01bridge")
{
return new Device(roomConfig.Key, roomConfig.Name); // placeholder device that does nothing.
}
if (typeName == "dualdisplay")
{
return new EssentialsDualDisplayRoom(roomConfig);
}
return rm;
}
return null;
return typeName != "techroom" ? null : new EssentialsTechRoom(roomConfig);
}
/// <summary>

View File

@@ -0,0 +1,40 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Room.Config
{
public class EssentialsTechRoomConfig
{
[JsonProperty("dummySourceKey")]
public string DummySourceKey { get; set; }
[JsonProperty("displays")]
public List<string> Displays;
[JsonProperty("tuners")]
public List<string> Tuners;
[JsonProperty("userPin")]
public string UserPin;
[JsonProperty("techPin")]
public string TechPin;
[JsonProperty("presetsFileName")]
public string PresetsFileName;
[JsonProperty("scheduledEvents")]
public List<ScheduledEventConfig> ScheduledEvents;
[JsonProperty("isPrimary")] public bool IsPrimary;
[JsonProperty("isTvPresetsProvider")] public bool IsTvPresetsProvider;
public EssentialsTechRoomConfig()
{
Displays = new List<string>();
Tuners = new List<string>();
ScheduledEvents = new List<ScheduledEventConfig>();
}
}
}

View File

@@ -283,19 +283,23 @@ namespace PepperDash.Essentials
if (disp != null)
{
// Link power, warming, cooling to display
disp.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
var dispTwoWay = disp as IHasPowerControlWithFeedback;
if (dispTwoWay != null)
{
dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (!disp.PowerIsOnFeedback.BoolValue)
disp.CurrentSourceInfo = null;
OnFeedback.FireUpdate();
}
if (disp.PowerIsOnFeedback.BoolValue)
{
SetDefaultLevels();
}
};
if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
{
if (!dispTwoWay.PowerIsOnFeedback.BoolValue)
disp.CurrentSourceInfo = null;
OnFeedback.FireUpdate();
}
if (dispTwoWay.PowerIsOnFeedback.BoolValue)
{
SetDefaultLevels();
}
};
}
disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
{
@@ -579,8 +583,8 @@ namespace PepperDash.Essentials
if (dest is IPower)
(dest as IPower).PowerOff();
if (dest is IHasPowerControl)
(dest as IHasPowerControl).PowerOff();
}
else
{

View File

@@ -176,15 +176,19 @@ namespace PepperDash.Essentials
if (disp != null)
{
// Link power, warming, cooling to display
disp.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
{
if (!disp.PowerIsOnFeedback.BoolValue)
CurrentSourceInfo = null;
OnFeedback.FireUpdate();
}
};
var dispTwoWay = disp as IHasPowerControlWithFeedback;
if (dispTwoWay != null)
{
dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
{
if (!dispTwoWay.PowerIsOnFeedback.BoolValue)
CurrentSourceInfo = null;
OnFeedback.FireUpdate();
}
};
}
disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
{
@@ -495,8 +499,8 @@ namespace PepperDash.Essentials
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
{
dest.ReleaseRoute();
if (dest is IPower)
(dest as IPower).PowerOff();
if (dest is IHasPowerControl)
(dest as IHasPowerControl).PowerOff();
}
else
{

View File

@@ -190,6 +190,12 @@ namespace PepperDash.Essentials
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.DidChange);
var vc = VideoCodec as IHasExternalSourceSwitching;
if (vc != null)
{
vc.SetSelectedSource(CurrentSourceInfoKey);
}
}
}
SourceListItem _CurrentSourceInfo;
@@ -273,19 +279,23 @@ namespace PepperDash.Essentials
if (disp != null)
{
// Link power, warming, cooling to display
disp.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
var dispTwoWay = disp as IHasPowerControlWithFeedback;
if (dispTwoWay != null)
{
dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (!disp.PowerIsOnFeedback.BoolValue)
CurrentSourceInfo = null;
OnFeedback.FireUpdate();
}
if (disp.PowerIsOnFeedback.BoolValue)
{
SetDefaultLevels();
}
};
if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
{
if (!dispTwoWay.PowerIsOnFeedback.BoolValue)
CurrentSourceInfo = null;
OnFeedback.FireUpdate();
}
if (dispTwoWay.PowerIsOnFeedback.BoolValue)
{
SetDefaultLevels();
}
};
}
disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
{
@@ -383,6 +393,8 @@ namespace PepperDash.Essentials
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting down room");
RunRouteAction("roomOff");
VideoCodec.StopSharing();
VideoCodec.StandbyActivate();
}
/// <summary>
@@ -580,6 +592,19 @@ namespace PepperDash.Essentials
OnFeedback.FireUpdate();
if (OnFeedback.BoolValue)
{
if (VideoCodec.UsageTracker.InUseTracker.InUseFeedback.BoolValue)
{
Debug.Console(1, this, "Video Codec in use, deactivating standby on codec");
}
if (VideoCodec.StandbyIsOnFeedback.BoolValue)
{
VideoCodec.StandbyDeactivate();
}
}
// report back when done
if (successCallback != null)
successCallback();
@@ -640,8 +665,9 @@ namespace PepperDash.Essentials
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
{
dest.ReleaseRoute();
if (dest is IPower)
(dest as IPower).PowerOff();
if (dest is IHasPowerControl)
(dest as IHasPowerControl).PowerOff();
}
else
{
@@ -693,37 +719,44 @@ namespace PepperDash.Essentials
}
/// <summary>
/// Setup the external sources for the Cisco Touch 10 devices that support IHasExternalSourceSwitch
/// </summary>
private void SetCodecExternalSources()
{
var videoCodecWithExternalSwitching = VideoCodec as IHasExternalSourceSwitching;
/// <summary>
/// Setup the external sources for the Cisco Touch 10 devices that support IHasExternalSourceSwitch
/// </summary>
private void SetCodecExternalSources()
{
var videoCodecWithExternalSwitching = VideoCodec as IHasExternalSourceSwitching;
if (videoCodecWithExternalSwitching == null)
{
return;
}
if (videoCodecWithExternalSwitching == null || !videoCodecWithExternalSwitching.ExternalSourceListEnabled)
{
return;
}
string codecTieLine = ConfigReader.ConfigObject.TieLines.SingleOrDefault(x => x.DestinationKey == VideoCodec.Key).DestinationPort;
videoCodecWithExternalSwitching.ClearExternalSources();
videoCodecWithExternalSwitching.RunRouteAction = RunRouteAction;
var srcList = ConfigReader.ConfigObject.SourceLists.SingleOrDefault(x => x.Key == SourceListKey).Value.OrderBy(kv => kv.Value.Order); ;
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;
foreach (var kvp in srcList)
{
var srcConfig = kvp.Value;
videoCodecWithExternalSwitching.ClearExternalSources();
videoCodecWithExternalSwitching.RunRouteAction = RunRouteAction;
var srcList = ConfigReader.ConfigObject.SourceLists.SingleOrDefault(x => x.Key == SourceListKey).Value.OrderBy(kv => kv.Value.Order); ;
if (kvp.Key != DefaultCodecRouteString && kvp.Key != "roomOff")
{
foreach (var kvp in srcList)
{
var srcConfig = kvp.Value;
videoCodecWithExternalSwitching.AddExternalSource(codecTieLine, kvp.Key, srcConfig.PreferredName, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceType.desktop);
videoCodecWithExternalSwitching.SetExternalSourceState(kvp.Key, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceMode.Ready);
}
}
}
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()
{

View File

@@ -0,0 +1,473 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Crestron.SimplSharp;
using Crestron.SimplSharp.Scheduler;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Core.Presets;
using PepperDash.Essentials.Devices.Common;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials
{
public class EssentialsTechRoom : EssentialsRoomBase, ITvPresetsProvider, IBridgeAdvanced, IRunDirectRouteAction
{
private readonly EssentialsTechRoomConfig _config;
private readonly Dictionary<string, TwoWayDisplayBase> _displays;
private readonly DevicePresetsModel _tunerPresets;
private readonly Dictionary<string, IRSetTopBoxBase> _tuners;
private Dictionary<string, string> _currentPresets;
private ScheduledEventGroup _roomScheduledEventGroup;
/// <summary>
///
/// </summary>
protected override Func<bool> IsWarmingFeedbackFunc
{
get
{
return () =>
{
return _displays.All(kv => kv.Value.IsWarmingUpFeedback.BoolValue);
};
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsCoolingFeedbackFunc
{
get
{
return () =>
{
return _displays.All(kv => kv.Value.IsCoolingDownFeedback.BoolValue);
};
}
}
public EssentialsTechRoom(DeviceConfig config) : base(config)
{
_config = config.Properties.ToObject<EssentialsTechRoomConfig>();
_tunerPresets = new DevicePresetsModel(String.Format("{0}-presets", config.Key), _config.PresetsFileName);
_tunerPresets.SetFileName(_config.PresetsFileName);
_tunerPresets.PresetRecalled += TunerPresetsOnPresetRecalled;
_tuners = GetDevices<IRSetTopBoxBase>(_config.Tuners);
_displays = GetDevices<TwoWayDisplayBase>(_config.Displays);
RoomPowerIsOnFeedback = new BoolFeedback(() => RoomPowerIsOn);
SetUpTunerPresetsFeedback();
SubscribeToDisplayFeedbacks();
CreateOrUpdateScheduledEvents();
}
public Dictionary<string, StringFeedback> CurrentPresetsFeedbacks { get; private set; }
public Dictionary<string, IRSetTopBoxBase> Tuners
{
get { return _tuners; }
}
public Dictionary<string, TwoWayDisplayBase> Displays
{
get { return _displays; }
}
public BoolFeedback RoomPowerIsOnFeedback { get; private set; }
public bool RoomPowerIsOn
{
get { return _displays.All(kv => kv.Value.PowerIsOnFeedback.BoolValue); }
}
#region ITvPresetsProvider Members
public DevicePresetsModel TvPresets
{
get { return _tunerPresets; }
}
#endregion
private void TunerPresetsOnPresetRecalled(ISetTopBoxNumericKeypad device, string channel)
{
if (!_currentPresets.ContainsKey(device.Key))
{
return;
}
_currentPresets[device.Key] = channel;
if (!CurrentPresetsFeedbacks.ContainsKey(device.Key))
{
CurrentPresetsFeedbacks[device.Key].FireUpdate();
}
}
private void SetUpTunerPresetsFeedback()
{
_currentPresets = new Dictionary<string, string>();
CurrentPresetsFeedbacks = new Dictionary<string, StringFeedback>();
foreach (var setTopBox in _tuners)
{
var tuner = setTopBox.Value;
_currentPresets.Add(tuner.Key, String.Empty);
CurrentPresetsFeedbacks.Add(tuner.Key, new StringFeedback(() => _currentPresets[tuner.Key]));
}
}
private void SubscribeToDisplayFeedbacks()
{
foreach (var display in _displays)
{
display.Value.PowerIsOnFeedback.OutputChange +=
(sender, args) =>
{
RoomPowerIsOnFeedback.InvokeFireUpdate();
IsWarmingUpFeedback.InvokeFireUpdate();
IsCoolingDownFeedback.InvokeFireUpdate();
};
}
}
private void CreateOrUpdateScheduledEvents()
{
var eventsConfig = _config.ScheduledEvents;
GetOrCreateScheduleGroup();
foreach (var eventConfig in eventsConfig)
{
CreateOrUpdateSingleEvent(eventConfig);
}
_roomScheduledEventGroup.UserGroupCallBack += HandleScheduledEvent;
}
private void GetOrCreateScheduleGroup()
{
if (_roomScheduledEventGroup == null)
{
_roomScheduledEventGroup = Scheduler.GetEventGroup(Key) ?? new ScheduledEventGroup(Key);
Scheduler.AddEventGroup(_roomScheduledEventGroup);
}
_roomScheduledEventGroup.RetrieveAllEvents();
}
private void CreateOrUpdateSingleEvent(ScheduledEventConfig scheduledEvent)
{
if (!_roomScheduledEventGroup.ScheduledEvents.ContainsKey(scheduledEvent.Key))
{
SchedulerUtilities.CreateEventFromConfig(scheduledEvent, _roomScheduledEventGroup, HandleScheduledEvent);
return;
}
var roomEvent = _roomScheduledEventGroup.ScheduledEvents[scheduledEvent.Key];
if (!SchedulerUtilities.CheckEventTimeForMatch(roomEvent, DateTime.Parse(scheduledEvent.Time)) &&
!SchedulerUtilities.CheckEventRecurrenceForMatch(roomEvent, scheduledEvent.Days))
{
return;
}
Debug.Console(1, this,
"Existing event does not match new config properties. Deleting existing event '{0}' and creating new event from configuration",
roomEvent.Name);
_roomScheduledEventGroup.DeleteEvent(roomEvent);
SchedulerUtilities.CreateEventFromConfig(scheduledEvent, _roomScheduledEventGroup, HandleScheduledEvent);
}
public void AddOrUpdateScheduledEvent(ScheduledEventConfig scheduledEvent)
{
//update config based on key of scheduleEvent
GetOrCreateScheduleGroup();
var existingEventIndex = _config.ScheduledEvents.FindIndex((e) => e.Key == scheduledEvent.Key);
if (existingEventIndex < 0)
{
_config.ScheduledEvents.Add(scheduledEvent);
}
else
{
_config.ScheduledEvents[existingEventIndex] = scheduledEvent;
}
//create or update event based on config
CreateOrUpdateSingleEvent(scheduledEvent);
//save config
Config.Properties = JToken.FromObject(_config);
CustomSetConfig(Config);
//Fire Event
OnScheduledEventUpdate();
}
public List<ScheduledEventConfig> GetScheduledEvents()
{
return _config.ScheduledEvents ?? new List<ScheduledEventConfig>();
}
private void OnScheduledEventUpdate()
{
var handler = ScheduledEventsChanged;
if (handler == null)
{
return;
}
handler(this, new ScheduledEventEventArgs {ScheduledEvents = _config.ScheduledEvents});
}
public event EventHandler<ScheduledEventEventArgs> ScheduledEventsChanged;
private void HandleScheduledEvent(ScheduledEvent schevent, ScheduledEventCommon.eCallbackReason type)
{
var eventConfig = _config.ScheduledEvents.FirstOrDefault(e => e.Key == schevent.Name);
if (eventConfig == null)
{
Debug.Console(1, this, "Event with name {0} not found", schevent.Name);
return;
}
Debug.Console(1, this, "Running actions for event {0}", schevent.Name);
if (eventConfig.Acknowledgeable)
{
schevent.Acknowledge();
}
CrestronInvoke.BeginInvoke((o) =>
{
Debug.Console(2, this, "There are {0} actions to execute for this event.", eventConfig.Actions.Count);
foreach (var a in eventConfig.Actions)
{
Debug.Console(2, this,
@"Attempting to run action:
DeviceKey: {0}
MethodName: {1}
Params: {2}"
, a.DeviceKey, a.MethodName, a.Params);
DeviceJsonApi.DoDeviceAction(a);
}
});
}
public void RoomPowerOn()
{
Debug.Console(2, this, "Room Powering On");
var dummySource = DeviceManager.GetDeviceForKey(_config.DummySourceKey) as IRoutingOutputs;
if (dummySource == null)
{
Debug.Console(1, this, "Unable to get source with key: {0}", _config.DummySourceKey);
return;
}
foreach (var display in _displays)
{
RunDirectRoute(dummySource, display.Value);
}
}
public void RoomPowerOff()
{
Debug.Console(2, this, "Room Powering Off");
foreach (var display in _displays)
{
display.Value.PowerOff();
}
}
private Dictionary<string, T> GetDevices<T>(ICollection<string> config) where T : IKeyed
{
try
{
var returnValue = DeviceManager.AllDevices.OfType<T>()
.Where(d => config.Contains(d.Key))
.ToDictionary(d => d.Key, d => d);
return returnValue;
}
catch
{
Debug.Console(0, this, Debug.ErrorLogLevel.Error,
"Error getting devices. Check Essentials Configuration");
return null;
}
}
#region Overrides of EssentialsRoomBase
protected override Func<bool> OnFeedbackFunc
{
get { return () => RoomPowerIsOn; }
}
protected override void EndShutdown()
{
}
public override void SetDefaultLevels()
{
}
public override void PowerOnToDefaultOrLastSource()
{
}
public override bool RunDefaultPresentRoute()
{
return false;
}
public override void RoomVacatedForTimeoutPeriod(object o)
{
}
#endregion
#region Implementation of IBridgeAdvanced
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new EssentialsTechRoomJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!String.IsNullOrEmpty(joinMapSerialized))
{
joinMap = JsonConvert.DeserializeObject<EssentialsTechRoomJoinMap>(joinMapSerialized);
}
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
uint i;
if (_config.IsPrimary)
{
i = 0;
foreach (var feedback in CurrentPresetsFeedbacks)
{
feedback.Value.LinkInputSig(trilist.StringInput[(uint) (joinMap.CurrentPreset.JoinNumber + i)]);
i++;
}
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine)
{
return;
}
foreach (var feedback in CurrentPresetsFeedbacks)
{
feedback.Value.FireUpdate();
}
};
return;
}
i = 0;
foreach (var setTopBox in _tuners)
{
var tuner = setTopBox;
trilist.SetStringSigAction(joinMap.CurrentPreset.JoinNumber + i, s => _tunerPresets.Dial(s, tuner.Value));
i++;
}
}
#endregion
private class EssentialsTechRoomJoinMap : JoinMapBaseAdvanced
{
[JoinName("currentPreset")]
public JoinDataComplete CurrentPreset = new JoinDataComplete(new JoinData {JoinNumber = 1, JoinSpan = 16},
new JoinMetadata {Description = "Current Tuner Preset", JoinType = eJoinType.Serial});
public EssentialsTechRoomJoinMap(uint joinStart) : base(joinStart, typeof(EssentialsTechRoomJoinMap))
{
}
}
#region IRunDirectRouteAction Members
private void RunDirectRoute(IRoutingOutputs source, IRoutingSink dest)
{
if (dest == null)
{
Debug.Console(1, this, "Cannot route, unknown destination '{0}'", dest.Key);
return;
}
if (source == null)
{
dest.ReleaseRoute();
if (dest is IHasPowerControl)
(dest as IHasPowerControl).PowerOff();
}
else
{
dest.ReleaseAndMakeRoute(source, eRoutingSignalType.Video);
}
}
/// <summary>
/// Attempts to route directly between a source and destination
/// </summary>
/// <param name="sourceKey"></param>
/// <param name="destinationKey"></param>
public void RunDirectRoute(string sourceKey, string destinationKey)
{
IRoutingSink dest = null;
dest = DeviceManager.GetDeviceForKey(destinationKey) as IRoutingSink;
var source = DeviceManager.GetDeviceForKey(sourceKey) as IRoutingOutputs;
if (source == null || dest == null)
{
Debug.Console(1, this, "Cannot route unknown source or destination '{0}' to {1}", sourceKey, destinationKey);
return;
}
RunDirectRoute(source, dest);
}
#endregion
}
public class ScheduledEventEventArgs : EventArgs
{
public List<ScheduledEventConfig> ScheduledEvents;
}
}

View File

@@ -1,13 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Net.Http;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials
{
@@ -16,12 +13,12 @@ namespace PepperDash.Essentials
/// <summary>
///
/// </summary>
HttpServer Server;
readonly HttpServer _server;
/// <summary>
///
/// </summary>
string FileDirectory;
readonly string _fileDirectory;
/// <summary>
///
@@ -45,18 +42,17 @@ namespace PepperDash.Essentials
//{ ".js", "application/javascript" },
//{ ".json", "application/json" },
//{ ".map", "application/x-navimap" },
{ ".pdf", "application.pdf" },
{ ".pdf", "application/pdf" },
{ ".png", "image/png" },
//{ ".txt", "text/plain" },
};
Server = new HttpServer();
Server.Port = port;
FileDirectory = directory;
Server.OnHttpRequest += new OnHttpRequestHandler(Server_OnHttpRequest);
Server.Open();
_server = new HttpServer {Port = port};
_fileDirectory = directory;
_server.OnHttpRequest += Server_OnHttpRequest;
_server.Open();
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler;
}
/// <summary>
@@ -67,27 +63,40 @@ namespace PepperDash.Essentials
var path = args.Request.Path;
Debug.Console(2, "HTTP Request with path: '{0}'", args.Request.Path);
if (File.Exists(FileDirectory + path))
try
{
string filePath = path.Replace('/', '\\');
string localPath = string.Format(@"{0}{1}", FileDirectory, filePath);
Debug.Console(2, "HTTP Logo Server attempting to find file: '{0}'", localPath);
if (File.Exists(localPath))
if (File.Exists(_fileDirectory + path))
{
args.Response.Header.ContentType = GetContentType(new FileInfo(localPath).Extension);
args.Response.ContentStream = new FileStream(localPath, FileMode.Open, FileAccess.Read);
var filePath = path.Replace('/', '\\');
var localPath = string.Format(@"{0}{1}", _fileDirectory, filePath);
Debug.Console(2, "HTTP Logo Server attempting to find file: '{0}'", localPath);
if (File.Exists(localPath))
{
args.Response.Header.ContentType = GetContentType(new FileInfo(localPath).Extension);
args.Response.ContentStream = new FileStream(localPath, FileMode.Open, FileAccess.Read);
}
else
{
Debug.Console(2, "HTTP Logo Server Cannot find file '{0}'", localPath);
args.Response.ContentString = string.Format("Not found: '{0}'", filePath);
args.Response.Code = 404;
}
}
else
{
Debug.Console(2, "HTTP Logo Server Cannot find file '{0}'", localPath);
args.Response.ContentString = string.Format("Not found: '{0}'", filePath);
Debug.Console(2, "HTTP Logo Server: '{0}' does not exist", _fileDirectory + path);
args.Response.ContentString = string.Format("Not found: '{0}'", _fileDirectory + path);
args.Response.Code = 404;
}
}
else
catch (Exception ex)
{
Debug.Console(2, "HTTP Logo Server: '{0}' does not exist", FileDirectory + path);
Debug.Console(0, Debug.ErrorLogLevel.Error, "Exception getting file: {0}", ex.Message);
Debug.Console(0, Debug.ErrorLogLevel.Error, "Stack Trace: {0}", ex.StackTrace);
args.Response.Code = 400;
args.Response.ContentString = string.Format("invalid request");
}
}
@@ -97,7 +106,7 @@ namespace PepperDash.Essentials
void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
{
if (programEventType == eProgramStatusEventType.Stopping)
Server.Close();
_server.Close();
}
/// <summary>
@@ -107,11 +116,7 @@ namespace PepperDash.Essentials
/// <returns></returns>
public static string GetContentType(string extension)
{
string type;
if (ExtensionContentTypes.ContainsKey(extension))
type = ExtensionContentTypes[extension];
else
type = "text/plain";
var type = ExtensionContentTypes.ContainsKey(extension) ? ExtensionContentTypes[extension] : "text/plain";
return type;
}
}

View File

@@ -305,9 +305,9 @@ namespace PepperDash.Essentials
TriList.SetSigFalseAction(UIBoolJoin.ShowPowerOffPress, EndMeetingPress);
TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () =>
{
if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IPower)
(CurrentRoom.DefaultDisplay as IPower).PowerToggle();
{
if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IHasPowerControl)
(CurrentRoom.DefaultDisplay as IHasPowerControl).PowerToggle();
});
base.Show();
@@ -984,8 +984,8 @@ namespace PepperDash.Essentials
(previousDev as IDvr).UnlinkButtons(TriList);
if (previousDev is INumericKeypad)
(previousDev as INumericKeypad).UnlinkButtons(TriList);
if (previousDev is IPower)
(previousDev as IPower).UnlinkButtons(TriList);
if (previousDev is IHasPowerControl)
(previousDev as IHasPowerControl).UnlinkButtons(TriList);
if (previousDev is ITransport)
(previousDev as ITransport).UnlinkButtons(TriList);
//if (previousDev is IRadio)
@@ -1044,8 +1044,8 @@ namespace PepperDash.Essentials
(dev as IDvr).LinkButtons(TriList);
if (dev is INumericKeypad)
(dev as INumericKeypad).LinkButtons(TriList);
if (dev is IPower)
(dev as IPower).LinkButtons(TriList);
if (dev is IHasPowerControl)
(dev as IHasPowerControl).LinkButtons(TriList);
if (dev is ITransport)
(dev as ITransport).LinkButtons(TriList);
//if (dev is IRadio)

View File

@@ -319,8 +319,8 @@ namespace PepperDash.Essentials
TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () =>
{
if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IPower)
(CurrentRoom.DefaultDisplay as IPower).PowerToggle();
if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IHasPowerControl)
(CurrentRoom.DefaultDisplay as IHasPowerControl).PowerToggle();
});
SetupNextMeetingTimer();
@@ -1293,8 +1293,8 @@ namespace PepperDash.Essentials
(previousDev as IDvr).UnlinkButtons(TriList);
if (previousDev is INumericKeypad)
(previousDev as INumericKeypad).UnlinkButtons(TriList);
if (previousDev is IPower)
(previousDev as IPower).UnlinkButtons(TriList);
if (previousDev is IHasPowerControl)
(previousDev as IHasPowerControl).UnlinkButtons(TriList);
if (previousDev is ITransport)
(previousDev as ITransport).UnlinkButtons(TriList);
}
@@ -1351,8 +1351,8 @@ namespace PepperDash.Essentials
(dev as IDvr).LinkButtons(TriList);
if (dev is INumericKeypad)
(dev as INumericKeypad).LinkButtons(TriList);
if (dev is IPower)
(dev as IPower).LinkButtons(TriList);
if (dev is IHasPowerControl)
(dev as IHasPowerControl).LinkButtons(TriList);
if (dev is ITransport)
(dev as ITransport).LinkButtons(TriList);
}

View File

@@ -78,7 +78,7 @@ namespace PepperDash.Essentials.Core.Bridges
/// <summary>
/// Bridge API using EISC
/// </summary>
public class EiscApiAdvanced : BridgeApi
public class EiscApiAdvanced : BridgeApi, ICommunicationMonitor
{
public EiscApiPropertiesConfig PropertiesConfig { get; private set; }
@@ -98,13 +98,35 @@ namespace PepperDash.Essentials.Core.Bridges
Eisc.SigChange += Eisc_SigChange;
CommunicationMonitor = new CrestronGenericBaseCommunicationMonitor(this, Eisc, 120000, 300000);
AddPostActivationAction(LinkDevices);
AddPostActivationAction(LinkRooms);
AddPostActivationAction(RegisterEisc);
}
public override bool CustomActivate()
{
CommunicationMonitor.Start();
return base.CustomActivate();
}
public override bool Deactivate()
{
CommunicationMonitor.Stop();
return base.Deactivate();
}
private void LinkDevices()
{
Debug.Console(1, this, "Linking Devices...");
if (PropertiesConfig.Devices == null)
{
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "No devices linked to this bridge");
return;
}
foreach (var d in PropertiesConfig.Devices)
{
var device = DeviceManager.GetDeviceForKey(d.DeviceKey);
@@ -130,6 +152,14 @@ namespace PepperDash.Essentials.Core.Bridges
bridge.LinkToApi(Eisc, d.JoinStart, d.JoinMapKey, this);
}
}
}
private void RegisterEisc()
{
if (Eisc.Registered)
{
return;
}
var registerResult = Eisc.Register();
@@ -142,6 +172,31 @@ namespace PepperDash.Essentials.Core.Bridges
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "EISC registration successful");
}
public void LinkRooms()
{
Debug.Console(1, this, "Linking Rooms...");
if (PropertiesConfig.Rooms == null)
{
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "No rooms linked to this bridge.");
return;
}
foreach (var room in PropertiesConfig.Rooms)
{
var rm = DeviceManager.GetDeviceForKey(room.RoomKey) as IBridgeAdvanced;
if (rm == null)
{
Debug.Console(1, this, Debug.ErrorLogLevel.Notice,
"Room {0} does not implement IBridgeAdvanced. Skipping...", room.RoomKey);
continue;
}
rm.LinkToApi(Eisc, room.JoinStart, room.JoinMapKey, this);
}
}
/// <summary>
/// Adds a join map
/// </summary>
@@ -280,6 +335,12 @@ namespace PepperDash.Essentials.Core.Bridges
Debug.Console(2, this, "Error in Eisc_SigChange handler: {0}", e);
}
}
#region Implementation of ICommunicationMonitor
public StatusMonitorBase CommunicationMonitor { get; private set; }
#endregion
}
public class EiscApiPropertiesConfig
@@ -290,6 +351,9 @@ namespace PepperDash.Essentials.Core.Bridges
[JsonProperty("devices")]
public List<ApiDevicePropertiesConfig> Devices { get; set; }
[JsonProperty("rooms")]
public List<ApiRoomPropertiesConfig> Rooms { get; set; }
public class ApiDevicePropertiesConfig
{
@@ -303,6 +367,18 @@ namespace PepperDash.Essentials.Core.Bridges
public string JoinMapKey { get; set; }
}
public class ApiRoomPropertiesConfig
{
[JsonProperty("roomKey")]
public string RoomKey { get; set; }
[JsonProperty("joinStart")]
public uint JoinStart { get; set; }
[JsonProperty("joinMapKey")]
public string JoinMapKey { get; set; }
}
}
public class EiscApiAdvancedFactory : EssentialsDeviceFactory<EiscApiAdvanced>

View File

@@ -76,6 +76,14 @@ namespace PepperDash.Essentials.Core.Bridges
public JoinDataComplete HdcpSupportCapability = new JoinDataComplete(new JoinData { JoinNumber = 1201, JoinSpan = 32 },
new JoinMetadata { Description = "DM Chassis Input HDCP Support Capability", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog });
[JoinName("InputStreamCardState")]
public JoinDataComplete InputStreamCardState = new JoinDataComplete(new JoinData { JoinNumber = 1501, JoinSpan = 32 },
new JoinMetadata { Description = "DM Chassis Stream Input Start (1), Stop (2), Pause (3) with Feedback", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog });
[JoinName("OutputStreamCardState")]
public JoinDataComplete OutputStreamCardState = new JoinDataComplete(new JoinData { JoinNumber = 1601, JoinSpan = 32 },
new JoinMetadata { Description = "DM Chassis Stream Output Start (1), Stop (2), Pause (3) with Feedback", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog });
[JoinName("InputNames")]
public JoinDataComplete InputNames = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 },
new JoinMetadata { Description = "DM Chassis Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });

View File

@@ -56,6 +56,11 @@ namespace PepperDash.Essentials.Core
private void RegisterAndConfigureComPort()
{
if (Port == null)
{
Debug.Console(0,this,Debug.ErrorLogLevel.Error, "Configured com Port for this device does not exist.");
return;
}
if (Port.Parent is CrestronControlSystem)
{
var result = Port.Register();

View File

@@ -104,7 +104,7 @@ namespace PepperDash.Essentials.Core
var dev = GetIComPortsDeviceFromManagedDevice(config.ControlPortDevKey);
if (dev != null && config.ControlPortNumber <= dev.NumberOfComPorts)
return dev.ComPorts[config.ControlPortNumber];
Debug.Console(0, "GetComPort: Device '{0}' does not have com port {1}", config.ControlPortDevKey, config.ControlPortNumber);
Debug.Console(0,Debug.ErrorLogLevel.Notice, "GetComPort: Device '{0}' does not have com port {1}", config.ControlPortDevKey, config.ControlPortNumber);
return null;
}

View File

@@ -1,38 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.CrestronIO
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.CrestronIO
{
[Description("Wrapper class for Digital Input")]
public class GenericDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput
{
public DigitalInput InputPort { get; private set; }
public BoolFeedback InputStateFeedback { get; private set; }
Func<bool> InputStateFeedbackFunc
{
get
{
return () => InputPort.State;
}
}
public class GenericDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput
{
public DigitalInput InputPort { get; private set; }
public BoolFeedback InputStateFeedback { get; private set; }
Func<bool> InputStateFeedbackFunc
{
get
{
return () => InputPort.State;
}
}
public GenericDigitalInputDevice(string key, string name, Func<IOPortConfig, DigitalInput> postActivationFunc,
IOPortConfig config)
: base(key, name)
{
InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc);
AddPostActivationAction(() =>
{
@@ -40,15 +41,15 @@ namespace PepperDash.Essentials.Core.CrestronIO
InputPort.Register();
InputPort.StateChange += InputPort_StateChange;
InputPort.StateChange += InputPort_StateChange;
});
}
#region Events
void InputPort_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args)
{
void InputPort_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args)
{
InputStateFeedback.FireUpdate();
}
@@ -81,7 +82,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
}
if (ioPortDevice == null)
{
Debug.Console(0, "GetDigitalInput: Device '0' is not a valid IRelayPorts Device", dc.PortDeviceKey);
Debug.Console(0, "GetDigitalInput: Device '0' is not a valid IDigitalInputPorts Device", dc.PortDeviceKey);
return null;
}
@@ -99,13 +100,13 @@ namespace PepperDash.Essentials.Core.CrestronIO
#region Bridge Linking
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new IDigitalInputJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
var joinMap = new IDigitalInputJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<IDigitalInputJoinMap>(joinMapSerialized);
if (bridge != null)
@@ -115,19 +116,19 @@ namespace PepperDash.Essentials.Core.CrestronIO
else
{
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
try
{
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
// Link feedback for input state
InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]);
}
catch (Exception e)
{
Debug.Console(1, this, "Unable to link device '{0}'. Input is null", Key);
Debug.Console(1, this, "Error: {0}", e);
}
try
{
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
// Link feedback for input state
InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]);
}
catch (Exception e)
{
Debug.Console(1, this, "Unable to link device '{0}'. Input is null", Key);
Debug.Console(1, this, "Error: {0}", e);
}
}
@@ -144,7 +145,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new Generic Relay Device");
Debug.Console(1, "Factory Attempting to create new Generic Digital Input Device");
var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString());
@@ -158,7 +159,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
#endregion
}
}
}

View File

@@ -4,15 +4,21 @@ using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Bridges;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core.CrestronIO
{
/// <summary>
/// Represents a generic digital input deviced tied to a versiport
/// </summary>
public class GenericVersiportDigitalInputDevice : EssentialsDevice, IDigitalInput
public class GenericVersiportDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput
{
public Versiport InputPort { get; private set; }
@@ -26,17 +32,29 @@ namespace PepperDash.Essentials.Core.CrestronIO
}
}
public GenericVersiportDigitalInputDevice(string key, Versiport inputPort, IOPortConfig props):
base(key)
public GenericVersiportDigitalInputDevice(string key, string name, Func<IOPortConfig, Versiport> postActivationFunc, IOPortConfig config) :
base(key, name)
{
InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc);
InputPort = inputPort;
InputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput);
if (props.DisablePullUpResistor)
InputPort.DisablePullUpResistor = true;
InputPort.VersiportChange += new VersiportEventHandler(InputPort_VersiportChange);
Debug.Console(1, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", props.PortNumber, InputPort.DisablePullUpResistor);
AddPostActivationAction(() =>
{
InputPort = postActivationFunc(config);
InputPort.Register();
InputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput);
if (config.DisablePullUpResistor)
InputPort.DisablePullUpResistor = true;
InputPort.VersiportChange += InputPort_VersiportChange;
Debug.Console(1, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, InputPort.DisablePullUpResistor);
});
}
void InputPort_VersiportChange(Versiport port, VersiportEventArgs args)
@@ -46,5 +64,105 @@ namespace PepperDash.Essentials.Core.CrestronIO
if(args.Event == eVersiportEvent.DigitalInChange)
InputStateFeedback.FireUpdate();
}
#region Bridge Linking
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new IDigitalInputJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<IDigitalInputJoinMap>(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.");
}
try
{
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
// Link feedback for input state
InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]);
}
catch (Exception e)
{
Debug.Console(1, this, "Unable to link device '{0}'. Input is null", Key);
Debug.Console(1, this, "Error: {0}", e);
}
}
#endregion
public static Versiport GetVersiportDigitalInput(IOPortConfig dc)
{
IIOPorts ioPortDevice;
if (dc.PortDeviceKey.Equals("processor"))
{
if (!Global.ControlSystem.SupportsVersiport)
{
Debug.Console(0, "GetVersiportDigitalInput: Processor does not support Versiports");
return null;
}
ioPortDevice = Global.ControlSystem;
}
else
{
var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts;
if (ioPortDev == null)
{
Debug.Console(0, "GetVersiportDigitalInput: Device {0} is not a valid device", dc.PortDeviceKey);
return null;
}
ioPortDevice = ioPortDev;
}
if (ioPortDevice == null)
{
Debug.Console(0, "GetVersiportDigitalInput: Device '0' is not a valid IIOPorts Device", dc.PortDeviceKey);
return null;
}
if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts)
{
Debug.Console(0, "GetVersiportDigitalInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber);
}
return ioPortDevice.VersiPorts[dc.PortNumber];
}
}
public class GenericVersiportDigitalInputDeviceFactory : EssentialsDeviceFactory<GenericVersiportDigitalInputDevice>
{
public GenericVersiportDigitalInputDeviceFactory()
{
TypeNames = new List<string>() { "versiportinput" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new Generic Versiport Device");
var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString());
if (props == null) return null;
var portDevice = new GenericVersiportDigitalInputDevice(dc.Key, dc.Name, GenericVersiportDigitalInputDevice.GetVersiportDigitalInput, props);
return portDevice;
}
}
}

View File

@@ -1,25 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.CrestronIO
{
/// <summary>
/// Represents a generic device controlled by relays
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.CrestronIO
{
/// <summary>
/// Represents a generic device controlled by relays
/// </summary>
[Description("Wrapper class for a Relay")]
public class GenericRelayDevice : EssentialsBridgeableDevice, ISwitchedOutput
{
public Relay RelayOutput { get; private set; }
public class GenericRelayDevice : EssentialsBridgeableDevice, ISwitchedOutput
{
public Relay RelayOutput { get; private set; }
public BoolFeedback OutputIsOnFeedback { get; private set; }
//Maintained for compatibility with PepperDash.Essentials.Core.Devices.CrestronProcessor
@@ -94,11 +94,11 @@ namespace PepperDash.Essentials.Core.CrestronIO
#region Events
void RelayOutput_StateChange(Relay relay, RelayEventArgs args)
{
void RelayOutput_StateChange(Relay relay, RelayEventArgs args)
{
OutputIsOnFeedback.FireUpdate();
}
}
#endregion
#region Methods
@@ -119,33 +119,33 @@ namespace PepperDash.Essentials.Core.CrestronIO
OpenRelay();
else
CloseRelay();
}
}
#endregion
#region ISwitchedOutput Members
void ISwitchedOutput.On()
{
CloseRelay();
}
void ISwitchedOutput.Off()
{
OpenRelay();
}
#region ISwitchedOutput Members
void ISwitchedOutput.On()
{
CloseRelay();
}
void ISwitchedOutput.Off()
{
OpenRelay();
}
#endregion
#region Bridge Linking
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new GenericRelayControllerJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
var joinMap = new GenericRelayControllerJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<GenericRelayControllerJoinMap>(joinMapSerialized);
if (bridge != null)
@@ -155,26 +155,26 @@ namespace PepperDash.Essentials.Core.CrestronIO
else
{
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
if (RelayOutput == null)
{
Debug.Console(1, this, "Unable to link device '{0}'. Relay is null", Key);
return;
}
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
trilist.SetBoolSigAction(joinMap.Relay.JoinNumber, b =>
{
if (b)
CloseRelay();
else
OpenRelay();
});
// feedback for relay state
}
if (RelayOutput == null)
{
Debug.Console(1, this, "Unable to link device '{0}'. Relay is null", Key);
return;
}
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
trilist.SetBoolSigAction(joinMap.Relay.JoinNumber, b =>
{
if (b)
CloseRelay();
else
OpenRelay();
});
// feedback for relay state
OutputIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Relay.JoinNumber]);
}
@@ -202,54 +202,54 @@ namespace PepperDash.Essentials.Core.CrestronIO
return portDevice;
/*
if (props.PortDeviceKey == "processor")
portDevice = Global.ControlSystem as IRelayPorts;
else
portDevice = DeviceManager.GetDeviceForKey(props.PortDeviceKey) as IRelayPorts;
if (portDevice == null)
Debug.Console(0, "Unable to add relay device with key '{0}'. Port Device does not support relays", key);
else
{
var cs = (portDevice as CrestronControlSystem);
if (cs != null)
{
// The relay is on a control system processor
if (!cs.SupportsRelay || props.PortNumber > cs.NumberOfRelayPorts)
{
Debug.Console(0, "Port Device: {0} does not support relays or does not have enough relays");
return null;
}
}
else
{
// The relay is on another device type
if (props.PortNumber > portDevice.NumberOfRelayPorts)
{
Debug.Console(0, "Port Device: {0} does not have enough relays");
return null;
}
}
Relay relay = portDevice.RelayPorts[props.PortNumber];
if (!relay.Registered)
{
if (relay.Register() == eDeviceRegistrationUnRegistrationResponse.Success)
return new GenericRelayDevice(key, relay);
else
Debug.Console(0, "Attempt to register relay {0} on device with key '{1}' failed.", props.PortNumber, props.PortDeviceKey);
}
else
{
return new GenericRelayDevice(key, relay);
}
// Future: Check if portDevice is 3-series card or other non control system that supports versiports
}
/*
if (props.PortDeviceKey == "processor")
portDevice = Global.ControlSystem as IRelayPorts;
else
portDevice = DeviceManager.GetDeviceForKey(props.PortDeviceKey) as IRelayPorts;
if (portDevice == null)
Debug.Console(0, "Unable to add relay device with key '{0}'. Port Device does not support relays", key);
else
{
var cs = (portDevice as CrestronControlSystem);
if (cs != null)
{
// The relay is on a control system processor
if (!cs.SupportsRelay || props.PortNumber > cs.NumberOfRelayPorts)
{
Debug.Console(0, "Port Device: {0} does not support relays or does not have enough relays");
return null;
}
}
else
{
// The relay is on another device type
if (props.PortNumber > portDevice.NumberOfRelayPorts)
{
Debug.Console(0, "Port Device: {0} does not have enough relays");
return null;
}
}
Relay relay = portDevice.RelayPorts[props.PortNumber];
if (!relay.Registered)
{
if (relay.Register() == eDeviceRegistrationUnRegistrationResponse.Success)
return new GenericRelayDevice(key, relay);
else
Debug.Console(0, "Attempt to register relay {0} on device with key '{1}' failed.", props.PortNumber, props.PortDeviceKey);
}
else
{
return new GenericRelayDevice(key, relay);
}
// Future: Check if portDevice is 3-series card or other non control system that supports versiports
}
*/
}
@@ -258,7 +258,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
#endregion
}
}
}

View File

@@ -0,0 +1,11 @@
namespace PepperDash.Essentials.Core.DeviceInfo
{
public class DeviceInfo
{
public string HostName { get; set; }
public string IpAddress { get; set; }
public string MacAddress { get; set; }
public string SerialNumber { get; set; }
public string FirmwareVersion { get; set; }
}
}

View File

@@ -0,0 +1,19 @@
using System;
namespace PepperDash.Essentials.Core.DeviceInfo
{
public class DeviceInfoEventArgs:EventArgs
{
public DeviceInfo DeviceInfo { get; set; }
public DeviceInfoEventArgs()
{
}
public DeviceInfoEventArgs(DeviceInfo devInfo)
{
DeviceInfo = devInfo;
}
}
}

View File

@@ -0,0 +1,16 @@
using System;
using PepperDash.Core;
namespace PepperDash.Essentials.Core.DeviceInfo
{
public interface IDeviceInfoProvider:IKeyed
{
DeviceInfo DeviceInfo { get; }
event DeviceInfoChangeHandler DeviceInfoChanged;
void UpdateDeviceInfo();
}
public delegate void DeviceInfoChangeHandler(IKeyed device, DeviceInfoEventArgs args);
}

View File

@@ -6,7 +6,7 @@ using PepperDash.Essentials.Core.SmartObjects;
namespace PepperDash.Essentials.Core
{
public interface IDiscPlayerControls : IColor, IDPad, INumericKeypad, IPower, ITransport, IUiDisplayInfo
public interface IDiscPlayerControls : IColor, IDPad, INumericKeypad, IHasPowerControl, ITransport, IUiDisplayInfo
{
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
namespace PepperDash_Essentials_Core.DeviceTypeInterfaces
{
public interface ILanguageDefinition
{
string LocaleName { get; set; }
string FriendlyName { get; set; }
bool Enable { get; set; }
List<LanguageLabel> UiLabels { get; set; }
List<LanguageLabel> Sources { get; set; }
List<LanguageLabel> Destinations { get; set; }
List<LanguageLabel> SourceGroupNames { get; set; }
List<LanguageLabel> DestinationGroupNames { get; set; }
List<LanguageLabel> RoomNames { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
namespace PepperDash_Essentials_Core.DeviceTypeInterfaces
{
public interface ILanguageProvider
{
ILanguageDefinition CurrentLanguage { get; set; }
event EventHandler CurrentLanguageChanged;
}
}

View File

@@ -8,11 +8,9 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
/// </summary>
public interface IMobileControl : IKeyed
{
void CreateMobileControlRoomBridge(EssentialsRoomBase room);
void CreateMobileControlRoomBridge(EssentialsRoomBase room, IMobileControl parent);
void LinkSystemMonitorToAppServer();
}
/// <summary>
@@ -26,6 +24,8 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
string QrCodeUrl { get; }
string QrCodeChecksum { get; }
string McServerUrl { get; }
string RoomName { get; }

View File

@@ -1,5 +1,5 @@
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.SmartObjects;
@@ -8,7 +8,7 @@ namespace PepperDash.Essentials.Core
/// <summary>
///
/// </summary>
public interface INumericKeypad
public interface INumericKeypad:IKeyed
{
void Digit0(bool pressRelease);
void Digit1(bool pressRelease);

View File

@@ -14,35 +14,64 @@ using PepperDash.Essentials.Core.SmartObjects;
namespace PepperDash.Essentials.Core
{
/// <summary>
///
/// Defines the ability to power a device on and off
/// </summary>
[Obsolete("Will be replaced by IHasPowerControlWithFeedback")]
public interface IPower
{
void PowerOn();
void PowerOff();
void PowerToggle();
BoolFeedback PowerIsOnFeedback { get; }
BoolFeedback PowerIsOnFeedback { get; }
}
/// <summary>
/// Adds feedback for current power state
/// </summary>
public interface IHasPowerControlWithFeedback : IHasPowerControl
{
BoolFeedback PowerIsOnFeedback { get; }
}
/// <summary>
/// Defines the ability to power a device on and off
/// </summary>
public interface IHasPowerControl
{
void PowerOn();
void PowerOff();
void PowerToggle();
}
/// <summary>
///
/// </summary>
public static class IPowerExtensions
public static class IHasPowerControlExtensions
{
public static void LinkButtons(this IPower dev, BasicTriList triList)
public static void LinkButtons(this IHasPowerControl dev, BasicTriList triList)
{
triList.SetSigFalseAction(101, dev.PowerOn);
triList.SetSigFalseAction(102, dev.PowerOff);
triList.SetSigFalseAction(103, dev.PowerToggle);
dev.PowerIsOnFeedback.LinkInputSig(triList.BooleanInput[101]);
var fbdev = dev as IHasPowerControlWithFeedback;
if (fbdev != null)
{
fbdev.PowerIsOnFeedback.LinkInputSig(triList.BooleanInput[101]);
}
}
public static void UnlinkButtons(this IPower dev, BasicTriList triList)
public static void UnlinkButtons(this IHasPowerControl dev, BasicTriList triList)
{
triList.ClearBoolSigAction(101);
triList.ClearBoolSigAction(102);
triList.ClearBoolSigAction(103);
dev.PowerIsOnFeedback.UnlinkInputSig(triList.BooleanInput[101]);
var fbdev = dev as IHasPowerControlWithFeedback;
if (fbdev != null)
{
fbdev.PowerIsOnFeedback.UnlinkInputSig(triList.BooleanInput[101]);
}
}
}
}

View File

@@ -0,0 +1,9 @@
using PepperDash.Essentials.Core.Presets;
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
{
public interface ITvPresetsProvider
{
DevicePresetsModel TvPresets { get; }
}
}

View File

@@ -0,0 +1,12 @@
using PepperDash.Core;
namespace PepperDash_Essentials_Core.DeviceTypeInterfaces
{
public class LanguageLabel
{
public string Key { get; set; }
public string Description { get; set; }
public string DisplayText { get; set; }
public uint JoinNumber { get; set; }
}
}

View File

@@ -1,342 +1,355 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
public static class DeviceManager
{
private static readonly CCriticalSection DeviceCriticalSection = new CCriticalSection();
private static readonly CEvent AllowAddDevicesCEvent = new CEvent(false, true);
//public static List<Device> Devices { get { return _Devices; } }
//static List<Device> _Devices = new List<Device>();
static readonly Dictionary<string, IKeyed> Devices = new Dictionary<string, IKeyed>(StringComparer.OrdinalIgnoreCase);
/// <summary>
/// Returns a copy of all the devices in a list
/// </summary>
public static List<IKeyed> AllDevices { get { return new List<IKeyed>(Devices.Values); } }
public static bool AddDeviceEnabled;
public static void Initialize(CrestronControlSystem cs)
{
AddDeviceEnabled = true;
CrestronConsole.AddNewConsoleCommand(ListDeviceCommStatuses, "devcommstatus", "Lists the communication status of all devices",
ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(ListDeviceFeedbacks, "devfb", "Lists current feedbacks",
ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(ListDevices, "devlist", "Lists current managed devices",
ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(DeviceJsonApi.DoDeviceActionWithJson, "devjson", "",
ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetProperties(s)), "devprops", "", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetMethods(s)), "devmethods", "", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s)), "apimethods", "", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(SimulateComReceiveOnDevice, "devsimreceive",
"Simulates incoming data on a com device", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => SetDeviceStreamDebugging(s), "setdevicestreamdebug", "set comm debug [deviceKey] [off/rx/tx/both] ([minutes])", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => DisableAllDeviceStreamDebugging(), "disableallstreamdebug", "disables stream debugging on all devices", ConsoleAccessLevelEnum.AccessOperator);
}
/// <summary>
/// Calls activate steps on all Device class items
/// </summary>
public static void ActivateAll()
{
try
{
DeviceCriticalSection.Enter();
AddDeviceEnabled = false;
// PreActivate all devices
foreach (var d in Devices.Values)
{
try
{
if (d is Device)
(d as Device).PreActivate();
}
catch (Exception e)
{
Debug.Console(0, d, "ERROR: Device PreActivation failure:\r{0}", e);
}
}
// Activate all devices
foreach (var d in Devices.Values)
{
try
{
if (d is Device)
(d as Device).Activate();
}
catch (Exception e)
{
Debug.Console(0, d, "ERROR: Device Activation failure:\r{0}", e);
}
}
// PostActivate all devices
foreach (var d in Devices.Values)
{
try
{
if (d is Device)
(d as Device).PostActivate();
}
catch (Exception e)
{
Debug.Console(0, d, "ERROR: Device PostActivation failure:\r{0}", e);
}
}
}
finally
{
DeviceCriticalSection.Leave();
}
}
/// <summary>
/// Calls activate on all Device class items
/// </summary>
public static void DeactivateAll()
{
try
{
DeviceCriticalSection.Enter();
foreach (var d in Devices.Values.OfType<Device>())
{
d.Deactivate();
}
}
finally
{
DeviceCriticalSection.Leave();
}
}
//static void ListMethods(string devKey)
//{
// var dev = GetDeviceForKey(devKey);
// if(dev != null)
// {
// var type = dev.GetType().GetCType();
// var methods = type.GetMethods(BindingFlags.Public|BindingFlags.Instance);
// var sb = new StringBuilder();
// sb.AppendLine(string.Format("{2} methods on [{0}] ({1}):", dev.Key, type.Name, methods.Length));
// foreach (var m in methods)
// {
// sb.Append(string.Format("{0}(", m.Name));
// var pars = m.GetParameters();
// foreach (var p in pars)
// sb.Append(string.Format("({1}){0} ", p.Name, p.ParameterType.Name));
// sb.AppendLine(")");
// }
// CrestronConsole.ConsoleCommandResponse(sb.ToString());
// }
//}
private static void ListDevices(string s)
{
Debug.Console(0, "{0} Devices registered with Device Manager:", Devices.Count);
var sorted = Devices.Values.ToList();
sorted.Sort((a, b) => a.Key.CompareTo(b.Key));
foreach (var d in sorted)
{
var name = d is IKeyName ? (d as IKeyName).Name : "---";
Debug.Console(0, " [{0}] {1}", d.Key, name);
}
}
private static void ListDeviceFeedbacks(string devKey)
{
var dev = GetDeviceForKey(devKey);
if (dev == null)
{
Debug.Console(0, "Device '{0}' not found", devKey);
return;
}
var statusDev = dev as IHasFeedback;
if (statusDev == null)
{
Debug.Console(0, "Device '{0}' does not have visible feedbacks", devKey);
return;
}
statusDev.DumpFeedbacksToConsole(true);
}
//static void ListDeviceCommands(string devKey)
//{
// var dev = GetDeviceForKey(devKey);
// if (dev == null)
// {
// Debug.Console(0, "Device '{0}' not found", devKey);
// return;
// }
// Debug.Console(0, "This needs to be reworked. Stay tuned.", devKey);
//}
private static void ListDeviceCommStatuses(string input)
{
var sb = new StringBuilder();
foreach (var dev in Devices.Values.OfType<ICommunicationMonitor>())
{
sb.Append(string.Format("{0}: {1}\r", dev,
dev.CommunicationMonitor.Status));
}
CrestronConsole.ConsoleCommandResponse(sb.ToString());
}
//static void DoDeviceCommand(string command)
//{
// Debug.Console(0, "Not yet implemented. Stay tuned");
//}
public static void AddDevice(IKeyed newDev)
{
try
{
if (!DeviceCriticalSection.TryEnter())
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "Currently unable to add devices to Device Manager. Please try again");
return;
}
// Check for device with same key
//var existingDevice = _Devices.FirstOrDefault(d => d.Key.Equals(newDev.Key, StringComparison.OrdinalIgnoreCase));
////// If it exists, remove or warn??
//if (existingDevice != null)
if (!AddDeviceEnabled)
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "All devices have been activated. Adding new devices is not allowed.");
return;
}
if (Devices.ContainsKey(newDev.Key))
{
Debug.Console(0, newDev, "WARNING: A device with this key already exists. Not added to manager");
return;
}
Devices.Add(newDev.Key, newDev);
//if (!(_Devices.Contains(newDev)))
// _Devices.Add(newDev);
}
finally
{
DeviceCriticalSection.Leave();
}
}
public static void AddDevice(IEnumerable<IKeyed> devicesToAdd)
{
try
{
if (!DeviceCriticalSection.TryEnter())
{
Debug.Console(0, Debug.ErrorLogLevel.Error,
"Currently unable to add devices to Device Manager. Please try again");
return;
}
if (!AddDeviceEnabled)
{
Debug.Console(0, Debug.ErrorLogLevel.Error,
"All devices have been activated. Adding new devices is not allowed.");
return;
}
foreach (var dev in devicesToAdd)
{
try
{
Devices.Add(dev.Key, dev);
}
catch (ArgumentException ex)
{
Debug.Console(0, "Error adding device with key {0} to Device Manager: {1}\r\nStack Trace: {2}",
dev.Key, ex.Message, ex.StackTrace);
}
}
}
finally
{
DeviceCriticalSection.Leave();
}
}
public static void RemoveDevice(IKeyed newDev)
{
try
{
DeviceCriticalSection.Enter();
if (newDev == null)
return;
if (Devices.ContainsKey(newDev.Key))
Devices.Remove(newDev.Key);
//if (_Devices.Contains(newDev))
// _Devices.Remove(newDev);
else
Debug.Console(0, "Device manager: Device '{0}' does not exist in manager. Cannot remove", newDev.Key);
}
finally
{
DeviceCriticalSection.Leave();
}
}
public static IEnumerable<string> GetDeviceKeys()
{
//return _Devices.Select(d => d.Key).ToList();
return Devices.Keys;
}
public static IEnumerable<IKeyed> GetDevices()
{
//return _Devices.Select(d => d.Key).ToList();
return Devices.Values;
}
public static IKeyed GetDeviceForKey(string key)
{
//return _Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
if (key != null && Devices.ContainsKey(key))
return Devices[key];
return null;
}
/// <summary>
/// Console handler that simulates com port data receive
/// </summary>
/// <param name="s"></param>
public static void SimulateComReceiveOnDevice(string s)
{
// devcomsim:1 xyzabc
var match = Regex.Match(s, @"(\S*)\s*(.*)");
if (match.Groups.Count < 3)
{
CrestronConsole.ConsoleCommandResponse(" Format: devsimreceive:P <device key> <string to send>");
return;
}
//Debug.Console(2, "**** {0} - {1} ****", match.Groups[1].Value, match.Groups[2].Value);
var com = GetDeviceForKey(match.Groups[1].Value) as ComPortController;
if (com == null)
{
CrestronConsole.ConsoleCommandResponse("'{0}' is not a comm port device", match.Groups[1].Value);
return;
}
com.SimulateReceive(match.Groups[2].Value);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
public static class DeviceManager
{
public static event EventHandler<EventArgs> AllDevicesActivated;
private static readonly CCriticalSection DeviceCriticalSection = new CCriticalSection();
private static readonly CEvent AllowAddDevicesCEvent = new CEvent(false, true);
//public static List<Device> Devices { get { return _Devices; } }
//static List<Device> _Devices = new List<Device>();
static readonly Dictionary<string, IKeyed> Devices = new Dictionary<string, IKeyed>(StringComparer.OrdinalIgnoreCase);
/// <summary>
/// Returns a copy of all the devices in a list
/// </summary>
public static List<IKeyed> AllDevices { get { return new List<IKeyed>(Devices.Values); } }
public static bool AddDeviceEnabled;
public static void Initialize(CrestronControlSystem cs)
{
AddDeviceEnabled = true;
CrestronConsole.AddNewConsoleCommand(ListDeviceCommStatuses, "devcommstatus", "Lists the communication status of all devices",
ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(ListDeviceFeedbacks, "devfb", "Lists current feedbacks",
ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(ListDevices, "devlist", "Lists current managed devices",
ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(DeviceJsonApi.DoDeviceActionWithJson, "devjson", "",
ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetProperties(s)), "devprops", "", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetMethods(s)), "devmethods", "", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s)), "apimethods", "", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(SimulateComReceiveOnDevice, "devsimreceive",
"Simulates incoming data on a com device", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => SetDeviceStreamDebugging(s), "setdevicestreamdebug", "set comm debug [deviceKey] [off/rx/tx/both] ([minutes])", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => DisableAllDeviceStreamDebugging(), "disableallstreamdebug", "disables stream debugging on all devices", ConsoleAccessLevelEnum.AccessOperator);
}
/// <summary>
/// Calls activate steps on all Device class items
/// </summary>
public static void ActivateAll()
{
try
{
DeviceCriticalSection.Enter();
AddDeviceEnabled = false;
// PreActivate all devices
foreach (var d in Devices.Values)
{
try
{
if (d is Device)
(d as Device).PreActivate();
}
catch (Exception e)
{
Debug.Console(0, d, "ERROR: Device PreActivation failure:\r{0}", e);
}
}
// Activate all devices
foreach (var d in Devices.Values)
{
try
{
if (d is Device)
(d as Device).Activate();
}
catch (Exception e)
{
Debug.Console(0, d, "ERROR: Device Activation failure:\r{0}", e);
}
}
// PostActivate all devices
foreach (var d in Devices.Values)
{
try
{
if (d is Device)
(d as Device).PostActivate();
}
catch (Exception e)
{
Debug.Console(0, d, "ERROR: Device PostActivation failure:\r{0}", e);
}
}
OnAllDevicesActivated();
}
finally
{
DeviceCriticalSection.Leave();
}
}
private static void OnAllDevicesActivated()
{
var handler = AllDevicesActivated;
if (handler != null)
{
handler(null, new EventArgs());
}
}
/// <summary>
/// Calls activate on all Device class items
/// </summary>
public static void DeactivateAll()
{
try
{
DeviceCriticalSection.Enter();
foreach (var d in Devices.Values.OfType<Device>())
{
d.Deactivate();
}
}
finally
{
DeviceCriticalSection.Leave();
}
}
//static void ListMethods(string devKey)
//{
// var dev = GetDeviceForKey(devKey);
// if(dev != null)
// {
// var type = dev.GetType().GetCType();
// var methods = type.GetMethods(BindingFlags.Public|BindingFlags.Instance);
// var sb = new StringBuilder();
// sb.AppendLine(string.Format("{2} methods on [{0}] ({1}):", dev.Key, type.Name, methods.Length));
// foreach (var m in methods)
// {
// sb.Append(string.Format("{0}(", m.Name));
// var pars = m.GetParameters();
// foreach (var p in pars)
// sb.Append(string.Format("({1}){0} ", p.Name, p.ParameterType.Name));
// sb.AppendLine(")");
// }
// CrestronConsole.ConsoleCommandResponse(sb.ToString());
// }
//}
private static void ListDevices(string s)
{
Debug.Console(0, "{0} Devices registered with Device Manager:", Devices.Count);
var sorted = Devices.Values.ToList();
sorted.Sort((a, b) => a.Key.CompareTo(b.Key));
foreach (var d in sorted)
{
var name = d is IKeyName ? (d as IKeyName).Name : "---";
Debug.Console(0, " [{0}] {1}", d.Key, name);
}
}
private static void ListDeviceFeedbacks(string devKey)
{
var dev = GetDeviceForKey(devKey);
if (dev == null)
{
Debug.Console(0, "Device '{0}' not found", devKey);
return;
}
var statusDev = dev as IHasFeedback;
if (statusDev == null)
{
Debug.Console(0, "Device '{0}' does not have visible feedbacks", devKey);
return;
}
statusDev.DumpFeedbacksToConsole(true);
}
//static void ListDeviceCommands(string devKey)
//{
// var dev = GetDeviceForKey(devKey);
// if (dev == null)
// {
// Debug.Console(0, "Device '{0}' not found", devKey);
// return;
// }
// Debug.Console(0, "This needs to be reworked. Stay tuned.", devKey);
//}
private static void ListDeviceCommStatuses(string input)
{
var sb = new StringBuilder();
foreach (var dev in Devices.Values.OfType<ICommunicationMonitor>())
{
sb.Append(string.Format("{0}: {1}\r", dev,
dev.CommunicationMonitor.Status));
}
CrestronConsole.ConsoleCommandResponse(sb.ToString());
}
//static void DoDeviceCommand(string command)
//{
// Debug.Console(0, "Not yet implemented. Stay tuned");
//}
public static void AddDevice(IKeyed newDev)
{
try
{
if (!DeviceCriticalSection.TryEnter())
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "Currently unable to add devices to Device Manager. Please try again");
return;
}
// Check for device with same key
//var existingDevice = _Devices.FirstOrDefault(d => d.Key.Equals(newDev.Key, StringComparison.OrdinalIgnoreCase));
////// If it exists, remove or warn??
//if (existingDevice != null)
if (!AddDeviceEnabled)
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "All devices have been activated. Adding new devices is not allowed.");
return;
}
if (Devices.ContainsKey(newDev.Key))
{
Debug.Console(0, newDev, "WARNING: A device with this key already exists. Not added to manager");
return;
}
Devices.Add(newDev.Key, newDev);
//if (!(_Devices.Contains(newDev)))
// _Devices.Add(newDev);
}
finally
{
DeviceCriticalSection.Leave();
}
}
public static void AddDevice(IEnumerable<IKeyed> devicesToAdd)
{
try
{
if (!DeviceCriticalSection.TryEnter())
{
Debug.Console(0, Debug.ErrorLogLevel.Error,
"Currently unable to add devices to Device Manager. Please try again");
return;
}
if (!AddDeviceEnabled)
{
Debug.Console(0, Debug.ErrorLogLevel.Error,
"All devices have been activated. Adding new devices is not allowed.");
return;
}
foreach (var dev in devicesToAdd)
{
try
{
Devices.Add(dev.Key, dev);
}
catch (ArgumentException ex)
{
Debug.Console(0, "Error adding device with key {0} to Device Manager: {1}\r\nStack Trace: {2}",
dev.Key, ex.Message, ex.StackTrace);
}
}
}
finally
{
DeviceCriticalSection.Leave();
}
}
public static void RemoveDevice(IKeyed newDev)
{
try
{
DeviceCriticalSection.Enter();
if (newDev == null)
return;
if (Devices.ContainsKey(newDev.Key))
Devices.Remove(newDev.Key);
//if (_Devices.Contains(newDev))
// _Devices.Remove(newDev);
else
Debug.Console(0, "Device manager: Device '{0}' does not exist in manager. Cannot remove", newDev.Key);
}
finally
{
DeviceCriticalSection.Leave();
}
}
public static IEnumerable<string> GetDeviceKeys()
{
//return _Devices.Select(d => d.Key).ToList();
return Devices.Keys;
}
public static IEnumerable<IKeyed> GetDevices()
{
//return _Devices.Select(d => d.Key).ToList();
return Devices.Values;
}
public static IKeyed GetDeviceForKey(string key)
{
//return _Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
if (key != null && Devices.ContainsKey(key))
return Devices[key];
return null;
}
/// <summary>
/// Console handler that simulates com port data receive
/// </summary>
/// <param name="s"></param>
public static void SimulateComReceiveOnDevice(string s)
{
// devcomsim:1 xyzabc
var match = Regex.Match(s, @"(\S*)\s*(.*)");
if (match.Groups.Count < 3)
{
CrestronConsole.ConsoleCommandResponse(" Format: devsimreceive:P <device key> <string to send>");
return;
}
//Debug.Console(2, "**** {0} - {1} ****", match.Groups[1].Value, match.Groups[2].Value);
var com = GetDeviceForKey(match.Groups[1].Value) as ComPortController;
if (com == null)
{
CrestronConsole.ConsoleCommandResponse("'{0}' is not a comm port device", match.Groups[1].Value);
return;
}
com.SimulateReceive(match.Groups[2].Value);
}
/// <summary>
@@ -366,82 +379,82 @@ namespace PepperDash.Essentials.Core
Debug.Console(0, "{0}", routingOutputPort.Key);
}
}
}
/// <summary>
/// Attempts to set the debug level of a device
/// </summary>
/// <param name="s"></param>
public static void SetDeviceStreamDebugging(string s)
{
var args = s.Split(' ');
var deviceKey = args[0];
var setting = args[1];
var timeout= String.Empty;
if (args.Length >= 3)
{
timeout = args[2];
}
var device = GetDeviceForKey(deviceKey) as IStreamDebugging;
if (device == null)
{
Debug.Console(0, "Unable to get device with key: {0}", deviceKey);
return;
}
eStreamDebuggingSetting debugSetting;
try
{
debugSetting = (eStreamDebuggingSetting)Enum.Parse(typeof(eStreamDebuggingSetting), setting, true);
}
catch
{
Debug.Console(0, "Unable to convert setting value. Please use off/rx/tx/both");
return;
}
if (!string.IsNullOrEmpty(timeout))
{
try
{
var min = Convert.ToUInt32(timeout);
device.StreamDebugging.SetDebuggingWithSpecificTimeout(debugSetting, min);
Debug.Console(0, "Device: '{0}' debug level set to {1) for {2} minutes", deviceKey, debugSetting, min);
}
catch (Exception e)
{
Debug.Console(0, "Unable to convert minutes or settings value. Please use an integer value for minutes. Errro: {0}", e);
}
}
else
{
device.StreamDebugging.SetDebuggingWithDefaultTimeout(debugSetting);
Debug.Console(0, "Device: '{0}' debug level set to {1) for default time (30 minutes)", deviceKey, debugSetting);
}
}
/// <summary>
/// Sets stream debugging settings to off for all devices
/// </summary>
public static void DisableAllDeviceStreamDebugging()
{
foreach (var device in AllDevices)
{
var streamDevice = device as IStreamDebugging;
if (streamDevice != null)
{
streamDevice.StreamDebugging.SetDebuggingWithDefaultTimeout(eStreamDebuggingSetting.Off);
}
}
}
}
}
/// <summary>
/// Attempts to set the debug level of a device
/// </summary>
/// <param name="s"></param>
public static void SetDeviceStreamDebugging(string s)
{
var args = s.Split(' ');
var deviceKey = args[0];
var setting = args[1];
var timeout= String.Empty;
if (args.Length >= 3)
{
timeout = args[2];
}
var device = GetDeviceForKey(deviceKey) as IStreamDebugging;
if (device == null)
{
Debug.Console(0, "Unable to get device with key: {0}", deviceKey);
return;
}
eStreamDebuggingSetting debugSetting;
try
{
debugSetting = (eStreamDebuggingSetting)Enum.Parse(typeof(eStreamDebuggingSetting), setting, true);
}
catch
{
Debug.Console(0, "Unable to convert setting value. Please use off/rx/tx/both");
return;
}
if (!string.IsNullOrEmpty(timeout))
{
try
{
var min = Convert.ToUInt32(timeout);
device.StreamDebugging.SetDebuggingWithSpecificTimeout(debugSetting, min);
Debug.Console(0, "Device: '{0}' debug level set to {1) for {2} minutes", deviceKey, debugSetting, min);
}
catch (Exception e)
{
Debug.Console(0, "Unable to convert minutes or settings value. Please use an integer value for minutes. Errro: {0}", e);
}
}
else
{
device.StreamDebugging.SetDebuggingWithDefaultTimeout(debugSetting);
Debug.Console(0, "Device: '{0}' debug level set to {1) for default time (30 minutes)", deviceKey, debugSetting);
}
}
/// <summary>
/// Sets stream debugging settings to off for all devices
/// </summary>
public static void DisableAllDeviceStreamDebugging()
{
foreach (var device in AllDevices)
{
var streamDevice = device as IStreamDebugging;
if (streamDevice != null)
{
streamDevice.StreamDebugging.SetDebuggingWithDefaultTimeout(eStreamDebuggingSetting.Off);
}
}
}
}
}

View File

@@ -0,0 +1,17 @@
using System.Collections.Generic;
namespace PepperDash.Essentials.Core
{
public interface IHasDspPresets
{
List<IDspPreset> Presets { get; }
void RecallPreset(IDspPreset preset);
}
public interface IDspPreset
{
string Name { get; }
}
}

View File

@@ -20,10 +20,13 @@ namespace PepperDash.Essentials.Core
public IrOutputPortController IrPort { get; private set; }
public ushort IrPulseTime { get; set; }
protected override Func<bool> PowerIsOnFeedbackFunc
{
get { return () => _PowerIsOn; }
}
[Obsolete("This property will be removed in version 2.0.0")]
public override BoolFeedback PowerIsOnFeedback { get; protected set; }
protected Func<bool> PowerIsOnFeedbackFunc
{
get { return () => _PowerIsOn; }
}
protected override Func<bool> IsCoolingDownFeedbackFunc
{
get { return () => _IsCoolingDown; }
@@ -33,7 +36,7 @@ namespace PepperDash.Essentials.Core
get { return () => _IsWarmingUp; }
}
bool _PowerIsOn;
bool _PowerIsOn;
bool _IsWarmingUp;
bool _IsCoolingDown;
@@ -43,11 +46,14 @@ namespace PepperDash.Essentials.Core
IrPort = new IrOutputPortController(key + "-ir", port, irDriverFilepath);
DeviceManager.AddDevice(IrPort);
PowerIsOnFeedback.OutputChange += (o, a) => {
Debug.Console(2, this, "Power on={0}", _PowerIsOn);
if (_PowerIsOn) StartWarmingTimer();
else StartCoolingTimer();
};
PowerIsOnFeedback = new BoolFeedback(PowerIsOnFeedbackFunc);
PowerIsOnFeedback.OutputChange += (o, a) =>
{
Debug.Console(2, this, "Power on={0}", _PowerIsOn);
if (_PowerIsOn) StartWarmingTimer();
else StartCoolingTimer();
};
IsWarmingUpFeedback.OutputChange += (o, a) => Debug.Console(2, this, "Warming up={0}", _IsWarmingUp);
IsCoolingDownFeedback.OutputChange += (o, a) => Debug.Console(2, this, "Cooling down={0}", _IsCoolingDown);
@@ -110,21 +116,21 @@ namespace PepperDash.Essentials.Core
public override void PowerOn()
{
IrPort.Pulse(IROutputStandardCommands.IROut_POWER_ON, IrPulseTime);
_PowerIsOn = true;
PowerIsOnFeedback.FireUpdate();
_PowerIsOn = true;
PowerIsOnFeedback.FireUpdate();
}
public override void PowerOff()
{
_PowerIsOn = false;
PowerIsOnFeedback.FireUpdate();
_PowerIsOn = false;
PowerIsOnFeedback.FireUpdate();
IrPort.Pulse(IROutputStandardCommands.IROut_POWER_OFF, IrPulseTime);
}
public override void PowerToggle()
{
_PowerIsOn = false;
PowerIsOnFeedback.FireUpdate();
_PowerIsOn = false;
PowerIsOnFeedback.FireUpdate();
IrPort.Pulse(IROutputStandardCommands.IROut_POWER, IrPulseTime);
}

View File

@@ -1,131 +1,118 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Endpoints;
using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.Core
{
/// <summary>
///
/// </summary>
public abstract class DisplayBase : EssentialsDevice, IHasFeedback, IRoutingSinkWithSwitching, IPower, IWarmingCooling, IUsageTracking
{
public event SourceInfoChangeHandler CurrentSourceChange;
public string CurrentSourceInfoKey { get; set; }
public SourceListItem CurrentSourceInfo
{
get
{
return _CurrentSourceInfo;
}
set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSourceChange;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.WillChange);
_CurrentSourceInfo = value;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.DidChange);
}
}
SourceListItem _CurrentSourceInfo;
public BoolFeedback PowerIsOnFeedback { get; protected set; }
public BoolFeedback IsCoolingDownFeedback { get; protected set; }
public BoolFeedback IsWarmingUpFeedback { get; private set; }
public UsageTracking UsageTracker { get; set; }
public uint WarmupTime { get; set; }
public uint CooldownTime { get; set; }
/// <summary>
/// Bool Func that will provide a value for the PowerIsOn Output. Must be implemented
/// by concrete sub-classes
/// </summary>
abstract protected Func<bool> PowerIsOnFeedbackFunc { get; }
abstract protected Func<bool> IsCoolingDownFeedbackFunc { get; }
abstract protected Func<bool> IsWarmingUpFeedbackFunc { get; }
protected CTimer WarmupTimer;
protected CTimer CooldownTimer;
#region IRoutingInputs Members
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
#endregion
protected DisplayBase(string key, string name)
: base(key, name)
{
PowerIsOnFeedback = new BoolFeedback("PowerOnFeedback", PowerIsOnFeedbackFunc);
IsCoolingDownFeedback = new BoolFeedback("IsCoolingDown", IsCoolingDownFeedbackFunc);
IsWarmingUpFeedback = new BoolFeedback("IsWarmingUp", IsWarmingUpFeedbackFunc);
InputPorts = new RoutingPortCollection<RoutingInputPort>();
PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange;
}
void PowerIsOnFeedback_OutputChange(object sender, EventArgs e)
{
if (UsageTracker != null)
{
if (PowerIsOnFeedback.BoolValue)
UsageTracker.StartDeviceUsage();
else
UsageTracker.EndDeviceUsage();
}
}
public abstract void PowerOn();
public abstract void PowerOff();
public abstract void PowerToggle();
public virtual FeedbackCollection<Feedback> Feedbacks
{
get
{
return new FeedbackCollection<Feedback>
{
PowerIsOnFeedback,
IsCoolingDownFeedback,
IsWarmingUpFeedback
};
}
}
public abstract void ExecuteSwitch(object selector);
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);
if (!string.IsNullOrEmpty(joinMapSerialized))
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Endpoints;
using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.Core
{
/// <summary>
///
/// </summary>
public abstract class DisplayBase : EssentialsDevice, IHasFeedback, IRoutingSinkWithSwitching, IHasPowerControl, IWarmingCooling, IUsageTracking, IPower
{
public event SourceInfoChangeHandler CurrentSourceChange;
public string CurrentSourceInfoKey { get; set; }
public SourceListItem CurrentSourceInfo
{
get
{
return _CurrentSourceInfo;
}
set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSourceChange;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.WillChange);
_CurrentSourceInfo = value;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.DidChange);
}
}
SourceListItem _CurrentSourceInfo;
public BoolFeedback IsCoolingDownFeedback { get; protected set; }
public BoolFeedback IsWarmingUpFeedback { get; private set; }
[Obsolete("This property will be removed in version 2.0.0")]
public abstract BoolFeedback PowerIsOnFeedback { get; protected set; }
public UsageTracking UsageTracker { get; set; }
public uint WarmupTime { get; set; }
public uint CooldownTime { get; set; }
/// <summary>
/// Bool Func that will provide a value for the PowerIsOn Output. Must be implemented
/// by concrete sub-classes
/// </summary>
abstract protected Func<bool> IsCoolingDownFeedbackFunc { get; }
abstract protected Func<bool> IsWarmingUpFeedbackFunc { get; }
protected CTimer WarmupTimer;
protected CTimer CooldownTimer;
#region IRoutingInputs Members
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
#endregion
protected DisplayBase(string key, string name)
: base(key, name)
{
IsCoolingDownFeedback = new BoolFeedback("IsCoolingDown", IsCoolingDownFeedbackFunc);
IsWarmingUpFeedback = new BoolFeedback("IsWarmingUp", IsWarmingUpFeedbackFunc);
InputPorts = new RoutingPortCollection<RoutingInputPort>();
}
public abstract void PowerOn();
public abstract void PowerOff();
public abstract void PowerToggle();
public virtual FeedbackCollection<Feedback> Feedbacks
{
get
{
return new FeedbackCollection<Feedback>
{
IsCoolingDownFeedback,
IsWarmingUpFeedback
};
}
}
public abstract void ExecuteSwitch(object selector);
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);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<DisplayControllerJoinMap>(joinMapSerialized);
if (bridge != null)
@@ -137,163 +124,198 @@ 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();
});
displayDevice.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (!a.BoolValue)
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
}
else
{
inputNumber = 0;
inputNumberFeedback.FireUpdate();
}
};
displayDevice.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]);
// PowerOn
trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () =>
{
inputNumber = 0;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOn();
});
displayDevice.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]);
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>
///
/// </summary>
public abstract class TwoWayDisplayBase : DisplayBase
{
public StringFeedback CurrentInputFeedback { get; private set; }
abstract protected Func<string> CurrentInputFeedbackFunc { get; }
public static MockDisplay DefaultDisplay
{
get
{
if (_DefaultDisplay == null)
_DefaultDisplay = new MockDisplay("default", "Default Display");
return _DefaultDisplay;
}
}
static MockDisplay _DefaultDisplay;
public TwoWayDisplayBase(string key, string name)
: base(key, name)
{
CurrentInputFeedback = new StringFeedback(CurrentInputFeedbackFunc);
WarmupTime = 7000;
CooldownTime = 15000;
Feedbacks.Add(CurrentInputFeedback);
}
}
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]);
}
}
/// <summary>
///
/// </summary>
public abstract class TwoWayDisplayBase : DisplayBase, IRoutingFeedback, IHasPowerControlWithFeedback
{
public StringFeedback CurrentInputFeedback { get; private set; }
abstract protected Func<string> CurrentInputFeedbackFunc { get; }
public override BoolFeedback PowerIsOnFeedback { get; protected set; }
abstract protected Func<bool> PowerIsOnFeedbackFunc { get; }
public static MockDisplay DefaultDisplay
{
get
{
if (_DefaultDisplay == null)
_DefaultDisplay = new MockDisplay("default", "Default Display");
return _DefaultDisplay;
}
}
static MockDisplay _DefaultDisplay;
public TwoWayDisplayBase(string key, string name)
: base(key, name)
{
CurrentInputFeedback = new StringFeedback(CurrentInputFeedbackFunc);
WarmupTime = 7000;
CooldownTime = 15000;
PowerIsOnFeedback = new BoolFeedback("PowerOnFeedback", PowerIsOnFeedbackFunc);
Feedbacks.Add(CurrentInputFeedback);
Feedbacks.Add(PowerIsOnFeedback);
PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange;
}
void PowerIsOnFeedback_OutputChange(object sender, EventArgs e)
{
if (UsageTracker != null)
{
if (PowerIsOnFeedback.BoolValue)
UsageTracker.StartDeviceUsage();
else
UsageTracker.EndDeviceUsage();
}
}
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
protected void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
}
}

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash_Essentials_Core.Gateways
{
public class CenCn2Controller
{
}
}

View File

@@ -1,11 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.Reflection;
using Crestron.SimplSharp.Scheduler;
using PepperDash.Core;
using PepperDash.Essentials.Core.Fusion;
using PepperDash.Essentials.Room.Config;
using Activator = System.Activator;
namespace PepperDash.Essentials.Core
{
@@ -14,7 +17,7 @@ namespace PepperDash.Essentials.Core
/// </summary>
public static class Scheduler
{
private static Dictionary<string, ScheduledEventGroup> EventGroups = new Dictionary<string,ScheduledEventGroup>();
private static readonly Dictionary<string, ScheduledEventGroup> EventGroups = new Dictionary<string,ScheduledEventGroup>();
static Scheduler()
{
@@ -49,7 +52,6 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// Adds the event group to the global list
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public static void AddEventGroup(ScheduledEventGroup eventGroup)
{
@@ -67,6 +69,13 @@ namespace PepperDash.Essentials.Core
if(!EventGroups.ContainsKey(eventGroup.Name))
EventGroups.Remove(eventGroup.Name);
}
public static ScheduledEventGroup GetEventGroup(string key)
{
ScheduledEventGroup returnValue;
return EventGroups.TryGetValue(key, out returnValue) ? returnValue : null;
}
}
public static class SchedulerUtilities
@@ -135,5 +144,90 @@ namespace PepperDash.Essentials.Core
return isMatch;
}
public static bool CheckEventTimeForMatch(ScheduledEvent evnt, DateTime time)
{
return evnt.DateAndTime.Hour == time.Hour && evnt.DateAndTime.Minute == time.Minute;
}
public static bool CheckEventRecurrenceForMatch(ScheduledEvent evnt, ScheduledEventCommon.eWeekDays days)
{
return evnt.Recurrence.RecurrenceDays == days;
}
public static void CreateEventFromConfig(ScheduledEventConfig config, ScheduledEventGroup group, ScheduledEvent.UserEventCallBack handler)
{
if (group == null)
{
Debug.Console(0, "Unable to create event. Group is null");
return;
}
var scheduledEvent = new ScheduledEvent(config.Key, group)
{
Acknowledgeable = config.Acknowledgeable,
Persistent = config.Persistent
};
scheduledEvent.UserCallBack += handler;
scheduledEvent.DateAndTime.SetFirstDayOfWeek(ScheduledEventCommon.eFirstDayOfWeek.Sunday);
var eventTime = DateTime.Parse(config.Time);
if (DateTime.Now > eventTime)
{
eventTime = eventTime.AddDays(1);
}
Debug.Console(2, "[Scheduler] Current Date day of week: {0} recurrence days: {1}", eventTime.DayOfWeek,
config.Days);
var dayOfWeekConverted = ConvertDayOfWeek(eventTime);
Debug.Console(1, "[Scheduler] eventTime Day: {0}", dayOfWeekConverted);
while (!dayOfWeekConverted.IsFlagSet(config.Days))
{
eventTime = eventTime.AddDays(1);
dayOfWeekConverted = ConvertDayOfWeek(eventTime);
}
scheduledEvent.DateAndTime.SetAbsoluteEventTime(eventTime);
scheduledEvent.Recurrence.Weekly(config.Days);
if (config.Enable)
{
scheduledEvent.Enable();
}
else
{
scheduledEvent.Disable();
}
}
private static ScheduledEventCommon.eWeekDays ConvertDayOfWeek(DateTime eventTime)
{
return (ScheduledEventCommon.eWeekDays) Enum.Parse(typeof(ScheduledEventCommon.eWeekDays), eventTime.DayOfWeek.ToString(), true);
}
private static bool IsFlagSet<T>(this T value, T flag) where T : struct
{
CheckIsEnum<T>(true);
var lValue = Convert.ToInt64(value);
var lFlag = Convert.ToInt64(flag);
return (lValue & lFlag) != 0;
}
private static void CheckIsEnum<T>(bool withFlags)
{
if (!typeof(T).IsEnum)
throw new ArgumentException(string.Format("Type '{0}' is not an enum", typeof(T).FullName));
if (withFlags && !Attribute.IsDefined(typeof(T), typeof(FlagsAttribute)))
throw new ArgumentException(string.Format("Type '{0}' doesn't have the 'Flags' attribute", typeof(T).FullName));
}
}
}

View File

@@ -88,8 +88,12 @@ namespace PepperDash.Essentials.Core.Privacy
else
Debug.Console(0, this, "Unable to add Red LED device");
DeviceManager.AllDevicesActivated += (o, a) =>
{
CheckPrivacyMode();
};
AddPostActivationAction(() => {
CheckPrivacyMode();
PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange -= PrivacyModeIsOnFeedback_OutputChange;
PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange;
});

View File

@@ -83,7 +83,7 @@
<HintPath>..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="PepperDash_Core, Version=1.0.41.31808, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="PepperDash_Core, Version=1.0.42.30563, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll</HintPath>
</Reference>
@@ -183,6 +183,9 @@
<Compile Include="Crestron IO\Relay\GenericRelayDevice.cs" />
<Compile Include="Crestron IO\Relay\ISwitchedOutput.cs" />
<Compile Include="Crestron IO\StatusSign\StatusSignController.cs" />
<Compile Include="Device Info\DeviceInfo.cs" />
<Compile Include="Device Info\DeviceInfoEventArgs.cs" />
<Compile Include="Device Info\IDeviceInfoProvider.cs" />
<Compile Include="Devices\CodecInterfaces.cs" />
<Compile Include="Devices\CrestronProcessor.cs" />
<Compile Include="Devices\DeviceApiBase.cs" />
@@ -190,12 +193,17 @@
<Compile Include="Devices\EssentialsBridgeableDevice.cs" />
<Compile Include="Devices\EssentialsDevice.cs" />
<Compile Include="Devices\GenericIRController.cs" />
<Compile Include="Devices\IDspPreset.cs" />
<Compile Include="Devices\IProjectorInterfaces.cs" />
<Compile Include="Devices\PC\InRoomPc.cs" />
<Compile Include="Devices\PC\Laptop.cs" />
<Compile Include="Devices\ReconfigurableDevice.cs" />
<Compile Include="Devices\VolumeDeviceChangeEventArgs.cs" />
<Compile Include="DeviceTypeInterfaces\ITvPresetsProvider.cs" />
<Compile Include="DeviceTypeInterfaces\LanguageLabel.cs" />
<Compile Include="DeviceTypeInterfaces\ILanguageProvider.cs" />
<Compile Include="DeviceTypeInterfaces\IHasBranding.cs" />
<Compile Include="DeviceTypeInterfaces\ILanguageDefinition.cs" />
<Compile Include="DeviceTypeInterfaces\IHasFarEndContentStatus.cs" />
<Compile Include="DeviceTypeInterfaces\IHasPhoneDialing.cs" />
<Compile Include="DeviceTypeInterfaces\IMobileControl.cs" />
@@ -271,6 +279,7 @@
<Compile Include="Remotes\Hrxx0WirelessRemoteController.cs" />
<Compile Include="Room\Behaviours\RoomOnToDefaultSourceWhenOccupied.cs" />
<Compile Include="Room\EssentialsRoomBase.cs" />
<Compile Include="Room\Config\EssentialsRoomScheduledEventsConfig.cs" />
<Compile Include="Room\Interfaces.cs" />
<Compile Include="Room\iOccupancyStatusProvider.cs" />
<Compile Include="Routing\DummyRoutingInputsDevice.cs" />

View File

@@ -14,7 +14,7 @@
<tags>crestron 3series 4series</tags>
<repository type="git" url="https://github.com/PepperDash/Essentials"/>
<dependencies>
<dependency id="PepperDashCore" version="[1.0, 1.1)"/>
<dependency id="PepperDashCore" version="[1.0.44, 1.1.0)"/>
</dependencies>
</metadata>
<files>

View File

@@ -402,13 +402,16 @@ namespace PepperDash.Essentials
/// Loads a
/// </summary>
/// <param name="plugin"></param>
/// <param name="loadedAssembly"></param>
static void LoadCustomPlugin(IPluginDeviceFactory plugin, LoadedAssembly loadedAssembly)
{
var passed = Global.IsRunningMinimumVersionOrHigher(plugin.MinimumEssentialsFrameworkVersion);
if (!passed)
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "Plugin indicates minimum Essentials version {0}. Dependency check failed. Skipping Plugin", plugin.MinimumEssentialsFrameworkVersion);
Debug.Console(0, Debug.ErrorLogLevel.Error,
"\r\n********************\r\n\tPlugin indicates minimum Essentials version {0}. Dependency check failed. Skipping Plugin {1}\r\n********************",
plugin.MinimumEssentialsFrameworkVersion, loadedAssembly.Name);
return;
}
else

View File

@@ -1,178 +1,300 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
//using SSMono.IO;
using PepperDash.Core.WebApi.Presets;
namespace PepperDash.Essentials.Core.Presets
{
/// <summary>
/// Class that represents the model behind presets display
/// </summary>
public class DevicePresetsModel : Device
{
public event EventHandler PresetsLoaded;
/// <summary>
/// Class that represents the model behind presets display
/// </summary>
public class DevicePresetsModel : Device
{
public delegate void PresetRecalledCallback(ISetTopBoxNumericKeypad device, string channel);
public int PulseTime { get; set; }
public int DigitSpacingMS { get; set; }
public bool PresetsAreLoaded { get; private set; }
public delegate void PresetsSavedCallback(List<PresetChannel> presets);
public List<PresetChannel> PresetsList { get { return _PresetsList.ToList(); } }
List<PresetChannel> _PresetsList;
public int Count { get { return PresetsList != null ? PresetsList.Count : 0; } }
private readonly CCriticalSection _fileOps = new CCriticalSection();
private readonly bool _initSuccess;
public bool UseLocalImageStorage { get; set; }
public string ImagesLocalHostPrefix { get; set; }
public string ImagesPathPrefix { get; set; }
public string ListPathPrefix { get; set; }
private readonly ISetTopBoxNumericKeypad _setTopBox;
/// <summary>
/// The methods on the STB device to call when dialing
/// </summary>
Dictionary<char, Action<bool>> DialFunctions;
Action<bool> EnterFunction;
/// <summary>
/// The methods on the STB device to call when dialing
/// </summary>
private Dictionary<char, Action<bool>> _dialFunctions;
bool DialIsRunning;
string FilePath;
bool InitSuccess;
//SSMono.IO.FileSystemWatcher ListWatcher;
private bool _dialIsRunning;
private Action<bool> _enterFunction;
private string _filePath;
public DevicePresetsModel(string key, ISetTopBoxNumericKeypad setTopBox, string fileName)
: base(key)
{
PulseTime = 150;
DigitSpacingMS = 150;
public DevicePresetsModel(string key, ISetTopBoxNumericKeypad setTopBox, string fileName)
: this(key, fileName)
{
try
{
_setTopBox = setTopBox;
try
{
// Grab the digit functions from the device
// If any fail, the whole thing fails peacefully
DialFunctions = new Dictionary<char, Action<bool>>(10)
{
{ '1', setTopBox.Digit1 },
{ '2', setTopBox.Digit2 },
{ '3', setTopBox.Digit3 },
{ '4', setTopBox.Digit4 },
{ '5', setTopBox.Digit5 },
{ '6', setTopBox.Digit6 },
{ '7', setTopBox.Digit7 },
{ '8', setTopBox.Digit8 },
{ '9', setTopBox.Digit9 },
{ '0', setTopBox.Digit0 },
{ '-', setTopBox.Dash }
};
}
catch
{
Debug.Console(0, "DevicePresets '{0}', not attached to INumericKeypad device. Ignoring", key);
DialFunctions = null;
return;
}
// Grab the digit functions from the device
// If any fail, the whole thing fails peacefully
_dialFunctions = new Dictionary<char, Action<bool>>(10)
{
{'1', setTopBox.Digit1},
{'2', setTopBox.Digit2},
{'3', setTopBox.Digit3},
{'4', setTopBox.Digit4},
{'5', setTopBox.Digit5},
{'6', setTopBox.Digit6},
{'7', setTopBox.Digit7},
{'8', setTopBox.Digit8},
{'9', setTopBox.Digit9},
{'0', setTopBox.Digit0},
{'-', setTopBox.Dash}
};
}
catch
{
Debug.Console(0, "DevicePresets '{0}', not attached to INumericKeypad device. Ignoring", key);
_dialFunctions = null;
return;
}
EnterFunction = setTopBox.KeypadEnter;
_enterFunction = setTopBox.KeypadEnter;
}
UseLocalImageStorage = true;
public DevicePresetsModel(string key, string fileName) : base(key)
{
PulseTime = 150;
DigitSpacingMs = 150;
ImagesLocalHostPrefix = "http://" + CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS,0);
ImagesPathPrefix = @"/presets/images.zip/";
ListPathPrefix = @"/html/presets/lists/";
UseLocalImageStorage = true;
SetFileName(fileName);
ImagesLocalHostPrefix = "http://" + CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0);
ImagesPathPrefix = @"/presets/images.zip/";
ListPathPrefix = @"/html/presets/lists/";
//ListWatcher = new FileSystemWatcher(@"\HTML\presets\lists");
//ListWatcher.NotifyFilter = NotifyFilters.LastWrite;
//ListWatcher.EnableRaisingEvents = true;
//ListWatcher.Changed += ListWatcher_Changed;
InitSuccess = true;
}
SetFileName(fileName);
_initSuccess = true;
}
public event PresetRecalledCallback PresetRecalled;
public event PresetsSavedCallback PresetsSaved;
public int PulseTime { get; set; }
public int DigitSpacingMs { get; set; }
public bool PresetsAreLoaded { get; private set; }
public List<PresetChannel> PresetsList { get; private set; }
public int Count
{
get { return PresetsList != null ? PresetsList.Count : 0; }
}
public bool UseLocalImageStorage { get; set; }
public string ImagesLocalHostPrefix { get; set; }
public string ImagesPathPrefix { get; set; }
public string ListPathPrefix { get; set; }
public event EventHandler PresetsLoaded;
public void SetFileName(string path)
{
FilePath = ListPathPrefix + path;
LoadChannels();
}
public void SetFileName(string path)
{
_filePath = ListPathPrefix + path;
public void LoadChannels()
{
PresetsAreLoaded = false;
try
{
var pl = JsonConvert.DeserializeObject<PresetsList>(Crestron.SimplSharp.CrestronIO.File.ReadToEnd(FilePath, Encoding.ASCII));
Name = pl.Name;
_PresetsList = pl.Channels;
}
catch (Exception e)
{
Debug.Console(2, this, "LoadChannels: Error reading presets file. These presets will be empty:\r '{0}'\r Error:{1}", FilePath, e.Message);
// Just save a default empty list
_PresetsList = new List<PresetChannel>();
}
PresetsAreLoaded = true;
Debug.Console(2, this, "Setting presets file path to {0}", _filePath);
LoadChannels();
}
var handler = PresetsLoaded;
if (handler != null)
handler(this, EventArgs.Empty);
}
public void LoadChannels()
{
try
{
_fileOps.Enter();
public void Dial(int presetNum)
{
if (presetNum <= _PresetsList.Count)
Dial(_PresetsList[presetNum - 1].Channel);
}
Debug.Console(2, this, "Loading presets from {0}", _filePath);
PresetsAreLoaded = false;
try
{
var pl = JsonConvert.DeserializeObject<PresetsList>(File.ReadToEnd(_filePath, Encoding.ASCII));
Name = pl.Name;
PresetsList = pl.Channels;
}
catch (Exception e)
{
Debug.Console(2, this,
"LoadChannels: Error reading presets file. These presets will be empty:\r '{0}'\r Error:{1}",
_filePath, e.Message);
// Just save a default empty list
PresetsList = new List<PresetChannel>();
}
PresetsAreLoaded = true;
public void Dial(string chanNum)
{
if (DialIsRunning || !InitSuccess) return;
if (DialFunctions == null)
{
Debug.Console(1, "DevicePresets '{0}', not attached to keypad device. Ignoring channel", Key);
return;
}
var handler = PresetsLoaded;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
finally
{
_fileOps.Leave();
}
}
DialIsRunning = true;
CrestronInvoke.BeginInvoke(o =>
{
foreach (var c in chanNum.ToCharArray())
{
if (DialFunctions.ContainsKey(c))
Pulse(DialFunctions[c]);
CrestronEnvironment.Sleep(DigitSpacingMS);
}
public void Dial(int presetNum)
{
if (presetNum <= PresetsList.Count)
{
Dial(PresetsList[presetNum - 1].Channel);
}
}
if (EnterFunction != null)
Pulse(EnterFunction);
DialIsRunning = false;
});
}
public void Dial(string chanNum)
{
if (_dialIsRunning || !_initSuccess)
{
return;
}
if (_dialFunctions == null)
{
Debug.Console(1, "DevicePresets '{0}', not attached to keypad device. Ignoring channel", Key);
return;
}
void Pulse(Action<bool> act)
{
act(true);
CrestronEnvironment.Sleep(PulseTime);
act(false);
}
_dialIsRunning = true;
CrestronInvoke.BeginInvoke(o =>
{
foreach (var c in chanNum.ToCharArray())
{
if (_dialFunctions.ContainsKey(c))
{
Pulse(_dialFunctions[c]);
}
CrestronEnvironment.Sleep(DigitSpacingMs);
}
/// <summary>
/// Event handler for filesystem watcher. When directory changes, this is called
/// </summary>
//void ListWatcher_Changed(object sender, FileSystemEventArgs e)
//{
// Debug.Console(1, this, "folder modified: {0}", e.FullPath);
// if (e.FullPath.Equals(FilePath, StringComparison.OrdinalIgnoreCase))
// {
// Debug.Console(1, this, "File changed: {0}", e.ChangeType);
// LoadChannels();
// }
//}
}
if (_enterFunction != null)
{
Pulse(_enterFunction);
}
_dialIsRunning = false;
});
if (_setTopBox == null) return;
OnPresetRecalled(_setTopBox, chanNum);
}
public void Dial(int presetNum, ISetTopBoxNumericKeypad setTopBox)
{
if (presetNum <= PresetsList.Count)
{
Dial(PresetsList[presetNum - 1].Channel, setTopBox);
}
}
public void Dial(string chanNum, ISetTopBoxNumericKeypad setTopBox)
{
_dialFunctions = new Dictionary<char, Action<bool>>(10)
{
{'1', setTopBox.Digit1},
{'2', setTopBox.Digit2},
{'3', setTopBox.Digit3},
{'4', setTopBox.Digit4},
{'5', setTopBox.Digit5},
{'6', setTopBox.Digit6},
{'7', setTopBox.Digit7},
{'8', setTopBox.Digit8},
{'9', setTopBox.Digit9},
{'0', setTopBox.Digit0},
{'-', setTopBox.Dash}
};
_enterFunction = setTopBox.KeypadEnter;
OnPresetRecalled(setTopBox, chanNum);
Dial(chanNum);
}
private void OnPresetRecalled(ISetTopBoxNumericKeypad setTopBox, string channel)
{
var handler = PresetRecalled;
if (handler == null)
{
return;
}
handler(setTopBox, channel);
}
public void UpdatePreset(int index, PresetChannel preset)
{
if (index >= PresetsList.Count)
{
return;
}
PresetsList[index] = preset;
SavePresets();
OnPresetsSaved();
}
public void UpdatePresets(List<PresetChannel> presets)
{
PresetsList = presets;
SavePresets();
OnPresetsSaved();
}
private void SavePresets()
{
try
{
_fileOps.Enter();
var pl = new PresetsList {Channels = PresetsList, Name = Name};
var json = JsonConvert.SerializeObject(pl, Formatting.Indented);
using (var file = File.Open(_filePath, FileMode.Truncate))
{
file.Write(json, Encoding.UTF8);
}
}
finally
{
_fileOps.Leave();
}
}
private void OnPresetsSaved()
{
var handler = PresetsSaved;
if (handler == null) return;
handler(PresetsList);
}
private void Pulse(Action<bool> act)
{
act(true);
CrestronEnvironment.Sleep(PulseTime);
act(false);
}
}
}

View File

@@ -10,19 +10,22 @@ namespace PepperDash.Essentials.Core.Presets
public class PresetChannel
{
[JsonProperty(Required = Required.Always)]
[JsonProperty(Required = Required.Always,PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(Required = Required.Always)]
[JsonProperty(Required = Required.Always, PropertyName = "iconUrl")]
public string IconUrl { get; set; }
[JsonProperty(Required = Required.Always)]
[JsonProperty(Required = Required.Always, PropertyName = "channel")]
public string Channel { get; set; }
}
public class PresetsList
{
[JsonProperty(Required=Required.Always)]
[JsonProperty(Required=Required.Always,PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(Required = Required.Always)]
[JsonProperty(Required = Required.Always, PropertyName = "channels")]
public List<PresetChannel> Channels { get; set; }
}
}

View File

@@ -0,0 +1,41 @@
using System.Collections.Generic;
using Crestron.SimplSharp.Scheduler;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.Config
{
public class EssentialsRoomScheduledEventsConfig
{
[JsonProperty("scheduledEvents")]
public List<ScheduledEventConfig> ScheduledEvents;
}
public class ScheduledEventConfig
{
[JsonProperty("key")]
public string Key;
[JsonProperty("name")]
public string Name;
[JsonProperty("days")]
public ScheduledEventCommon.eWeekDays Days;
[JsonProperty("time")]
public string Time;
[JsonProperty("actions")]
public List<DeviceActionWrapper> Actions;
[JsonProperty("persistent")]
public bool Persistent;
[JsonProperty("acknowledgeable")]
public bool Acknowledgeable;
[JsonProperty("enable")]
public bool Enable;
}
}

View File

@@ -1,58 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.Scheduler;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Devices;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials.Core
{
/// <summary>
///
/// </summary>
public abstract class EssentialsRoomBase : ReconfigurableDevice
{
/// <summary>
///
/// </summary>
public BoolFeedback OnFeedback { get; private set; }
/// <summary>
/// Fires when the RoomOccupancy object is set
/// </summary>
public event EventHandler<EventArgs> RoomOccupancyIsSet;
public BoolFeedback IsWarmingUpFeedback { get; private set; }
public BoolFeedback IsCoolingDownFeedback { get; private set; }
public IOccupancyStatusProvider RoomOccupancy { get; private set; }
public bool OccupancyStatusProviderIsRemote { get; private set; }
protected abstract Func<bool> IsWarmingFeedbackFunc { get; }
protected abstract Func<bool> IsCoolingFeedbackFunc { get; }
/// <summary>
/// Indicates if this room is Mobile Control Enabled
/// </summary>
public bool IsMobileControlEnabled { get; private set; }
/// <summary>
/// The bridge for this room if Mobile Control is enabled
/// </summary>
public IMobileControlRoomBridge MobileControlRoomBridge { get; private set; }
/// <summary>
/// The config name of the source list
/// </summary>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.Scheduler;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Devices;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials.Core
{
/// <summary>
///
/// </summary>
public abstract class EssentialsRoomBase : ReconfigurableDevice
{
/// <summary>
///
/// </summary>
public BoolFeedback OnFeedback { get; private set; }
/// <summary>
/// Fires when the RoomOccupancy object is set
/// </summary>
public event EventHandler<EventArgs> RoomOccupancyIsSet;
public BoolFeedback IsWarmingUpFeedback { get; private set; }
public BoolFeedback IsCoolingDownFeedback { get; private set; }
public IOccupancyStatusProvider RoomOccupancy { get; private set; }
public bool OccupancyStatusProviderIsRemote { get; private set; }
protected abstract Func<bool> IsWarmingFeedbackFunc { get; }
protected abstract Func<bool> IsCoolingFeedbackFunc { get; }
/// <summary>
/// Indicates if this room is Mobile Control Enabled
/// </summary>
public bool IsMobileControlEnabled { get; private set; }
/// <summary>
/// The bridge for this room if Mobile Control is enabled
/// </summary>
public IMobileControlRoomBridge MobileControlRoomBridge { get; private set; }
/// <summary>
/// The config name of the source list
/// </summary>
///
protected string _SourceListKey;
protected string _SourceListKey;
public virtual string SourceListKey {
get
{
@@ -63,306 +63,306 @@ namespace PepperDash.Essentials.Core
_SourceListKey = value;
}
}
/// <summary>
/// Timer used for informing the UIs of a shutdown
/// </summary>
public SecondsCountdownTimer ShutdownPromptTimer { get; private set; }
/// <summary>
///
/// </summary>
public int ShutdownPromptSeconds { get; set; }
public int ShutdownVacancySeconds { get; set; }
public eShutdownType ShutdownType { get; private set; }
public EssentialsRoomEmergencyBase Emergency { get; set; }
public Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; set; }
public string LogoUrlLightBkgnd { get; set; }
public string LogoUrlDarkBkgnd { get; set; }
protected SecondsCountdownTimer RoomVacancyShutdownTimer { get; private set; }
public eVacancyMode VacancyMode { get; private set; }
/// <summary>
/// Seconds after vacancy prompt is displayed until shutdown
/// </summary>
protected int RoomVacancyShutdownSeconds;
/// <summary>
/// Seconds after vacancy detected until prompt is displayed
/// </summary>
protected int RoomVacancyShutdownPromptSeconds;
/// <summary>
///
/// </summary>
protected abstract Func<bool> OnFeedbackFunc { get; }
protected Dictionary<IBasicVolumeWithFeedback, uint> SavedVolumeLevels = new Dictionary<IBasicVolumeWithFeedback, uint>();
/// <summary>
/// When volume control devices change, should we zero the one that we are leaving?
/// </summary>
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; }
public EssentialsRoomBase(DeviceConfig config)
: base(config)
{
// Setup the ShutdownPromptTimer
ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer");
ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) =>
{
if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue)
ShutdownType = eShutdownType.None;
};
ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered
ShutdownPromptSeconds = 60;
ShutdownVacancySeconds = 120;
ShutdownType = eShutdownType.None;
RoomVacancyShutdownTimer = new SecondsCountdownTimer(Key + "-vacancyOffTimer");
//RoomVacancyShutdownTimer.IsRunningFeedback.OutputChange += (o, a) =>
//{
// if (!RoomVacancyShutdownTimer.IsRunningFeedback.BoolValue)
// ShutdownType = ShutdownType.Vacancy;
//};
RoomVacancyShutdownTimer.HasFinished += new EventHandler<EventArgs>(RoomVacancyShutdownPromptTimer_HasFinished); // Shutdown is triggered
RoomVacancyShutdownPromptSeconds = 1500; // 25 min to prompt warning
RoomVacancyShutdownSeconds = 240; // 4 min after prompt will trigger shutdown prompt
VacancyMode = eVacancyMode.None;
OnFeedback = new BoolFeedback(OnFeedbackFunc);
IsWarmingUpFeedback = new BoolFeedback(IsWarmingFeedbackFunc);
IsCoolingDownFeedback = new BoolFeedback(IsCoolingFeedbackFunc);
AddPostActivationAction(() =>
{
if (RoomOccupancy != null)
OnRoomOccupancyIsSet();
});
}
public override bool CustomActivate()
{
SetUpMobileControl();
return base.CustomActivate();
}
/// <summary>
/// If mobile control is enabled, sets the appropriate properties
/// </summary>
void SetUpMobileControl()
{
var mcBridgeKey = string.Format("mobileControlBridge-{0}", Key);
var mcBridge = DeviceManager.GetDeviceForKey(mcBridgeKey);
if (mcBridge == null)
{
Debug.Console(1, this, "*********************Mobile Control Bridge Not found for this room.");
IsMobileControlEnabled = false;
return;
}
else
{
MobileControlRoomBridge = mcBridge as IMobileControlRoomBridge;
Debug.Console(1, this, "*********************Mobile Control Bridge found and enabled for this room");
IsMobileControlEnabled = true;
}
}
void RoomVacancyShutdownPromptTimer_HasFinished(object sender, EventArgs e)
{
switch (VacancyMode)
{
case eVacancyMode.None:
StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
break;
case eVacancyMode.InInitialVacancy:
StartRoomVacancyTimer(eVacancyMode.InShutdownWarning);
break;
case eVacancyMode.InShutdownWarning:
{
StartShutdown(eShutdownType.Vacancy);
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting Down due to vacancy.");
break;
}
default:
break;
}
}
/// <summary>
///
/// </summary>
/// <param name="type"></param>
public void StartShutdown(eShutdownType type)
{
// Check for shutdowns running. Manual should override other shutdowns
if (type == eShutdownType.Manual)
ShutdownPromptTimer.SecondsToCount = ShutdownPromptSeconds;
else if (type == eShutdownType.Vacancy)
ShutdownPromptTimer.SecondsToCount = ShutdownVacancySeconds;
ShutdownType = type;
ShutdownPromptTimer.Start();
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "ShutdownPromptTimer Started. Type: {0}. Seconds: {1}", ShutdownType, ShutdownPromptTimer.SecondsToCount);
}
public void StartRoomVacancyTimer(eVacancyMode mode)
{
if (mode == eVacancyMode.None)
RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownPromptSeconds;
else if (mode == eVacancyMode.InInitialVacancy)
RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownSeconds;
else if (mode == eVacancyMode.InShutdownWarning)
RoomVacancyShutdownTimer.SecondsToCount = 60;
VacancyMode = mode;
RoomVacancyShutdownTimer.Start();
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Vacancy Timer Started. Mode: {0}. Seconds: {1}", VacancyMode, RoomVacancyShutdownTimer.SecondsToCount);
}
/// <summary>
/// Resets the vacancy mode and shutsdwon the room
/// </summary>
public void Shutdown()
{
VacancyMode = eVacancyMode.None;
EndShutdown();
}
/// <summary>
/// This method is for the derived class to define it's specific shutdown
/// requirements but should not be called directly. It is called by Shutdown()
/// </summary>
protected abstract void EndShutdown();
/// <summary>
/// Override this to implement a default volume level(s) method
/// </summary>
public abstract void SetDefaultLevels();
/// <summary>
/// Sets the object to be used as the IOccupancyStatusProvider for the room. Can be an Occupancy Aggregator or a specific device
/// </summary>
/// <param name="statusProvider"></param>
public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes)
{
if (statusProvider == null)
{
Debug.Console(0, this, "ERROR: Occupancy sensor device is null");
return;
}
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Room Occupancy set to device: '{0}'", (statusProvider as Device).Key);
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Timeout Minutes from Config is: {0}", timeoutMinutes);
// If status provider is fusion, set flag to remote
if (statusProvider is Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase)
OccupancyStatusProviderIsRemote = true;
if(timeoutMinutes > 0)
RoomVacancyShutdownSeconds = timeoutMinutes * 60;
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "RoomVacancyShutdownSeconds set to {0}", RoomVacancyShutdownSeconds);
RoomOccupancy = statusProvider;
RoomOccupancy.RoomIsOccupiedFeedback.OutputChange -= RoomIsOccupiedFeedback_OutputChange;
RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
OnRoomOccupancyIsSet();
}
void OnRoomOccupancyIsSet()
{
var handler = RoomOccupancyIsSet;
if (handler != null)
handler(this, new EventArgs());
}
/// <summary>
/// To allow base class to power room on to last source
/// </summary>
public abstract void PowerOnToDefaultOrLastSource();
/// <summary>
/// To allow base class to power room on to default source
/// </summary>
/// <returns></returns>
public abstract bool RunDefaultPresentRoute();
void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e)
{
if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false)
{
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Vacancy Detected");
// Trigger the timer when the room is vacant
StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
}
else
{
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Occupancy Detected");
// Reset the timer when the room is occupied
RoomVacancyShutdownTimer.Cancel();
}
}
/// <summary>
/// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed
/// </summary>
/// <param name="o"></param>
public abstract void RoomVacatedForTimeoutPeriod(object o);
}
/// <summary>
/// To describe the various ways a room may be shutting down
/// </summary>
public enum eShutdownType
{
None = 0,
External,
Manual,
Vacancy
}
public enum eVacancyMode
{
None = 0,
InInitialVacancy,
InShutdownWarning
}
/// <summary>
///
/// </summary>
public enum eWarmingCoolingMode
{
None,
Warming,
Cooling
}
public abstract class EssentialsRoomEmergencyBase : IKeyed
{
public string Key { get; private set; }
public EssentialsRoomEmergencyBase(string key)
{
Key = key;
}
}
}
/// <summary>
/// Timer used for informing the UIs of a shutdown
/// </summary>
public SecondsCountdownTimer ShutdownPromptTimer { get; private set; }
/// <summary>
///
/// </summary>
public int ShutdownPromptSeconds { get; set; }
public int ShutdownVacancySeconds { get; set; }
public eShutdownType ShutdownType { get; private set; }
public EssentialsRoomEmergencyBase Emergency { get; set; }
public Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; set; }
public string LogoUrlLightBkgnd { get; set; }
public string LogoUrlDarkBkgnd { get; set; }
protected SecondsCountdownTimer RoomVacancyShutdownTimer { get; private set; }
public eVacancyMode VacancyMode { get; private set; }
/// <summary>
/// Seconds after vacancy prompt is displayed until shutdown
/// </summary>
protected int RoomVacancyShutdownSeconds;
/// <summary>
/// Seconds after vacancy detected until prompt is displayed
/// </summary>
protected int RoomVacancyShutdownPromptSeconds;
/// <summary>
///
/// </summary>
protected abstract Func<bool> OnFeedbackFunc { get; }
protected Dictionary<IBasicVolumeWithFeedback, uint> SavedVolumeLevels = new Dictionary<IBasicVolumeWithFeedback, uint>();
/// <summary>
/// When volume control devices change, should we zero the one that we are leaving?
/// </summary>
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; }
public EssentialsRoomBase(DeviceConfig config)
: base(config)
{
// Setup the ShutdownPromptTimer
ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer");
ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) =>
{
if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue)
ShutdownType = eShutdownType.None;
};
ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered
ShutdownPromptSeconds = 60;
ShutdownVacancySeconds = 120;
ShutdownType = eShutdownType.None;
RoomVacancyShutdownTimer = new SecondsCountdownTimer(Key + "-vacancyOffTimer");
//RoomVacancyShutdownTimer.IsRunningFeedback.OutputChange += (o, a) =>
//{
// if (!RoomVacancyShutdownTimer.IsRunningFeedback.BoolValue)
// ShutdownType = ShutdownType.Vacancy;
//};
RoomVacancyShutdownTimer.HasFinished += new EventHandler<EventArgs>(RoomVacancyShutdownPromptTimer_HasFinished); // Shutdown is triggered
RoomVacancyShutdownPromptSeconds = 1500; // 25 min to prompt warning
RoomVacancyShutdownSeconds = 240; // 4 min after prompt will trigger shutdown prompt
VacancyMode = eVacancyMode.None;
OnFeedback = new BoolFeedback(OnFeedbackFunc);
IsWarmingUpFeedback = new BoolFeedback(IsWarmingFeedbackFunc);
IsCoolingDownFeedback = new BoolFeedback(IsCoolingFeedbackFunc);
AddPostActivationAction(() =>
{
if (RoomOccupancy != null)
OnRoomOccupancyIsSet();
});
}
public override bool CustomActivate()
{
SetUpMobileControl();
return base.CustomActivate();
}
/// <summary>
/// If mobile control is enabled, sets the appropriate properties
/// </summary>
void SetUpMobileControl()
{
var mcBridgeKey = string.Format("mobileControlBridge-{0}", Key);
var mcBridge = DeviceManager.GetDeviceForKey(mcBridgeKey);
if (mcBridge == null)
{
Debug.Console(1, this, "*********************Mobile Control Bridge Not found for this room.");
IsMobileControlEnabled = false;
return;
}
else
{
MobileControlRoomBridge = mcBridge as IMobileControlRoomBridge;
Debug.Console(1, this, "*********************Mobile Control Bridge found and enabled for this room");
IsMobileControlEnabled = true;
}
}
void RoomVacancyShutdownPromptTimer_HasFinished(object sender, EventArgs e)
{
switch (VacancyMode)
{
case eVacancyMode.None:
StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
break;
case eVacancyMode.InInitialVacancy:
StartRoomVacancyTimer(eVacancyMode.InShutdownWarning);
break;
case eVacancyMode.InShutdownWarning:
{
StartShutdown(eShutdownType.Vacancy);
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting Down due to vacancy.");
break;
}
default:
break;
}
}
/// <summary>
///
/// </summary>
/// <param name="type"></param>
public void StartShutdown(eShutdownType type)
{
// Check for shutdowns running. Manual should override other shutdowns
if (type == eShutdownType.Manual)
ShutdownPromptTimer.SecondsToCount = ShutdownPromptSeconds;
else if (type == eShutdownType.Vacancy)
ShutdownPromptTimer.SecondsToCount = ShutdownVacancySeconds;
ShutdownType = type;
ShutdownPromptTimer.Start();
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "ShutdownPromptTimer Started. Type: {0}. Seconds: {1}", ShutdownType, ShutdownPromptTimer.SecondsToCount);
}
public void StartRoomVacancyTimer(eVacancyMode mode)
{
if (mode == eVacancyMode.None)
RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownPromptSeconds;
else if (mode == eVacancyMode.InInitialVacancy)
RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownSeconds;
else if (mode == eVacancyMode.InShutdownWarning)
RoomVacancyShutdownTimer.SecondsToCount = 60;
VacancyMode = mode;
RoomVacancyShutdownTimer.Start();
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Vacancy Timer Started. Mode: {0}. Seconds: {1}", VacancyMode, RoomVacancyShutdownTimer.SecondsToCount);
}
/// <summary>
/// Resets the vacancy mode and shutsdwon the room
/// </summary>
public void Shutdown()
{
VacancyMode = eVacancyMode.None;
EndShutdown();
}
/// <summary>
/// This method is for the derived class to define it's specific shutdown
/// requirements but should not be called directly. It is called by Shutdown()
/// </summary>
protected abstract void EndShutdown();
/// <summary>
/// Override this to implement a default volume level(s) method
/// </summary>
public abstract void SetDefaultLevels();
/// <summary>
/// Sets the object to be used as the IOccupancyStatusProvider for the room. Can be an Occupancy Aggregator or a specific device
/// </summary>
/// <param name="statusProvider"></param>
public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes)
{
if (statusProvider == null)
{
Debug.Console(0, this, "ERROR: Occupancy sensor device is null");
return;
}
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Room Occupancy set to device: '{0}'", (statusProvider as Device).Key);
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Timeout Minutes from Config is: {0}", timeoutMinutes);
// If status provider is fusion, set flag to remote
if (statusProvider is Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase)
OccupancyStatusProviderIsRemote = true;
if(timeoutMinutes > 0)
RoomVacancyShutdownSeconds = timeoutMinutes * 60;
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "RoomVacancyShutdownSeconds set to {0}", RoomVacancyShutdownSeconds);
RoomOccupancy = statusProvider;
RoomOccupancy.RoomIsOccupiedFeedback.OutputChange -= RoomIsOccupiedFeedback_OutputChange;
RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
OnRoomOccupancyIsSet();
}
void OnRoomOccupancyIsSet()
{
var handler = RoomOccupancyIsSet;
if (handler != null)
handler(this, new EventArgs());
}
/// <summary>
/// To allow base class to power room on to last source
/// </summary>
public abstract void PowerOnToDefaultOrLastSource();
/// <summary>
/// To allow base class to power room on to default source
/// </summary>
/// <returns></returns>
public abstract bool RunDefaultPresentRoute();
void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e)
{
if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false)
{
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Vacancy Detected");
// Trigger the timer when the room is vacant
StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
}
else
{
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Occupancy Detected");
// Reset the timer when the room is occupied
RoomVacancyShutdownTimer.Cancel();
}
}
/// <summary>
/// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed
/// </summary>
/// <param name="o"></param>
public abstract void RoomVacatedForTimeoutPeriod(object o);
}
/// <summary>
/// To describe the various ways a room may be shutting down
/// </summary>
public enum eShutdownType
{
None = 0,
External,
Manual,
Vacancy
}
public enum eVacancyMode
{
None = 0,
InInitialVacancy,
InShutdownWarning
}
/// <summary>
///
/// </summary>
public enum eWarmingCoolingMode
{
None,
Warming,
Cooling
}
public abstract class EssentialsRoomEmergencyBase : IKeyed
{
public string Key { get; private set; }
public EssentialsRoomEmergencyBase(string key)
{
Key = key;
}
}
}

View File

@@ -41,6 +41,14 @@ namespace PepperDash.Essentials.Core
}
/// <summary>
/// Simplified routing direct from source to destination
/// </summary>
public interface IRunDirectRouteAction
{
void RunDirectRoute(string sourceKey, string destinationKey);
}
/// <summary>
/// For rooms that default presentation only routing
/// </summary>

View File

@@ -59,7 +59,7 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// For fixed-source endpoint devices
/// </summary>
[Obsolete]
[Obsolete("Please switch to IRoutingSink")]
public interface IRoutingSinkNoSwitching : IRoutingSink
{
@@ -111,10 +111,87 @@ namespace PepperDash.Essentials.Core
IntFeedback AudioVideoSourceNumericFeedback { get; }
}
/// <summary>
/// <summary>
/// Defines an IRmcRouting with a feedback event
/// </summary>
public interface ITxRoutingWithFeedback : ITxRouting
{
}
/// <summary>
/// Defines an IRmcRouting with a feedback event
/// </summary>
public interface IRmcRoutingWithFeedback : IRmcRouting
{
}
/// <summary>
/// Defines an IRoutingOutputs devices as being a source - the start of the chain
/// </summary>
public interface IRoutingSource : IRoutingOutputs
{
}
/// <summary>
/// Defines an event structure for reporting output route data
/// </summary>
public interface IRoutingFeedback : IKeyName
{
event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
//void OnSwitchChange(RoutingNumericEventArgs e);
}
/// <summary>
/// Defines an IRoutingNumeric with a feedback event
/// </summary>
public interface IRoutingNumericWithFeedback : IRoutingNumeric, IRoutingFeedback
{
}
/// <summary>
/// Defines an IRouting with a feedback event
/// </summary>
public interface IRoutingWithFeedback : IRouting, IRoutingFeedback
{
}
public class RoutingNumericEventArgs : EventArgs
{
public uint? Output { get; set; }
public uint? Input { get; set; }
public eRoutingSignalType SigType { get; set; }
public RoutingInputPort InputPort { get; set; }
public RoutingOutputPort OutputPort { get; set; }
public RoutingNumericEventArgs(uint output, uint input, eRoutingSignalType sigType) : this(output, input, null, null, sigType)
{
}
public RoutingNumericEventArgs(RoutingOutputPort outputPort, RoutingInputPort inputPort,
eRoutingSignalType sigType)
: this(null, null, outputPort, inputPort, sigType)
{
}
public RoutingNumericEventArgs()
: this(null, null, null, null, 0)
{
}
public RoutingNumericEventArgs(uint? output, uint? input, RoutingOutputPort outputPort,
RoutingInputPort inputPort, eRoutingSignalType sigType)
{
OutputPort = outputPort;
InputPort = inputPort;
Output = output;
Input = input;
SigType = sigType;
}
}
}

View File

@@ -17,7 +17,7 @@ using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.DM.AirMedia
{
[Description("Wrapper class for an AM-200 or AM-300")]
public class AirMediaController : CrestronGenericBridgeableBaseDevice, IRoutingNumeric, IIROutputPorts, IComPorts
public class AirMediaController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IIROutputPorts, IComPorts
{
public AmX00 AirMedia { get; private set; }
@@ -29,6 +29,10 @@ namespace PepperDash.Essentials.DM.AirMedia
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
public BoolFeedback IsInSessionFeedback { get; private set; }
public IntFeedback ErrorFeedback { get; private set; }
public IntFeedback NumberOfUsersConnectedFeedback { get; set; }
@@ -43,6 +47,7 @@ namespace PepperDash.Essentials.DM.AirMedia
public AirMediaController(string key, string name, AmX00 device, DeviceConfig dc, AirMediaPropertiesConfig props)
: base(key, name, device)
{
AirMedia = device;
DeviceConfig = dc;
@@ -53,21 +58,36 @@ namespace PepperDash.Essentials.DM.AirMedia
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
InputPorts.Add(new RoutingInputPort(DmPortName.Osd, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.None, new Action(SelectPinPointUxLandingPage), this));
eRoutingPortConnectionType.None, new Action(SelectPinPointUxLandingPage), this)
{
FeedbackMatchObject = 0
});
InputPorts.Add(new RoutingInputPort(DmPortName.AirMediaIn, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Streaming, new Action(SelectAirMedia), this));
eRoutingPortConnectionType.Streaming, new Action(SelectAirMedia), this)
{
FeedbackMatchObject = 1
});
InputPorts.Add(new RoutingInputPort(DmPortName.HdmiIn, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, new Action(SelectHdmiIn), this));
eRoutingPortConnectionType.Hdmi, new Action(SelectHdmiIn), this)
{
FeedbackMatchObject = 2
});
InputPorts.Add(new RoutingInputPort(DmPortName.AirBoardIn, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.None, new Action(SelectAirboardIn), this));
eRoutingPortConnectionType.None, new Action(SelectAirboardIn), this)
{
FeedbackMatchObject = 4
});
if (AirMedia is Am300)
{
InputPorts.Add(new RoutingInputPort(DmPortName.DmIn, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.DmCat, new Action(SelectDmIn), this));
eRoutingPortConnectionType.DmCat, new Action(SelectDmIn), this)
{
FeedbackMatchObject = 3
});
}
OutputPorts.Add(new RoutingOutputPort(DmPortName.HdmiOut, eRoutingSignalType.AudioVideo,
@@ -153,6 +173,17 @@ namespace PepperDash.Essentials.DM.AirMedia
SerialNumberFeedback.LinkInputSig(trilist.StringInput[joinMap.SerialNumberFeedback.JoinNumber]);
}
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
void AirMedia_AirMediaChange(object sender, Crestron.SimplSharpPro.DeviceSupport.GenericEventArgs args)
{
if (args.EventId == AirMediaInputSlot.AirMediaStatusFeedbackEventId)
@@ -172,12 +203,20 @@ namespace PepperDash.Essentials.DM.AirMedia
void DisplayControl_DisplayControlChange(object sender, Crestron.SimplSharpPro.DeviceSupport.GenericEventArgs args)
{
if (args.EventId == AmX00.VideoOutFeedbackEventId)
{
VideoOutFeedback.FireUpdate();
var localInputPort =
InputPorts.FirstOrDefault(p => (int) p.FeedbackMatchObject == VideoOutFeedback.UShortValue);
OnSwitchChange(new RoutingNumericEventArgs(1, VideoOutFeedback.UShortValue, OutputPorts.First(),
localInputPort, eRoutingSignalType.AudioVideo));
}
else if (args.EventId == AmX00.EnableAutomaticRoutingFeedbackEventId)
AutomaticInputRoutingEnabledFeedback.FireUpdate();
}
void HdmiIn_StreamChange(Crestron.SimplSharpPro.DeviceSupport.Stream stream, Crestron.SimplSharpPro.DeviceSupport.StreamEventArgs args)
void HdmiIn_StreamChange(Stream stream, Crestron.SimplSharpPro.DeviceSupport.StreamEventArgs args)
{
if (args.EventId == DMInputEventIds.SourceSyncEventId)
HdmiVideoSyncDetectedFeedback.FireUpdate();

View File

@@ -21,12 +21,15 @@ namespace PepperDash.Essentials.DM {
/// Builds a controller for basic DM-RMCs with Com and IR ports and no control functions
///
/// </summary>
public class DmBladeChassisController : CrestronGenericBridgeableBaseDevice, IDmSwitch, IRoutingNumeric
public class DmBladeChassisController : CrestronGenericBridgeableBaseDevice, IDmSwitch, IRoutingNumericWithFeedback
{
public DMChassisPropertiesConfig PropertiesConfig { get; set; }
public Switch Chassis { get; private set; }
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
// Feedbacks for EssentialDM
public Dictionary<uint, IntFeedback> VideoOutputFeedbacks { get; private set; }
public Dictionary<uint, IntFeedback> AudioOutputFeedbacks { get; private set; }
@@ -287,6 +290,15 @@ namespace PepperDash.Essentials.DM {
}
}
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
void AddHdmiInBladePorts(uint number, ICec cecPort) {
@@ -377,7 +389,10 @@ namespace PepperDash.Essentials.DM {
void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType) {
var portKey = string.Format("inputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding input port '{0}'", portKey);
var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this);
var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this)
{
FeedbackMatchObject = Chassis.Inputs[cardNum]
};
InputPorts.Add(inputPort);
}
@@ -385,19 +400,20 @@ namespace PepperDash.Essentials.DM {
/// <summary>
/// Adds InputPort and sets Port as ICec object
/// </summary>
void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, ICec cecPort) {
private void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType,
eRoutingPortConnectionType portType, ICec cecPort)
{
var portKey = string.Format("inputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding input port '{0}'", portKey);
var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this);
var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this)
{
FeedbackMatchObject = Chassis.Inputs[cardNum]
};
if (inputPort != null) {
if (cecPort != null)
inputPort.Port = cecPort;
if (cecPort != null)
inputPort.Port = cecPort;
InputPorts.Add(inputPort);
}
else
Debug.Console(2, this, "inputPort is null");
InputPorts.Add(inputPort);
}
@@ -407,7 +423,10 @@ namespace PepperDash.Essentials.DM {
void AddOutputPortWithDebug(string cardName, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector) {
var portKey = string.Format("{0}--{1}", cardName, portName);
Debug.Console(2, this, "Adding output port '{0}'", portKey);
OutputPorts.Add(new RoutingOutputPort(portKey, sigType, portType, selector, this));
OutputPorts.Add(new RoutingOutputPort(portKey, sigType, portType, selector, this)
{
FeedbackMatchObject = Chassis.Outputs[(uint)selector]
});
}
@@ -458,54 +477,84 @@ namespace PepperDash.Essentials.DM {
}
}
}
///
/// </summary>
void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args)
private void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args)
{
var output = args.Number;
switch (args.EventId) {
case DMOutputEventIds.VolumeEventId: {
if (VolumeControls.ContainsKey(output)) {
VolumeControls[args.Number].VolumeEventFromChassis();
}
break;
switch (args.EventId)
{
case DMOutputEventIds.VolumeEventId:
{
if (VolumeControls.ContainsKey(output))
{
VolumeControls[args.Number].VolumeEventFromChassis();
}
case DMOutputEventIds.EndpointOnlineEventId: {
Debug.Console(2, this, "Output {0} DMOutputEventIds.EndpointOnlineEventId fired. EndpointOnlineFeedback State: {1}", args.Number, Chassis.Outputs[output].EndpointOnlineFeedback);
if(Chassis.Outputs[output].Endpoint != null)
Debug.Console(2, this, "Output {0} DMOutputEventIds.EndpointOnlineEventId fired. Endpoint.IsOnline State: {1}", args.Number, Chassis.Outputs[output].Endpoint.IsOnline);
break;
}
case DMOutputEventIds.EndpointOnlineEventId:
{
Debug.Console(2, this,
"Output {0} DMOutputEventIds.EndpointOnlineEventId fired. EndpointOnlineFeedback State: {1}",
args.Number, Chassis.Outputs[output].EndpointOnlineFeedback);
if (Chassis.Outputs[output].Endpoint != null)
Debug.Console(2, this,
"Output {0} DMOutputEventIds.EndpointOnlineEventId fired. Endpoint.IsOnline State: {1}",
args.Number, Chassis.Outputs[output].Endpoint.IsOnline);
OutputEndpointOnlineFeedbacks[output].FireUpdate();
break;
}
case DMOutputEventIds.OnlineFeedbackEventId: {
Debug.Console(2, this, "Output {0} DMInputEventIds.OnlineFeedbackEventId fired. State: {1}", args.Number, Chassis.Outputs[output].EndpointOnlineFeedback);
OutputEndpointOnlineFeedbacks[output].FireUpdate();
break;
}
case DMOutputEventIds.VideoOutEventId: {
if (Chassis.Outputs[output].VideoOutFeedback != null) {
Debug.Console(2, this, "DMSwitchVideo:{0} Routed Input:{1} Output:{2}'", this.Name, Chassis.Outputs[output].VideoOutFeedback.Number, output);
}
if (VideoOutputFeedbacks.ContainsKey(output)) {
VideoOutputFeedbacks[output].FireUpdate();
OutputEndpointOnlineFeedbacks[output].FireUpdate();
break;
}
case DMOutputEventIds.OnlineFeedbackEventId:
{
Debug.Console(2, this, "Output {0} DMInputEventIds.OnlineFeedbackEventId fired. State: {1}",
args.Number, Chassis.Outputs[output].EndpointOnlineFeedback);
OutputEndpointOnlineFeedbacks[output].FireUpdate();
break;
}
case DMOutputEventIds.VideoOutEventId:
{
var inputNumber = Chassis.Outputs[output].VideoOutFeedback == null ? 0 : Chassis.Outputs[output].VideoOutFeedback.Number;
Debug.Console(2, this, "DMSwitchAudioVideo:{0} Routed Input:{1} Output:{2}'", this.Name,
inputNumber, output);
if (VideoOutputFeedbacks.ContainsKey(output))
{
var localInputPort = InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == Chassis.Outputs[output].VideoOutFeedback);
var localOutputPort =
OutputPorts.FirstOrDefault(p => (DMOutput) p.FeedbackMatchObject == Chassis.Outputs[output]);
VideoOutputFeedbacks[output].FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(output,
inputNumber,
localOutputPort,
localInputPort,
eRoutingSignalType.AudioVideo));
}
if (OutputVideoRouteNameFeedbacks.ContainsKey(output)) {
OutputVideoRouteNameFeedbacks[output].FireUpdate();
}
break;
}
case DMOutputEventIds.OutputNameEventId: {
Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output);
OutputNameFeedbacks[output].FireUpdate();
break;
}
default: {
Debug.Console(2, this, "DMOutputChange fired for Output {0} with Unhandled EventId: {1}", args.Number, args.EventId);
break;
if (OutputVideoRouteNameFeedbacks.ContainsKey(output))
{
OutputVideoRouteNameFeedbacks[output].FireUpdate();
}
break;
}
case DMOutputEventIds.OutputNameEventId:
{
Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output);
OutputNameFeedbacks[output].FireUpdate();
break;
}
default:
{
Debug.Console(2, this, "DMOutputChange fired for Output {0} with Unhandled EventId: {1}",
args.Number, args.EventId);
break;
}
}
}

View File

@@ -20,12 +20,15 @@ namespace PepperDash.Essentials.DM
/// Builds a controller for basic DM-RMCs with Com and IR ports and no control functions
///
/// </summary>
[Description("Wrapper class for all DM-MD chassis variants from 8x8 to 32x32")]
public class DmChassisController : CrestronGenericBridgeableBaseDevice, IDmSwitch, IRoutingNumeric
[Description("Wrapper class for all DM-MD chassis variants from 8x8 to 32x32")]
public class DmChassisController : CrestronGenericBridgeableBaseDevice, IDmSwitch, IRoutingNumericWithFeedback
{
public DMChassisPropertiesConfig PropertiesConfig { get; set; }
public Switch Chassis { get; private set; }
public Switch Chassis { get; private set; }
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
// Feedbacks for EssentialDM
public Dictionary<uint, IntFeedback> VideoOutputFeedbacks { get; private set; }
@@ -46,7 +49,9 @@ namespace PepperDash.Essentials.DM
public BoolFeedback EnableAudioBreakawayFeedback { get; private set; }
public BoolFeedback EnableUsbBreakawayFeedback { get; private set; }
public Dictionary<uint, IntFeedback> InputCardHdcpStateFeedbacks { get; private set; }
public Dictionary<uint, IntFeedback> InputCardHdcpStateFeedbacks { get; private set; }
public Dictionary<uint, IntFeedback> InputStreamCardStateFeedbacks { get; private set; }
public Dictionary<uint, IntFeedback> OutputStreamCardStateFeedbacks { get; private set; }
public Dictionary<uint, eHdcpCapabilityType> InputCardHdcpCapabilityTypes { get; private set; }
@@ -187,7 +192,8 @@ namespace PepperDash.Essentials.DM
/// <param name="chassis"></param>
public DmChassisController(string key, string name, DmMDMnxn chassis)
: base(key, name, chassis)
{
{
Chassis = chassis;
InputPorts = new RoutingPortCollection<RoutingInputPort>();
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
@@ -219,7 +225,9 @@ namespace PepperDash.Essentials.DM
EnableUsbBreakawayFeedback =
new BoolFeedback(() => (Chassis as DmMDMnxn).EnableUSBBreakawayFeedback.BoolValue);
InputCardHdcpStateFeedbacks = new Dictionary<uint, IntFeedback>();
InputCardHdcpStateFeedbacks = new Dictionary<uint, IntFeedback>();
InputStreamCardStateFeedbacks = new Dictionary<uint, IntFeedback>();
OutputStreamCardStateFeedbacks = new Dictionary<uint, IntFeedback>();
InputCardHdcpCapabilityTypes = new Dictionary<uint, eHdcpCapabilityType>();
for (uint x = 1; x <= Chassis.NumberOfOutputs; x++)
@@ -303,6 +311,33 @@ namespace PepperDash.Essentials.DM
// return hdMdNxMHdmiOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue;
return false;
});
OutputStreamCardStateFeedbacks[tempX] = new IntFeedback(() =>
{
try
{
var outputCard = Chassis.Outputs[tempX];
if (outputCard.Card is DmcStroAV)
{
Debug.Console(2, "Found output stream card in slot: {0}.", tempX);
var streamCard = outputCard.Card as DmcStroAV;
if (streamCard.Control.StartFeedback.BoolValue == true)
return 1;
else if (streamCard.Control.StopFeedback.BoolValue == true)
return 2;
else if (streamCard.Control.PauseFeedback.BoolValue == true)
return 3;
else
return 0;
}
return 0;
}
catch (InvalidOperationException iopex)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "Error adding output stream card in slot: {0}. Error: {1}", tempX, iopex);
return 0;
}
});
}
@@ -402,6 +437,33 @@ namespace PepperDash.Essentials.DM
Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "The Input Card in slot: {0} supports HDCP 2. Please update the configuration value in the inputCardSupportsHdcp2 object to true. Error: {1}", tempX, iopex);
return 0;
}
});
InputStreamCardStateFeedbacks[tempX] = new IntFeedback(() =>
{
try
{
var inputCard = Chassis.Inputs[tempX];
if (inputCard.Card is DmcStr)
{
Debug.Console(2, "Found input stream card in slot: {0}.", tempX);
var streamCard = inputCard.Card as DmcStr;
if (streamCard.Control.StartFeedback.BoolValue == true)
return 1;
else if (streamCard.Control.StopFeedback.BoolValue == true)
return 2;
else if (streamCard.Control.PauseFeedback.BoolValue == true)
return 3;
else
return 0;
}
return 0;
}
catch (InvalidOperationException iopex)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "Error adding input stream card in slot: {0}. Error: {1}", tempX, iopex);
return 0;
}
});
}
}
@@ -737,7 +799,10 @@ namespace PepperDash.Essentials.DM
{
var portKey = string.Format("inputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding input port '{0}'", portKey);
var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this);
var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this)
{
FeedbackMatchObject = Chassis.Inputs[cardNum]
};
InputPorts.Add(inputPort);
}
@@ -749,12 +814,15 @@ namespace PepperDash.Essentials.DM
{
var portKey = string.Format("inputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding input port '{0}'", portKey);
var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this);
var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this)
{
FeedbackMatchObject = Chassis.Inputs[cardNum]
}; ;
if (cecPort != null)
inputPort.Port = cecPort;
InputPorts.Add(inputPort);
InputPorts.Add(inputPort);
}
/// <summary>
@@ -763,8 +831,16 @@ namespace PepperDash.Essentials.DM
void AddOutputPortWithDebug(string cardName, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector)
{
var portKey = string.Format("{0}--{1}", cardName, portName);
Debug.Console(2, this, "Adding output port '{0}'", portKey);
OutputPorts.Add(new RoutingOutputPort(portKey, sigType, portType, selector, this));
Debug.Console(2, this, "Adding output port '{0}'", portKey);
var outputPort = new RoutingOutputPort(portKey, sigType, portType, selector, this);
if (portName.IndexOf("Loop", StringComparison.InvariantCultureIgnoreCase) < 0)
{
outputPort.FeedbackMatchObject = Chassis.Outputs[(uint) selector];
}
OutputPorts.Add(outputPort);
}
/// <summary>
@@ -773,13 +849,17 @@ namespace PepperDash.Essentials.DM
void AddOutputPortWithDebug(string cardName, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector, ICec cecPort)
{
var portKey = string.Format("{0}--{1}", cardName, portName);
Debug.Console(2, this, "Adding output port '{0}'", portKey);
var outputPort = new RoutingOutputPort(portKey, sigType, portType, selector, this);
Debug.Console(2, this, "Adding output port '{0}'", portKey);
var outputPort = new RoutingOutputPort(portKey, sigType, portType, selector, this);
if (portName.IndexOf("Loop", StringComparison.InvariantCultureIgnoreCase) < 0)
{
outputPort.FeedbackMatchObject = Chassis.Outputs[(uint)selector];
}
if (cecPort != null)
outputPort.Port = cecPort;
OutputPorts.Add(outputPort);
OutputPorts.Add(outputPort);
}
/// <summary>
@@ -893,6 +973,19 @@ namespace PepperDash.Essentials.DM
else
Debug.Console(1, this, "No index of {0} found in InputCardHdcpCapabilityFeedbacks");
break;
}
case DMInputEventIds.StartEventId:
case DMInputEventIds.StopEventId:
case DMInputEventIds.PauseEventId:
{
Debug.Console(2, this, "DM Input {0} Stream Status EventId", args.Number);
if (InputStreamCardStateFeedbacks[args.Number] != null)
{
InputStreamCardStateFeedbacks[args.Number].FireUpdate();
}
else
Debug.Console(2, this, "No index of {0} found in InputStreamCardStateFeedbacks");
break;
}
default:
{
@@ -905,6 +998,17 @@ namespace PepperDash.Essentials.DM
{
Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error in Chassis_DMInputChange: {0}", ex);
}
}
/// <summary>
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
///
@@ -938,30 +1042,59 @@ namespace PepperDash.Essentials.DM
OutputEndpointOnlineFeedbacks[output].FireUpdate();
break;
}
case DMOutputEventIds.VideoOutEventId:
case DMOutputEventIds.VideoOutEventId:
{
if (Chassis.Outputs[output].VideoOutFeedback != null)
Debug.Console(2, this, "DMSwitchVideo:{0} Routed Input:{1} Output:{2}'", this.Name, Chassis.Outputs[output].VideoOutFeedback.Number, output);
if (VideoOutputFeedbacks.ContainsKey(output))
VideoOutputFeedbacks[output].FireUpdate();
var inputNumber = Chassis.Outputs[output].VideoOutFeedback == null ? 0 : Chassis.
Outputs[output].VideoOutFeedback.Number;
Debug.Console(2, this, "DMSwitchVideo:{0} Routed Input:{1} Output:{2}'", this.Name, inputNumber, output);
if (VideoOutputFeedbacks.ContainsKey(output))
{
var localInputPort = InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == Chassis.Outputs[output].VideoOutFeedback);
var localOutputPort =
OutputPorts.FirstOrDefault(p => (DMOutput) p.FeedbackMatchObject == Chassis.Outputs[output]);
VideoOutputFeedbacks[output].FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(output,
inputNumber,
localOutputPort,
localInputPort,
eRoutingSignalType.Video));
}
if (OutputVideoRouteNameFeedbacks.ContainsKey(output))
OutputVideoRouteNameFeedbacks[output].FireUpdate();
break;
}
case DMOutputEventIds.AudioOutEventId:
{
if (Chassis.Outputs[output].AudioOutFeedback != null)
Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name, Chassis.Outputs[output].AudioOutFeedback.Number, output);
if (AudioOutputFeedbacks.ContainsKey(output))
AudioOutputFeedbacks[output].FireUpdate();
if (OutputAudioRouteNameFeedbacks.ContainsKey(output))
OutputAudioRouteNameFeedbacks[output].FireUpdate();
case DMOutputEventIds.AudioOutEventId:
{
var inputNumber = Chassis.Outputs[output].AudioOutFeedback == null ? 0 : Chassis.
Outputs[output].AudioOutFeedback.Number;
Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name, inputNumber, output);
if (AudioOutputFeedbacks.ContainsKey(output))
{
var localInputPort = InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == Chassis.Outputs[output].AudioOutFeedback);
var localOutputPort =
OutputPorts.FirstOrDefault(p => (DMOutput)p.FeedbackMatchObject == Chassis.Outputs[output]);
AudioOutputFeedbacks[output].FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(output,
inputNumber,
localOutputPort,
localInputPort,
eRoutingSignalType.Audio));
}
if (OutputAudioRouteNameFeedbacks.ContainsKey(output))
OutputAudioRouteNameFeedbacks[output].FireUpdate();
break;
}
case DMOutputEventIds.OutputNameEventId:
@@ -981,6 +1114,19 @@ namespace PepperDash.Essentials.DM
Debug.Console(2, this, "DM Output {0} DisabledByHdcpEventId", args.Number);
OutputDisabledByHdcpFeedbacks[args.Number].FireUpdate();
break;
}
case DMOutputEventIds.StartEventId:
case DMOutputEventIds.StopEventId:
case DMOutputEventIds.PauseEventId:
{
Debug.Console(2, this, "DM Output {0} Stream Status EventId", args.Number);
if (OutputStreamCardStateFeedbacks[args.Number] != null)
{
OutputStreamCardStateFeedbacks[args.Number].FireUpdate();
}
else
Debug.Console(2, this, "No index of {0} found in OutputStreamCardStateFeedbacks");
break;
}
default:
{
@@ -1180,13 +1326,16 @@ namespace PepperDash.Essentials.DM
}
else
{
LinkHdmiInputToApi(trilist, ioSlot, joinMap, ioSlotJoin);
}
if (RxDictionary.ContainsKey(ioSlot))
{
LinkRxToApi(trilist, ioSlot, joinMap, ioSlotJoin);
}
LinkHdmiInputToApi(trilist, ioSlot, joinMap, ioSlotJoin);
LinkStreamInputToApi(trilist, ioSlot, joinMap, ioSlotJoin);
}
if (RxDictionary.ContainsKey(ioSlot))
{
LinkRxToApi(trilist, ioSlot, joinMap, ioSlotJoin);
}
else
LinkStreamOutputToApi(trilist, ioSlot, joinMap, ioSlotJoin);
}
}
@@ -1233,6 +1382,86 @@ namespace PepperDash.Essentials.DM
{
trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = 1;
}
}
private void LinkStreamInputToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin)
{
var inputPort = InputPorts[string.Format("inputCard{0}--streamIn", ioSlot)];
if (inputPort == null)
{
return;
}
var streamCard = Chassis.Inputs[ioSlot].Card as DmcStr;
var join = joinMap.InputStreamCardState.JoinNumber + ioSlotJoin;
Debug.Console(1, "Port value for input card {0} is set as a stream card", ioSlot);
trilist.SetUShortSigAction(join, s =>
{
if (s == 1)
{
Debug.Console(2, this, "Join {0} value {1}: Setting stream state to start", join, s);
streamCard.Control.Start();
}
else if (s == 2)
{
Debug.Console(2, this, "Join {0} value {1}: Setting stream state to stop", join, s);
streamCard.Control.Stop();
}
else if (s == 3)
{
Debug.Console(2, this, "Join {0} value {1}: Setting stream state to pause", join, s);
streamCard.Control.Pause();
}
else
{
Debug.Console(2, this, "Join {0} value {1}: Ignore stream state", join, s);
}
});
InputStreamCardStateFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[join]);
trilist.UShortInput[join].UShortValue = InputStreamCardStateFeedbacks[ioSlot].UShortValue;
}
private void LinkStreamOutputToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin)
{
var outputPort = OutputPorts[string.Format("outputCard{0}--streamOut", ioSlot)];
if (outputPort == null)
{
return;
}
var streamCard = Chassis.Outputs[ioSlot].Card as DmcStroAV;
var join = joinMap.OutputStreamCardState.JoinNumber + ioSlotJoin;
Debug.Console(1, "Port value for output card {0} is set as a stream card", ioSlot);
trilist.SetUShortSigAction(join, s =>
{
if (s == 1)
{
Debug.Console(2, this, "Join {0} value {1}: Setting stream state to start", join, s);
streamCard.Control.Start();
}
else if (s == 2)
{
Debug.Console(2, this, "Join {0} value {1}: Setting stream state to stop", join, s);
streamCard.Control.Stop();
}
else if (s == 3)
{
Debug.Console(2, this, "Join {0} value {1}: Setting stream state to pause", join, s);
streamCard.Control.Pause();
}
else
{
Debug.Console(2, this, "Join {0} value {1}: Ignore stream state", join, s);
}
});
OutputStreamCardStateFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[join]);
trilist.UShortInput[join].UShortValue = OutputStreamCardStateFeedbacks[ioSlot].UShortValue;
}
private void LinkRxToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin)

View File

@@ -18,12 +18,15 @@ using PepperDash.Essentials.DM.Config;
using Feedback = PepperDash.Essentials.Core.Feedback;
namespace PepperDash.Essentials.DM
{
public class DmpsRoutingController : EssentialsBridgeableDevice, IRoutingNumeric, IHasFeedback
{
public class DmpsRoutingController : EssentialsBridgeableDevice, IRoutingNumericWithFeedback, IHasFeedback
{
public CrestronControlSystem Dmps { get; set; }
public ISystemControl SystemControl { get; private set; }
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
// Feedbacks for EssentialDM
public Dictionary<uint, IntFeedback> VideoOutputFeedbacks { get; private set; }
public Dictionary<uint, IntFeedback> AudioOutputFeedbacks { get; private set; }
@@ -56,11 +59,23 @@ namespace PepperDash.Essentials.DM
/// </summary>
public string NoRouteText = "";
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
public static DmpsRoutingController GetDmpsRoutingController(string key, string name,
DmpsRoutingPropertiesConfig properties)
{
try
{
ISystemControl systemControl = null;
systemControl = Global.ControlSystem.SystemControl as ISystemControl;
@@ -120,6 +135,9 @@ namespace PepperDash.Essentials.DM
Debug.Console(1, this, "{0} Switcher Inputs Present.", Dmps.SwitcherInputs.Count);
Debug.Console(1, this, "{0} Switcher Outputs Present.", Dmps.SwitcherOutputs.Count);
Debug.Console(1, this, "{0} Inputs in ControlSystem", Dmps.NumberOfSwitcherInputs);
Debug.Console(1, this, "{0} Outputs in ControlSystem", Dmps.NumberOfSwitcherOutputs);
SetupOutputCards();
SetupInputCards();
@@ -128,148 +146,197 @@ namespace PepperDash.Essentials.DM
public override bool CustomActivate()
{
// Set input and output names from config
if (InputNames != null)
{
foreach (var kvp in InputNames)
{
var input = (Dmps.SwitcherInputs[kvp.Key] as DMInput);
if (input != null)
input.Name.StringValue = kvp.Value;
}
}
if (OutputNames != null)
{
foreach (var kvp in OutputNames)
{
var output = (Dmps.SwitcherOutputs[kvp.Key] as DMOutput);
if (output != null)
output.Name.StringValue = kvp.Value;
}
}
SetInputNames();
SetOutputNames();
// Subscribe to events
Dmps.DMInputChange += new DMInputEventHandler(Dmps_DMInputChange);
Dmps.DMOutputChange += new DMOutputEventHandler(Dmps_DMOutputChange);
Dmps.DMInputChange += Dmps_DMInputChange;
Dmps.DMOutputChange += Dmps_DMOutputChange;
return base.CustomActivate();
}
private void SetOutputNames()
{
if (OutputNames == null)
{
return;
}
foreach (var kvp in OutputNames)
{
var output = (Dmps.SwitcherOutputs[kvp.Key] as DMOutput);
if (output != null && output.Name.Type != eSigType.NA)
{
output.Name.StringValue = kvp.Value;
}
}
}
private void SetInputNames()
{
if (InputNames == null)
{
return;
}
foreach (var kvp in InputNames)
{
var input = (Dmps.SwitcherInputs[kvp.Key] as DMInput);
if (input != null && input.Name.Type != eSigType.NA)
{
input.Name.StringValue = kvp.Value;
}
}
}
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
{
var joinMap = new DmpsRoutingControllerJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<DmpsRoutingControllerJoinMap>(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.");
joinMap = JsonConvert.DeserializeObject<DmpsRoutingControllerJoinMap>(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.");
}
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
// Link up outputs
for (uint i = 1; i <= Dmps.NumberOfSwitcherInputs; i++)
{
Debug.Console(2, this, "Linking Input Card {0}", i);
LinkInputsToApi(trilist, joinMap);
var ioSlot = i;
var ioSlotJoin = ioSlot - 1;
LinkOutputsToApi(trilist, joinMap);
}
//if (TxDictionary.ContainsKey(ioSlot))
//{
// Debug.Console(2, "Creating Tx Feedbacks {0}", ioSlot);
// var TxKey = TxDictionary[ioSlot];
// var TxDevice = DeviceManager.GetDeviceForKey(TxKey) as DmTxControllerBase;
// //TxDevice.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.InputEndpointOnline + ioSlot]);
// // TxDevice.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputEndpointOnline + ioSlot]);
// // trilist.SetUShortSigAction((ApiMap.HdcpSupport[ioSlot]), u => TxDevice.SetHdcpSupportAll((ePdtHdcpSupport)(u)));
// // TxDevice.HdcpSupportAllFeedback.LinkInputSig(trilist.UShortInput[joinMap. + ioSlot]);
// // trilist.UShortInput[ApiMap.HdcpSupportCapability[ioSlot]].UShortValue = TxDevice.HdcpSupportCapability;
//}
//else
//{
// // dmChassis.VideoInputSyncFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[ApiMap.TxVideoSyncStatus[ioSlot]]);
//}
if (VideoInputSyncFeedbacks[ioSlot] != null)
VideoInputSyncFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]);
if (InputNameFeedbacks[ioSlot] != null)
InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]);
trilist.SetStringSigAction(joinMap.InputNames.JoinNumber + ioSlotJoin, new Action<string>(s =>
{
var inputCard = Dmps.SwitcherInputs[ioSlot] as DMInput;
if (inputCard != null)
{
if (inputCard.NameFeedback != null && !string.IsNullOrEmpty(inputCard.NameFeedback.StringValue) && inputCard.NameFeedback.StringValue != s)
if (inputCard.Name != null)
inputCard.Name.StringValue = s;
}
}));
if (InputEndpointOnlineFeedbacks[ioSlot] != null)
InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]);
}
for (uint i = 1; i <= Dmps.NumberOfSwitcherOutputs; i++)
private void LinkOutputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap)
{
for (uint i = 1; i <= Dmps.SwitcherOutputs.Count; i++)
{
Debug.Console(2, this, "Linking Output Card {0}", i);
var ioSlot = i;
var ioSlot = i;
var ioSlotJoin = ioSlot - 1;
// Control
trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin, o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Video));
trilist.SetUShortSigAction(joinMap.OutputAudio.JoinNumber + ioSlotJoin, o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Audio));
// Control
trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin,
o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Video));
trilist.SetUShortSigAction(joinMap.OutputAudio.JoinNumber + ioSlotJoin,
o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Audio));
trilist.SetStringSigAction(joinMap.OutputNames.JoinNumber + ioSlotJoin, s =>
{
var outputCard = Dmps.SwitcherOutputs[ioSlot] as DMOutput;
//Debug.Console(2, dmpsRouter, "Output Name String Sig Action for Output Card {0}", ioSlot);
if (outputCard != null)
if (outputCard == null)
{
//Debug.Console(2, dmpsRouter, "Card Type: {0}", outputCard.CardInputOutputType);
return;
}
//Debug.Console(2, dmpsRouter, "Card Type: {0}", outputCard.CardInputOutputType);
if (!(outputCard is Card.Dmps3CodecOutput) && outputCard.NameFeedback != null)
{
if (!string.IsNullOrEmpty(outputCard.NameFeedback.StringValue))
{
//Debug.Console(2, dmpsRouter, "NameFeedabck: {0}", outputCard.NameFeedback.StringValue);
if (outputCard is Card.Dmps3CodecOutput || outputCard.NameFeedback == null)
{
return;
}
if (string.IsNullOrEmpty(outputCard.NameFeedback.StringValue))
{
return;
}
//Debug.Console(2, dmpsRouter, "NameFeedabck: {0}", outputCard.NameFeedback.StringValue);
if (outputCard.NameFeedback.StringValue != s && outputCard.Name != null)
{
outputCard.Name.StringValue = s;
}
}
}
if (outputCard.NameFeedback.StringValue != s && outputCard.Name != null)
{
outputCard.Name.StringValue = s;
}
});
// Feedback
if (VideoOutputFeedbacks[ioSlot] != null)
if (VideoOutputFeedbacks[ioSlot] != null)
{
VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo.JoinNumber + ioSlotJoin]);
if (AudioOutputFeedbacks[ioSlot] != null)
}
if (AudioOutputFeedbacks[ioSlot] != null)
{
AudioOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio.JoinNumber + ioSlotJoin]);
if (OutputNameFeedbacks[ioSlot] != null)
}
if (OutputNameFeedbacks[ioSlot] != null)
{
OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]);
if (OutputVideoRouteNameFeedbacks[ioSlot] != null)
OutputVideoRouteNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputCurrentVideoInputNames.JoinNumber + ioSlotJoin]);
if (OutputAudioRouteNameFeedbacks[ioSlot] != null)
OutputAudioRouteNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputCurrentAudioInputNames.JoinNumber + ioSlotJoin]);
if (OutputEndpointOnlineFeedbacks[ioSlot] != null)
OutputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.OutputEndpointOnline.JoinNumber + ioSlotJoin]);
}
if (OutputVideoRouteNameFeedbacks[ioSlot] != null)
{
OutputVideoRouteNameFeedbacks[ioSlot].LinkInputSig(
trilist.StringInput[joinMap.OutputCurrentVideoInputNames.JoinNumber + ioSlotJoin]);
}
if (OutputAudioRouteNameFeedbacks[ioSlot] != null)
{
OutputAudioRouteNameFeedbacks[ioSlot].LinkInputSig(
trilist.StringInput[joinMap.OutputCurrentAudioInputNames.JoinNumber + ioSlotJoin]);
}
if (OutputEndpointOnlineFeedbacks[ioSlot] != null)
{
OutputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(
trilist.BooleanInput[joinMap.OutputEndpointOnline.JoinNumber + ioSlotJoin]);
}
}
}
private void LinkInputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap)
{
for (uint i = 1; i <= Dmps.SwitcherInputs.Count; i++)
{
Debug.Console(2, this, "Linking Input Card {0}", i);
var ioSlot = i;
var ioSlotJoin = ioSlot - 1;
if (VideoInputSyncFeedbacks[ioSlot] != null)
{
VideoInputSyncFeedbacks[ioSlot].LinkInputSig(
trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]);
}
if (InputNameFeedbacks[ioSlot] != null)
{
InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]);
}
trilist.SetStringSigAction(joinMap.InputNames.JoinNumber + ioSlotJoin, s =>
{
var inputCard = Dmps.SwitcherInputs[ioSlot] as DMInput;
if (inputCard == null)
{
return;
}
if (inputCard.NameFeedback == null || string.IsNullOrEmpty(inputCard.NameFeedback.StringValue) ||
inputCard.NameFeedback.StringValue == s)
{
return;
}
if (inputCard.Name != null)
{
inputCard.Name.StringValue = s;
}
});
if (InputEndpointOnlineFeedbacks[ioSlot] != null)
{
InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(
trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]);
}
}
}
@@ -281,65 +348,69 @@ namespace PepperDash.Essentials.DM
{
foreach (var card in Dmps.SwitcherOutputs)
{
Debug.Console(1, this, "Output Card Type: {0}", card.CardInputOutputType);
var outputCard = card as DMOutput;
Debug.Console(1, this, "Adding Output Card Number {0} Type: {1}", outputCard.Number, outputCard.CardInputOutputType.ToString());
if (outputCard != null)
if (outputCard == null)
{
VideoOutputFeedbacks[outputCard.Number] = new IntFeedback(() =>
{
if (outputCard.VideoOutFeedback != null) { return (ushort)outputCard.VideoOutFeedback.Number; }
else { return 0; };
});
AudioOutputFeedbacks[outputCard.Number] = new IntFeedback(() =>
{
if (outputCard.AudioOutFeedback != null) { return (ushort)outputCard.AudioOutFeedback.Number; }
else { return 0; };
});
OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
{
if (outputCard.NameFeedback != null && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue))
{
Debug.Console(2, this, "Output Card {0} Name: {1}", outputCard.Number, outputCard.NameFeedback.StringValue);
return outputCard.NameFeedback.StringValue;
}
else
{
return "";
}
});
OutputVideoRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
{
if (outputCard.VideoOutFeedback != null && outputCard.VideoOutFeedback.NameFeedback != null)
{
return outputCard.VideoOutFeedback.NameFeedback.StringValue;
}
else
{
return NoRouteText;
}
});
OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
{
if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null)
{
return outputCard.AudioOutFeedback.NameFeedback.StringValue;
}
else
{
return NoRouteText;
}
});
OutputEndpointOnlineFeedbacks[outputCard.Number] = new BoolFeedback(() => { return outputCard.EndpointOnlineFeedback; });
AddOutputCard(outputCard.Number, outputCard);
Debug.Console(1, this, "Output card {0} is not a DMOutput", card.CardInputOutputType);
continue;
}
Debug.Console(1, this, "Adding Output Card Number {0} Type: {1}", outputCard.Number, outputCard.CardInputOutputType.ToString());
VideoOutputFeedbacks[outputCard.Number] = new IntFeedback(() =>
{
if (outputCard.VideoOutFeedback != null) { return (ushort)outputCard.VideoOutFeedback.Number; }
return 0;
;
});
AudioOutputFeedbacks[outputCard.Number] = new IntFeedback(() =>
{
try
{
if (outputCard.AudioOutFeedback != null)
{
return (ushort) outputCard.AudioOutFeedback.Number;
}
return 0;
}
catch (NotSupportedException)
{
return (ushort) outputCard.AudioOutSourceFeedback;
}
});
OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
{
if (outputCard.NameFeedback != null && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue))
{
Debug.Console(2, this, "Output Card {0} Name: {1}", outputCard.Number, outputCard.NameFeedback.StringValue);
return outputCard.NameFeedback.StringValue;
}
return "";
});
OutputVideoRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
{
if (outputCard.VideoOutFeedback != null && outputCard.VideoOutFeedback.NameFeedback != null)
{
return outputCard.VideoOutFeedback.NameFeedback.StringValue;
}
return NoRouteText;
});
OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
{
if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null)
{
return outputCard.AudioOutFeedback.NameFeedback.StringValue;
}
return NoRouteText;
});
OutputEndpointOnlineFeedbacks[outputCard.Number] = new BoolFeedback(() => outputCard.EndpointOnlineFeedback);
AddOutputCard(outputCard.Number, outputCard);
}
}
@@ -457,11 +528,16 @@ namespace PepperDash.Essentials.DM
/// <summary>
/// Adds InputPort
/// </summary>
void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType)
private void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType,
eRoutingPortConnectionType portType)
{
var portKey = string.Format("inputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding input port '{0}'", portKey);
var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this);
var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this)
{
FeedbackMatchObject = Dmps.SwitcherInputs[cardNum]
};
;
InputPorts.Add(inputPort);
}
@@ -473,7 +549,11 @@ namespace PepperDash.Essentials.DM
{
var portKey = string.Format("inputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding input port '{0}'", portKey);
var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this);
var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this)
{
FeedbackMatchObject = Dmps.SwitcherInputs[cardNum]
};
;
if (cecPort != null)
inputPort.Port = cecPort;
@@ -481,6 +561,7 @@ namespace PepperDash.Essentials.DM
InputPorts.Add(inputPort);
}
/// <summary>
/// Builds the appropriate ports and calls the appropriate add port method
/// </summary>
@@ -495,17 +576,22 @@ namespace PepperDash.Essentials.DM
var cecPort = hdmiOutputCard.HdmiOutputPort;
AddHdmiOutputPort(number, cecPort);
}
else if (outputCard is Card.Dmps3HdmiOutputBackend)
{
var hdmiOutputCard = outputCard as Card.Dmps3HdmiOutputBackend;
return;
var cecPort = hdmiOutputCard.HdmiOutputPort;
AddHdmiOutputPort(number, cecPort);
}
else if (outputCard is Card.Dmps3DmOutput)
{
var dmOutputCard = outputCard as Card.Dmps3DmOutput;
var cecPort = dmOutputCard.DmOutputPort;
AddDmOutputPort(number);
return;
}
else if (outputCard is Card.Dmps3DmOutputBackend)
{
AddDmOutputPort(number);
}
else if (outputCard is Card.Dmps3ProgramOutput)
{
@@ -514,49 +600,50 @@ namespace PepperDash.Essentials.DM
var programOutput = new DmpsAudioOutputController(string.Format("processor-programAudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase);
DeviceManager.AddDevice(programOutput);
return;
}
else if (outputCard is Card.Dmps3AuxOutput)
{
if (outputCard.CardInputOutputType == eCardInputOutputType.Dmps3Aux1Output)
switch (outputCard.CardInputOutputType)
{
AddAudioOnlyOutputPort(number, "Aux1");
case eCardInputOutputType.Dmps3Aux1Output:
{
AddAudioOnlyOutputPort(number, "Aux1");
var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase);
var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase);
DeviceManager.AddDevice(aux1Output);
DeviceManager.AddDevice(aux1Output);
}
break;
case eCardInputOutputType.Dmps3Aux2Output:
{
AddAudioOnlyOutputPort(number, "Aux2");
var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase);
DeviceManager.AddDevice(aux2Output);
}
break;
}
else if (outputCard.CardInputOutputType == eCardInputOutputType.Dmps3Aux2Output)
{
AddAudioOnlyOutputPort(number, "Aux2");
var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase);
DeviceManager.AddDevice(aux2Output);
}
return;
}
else if (outputCard is Card.Dmps3CodecOutput)
{
if (number == (uint)CrestronControlSystem.eDmps300cOutputs.Codec1
|| number == (uint)CrestronControlSystem.eDmps3200cOutputs.Codec1
|| number == (uint)CrestronControlSystem.eDmps3300cAecOutputs.Codec1
|| number == (uint)CrestronControlSystem.eDmps34K250COutputs.Codec1
|| number == (uint)CrestronControlSystem.eDmps34K350COutputs.Codec1)
AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps300cOutputs.Codec1.ToString());
else if (number == (uint)CrestronControlSystem.eDmps300cOutputs.Codec2
|| number == (uint)CrestronControlSystem.eDmps3200cOutputs.Codec2
|| number == (uint)CrestronControlSystem.eDmps3300cAecOutputs.Codec2
|| number == (uint)CrestronControlSystem.eDmps34K250COutputs.Codec2
|| number == (uint)CrestronControlSystem.eDmps34K350COutputs.Codec2)
AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps300cOutputs.Codec2.ToString());
return;
switch (number)
{
case (uint)CrestronControlSystem.eDmps34K350COutputs.Codec1:
case (uint)CrestronControlSystem.eDmps34K250COutputs.Codec1:
case (uint)CrestronControlSystem.eDmps3300cAecOutputs.Codec1:
AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps300cOutputs.Codec1.ToString());
break;
case (uint)CrestronControlSystem.eDmps34K350COutputs.Codec2:
case (uint)CrestronControlSystem.eDmps34K250COutputs.Codec2:
case (uint)CrestronControlSystem.eDmps3300cAecOutputs.Codec2:
AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps300cOutputs.Codec2.ToString());
break;
}
}
else if (outputCard is Card.Dmps3DialerOutput)
{
AddAudioOnlyOutputPort(number, "Dialer");
return;
}
else if (outputCard is Card.Dmps3DigitalMixOutput)
{
@@ -568,12 +655,10 @@ namespace PepperDash.Essentials.DM
|| number == (uint)CrestronControlSystem.eDmps34K300COutputs.Mix2
|| number == (uint)CrestronControlSystem.eDmps34K350COutputs.Mix2)
AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps34K250COutputs.Mix2.ToString());
return;
}
else if (outputCard is Card.Dmps3AecOutput)
{
AddAudioOnlyOutputPort(number, "Aec");
return;
}
else
{
@@ -616,7 +701,10 @@ namespace PepperDash.Essentials.DM
{
var portKey = string.Format("outputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding output port '{0}'", portKey);
OutputPorts.Add(new RoutingOutputPort(portKey, sigType, portType, selector, this));
OutputPorts.Add(new RoutingOutputPort(portKey, sigType, portType, selector, this)
{
FeedbackMatchObject = Dmps.SwitcherOutputs[cardNum]
});
}
/// <summary>
@@ -626,7 +714,10 @@ namespace PepperDash.Essentials.DM
{
var portKey = string.Format("outputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding output port '{0}'", portKey);
var outputPort = new RoutingOutputPort(portKey, sigType, portType, selector, this);
var outputPort = new RoutingOutputPort(portKey, sigType, portType, selector, this)
{
FeedbackMatchObject = Dmps.SwitcherOutputs[cardNum]
};
if (cecPort != null)
outputPort.Port = cecPort;
@@ -703,13 +794,29 @@ namespace PepperDash.Essentials.DM
}
else if (args.EventId == DMOutputEventIds.AudioOutEventId)
{
if (outputCard != null && outputCard.AudioOutFeedback != null)
try
{
Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name, outputCard.AudioOutFeedback.Number, output);
if (outputCard != null && outputCard.AudioOutFeedback != null)
{
Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name,
outputCard.AudioOutFeedback.Number, output);
}
if (AudioOutputFeedbacks.ContainsKey(output))
{
AudioOutputFeedbacks[output].FireUpdate();
}
}
if (AudioOutputFeedbacks.ContainsKey(output))
catch (NotSupportedException)
{
AudioOutputFeedbacks[output].FireUpdate();
if (outputCard != null)
{
Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", Name,
outputCard.AudioOutSourceFeedback, output);
}
if (AudioOutputFeedbacks.ContainsKey(output))
{
AudioOutputFeedbacks[output].FireUpdate();
}
}
}
else if (args.EventId == DMOutputEventIds.OutputNameEventId
@@ -744,7 +851,14 @@ namespace PepperDash.Essentials.DM
var input = Convert.ToUInt32(inputSelector); // Cast can sometimes fail
var output = Convert.ToUInt32(outputSelector);
if (input <= Dmps.NumberOfSwitcherInputs && output <= Dmps.NumberOfSwitcherOutputs)
var sigTypeIsUsbOrVideo = ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video) ||
((sigType & eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput) ||
((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput);
if ((input <= Dmps.NumberOfSwitcherInputs && output <= Dmps.NumberOfSwitcherOutputs &&
sigTypeIsUsbOrVideo) ||
(input <= Dmps.NumberOfSwitcherInputs + 5 && output <= Dmps.NumberOfSwitcherOutputs &&
(sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio))
{
// Check to see if there's an off timer waiting on this and if so, cancel
var key = new PortNumberType(output, sigType);
@@ -762,37 +876,55 @@ namespace PepperDash.Essentials.DM
}
}
DMInput inCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput;
DMOutput outCard = output == 0 ? null : Dmps.SwitcherOutputs[output] as DMOutput;
DMOutput dmOutputCard = output == 0 ? null : Dmps.SwitcherOutputs[output] as DMOutput;
//if (inCard != null)
//{
// NOTE THAT BITWISE COMPARISONS - TO CATCH ALL ROUTING TYPES
if ((sigType | eRoutingSignalType.Video) == eRoutingSignalType.Video)
{
// NOTE THAT BITWISE COMPARISONS - TO CATCH ALL ROUTING TYPES
if ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video)
{
DMInput dmInputCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput;
//SystemControl.VideoEnter.BoolValue = true;
if (dmOutputCard != null)
dmOutputCard.VideoOut = dmInputCard;
}
//SystemControl.VideoEnter.BoolValue = true;
if (outCard != null)
outCard.VideoOut = inCard;
if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio)
{
DMInput dmInputCard = null;
if (input <= Dmps.NumberOfSwitcherInputs)
{
dmInputCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput;
}
if ((sigType | eRoutingSignalType.Audio) == eRoutingSignalType.Audio)
{
if (outCard != null)
outCard.AudioOut = inCard;
}
if (dmOutputCard != null)
try
{
dmOutputCard.AudioOut = dmInputCard;
}
catch (NotSupportedException)
{
Debug.Console(1, this, "Routing input {0} audio to output {1}",
(eDmps34KAudioOutSource) input, (CrestronControlSystem.eDmps34K350COutputs) output);
if ((sigType | eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput)
{
if (outCard != null)
outCard.USBRoutedTo = inCard;
}
dmOutputCard.AudioOutSource = (eDmps34KAudioOutSource) input;
}
}
if ((sigType | eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput)
{
if (inCard != null)
inCard.USBRoutedTo = outCard;
}
if ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput)
{
DMInput dmInputCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput;
if (dmOutputCard != null)
dmOutputCard.USBRoutedTo = dmInputCard;
}
if ((sigType & eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput)
{
DMInput dmInputCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput;
if (dmInputCard != null)
dmInputCard.USBRoutedTo = dmOutputCard;
}
//}
//else
//{
@@ -802,7 +934,8 @@ namespace PepperDash.Essentials.DM
}
else
{
Debug.Console(1, this, "Unable to execute route from input {0} to output {1}", inputSelector, outputSelector);
Debug.Console(1, this, "Unable to execute route from input {0} to output {1}", inputSelector,
outputSelector);
}
}
catch (Exception e)
@@ -811,15 +944,15 @@ namespace PepperDash.Essentials.DM
}
}
#endregion
#region IRoutingNumeric Members
public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType sigType)
{
ExecuteSwitch(inputSelector, outputSelector, sigType);
}
#endregion
#endregion
#region IRoutingNumeric Members
public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType sigType)
{
ExecuteSwitch(inputSelector, outputSelector, sigType);
}
#endregion
}
}

View File

@@ -16,11 +16,14 @@ using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.DM.Chassis
{
[Description("Wrapper class for all HdMdNxM4E switchers")]
public class HdMdNxM4kEBridgeableController : CrestronGenericBridgeableBaseDevice, IRoutingInputsOutputs, IRoutingNumeric, IHasFeedback
public class HdMdNxM4kEBridgeableController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IHasFeedback
{
private HdMdNxM _Chassis;
private HdMd4x14kE _Chassis4x1;
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
public Dictionary<uint, string> InputNames { get; set; }
public Dictionary<uint, string> OutputNames { get; set; }
@@ -70,26 +73,34 @@ namespace PepperDash.Essentials.DM.Chassis
for (uint i = 1; i <= _Chassis.NumberOfInputs; i++)
{
var inputName = InputNames[i];
_Chassis.Inputs[i].Name.StringValue = inputName;
var index = i;
var inputName = InputNames[index];
_Chassis.Inputs[index].Name.StringValue = inputName;
InputPorts.Add(new RoutingInputPort(inputName, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, i, this));
VideoInputSyncFeedbacks.Add(new BoolFeedback(inputName, () => _Chassis.Inputs[i].VideoDetectedFeedback.BoolValue));
InputNameFeedbacks.Add(new StringFeedback(inputName, () => _Chassis.Inputs[i].Name.StringValue));
InputHdcpEnableFeedback.Add(new BoolFeedback(inputName, () => _Chassis.HdmiInputs[i].HdmiInputPort.HdcpSupportOnFeedback.BoolValue));
eRoutingPortConnectionType.Hdmi, index, this)
{
FeedbackMatchObject = _Chassis.HdmiInputs[index]
});
VideoInputSyncFeedbacks.Add(new BoolFeedback(inputName, () => _Chassis.Inputs[index].VideoDetectedFeedback.BoolValue));
InputNameFeedbacks.Add(new StringFeedback(inputName, () => _Chassis.Inputs[index].Name.StringValue));
InputHdcpEnableFeedback.Add(new BoolFeedback(inputName, () => _Chassis.HdmiInputs[index].HdmiInputPort.HdcpSupportOnFeedback.BoolValue));
}
for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
{
var outputName = OutputNames[i];
var index = i;
var outputName = OutputNames[index];
_Chassis.Outputs[i].Name.StringValue = outputName;
OutputPorts.Add(new RoutingOutputPort(outputName, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, i, this));
VideoOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => (int)_Chassis.Outputs[i].VideoOutFeedback.Number));
OutputNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[i].Name.StringValue));
OutputRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[i].VideoOutFeedback.NameFeedback.StringValue));
eRoutingPortConnectionType.Hdmi, index, this)
{
FeedbackMatchObject = _Chassis.HdmiOutputs[index]
});
VideoOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => (int)_Chassis.Outputs[index].VideoOutFeedback.Number));
OutputNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].Name.StringValue));
OutputRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback.NameFeedback.StringValue));
}
_Chassis.DMInputChange += new DMInputEventHandler(Chassis_DMInputChange);
@@ -102,6 +113,16 @@ namespace PepperDash.Essentials.DM.Chassis
#region Methods
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
public void EnableHdcp(uint port)
{
if (port > _Chassis.NumberOfInputs) return;
@@ -328,44 +349,45 @@ namespace PepperDash.Essentials.DM.Chassis
void Chassis_OnlineStatusChange(Crestron.SimplSharpPro.GenericBase currentDevice, Crestron.SimplSharpPro.OnlineOfflineEventArgs args)
{
if (args.DeviceOnLine)
if (!args.DeviceOnLine) return;
for (uint i = 1; i <= _Chassis.NumberOfInputs; i++)
{
for (uint i = 1; i <= _Chassis.NumberOfInputs; i++)
{
_Chassis.Inputs[i].Name.StringValue = InputNames[i];
}
for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
{
_Chassis.Outputs[i].Name.StringValue = OutputNames[i];
}
foreach (var feedback in Feedbacks)
{
feedback.FireUpdate();
}
_Chassis.Inputs[i].Name.StringValue = InputNames[i];
}
for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
{
_Chassis.Outputs[i].Name.StringValue = OutputNames[i];
}
foreach (var feedback in Feedbacks)
{
feedback.FireUpdate();
}
}
void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args)
{
if (args.EventId == DMOutputEventIds.VideoOutEventId)
if (args.EventId != DMOutputEventIds.VideoOutEventId) return;
for (var i = 0; i < VideoOutputRouteFeedbacks.Count; i++)
{
foreach (var item in VideoOutputRouteFeedbacks)
{
item.FireUpdate();
}
var index = i;
var localInputPort = InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == _Chassis.HdmiOutputs[(uint)index + 1].VideoOutFeedback);
var localOutputPort =
OutputPorts.FirstOrDefault(p => (DMOutput)p.FeedbackMatchObject == _Chassis.HdmiOutputs[(uint)index + 1]);
VideoOutputRouteFeedbacks[i].FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs((ushort)i, VideoOutputRouteFeedbacks[i].UShortValue, localOutputPort, localInputPort, eRoutingSignalType.AudioVideo));
}
}
void Chassis_DMInputChange(Switch device, DMInputEventArgs args)
{
if (args.EventId == DMInputEventIds.VideoDetectedEventId)
if (args.EventId != DMInputEventIds.VideoDetectedEventId) return;
foreach (var item in VideoInputSyncFeedbacks)
{
foreach (var item in VideoInputSyncFeedbacks)
{
item.FireUpdate();
}
item.FireUpdate();
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
@@ -14,15 +15,19 @@ using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Essentials.Core.DeviceInfo;
namespace PepperDash.Essentials.DM.Endpoints.DGEs
{
[Description("Wrapper class for DGE-100")]
public class Dge100Controller : CrestronGenericBaseDevice, IComPorts, IIROutputPorts, IHasBasicTriListWithSmartObject, ICec
public class Dge100Controller : CrestronGenericBaseDevice, IComPorts, IIROutputPorts, IHasBasicTriListWithSmartObject, ICec, IDeviceInfoProvider
{
private const int CtpPort = 41795;
private readonly Dge100 _dge;
private readonly TsxCcsUcCodec100EthernetReservedSigs _dgeEthernetInfo;
public BasicTriListWithSmartObject Panel { get { return _dge; } }
private DeviceConfig _dc;
@@ -32,7 +37,14 @@ namespace PepperDash.Essentials.DM.Endpoints.DGEs
public Dge100Controller(string key, string name, Dge100 device, DeviceConfig dc, CrestronTouchpanelPropertiesConfig props)
:base(key, name, device)
{
_dge = device;
_dge = device;
_dgeEthernetInfo = _dge.ExtenderEthernetReservedSigs;
//_dgeEthernetInfo.DeviceExtenderSigChange += (extender, args) => UpdateDeviceInfo();
_dgeEthernetInfo.Use();
DeviceInfo = new DeviceInfo();
//_dge.OnlineStatusChange += (currentDevice, args) => { if (args.DeviceOnLine) UpdateDeviceInfo(); };
_dc = dc;
@@ -69,8 +81,86 @@ namespace PepperDash.Essentials.DM.Endpoints.DGEs
#region ICec Members
public Cec StreamCec { get { return _dge.HdmiOut.StreamCec; } }
#endregion
#endregion
#region Implementation of IDeviceInfoProvider
public DeviceInfo DeviceInfo { get; private set; }
public event DeviceInfoChangeHandler DeviceInfoChanged;
public void UpdateDeviceInfo()
{
DeviceInfo.IpAddress = _dgeEthernetInfo.IpAddressFeedback.StringValue;
DeviceInfo.MacAddress = _dgeEthernetInfo.MacAddressFeedback.StringValue;
GetFirmwareAndSerialInfo();
OnDeviceInfoChange();
}
private void GetFirmwareAndSerialInfo()
{
if (String.IsNullOrEmpty(_dgeEthernetInfo.IpAddressFeedback.StringValue))
{
Debug.Console(1, this, "IP Address information not yet received. No device is online");
return;
}
var tcpClient = new GenericTcpIpClient("", _dgeEthernetInfo.IpAddressFeedback.StringValue, CtpPort, 1024){AutoReconnect = false};
var gather = new CommunicationGather(tcpClient, "\r\n\r\n");
tcpClient.ConnectionChange += (sender, args) =>
{
if (!args.Client.IsConnected)
{
return;
}
args.Client.SendText("ver\r\n");
};
gather.LineReceived += (sender, args) =>
{
if (args.Text.ToLower().Contains("host"))
{
DeviceInfo.HostName = args.Text.Split(';')[1].Trim();
tcpClient.Disconnect();
return;
}
//ignore console prompt
if (args.Text.ToLower().Contains(">"))
{
return;
}
if (!args.Text.ToLower().Contains("dge"))
{
return;
}
DeviceInfo.SerialNumber = args.Text.Split('[')[1].Split(' ')[4].Replace("#", "");
DeviceInfo.FirmwareVersion = args.Text.Split('[')[1].Split(' ')[1];
tcpClient.SendText("host\r\n");
};
tcpClient.Connect();
}
private void OnDeviceInfoChange()
{
var handler = DeviceInfoChanged;
if (handler == null) return;
handler(this, new DeviceInfoEventArgs(DeviceInfo));
}
#endregion
}
public class Dge100ControllerFactory : EssentialsDeviceFactory<Dge100Controller>

View File

@@ -13,7 +13,7 @@ using PepperDash.Core;
namespace PepperDash.Essentials.DM
{
[Description("Wrapper Class for DM-RMC-4K-Z-SCALER-C")]
public class DmRmc4kZScalerCController : DmRmcControllerBase, IRmcRouting,
public class DmRmc4kZScalerCController : DmRmcControllerBase, IRmcRoutingWithFeedback,
IIROutputPorts, IComPorts, ICec
{
private readonly DmRmc4kzScalerC _rmc;
@@ -31,14 +31,34 @@ namespace PepperDash.Essentials.DM
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
public DmRmc4kZScalerCController(string key, string name, DmRmc4kzScalerC rmc)
: base(key, name, rmc)
{
_rmc = rmc;
DmIn = new RoutingInputPort(DmPortName.DmIn, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.DmCat, 0, this);
eRoutingPortConnectionType.DmCat, 0, this)
{
FeedbackMatchObject = 1
};
HdmiIn = new RoutingInputPort(DmPortName.HdmiIn, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, 0, this);
eRoutingPortConnectionType.Hdmi, 0, this)
{
FeedbackMatchObject = 2
};
HdmiOut = new RoutingOutputPort(DmPortName.HdmiOut, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, null, this);
@@ -55,12 +75,20 @@ namespace PepperDash.Essentials.DM
_rmc.HdmiOutput.OutputStreamChange += HdmiOutput_OutputStreamChange;
_rmc.HdmiOutput.ConnectedDevice.DeviceInformationChange += ConnectedDevice_DeviceInformationChange;
_rmc.OnlineStatusChange += _rmc_OnlineStatusChange;
// Set Ports for CEC
HdmiOut.Port = _rmc.HdmiOutput;
AudioVideoSourceNumericFeedback = new IntFeedback(() => (ushort)(_rmc.SelectedSourceFeedback));
}
private void _rmc_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
{
AudioVideoSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, AudioVideoSourceNumericFeedback.UShortValue, eRoutingSignalType.AudioVideo));
}
void HdmiOutput_OutputStreamChange(EndpointOutputStream outputStream, EndpointOutputStreamEventArgs args)
{
if (args.EventId == EndpointOutputStreamEventIds.HorizontalResolutionFeedbackEventId || args.EventId == EndpointOutputStreamEventIds.VerticalResolutionFeedbackEventId ||
@@ -71,7 +99,12 @@ namespace PepperDash.Essentials.DM
if (args.EventId == EndpointOutputStreamEventIds.SelectedSourceFeedbackEventId)
{
var localInputPort =
InputPorts.FirstOrDefault(p => (int)p.FeedbackMatchObject == AudioVideoSourceNumericFeedback.UShortValue);
AudioVideoSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, AudioVideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputPort, eRoutingSignalType.AudioVideo));
}
}

View File

@@ -2,19 +2,22 @@
using System.Collections.Generic;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Cards;
using Crestron.SimplSharpPro.DM.Endpoints.Receivers;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.DeviceInfo;
using PepperDash.Essentials.DM.Config;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.DM
{
[Description("Wrapper class for all DM-RMC variants")]
public abstract class DmRmcControllerBase : CrestronGenericBridgeableBaseDevice
public abstract class DmRmcControllerBase : CrestronGenericBridgeableBaseDevice, IDeviceInfoProvider
{
private const int CtpPort = 41795;
private readonly EndpointReceiverBase _rmc; //kept here just in case. Only property or method on this class that's not device-specific is the DMOutput that it's attached to.
public StringFeedback VideoOutputResolutionFeedback { get; protected set; }
@@ -31,6 +34,10 @@ namespace PepperDash.Essentials.DM
PreventRegistration = _rmc.DMOutput != null;
AddToFeedbackList(VideoOutputResolutionFeedback, EdidManufacturerFeedback, EdidSerialNumberFeedback, EdidNameFeedback, EdidPreferredTimingFeedback);
DeviceInfo = new DeviceInfo();
_rmc.OnlineStatusChange += (currentDevice, args) => { if (args.DeviceOnLine) UpdateDeviceInfo(); };
}
protected void LinkDmRmcToApi(DmRmcControllerBase rmc, BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
@@ -78,7 +85,106 @@ namespace PepperDash.Essentials.DM
trilist.SetUShortSigAction(joinMap.AudioVideoSource.JoinNumber, a => routing.ExecuteNumericSwitch(a, 1, eRoutingSignalType.AudioVideo));
}
}
#region Implementation of IDeviceInfoProvider
public DeviceInfo DeviceInfo { get; private set; }
public event DeviceInfoChangeHandler DeviceInfoChanged;
public void UpdateDeviceInfo()
{
Debug.Console(1, this, "Updating Device Info");
if (_rmc.ConnectedIpList.Count == 0)
{
Debug.Console(1, this, "IP Address information not yet received. No device is online");
return;
}
DeviceInfo.IpAddress = _rmc.ConnectedIpList[0].DeviceIpAddress;
foreach (var ip in _rmc.ConnectedIpList)
{
Debug.Console(0, this, "Connected IP Address: {0}", ip.DeviceIpAddress);
}
GetFirmwareAndSerialInfo();
OnDeviceInfoChange();
}
private void GetFirmwareAndSerialInfo()
{
var tcpClient = new GenericTcpIpClient(String.Format("{0}-devInfoSocket", Key), _rmc.ConnectedIpList[0].DeviceIpAddress, CtpPort, 1024)
{
AutoReconnect = false,
};
var gather = new CommunicationGather(tcpClient, "\r\n\r\n");
tcpClient.ConnectionChange += (sender, args) =>
{
if (!args.Client.IsConnected)
{
OnDeviceInfoChange();
return;
}
args.Client.SendText("ver\r\n");
};
gather.LineReceived += (sender, args) =>
{
//ignore console prompt
if (args.Text.ToLower().Contains(">"))
{
return;
}
if (args.Text.ToLower().Contains("host"))
{
DeviceInfo.HostName = args.Text.Split(':')[1].Trim();
tcpClient.SendText("maca\r\n");
return;
}
if (args.Text.ToLower().Contains("mac"))
{
DeviceInfo.MacAddress = args.Text.Split(':')[1].Trim().Replace(" ", ":");
tcpClient.Disconnect();
return;
}
if (!args.Text.ToLower().Contains("rmc"))
{
return;
}
DeviceInfo.SerialNumber = args.Text.Split('[')[1].Split(' ')[4].Replace("#", "");
DeviceInfo.FirmwareVersion = args.Text.Split('[')[1].Split(' ')[1];
tcpClient.SendText("host\r\n");
};
tcpClient.Connect();
}
private void OnDeviceInfoChange()
{
var handler = DeviceInfoChanged;
if (handler == null) return;
handler(this, new DeviceInfoEventArgs(DeviceInfo));
}
#endregion
}
public abstract class DmHdBaseTControllerBase : CrestronGenericBaseDevice
{
@@ -221,6 +327,10 @@ namespace PepperDash.Essentials.DM
DmRmcPropertiesConfig props, string pKey, uint ipid)
{
var parentDev = DeviceManager.GetDeviceForKey(pKey);
if (parentDev is DmpsRoutingController)
{
return GetDmRmcControllerForDmps(key, name, typeName, parentDev as DmpsRoutingController, props.ParentOutputNumber);
}
if (!(parentDev is IDmSwitch))
{
Debug.Console(0, "Cannot create DM device '{0}'. '{1}' is not a DM Chassis.",
@@ -285,6 +395,28 @@ namespace PepperDash.Essentials.DM
return null;
}
private static CrestronGenericBaseDevice GetDmRmcControllerForDmps(string key, string name, string typeName,
DmpsRoutingController controller, uint num)
{
Func<string, string, DMOutput, CrestronGenericBaseDevice> dmpsHandler;
if (ChassisCpu3Dict.TryGetValue(typeName.ToLower(), out dmpsHandler))
{
var output = controller.Dmps.SwitcherOutputs[num] as DMOutput;
if (output != null)
{
return dmpsHandler(key, name, output);
}
Debug.Console(0, Debug.ErrorLogLevel.Error,
"Cannot attach DM-RMC of type '{0}' to output {1} on DMPS chassis. Output is not a DM Output.",
typeName, num);
return null;
}
Debug.Console(0, Debug.ErrorLogLevel.Error, "Cannot create DM-RMC of type '{0}' to output {1} on DMPS chassis", typeName, num);
return null;
}
private static CrestronGenericBaseDevice GetDmRmcControllerForProcessor(string key, string name, string typeName, uint ipid)
{
try
@@ -305,6 +437,8 @@ namespace PepperDash.Essentials.DM
return null;
}
}
}
public class DmRmcControllerFactory : EssentialsDeviceFactory<DmRmcControllerBase>

View File

@@ -1,4 +1,5 @@
using System;
using System;
using System.Linq;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
@@ -17,7 +18,7 @@ namespace PepperDash.Essentials.DM
/// Controller class for all DM-TX-201C/S/F transmitters
/// </summary>
[Description("Wrapper class for DM-TX-200-C")]
public class DmTx200Controller : DmTxControllerBase, ITxRouting, IHasFreeRun, IVgaBrightnessContrastControls
public class DmTx200Controller : DmTxControllerBase, ITxRoutingWithFeedback, IHasFreeRun, IVgaBrightnessContrastControls
{
public DmTx200C2G Tx { get; private set; }
@@ -35,7 +36,21 @@ namespace PepperDash.Essentials.DM
public BoolFeedback FreeRunEnabledFeedback { get; protected set; }
public IntFeedback VgaBrightnessFeedback { get; protected set; }
public IntFeedback VgaContrastFeedback { get; protected set; }
public IntFeedback VgaContrastFeedback { get; protected set; }
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
/// <summary>
/// Helps get the "real" inputs, including when in Auto
@@ -85,14 +100,22 @@ namespace PepperDash.Essentials.DM
public DmTx200Controller(string key, string name, DmTx200C2G tx)
: base(key, name, tx)
{
Tx = tx;
HdmiInput = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, DmTx200Base.eSourceSelection.Digital, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInput));
VgaInput = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn,
eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, DmTx200Base.eSourceSelection.Analog, this,
VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput));
Tx = tx;
HdmiInput = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi,
DmTx200Base.eSourceSelection.Digital, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInput))
{
FeedbackMatchObject = DmTx200Base.eSourceSelection.Digital
};
VgaInput = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn,
eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, DmTx200Base.eSourceSelection.Analog, this,
VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput))
{
FeedbackMatchObject = DmTx200Base.eSourceSelection.Analog
};
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
@@ -195,12 +218,19 @@ namespace PepperDash.Essentials.DM
}
}
void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
{
void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
{
var localVideoInputPort =
InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection) p.Selector == Tx.VideoSourceFeedback);
var localAudioInputPort =
InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection) p.Selector == Tx.AudioSourceFeedback);
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
AudioSourceNumericFeedback.FireUpdate();
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localAudioInputPort, eRoutingSignalType.Audio));
}
public override bool CustomActivate()
@@ -303,14 +333,18 @@ namespace PepperDash.Essentials.DM
switch (id)
{
case EndpointTransmitterBase.VideoSourceFeedbackEventId:
case EndpointTransmitterBase.VideoSourceFeedbackEventId:
var localVideoInputPort = InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.VideoSourceFeedback);
Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
VideoSourceNumericFeedback.FireUpdate();
ActiveVideoInputFeedback.FireUpdate();
ActiveVideoInputFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
var localInputAudioPort = InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.AudioSourceFeedback);
Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;
}
}

View File

@@ -4,6 +4,7 @@ using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Endpoints;
using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
using System.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
@@ -14,8 +15,8 @@ namespace PepperDash.Essentials.DM
/// <summary>
/// Controller class for all DM-TX-201C/S/F transmitters
/// </summary>
[Description("Wrapper class for DM-TX-201-C")]
public class DmTx201CController : DmTxControllerBase, ITxRouting, IHasFreeRun, IVgaBrightnessContrastControls
[Description("Wrapper class for DM-TX-201-C")]
public class DmTx201CController : DmTxControllerBase, ITxRoutingWithFeedback, IHasFreeRun, IVgaBrightnessContrastControls
{
public DmTx201C Tx { get; private set; }
@@ -34,7 +35,20 @@ namespace PepperDash.Essentials.DM
public BoolFeedback FreeRunEnabledFeedback { get; protected set; }
public IntFeedback VgaBrightnessFeedback { get; protected set; }
public IntFeedback VgaContrastFeedback { get; protected set; }
public IntFeedback VgaContrastFeedback { get; protected set; }
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
/// <summary>
/// Helps get the "real" inputs, including when in Auto
@@ -89,14 +103,22 @@ namespace PepperDash.Essentials.DM
public DmTx201CController(string key, string name, DmTx201C tx)
: base(key, name, tx)
{
Tx = tx;
HdmiInput = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, DmTx200Base.eSourceSelection.Digital, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInput));
VgaInput = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn,
eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, DmTx200Base.eSourceSelection.Analog, this,
VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput));
Tx = tx;
HdmiInput = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi,
DmTx200Base.eSourceSelection.Digital, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInput))
{
FeedbackMatchObject = DmTx200Base.eSourceSelection.Digital
};
VgaInput = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn,
eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, DmTx200Base.eSourceSelection.Analog, this,
VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput))
{
FeedbackMatchObject = DmTx200Base.eSourceSelection.Analog
};
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
@@ -190,16 +212,23 @@ namespace PepperDash.Essentials.DM
VgaContrastFeedback.FireUpdate();
break;
}
}
void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
{
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
AudioSourceNumericFeedback.FireUpdate();
}
void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
{
var localVideoInputPort =
InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.VideoSourceFeedback);
var localAudioInputPort =
InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.AudioSourceFeedback);
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localAudioInputPort, eRoutingSignalType.Audio));
}
private void VgaInputOnInputStreamChange(EndpointInputStream inputStream, EndpointInputStreamEventArgs args)
{
switch (args.EventId)
@@ -312,23 +341,26 @@ namespace PepperDash.Essentials.DM
}
void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
{
var id = args.EventId;
{
var id = args.EventId;
Debug.Console(2, this, "EventId {0}", args.EventId);
switch (id)
{
case EndpointTransmitterBase.VideoSourceFeedbackEventId:
var localVideoInputPort = InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.VideoSourceFeedback);
Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
ActiveVideoInputFeedback.FireUpdate();
ActiveVideoInputFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
Debug.Console(2, this, " Audio Source : {0}", Tx.AudioSourceFeedback);
var localInputAudioPort = InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.AudioSourceFeedback);
Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;
}
}
}
void InputStreamChangeEvent(EndpointInputStream inputStream, EndpointInputStreamEventArgs args)

View File

@@ -4,6 +4,7 @@ using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Endpoints;
using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
using System.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
@@ -15,7 +16,7 @@ namespace PepperDash.Essentials.DM
/// Controller class for all DM-TX-201S/F transmitters
/// </summary>
[Description("Wrapper class for DM-TX-201-S/F")]
public class DmTx201SController : DmTxControllerBase, ITxRouting, IHasFreeRun, IVgaBrightnessContrastControls
public class DmTx201SController : DmTxControllerBase, ITxRoutingWithFeedback, IHasFreeRun, IVgaBrightnessContrastControls
{
public DmTx201S Tx { get; private set; }
@@ -36,6 +37,21 @@ namespace PepperDash.Essentials.DM
public IntFeedback VgaBrightnessFeedback { get; protected set; }
public IntFeedback VgaContrastFeedback { get; protected set; }
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
/// <summary>
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
/// <summary>
/// Helps get the "real" inputs, including when in Auto
/// </summary>
@@ -92,11 +108,19 @@ namespace PepperDash.Essentials.DM
Tx = tx;
HdmiInput = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, DmTx200Base.eSourceSelection.Digital, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInput));
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi,
DmTx200Base.eSourceSelection.Digital, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInput))
{
FeedbackMatchObject = DmTx200Base.eSourceSelection.Digital
};
VgaInput = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn,
eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, DmTx200Base.eSourceSelection.Analog, this,
VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput));
VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput))
{
FeedbackMatchObject = DmTx200Base.eSourceSelection.Analog
};
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
@@ -194,11 +218,18 @@ namespace PepperDash.Essentials.DM
void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
{
var localVideoInputPort =
InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.VideoSourceFeedback);
var localAudioInputPort =
InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.AudioSourceFeedback);
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
AudioSourceNumericFeedback.FireUpdate();
}
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localAudioInputPort, eRoutingSignalType.Audio));
}
private void VgaInputOnInputStreamChange(EndpointInputStream inputStream, EndpointInputStreamEventArgs args)
{
@@ -319,17 +350,20 @@ namespace PepperDash.Essentials.DM
switch (id)
{
case EndpointTransmitterBase.VideoSourceFeedbackEventId:
var localVideoInputPort = InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.VideoSourceFeedback);
Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
ActiveVideoInputFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
Debug.Console(2, this, " Audio Source : {0}", Tx.AudioSourceFeedback);
var localInputAudioPort = InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.AudioSourceFeedback);
Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;
}
}
}
void InputStreamChangeEvent(EndpointInputStream inputStream, EndpointInputStreamEventArgs args)
{

View File

@@ -20,7 +20,7 @@ namespace PepperDash.Essentials.DM
using eVst = DmTx401C.eSourceSelection;
[Description("Wrapper class for DM-TX-401-C")]
public class DmTx401CController : DmTxControllerBase, ITxRouting, IIROutputPorts, IComPorts, IHasFreeRun, IVgaBrightnessContrastControls
public class DmTx401CController : DmTxControllerBase, ITxRoutingWithFeedback, IIROutputPorts, IComPorts, IHasFreeRun, IVgaBrightnessContrastControls
{
public DmTx401C Tx { get; private set; }
@@ -41,7 +41,21 @@ namespace PepperDash.Essentials.DM
public BoolFeedback FreeRunEnabledFeedback { get; protected set; }
public IntFeedback VgaBrightnessFeedback { get; protected set; }
public IntFeedback VgaContrastFeedback { get; protected set; }
public IntFeedback VgaContrastFeedback { get; protected set; }
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
/// <summary>
/// Helps get the "real" inputs, including when in Auto
@@ -104,20 +118,33 @@ namespace PepperDash.Essentials.DM
HdmiIn = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.HDMI, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInput));
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInput))
{
FeedbackMatchObject = eVst.HDMI
};
DisplayPortIn = new RoutingInputPortWithVideoStatuses(DmPortName.DisplayPortIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.DisplayPort, this,
VideoStatusHelper.GetDisplayPortInputStatusFuncs(tx.DisplayPortInput));
VideoStatusHelper.GetDisplayPortInputStatusFuncs(tx.DisplayPortInput))
{
FeedbackMatchObject = eVst.DisplayPort
};
VgaIn = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn,
eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, eVst.VGA, this,
VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput));
VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput))
{
FeedbackMatchObject = eVst.VGA
};
CompositeIn = new RoutingInputPortWithVideoStatuses(DmPortName.CompositeIn,
eRoutingSignalType.Video, eRoutingPortConnectionType.Composite, eVst.Composite, this,
VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput));
VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput))
{
FeedbackMatchObject = eVst.Composite
};
Tx.HdmiInput.InputStreamChange += HdmiInputStreamChangeEvent;
Tx.DisplayPortInput.InputStreamChange += DisplayPortInputStreamChangeEvent;
Tx.BaseEvent += Tx_BaseEvent;
Tx.OnlineStatusChange += Tx_OnlineStatusChange;
Tx.VgaInput.InputStreamChange += VgaInputOnInputStreamChange;
tx.VgaInput.VideoControls.ControlChange += VideoControls_ControlChange;
@@ -286,6 +313,20 @@ namespace PepperDash.Essentials.DM
Tx.AudioSource = (eVst)inputSelector;
}
void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
{
var localVideoInputPort =
InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
var localAudioInputPort =
InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.AudioSourceFeedback);
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localAudioInputPort, eRoutingSignalType.Audio));
}
void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
{
var id = args.EventId;
@@ -294,16 +335,20 @@ namespace PepperDash.Essentials.DM
switch (id)
{
case EndpointTransmitterBase.VideoSourceFeedbackEventId:
var localVideoInputPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
VideoSourceNumericFeedback.FireUpdate();
ActiveVideoInputFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
var localInputAudioPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.AudioSourceFeedback);
Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;
}
}
}
void VideoControls_ControlChange(object sender, GenericEventArgs args)
{

View File

@@ -20,8 +20,8 @@ namespace PepperDash.Essentials.DM
using eVst = Crestron.SimplSharpPro.DeviceSupport.eX02VideoSourceType;
using eAst = Crestron.SimplSharpPro.DeviceSupport.eX02AudioSourceType;
[Description("Wrapper class for DM-TX-4K-202-C")]
public class DmTx4k202CController : DmTxControllerBase, ITxRouting, IHasFeedback,
[Description("Wrapper class for DM-TX-4K-202-C")]
public class DmTx4k202CController : DmTxControllerBase, ITxRoutingWithFeedback, IHasFeedback,
IIROutputPorts, IComPorts
{
public DmTx4k202C Tx { get; private set; }
@@ -37,7 +37,21 @@ namespace PepperDash.Essentials.DM
public IntFeedback HdmiIn1HdcpCapabilityFeedback { get; protected set; }
public IntFeedback HdmiIn2HdcpCapabilityFeedback { get; protected set; }
public BoolFeedback Hdmi1VideoSyncFeedback { get; protected set; }
public BoolFeedback Hdmi2VideoSyncFeedback { get; protected set; }
public BoolFeedback Hdmi2VideoSyncFeedback { get; protected set; }
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
//public override IntFeedback HdcpSupportAllFeedback { get; protected set; }
//public override ushort HdcpSupportCapability { get; protected set; }
@@ -80,106 +94,121 @@ namespace PepperDash.Essentials.DM
{
return new RoutingPortCollection<RoutingOutputPort> { DmOut, HdmiLoopOut };
}
}
public DmTx4k202CController(string key, string name, DmTx4k202C tx)
: base(key, name, tx)
{
Tx = tx;
HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[1]));
HdmiIn2 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn2,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi2, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[2]));
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent;
Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent;
Tx.BaseEvent += Tx_BaseEvent;
VideoSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
AudioSourceNumericFeedback = new IntFeedback(() => (int)Tx.AudioSourceFeedback);
HdmiIn1HdcpCapabilityFeedback = new IntFeedback("HdmiIn1HdcpCapability", () => (int)tx.HdmiInputs[1].HdcpCapabilityFeedback);
HdmiIn2HdcpCapabilityFeedback = new IntFeedback("HdmiIn2HdcpCapability", () => (int)tx.HdmiInputs[2].HdcpCapabilityFeedback);
HdcpStateFeedback =
new IntFeedback(
() =>
tx.HdmiInputs[1].HdcpCapabilityFeedback > tx.HdmiInputs[2].HdcpCapabilityFeedback
? (int) tx.HdmiInputs[1].HdcpCapabilityFeedback
: (int) tx.HdmiInputs[2].HdcpCapabilityFeedback);
HdcpSupportCapability = eHdcpCapabilityType.Hdcp2_2Support;
Hdmi1VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue);
Hdmi2VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue);
var combinedFuncs = new VideoStatusFuncsWrapper
{
HdcpActiveFeedbackFunc = () =>
(ActualActiveVideoInput == eVst.Hdmi1
&& tx.HdmiInputs[1].VideoAttributes.HdcpActiveFeedback.BoolValue)
|| (ActualActiveVideoInput == eVst.Hdmi2
&& tx.HdmiInputs[2].VideoAttributes.HdcpActiveFeedback.BoolValue),
HdcpStateFeedbackFunc = () =>
{
if (ActualActiveVideoInput == eVst.Hdmi1)
return tx.HdmiInputs[1].VideoAttributes.HdcpStateFeedback.ToString();
if (ActualActiveVideoInput == eVst.Hdmi2)
return tx.HdmiInputs[2].VideoAttributes.HdcpStateFeedback.ToString();
return "";
},
VideoResolutionFeedbackFunc = () =>
{
if (ActualActiveVideoInput == eVst.Hdmi1)
return tx.HdmiInputs[1].VideoAttributes.GetVideoResolutionString();
if (ActualActiveVideoInput == eVst.Hdmi2)
return tx.HdmiInputs[2].VideoAttributes.GetVideoResolutionString();
return "";
},
VideoSyncFeedbackFunc = () =>
(ActualActiveVideoInput == eVst.Hdmi1
&& tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue)
|| (ActualActiveVideoInput == eVst.Hdmi2
&& tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue)
};
AnyVideoInput = new RoutingInputPortWithVideoStatuses(DmPortName.AnyVideoIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.None, 0, this, combinedFuncs);
DmOut = new RoutingOutputPort(DmPortName.DmOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.DmCat, null, this);
HdmiLoopOut = new RoutingOutputPort(DmPortName.HdmiLoopOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this);
AddToFeedbackList(ActiveVideoInputFeedback, VideoSourceNumericFeedback, AudioSourceNumericFeedback,
AnyVideoInput.VideoStatus.HasVideoStatusFeedback, AnyVideoInput.VideoStatus.HdcpActiveFeedback,
AnyVideoInput.VideoStatus.HdcpStateFeedback, AnyVideoInput.VideoStatus.VideoResolutionFeedback,
AnyVideoInput.VideoStatus.VideoSyncFeedback, HdmiIn1HdcpCapabilityFeedback, HdmiIn2HdcpCapabilityFeedback,
Hdmi1VideoSyncFeedback, Hdmi2VideoSyncFeedback);
// Set Ports for CEC
HdmiIn1.Port = Tx.HdmiInputs[1];
HdmiIn2.Port = Tx.HdmiInputs[2];
HdmiLoopOut.Port = Tx.HdmiOutput;
DmOut.Port = Tx.DmOutput;
}
}
public DmTx4k202CController(string key, string name, DmTx4k202C tx)
: base(key, name, tx)
{
Tx = tx;
HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[1]))
{
FeedbackMatchObject = eVst.Hdmi1
};
HdmiIn2 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn2,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi2, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[2]))
{
FeedbackMatchObject = eVst.Hdmi2
};
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent;
Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent;
Tx.BaseEvent += Tx_BaseEvent;
Tx.OnlineStatusChange += Tx_OnlineStatusChange;
VideoSourceNumericFeedback = new IntFeedback(() => (int) Tx.VideoSourceFeedback);
AudioSourceNumericFeedback = new IntFeedback(() => (int) Tx.AudioSourceFeedback);
HdmiIn1HdcpCapabilityFeedback = new IntFeedback("HdmiIn1HdcpCapability",
() => (int) tx.HdmiInputs[1].HdcpCapabilityFeedback);
HdmiIn2HdcpCapabilityFeedback = new IntFeedback("HdmiIn2HdcpCapability",
() => (int) tx.HdmiInputs[2].HdcpCapabilityFeedback);
HdcpStateFeedback =
new IntFeedback(
() =>
tx.HdmiInputs[1].HdcpCapabilityFeedback > tx.HdmiInputs[2].HdcpCapabilityFeedback
? (int) tx.HdmiInputs[1].HdcpCapabilityFeedback
: (int) tx.HdmiInputs[2].HdcpCapabilityFeedback);
HdcpSupportCapability = eHdcpCapabilityType.Hdcp2_2Support;
Hdmi1VideoSyncFeedback = new BoolFeedback(() => (bool) tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue);
Hdmi2VideoSyncFeedback = new BoolFeedback(() => (bool) tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue);
var combinedFuncs = new VideoStatusFuncsWrapper
{
HdcpActiveFeedbackFunc = () =>
(ActualActiveVideoInput == eVst.Hdmi1
&& tx.HdmiInputs[1].VideoAttributes.HdcpActiveFeedback.BoolValue)
|| (ActualActiveVideoInput == eVst.Hdmi2
&& tx.HdmiInputs[2].VideoAttributes.HdcpActiveFeedback.BoolValue),
HdcpStateFeedbackFunc = () =>
{
if (ActualActiveVideoInput == eVst.Hdmi1)
return tx.HdmiInputs[1].VideoAttributes.HdcpStateFeedback.ToString();
if (ActualActiveVideoInput == eVst.Hdmi2)
return tx.HdmiInputs[2].VideoAttributes.HdcpStateFeedback.ToString();
return "";
},
VideoResolutionFeedbackFunc = () =>
{
if (ActualActiveVideoInput == eVst.Hdmi1)
return tx.HdmiInputs[1].VideoAttributes.GetVideoResolutionString();
if (ActualActiveVideoInput == eVst.Hdmi2)
return tx.HdmiInputs[2].VideoAttributes.GetVideoResolutionString();
return "";
},
VideoSyncFeedbackFunc = () =>
(ActualActiveVideoInput == eVst.Hdmi1
&& tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue)
|| (ActualActiveVideoInput == eVst.Hdmi2
&& tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue)
};
AnyVideoInput = new RoutingInputPortWithVideoStatuses(DmPortName.AnyVideoIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.None, 0, this,
combinedFuncs);
DmOut = new RoutingOutputPort(DmPortName.DmOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.DmCat, null, this);
HdmiLoopOut = new RoutingOutputPort(DmPortName.HdmiLoopOut,
eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this);
AddToFeedbackList(ActiveVideoInputFeedback, VideoSourceNumericFeedback, AudioSourceNumericFeedback,
AnyVideoInput.VideoStatus.HasVideoStatusFeedback, AnyVideoInput.VideoStatus.HdcpActiveFeedback,
AnyVideoInput.VideoStatus.HdcpStateFeedback, AnyVideoInput.VideoStatus.VideoResolutionFeedback,
AnyVideoInput.VideoStatus.VideoSyncFeedback, HdmiIn1HdcpCapabilityFeedback,
HdmiIn2HdcpCapabilityFeedback,
Hdmi1VideoSyncFeedback, Hdmi2VideoSyncFeedback);
// Set Ports for CEC
HdmiIn1.Port = Tx.HdmiInputs[1];
HdmiIn2.Port = Tx.HdmiInputs[2];
HdmiLoopOut.Port = Tx.HdmiOutput;
DmOut.Port = Tx.DmOutput;
}
public override bool CustomActivate()
{
// Link up all of these damned events to the various RoutingPorts via a helper handler
@@ -294,26 +323,43 @@ namespace PepperDash.Essentials.DM
if (inputStream == Tx.HdmiInputs[2]) Hdmi2VideoSyncFeedback.FireUpdate();
break;
}
}
void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
{
var id = args.EventId;
Debug.Console(2, this, "EventId {0}", args.EventId);
switch (id)
{
case EndpointTransmitterBase.VideoSourceFeedbackEventId:
Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
ActiveVideoInputFeedback.FireUpdate();
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
Debug.Console(2, this, " Audio Source : {0}", Tx.AudioSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
break;
}
}
void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
{
var localVideoInputPort =
InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
var localAudioInputPort =
InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localAudioInputPort, eRoutingSignalType.Audio));
}
void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
{
var id = args.EventId;
Debug.Console(2, this, "EventId {0}", args.EventId);
switch (id)
{
case EndpointTransmitterBase.VideoSourceFeedbackEventId:
var localVideoInputPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
VideoSourceNumericFeedback.FireUpdate();
ActiveVideoInputFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
var localInputAudioPort = InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;
}
}
/// <summary>

View File

@@ -21,7 +21,7 @@ namespace PepperDash.Essentials.DM
using eAst = Crestron.SimplSharpPro.DeviceSupport.eX02AudioSourceType;
[Description("Wrapper class for DM-TX-4K-302-C")]
public class DmTx4k302CController : DmTxControllerBase, ITxRouting, IHasFeedback,
public class DmTx4k302CController : DmTxControllerBase, ITxRoutingWithFeedback, IHasFeedback,
IIROutputPorts, IComPorts, IHasFreeRun, IVgaBrightnessContrastControls
{
public DmTx4k302C Tx { get; private set; }
@@ -44,7 +44,21 @@ namespace PepperDash.Essentials.DM
public BoolFeedback FreeRunEnabledFeedback { get; protected set; }
public IntFeedback VgaBrightnessFeedback { get; protected set; }
public IntFeedback VgaContrastFeedback { get; protected set; }
public IntFeedback VgaContrastFeedback { get; protected set; }
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
/// <summary>
/// Helps get the "real" inputs, including when in Auto
@@ -95,13 +109,24 @@ namespace PepperDash.Essentials.DM
HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[1]));
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[1]))
{
FeedbackMatchObject = eVst.Hdmi1
};
HdmiIn2 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn2,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi2, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[2]));
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[2]))
{
FeedbackMatchObject = eVst.Hdmi2
};
VgaIn = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn,
eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, eVst.Vga, this,
VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput));
VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput))
{
FeedbackMatchObject = eVst.Vga
};
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
@@ -110,6 +135,8 @@ namespace PepperDash.Essentials.DM
Tx.VgaInput.InputStreamChange += VgaInputOnInputStreamChange;
Tx.BaseEvent += Tx_BaseEvent;
Tx.OnlineStatusChange += Tx_OnlineStatusChange;
VideoSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
AudioSourceNumericFeedback = new IntFeedback(() => (int)Tx.AudioSourceFeedback);
@@ -387,23 +414,42 @@ namespace PepperDash.Essentials.DM
break;
}
}
void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
{
var localVideoInputPort =
InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
var localAudioInputPort =
InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localAudioInputPort, eRoutingSignalType.Audio));
}
void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
{
var id = args.EventId;
Debug.Console(2, this, "EventId {0}", args.EventId);
switch (id)
{
case EndpointTransmitterBase.VideoSourceFeedbackEventId:
var localVideoInputPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
VideoSourceNumericFeedback.FireUpdate();
ActiveVideoInputFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
var localInputAudioPort = InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;
}
}
}
/// <summary>
/// Relays the input stream change to the appropriate RoutingInputPort.

View File

@@ -1,4 +1,6 @@
using Crestron.SimplSharpPro;
using System;
using System.Linq;
//using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
@@ -12,9 +14,9 @@ using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.DM
{
using eVst = eX02VideoSourceType;
using eAst = eX02AudioSourceType;
public class DmTx4kz202CController : DmTxControllerBase, ITxRouting,
using eAst = eX02AudioSourceType;
public class DmTx4kz202CController : DmTxControllerBase, ITxRoutingWithFeedback,
IIROutputPorts, IComPorts
{
public DmTx4kz202C Tx { get; private set; }
@@ -33,7 +35,21 @@ namespace PepperDash.Essentials.DM
public BoolFeedback Hdmi2VideoSyncFeedback { get; protected set; }
//public override IntFeedback HdcpSupportAllFeedback { get; protected set; }
//public override ushort HdcpSupportCapability { get; protected set; }
//public override ushort HdcpSupportCapability { get; protected set; }
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
/// <summary>
/// Helps get the "real" inputs, including when in Auto
@@ -73,14 +89,21 @@ namespace PepperDash.Essentials.DM
public DmTx4kz202CController(string key, string name, DmTx4kz202C tx)
: base(key, name, tx)
{
Tx = tx;
HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[1]));
HdmiIn2 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn2,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi2, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[2]));
Tx = tx;
HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[1]))
{
FeedbackMatchObject = eVst.Hdmi1
};
HdmiIn2 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn2,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi2, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[2]))
{
FeedbackMatchObject = eVst.Hdmi2
};
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
@@ -89,6 +112,7 @@ namespace PepperDash.Essentials.DM
Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent;
Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent;
Tx.BaseEvent += Tx_BaseEvent;
Tx.OnlineStatusChange += Tx_OnlineStatusChange;
VideoSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
@@ -282,27 +306,44 @@ namespace PepperDash.Essentials.DM
if (inputStream == Tx.HdmiInputs[2]) Hdmi2VideoSyncFeedback.FireUpdate();
break;
}
}
void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
{
var id = args.EventId;
Debug.Console(2, this, "EventId {0}", args.EventId);
switch (id)
{
case EndpointTransmitterBase.VideoSourceFeedbackEventId:
Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
AudioSourceNumericFeedback.FireUpdate();
ActiveVideoInputFeedback.FireUpdate();
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
Debug.Console(2, this, " Audio Source : {0}", Tx.AudioSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
break;
}
}
void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
{
var localVideoInputPort =
InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
var localAudioInputPort =
InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localAudioInputPort, eRoutingSignalType.Audio));
}
void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
{
var id = args.EventId;
Debug.Console(2, this, "EventId {0}", args.EventId);
switch (id)
{
case EndpointTransmitterBase.VideoSourceFeedbackEventId:
var localVideoInputPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
VideoSourceNumericFeedback.FireUpdate();
ActiveVideoInputFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
var localInputAudioPort = InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;
}
}
/// <summary>

View File

@@ -1,366 +1,426 @@
using Crestron.SimplSharpPro;
//using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Endpoints;
using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.DM
{
using eVst = eX02VideoSourceType;
using eAst = eX02AudioSourceType;
[Description("Wrapper class for DM-TX-4K-Z-302-C")]
public class DmTx4kz302CController : DmTxControllerBase, ITxRouting, IHasFeedback,
IIROutputPorts, IComPorts
{
public DmTx4kz302C Tx { get; private set; }
public RoutingInputPortWithVideoStatuses HdmiIn1 { get; private set; }
public RoutingInputPortWithVideoStatuses HdmiIn2 { get; private set; }
public RoutingInputPortWithVideoStatuses DisplayPortIn { get; private set; }
public RoutingOutputPort DmOut { get; private set; }
public RoutingOutputPort HdmiLoopOut { get; private set; }
public override StringFeedback ActiveVideoInputFeedback { get; protected set; }
public IntFeedback VideoSourceNumericFeedback { get; protected set; }
public IntFeedback AudioSourceNumericFeedback { get; protected set; }
public IntFeedback HdmiIn1HdcpCapabilityFeedback { get; protected set; }
public IntFeedback HdmiIn2HdcpCapabilityFeedback { get; protected set; }
public BoolFeedback Hdmi1VideoSyncFeedback { get; protected set; }
public BoolFeedback Hdmi2VideoSyncFeedback { get; protected set; }
public BoolFeedback DisplayPortVideoSyncFeedback { get; protected set; }
//public override IntFeedback HdcpSupportAllFeedback { get; protected set; }
//public override ushort HdcpSupportCapability { get; protected set; }
/// <summary>
/// Helps get the "real" inputs, including when in Auto
/// </summary>
public eX02VideoSourceType ActualActiveVideoInput
{
get
{
if (Tx.VideoSourceFeedback != eVst.Auto)
return Tx.VideoSourceFeedback;
if (Tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue)
return eVst.Hdmi1;
if (Tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue)
return eVst.Hdmi2;
return Tx.DisplayPortInput.SyncDetectedFeedback.BoolValue ? eVst.Vga : eVst.AllDisabled;
}
}
public RoutingPortCollection<RoutingInputPort> InputPorts
{
get
{
return new RoutingPortCollection<RoutingInputPort>
{
HdmiIn1,
HdmiIn2,
DisplayPortIn,
AnyVideoInput
};
}
}
public RoutingPortCollection<RoutingOutputPort> OutputPorts
{
get
{
return new RoutingPortCollection<RoutingOutputPort> { DmOut, HdmiLoopOut };
}
}
public DmTx4kz302CController(string key, string name, DmTx4kz302C tx)
: base(key, name, tx)
{
Tx = tx;
HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[1]));
HdmiIn2 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn2,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi2, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[2]));
DisplayPortIn = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DisplayPort, eVst.DisplayPort, this,
VideoStatusHelper.GetDisplayPortInputStatusFuncs(tx.DisplayPortInput));
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent;
Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent;
Tx.DisplayPortInput.InputStreamChange += DisplayPortInputStreamChange;
Tx.BaseEvent += Tx_BaseEvent;
VideoSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
AudioSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
HdmiIn1HdcpCapabilityFeedback = new IntFeedback("HdmiIn1HdcpCapability", () => (int)tx.HdmiInputs[1].HdcpCapabilityFeedback);
HdmiIn2HdcpCapabilityFeedback = new IntFeedback("HdmiIn2HdcpCapability", () => (int)tx.HdmiInputs[2].HdcpCapabilityFeedback);
HdcpStateFeedback =
new IntFeedback(
() =>
tx.HdmiInputs[1].HdcpCapabilityFeedback > tx.HdmiInputs[2].HdcpCapabilityFeedback
? (int)tx.HdmiInputs[1].HdcpCapabilityFeedback
: (int)tx.HdmiInputs[2].HdcpCapabilityFeedback);
HdcpSupportCapability = eHdcpCapabilityType.Hdcp2_2Support;
Hdmi1VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue);
Hdmi2VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue);
DisplayPortVideoSyncFeedback = new BoolFeedback(() => (bool)tx.DisplayPortInput.SyncDetectedFeedback.BoolValue);
var combinedFuncs = new VideoStatusFuncsWrapper
{
HdcpActiveFeedbackFunc = () =>
(ActualActiveVideoInput == eVst.Hdmi1
&& tx.HdmiInputs[1].VideoAttributes.HdcpActiveFeedback.BoolValue)
|| (ActualActiveVideoInput == eVst.Hdmi2
&& tx.HdmiInputs[2].VideoAttributes.HdcpActiveFeedback.BoolValue),
HdcpStateFeedbackFunc = () =>
{
if (ActualActiveVideoInput == eVst.Hdmi1)
return tx.HdmiInputs[1].VideoAttributes.HdcpStateFeedback.ToString();
return ActualActiveVideoInput == eVst.Hdmi2 ? tx.HdmiInputs[2].VideoAttributes.HdcpStateFeedback.ToString() : "";
},
VideoResolutionFeedbackFunc = () =>
{
if (ActualActiveVideoInput == eVst.Hdmi1)
return tx.HdmiInputs[1].VideoAttributes.GetVideoResolutionString();
if (ActualActiveVideoInput == eVst.Hdmi2)
return tx.HdmiInputs[2].VideoAttributes.GetVideoResolutionString();
return ActualActiveVideoInput == eVst.Vga ? tx.DisplayPortInput.VideoAttributes.GetVideoResolutionString() : "";
},
VideoSyncFeedbackFunc = () =>
(ActualActiveVideoInput == eVst.Hdmi1
&& tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue)
|| (ActualActiveVideoInput == eVst.Hdmi2
&& tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue)
|| (ActualActiveVideoInput == eVst.Vga
&& tx.DisplayPortInput.SyncDetectedFeedback.BoolValue)
};
AnyVideoInput = new RoutingInputPortWithVideoStatuses(DmPortName.AnyVideoIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.None, 0, this, combinedFuncs);
DmOut = new RoutingOutputPort(DmPortName.DmOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.DmCat, null, this);
HdmiLoopOut = new RoutingOutputPort(DmPortName.HdmiLoopOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this);
AddToFeedbackList(ActiveVideoInputFeedback, VideoSourceNumericFeedback, AudioSourceNumericFeedback,
AnyVideoInput.VideoStatus.HasVideoStatusFeedback, AnyVideoInput.VideoStatus.HdcpActiveFeedback,
AnyVideoInput.VideoStatus.HdcpStateFeedback, AnyVideoInput.VideoStatus.VideoResolutionFeedback,
AnyVideoInput.VideoStatus.VideoSyncFeedback, HdmiIn1HdcpCapabilityFeedback, HdmiIn2HdcpCapabilityFeedback,
Hdmi1VideoSyncFeedback, Hdmi2VideoSyncFeedback, DisplayPortVideoSyncFeedback);
// Set Ports for CEC
HdmiIn1.Port = Tx.HdmiInputs[1];
HdmiIn2.Port = Tx.HdmiInputs[2];
HdmiLoopOut.Port = Tx.HdmiOutput;
DmOut.Port = Tx.DmOutput;
}
void DisplayPortInputStreamChange(EndpointInputStream inputStream, EndpointInputStreamEventArgs args)
{
Debug.Console(2, "{0} event {1} stream {2}", Tx.ToString(), inputStream.ToString(), args.EventId.ToString());
switch (args.EventId)
{
case EndpointInputStreamEventIds.SyncDetectedFeedbackEventId:
DisplayPortVideoSyncFeedback.FireUpdate();
break;
}
}
public override bool CustomActivate()
{
// Link up all of these damned events to the various RoutingPorts via a helper handler
Tx.HdmiInputs[1].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn1, a.EventId);
Tx.HdmiInputs[1].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn1, a.EventId);
Tx.HdmiInputs[2].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn2, a.EventId);
Tx.HdmiInputs[2].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn2, a.EventId);
Tx.DisplayPortInput.InputStreamChange += (o, a) => FowardInputStreamChange(DisplayPortIn, a.EventId);
Tx.DisplayPortInput.VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(DisplayPortIn, a.EventId);
// Base does register and sets up comm monitoring.
return base.CustomActivate();
}
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = GetDmTxJoinMap(joinStart, joinMapKey);
if (Hdmi1VideoSyncFeedback != null)
{
Hdmi1VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input1VideoSyncStatus.JoinNumber]);
}
if (Hdmi2VideoSyncFeedback != null)
{
Hdmi2VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input2VideoSyncStatus.JoinNumber]);
}
if (DisplayPortVideoSyncFeedback != null)
{
DisplayPortVideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input3VideoSyncStatus.JoinNumber]);
}
LinkDmTxToApi(this, trilist, joinMap, bridge);
}
public void ExecuteNumericSwitch(ushort input, ushort output, eRoutingSignalType type)
{
Debug.Console(2, this, "Executing Numeric Switch to input {0}.", input);
switch (input)
{
case 0:
{
ExecuteSwitch(eVst.Auto, null, eRoutingSignalType.Audio | eRoutingSignalType.Video);
break;
}
case 1:
{
ExecuteSwitch(HdmiIn1.Selector, null, eRoutingSignalType.Audio | eRoutingSignalType.Video);
break;
}
case 2:
{
ExecuteSwitch(HdmiIn2.Selector, null, eRoutingSignalType.Audio | eRoutingSignalType.Video);
break;
}
case 3:
{
ExecuteSwitch(DisplayPortIn.Selector, null, eRoutingSignalType.Audio | eRoutingSignalType.Video);
break;
}
case 4:
{
ExecuteSwitch(eVst.AllDisabled, null, eRoutingSignalType.Audio | eRoutingSignalType.Video);
break;
}
}
}
public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType)
{
if ((signalType | eRoutingSignalType.Video) == eRoutingSignalType.Video)
Tx.VideoSource = (eVst)inputSelector;
// NOTE: It's possible that this particular TX model may not like the AudioSource property being set.
// The SIMPL definition only shows a single analog for AudioVideo Source
if ((signalType | eRoutingSignalType.Audio) == eRoutingSignalType.Audio)
//it doesn't
Debug.Console(2, this, "Unable to execute audio-only switch for tx {0}", Key);
//Tx.AudioSource = (eAst)inputSelector;
}
void InputStreamChangeEvent(EndpointInputStream inputStream, EndpointInputStreamEventArgs args)
{
Debug.Console(2, "{0} event {1} stream {2}", Tx.ToString(), inputStream.ToString(), args.EventId.ToString());
switch (args.EventId)
{
case EndpointInputStreamEventIds.HdcpSupportOffFeedbackEventId:
case EndpointInputStreamEventIds.HdcpSupportOnFeedbackEventId:
case EndpointInputStreamEventIds.HdcpCapabilityFeedbackEventId:
if (inputStream == Tx.HdmiInputs[1]) HdmiIn1HdcpCapabilityFeedback.FireUpdate();
if (inputStream == Tx.HdmiInputs[2]) HdmiIn2HdcpCapabilityFeedback.FireUpdate();
HdcpStateFeedback.FireUpdate();
break;
case EndpointInputStreamEventIds.SyncDetectedFeedbackEventId:
if (inputStream == Tx.HdmiInputs[1]) Hdmi1VideoSyncFeedback.FireUpdate();
if (inputStream == Tx.HdmiInputs[2]) Hdmi2VideoSyncFeedback.FireUpdate();
break;
}
}
void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
{
var id = args.EventId;
switch (id)
{
case EndpointTransmitterBase.VideoSourceFeedbackEventId:
Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
VideoSourceNumericFeedback.FireUpdate();
ActiveVideoInputFeedback.FireUpdate();
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
break;
}
}
/// <summary>
/// Relays the input stream change to the appropriate RoutingInputPort.
/// </summary>
void FowardInputStreamChange(RoutingInputPortWithVideoStatuses inputPort, int eventId)
{
if (eventId != EndpointInputStreamEventIds.SyncDetectedFeedbackEventId) return;
inputPort.VideoStatus.VideoSyncFeedback.FireUpdate();
AnyVideoInput.VideoStatus.VideoSyncFeedback.FireUpdate();
}
/// <summary>
/// Relays the VideoAttributes change to a RoutingInputPort
/// </summary>
void ForwardVideoAttributeChange(RoutingInputPortWithVideoStatuses inputPort, int eventId)
{
//// LOCATION: Crestron.SimplSharpPro.DM.VideoAttributeEventIds
//Debug.Console(2, this, "VideoAttributes_AttributeChange event id={0} from {1}",
// args.EventId, (sender as VideoAttributesEnhanced).Owner.GetType());
switch (eventId)
{
case VideoAttributeEventIds.HdcpActiveFeedbackEventId:
inputPort.VideoStatus.HdcpActiveFeedback.FireUpdate();
AnyVideoInput.VideoStatus.HdcpActiveFeedback.FireUpdate();
break;
case VideoAttributeEventIds.HdcpStateFeedbackEventId:
inputPort.VideoStatus.HdcpStateFeedback.FireUpdate();
AnyVideoInput.VideoStatus.HdcpStateFeedback.FireUpdate();
break;
case VideoAttributeEventIds.HorizontalResolutionFeedbackEventId:
case VideoAttributeEventIds.VerticalResolutionFeedbackEventId:
inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate();
AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate();
break;
case VideoAttributeEventIds.FramesPerSecondFeedbackEventId:
inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate();
AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate();
break;
}
}
#region IIROutputPorts Members
public CrestronCollection<IROutputPort> IROutputPorts { get { return Tx.IROutputPorts; } }
public int NumberOfIROutputPorts { get { return Tx.NumberOfIROutputPorts; } }
#endregion
#region IComPorts Members
public CrestronCollection<ComPort> ComPorts { get { return Tx.ComPorts; } }
public int NumberOfComPorts { get { return Tx.NumberOfComPorts; } }
#endregion
}
using Crestron.SimplSharpPro;
using System;
using System.Linq;
//using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Endpoints;
using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.DM
{
using eVst = eX02VideoSourceType;
using eAst = eX02AudioSourceType;
[Description("Wrapper class for DM-TX-4K-Z-302-C")]
public class DmTx4kz302CController : DmTxControllerBase, ITxRoutingWithFeedback, IHasFeedback,
IIROutputPorts, IComPorts
{
public DmTx4kz302C Tx { get; private set; }
public RoutingInputPortWithVideoStatuses HdmiIn1 { get; private set; }
public RoutingInputPortWithVideoStatuses HdmiIn2 { get; private set; }
public RoutingInputPortWithVideoStatuses DisplayPortIn { get; private set; }
public RoutingOutputPort DmOut { get; private set; }
public RoutingOutputPort HdmiLoopOut { get; private set; }
public override StringFeedback ActiveVideoInputFeedback { get; protected set; }
public IntFeedback VideoSourceNumericFeedback { get; protected set; }
public IntFeedback AudioSourceNumericFeedback { get; protected set; }
public IntFeedback HdmiIn1HdcpCapabilityFeedback { get; protected set; }
public IntFeedback HdmiIn2HdcpCapabilityFeedback { get; protected set; }
public BoolFeedback Hdmi1VideoSyncFeedback { get; protected set; }
public BoolFeedback Hdmi2VideoSyncFeedback { get; protected set; }
public BoolFeedback DisplayPortVideoSyncFeedback { get; protected set; }
//public override IntFeedback HdcpSupportAllFeedback { get; protected set; }
//public override ushort HdcpSupportCapability { get; protected set; }
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
/// <summary>
/// Helps get the "real" inputs, including when in Auto
/// </summary>
public eX02VideoSourceType ActualActiveVideoInput
{
get
{
if (Tx.VideoSourceFeedback != eVst.Auto)
return Tx.VideoSourceFeedback;
if (Tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue)
return eVst.Hdmi1;
if (Tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue)
return eVst.Hdmi2;
return Tx.DisplayPortInput.SyncDetectedFeedback.BoolValue ? eVst.Vga : eVst.AllDisabled;
}
}
public RoutingPortCollection<RoutingInputPort> InputPorts
{
get
{
return new RoutingPortCollection<RoutingInputPort>
{
HdmiIn1,
HdmiIn2,
DisplayPortIn,
AnyVideoInput
};
}
}
public RoutingPortCollection<RoutingOutputPort> OutputPorts
{
get
{
return new RoutingPortCollection<RoutingOutputPort> { DmOut, HdmiLoopOut };
}
}
public DmTx4kz302CController(string key, string name, DmTx4kz302C tx)
: base(key, name, tx)
{
Tx = tx;
HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[1]))
{
FeedbackMatchObject = eVst.Hdmi1
};
HdmiIn2 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn2,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi2, this,
VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[2]))
{
FeedbackMatchObject = eVst.Hdmi2
};
DisplayPortIn = new RoutingInputPortWithVideoStatuses(DmPortName.DisplayPortIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DisplayPort, eVst.DisplayPort, this,
VideoStatusHelper.GetDisplayPortInputStatusFuncs(tx.DisplayPortInput))
{
FeedbackMatchObject = eVst.DisplayPort
};
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent;
Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent;
Tx.DisplayPortInput.InputStreamChange += DisplayPortInputStreamChange;
Tx.BaseEvent += Tx_BaseEvent;
Tx.OnlineStatusChange += Tx_OnlineStatusChange;
VideoSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
AudioSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
HdmiIn1HdcpCapabilityFeedback = new IntFeedback("HdmiIn1HdcpCapability", () => (int)tx.HdmiInputs[1].HdcpCapabilityFeedback);
HdmiIn2HdcpCapabilityFeedback = new IntFeedback("HdmiIn2HdcpCapability", () => (int)tx.HdmiInputs[2].HdcpCapabilityFeedback);
HdcpStateFeedback =
new IntFeedback(
() =>
tx.HdmiInputs[1].HdcpCapabilityFeedback > tx.HdmiInputs[2].HdcpCapabilityFeedback
? (int)tx.HdmiInputs[1].HdcpCapabilityFeedback
: (int)tx.HdmiInputs[2].HdcpCapabilityFeedback);
HdcpSupportCapability = eHdcpCapabilityType.Hdcp2_2Support;
Hdmi1VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue);
Hdmi2VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue);
DisplayPortVideoSyncFeedback = new BoolFeedback(() => (bool)tx.DisplayPortInput.SyncDetectedFeedback.BoolValue);
var combinedFuncs = new VideoStatusFuncsWrapper
{
HdcpActiveFeedbackFunc = () =>
(ActualActiveVideoInput == eVst.Hdmi1
&& tx.HdmiInputs[1].VideoAttributes.HdcpActiveFeedback.BoolValue)
|| (ActualActiveVideoInput == eVst.Hdmi2
&& tx.HdmiInputs[2].VideoAttributes.HdcpActiveFeedback.BoolValue),
HdcpStateFeedbackFunc = () =>
{
if (ActualActiveVideoInput == eVst.Hdmi1)
return tx.HdmiInputs[1].VideoAttributes.HdcpStateFeedback.ToString();
return ActualActiveVideoInput == eVst.Hdmi2 ? tx.HdmiInputs[2].VideoAttributes.HdcpStateFeedback.ToString() : "";
},
VideoResolutionFeedbackFunc = () =>
{
if (ActualActiveVideoInput == eVst.Hdmi1)
return tx.HdmiInputs[1].VideoAttributes.GetVideoResolutionString();
if (ActualActiveVideoInput == eVst.Hdmi2)
return tx.HdmiInputs[2].VideoAttributes.GetVideoResolutionString();
return ActualActiveVideoInput == eVst.Vga ? tx.DisplayPortInput.VideoAttributes.GetVideoResolutionString() : "";
},
VideoSyncFeedbackFunc = () =>
(ActualActiveVideoInput == eVst.Hdmi1
&& tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue)
|| (ActualActiveVideoInput == eVst.Hdmi2
&& tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue)
|| (ActualActiveVideoInput == eVst.Vga
&& tx.DisplayPortInput.SyncDetectedFeedback.BoolValue)
};
AnyVideoInput = new RoutingInputPortWithVideoStatuses(DmPortName.AnyVideoIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.None, 0, this, combinedFuncs);
DmOut = new RoutingOutputPort(DmPortName.DmOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.DmCat, null, this);
HdmiLoopOut = new RoutingOutputPort(DmPortName.HdmiLoopOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this);
AddToFeedbackList(ActiveVideoInputFeedback, VideoSourceNumericFeedback, AudioSourceNumericFeedback,
AnyVideoInput.VideoStatus.HasVideoStatusFeedback, AnyVideoInput.VideoStatus.HdcpActiveFeedback,
AnyVideoInput.VideoStatus.HdcpStateFeedback, AnyVideoInput.VideoStatus.VideoResolutionFeedback,
AnyVideoInput.VideoStatus.VideoSyncFeedback, HdmiIn1HdcpCapabilityFeedback, HdmiIn2HdcpCapabilityFeedback,
Hdmi1VideoSyncFeedback, Hdmi2VideoSyncFeedback, DisplayPortVideoSyncFeedback);
// Set Ports for CEC
HdmiIn1.Port = Tx.HdmiInputs[1];
HdmiIn2.Port = Tx.HdmiInputs[2];
HdmiLoopOut.Port = Tx.HdmiOutput;
DmOut.Port = Tx.DmOutput;
}
void DisplayPortInputStreamChange(EndpointInputStream inputStream, EndpointInputStreamEventArgs args)
{
Debug.Console(2, "{0} event {1} stream {2}", Tx.ToString(), inputStream.ToString(), args.EventId.ToString());
switch (args.EventId)
{
case EndpointInputStreamEventIds.SyncDetectedFeedbackEventId:
DisplayPortVideoSyncFeedback.FireUpdate();
break;
}
}
public override bool CustomActivate()
{
// Link up all of these damned events to the various RoutingPorts via a helper handler
Tx.HdmiInputs[1].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn1, a.EventId);
Tx.HdmiInputs[1].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn1, a.EventId);
Tx.HdmiInputs[2].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn2, a.EventId);
Tx.HdmiInputs[2].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn2, a.EventId);
Tx.DisplayPortInput.InputStreamChange += (o, a) => FowardInputStreamChange(DisplayPortIn, a.EventId);
Tx.DisplayPortInput.VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(DisplayPortIn, a.EventId);
// Base does register and sets up comm monitoring.
return base.CustomActivate();
}
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = GetDmTxJoinMap(joinStart, joinMapKey);
if (Hdmi1VideoSyncFeedback != null)
{
Hdmi1VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input1VideoSyncStatus.JoinNumber]);
}
if (Hdmi2VideoSyncFeedback != null)
{
Hdmi2VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input2VideoSyncStatus.JoinNumber]);
}
if (DisplayPortVideoSyncFeedback != null)
{
DisplayPortVideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input3VideoSyncStatus.JoinNumber]);
}
LinkDmTxToApi(this, trilist, joinMap, bridge);
}
public void ExecuteNumericSwitch(ushort input, ushort output, eRoutingSignalType type)
{
Debug.Console(2, this, "Executing Numeric Switch to input {0}.", input);
switch (input)
{
case 0:
{
ExecuteSwitch(eVst.Auto, null, type);
break;
}
case 1:
{
ExecuteSwitch(HdmiIn1.Selector, null, type);
break;
}
case 2:
{
ExecuteSwitch(HdmiIn2.Selector, null, type);
break;
}
case 3:
{
ExecuteSwitch(DisplayPortIn.Selector, null, type);
break;
}
case 4:
{
ExecuteSwitch(eVst.AllDisabled, null, type);
break;
}
default:
{
Debug.Console(2, this, "Unable to execute numeric switch to input {0}", input);
break;
}
}
}
public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType)
{
try
{
Debug.Console(2, this, "Attempting to switch InputSelector {0}", ((eVst)inputSelector).ToString());
if ((signalType | eRoutingSignalType.Video) == eRoutingSignalType.Video)
Tx.VideoSource = (eVst)inputSelector;
// NOTE: It's possible that this particular TX model may not like the AudioSource property being set.
// The SIMPL definition only shows a single analog for AudioVideo Source
if ((signalType | eRoutingSignalType.Audio) == eRoutingSignalType.Audio)
//it doesn't
Debug.Console(2, this, "Unable to execute audio-only switch for tx {0}", Key);
//Tx.AudioSource = (eAst)inputSelector;
}
catch (Exception e)
{
Debug.Console(2, this, "Exception in ExecuteSwitch: {0}", e);
}
}
void InputStreamChangeEvent(EndpointInputStream inputStream, EndpointInputStreamEventArgs args)
{
Debug.Console(2, "{0} event {1} stream {2}", Tx.ToString(), inputStream.ToString(), args.EventId.ToString());
switch (args.EventId)
{
case EndpointInputStreamEventIds.HdcpSupportOffFeedbackEventId:
case EndpointInputStreamEventIds.HdcpSupportOnFeedbackEventId:
case EndpointInputStreamEventIds.HdcpCapabilityFeedbackEventId:
if (inputStream == Tx.HdmiInputs[1]) HdmiIn1HdcpCapabilityFeedback.FireUpdate();
if (inputStream == Tx.HdmiInputs[2]) HdmiIn2HdcpCapabilityFeedback.FireUpdate();
HdcpStateFeedback.FireUpdate();
break;
case EndpointInputStreamEventIds.SyncDetectedFeedbackEventId:
if (inputStream == Tx.HdmiInputs[1]) Hdmi1VideoSyncFeedback.FireUpdate();
if (inputStream == Tx.HdmiInputs[2]) Hdmi2VideoSyncFeedback.FireUpdate();
break;
}
}
void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
{
var localVideoInputPort =
InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
var localAudioInputPort =
InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localAudioInputPort, eRoutingSignalType.Audio));
}
void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
{
var id = args.EventId;
Debug.Console(2, this, "EventId {0}", args.EventId);
switch (id)
{
case EndpointTransmitterBase.VideoSourceFeedbackEventId:
var localVideoInputPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
VideoSourceNumericFeedback.FireUpdate();
ActiveVideoInputFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
var localInputAudioPort = InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;
}
}
/// <summary>
/// Relays the input stream change to the appropriate RoutingInputPort.
/// </summary>
void FowardInputStreamChange(RoutingInputPortWithVideoStatuses inputPort, int eventId)
{
if (eventId != EndpointInputStreamEventIds.SyncDetectedFeedbackEventId) return;
inputPort.VideoStatus.VideoSyncFeedback.FireUpdate();
AnyVideoInput.VideoStatus.VideoSyncFeedback.FireUpdate();
}
/// <summary>
/// Relays the VideoAttributes change to a RoutingInputPort
/// </summary>
void ForwardVideoAttributeChange(RoutingInputPortWithVideoStatuses inputPort, int eventId)
{
//// LOCATION: Crestron.SimplSharpPro.DM.VideoAttributeEventIds
//Debug.Console(2, this, "VideoAttributes_AttributeChange event id={0} from {1}",
// args.EventId, (sender as VideoAttributesEnhanced).Owner.GetType());
switch (eventId)
{
case VideoAttributeEventIds.HdcpActiveFeedbackEventId:
inputPort.VideoStatus.HdcpActiveFeedback.FireUpdate();
AnyVideoInput.VideoStatus.HdcpActiveFeedback.FireUpdate();
break;
case VideoAttributeEventIds.HdcpStateFeedbackEventId:
inputPort.VideoStatus.HdcpStateFeedback.FireUpdate();
AnyVideoInput.VideoStatus.HdcpStateFeedback.FireUpdate();
break;
case VideoAttributeEventIds.HorizontalResolutionFeedbackEventId:
case VideoAttributeEventIds.VerticalResolutionFeedbackEventId:
inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate();
AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate();
break;
case VideoAttributeEventIds.FramesPerSecondFeedbackEventId:
inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate();
AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate();
break;
}
}
#region IIROutputPorts Members
public CrestronCollection<IROutputPort> IROutputPorts { get { return Tx.IROutputPorts; } }
public int NumberOfIROutputPorts { get { return Tx.NumberOfIROutputPorts; } }
#endregion
#region IComPorts Members
public CrestronCollection<ComPort> ComPorts { get { return Tx.ComPorts; } }
public int NumberOfComPorts { get { return Tx.NumberOfComPorts; } }
#endregion
}
}

View File

@@ -59,7 +59,7 @@
<HintPath>..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="PepperDash_Core, Version=1.0.41.31808, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="PepperDash_Core, Version=1.0.42.30563, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll</HintPath>
</Reference>

View File

@@ -181,14 +181,18 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
});
}
if (cameraDevice is IPower)
var powerCamera = cameraDevice as IHasPowerControl;
if (powerCamera != null)
{
var powerCamera = cameraDevice as IPower;
trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () => powerCamera.PowerOn());
trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () => powerCamera.PowerOff());
powerCamera.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]);
powerCamera.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]);
var powerFbCamera = powerCamera as IHasPowerControlWithFeedback;
if (powerFbCamera != null)
{
powerFbCamera.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]);
powerFbCamera.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]);
}
}
if (cameraDevice is ICommunicationMonitor)

View File

@@ -92,8 +92,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// </summary>
public interface IHasCameraPanControl : IHasCameraControls
{
// void PanLeft(bool pressRelease);
// void PanRight(bool pressRelease);
void PanLeft();
void PanRight();
void PanStop();
@@ -104,8 +102,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// </summary>
public interface IHasCameraTiltControl : IHasCameraControls
{
// void TiltDown(bool pressRelease);
// void TildUp(bool pressRelease);
void TiltDown();
void TiltUp();
void TiltStop();
@@ -116,8 +112,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// </summary>
public interface IHasCameraZoomControl : IHasCameraControls
{
// void ZoomIn(bool pressRelease);
// void ZoomOut(bool pressRelease);
void ZoomIn();
void ZoomOut();
void ZoomStop();
@@ -135,6 +129,13 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
void TriggerAutoFocus();
}
public interface IHasAutoFocusMode
{
void SetFocusModeAuto();
void SetFocusModeManual();
void ToggleFocusMode();
}
public interface IHasCameraAutoMode : IHasCameraControls
{
void CameraAutoModeOn();

View File

@@ -12,29 +12,86 @@ using PepperDash.Essentials.Devices.Common.Codec;
using System.Text.RegularExpressions;
using Crestron.SimplSharp.Reflection;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.Cameras
{
public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IPower, IBridgeAdvanced
public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IHasPowerControlWithFeedback, IBridgeAdvanced, IHasCameraFocusControl, IHasAutoFocusMode
{
CameraViscaPropertiesConfig PropertiesConfig;
public IBasicCommunication Communication { get; private set; }
public CommunicationGather PortGather { get; private set; }
public StatusMonitorBase CommunicationMonitor { get; private set; }
public byte PanSpeed = 0x10;
public byte TiltSpeed = 0x10;
/// <summary>
/// Used to store the actions to parse inquiry responses as the inquiries are sent
/// </summary>
private CrestronQueue<Action<byte[]>> InquiryResponseQueue;
/// <summary>
/// Camera ID (Default 1)
/// </summary>
public byte ID = 0x01;
public byte ResponseID;
public byte PanSpeedSlow = 0x10;
public byte TiltSpeedSlow = 0x10;
public byte PanSpeedFast = 0x13;
public byte TiltSpeedFast = 0x13;
private bool IsMoving;
private bool IsZooming;
public bool PowerIsOn { get; private set; }
bool _powerIsOn;
public bool PowerIsOn
{
get
{
return _powerIsOn;
}
private set
{
if (value != _powerIsOn)
{
_powerIsOn = value;
PowerIsOnFeedback.FireUpdate();
CameraIsOffFeedback.FireUpdate();
}
}
}
const byte ZoomInCmd = 0x02;
const byte ZoomOutCmd = 0x03;
const byte ZoomStopCmd = 0x00;
/// <summary>
/// Used to determine when to move the camera at a faster speed if a direction is held
/// </summary>
CTimer SpeedTimer;
// TODO: Implment speed timer for PTZ controls
long FastSpeedHoldTimeMs = 2000;
byte[] IncomingBuffer = new byte[] { };
public BoolFeedback PowerIsOnFeedback { get; private set; }
public CameraVisca(string key, string name, IBasicCommunication comm, CameraPropertiesConfig props) :
public CameraVisca(string key, string name, IBasicCommunication comm, CameraViscaPropertiesConfig props) :
base(key, name)
{
InquiryResponseQueue = new CrestronQueue<Action<byte[]>>(15);
Presets = props.Presets;
PropertiesConfig = props;
ID = (byte)(props.Id + 0x80);
ResponseID = (byte)((props.Id * 0x10) + 0x80);
SetupCameraSpeeds();
OutputPorts.Add(new RoutingOutputPort("videoOut", eRoutingSignalType.Video, eRoutingPortConnectionType.None, null, this, true));
// Default to all capabilties
@@ -51,11 +108,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
{
// This instance uses RS-232 control
}
PortGather = new CommunicationGather(Communication, "\xFF");
Communication.BytesReceived += new EventHandler<GenericCommMethodReceiveBytesArgs>(Communication_BytesReceived);
PowerIsOnFeedback = new BoolFeedback(() => { return PowerIsOn; });
CameraIsOffFeedback = new BoolFeedback(() => { return !PowerIsOn; });
if (props.CommunicationMonitorProperties != null)
{
@@ -66,9 +122,38 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 20000, 120000, 300000, "\x81\x09\x04\x00\xFF");
}
DeviceManager.AddDevice(CommunicationMonitor);
}
/// <summary>
/// Sets up camera speed values based on config
/// </summary>
void SetupCameraSpeeds()
{
if (PropertiesConfig.FastSpeedHoldTimeMs > 0)
{
FastSpeedHoldTimeMs = PropertiesConfig.FastSpeedHoldTimeMs;
}
if (PropertiesConfig.PanSpeedSlow > 0)
{
PanSpeedSlow = (byte)PropertiesConfig.PanSpeedSlow;
}
if (PropertiesConfig.PanSpeedFast > 0)
{
PanSpeedFast = (byte)PropertiesConfig.PanSpeedFast;
}
if (PropertiesConfig.TiltSpeedSlow > 0)
{
TiltSpeedSlow = (byte)PropertiesConfig.TiltSpeedSlow;
}
if (PropertiesConfig.TiltSpeedFast > 0)
{
TiltSpeedFast = (byte)PropertiesConfig.TiltSpeedFast;
}
}
public override bool CustomActivate()
{
Communication.Connect();
@@ -110,40 +195,245 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
Communication.SendBytes(b);
}
void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e)
{
// This is probably not thread-safe buffering
// Append the incoming bytes with whatever is in the buffer
var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length];
IncomingBuffer.CopyTo(newBytes, 0);
e.Bytes.CopyTo(newBytes, IncomingBuffer.Length);
if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
Debug.Console(2, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes));
}
var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length];
try
{
// This is probably not thread-safe buffering
// Append the incoming bytes with whatever is in the buffer
IncomingBuffer.CopyTo(newBytes, 0);
e.Bytes.CopyTo(newBytes, IncomingBuffer.Length);
if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
Debug.Console(2, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes));
private void SendPanTiltCommand (byte[] cmd)
byte[] message = new byte[] { };
// Search for the delimiter 0xFF character
for (int i = 0; i < newBytes.Length; i++)
{
if (newBytes[i] == 0xFF)
{
// i will be the index of the delmiter character
message = newBytes.Take(i).ToArray();
// Skip over what we just took and save the rest for next time
newBytes = newBytes.Skip(i).ToArray();
}
}
if (message.Length > 0)
{
// Check for matching ID
if (message[0] != ResponseID)
{
return;
}
switch (message[1])
{
case 0x40:
{
// ACK received
Debug.Console(2, this, "ACK Received");
break;
}
case 0x50:
{
if (message[2] == 0xFF)
{
// Completion received
Debug.Console(2, this, "Completion Received");
}
else
{
// Inquiry response received. Dequeue the next response handler and invoke it
if (InquiryResponseQueue.Count > 0)
{
var inquiryAction = InquiryResponseQueue.Dequeue();
inquiryAction.Invoke(message.Skip(2).ToArray());
}
else
{
Debug.Console(2, this, "Response Queue is empty. Nothing to dequeue.");
}
}
break;
}
case 0x60:
{
// Error message
switch (message[2])
{
case 0x01:
{
// Message Length Error
Debug.Console(2, this, "Error from device: Message Length Error");
break;
}
case 0x02:
{
// Syntax Error
Debug.Console(2, this, "Error from device: Syntax Error");
break;
}
case 0x03:
{
// Command Buffer Full
Debug.Console(2, this, "Error from device: Command Buffer Full");
break;
}
case 0x04:
{
// Command Cancelled
Debug.Console(2, this, "Error from device: Command Cancelled");
break;
}
case 0x05:
{
// No Socket
Debug.Console(2, this, "Error from device: No Socket");
break;
}
case 0x41:
{
// Command not executable
Debug.Console(2, this, "Error from device: Command not executable");
break;
}
}
break;
}
}
if (message == new byte[] { ResponseID, 0x50, 0x02, 0xFF })
{
PowerIsOn = true;
}
else if (message == new byte[] { ResponseID, 0x50, 0x03, 0xFF })
{
PowerIsOn = false;
}
}
}
catch (Exception err)
{
Debug.Console(2, this, "Error parsing feedback: {0}", err);
}
finally
{
// Save whatever partial message is here
IncomingBuffer = newBytes;
}
}
/// <summary>
/// Sends a pan/tilt command. If the command is not for fastSpeed then it starts a timer to initiate fast speed.
/// </summary>
/// <param name="cmd"></param>
/// <param name="fastSpeed"></param>
private void SendPanTiltCommand (byte[] cmd, bool fastSpeedEnabled)
{
var temp = new Byte[] { 0x81, 0x01, 0x06, 0x01, PanSpeed, TiltSpeed };
int length = temp.Length + cmd.Length + 1;
byte[] sum = new byte[length];
temp.CopyTo(sum, 0);
cmd.CopyTo(sum, temp.Length);
sum[length - 1] = 0xFF;
SendBytes(sum);
SendBytes(GetPanTiltCommand(cmd, fastSpeedEnabled));
if (!fastSpeedEnabled)
{
if (SpeedTimer != null)
{
StopSpeedTimer();
}
// Start the timer to send fast speed if still moving after FastSpeedHoldTime elapses
SpeedTimer = new CTimer((o) => SendPanTiltCommand(GetPanTiltCommand(cmd, true), true), FastSpeedHoldTimeMs);
}
}
private void StopSpeedTimer()
{
if (SpeedTimer != null)
{
SpeedTimer.Stop();
SpeedTimer.Dispose();
SpeedTimer = null;
}
}
/// <summary>
/// Generates the pan/tilt command with either slow or fast speed
/// </summary>
/// <param name="cmd"></param>
/// <param name="fastSpeed"></param>
/// <returns></returns>
private byte[] GetPanTiltCommand(byte[] cmd, bool fastSpeed)
{
byte panSpeed;
byte tiltSpeed;
if (!fastSpeed)
{
panSpeed = PanSpeedSlow;
tiltSpeed = TiltSpeedSlow;
}
else
{
panSpeed = PanSpeedFast;
tiltSpeed = TiltSpeedFast;
}
var temp = new byte[] { ID, 0x01, 0x06, 0x01, panSpeed, tiltSpeed };
int length = temp.Length + cmd.Length + 1;
byte[] sum = new byte[length];
temp.CopyTo(sum, 0);
cmd.CopyTo(sum, temp.Length);
sum[length - 1] = 0xFF;
return sum;
}
void SendPowerQuery()
{
SendBytes(new byte[] { ID, 0x09, 0x04, 0x00, 0xFF });
InquiryResponseQueue.Enqueue(HandlePowerResponse);
}
public void PowerOn()
{
SendBytes(new Byte[] { 0x81, 0x01, 0x04, 0x00, 0x02, 0xFF });
SendBytes(new byte[] { ID, 0x01, 0x04, 0x00, 0x02, 0xFF });
SendPowerQuery();
}
void HandlePowerResponse(byte[] response)
{
switch (response[0])
{
case 0x02:
{
PowerIsOn = true;
break;
}
case 0x03:
{
PowerIsOn = false;
break;
}
}
}
public void PowerOff()
{
SendBytes(new Byte[] {0x81, 0x01, 0x04, 0x00, 0x03, 0xFF});
}
SendBytes(new byte[] {ID, 0x01, 0x04, 0x00, 0x03, 0xFF});
SendPowerQuery();
}
public void PowerToggle()
{
@@ -155,12 +445,12 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
public void PanLeft()
{
SendPanTiltCommand(new byte[] {0x01, 0x03});
SendPanTiltCommand(new byte[] {0x01, 0x03}, false);
IsMoving = true;
}
public void PanRight()
{
SendPanTiltCommand(new byte[] { 0x02, 0x03 });
SendPanTiltCommand(new byte[] { 0x02, 0x03 }, false);
IsMoving = true;
}
public void PanStop()
@@ -169,12 +459,12 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
}
public void TiltDown()
{
SendPanTiltCommand(new byte[] { 0x03, 0x02 });
SendPanTiltCommand(new byte[] { 0x03, 0x02 }, false);
IsMoving = true;
}
public void TiltUp()
{
SendPanTiltCommand(new byte[] { 0x03, 0x01 });
SendPanTiltCommand(new byte[] { 0x03, 0x01 }, false);
IsMoving = true;
}
public void TiltStop()
@@ -184,16 +474,18 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
private void SendZoomCommand (byte cmd)
{
SendBytes(new byte[] {0x81, 0x01, 0x04, 0x07, cmd, 0xFF} );
SendBytes(new byte[] {ID, 0x01, 0x04, 0x07, cmd, 0xFF} );
}
public void ZoomIn()
{
SendZoomCommand(0x02);
SendZoomCommand(ZoomInCmd);
IsZooming = true;
}
public void ZoomOut()
{
SendZoomCommand(0x03);
SendZoomCommand(ZoomOutCmd);
IsZooming = true;
}
public void ZoomStop()
@@ -205,26 +497,28 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
{
if (IsZooming)
{
SendZoomCommand(0x00);
SendZoomCommand(ZoomStopCmd);
IsZooming = false;
}
else
{
SendPanTiltCommand(new byte[] {0x03, 0x03});
StopSpeedTimer();
SendPanTiltCommand(new byte[] { 0x03, 0x03 }, false);
IsMoving = false;
}
}
public void PositionHome()
{
throw new NotImplementedException();
SendBytes(new byte[] { ID, 0x01, 0x06, 0x02, PanSpeedFast, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF });
SendBytes(new byte[] { ID, 0x01, 0x04, 0x47, 0x00, 0x00, 0x00, 0x00, 0xFF });
}
public void RecallPreset(int presetNumber)
{
SendBytes(new byte[] {0x81, 0x01, 0x04, 0x3F, 0x02, (byte)presetNumber, 0xFF} );
SendBytes(new byte[] {ID, 0x01, 0x04, 0x3F, 0x02, (byte)presetNumber, 0xFF} );
}
public void SavePreset(int presetNumber)
{
SendBytes(new byte[] { 0x81, 0x01, 0x04, 0x3F, 0x01, (byte)presetNumber, 0xFF });
SendBytes(new byte[] { ID, 0x01, 0x04, 0x3F, 0x01, (byte)presetNumber, 0xFF });
}
#region IHasCameraPresets Members
@@ -244,6 +538,90 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
}
#endregion
#region IHasCameraFocusControl Members
public void FocusNear()
{
SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x03, 0xFF });
}
public void FocusFar()
{
SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x02, 0xFF });
}
public void FocusStop()
{
SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x00, 0xFF });
}
public void TriggerAutoFocus()
{
SendBytes(new byte[] { ID, 0x01, 0x04, 0x18, 0x01, 0xFF });
SendAutoFocusQuery();
}
#endregion
#region IHasAutoFocus Members
public void SetFocusModeAuto()
{
SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x02, 0xFF });
SendAutoFocusQuery();
}
public void SetFocusModeManual()
{
SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x03, 0xFF });
SendAutoFocusQuery();
}
public void ToggleFocusMode()
{
SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x10, 0xFF });
SendAutoFocusQuery();
}
#endregion
void SendAutoFocusQuery()
{
SendBytes(new byte[] { ID, 0x09, 0x04, 0x38, 0xFF });
InquiryResponseQueue.Enqueue(HandleAutoFocusResponse);
}
void HandleAutoFocusResponse(byte[] response)
{
switch (response[0])
{
case 0x02:
{
// Auto Mode
PowerIsOn = true;
break;
}
case 0x03:
{
// Manual Mode
PowerIsOn = false;
break;
}
}
}
#region IHasCameraOff Members
public BoolFeedback CameraIsOffFeedback { get; private set; }
public void CameraOff()
{
PowerOff();
}
#endregion
}
public class CameraViscaFactory : EssentialsDeviceFactory<CameraVisca>
@@ -257,10 +635,51 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
{
Debug.Console(1, "Factory Attempting to create new CameraVisca Device");
var comm = CommFactory.CreateCommForDevice(dc);
var props = Newtonsoft.Json.JsonConvert.DeserializeObject<Cameras.CameraPropertiesConfig>(
var props = Newtonsoft.Json.JsonConvert.DeserializeObject<Cameras.CameraViscaPropertiesConfig>(
dc.Properties.ToString());
return new Cameras.CameraVisca(dc.Key, dc.Name, comm, props);
}
}
public class CameraViscaPropertiesConfig : CameraPropertiesConfig
{
/// <summary>
/// Control ID of the camera (1-7)
/// </summary>
[JsonProperty("id")]
public uint Id { get; set; }
/// <summary>
/// Slow Pan speed (0-18)
/// </summary>
[JsonProperty("panSpeedSlow")]
public uint PanSpeedSlow { get; set; }
/// <summary>
/// Fast Pan speed (0-18)
/// </summary>
[JsonProperty("panSpeedFast")]
public uint PanSpeedFast { get; set; }
/// <summary>
/// Slow tilt speed (0-18)
/// </summary>
[JsonProperty("tiltSpeedSlow")]
public uint TiltSpeedSlow { get; set; }
/// <summary>
/// Fast tilt speed (0-18)
/// </summary>
[JsonProperty("tiltSpeedFast")]
public uint TiltSpeedFast { get; set; }
/// <summary>
/// Time a button must be held before fast speed is engaged (Milliseconds)
/// </summary>
[JsonProperty("fastSpeedHoldTimeMs")]
public uint FastSpeedHoldTimeMs { get; set; }
}
}

View File

@@ -11,9 +11,11 @@ namespace PepperDash.Essentials.Devices.Common.Codec
public interface IHasExternalSourceSwitching
{
bool ExternalSourceListEnabled { get; }
string ExternalSourceInputPort { get; }
void AddExternalSource(string connectorId, string key, string name, eExternalSourceType type);
void SetExternalSourceState(string key, eExternalSourceMode mode);
void ClearExternalSources();
void SetSelectedSource(string key);
Action<string, string> RunRouteAction { set;}
}

View File

@@ -6,390 +6,398 @@ using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using System.Text.RegularExpressions;
namespace PepperDash.Essentials.Devices.Common.DSP
{
// QUESTIONS:
//
// When subscribing, just use the Instance ID for Custom Name?
// Verbose on subscriptions?
// Example subscription feedback responses
// ! "publishToken":"name" "value":-77.0
// ! "myLevelName" -77
public class BiampTesiraForteDsp : DspBase
{
public IBasicCommunication Communication { get; private set; }
public CommunicationGather PortGather { get; private set; }
public StatusMonitorBase CommunicationMonitor { get; private set; }
new public Dictionary<string, TesiraForteLevelControl> LevelControlPoints { get; private set; }
public bool isSubscribed;
private CTimer SubscriptionTimer;
CrestronQueue CommandQueue;
bool CommandQueueInProgress = false;
//new public Dictionary<string, DspControlPoint> DialerControlPoints { get; private set; }
//new public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
/// <summary>
/// Shows received lines as hex
/// </summary>
public bool ShowHexResponse { get; set; }
public BiampTesiraForteDsp(string key, string name, IBasicCommunication comm, BiampTesiraFortePropertiesConfig props) :
base(key, name)
{
CommandQueue = new CrestronQueue(100);
Communication = comm;
var socket = comm as ISocketStatus;
if (socket != null)
{
// This instance uses IP control
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
}
else
{
// This instance uses RS-232 control
}
PortGather = new CommunicationGather(Communication, "\x0d\x0a");
PortGather.LineReceived += this.Port_LineReceived;
if (props.CommunicationMonitorProperties != null)
{
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties);
}
else
{
//#warning Need to deal with this poll string
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 120000, 120000, 300000, "SESSION get aliases\x0d\x0a");
}
LevelControlPoints = new Dictionary<string, TesiraForteLevelControl>();
foreach (KeyValuePair<string, BiampTesiraForteLevelControlBlockConfig> block in props.LevelControlBlocks)
{
this.LevelControlPoints.Add(block.Key, new TesiraForteLevelControl(block.Key, block.Value, this));
}
}
public override bool CustomActivate()
{
Communication.Connect();
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
CommunicationMonitor.Start();
CrestronConsole.AddNewConsoleCommand(SendLine, "send" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
return true;
}
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
{
Debug.Console(2, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
if (e.Client.IsConnected)
{
// Tasks on connect
}
else
{
// Cleanup items from this session
if (SubscriptionTimer != null)
{
SubscriptionTimer.Stop();
SubscriptionTimer = null;
}
isSubscribed = false;
CommandQueue.Clear();
CommandQueueInProgress = false;
}
}
/// <summary>
/// Initiates the subscription process to the DSP
/// </summary>
void SubscribeToAttributes()
{
SendLine("SESSION set verbose true");
foreach (KeyValuePair<string, TesiraForteLevelControl> level in LevelControlPoints)
{
level.Value.Subscribe();
}
if (!CommandQueueInProgress)
SendNextQueuedCommand();
ResetSubscriptionTimer();
}
/// <summary>
/// Resets or Sets the subscription timer
/// </summary>
void ResetSubscriptionTimer()
{
isSubscribed = true;
if (SubscriptionTimer != null)
{
SubscriptionTimer = new CTimer(o => SubscribeToAttributes(), 30000);
SubscriptionTimer.Reset();
}
}
/// <summary>
/// Handles a response message from the DSP
/// </summary>
/// <param name="dev"></param>
/// <param name="args"></param>
void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
{
if (Debug.Level == 2)
Debug.Console(2, this, "RX: '{0}'",
ShowHexResponse ? ComTextHelper.GetEscapedText(args.Text) : args.Text);
Debug.Console(1, this, "RX: '{0}'", args.Text);
try
{
if (args.Text.IndexOf("Welcome to the Tesira Text Protocol Server...") > -1)
{
// Indicates a new TTP session
SubscribeToAttributes();
}
else if (args.Text.IndexOf("publishToken") > -1)
{
// response is from a subscribed attribute
string pattern = "! \"publishToken\":[\"](.*)[\"] \"value\":(.*)";
Match match = Regex.Match(args.Text, pattern);
if (match.Success)
{
string key;
string customName;
string value;
customName = match.Groups[1].Value;
// Finds the key (everything before the '~' character
key = customName.Substring(0, customName.IndexOf("~", 0) - 1);
value = match.Groups[2].Value;
foreach (KeyValuePair<string, TesiraForteLevelControl> controlPoint in LevelControlPoints)
{
if (customName == controlPoint.Value.LevelCustomName || customName == controlPoint.Value.MuteCustomName)
{
controlPoint.Value.ParseSubscriptionMessage(customName, value);
return;
}
}
}
/// same for dialers
/// same for switchers
}
else if (args.Text.IndexOf("+OK") > -1)
{
if (args.Text == "+OK" || args.Text.IndexOf("list\":") > -1 ) // Check for a simple "+OK" only 'ack' repsonse or a list response and ignore
return;
// response is not from a subscribed attribute. From a get/set/toggle/increment/decrement command
if (!CommandQueue.IsEmpty)
{
if (CommandQueue.Peek() is QueuedCommand)
{
// Expected response belongs to a child class
QueuedCommand tempCommand = (QueuedCommand)CommandQueue.TryToDequeue();
//Debug.Console(1, this, "Command Dequeued. CommandQueue Size: {0}", CommandQueue.Count);
tempCommand.ControlPoint.ParseGetMessage(tempCommand.AttributeCode, args.Text);
}
else
{
// Expected response belongs to this class
string temp = (string)CommandQueue.TryToDequeue();
//Debug.Console(1, this, "Command Dequeued. CommandQueue Size: {0}", CommandQueue.Count);
}
if (CommandQueue.IsEmpty)
CommandQueueInProgress = false;
else
SendNextQueuedCommand();
}
}
else if (args.Text.IndexOf("-ERR") > -1)
{
// Error response
switch (args.Text)
{
case "-ERR ALREADY_SUBSCRIBED":
{
ResetSubscriptionTimer();
break;
}
default:
{
Debug.Console(0, this, "Error From DSP: '{0}'", args.Text);
break;
}
}
}
}
catch (Exception e)
{
if (Debug.Level == 2)
Debug.Console(2, this, "Error parsing response: '{0}'\n{1}", args.Text, e);
}
}
/// <summary>
/// Sends a command to the DSP (with delimiter appended)
/// </summary>
/// <param name="s">Command to send</param>
public void SendLine(string s)
{
Debug.Console(1, this, "TX: '{0}'", s);
Communication.SendText(s + "\x0a");
}
/// <summary>
/// Adds a command from a child module to the queue
/// </summary>
/// <param name="command">Command object from child module</param>
public void EnqueueCommand(QueuedCommand commandToEnqueue)
{
CommandQueue.Enqueue(commandToEnqueue);
//Debug.Console(1, this, "Command (QueuedCommand) Enqueued '{0}'. CommandQueue has '{1}' Elements.", commandToEnqueue.Command, CommandQueue.Count);
if(!CommandQueueInProgress)
SendNextQueuedCommand();
}
/// <summary>
/// Adds a raw string command to the queue
/// </summary>
/// <param name="command"></param>
public void EnqueueCommand(string command)
{
CommandQueue.Enqueue(command);
//Debug.Console(1, this, "Command (string) Enqueued '{0}'. CommandQueue has '{1}' Elements.", command, CommandQueue.Count);
if (!CommandQueueInProgress)
SendNextQueuedCommand();
}
/// <summary>
/// Sends the next queued command to the DSP
/// </summary>
void SendNextQueuedCommand()
{
//Debug.Console(2, this, "Attempting to send next queued command. CommandQueueInProgress: {0} Communication isConnected: {1}", CommandQueueInProgress, Communication.IsConnected);
//if (CommandQueue.IsEmpty)
// CommandQueueInProgress = false;
//Debug.Console(1, this, "CommandQueue has {0} Elements:\n", CommandQueue.Count);
//foreach (object o in CommandQueue)
//{
// if (o is string)
// Debug.Console(1, this, "{0}", o);
// else if(o is QueuedCommand)
// {
// var item = (QueuedCommand)o;
// Debug.Console(1, this, "{0}", item.Command);
// }
//}
//Debug.Console(1, this, "End of CommandQueue");
if (Communication.IsConnected && !CommandQueue.IsEmpty)
{
CommandQueueInProgress = true;
if (CommandQueue.Peek() is QueuedCommand)
{
QueuedCommand nextCommand = new QueuedCommand();
nextCommand = (QueuedCommand)CommandQueue.Peek();
SendLine(nextCommand.Command);
}
else
{
string nextCommand = (string)CommandQueue.Peek();
SendLine(nextCommand);
}
}
}
/// <summary>
/// Sends a command to execute a preset
/// </summary>
/// <param name="name">Preset Name</param>
public override void RunPreset(string name)
{
SendLine(string.Format("DEVICE recallPreset {0}", name));
}
public class QueuedCommand
{
public string Command { get; set; }
public string AttributeCode { get; set; }
public TesiraForteControlPoint ControlPoint { get; set; }
}
}
public class BiampTesiraForteDspFactory : EssentialsDeviceFactory<BiampTesiraForteDsp>
{
public BiampTesiraForteDspFactory()
{
TypeNames = new List<string>() { "biamptesira" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new BiampTesira Device");
var comm = CommFactory.CreateCommForDevice(dc);
var props = Newtonsoft.Json.JsonConvert.DeserializeObject<BiampTesiraFortePropertiesConfig>(
dc.Properties.ToString());
return new BiampTesiraForteDsp(dc.Key, dc.Name, comm, props);
}
}
}
using System.Text.RegularExpressions;
namespace PepperDash.Essentials.Devices.Common.DSP
{
// QUESTIONS:
//
// When subscribing, just use the Instance ID for Custom Name?
// Verbose on subscriptions?
// Example subscription feedback responses
// ! "publishToken":"name" "value":-77.0
// ! "myLevelName" -77
public class BiampTesiraForteDsp : DspBase
{
public IBasicCommunication Communication { get; private set; }
public CommunicationGather PortGather { get; private set; }
public StatusMonitorBase CommunicationMonitor { get; private set; }
public new Dictionary<string, TesiraForteLevelControl> LevelControlPoints { get; private set; }
public bool isSubscribed;
private CTimer SubscriptionTimer;
private CrestronQueue CommandQueue;
private bool CommandQueueInProgress = false;
//new public Dictionary<string, DspControlPoint> DialerControlPoints { get; private set; }
//new public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
/// <summary>
/// Shows received lines as hex
/// </summary>
public bool ShowHexResponse { get; set; }
public BiampTesiraForteDsp(string key, string name, IBasicCommunication comm,
BiampTesiraFortePropertiesConfig props) :
base(key, name)
{
CommandQueue = new CrestronQueue(100);
Communication = comm;
var socket = comm as ISocketStatus;
if (socket != null)
{
// This instance uses IP control
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
}
else
{
// This instance uses RS-232 control
}
PortGather = new CommunicationGather(Communication, "\x0d\x0a");
PortGather.LineReceived += this.Port_LineReceived;
if (props.CommunicationMonitorProperties != null)
{
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication,
props.CommunicationMonitorProperties);
}
else
{
//#warning Need to deal with this poll string
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 120000, 120000, 300000,
"SESSION get aliases\x0d\x0a");
}
LevelControlPoints = new Dictionary<string, TesiraForteLevelControl>();
foreach (KeyValuePair<string, BiampTesiraForteLevelControlBlockConfig> block in props.LevelControlBlocks)
{
this.LevelControlPoints.Add(block.Key, new TesiraForteLevelControl(block.Key, block.Value, this));
}
}
public override bool CustomActivate()
{
Communication.Connect();
CommunicationMonitor.StatusChange +=
(o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
CommunicationMonitor.Start();
CrestronConsole.AddNewConsoleCommand(SendLine, "send" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "",
ConsoleAccessLevelEnum.AccessOperator);
return true;
}
private void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
{
Debug.Console(2, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
if (e.Client.IsConnected)
{
// Tasks on connect
}
else
{
// Cleanup items from this session
if (SubscriptionTimer != null)
{
SubscriptionTimer.Stop();
SubscriptionTimer = null;
}
isSubscribed = false;
CommandQueue.Clear();
CommandQueueInProgress = false;
}
}
/// <summary>
/// Initiates the subscription process to the DSP
/// </summary>
private void SubscribeToAttributes()
{
SendLine("SESSION set verbose true");
foreach (KeyValuePair<string, TesiraForteLevelControl> level in LevelControlPoints)
{
level.Value.Subscribe();
}
if (!CommandQueueInProgress)
SendNextQueuedCommand();
ResetSubscriptionTimer();
}
/// <summary>
/// Resets or Sets the subscription timer
/// </summary>
private void ResetSubscriptionTimer()
{
isSubscribed = true;
if (SubscriptionTimer != null)
{
SubscriptionTimer = new CTimer(o => SubscribeToAttributes(), 30000);
SubscriptionTimer.Reset();
}
}
/// <summary>
/// Handles a response message from the DSP
/// </summary>
/// <param name="dev"></param>
/// <param name="args"></param>
private void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
{
if (Debug.Level == 2)
Debug.Console(2, this, "RX: '{0}'",
ShowHexResponse ? ComTextHelper.GetEscapedText(args.Text) : args.Text);
Debug.Console(1, this, "RX: '{0}'", args.Text);
try
{
if (args.Text.IndexOf("Welcome to the Tesira Text Protocol Server...") > -1)
{
// Indicates a new TTP session
SubscribeToAttributes();
}
else if (args.Text.IndexOf("publishToken") > -1)
{
// response is from a subscribed attribute
string pattern = "! \"publishToken\":[\"](.*)[\"] \"value\":(.*)";
Match match = Regex.Match(args.Text, pattern);
if (match.Success)
{
string key;
string customName;
string value;
customName = match.Groups[1].Value;
// Finds the key (everything before the '~' character
key = customName.Substring(0, customName.IndexOf("~", 0) - 1);
value = match.Groups[2].Value;
foreach (KeyValuePair<string, TesiraForteLevelControl> controlPoint in LevelControlPoints)
{
if (customName == controlPoint.Value.LevelCustomName ||
customName == controlPoint.Value.MuteCustomName)
{
controlPoint.Value.ParseSubscriptionMessage(customName, value);
return;
}
}
}
/// same for dialers
/// same for switchers
}
else if (args.Text.IndexOf("+OK") > -1)
{
if (args.Text == "+OK" || args.Text.IndexOf("list\":") > -1)
// Check for a simple "+OK" only 'ack' repsonse or a list response and ignore
return;
// response is not from a subscribed attribute. From a get/set/toggle/increment/decrement command
if (!CommandQueue.IsEmpty)
{
if (CommandQueue.Peek() is QueuedCommand)
{
// Expected response belongs to a child class
QueuedCommand tempCommand = (QueuedCommand) CommandQueue.TryToDequeue();
//Debug.Console(1, this, "Command Dequeued. CommandQueue Size: {0}", CommandQueue.Count);
tempCommand.ControlPoint.ParseGetMessage(tempCommand.AttributeCode, args.Text);
}
else
{
// Expected response belongs to this class
string temp = (string) CommandQueue.TryToDequeue();
//Debug.Console(1, this, "Command Dequeued. CommandQueue Size: {0}", CommandQueue.Count);
}
if (CommandQueue.IsEmpty)
CommandQueueInProgress = false;
else
SendNextQueuedCommand();
}
}
else if (args.Text.IndexOf("-ERR") > -1)
{
// Error response
switch (args.Text)
{
case "-ERR ALREADY_SUBSCRIBED":
{
ResetSubscriptionTimer();
break;
}
default:
{
Debug.Console(0, this, "Error From DSP: '{0}'", args.Text);
break;
}
}
}
}
catch (Exception e)
{
if (Debug.Level == 2)
Debug.Console(2, this, "Error parsing response: '{0}'\n{1}", args.Text, e);
}
}
/// <summary>
/// Sends a command to the DSP (with delimiter appended)
/// </summary>
/// <param name="s">Command to send</param>
public void SendLine(string s)
{
Debug.Console(1, this, "TX: '{0}'", s);
Communication.SendText(s + "\x0a");
}
/// <summary>
/// Adds a command from a child module to the queue
/// </summary>
/// <param name="command">Command object from child module</param>
public void EnqueueCommand(QueuedCommand commandToEnqueue)
{
CommandQueue.Enqueue(commandToEnqueue);
//Debug.Console(1, this, "Command (QueuedCommand) Enqueued '{0}'. CommandQueue has '{1}' Elements.", commandToEnqueue.Command, CommandQueue.Count);
if (!CommandQueueInProgress)
SendNextQueuedCommand();
}
/// <summary>
/// Adds a raw string command to the queue
/// </summary>
/// <param name="command"></param>
public void EnqueueCommand(string command)
{
CommandQueue.Enqueue(command);
//Debug.Console(1, this, "Command (string) Enqueued '{0}'. CommandQueue has '{1}' Elements.", command, CommandQueue.Count);
if (!CommandQueueInProgress)
SendNextQueuedCommand();
}
/// <summary>
/// Sends the next queued command to the DSP
/// </summary>
private void SendNextQueuedCommand()
{
//Debug.Console(2, this, "Attempting to send next queued command. CommandQueueInProgress: {0} Communication isConnected: {1}", CommandQueueInProgress, Communication.IsConnected);
//if (CommandQueue.IsEmpty)
// CommandQueueInProgress = false;
//Debug.Console(1, this, "CommandQueue has {0} Elements:\n", CommandQueue.Count);
//foreach (object o in CommandQueue)
//{
// if (o is string)
// Debug.Console(1, this, "{0}", o);
// else if(o is QueuedCommand)
// {
// var item = (QueuedCommand)o;
// Debug.Console(1, this, "{0}", item.Command);
// }
//}
//Debug.Console(1, this, "End of CommandQueue");
if (Communication.IsConnected && !CommandQueue.IsEmpty)
{
CommandQueueInProgress = true;
if (CommandQueue.Peek() is QueuedCommand)
{
QueuedCommand nextCommand = new QueuedCommand();
nextCommand = (QueuedCommand) CommandQueue.Peek();
SendLine(nextCommand.Command);
}
else
{
string nextCommand = (string) CommandQueue.Peek();
SendLine(nextCommand);
}
}
}
/// <summary>
/// Sends a command to execute a preset
/// </summary>
/// <param name="name">Preset Name</param>
public void RunPreset(string name)
{
SendLine(string.Format("DEVICE recallPreset {0}", name));
}
public class QueuedCommand
{
public string Command { get; set; }
public string AttributeCode { get; set; }
public TesiraForteControlPoint ControlPoint { get; set; }
}
}
public class BiampTesiraForteDspFactory : EssentialsDeviceFactory<BiampTesiraForteDsp>
{
public BiampTesiraForteDspFactory()
{
TypeNames = new List<string>() {"biamptesira"};
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new BiampTesira Device");
var comm = CommFactory.CreateCommForDevice(dc);
var props = Newtonsoft.Json.JsonConvert.DeserializeObject<BiampTesiraFortePropertiesConfig>(
dc.Properties.ToString());
return new BiampTesiraForteDsp(dc.Key, dc.Name, comm, props);
}
}
}

View File

@@ -15,18 +15,19 @@ namespace PepperDash.Essentials.Devices.Common.DSP
public Dictionary<string, DspControlPoint> DialerControlPoints { get; private set; }
public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
public abstract void RunPreset(string name);
public DspBase(string key, string name) :
base(key, name) { }
public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
public DspBase(string key, string name) :
base(key, name)
{
}
// in audio call feedback
// VOIP
// Phone dialer
// Phone dialer
}
// Fusion

View File

@@ -10,26 +10,28 @@ using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Displays
{
public abstract class ComTcpDisplayBase : DisplayBase, IPower
[Obsolete("Please use TwoWayDisplayBase instead")]
public abstract class ComTcpDisplayBase : TwoWayDisplayBase
{
/// <summary>
/// Sets the communication method for this - swaps out event handlers and output handlers
/// </summary>
public IBasicCommunication CommunicationMethod
{
get { return _CommunicationMethod; }
set
{
if (_CommunicationMethod != null)
_CommunicationMethod.BytesReceived -= this.CommunicationMethod_BytesReceived;
// Outputs???
_CommunicationMethod = value;
if (_CommunicationMethod != null)
_CommunicationMethod.BytesReceived += this.CommunicationMethod_BytesReceived;
// Outputs?
}
}
IBasicCommunication _CommunicationMethod;
///// <summary>
///// Sets the communication method for this - swaps out event handlers and output handlers
///// </summary>
//public IBasicCommunication CommunicationMethod
//{
// get { return _CommunicationMethod; }
// set
// {
// if (_CommunicationMethod != null)
// _CommunicationMethod.BytesReceived -= this.CommunicationMethod_BytesReceived;
// // Outputs???
// _CommunicationMethod = value;
// if (_CommunicationMethod != null)
// _CommunicationMethod.BytesReceived += this.CommunicationMethod_BytesReceived;
// // Outputs?
// }
//}
//IBasicCommunication _CommunicationMethod;
public ComTcpDisplayBase(string key, string name)
: base(key, name)
@@ -38,6 +40,6 @@ namespace PepperDash.Essentials.Devices.Displays
}
protected abstract void CommunicationMethod_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs args);
//protected abstract void CommunicationMethod_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs args);
}
}

View File

@@ -11,217 +11,222 @@ using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.Devices.Displays
{
public class NecPaSeriesProjector : ComTcpDisplayBase, IBridgeAdvanced
{
public readonly IntFeedback Lamp1RemainingPercent;
int _Lamp1RemainingPercent;
public readonly IntFeedback Lamp2RemainingPercent;
int _Lamp2RemainingPercent;
protected override Func<bool> PowerIsOnFeedbackFunc
{
get { return () => _PowerIsOn; }
}
bool _PowerIsOn;
//public class NecPaSeriesProjector : TwoWayDisplayBase, IBridgeAdvanced
//{
// public readonly IntFeedback Lamp1RemainingPercent;
// int _Lamp1RemainingPercent;
// public readonly IntFeedback Lamp2RemainingPercent;
// int _Lamp2RemainingPercent;
protected override Func<bool> IsCoolingDownFeedbackFunc
{
get { return () => false; }
}
// RoutingInputPort _CurrentInputPort;
protected override Func<bool> IsWarmingUpFeedbackFunc
{
get { return () => false; }
}
// protected override Func<string> CurrentInputFeedbackFunc { get { return () => _CurrentInputPort.Key; } }
// protected override Func<bool> PowerIsOnFeedbackFunc
// {
// get { return () => _PowerIsOn; }
// }
// bool _PowerIsOn;
public override void PowerToggle()
{
throw new NotImplementedException();
}
// protected override Func<bool> IsCoolingDownFeedbackFunc
// {
// get { return () => false; }
// }
public override void ExecuteSwitch(object selector)
{
throw new NotImplementedException();
}
// protected override Func<bool> IsWarmingUpFeedbackFunc
// {
// get { return () => false; }
// }
Dictionary<string, string> InputMap;
// public override void PowerToggle()
// {
// throw new NotImplementedException();
// }
/// <summary>
/// Constructor
/// </summary>
public NecPaSeriesProjector(string key, string name)
: base(key, name)
{
Lamp1RemainingPercent = new IntFeedback("Lamp1RemainingPercent", () => _Lamp1RemainingPercent);
Lamp2RemainingPercent = new IntFeedback("Lamp2RemainingPercent", () => _Lamp2RemainingPercent);
// public override void ExecuteSwitch(object selector)
// {
// throw new NotImplementedException();
// }
InputMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "computer1", "\x02\x03\x00\x00\x02\x01\x01\x09" },
{ "computer2", "\x02\x03\x00\x00\x02\x01\x02\x0a" },
{ "computer3", "\x02\x03\x00\x00\x02\x01\x03\x0b" },
{ "hdmi", "\x02\x03\x00\x00\x02\x01\x1a\x22" },
{ "dp", "\x02\x03\x00\x00\x02\x01\x1b\x23" },
{ "video", "\x02\x03\x00\x00\x02\x01\x06\x0e" },
{ "viewer", "\x02\x03\x00\x00\x02\x01\x1f\x27" },
{ "network", "\x02\x03\x00\x00\x02\x01\x20\x28" },
};
}
// Dictionary<string, string> InputMap;
void IsConnected_OutputChange(object sender, EventArgs e)
{
// /// <summary>
// /// Constructor
// /// </summary>
// public NecPaSeriesProjector(string key, string name)
// : base(key, name)
// {
// Lamp1RemainingPercent = new IntFeedback("Lamp1RemainingPercent", () => _Lamp1RemainingPercent);
// Lamp2RemainingPercent = new IntFeedback("Lamp2RemainingPercent", () => _Lamp2RemainingPercent);
}
// InputMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
// {
// { "computer1", "\x02\x03\x00\x00\x02\x01\x01\x09" },
// { "computer2", "\x02\x03\x00\x00\x02\x01\x02\x0a" },
// { "computer3", "\x02\x03\x00\x00\x02\x01\x03\x0b" },
// { "hdmi", "\x02\x03\x00\x00\x02\x01\x1a\x22" },
// { "dp", "\x02\x03\x00\x00\x02\x01\x1b\x23" },
// { "video", "\x02\x03\x00\x00\x02\x01\x06\x0e" },
// { "viewer", "\x02\x03\x00\x00\x02\x01\x1f\x27" },
// { "network", "\x02\x03\x00\x00\x02\x01\x20\x28" },
// };
// }
public void SetEnable(bool state)
{
var tcp = CommunicationMethod as GenericTcpIpClient;
if (tcp != null)
{
tcp.Connect();
}
}
// void IsConnected_OutputChange(object sender, EventArgs e)
// {
public override void PowerOn()
{
SendText("\x02\x00\x00\x00\x00\x02");
}
// }
public override void PowerOff()
{
SendText("\x02\x01\x00\x00\x00\x03");
}
// public void SetEnable(bool state)
// {
// var tcp = CommunicationMethod as GenericTcpIpClient;
// if (tcp != null)
// {
// tcp.Connect();
// }
// }
public void PictureMuteOn()
{
SendText("\x02\x10\x00\x00\x00\x12");
}
// public override void PowerOn()
// {
// SendText("\x02\x00\x00\x00\x00\x02");
// }
public void PictureMuteOff()
{
SendText("\x02\x11\x00\x00\x00\x13");
}
// public override void PowerOff()
// {
// SendText("\x02\x01\x00\x00\x00\x03");
// }
public void GetRunningStatus()
{
SendText("\x00\x85\x00\x00\x01\x01\x87");
}
// public void PictureMuteOn()
// {
// SendText("\x02\x10\x00\x00\x00\x12");
// }
public void GetLampRemaining(int lampNum)
{
if (!_PowerIsOn) return;
// public void PictureMuteOff()
// {
// SendText("\x02\x11\x00\x00\x00\x13");
// }
var bytes = new byte[]{0x03,0x96,0x00,0x00,0x02,0x00,0x04};
if (lampNum == 2)
bytes[5] = 0x01;
SendBytes(AppendChecksum(bytes));
}
// public void GetRunningStatus()
// {
// SendText("\x00\x85\x00\x00\x01\x01\x87");
// }
public void SelectInput(string inputKey)
{
if (InputMap.ContainsKey(inputKey))
SendText(InputMap[inputKey]);
}
// public void GetLampRemaining(int lampNum)
// {
// if (!_PowerIsOn) return;
void SendText(string text)
{
if (CommunicationMethod != null)
CommunicationMethod.SendText(text);
}
// var bytes = new byte[]{0x03,0x96,0x00,0x00,0x02,0x00,0x04};
// if (lampNum == 2)
// bytes[5] = 0x01;
// SendBytes(AppendChecksum(bytes));
// }
void SendBytes(byte[] bytes)
{
if (CommunicationMethod != null)
CommunicationMethod.SendBytes(bytes);
}
// public void SelectInput(string inputKey)
// {
// if (InputMap.ContainsKey(inputKey))
// SendText(InputMap[inputKey]);
// }
byte[] AppendChecksum(byte[] bytes)
{
byte sum = unchecked((byte)bytes.Sum(x => (int)x));
var retVal = new byte[bytes.Length + 1];
bytes.CopyTo(retVal, 0);
retVal[retVal.Length - 1] = sum;
return retVal;
}
// void SendText(string text)
// {
// if (CommunicationMethod != null)
// CommunicationMethod.SendText(text);
// }
protected override void CommunicationMethod_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs args)
{
var bytes = args.Bytes;
ParseBytes(args.Bytes);
}
// void SendBytes(byte[] bytes)
// {
// if (CommunicationMethod != null)
// CommunicationMethod.SendBytes(bytes);
// }
void ParseBytes(byte[] bytes)
{
if (bytes[0] == 0x22)
{
// Power on
if (bytes[1] == 0x00)
{
_PowerIsOn = true;
PowerIsOnFeedback.FireUpdate();
}
// Power off
else if (bytes[1] == 0x01)
{
_PowerIsOn = false;
PowerIsOnFeedback.FireUpdate();
}
}
// Running Status
else if (bytes[0] == 0x20 && bytes[1] == 0x85 && bytes[4] == 0x10)
{
var operationStates = new Dictionary<int, string>
{
{ 0x00, "Standby" },
{ 0x04, "Power On" },
{ 0x05, "Cooling" },
{ 0x06, "Standby (error)" },
{ 0x0f, "Standby (power saving" },
{ 0x10, "Network Standby" },
{ 0xff, "Not supported" }
};
// byte[] AppendChecksum(byte[] bytes)
// {
// byte sum = unchecked((byte)bytes.Sum(x => (int)x));
// var retVal = new byte[bytes.Length + 1];
// bytes.CopyTo(retVal, 0);
// retVal[retVal.Length - 1] = sum;
// return retVal;
// }
var newPowerIsOn = bytes[7] == 0x01;
if (newPowerIsOn != _PowerIsOn)
{
_PowerIsOn = newPowerIsOn;
PowerIsOnFeedback.FireUpdate();
}
// protected override void CommunicationMethod_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs args)
// {
// var bytes = args.Bytes;
// ParseBytes(args.Bytes);
// }
Debug.Console(2, this, "PowerIsOn={0}\rCooling={1}\rPowering on/off={2}\rStatus={3}",
_PowerIsOn,
bytes[8] == 0x01,
bytes[9] == 0x01,
operationStates[bytes[10]]);
// void ParseBytes(byte[] bytes)
// {
// if (bytes[0] == 0x22)
// {
// // Power on
// if (bytes[1] == 0x00)
// {
// _PowerIsOn = true;
// PowerIsOnFeedback.FireUpdate();
// }
// // Power off
// else if (bytes[1] == 0x01)
// {
// _PowerIsOn = false;
// PowerIsOnFeedback.FireUpdate();
// }
// }
// // Running Status
// else if (bytes[0] == 0x20 && bytes[1] == 0x85 && bytes[4] == 0x10)
// {
// var operationStates = new Dictionary<int, string>
// {
// { 0x00, "Standby" },
// { 0x04, "Power On" },
// { 0x05, "Cooling" },
// { 0x06, "Standby (error)" },
// { 0x0f, "Standby (power saving" },
// { 0x10, "Network Standby" },
// { 0xff, "Not supported" }
// };
// var newPowerIsOn = bytes[7] == 0x01;
// if (newPowerIsOn != _PowerIsOn)
// {
// _PowerIsOn = newPowerIsOn;
// PowerIsOnFeedback.FireUpdate();
// }
// Debug.Console(2, this, "PowerIsOn={0}\rCooling={1}\rPowering on/off={2}\rStatus={3}",
// _PowerIsOn,
// bytes[8] == 0x01,
// bytes[9] == 0x01,
// operationStates[bytes[10]]);
}
// Lamp remaining
else if (bytes[0] == 0x23 && bytes[1] == 0x96 && bytes[4] == 0x06 && bytes[6] == 0x04)
{
var newValue = bytes[7];
if (bytes[5] == 0x00)
{
if (newValue != _Lamp1RemainingPercent)
{
_Lamp1RemainingPercent = newValue;
Lamp1RemainingPercent.FireUpdate();
}
}
else
{
if (newValue != _Lamp2RemainingPercent)
{
_Lamp2RemainingPercent = newValue;
Lamp2RemainingPercent.FireUpdate();
}
}
Debug.Console(0, this, "Lamp {0}, {1}% remaining", (bytes[5] + 1), bytes[7]);
}
// }
// // Lamp remaining
// else if (bytes[0] == 0x23 && bytes[1] == 0x96 && bytes[4] == 0x06 && bytes[6] == 0x04)
// {
// var newValue = bytes[7];
// if (bytes[5] == 0x00)
// {
// if (newValue != _Lamp1RemainingPercent)
// {
// _Lamp1RemainingPercent = newValue;
// Lamp1RemainingPercent.FireUpdate();
// }
// }
// else
// {
// if (newValue != _Lamp2RemainingPercent)
// {
// _Lamp2RemainingPercent = newValue;
// Lamp2RemainingPercent.FireUpdate();
// }
// }
// Debug.Console(0, this, "Lamp {0}, {1}% remaining", (bytes[5] + 1), bytes[7]);
// }
}
// }
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge);
}
}
// public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
// {
// LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge);
// }
//}
}

View File

@@ -63,7 +63,7 @@
<HintPath>..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Lighting.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="PepperDash_Core, Version=1.0.41.31808, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="PepperDash_Core, Version=1.0.42.30563, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll</HintPath>
</Reference>

View File

@@ -16,12 +16,12 @@ using PepperDash.Essentials.Core.Routing;
namespace PepperDash.Essentials.Devices.Common
{
[Description("Wrapper class for an IR Set Top Box")]
public class IRSetTopBoxBase : EssentialsBridgeableDevice, ISetTopBoxControls, IRoutingOutputs, IUsageTracking, IPower
public class IRSetTopBoxBase : EssentialsBridgeableDevice, ISetTopBoxControls, IRoutingOutputs, IUsageTracking, IHasPowerControl
{
public IrOutputPortController IrPort { get; private set; }
public uint DisplayUiType { get { return DisplayUiConstants.TypeDirecTv; } }
public ushort IrPulseTime { get; set; }
public bool HasPresets { get; set; }
public bool HasDvr { get; set; }
@@ -35,6 +35,13 @@ namespace PepperDash.Essentials.Devices.Common
: base(key, name)
{
IrPort = portCont;
IrPulseTime = 200;
if (props.IrPulseTime > 0)
{
IrPulseTime = (ushort)props.IrPulseTime;
}
DeviceManager.AddDevice(portCont);
HasPresets = props.HasPresets;
@@ -47,7 +54,7 @@ namespace PepperDash.Essentials.Devices.Common
KeypadAccessoryButton1Label = "-";
HasKeypadAccessoryButton2 = true;
KeypadAccessoryButton2Command = "NumericEnter";
KeypadAccessoryButton2Command = "KEYPAD_ENTER";
KeypadAccessoryButton2Label = "Enter";
AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
@@ -55,7 +62,6 @@ namespace PepperDash.Essentials.Devices.Common
AnyAudioOut = new RoutingOutputPort(RoutingPortNames.AnyAudioOut, eRoutingSignalType.Audio,
eRoutingPortConnectionType.DigitalAudio, null, this);
OutputPorts = new RoutingPortCollection<RoutingOutputPort> { AnyVideoOut, AnyAudioOut };
}
public void LoadPresets(string filePath)
@@ -348,26 +354,17 @@ namespace PepperDash.Essentials.Devices.Common
public void PowerOn()
{
IrPort.PressRelease(IROutputStandardCommands.IROut_POWER_ON, true);
IrPort.PressRelease(IROutputStandardCommands.IROut_POWER_ON, false);
IrPort.Pulse(IROutputStandardCommands.IROut_POWER_ON, IrPulseTime);
}
public void PowerOff()
{
IrPort.PressRelease(IROutputStandardCommands.IROut_POWER_OFF, true);
IrPort.PressRelease(IROutputStandardCommands.IROut_POWER_OFF, false);
IrPort.Pulse(IROutputStandardCommands.IROut_POWER_OFF, IrPulseTime);
}
public void PowerToggle()
{
throw new NotImplementedException();
}
public BoolFeedback PowerIsOnFeedback
{
get { throw new NotImplementedException(); }
IrPort.Pulse(IROutputStandardCommands.IROut_POWER, IrPulseTime);
}
#endregion
@@ -395,79 +392,96 @@ namespace PepperDash.Essentials.Devices.Common
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = Name;
var stbBase = this as ISetTopBoxControls;
if (stbBase != null)
{
trilist.BooleanInput[joinMap.HasDpad.JoinNumber].BoolValue = stbBase.HasDpad;
trilist.BooleanInput[joinMap.HasNumeric.JoinNumber].BoolValue = stbBase.HasNumeric;
trilist.BooleanInput[joinMap.HasDvr.JoinNumber].BoolValue = stbBase.HasDvr;
trilist.BooleanInput[joinMap.HasPresets.JoinNumber].BoolValue = stbBase.HasPresets;
trilist.BooleanInput[joinMap.HasDpad.JoinNumber].BoolValue = stbBase.HasDpad;
trilist.BooleanInput[joinMap.HasNumeric.JoinNumber].BoolValue = stbBase.HasNumeric;
trilist.BooleanInput[joinMap.HasDvr.JoinNumber].BoolValue = stbBase.HasDvr;
trilist.BooleanInput[joinMap.HasPresets.JoinNumber].BoolValue = stbBase.HasPresets;
trilist.SetBoolSigAction(joinMap.DvrList.JoinNumber, stbBase.DvrList);
trilist.SetBoolSigAction(joinMap.Replay.JoinNumber, stbBase.Replay);
trilist.SetBoolSigAction(joinMap.DvrList.JoinNumber, stbBase.DvrList);
trilist.SetBoolSigAction(joinMap.Replay.JoinNumber, stbBase.Replay);
trilist.SetStringSigAction(joinMap.LoadPresets.JoinNumber, stbBase.LoadPresets);
}
trilist.SetStringSigAction(joinMap.LoadPresets.JoinNumber, stbBase.LoadPresets);
var stbPower = this as IPower;
trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, stbPower.PowerOn);
trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, stbPower.PowerOff);
trilist.SetSigTrueAction(joinMap.PowerToggle.JoinNumber, stbPower.PowerToggle);
var stbPower = this as IHasPowerControl;
if (stbPower != null)
{
trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, stbPower.PowerOn);
trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, stbPower.PowerOff);
trilist.SetSigTrueAction(joinMap.PowerToggle.JoinNumber, stbPower.PowerToggle);
}
var stbDPad = this as IDPad;
trilist.SetBoolSigAction(joinMap.Up.JoinNumber, stbDPad.Up);
trilist.SetBoolSigAction(joinMap.Down.JoinNumber, stbDPad.Down);
trilist.SetBoolSigAction(joinMap.Left.JoinNumber, stbDPad.Left);
trilist.SetBoolSigAction(joinMap.Right.JoinNumber, stbDPad.Right);
trilist.SetBoolSigAction(joinMap.Select.JoinNumber, stbDPad.Select);
trilist.SetBoolSigAction(joinMap.Menu.JoinNumber, stbDPad.Menu);
trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbDPad.Exit);
if (stbDPad != null)
{
trilist.SetBoolSigAction(joinMap.Up.JoinNumber, stbDPad.Up);
trilist.SetBoolSigAction(joinMap.Down.JoinNumber, stbDPad.Down);
trilist.SetBoolSigAction(joinMap.Left.JoinNumber, stbDPad.Left);
trilist.SetBoolSigAction(joinMap.Right.JoinNumber, stbDPad.Right);
trilist.SetBoolSigAction(joinMap.Select.JoinNumber, stbDPad.Select);
trilist.SetBoolSigAction(joinMap.Menu.JoinNumber, stbDPad.Menu);
trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbDPad.Exit);
}
var stbChannel = this as IChannel;
trilist.SetBoolSigAction(joinMap.ChannelUp.JoinNumber, stbChannel.ChannelUp);
trilist.SetBoolSigAction(joinMap.ChannelDown.JoinNumber, stbChannel.ChannelDown);
trilist.SetBoolSigAction(joinMap.LastChannel.JoinNumber, stbChannel.LastChannel);
trilist.SetBoolSigAction(joinMap.Guide.JoinNumber, stbChannel.Guide);
trilist.SetBoolSigAction(joinMap.Info.JoinNumber, stbChannel.Info);
trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbChannel.Exit);
if (stbChannel != null)
{
trilist.SetBoolSigAction(joinMap.ChannelUp.JoinNumber, stbChannel.ChannelUp);
trilist.SetBoolSigAction(joinMap.ChannelDown.JoinNumber, stbChannel.ChannelDown);
trilist.SetBoolSigAction(joinMap.LastChannel.JoinNumber, stbChannel.LastChannel);
trilist.SetBoolSigAction(joinMap.Guide.JoinNumber, stbChannel.Guide);
trilist.SetBoolSigAction(joinMap.Info.JoinNumber, stbChannel.Info);
trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbChannel.Exit);
}
var stbColor = this as IColor;
trilist.SetBoolSigAction(joinMap.Red.JoinNumber, stbColor.Red);
trilist.SetBoolSigAction(joinMap.Green.JoinNumber, stbColor.Green);
trilist.SetBoolSigAction(joinMap.Yellow.JoinNumber, stbColor.Yellow);
trilist.SetBoolSigAction(joinMap.Blue.JoinNumber, stbColor.Blue);
if (stbColor != null)
{
trilist.SetBoolSigAction(joinMap.Red.JoinNumber, stbColor.Red);
trilist.SetBoolSigAction(joinMap.Green.JoinNumber, stbColor.Green);
trilist.SetBoolSigAction(joinMap.Yellow.JoinNumber, stbColor.Yellow);
trilist.SetBoolSigAction(joinMap.Blue.JoinNumber, stbColor.Blue);
}
var stbKeypad = this as ISetTopBoxNumericKeypad;
if (stbKeypad != null)
{
trilist.StringInput[joinMap.KeypadAccessoryButton1Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton1Label;
trilist.StringInput[joinMap.KeypadAccessoryButton2Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton2Label;
trilist.StringInput[joinMap.KeypadAccessoryButton1Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton1Label;
trilist.StringInput[joinMap.KeypadAccessoryButton2Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton2Label;
trilist.BooleanInput[joinMap.HasKeypadAccessoryButton1.JoinNumber].BoolValue = stbKeypad.HasKeypadAccessoryButton1;
trilist.BooleanInput[joinMap.HasKeypadAccessoryButton2.JoinNumber].BoolValue = stbKeypad.HasKeypadAccessoryButton2;
trilist.BooleanInput[joinMap.HasKeypadAccessoryButton1.JoinNumber].BoolValue = stbKeypad.HasKeypadAccessoryButton1;
trilist.BooleanInput[joinMap.HasKeypadAccessoryButton2.JoinNumber].BoolValue = stbKeypad.HasKeypadAccessoryButton2;
trilist.SetBoolSigAction(joinMap.Digit0.JoinNumber, stbKeypad.Digit0);
trilist.SetBoolSigAction(joinMap.Digit1.JoinNumber, stbKeypad.Digit1);
trilist.SetBoolSigAction(joinMap.Digit2.JoinNumber, stbKeypad.Digit2);
trilist.SetBoolSigAction(joinMap.Digit3.JoinNumber, stbKeypad.Digit3);
trilist.SetBoolSigAction(joinMap.Digit4.JoinNumber, stbKeypad.Digit4);
trilist.SetBoolSigAction(joinMap.Digit5.JoinNumber, stbKeypad.Digit5);
trilist.SetBoolSigAction(joinMap.Digit6.JoinNumber, stbKeypad.Digit6);
trilist.SetBoolSigAction(joinMap.Digit7.JoinNumber, stbKeypad.Digit7);
trilist.SetBoolSigAction(joinMap.Digit8.JoinNumber, stbKeypad.Digit8);
trilist.SetBoolSigAction(joinMap.Digit9.JoinNumber, stbKeypad.Digit9);
trilist.SetBoolSigAction(joinMap.KeypadAccessoryButton1Press.JoinNumber, stbKeypad.KeypadAccessoryButton1);
trilist.SetBoolSigAction(joinMap.KeypadAccessoryButton2Press.JoinNumber, stbKeypad.KeypadAccessoryButton1);
trilist.SetBoolSigAction(joinMap.Dash.JoinNumber, stbKeypad.Dash);
trilist.SetBoolSigAction(joinMap.KeypadEnter.JoinNumber, stbKeypad.KeypadEnter);
trilist.SetBoolSigAction(joinMap.Digit0.JoinNumber, stbKeypad.Digit0);
trilist.SetBoolSigAction(joinMap.Digit1.JoinNumber, stbKeypad.Digit1);
trilist.SetBoolSigAction(joinMap.Digit2.JoinNumber, stbKeypad.Digit2);
trilist.SetBoolSigAction(joinMap.Digit3.JoinNumber, stbKeypad.Digit3);
trilist.SetBoolSigAction(joinMap.Digit4.JoinNumber, stbKeypad.Digit4);
trilist.SetBoolSigAction(joinMap.Digit5.JoinNumber, stbKeypad.Digit5);
trilist.SetBoolSigAction(joinMap.Digit6.JoinNumber, stbKeypad.Digit6);
trilist.SetBoolSigAction(joinMap.Digit7.JoinNumber, stbKeypad.Digit7);
trilist.SetBoolSigAction(joinMap.Digit8.JoinNumber, stbKeypad.Digit8);
trilist.SetBoolSigAction(joinMap.Digit9.JoinNumber, stbKeypad.Digit9);
trilist.SetBoolSigAction(joinMap.KeypadAccessoryButton1Press.JoinNumber, stbKeypad.KeypadAccessoryButton1);
trilist.SetBoolSigAction(joinMap.KeypadAccessoryButton2Press.JoinNumber, stbKeypad.KeypadAccessoryButton1);
trilist.SetBoolSigAction(joinMap.Dash.JoinNumber, stbKeypad.Dash);
trilist.SetBoolSigAction(joinMap.KeypadEnter.JoinNumber, stbKeypad.KeypadEnter);
}
var stbTransport = this as ITransport;
trilist.SetBoolSigAction(joinMap.Play.JoinNumber, stbTransport.Play);
trilist.SetBoolSigAction(joinMap.Pause.JoinNumber, stbTransport.Pause);
trilist.SetBoolSigAction(joinMap.Rewind.JoinNumber, stbTransport.Rewind);
trilist.SetBoolSigAction(joinMap.FFwd.JoinNumber, stbTransport.FFwd);
trilist.SetBoolSigAction(joinMap.ChapMinus.JoinNumber, stbTransport.ChapMinus);
trilist.SetBoolSigAction(joinMap.ChapPlus.JoinNumber, stbTransport.ChapPlus);
trilist.SetBoolSigAction(joinMap.Stop.JoinNumber, stbTransport.Stop);
trilist.SetBoolSigAction(joinMap.Record.JoinNumber, stbTransport.Record);
if (stbTransport != null)
{
trilist.SetBoolSigAction(joinMap.Play.JoinNumber, stbTransport.Play);
trilist.SetBoolSigAction(joinMap.Pause.JoinNumber, stbTransport.Pause);
trilist.SetBoolSigAction(joinMap.Rewind.JoinNumber, stbTransport.Rewind);
trilist.SetBoolSigAction(joinMap.FFwd.JoinNumber, stbTransport.FFwd);
trilist.SetBoolSigAction(joinMap.ChapMinus.JoinNumber, stbTransport.ChapMinus);
trilist.SetBoolSigAction(joinMap.ChapPlus.JoinNumber, stbTransport.ChapPlus);
trilist.SetBoolSigAction(joinMap.Stop.JoinNumber, stbTransport.Stop);
trilist.SetBoolSigAction(joinMap.Record.JoinNumber, stbTransport.Record);
}
}
}

View File

@@ -14,6 +14,7 @@ namespace PepperDash.Essentials.Devices.Common
public bool HasDvr { get; set; }
public bool HasDpad { get; set; }
public bool HasNumeric { get; set; }
public int IrPulseTime { get; set; }
public ControlPropertiesConfig Control { get; set; }
}

View File

@@ -106,8 +106,8 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
{
dest.ReleaseRoute();
if (dest is IPower)
(dest as IPower).PowerOff();
if (dest is IHasPowerControl)
(dest as IHasPowerControl).PowerOff();
}
else
{

View File

@@ -407,6 +407,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
CreateOsdSource();
ExternalSourceListEnabled = props.ExternalSourceListEnabled;
ExternalSourceInputPort = props.ExternalSourceInputPort;
if (props.UiBranding == null)
{
@@ -416,6 +417,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
props.UiBranding.BrandingUrl);
BrandingEnabled = props.UiBranding.Enable;
_brandingUrl = props.UiBranding.BrandingUrl;
}
@@ -514,12 +516,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
SendText("xconfiguration userinterface custommessage: \"Scan the QR code with a mobile phone to get started\"");
SendText("xconfiguration userinterface osd halfwakemessage: \"Tap the touch panel or scan the QR code with a mobile phone to get started\"");
var checksum = !String.IsNullOrEmpty(mcBridge.QrCodeChecksum)
? String.Format("checksum: {0} ", mcBridge.QrCodeChecksum)
: String.Empty;
SendText(String.Format(
"xcommand userinterface branding fetch type: branding url: {0}",
mcBridge.QrCodeUrl));
"xcommand userinterface branding fetch {1}type: branding url: {0}",
mcBridge.QrCodeUrl, checksum));
SendText(String.Format(
"xcommand userinterface branding fetch type: halfwakebranding url: {0}",
mcBridge.QrCodeUrl));
"xcommand userinterface branding fetch {1}type: halfwakebranding url: {0}",
mcBridge.QrCodeUrl, checksum));
}
private void SendBrandingUrl()
@@ -1339,10 +1345,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public override void SendDtmf(string s)
{
if (CallFavorites != null)
{
SendText(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", GetCallId(), s));
}
SendText(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", GetCallId(), s));
}
public void SelectPresentationSource(int source)
@@ -1920,7 +1923,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
#region IHasExternalSourceSwitching Members
/// <summary>
/// Weather the Cisco supports External Source Lists or not
/// Wheather the Cisco supports External Source Lists or not
/// </summary>
public bool ExternalSourceListEnabled
{
@@ -1928,6 +1931,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
private set;
}
/// <summary>
/// The name of the RoutingInputPort to which the upstream external switcher is connected
/// </summary>
public string ExternalSourceInputPort { get; private set; }
public bool BrandingEnabled { get; private set; }
private string _brandingUrl;
private bool _sendMcUrl;
@@ -1970,6 +1978,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
}
/// <summary>
/// Sets the selected source of the available external sources on teh Touch10 UI
/// </summary>
public void SetSelectedSource(string key)
{
SendText(string.Format("xCommand UserInterface Presentation ExternalSource Select SourceIdentifier: {0}", key));
}
/// <summary>
/// Action that will run when the External Source is selected.
/// </summary>
@@ -2097,7 +2113,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
public CiscoSparkCodecFactory()
{
TypeNames = new List<string>() { "ciscospark", "ciscowebex", "ciscowebexpro", "ciscoroomkit" };
TypeNames = new List<string>() { "ciscospark", "ciscowebex", "ciscowebexpro", "ciscoroomkit", "ciscosparkpluscodec" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)

View File

@@ -31,9 +31,18 @@ namespace PepperDash.Essentials.Devices.Common.Codec
[JsonProperty("sharing")]
public SharingProperties Sharing { get; set; }
/// <summary>
/// Enables external source switching capability
/// </summary>
[JsonProperty("externalSourceListEnabled")]
public bool ExternalSourceListEnabled { get; set; }
/// <summary>
/// The name of the routing input port on the codec to which the external switch is connected
/// </summary>
[JsonProperty("externalSourceInputPort")]
public string ExternalSourceInputPort { get; set; }
/// <summary>
/// Optionsal property to set the limit of any phonebook queries for directory or searching
/// </summary>

View File

@@ -1,131 +1,131 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
/// <summary>
/// This class exists to capture serialized data sent back by a Cisco codec in JSON output mode
/// </summary>
public class CiscoCodecEvents
{
public class CauseValue
{
public string id { get; set; }
public string Value { get; set; }
}
public class CauseType
{
public string id { get; set; }
public string Value { get; set; }
}
public class CauseString
{
public string id { get; set; }
public string Value { get; set; }
}
public class OrigCallDirection
{
public string id { get; set; }
public string Value { get; set; }
}
public class RemoteURI
{
public string id { get; set; }
public string Value { get; set; }
}
public class DisplayName
{
public string id { get; set; }
public string Value { get; set; }
}
public class CallId
{
public string id { get; set; }
public string Value { get; set; }
}
public class CauseCode
{
public string id { get; set; }
public string Value { get; set; }
}
public class CauseOrigin
{
public string id { get; set; }
public string Value { get; set; }
}
public class Protocol
{
public string id { get; set; }
public string Value { get; set; }
}
public class Duration
{
public string id { get; set; }
public string Value { get; set; }
}
public class CallType
{
public string id { get; set; }
public string Value { get; set; }
}
public class CallRate
{
public string id { get; set; }
public string Value { get; set; }
}
public class Encryption
{
public string id { get; set; }
public string Value { get; set; }
}
public class RequestedURI
{
public string id { get; set; }
public string Value { get; set; }
}
public class PeopleCountAverage
{
public string id { get; set; }
public string Value { get; set; }
}
public class CallDisconnect
{
public string id { get; set; }
public CauseValue CauseValue { get; set; }
public CauseType CauseType { get; set; }
public CauseString CauseString { get; set; }
public OrigCallDirection OrigCallDirection { get; set; }
public RemoteURI RemoteURI { get; set; }
public DisplayName DisplayName { get; set; }
public CallId CallId { get; set; }
public CauseCode CauseCode { get; set; }
public CauseOrigin CauseOrigin { get; set; }
public Protocol Protocol { get; set; }
public Duration Duration { get; set; }
public CallType CallType { get; set; }
public CallRate CallRate { get; set; }
public Encryption Encryption { get; set; }
public RequestedURI RequestedURI { get; set; }
public PeopleCountAverage PeopleCountAverage { get; set; }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
/// <summary>
/// This class exists to capture serialized data sent back by a Cisco codec in JSON output mode
/// </summary>
public class CiscoCodecEvents
{
public class CauseValue
{
public string id { get; set; }
public string Value { get; set; }
}
public class CauseType
{
public string id { get; set; }
public string Value { get; set; }
}
public class CauseString
{
public string id { get; set; }
public string Value { get; set; }
}
public class OrigCallDirection
{
public string id { get; set; }
public string Value { get; set; }
}
public class RemoteURI
{
public string id { get; set; }
public string Value { get; set; }
}
public class DisplayName
{
public string id { get; set; }
public string Value { get; set; }
}
public class CallId
{
public string id { get; set; }
public string Value { get; set; }
}
public class CauseCode
{
public string id { get; set; }
public string Value { get; set; }
}
public class CauseOrigin
{
public string id { get; set; }
public string Value { get; set; }
}
public class Protocol
{
public string id { get; set; }
public string Value { get; set; }
}
public class Duration
{
public string id { get; set; }
public string Value { get; set; }
}
public class CallType
{
public string id { get; set; }
public string Value { get; set; }
}
public class CallRate
{
public string id { get; set; }
public string Value { get; set; }
}
public class Encryption
{
public string id { get; set; }
public string Value { get; set; }
}
public class RequestedURI
{
public string id { get; set; }
public string Value { get; set; }
}
public class PeopleCountAverage
{
public string id { get; set; }
public string Value { get; set; }
}
public class CallDisconnect
{
public string id { get; set; }
public CauseValue CauseValue { get; set; }
public CauseType CauseType { get; set; }
public CauseString CauseString { get; set; }
public OrigCallDirection OrigCallDirection { get; set; }
public RemoteURI RemoteURI { get; set; }
public DisplayName DisplayName { get; set; }
public CallId CallId { get; set; }
public CauseCode CauseCode { get; set; }
public CauseOrigin CauseOrigin { get; set; }
public Protocol Protocol { get; set; }
public Duration Duration { get; set; }
public CallType CallType { get; set; }
public CallRate CallRate { get; set; }
public Encryption Encryption { get; set; }
public RequestedURI RequestedURI { get; set; }
public PeopleCountAverage PeopleCountAverage { get; set; }
}
public class UserInterface
{
@@ -151,16 +151,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
public string id { get; set; }
public string Value { get; set; }
}
public class Event
{
}
public class Event
{
public CallDisconnect CallDisconnect { get; set; }
public UserInterface UserInterface { get; set; }
}
public class RootObject
{
public Event Event { get; set; }
}
}
public UserInterface UserInterface { get; set; }
}
public class RootObject
{
public Event Event { get; set; }
}
}
}

View File

@@ -1368,8 +1368,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
set
{
// If the incoming value is "Of" it sets the BoolValue true, otherwise sets it false
BoolValue = value == "Off";
// If the incoming value is "On" it sets the BoolValue true, otherwise sets it false
BoolValue = value == "On";
OnValueChanged();
}
}

View File

@@ -5,6 +5,7 @@ using System.Text;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Ssh;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Core.Intersystem;
using PepperDash.Core.Intersystem.Tokens;
@@ -231,12 +232,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
/// </summary>
protected void SetIsReady()
{
IsReady = true;
var h = IsReadyChange;
if (h != null)
{
h(this, new EventArgs());
}
CrestronInvoke.BeginInvoke( (o) =>
{
try
{
IsReady = true;
var h = IsReadyChange;
if (h != null)
{
h(this, new EventArgs());
}
}
catch (Exception e)
{
Debug.Console(2, this, "Error in SetIsReady() : {0}", e);
}
});
}
// **** DEBUGGING THINGS ****

View File

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