Compare commits

..

176 Commits
1.6.6 ... 1.7.2

Author SHA1 Message Date
Andrew Welker
5d7cdab933 Merge pull request #557 from PepperDash/feature/add-fusion-joinmaps
Feature/add fusion joinmaps
2021-01-22 13:05:37 -07:00
Neil Dorin
c9fee785f9 Static Assets for displays now tested and working 2021-01-22 11:08:35 -07:00
Neil Dorin
dfc90e58dc Adds EssentialsTechRoomFusionSystemController 2021-01-21 17:19:01 -07:00
Neil Dorin
2a5810b671 Updates PD.Core to 1.0.45 2021-01-21 17:01:43 -07:00
Neil Dorin
9d354fb0ed custom fusion joinmap working. updates to hotfix PD.Core build 2021-01-21 16:46:21 -07:00
Neil Dorin
52494ca13e Changes to correct datatype for joinMaps in config 2021-01-21 15:04:01 -07:00
Neil Dorin
f6059e249f Merge branch 'main' into feature/add-fusion-joinmaps 2021-01-20 14:39:37 -07:00
Neil Dorin
cf14706961 Merge pull request #554 from PepperDash/hotfix/videocodecbase-incoming-call-popup
Upadted VideoCodecBase LinkVideoCodecCallControlsToApi
2021-01-20 14:32:34 -07:00
jkdevito
7945bce854 Upadted VideoCodecBase LinkVideoCodecCallControlsToApi IncomingCall bridge action to reference "args.CallItem.Status == eCodecCallStatus.Ringing" (previously referencing "args.CallItem.Status != eCodecCallStatus.Disconnected") 2021-01-18 15:37:39 -06:00
Andrew Welker
44cacc839b Merge pull request #538 from PepperDash/hotfix/zoomroom-obtp-dialing
Hotfix/zoomroom obtp dialing
2021-01-15 11:45:13 -07:00
Neil Dorin
dfebd47ef4 Merge branch 'main' into hotfix/zoomroom-obtp-dialing 2021-01-12 15:49:56 -07:00
Neil Dorin
3c714f724d Merge pull request #546 from PepperDash/hotfix/sys-monitor-not-updating-bridge
fixes a bug where the system monitor bridge wasn't updating
2021-01-12 15:48:43 -07:00
Neil Dorin
03e0dc5208 Merge branch 'main' into hotfix/sys-monitor-not-updating-bridge 2021-01-12 15:34:48 -07:00
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
Nick Genovese
030d69c190 fixes a bug where the system monitor bridge wasn't updating
- fires off all program start/stop/register feedbacks when they are created to set initial state
2021-01-12 09:20:15 -05: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
jkdevito
72197e547f Updated VideoCodecBase.cs and ZoomRooms.cs to resolve an issue with dialing the currently scheduled meetings.
VideoCodecBase.cs changes:
1. Moved the trilist.SetSigFalseActions for DialMeeting 1-3 from the UpdateMeetinsgList mehtod to the LinkVideoCodecScheduleToApi method.
- This was necessary to resolve an issue with dialing current meetings.
- When the SetSigFalseActions where located in the UpdateMeetingsList, they were using the codec.CodecSchedule.Meetings to dial, which was not updated based on the time of day.
2. Turned the local var currentMeetings into a private list, _currentMeetings, that can be updated by UpdateMeetingsList and then used in LinkVideoCodecScheduleToApi when the trilist actions are executed.
3. Added debug statements to help narrow down the issue and verify the data.
ZoomRoom.cs changes:
1. Added debug statement to Dial(Meeting meeting) method to confirm the data passed from LinkVideoCodecScheduleToApi was matching the _currentMeetings list data.
2021-01-06 16:22:54 -06:00
Neil Dorin
9b62849d9d removes old comment 2021-01-06 14:45:40 -07:00
Neil Dorin
d311b6fef9 Adds AttributeName property to JoinData allowing attribute name to be set from config as well 2021-01-05 18:21:32 -07:00
Neil Dorin
4a642b1e36 Adds UserObject for future use purposes 2021-01-04 16:19:08 -07:00
Neil Dorin
de4f003c67 Swapped out hardcoded joins for join map in Vtc1FusionController 2021-01-04 12:10:12 -07:00
Neil Dorin
708ee1a8ff #535 Wraps up EssentialsHuddleSpaceFusionSystemControllerBase. Starts on Vtc1FusionController 2020-12-30 17:01:55 -07:00
Neil Dorin
7196d0aba8 Adds FusionRoomJoinMap and ability to set IPID and JoinMapKey from config 2020-12-29 20:20:49 -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
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
90 changed files with 14209 additions and 10934 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
@@ -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

1
.gitignore vendored
View File

@@ -388,3 +388,4 @@ MigrationBackup/
# Fody - auto-generated XML schema
FodyWeavers.xsd
essentials-framework/Essentials Interfaces/PepperDash_Essentials_Interfaces/PepperDash_Essentials_Interfaces.csproj

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
@@ -456,19 +432,34 @@ namespace PepperDash.Essentials
var room = EssentialsRoomConfigHelper.GetRoomObject(roomConfig) as EssentialsRoomBase;
if (room != null)
{
// default IPID
uint fusionIpId = 0xf1;
// default to no join map key
string fusionJoinMapKey = string.Empty;
if (room.Config.Properties["fusion"] != null)
{
Debug.Console(2, "Custom Fusion config found. Using custom values");
var fusionConfig = room.Config.Properties["fusion"].ToObject<EssentialsRoomFusionConfig>();
if (fusionConfig != null)
{
fusionIpId = fusionConfig.IpIdInt;
fusionJoinMapKey = fusionConfig.JoinMapKey;
}
}
if (room is EssentialsHuddleSpaceRoom)
{
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, fusionIpId, fusionJoinMapKey));
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);
}
@@ -477,13 +468,21 @@ namespace PepperDash.Essentials
DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion");
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, 0xf1));
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey));
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 EssentialsTechRoomFusionSystemController((EssentialsTechRoom)room, fusionIpId, fusionJoinMapKey));
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge");
CreateMobileControlBridge(room);
}
@@ -504,34 +503,35 @@ 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
@@ -568,23 +568,31 @@ namespace PepperDash.Essentials
string logoLight = null;
string logo = null;
if (c.Properties["logoDark"] != null)
try
{
logoDark = c.Properties["logoDark"].Value<string>("type");
}
if (c.Properties["logoDark"] != null)
{
logoDark = c.Properties["logoDark"].Value<string>("type");
}
if (c.Properties["logoLight"] != null)
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
{
logoLight = c.Properties["logoLight"].Value<string>("type");
Debug.Console(1, Debug.ErrorLogLevel.Notice, "Unable to find logo information in any room config");
return false;
}
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"));
}
}
}

View File

@@ -16,8 +16,8 @@ namespace PepperDash.Essentials.Fusion
{
BooleanSigData CodecIsInCall;
public EssentialsHuddleVtc1FusionController(EssentialsHuddleVtc1Room room, uint ipId)
: base(room, ipId)
public EssentialsHuddleVtc1FusionController(EssentialsHuddleVtc1Room room, uint ipId, string joinMapKey)
: base(room, ipId, joinMapKey)
{
}
@@ -55,25 +55,25 @@ namespace PepperDash.Essentials.Fusion
// Map FusionRoom Attributes:
// Codec volume
var codecVolume = FusionRoom.CreateOffsetUshortSig(50, "Volume - Fader01", eSigIoMask.InputOutputSig);
var codecVolume = FusionRoom.CreateOffsetUshortSig(JoinMap.VolumeFader1.JoinNumber, JoinMap.VolumeFader1.AttributeName, eSigIoMask.InputOutputSig);
codecVolume.OutputSig.UserObject = new Action<ushort>(b => (codec as IBasicVolumeWithFeedback).SetVolume(b));
(codec as IBasicVolumeWithFeedback).VolumeLevelFeedback.LinkInputSig(codecVolume.InputSig);
// In Call Status
CodecIsInCall = FusionRoom.CreateOffsetBoolSig(69, "Conf - VC 1 In Call", eSigIoMask.InputSigOnly);
CodecIsInCall = FusionRoom.CreateOffsetBoolSig(JoinMap.VcCodecInCall.JoinNumber, JoinMap.VcCodecInCall.AttributeName, eSigIoMask.InputSigOnly);
codec.CallStatusChange += new EventHandler<PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
// Online status
if (codec is ICommunicationMonitor)
{
var c = codec as ICommunicationMonitor;
var codecOnline = FusionRoom.CreateOffsetBoolSig(122, "Online - VC 1", eSigIoMask.InputSigOnly);
var codecOnline = FusionRoom.CreateOffsetBoolSig(JoinMap.VcCodecOnline.JoinNumber, JoinMap.VcCodecOnline.AttributeName, eSigIoMask.InputSigOnly);
codecOnline.InputSig.BoolValue = c.CommunicationMonitor.Status == MonitorStatus.IsOk;
c.CommunicationMonitor.StatusChange += (o, a) =>
{
codecOnline.InputSig.BoolValue = a.Status == MonitorStatus.IsOk;
};
Debug.Console(0, this, "Linking '{0}' communication monitor to Fusion '{1}'", codec.Key, "Online - VC 1");
Debug.Console(0, this, "Linking '{0}' communication monitor to Fusion '{1}'", codec.Key, JoinMap.VcCodecOnline.AttributeName);
}
// Codec IP Address
@@ -101,10 +101,10 @@ namespace PepperDash.Essentials.Fusion
if (codecHasIpInfo)
{
codecIpAddressSig = FusionRoom.CreateOffsetStringSig(121, "IP Address - VC", eSigIoMask.InputSigOnly);
codecIpAddressSig = FusionRoom.CreateOffsetStringSig(JoinMap.VcCodecIpAddress.JoinNumber, JoinMap.VcCodecIpAddress.AttributeName, eSigIoMask.InputSigOnly);
codecIpAddressSig.InputSig.StringValue = codecIpAddress;
codecIpPortSig = FusionRoom.CreateOffsetStringSig(150, "IP Port - VC", eSigIoMask.InputSigOnly);
codecIpPortSig = FusionRoom.CreateOffsetStringSig(JoinMap.VcCodecIpPort.JoinNumber, JoinMap.VcCodecIpPort.AttributeName, eSigIoMask.InputSigOnly);
codecIpPortSig.InputSig.StringValue = codecIpPort.ToString();
}
@@ -123,7 +123,7 @@ namespace PepperDash.Essentials.Fusion
FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
}
var codecAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
var codecAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Codec", tempAsset.InstanceId);
codecAsset.PowerOn.OutputSig.UserObject = codecPowerOnAction;
codecAsset.PowerOff.OutputSig.UserObject = codecPowerOffAction;
codec.StandbyIsOnFeedback.LinkComplementInputSig(codecAsset.PowerOn.InputSig);
@@ -166,20 +166,19 @@ namespace PepperDash.Essentials.Fusion
CrestronConsole.AddNewConsoleCommand(RequestFullRoomSchedule, "FusReqRoomSchedule", "Requests schedule of the room for the next 24 hours", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(ModifyMeetingEndTimeConsoleHelper, "FusReqRoomSchMod", "Ends or extends a meeting by the specified time", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(CreateAsHocMeeting, "FusCreateMeeting", "Creates and Ad Hoc meeting for on hour or until the next meeting", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(CreateAdHocMeeting, "FusCreateMeeting", "Creates and Ad Hoc meeting for on hour or until the next meeting", ConsoleAccessLevelEnum.AccessOperator);
// Room to fusion room
Room.OnFeedback.LinkInputSig(FusionRoom.SystemPowerOn.InputSig);
// Moved to
CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(84, "Display 1 - Current Source", eSigIoMask.InputSigOnly);
CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(JoinMap.Display1CurrentSourceName.JoinNumber, JoinMap.Display1CurrentSourceName.AttributeName, eSigIoMask.InputSigOnly);
// Don't think we need to get current status of this as nothing should be alive yet.
(Room as EssentialsHuddleVtc1Room).CurrentSourceChange += Room_CurrentSourceInfoChange;
FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction((Room as EssentialsHuddleVtc1Room).PowerOnToDefaultOrLastSource);
FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff", Room.SourceListKey));
// NO!! room.RoomIsOn.LinkComplementInputSig(FusionRoom.SystemPowerOff.InputSig);
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
@@ -197,9 +196,9 @@ namespace PepperDash.Essentials.Fusion
uint i = 1;
foreach (var kvp in setTopBoxes)
{
TryAddRouteActionSigs("Display 1 - Source TV " + i, 188 + i, kvp.Key, kvp.Value.SourceDevice);
TryAddRouteActionSigs(JoinMap.Display1DiscPlayerSourceStart.AttributeName + " " + i, JoinMap.Display1DiscPlayerSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice);
i++;
if (i > 5) // We only have five spots
if (i > JoinMap.Display1SetTopBoxSourceStart.JoinSpan) // We only have five spots
break;
}
@@ -207,7 +206,7 @@ namespace PepperDash.Essentials.Fusion
i = 1;
foreach (var kvp in discPlayers)
{
TryAddRouteActionSigs("Display 1 - Source DVD " + i, 181 + i, kvp.Key, kvp.Value.SourceDevice);
TryAddRouteActionSigs(JoinMap.Display1DiscPlayerSourceStart.AttributeName + " " + i, JoinMap.Display1DiscPlayerSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice);
i++;
if (i > 5) // We only have five spots
break;
@@ -217,9 +216,9 @@ namespace PepperDash.Essentials.Fusion
i = 1;
foreach (var kvp in laptops)
{
TryAddRouteActionSigs("Display 1 - Source Laptop " + i, 166 + i, kvp.Key, kvp.Value.SourceDevice);
TryAddRouteActionSigs(JoinMap.Display1LaptopSourceStart.AttributeName + " " + i, JoinMap.Display1LaptopSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice);
i++;
if (i > 10) // We only have ten spots???
if (i > JoinMap.Display1LaptopSourceStart.JoinSpan) // We only have ten spots???
break;
}
@@ -273,14 +272,17 @@ 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);
MapDisplayToRoomJoins(1, JoinMap.Display1Start.JoinNumber, defaultDisplay);
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key));
@@ -302,8 +304,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);
@@ -315,7 +327,7 @@ namespace PepperDash.Essentials.Fusion
}
protected override void MapDisplayToRoomJoins(int displayIndex, int joinOffset, DisplayBase display)
protected override void MapDisplayToRoomJoins(int displayIndex, uint joinOffset, DisplayBase display)
{
string displayName = string.Format("Display {0} - ", displayIndex);
@@ -325,12 +337,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

@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Fusion;
namespace PepperDash.Essentials.Fusion
{
public class EssentialsTechRoomFusionSystemController : EssentialsHuddleSpaceFusionSystemControllerBase
{
public EssentialsTechRoomFusionSystemController(EssentialsTechRoom room, uint ipId, string joinMapKey)
: base(room, ipId, joinMapKey)
{
}
protected override void SetUpDisplay()
{
try
{
var displays = (Room as EssentialsTechRoom).Displays;
Debug.Console(1, this, "Setting up Static Assets for {0} Displays", displays.Count);
foreach (var display in displays.Values.Cast<DisplayBase>())
{
Debug.Console(2, this, "Setting up Static Asset for {0}", display.Key);
display.UsageTracker = new UsageTracking(display) { UsageIsTracked = true };
display.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
var dispPowerOnAction = new Action<bool>(b =>
{
if (!b)
{
display.PowerOn();
}
});
var dispPowerOffAction = new Action<bool>(b =>
{
if (!b)
{
display.PowerOff();
}
});
var deviceConfig = ConfigReader.ConfigObject.GetDeviceForKey(display.Key);
FusionAsset tempAsset;
if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
{
// Used existing asset
tempAsset = FusionStaticAssets[deviceConfig.Uid];
}
else
{
// Create a new asset
tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom),
display.Name, "Display", "");
FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
}
var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display",
tempAsset.InstanceId);
dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
var defaultTwoWayDisplay = display as IHasPowerControlWithFeedback;
if (defaultTwoWayDisplay != null)
{
defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
if (display is IDisplayUsage)
{
(display as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
}
defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
}
// Use extension methods
dispAsset.TrySetMakeModel(display);
dispAsset.TryLinkAssetErrorToCommunication(display);
}
}
catch (Exception e)
{
Debug.Console(1, this, "Error setting up displays in Fusion: {0}", e);
}
}
}
}

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>
@@ -133,6 +133,7 @@
<Compile Include="Devices\Amplifier.cs" />
<Compile Include="ControlSystem.cs" />
<Compile Include="Fusion\EssentialsHuddleVtc1FusionController.cs" />
<Compile Include="Fusion\EssentialsTechRoomFusionSystemController.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Room\Config\EssentialsDualDisplayRoomPropertiesConfig.cs" />
<Compile Include="Room\Config\EssentialsNDisplayRoomPropertiesConfig.cs" />
@@ -141,11 +142,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>
@@ -182,6 +177,9 @@ namespace PepperDash.Essentials.Room.Config
[JsonProperty("volumes")]
public EssentialsRoomVolumesConfig Volumes { get; set; }
[JsonProperty("fusion")]
public EssentialsRoomFusionConfig Fusion { get; set; }
[JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")]
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; }
@@ -225,6 +223,32 @@ namespace PepperDash.Essentials.Room.Config
}
public class EssentialsRoomFusionConfig
{
public uint IpIdInt
{
get
{
try
{
return Convert.ToUInt32(IpId, 16);
}
catch (Exception)
{
throw new FormatException(string.Format("ERROR:Unable to convert IP ID: {0} to hex. Error:\n{1}", IpId));
}
}
}
[JsonProperty("ipId")]
public string IpId { get; set; }
[JsonProperty("joinMapKey")]
public string JoinMapKey { get; set; }
}
public class EssentialsRoomMicrophonePrivacyConfig
{
[JsonProperty("deviceKey")]

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

@@ -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

@@ -47,7 +47,7 @@ namespace PepperDash.Essentials.Core.Bridges
/// <param name="joinStart">Join this join map will start at</param>
/// <param name="type">Type of the child join map</param>
public AppleTvJoinMap(uint joinStart, Type type) : base(joinStart, type)
{
}
{
}
}
}

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

@@ -7,6 +7,8 @@ using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using Newtonsoft.Json.Linq;
namespace PepperDash.Essentials.Core.Config
{
/// <summary>
@@ -27,7 +29,7 @@ namespace PepperDash.Essentials.Core.Config
public List<TieLineConfig> TieLines { get; set; }
[JsonProperty("joinMaps")]
public Dictionary<string, string> JoinMaps { get; set; }
public Dictionary<string, JObject> JoinMaps { get; set; }
/// <summary>
/// Checks SourceLists for a given list and returns it if found. Otherwise, returns null

View File

@@ -1,195 +1,195 @@
using System;
using System;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Core.Config;
namespace PepperDash.Essentials.Core.Config
{
/// <summary>
/// Loads the ConfigObject from the file
/// </summary>
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Core.Config;
namespace PepperDash.Essentials.Core.Config
{
/// <summary>
/// Loads the ConfigObject from the file
/// </summary>
public class ConfigReader
{
public const string LocalConfigPresent =
@"
***************************************************
************* Using Local config file *************
***************************************************";
public static EssentialsConfig ConfigObject { get; private set; }
public static bool LoadConfig2()
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading unmerged system/template portal configuration file.");
try
{
// Check for local config file first
var filePath = Global.FilePathPrefix + ConfigWriter.LocalConfigFolder + Global.DirectorySeparator + Global.ConfigFileName;
bool localConfigFound = false;
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to load Local config file: '{0}'", filePath);
// Check for local config directory first
var configFiles = GetConfigFiles(filePath);
if (configFiles != null)
{
if (configFiles.Length > 1)
{
Debug.Console(0, Debug.ErrorLogLevel.Error,
"****Error: Multiple Local Configuration files present. Please ensure only a single file exists and reset program.****");
return false;
}
if(configFiles.Length == 1)
{
***************************************************";
public static EssentialsConfig ConfigObject { get; private set; }
public static bool LoadConfig2()
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading unmerged system/template portal configuration file.");
try
{
// Check for local config file first
var filePath = Global.FilePathPrefix + ConfigWriter.LocalConfigFolder + Global.DirectorySeparator + Global.ConfigFileName;
bool localConfigFound = false;
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to load Local config file: '{0}'", filePath);
// Check for local config directory first
var configFiles = GetConfigFiles(filePath);
if (configFiles != null)
{
if (configFiles.Length > 1)
{
Debug.Console(0, Debug.ErrorLogLevel.Error,
"****Error: Multiple Local Configuration files present. Please ensure only a single file exists and reset program.****");
return false;
}
if(configFiles.Length == 1)
{
localConfigFound = true;
}
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice,
"Local Configuration file not present.", filePath);
}
// Check for Portal Config
if(!localConfigFound)
{
filePath = Global.FilePathPrefix + Global.ConfigFileName;
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to load Portal config file: '{0}'", filePath);
configFiles = GetConfigFiles(filePath);
if (configFiles != null)
{
Debug.Console(2, "{0} config files found matching pattern", configFiles.Length);
if (configFiles.Length > 1)
{
Debug.Console(0, Debug.ErrorLogLevel.Error,
"****Error: Multiple Portal Configuration files present. Please ensure only a single file exists and reset program.****");
return false;
}
else if (configFiles.Length == 1)
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Found Portal config file: '{0}'", filePath);
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "No config file found.");
return false;
}
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Error,
"ERROR: Portal Configuration file not present. Please load file and reset program.");
return false;
}
}
// Get the actual file path
}
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice,
"Local Configuration file not present.", filePath);
}
// Check for Portal Config
if(!localConfigFound)
{
filePath = Global.FilePathPrefix + Global.ConfigFileName;
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to load Portal config file: '{0}'", filePath);
configFiles = GetConfigFiles(filePath);
if (configFiles != null)
{
Debug.Console(2, "{0} config files found matching pattern", configFiles.Length);
if (configFiles.Length > 1)
{
Debug.Console(0, Debug.ErrorLogLevel.Error,
"****Error: Multiple Portal Configuration files present. Please ensure only a single file exists and reset program.****");
return false;
}
else if (configFiles.Length == 1)
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Found Portal config file: '{0}'", filePath);
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "No config file found.");
return false;
}
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Error,
"ERROR: Portal Configuration file not present. Please load file and reset program.");
return false;
}
}
// Get the actual file path
filePath = configFiles[0].FullName;
// Generate debug statement if using a local file.
if (localConfigFound)
{
GetLocalFileMessage(filePath);
}
// Read the file
using (StreamReader fs = new StreamReader(filePath))
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading config file: '{0}'", filePath);
if (localConfigFound)
{
ConfigObject = JObject.Parse(fs.ReadToEnd()).ToObject<EssentialsConfig>();
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Successfully Loaded Local Config");
return true;
}
else
{
var doubleObj = JObject.Parse(fs.ReadToEnd());
ConfigObject = PortalConfigReader.MergeConfigs(doubleObj).ToObject<EssentialsConfig>();
// Extract SystemUrl and TemplateUrl into final config output
if (doubleObj["system_url"] != null)
{
ConfigObject.SystemUrl = doubleObj["system_url"].Value<string>();
}
if (doubleObj["template_url"] != null)
{
ConfigObject.TemplateUrl = doubleObj["template_url"].Value<string>();
}
}
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Successfully Loaded Merged Config");
return true;
}
}
catch (Exception e)
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "ERROR: Config load failed: \r{0}", e);
return false;
}
}
/// <summary>
/// Returns all the files from the directory specified.
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public static FileInfo[] GetConfigFiles(string filePath)
{
// Get the directory
var dir = Path.GetDirectoryName(filePath);
if (Directory.Exists(dir))
{
Debug.Console(1, "Searching in Directory '{0}'", dir);
// Get the directory info
var dirInfo = new DirectoryInfo(dir);
// Get the file name
var fileName = Path.GetFileName(filePath);
Debug.Console(1, "For Config Files matching: '{0}'", fileName);
// Get the files that match from the directory
return dirInfo.GetFiles(fileName);
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice,
"Directory not found: ", dir);
return null;
}
}
/// <summary>
/// Returns the group for a given device key in config
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static string GetGroupForDeviceKey(string key)
{
var dev = ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
return dev == null ? null : dev.Group;
}
// Read the file
using (StreamReader fs = new StreamReader(filePath))
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading config file: '{0}'", filePath);
if (localConfigFound)
{
ConfigObject = JObject.Parse(fs.ReadToEnd()).ToObject<EssentialsConfig>();
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Successfully Loaded Local Config");
return true;
}
else
{
var doubleObj = JObject.Parse(fs.ReadToEnd());
ConfigObject = PortalConfigReader.MergeConfigs(doubleObj).ToObject<EssentialsConfig>();
// Extract SystemUrl and TemplateUrl into final config output
if (doubleObj["system_url"] != null)
{
ConfigObject.SystemUrl = doubleObj["system_url"].Value<string>();
}
if (doubleObj["template_url"] != null)
{
ConfigObject.TemplateUrl = doubleObj["template_url"].Value<string>();
}
}
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Successfully Loaded Merged Config");
return true;
}
}
catch (Exception e)
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "ERROR: Config load failed: \r{0}", e);
return false;
}
}
/// <summary>
/// Returns all the files from the directory specified.
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public static FileInfo[] GetConfigFiles(string filePath)
{
// Get the directory
var dir = Path.GetDirectoryName(filePath);
if (Directory.Exists(dir))
{
Debug.Console(1, "Searching in Directory '{0}'", dir);
// Get the directory info
var dirInfo = new DirectoryInfo(dir);
// Get the file name
var fileName = Path.GetFileName(filePath);
Debug.Console(1, "For Config Files matching: '{0}'", fileName);
// Get the files that match from the directory
return dirInfo.GetFiles(fileName);
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice,
"Directory not found: ", dir);
return null;
}
}
/// <summary>
/// Returns the group for a given device key in config
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static string GetGroupForDeviceKey(string key)
{
var dev = ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
return dev == null ? null : dev.Group;
}
private static void GetLocalFileMessage(string filePath)
@@ -248,7 +248,7 @@ namespace PepperDash.Essentials.Core.Config
Debug.Console(2, Debug.ErrorLogLevel.Notice, "Found Local config file: '{0}'", filePath);
Debug.Console(0, newDebugString.ToString());
}
}
}
}
}

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

@@ -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

@@ -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

@@ -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,150 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.Core.Fusion
{
public class EssentialsHuddleSpaceRoomFusionRoomJoinMap : JoinMapBaseAdvanced
{
// Processor Attributes
[JoinName("ProcessorIp1")]
public JoinDataComplete ProcessorIp1 = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1, AttributeName = "Info - Processor - IP 1" },
new JoinMetadata { Description = "Info - Processor - IP 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorIp2")]
public JoinDataComplete ProcessorIp2 = new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1, AttributeName = "Info - Processor - IP 2" },
new JoinMetadata { Description = "Info - Processor - IP 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorGateway")]
public JoinDataComplete ProcessorGateway = new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1, AttributeName = "Info - Processor - Gateway" },
new JoinMetadata { Description = "Info - Processor - Gateway", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorHostname")]
public JoinDataComplete ProcessorHostname = new JoinDataComplete(new JoinData { JoinNumber = 53, JoinSpan = 1, AttributeName = "Info - Processor - Hostname" },
new JoinMetadata { Description = "Info - Processor - Hostname", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorDomain")]
public JoinDataComplete ProcessorDomain = new JoinDataComplete(new JoinData { JoinNumber = 54, JoinSpan = 1, AttributeName = "Info - Processor - Domain" },
new JoinMetadata { Description = "Info - Processor - Domain", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorDns1")]
public JoinDataComplete ProcessorDns1 = new JoinDataComplete(new JoinData { JoinNumber = 55, JoinSpan = 1, AttributeName = "Info - Processor - DNS 1" },
new JoinMetadata { Description = "Info - Processor - DNS 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorDns2")]
public JoinDataComplete ProcessorDns2 = new JoinDataComplete(new JoinData { JoinNumber = 56, JoinSpan = 1, AttributeName = "Info - Processor - DNS 2" },
new JoinMetadata { Description = "Info - Processor - DNS 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorMac1")]
public JoinDataComplete ProcessorMac1 = new JoinDataComplete(new JoinData { JoinNumber = 57, JoinSpan = 1, AttributeName = "Info - Processor - MAC 1" },
new JoinMetadata { Description = "Info - Processor - MAC 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorMac2")]
public JoinDataComplete ProcessorMac2 = new JoinDataComplete(new JoinData { JoinNumber = 58, JoinSpan = 1, AttributeName = "Info - Processor - MAC 2" },
new JoinMetadata { Description = "Info - Processor - MAC 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorNetMask1")]
public JoinDataComplete ProcessorNetMask1 = new JoinDataComplete(new JoinData { JoinNumber = 59, JoinSpan = 1, AttributeName = "Info - Processor - Net Mask 1" },
new JoinMetadata { Description = "Info - Processor - Net Mask 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorNetMask2")]
public JoinDataComplete ProcessorNetMask2 = new JoinDataComplete(new JoinData { JoinNumber = 60, JoinSpan = 1, AttributeName = "Info - Processor - Net Mask 2" },
new JoinMetadata { Description = "Info - Processor - Net Mask 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorFirmware")]
public JoinDataComplete ProcessorFirmware = new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1, AttributeName = "Info - Processor - Firmware" },
new JoinMetadata { Description = "Info - Processor - Firmware", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProgramNameStart")]
public JoinDataComplete ProgramNameStart = new JoinDataComplete(new JoinData { JoinNumber = 62, JoinSpan = 10, AttributeName = "Info - Processor - Program" },
new JoinMetadata { Description = "Info - Processor - Program", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorReboot")]
public JoinDataComplete ProcessorReboot = new JoinDataComplete(new JoinData { JoinNumber = 74, JoinSpan = 1, AttributeName = "Processor - Reboot" },
new JoinMetadata { Description = "Processor - Reboot", JoinCapabilities = eJoinCapabilities.FromFusion, JoinType = eJoinType.Digital });
// Volume Controls
[JoinName("VolumeFader1")]
public JoinDataComplete VolumeFader1 = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1, AttributeName = "Volume - Fader01" },
new JoinMetadata { Description = "Volume - Fader01", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Analog });
// Codec Info
[JoinName("VcCodecInCall")]
public JoinDataComplete VcCodecInCall = new JoinDataComplete(new JoinData { JoinNumber = 69, JoinSpan = 1, AttributeName = "Conf - VC 1 In Call" },
new JoinMetadata { Description = "Conf - VC 1 In Call", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
[JoinName("VcCodecOnline")]
public JoinDataComplete VcCodecOnline = new JoinDataComplete(new JoinData { JoinNumber = 122, JoinSpan = 1, AttributeName = "Online - VC 1" },
new JoinMetadata { Description = "Online - VC 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
[JoinName("VcCodecIpAddress")]
public JoinDataComplete VcCodecIpAddress = new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1, AttributeName = "IP Address - VC" },
new JoinMetadata { Description = "IP Address - VC", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("VcCodecIpPort")]
public JoinDataComplete VcCodecIpPort = new JoinDataComplete(new JoinData { JoinNumber = 150, JoinSpan = 1, AttributeName = "IP Port - VC" },
new JoinMetadata { Description = "IP Port - VC", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
// Source Attributes
[JoinName("Display1CurrentSourceName")]
public JoinDataComplete Display1CurrentSourceName = new JoinDataComplete(new JoinData { JoinNumber = 84, JoinSpan = 1, AttributeName = "Display 1 - Current Source" },
new JoinMetadata { Description = "Display 1 - Current Source", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
// Device Online Status
[JoinName("TouchpanelOnlineStart")]
public JoinDataComplete TouchpanelOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 150, JoinSpan = 10, AttributeName = "Online - Touch Panel" },
new JoinMetadata { Description = "Online - Touch Panel", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
[JoinName("XpanelOnlineStart")]
public JoinDataComplete XpanelOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 160, JoinSpan = 5, AttributeName = "Online - XPanel" },
new JoinMetadata { Description = "Online - XPanel", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
[JoinName("DisplayOnlineStart")]
public JoinDataComplete DisplayOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 170, JoinSpan = 10, AttributeName = "Online - Display" },
new JoinMetadata { Description = "Online - Display", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
[JoinName("Display1LaptopSourceStart")]
public JoinDataComplete Display1LaptopSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 166, JoinSpan = 5, AttributeName = "Display 1 - Source Laptop" },
new JoinMetadata { Description = "Display 1 - Source Laptop", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital });
[JoinName("Display1DiscPlayerSourceStart")]
public JoinDataComplete Display1DiscPlayerSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 181, JoinSpan = 5, AttributeName = "Display 1 - Source Disc Player" },
new JoinMetadata { Description = "Display 1 - Source Disc Player", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital });
[JoinName("Display1SetTopBoxSourceStart")]
public JoinDataComplete Display1SetTopBoxSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 188, JoinSpan = 5, AttributeName = "Display 1 - Source TV" },
new JoinMetadata { Description = "Display 1 - Source TV", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital });
// Display 1
[JoinName("Display1Start")]
public JoinDataComplete Display1Start = new JoinDataComplete(new JoinData { JoinNumber = 158, JoinSpan = 1 },
new JoinMetadata { Description = "Display 1 Start", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital });
/// <summary>
/// Constructor to use when instantiating this Join Map without inheriting from it
/// </summary>
/// <param name="joinStart">Join this join map will start at</param>
public EssentialsHuddleSpaceRoomFusionRoomJoinMap(uint joinStart)
: base(joinStart, typeof(EssentialsHuddleSpaceRoomFusionRoomJoinMap))
{
}
/// <summary>
/// Constructor to use when extending this Join map
/// </summary>
/// <param name="joinStart">Join this join map will start at</param>
/// <param name="type">Type of the child join map</param>
public EssentialsHuddleSpaceRoomFusionRoomJoinMap(uint joinStart, Type type) : base(joinStart, type)
{
}
}
}

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

@@ -25,7 +25,7 @@ namespace PepperDash.Essentials.Core
var joinMap = ConfigReader.ConfigObject.JoinMaps[joinMapKey];
return joinMap;
return joinMap.ToString();
}
/// <summary>
@@ -45,16 +45,33 @@ namespace PepperDash.Essentials.Core
/// <returns></returns>
public static Dictionary<string, JoinData> TryGetJoinMapAdvancedForDevice(string joinMapKey)
{
if (string.IsNullOrEmpty(joinMapKey))
try
{
if (string.IsNullOrEmpty(joinMapKey))
return null;
if (!ConfigReader.ConfigObject.JoinMaps.ContainsKey(joinMapKey))
{
Debug.Console(2, "No Join Map found in config with key: '{0}'", joinMapKey);
return null;
}
Debug.Console(2, "Attempting to load custom join map with key: {0}", joinMapKey);
var joinMapJToken = ConfigReader.ConfigObject.JoinMaps[joinMapKey];
if (joinMapJToken == null)
return null;
var joinMapData = joinMapJToken.ToObject<Dictionary<string, JoinData>>();
return joinMapData;
}
catch (Exception e)
{
Debug.Console(2, "Error getting join map for key: '{0}'. Error: {1}", joinMapKey, e);
return null;
var joinMapSerialzed = ConfigReader.ConfigObject.JoinMaps[joinMapKey];
if (joinMapSerialzed == null) return null;
var joinMapData = JsonConvert.DeserializeObject<Dictionary<string, JoinData>>(joinMapSerialzed);
return joinMapData;
}
}
}
@@ -266,7 +283,7 @@ namespace PepperDash.Essentials.Core
@"Join Number: {0} | JoinSpan: '{1}' | Description: '{2}' | Type: '{3}' | Capabilities: '{4}'",
join.Value.JoinNumber,
join.Value.JoinSpan,
String.IsNullOrEmpty(join.Value.Metadata.Description) ? join.Value.Metadata.Label: join.Value.Metadata.Description,
String.IsNullOrEmpty(join.Value.AttributeName) ? join.Value.Metadata.Label : join.Value.AttributeName,
join.Value.Metadata.JoinType.ToString(),
join.Value.Metadata.JoinCapabilities.ToString());
}
@@ -288,7 +305,7 @@ namespace PepperDash.Essentials.Core
}
else
{
Debug.Console(2, "No mathcing key found in join map for: '{0}'", customJoinData.Key);
Debug.Console(2, "No matching key found in join map for: '{0}'", customJoinData.Key);
}
}
@@ -327,7 +344,10 @@ namespace PepperDash.Essentials.Core
None = 0,
ToSIMPL = 1,
FromSIMPL = 2,
ToFromSIMPL = ToSIMPL | FromSIMPL
ToFromSIMPL = ToSIMPL | FromSIMPL,
ToFusion = 4,
FromFusion = 8,
ToFromFusion = ToFusion | FromFusion,
}
[Flags]
@@ -340,7 +360,7 @@ namespace PepperDash.Essentials.Core
DigitalAnalog = Digital | Analog,
DigitalSerial = Digital | Serial,
AnalogSerial = Analog | Serial,
DigitalAnalogSerial = Digital | Analog | Serial
DigitalAnalogSerial = Digital | Analog | Serial,
}
/// <summary>
@@ -394,7 +414,7 @@ namespace PepperDash.Essentials.Core
}
/// <summary>
/// Data describing the join. Can be
/// Data describing the join. Can be overridden from configuratino
/// </summary>
public class JoinData
{
@@ -408,6 +428,11 @@ namespace PepperDash.Essentials.Core
/// </summary>
[JsonProperty("joinSpan")]
public uint JoinSpan { get; set; }
/// <summary>
/// Fusion Attribute Name (optional)
/// </summary>
[JsonProperty("attributeName")]
public string AttributeName { get; set; }
}
/// <summary>
@@ -419,6 +444,10 @@ namespace PepperDash.Essentials.Core
private JoinData _data;
public JoinMetadata Metadata { get; set; }
/// <summary>
/// To store some future information as you please
/// </summary>
public object UserObject { get; private set; }
public JoinDataComplete(JoinData data, JoinMetadata metadata)
{
@@ -449,6 +478,11 @@ namespace PepperDash.Essentials.Core
get { return _data.JoinSpan; }
}
public string AttributeName
{
get { return _data.AttributeName; }
}
public void SetCustomJoinData(JoinData customJoinData)
{
_data = customJoinData;

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" />
@@ -196,6 +199,7 @@
<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" />
@@ -216,6 +220,7 @@
<Compile Include="Fusion\FusionCustomPropertiesBridge.cs" />
<Compile Include="Fusion\FusionEventHandlers.cs" />
<Compile Include="Fusion\FusionProcessorQueries.cs" />
<Compile Include="Fusion\EssentialsHuddleSpaceRoomFusionRoomJoinMap.cs" />
<Compile Include="Fusion\FusionRviDataClasses.cs" />
<Compile Include="Gateways\CenRfgwController.cs" />
<Compile Include="Gateways\EssentialsRfGatewayConfig.cs" />
@@ -275,6 +280,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;
@@ -118,8 +133,8 @@ namespace PepperDash.Essentials.DM
OutputEndpointOnlineFeedbacks = new Dictionary<uint, BoolFeedback>();
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} 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);
@@ -140,57 +155,57 @@ namespace PepperDash.Essentials.DM
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;
}
}
}
}
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"));
@@ -199,194 +214,203 @@ namespace PepperDash.Essentials.DM
LinkInputsToApi(trilist, joinMap);
LinkOutputsToApi(trilist, joinMap);
}
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 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));
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)
{
return;
}
//Debug.Console(2, dmpsRouter, "Card Type: {0}", outputCard.CardInputOutputType);
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;
}
});
// Feedback
if (VideoOutputFeedbacks[ioSlot] != null)
{
VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo.JoinNumber + ioSlotJoin]);
}
if (AudioOutputFeedbacks[ioSlot] != null)
{
AudioOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio.JoinNumber + ioSlotJoin]);
}
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]);
}
}
}
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]);
}
}
}
}
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 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));
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)
{
return;
}
//Debug.Console(2, dmpsRouter, "Card Type: {0}", outputCard.CardInputOutputType);
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;
}
});
// Feedback
if (VideoOutputFeedbacks[ioSlot] != null)
{
VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo.JoinNumber + ioSlotJoin]);
}
if (AudioOutputFeedbacks[ioSlot] != null)
{
AudioOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio.JoinNumber + ioSlotJoin]);
}
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]);
}
}
}
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]);
}
}
}
/// <summary>
/// Iterate the SwitcherOutputs collection to setup feedbacks and add routing ports
/// </summary>
void SetupOutputCards()
{
foreach (var card in Dmps.SwitcherOutputs)
{
foreach (var card in Dmps.SwitcherOutputs)
{
Debug.Console(1, this, "Output Card Type: {0}", card.CardInputOutputType);
var outputCard = card as DMOutput;
if (outputCard == null)
{
Debug.Console(1, this, "Output card {0} is not a DMOutput", card.CardInputOutputType);
continue;
}
var outputCard = card as DMOutput;
if (outputCard == null)
{
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;
if (outputCard.VideoOutFeedback != null) { return (ushort)outputCard.VideoOutFeedback.Number; }
return 0;
;
});
AudioOutputFeedbacks[outputCard.Number] = new IntFeedback(() =>
{
if (outputCard.AudioOutFeedback != null) { return (ushort)outputCard.AudioOutFeedback.Number; }
return 0;
;
try
{
if (outputCard.AudioOutFeedback != null)
{
return (ushort) outputCard.AudioOutFeedback.Number;
}
return 0;
}
catch (NotSupportedException)
{
return (ushort) outputCard.AudioOutSourceFeedback;
}
});
OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
{
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 "";
}
return "";
});
OutputVideoRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
{
OutputVideoRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
{
if (outputCard.VideoOutFeedback != null && outputCard.VideoOutFeedback.NameFeedback != null)
{
return outputCard.VideoOutFeedback.NameFeedback.StringValue;
}
return NoRouteText;
}
return NoRouteText;
});
OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
{
OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
{
if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null)
{
return outputCard.AudioOutFeedback.NameFeedback.StringValue;
}
return NoRouteText;
}
return NoRouteText;
});
OutputEndpointOnlineFeedbacks[outputCard.Number] = new BoolFeedback(() => outputCard.EndpointOnlineFeedback);
AddOutputCard(outputCard.Number, outputCard);
AddOutputCard(outputCard.Number, outputCard);
}
}
@@ -504,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);
}
@@ -520,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;
@@ -528,6 +561,7 @@ namespace PepperDash.Essentials.DM
InputPorts.Add(inputPort);
}
/// <summary>
/// Builds the appropriate ports and calls the appropriate add port method
/// </summary>
@@ -541,23 +575,23 @@ namespace PepperDash.Essentials.DM
var cecPort = hdmiOutputCard.HdmiOutputPort;
AddHdmiOutputPort(number, cecPort);
AddHdmiOutputPort(number, cecPort);
}
else if (outputCard is Card.Dmps3HdmiOutputBackend)
{
var hdmiOutputCard = outputCard as Card.Dmps3HdmiOutputBackend;
var cecPort = hdmiOutputCard.HdmiOutputPort;
AddHdmiOutputPort(number, cecPort);
else if (outputCard is Card.Dmps3HdmiOutputBackend)
{
var hdmiOutputCard = outputCard as Card.Dmps3HdmiOutputBackend;
var cecPort = hdmiOutputCard.HdmiOutputPort;
AddHdmiOutputPort(number, cecPort);
}
else if (outputCard is Card.Dmps3DmOutput)
{
AddDmOutputPort(number);
{
AddDmOutputPort(number);
}
else if (outputCard is Card.Dmps3DmOutputBackend)
{
AddDmOutputPort(number);
else if (outputCard is Card.Dmps3DmOutputBackend)
{
AddDmOutputPort(number);
}
else if (outputCard is Card.Dmps3ProgramOutput)
{
@@ -565,51 +599,51 @@ namespace PepperDash.Essentials.DM
var programOutput = new DmpsAudioOutputController(string.Format("processor-programAudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase);
DeviceManager.AddDevice(programOutput);
DeviceManager.AddDevice(programOutput);
}
else if (outputCard is Card.Dmps3AuxOutput)
{
switch (outputCard.CardInputOutputType)
{
case eCardInputOutputType.Dmps3Aux1Output:
else if (outputCard is Card.Dmps3AuxOutput)
{
switch (outputCard.CardInputOutputType)
{
case eCardInputOutputType.Dmps3Aux1Output:
{
AddAudioOnlyOutputPort(number, "Aux1");
var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase);
DeviceManager.AddDevice(aux1Output);
}
break;
case eCardInputOutputType.Dmps3Aux2Output:
}
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 is Card.Dmps3CodecOutput)
{
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;
}
}
}
break;
}
}
else if (outputCard is Card.Dmps3CodecOutput)
{
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");
AddAudioOnlyOutputPort(number, "Dialer");
}
else if (outputCard is Card.Dmps3DigitalMixOutput)
{
@@ -620,11 +654,11 @@ namespace PepperDash.Essentials.DM
if (number == (uint)CrestronControlSystem.eDmps34K250COutputs.Mix2
|| number == (uint)CrestronControlSystem.eDmps34K300COutputs.Mix2
|| number == (uint)CrestronControlSystem.eDmps34K350COutputs.Mix2)
AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps34K250COutputs.Mix2.ToString());
AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps34K250COutputs.Mix2.ToString());
}
else if (outputCard is Card.Dmps3AecOutput)
{
AddAudioOnlyOutputPort(number, "Aec");
AddAudioOnlyOutputPort(number, "Aec");
}
else
{
@@ -667,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>
@@ -677,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;
@@ -754,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
@@ -795,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);
@@ -813,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
//{
@@ -853,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)
@@ -862,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

@@ -8,14 +8,16 @@ 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; }
@@ -32,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)
@@ -79,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
{

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

@@ -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

@@ -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.45" targetFramework="net35" allowedVersions="[1.0,1.1)"/>
</packages>